diff --git a/src/components/UsaHeader/UsaHeader.test.js b/src/components/UsaHeader/UsaHeader.test.js
index c59ded6f..2c4a88e8 100644
--- a/src/components/UsaHeader/UsaHeader.test.js
+++ b/src/components/UsaHeader/UsaHeader.test.js
@@ -1,6 +1,8 @@
import '@module/@uswds/uswds/dist/css/uswds.min.css'
import { h } from 'vue'
import UsaHeader from './UsaHeader.vue'
+import UsaNavbar from '@/components/UsaNavbar'
+import UsaNav from '@/components/UsaNav'
describe('UsaHeader', () => {
it('renders the component', () => {
@@ -88,6 +90,114 @@ describe('UsaHeader', () => {
cy.get('span').should('contain', 'Megamenu: false')
})
+ it('provide reactive values to `UsaNav` and `UsaNavbar` components', () => {
+ const childComponent = {
+ components: { UsaNavbar, UsaNav },
+ template: `
+ Test Navbar
+
+ Primary slot
+ Secondary slot
+
+ `,
+ }
+
+ // eslint-disable-next-line cypress/no-assigning-return-values
+ const wrapper = cy
+ .mount(UsaHeader, {
+ slots: {
+ default: () => h(childComponent),
+ },
+ })
+ .its('wrapper')
+ .as('wrapper')
+
+ cy.get('div.usa-overlay')
+ .as('overlay')
+ .should('not.have.class', 'is-visible')
+ .and('not.be.visible')
+
+ cy.get('.usa-navbar').should('contain', 'Test Navbar')
+
+ cy.get('button.usa-menu-btn')
+ .as('menuButton')
+ .should(
+ 'have.attr',
+ 'aria-controls',
+ '__vuswds-id-global-mobile-header-menu'
+ )
+
+ cy.get('nav.usa-nav')
+ .as('nav')
+ .should('have.id', '__vuswds-id-global-mobile-header-menu')
+
+ cy.get('@nav').should('not.have.class', 'is-visible').and('not.be.visible')
+ cy.get('@nav').find('> div.usa-nav__inner').should('not.exist')
+
+ cy.get('@nav').find('> button.usa-nav__close').as('closeButton')
+
+ cy.get('body > .usa-overlay').should('not.exist')
+ cy.get('body > nav').should('not.exist')
+ cy.get('body > :not(nav)').should('not.have.attr', 'aria-hidden')
+ cy.get('body > :not(.usa-overlay)').should('not.have.attr', 'aria-hidden')
+
+ wrapper.vue().then(vm => {
+ const usaHeaderComponent = vm.findComponent(UsaHeader)
+ expect(usaHeaderComponent.emitted()).to.not.have.property(
+ 'mobileMenuOpen'
+ )
+
+ // Click mobile menu button.
+ cy.get('@menuButton').click()
+
+ wrapper.vue().then(vm => {
+ const usaHeaderComponent = vm.findComponent(UsaHeader)
+
+ expect(usaHeaderComponent.emitted()).to.have.property('mobileMenuOpen')
+
+ const currentEvent = usaHeaderComponent.emitted('mobileMenuOpen')
+ expect(currentEvent).to.have.length(1)
+ expect(currentEvent[currentEvent.length - 1]).to.contain(true)
+ })
+ })
+
+ cy.get('body > .usa-overlay').should('exist')
+ cy.get('body > nav').should('exist')
+ cy.get('body > :not(nav)')
+ .should('have.attr', 'aria-hidden')
+ .and('contain', true)
+ cy.get('body > :not(.usa-overlay)').should('have.attr', 'aria-hidden')
+
+ cy.get('@overlay').should('have.class', 'is-visible').and('be.visible')
+ cy.get('@nav').should('have.class', 'is-visible').and('be.visible')
+
+ cy.get('@closeButton').should('have.focus')
+
+ // Click mobile menu close button.
+ cy.get('@closeButton').click()
+
+ wrapper.vue().then(vm => {
+ const usaHeaderComponent = vm.findComponent(UsaHeader)
+ expect(usaHeaderComponent.emitted()).to.have.property('mobileMenuOpen')
+
+ const currentEvent = usaHeaderComponent.emitted('mobileMenuOpen')
+ expect(currentEvent).to.have.length(2)
+ expect(currentEvent[currentEvent.length - 1]).to.contain(false)
+ })
+
+ cy.get('@menuButton').should('have.focus')
+
+ cy.get('body > .usa-overlay').should('not.exist')
+ cy.get('body > nav').should('not.exist')
+ cy.get('body > :not(nav)').should('not.have.attr', 'aria-hidden')
+ cy.get('body > :not(.usa-overlay)').should('not.have.attr', 'aria-hidden')
+
+ cy.get('@overlay')
+ .should('not.have.class', 'is-visible')
+ .and('not.be.visible')
+ cy.get('@nav').should('not.have.class', 'is-visible').and('not.be.visible')
+ })
+
it('adds custom CSS classes', () => {
cy.mount(UsaHeader, {
props: {
diff --git a/src/components/UsaHeader/UsaHeader.vue b/src/components/UsaHeader/UsaHeader.vue
index 664b5861..c8aa07a5 100644
--- a/src/components/UsaHeader/UsaHeader.vue
+++ b/src/components/UsaHeader/UsaHeader.vue
@@ -1,5 +1,8 @@
diff --git a/src/components/UsaNav/UsaNav.test.js b/src/components/UsaNav/UsaNav.test.js
index f81e5f13..425248a2 100644
--- a/src/components/UsaNav/UsaNav.test.js
+++ b/src/components/UsaNav/UsaNav.test.js
@@ -1,47 +1,14 @@
import '@module/@uswds/uswds/dist/css/uswds.min.css'
import { h, ref } from 'vue'
import UsaNav from './UsaNav.vue'
-import UsaNavbar from '@/components/UsaNavbar'
describe('UsaNav', () => {
- const wrapperComponent = {
- components: { UsaNavbar, UsaNav },
- props: {
- ariaLabel: {
- type: String,
- default: 'Primary navigation',
- },
- closeButtonLabel: {
- type: String,
- default: 'Close',
- },
- customClasses: {
- type: Object,
- default: () => {
- return {
- button: [],
- }
- },
- },
- },
- template: `
-
-
-
-
-
- `,
- }
-
it('renders the component', () => {
+ const isOpen = ref(false)
+
cy.viewport('iphone-6')
- // eslint-disable-next-line cypress/no-assigning-return-values
- const wrapper = cy.mount(wrapperComponent, {
+ cy.mount(UsaNav, {
props: {
customClasses: {
button: ['test-button-class'],
@@ -65,6 +32,13 @@ describe('UsaNav', () => {
'Test secondary slot'
),
},
+ global: {
+ provide: {
+ isMobileMenuOpen: isOpen,
+ mobileMenuId: 'test-id',
+ closeMobileMenu: () => (isOpen.value = false),
+ },
+ },
})
cy.get('div.usa-overlay')
@@ -72,7 +46,7 @@ describe('UsaNav', () => {
.should('not.have.class', 'is-visible')
.and('not.be.visible')
- cy.get('nav.usa-nav').as('nav').should('have.attr', 'id')
+ cy.get('nav.usa-nav').as('nav').should('have.id', 'test-id')
cy.get('@nav')
.should('have.attr', 'aria-label')
.and('contain', 'Primary navigation')
@@ -107,34 +81,14 @@ describe('UsaNav', () => {
cy.get('body > .usa-overlay').should('not.exist')
cy.get('body > nav').should('not.exist')
- cy.get('body > :not(nav)').should('not.have.attr', 'aria-hidden')
- cy.get('body > :not(.usa-overlay)').should('not.have.attr', 'aria-hidden')
-
- wrapper.vue().then(vm => {
- const usaNavbarComponent = vm.findComponent(UsaNavbar)
- expect(usaNavbarComponent.emitted()).to.not.have.property(
- 'mobileMenuOpen'
- )
- })
-
- // Click mobile menu button.
- cy.get('.usa-menu-btn').as('menuButton').click()
- wrapper.vue().then(vm => {
- const usaNavbarComponent = vm.findComponent(UsaNavbar)
- expect(usaNavbarComponent.emitted()).to.have.property('mobileMenuOpen')
-
- const currentEvent = usaNavbarComponent.emitted('mobileMenuOpen')
- expect(currentEvent).to.have.length(1)
- expect(currentEvent[currentEvent.length - 1]).to.contain(true)
+ // Open mobile menu.
+ cy.then(() => {
+ isOpen.value = true
})
cy.get('body > .usa-overlay').should('exist')
cy.get('body > nav').should('exist')
- cy.get('body > :not(nav)')
- .should('have.attr', 'aria-hidden')
- .and('contain', true)
- cy.get('body > :not(.usa-overlay)').should('have.attr', 'aria-hidden')
cy.get('@overlay').should('have.class', 'is-visible').and('be.visible')
cy.get('@nav').should('have.class', 'is-visible').and('be.visible')
@@ -159,21 +113,8 @@ describe('UsaNav', () => {
// Click mobile menu close button.
cy.get('@closeButton').click()
- wrapper.vue().then(vm => {
- const usaNavbarComponent = vm.findComponent(UsaNavbar)
- expect(usaNavbarComponent.emitted()).to.have.property('mobileMenuOpen')
-
- const currentEvent = usaNavbarComponent.emitted('mobileMenuOpen')
- expect(currentEvent).to.have.length(2)
- expect(currentEvent[currentEvent.length - 1]).to.contain(false)
- })
-
- cy.get('@menuButton').should('have.focus')
-
cy.get('body > .usa-overlay').should('not.exist')
cy.get('body > nav').should('not.exist')
- cy.get('body > :not(nav)').should('not.have.attr', 'aria-hidden')
- cy.get('body > :not(.usa-overlay)').should('not.have.attr', 'aria-hidden')
cy.get('@overlay')
.should('not.have.class', 'is-visible')
@@ -181,7 +122,9 @@ describe('UsaNav', () => {
cy.get('@nav').should('not.have.class', 'is-visible').and('not.be.visible')
// Open mobile menu again.
- cy.get('@menuButton').click()
+ cy.then(() => {
+ isOpen.value = true
+ })
cy.get('@overlay').should('have.class', 'is-visible').and('be.visible')
cy.get('@nav').should('have.class', 'is-visible').and('be.visible')
@@ -195,12 +138,14 @@ describe('UsaNav', () => {
cy.get('@nav').should('not.have.class', 'is-visible').and('not.be.visible')
// Open mobile menu again.
- cy.get('@menuButton').click()
+ cy.then(() => {
+ isOpen.value = true
+ })
cy.get('@overlay').should('have.class', 'is-visible').and('be.visible')
cy.get('@nav').should('have.class', 'is-visible').and('be.visible')
- cy.get('html').click('bottomLeft')
+ cy.get('html').click('topLeft')
cy.get('@overlay')
.should('not.have.class', 'is-visible')
@@ -208,16 +153,20 @@ describe('UsaNav', () => {
cy.get('@nav').should('not.have.class', 'is-visible').and('not.be.visible')
// Open mobile menu again.
- cy.get('@menuButton').click()
+ cy.then(() => {
+ isOpen.value = true
+ })
cy.get('@overlay').should('have.class', 'is-visible').and('be.visible')
cy.get('@nav').should('have.class', 'is-visible').and('be.visible')
})
it('slot positions change on mobile screens', () => {
+ const isOpen = ref(true)
+
cy.viewport('iphone-6')
- cy.mount(wrapperComponent, {
+ cy.mount(UsaNav, {
props: {
ariaLabel: 'Custom aria label',
closeButtonLabel: 'Custom close button label',
@@ -226,10 +175,15 @@ describe('UsaNav', () => {
primary: () => h('span', {}, 'Test primary slot'),
secondary: () => h('span', {}, 'Test secondary slot'),
},
+ global: {
+ provide: {
+ isMobileMenuOpen: isOpen,
+ mobileMenuId: 'test-id',
+ closeMobileMenu: () => (isOpen.value = false),
+ },
+ },
})
- cy.get('.usa-menu-btn').as('menuButton').click()
-
cy.get('div.usa-overlay')
.as('overlay')
.should('have.class', 'is-visible')
@@ -313,19 +267,26 @@ describe('UsaNav', () => {
})
it('uses custom global mobile breakpoint', () => {
+ const isOpen = ref(false)
+
cy.viewport('iphone-6')
- cy.mount(wrapperComponent, {
+ cy.mount(UsaNav, {
global: {
provide: {
'vueUswds.imagePath': '/test',
'vueUswds.mobileMenuBreakpoint': '400px',
- closeMobileMenu: () => {},
+ isMobileMenuOpen: isOpen,
+ mobileMenuId: 'test-mobile-menu-id',
+ closeMobileMenu: () => (isOpen.value = false),
},
},
})
- cy.get('.usa-menu-btn').as('menuButton').click()
+ // Open mobile menu.
+ cy.then(() => {
+ isOpen.value = true
+ })
cy.get('div.usa-overlay')
.as('overlay')
diff --git a/src/components/UsaNavbar/UsaNavbar.test.js b/src/components/UsaNavbar/UsaNavbar.test.js
index 213343b4..82c9ac32 100644
--- a/src/components/UsaNavbar/UsaNavbar.test.js
+++ b/src/components/UsaNavbar/UsaNavbar.test.js
@@ -1,10 +1,28 @@
import '@module/@uswds/uswds/dist/css/uswds.min.css'
-import { h } from 'vue'
+import { h, ref } from 'vue'
import UsaNavbar from './UsaNavbar.vue'
describe('UsaNavbar', () => {
it('renders the component', () => {
- cy.mount(UsaNavbar, {}).its('wrapper').as('wrapper')
+ const isOpen = ref(false)
+
+ cy.mount(UsaNavbar, {
+ global: {
+ provide: {
+ isMobileMenuOpen: isOpen,
+ mobileMenuId: 'test-id',
+ toggleMobileMenu: () => {
+ if (isOpen.value) {
+ isOpen.value = false
+ } else {
+ isOpen.value = true
+ }
+ },
+ },
+ },
+ })
+ .its('wrapper')
+ .as('wrapper')
cy.get('div.usa-navbar').should('exist')
cy.get('button.usa-menu-btn')
@@ -35,6 +53,13 @@ describe('UsaNavbar', () => {
'menu-button': ({ menuButtonLabel }) =>
`Test button slot content: ${menuButtonLabel}`,
},
+ global: {
+ provide: {
+ isMobileMenuOpen: ref(false),
+ mobileMenuId: 'test-id',
+ toggleMobileMenu: () => {},
+ },
+ },
})
cy.get('.usa-navbar > span').should('contain', 'Test default slot content')
@@ -46,6 +71,13 @@ describe('UsaNavbar', () => {
props: {
menuButtonLabel: 'Custom Menu',
},
+ global: {
+ provide: {
+ isMobileMenuOpen: ref(false),
+ mobileMenuId: 'test-id',
+ toggleMobileMenu: () => {},
+ },
+ },
})
cy.get('button.usa-menu-btn').should('contain', 'Custom Menu')
@@ -58,6 +90,13 @@ describe('UsaNavbar', () => {
button: ['test-button-class'],
},
},
+ global: {
+ provide: {
+ isMobileMenuOpen: ref(false),
+ mobileMenuId: 'test-id',
+ toggleMobileMenu: () => {},
+ },
+ },
})
cy.get('.usa-menu-btn').should('have.class', 'test-button-class')
diff --git a/src/components/UsaNavbar/UsaNavbar.vue b/src/components/UsaNavbar/UsaNavbar.vue
index ec76f2cb..0e132fac 100644
--- a/src/components/UsaNavbar/UsaNavbar.vue
+++ b/src/components/UsaNavbar/UsaNavbar.vue
@@ -1,6 +1,9 @@