test(app): smoke tests for three layout skeletons
WS-3 session 1a Task 3. Vitest covers each layout with: (1) it mounts without throwing, (2) it renders the expected DOM structure (top-bar/main/footer for PortalLayout, none for PublicLayout, slot-passthrough for OrganizerLayout), (3) it places <RouterView /> in the right region. Vuetify components (VApp/VAppBar/VMain/VFooter) are stubbed to their semantic HTML equivalents so the structural assertions still hold without pulling vuetify/components into the trimmed-down vitest config (which lacks the CSS plugin needed to transform Vuetify's .css side effects). OrganizerLayout uses vi.mock to short-circuit the DefaultLayoutWithVerticalNav import for the same reason. Vitest count: 41 -> 49 in apps/app.
This commit is contained in:
33
apps/app/src/layouts/__tests__/OrganizerLayout.spec.ts
Normal file
33
apps/app/src/layouts/__tests__/OrganizerLayout.spec.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import { describe, expect, it, vi } from 'vitest'
|
||||||
|
import { mount } from '@vue/test-utils'
|
||||||
|
|
||||||
|
// Mock the import path so OrganizerLayout's `import DefaultLayoutWithVerticalNav`
|
||||||
|
// statement doesn't pull in the real component (which transitively imports
|
||||||
|
// Vuetify .css files that the trimmed-down vitest config can't transform).
|
||||||
|
vi.mock('@/layouts/components/DefaultLayoutWithVerticalNav.vue', () => ({
|
||||||
|
default: { template: '<div><slot /></div>' },
|
||||||
|
}))
|
||||||
|
|
||||||
|
const OrganizerLayout = (await import('../OrganizerLayout.vue')).default
|
||||||
|
|
||||||
|
describe('OrganizerLayout', () => {
|
||||||
|
it('mounts without throwing', () => {
|
||||||
|
const wrapper = mount(OrganizerLayout, {
|
||||||
|
global: {
|
||||||
|
stubs: { RouterView: true },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(wrapper.exists()).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders a RouterView in its slot', () => {
|
||||||
|
const wrapper = mount(OrganizerLayout, {
|
||||||
|
global: {
|
||||||
|
stubs: { RouterView: { template: '<div data-test="router-view" />' } },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(wrapper.find('[data-test="router-view"]').exists()).toBe(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
50
apps/app/src/layouts/__tests__/PortalLayout.spec.ts
Normal file
50
apps/app/src/layouts/__tests__/PortalLayout.spec.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import { describe, expect, it } from 'vitest'
|
||||||
|
import { mount } from '@vue/test-utils'
|
||||||
|
import PortalLayout from '../PortalLayout.vue'
|
||||||
|
|
||||||
|
// Stub Vuetify components as their semantic HTML equivalents so we can
|
||||||
|
// assert structure without pulling vuetify/components (which loads .css
|
||||||
|
// files that the trimmed-down vitest config can't transform).
|
||||||
|
const vuetifyStubs = {
|
||||||
|
VApp: { template: '<div><slot /></div>' },
|
||||||
|
VAppBar: { template: '<header><slot /></header>' },
|
||||||
|
VMain: { template: '<main><slot /></main>' },
|
||||||
|
VFooter: { template: '<footer><slot /></footer>' },
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('PortalLayout', () => {
|
||||||
|
it('mounts without throwing', () => {
|
||||||
|
const wrapper = mount(PortalLayout, {
|
||||||
|
global: {
|
||||||
|
stubs: { ...vuetifyStubs, RouterView: true },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(wrapper.exists()).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders a top app bar, main region, and footer', () => {
|
||||||
|
const wrapper = mount(PortalLayout, {
|
||||||
|
global: {
|
||||||
|
stubs: { ...vuetifyStubs, RouterView: true },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(wrapper.find('header').exists()).toBe(true)
|
||||||
|
expect(wrapper.find('main').exists()).toBe(true)
|
||||||
|
expect(wrapper.find('footer').exists()).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders a RouterView inside the main region', () => {
|
||||||
|
const wrapper = mount(PortalLayout, {
|
||||||
|
global: {
|
||||||
|
stubs: {
|
||||||
|
...vuetifyStubs,
|
||||||
|
RouterView: { template: '<div data-test="router-view" />' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(wrapper.find('main [data-test="router-view"]').exists()).toBe(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
47
apps/app/src/layouts/__tests__/PublicLayout.spec.ts
Normal file
47
apps/app/src/layouts/__tests__/PublicLayout.spec.ts
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import { describe, expect, it } from 'vitest'
|
||||||
|
import { mount } from '@vue/test-utils'
|
||||||
|
import PublicLayout from '../PublicLayout.vue'
|
||||||
|
|
||||||
|
// Stub Vuetify components as their semantic HTML equivalents so we can
|
||||||
|
// assert structure without pulling vuetify/components (which loads .css
|
||||||
|
// files that the trimmed-down vitest config can't transform).
|
||||||
|
const vuetifyStubs = {
|
||||||
|
VApp: { template: '<div><slot /></div>' },
|
||||||
|
VMain: { template: '<main><slot /></main>' },
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('PublicLayout', () => {
|
||||||
|
it('mounts without throwing', () => {
|
||||||
|
const wrapper = mount(PublicLayout, {
|
||||||
|
global: {
|
||||||
|
stubs: { ...vuetifyStubs, RouterView: true },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(wrapper.exists()).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does NOT render a header or footer (intentionally minimal)', () => {
|
||||||
|
const wrapper = mount(PublicLayout, {
|
||||||
|
global: {
|
||||||
|
stubs: { ...vuetifyStubs, RouterView: true },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(wrapper.find('header').exists()).toBe(false)
|
||||||
|
expect(wrapper.find('footer').exists()).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders a RouterView inside main', () => {
|
||||||
|
const wrapper = mount(PublicLayout, {
|
||||||
|
global: {
|
||||||
|
stubs: {
|
||||||
|
...vuetifyStubs,
|
||||||
|
RouterView: { template: '<div data-test="router-view" />' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(wrapper.find('main [data-test="router-view"]').exists()).toBe(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user