import { describe, expect, it, vi } from 'vitest' import { mount } from '@vue/test-utils' import { createPinia } from 'pinia' import AppShellV2 from '@/layouts/components/AppShellV2.vue' describe('AppShellV2 (skeleton)', () => { it('renders the grid regions and default slot content', () => { const wrapper = mount(AppShellV2, { global: { plugins: [createPinia()] }, slots: { sidebar: '', topbar: '
TB
', default: '
CONTENT
', drawer: '', }, }) expect(wrapper.find('[data-testid="appshell-v2"]').exists()).toBe(true) expect(wrapper.find('[data-testid="sb"]').exists()).toBe(true) expect(wrapper.find('[data-testid="tb"]').exists()).toBe(true) expect(wrapper.find('[data-testid="content"]').text()).toBe('CONTENT') expect(wrapper.find('[data-testid="dr"]').exists()).toBe(true) }) it('applies the collapsed modifier from useShellUiStore', async () => { const pinia = createPinia() const wrapper = mount(AppShellV2, { global: { plugins: [pinia] } }) const { useShellUiStore } = await import('@/stores/useShellUiStore') useShellUiStore().toggleSidebar() await wrapper.vm.$nextTick() expect(wrapper.find('[data-testid="appshell-v2"]').classes()).toContain('is-collapsed') }) // Plan 2.5 P8 dedupe — AppShellV2's watch([theme, density]) is the single // applyDomAttributes() authority. toggleDensity() (useShellUiStore) no longer // writes the DOM itself; the watch covers it. These specs lock that contract: // the density change reaches via the watch, and exactly one // applyDomAttributes() call fires per toggle (no redundant double-call). it('watch writes the toggled density to ', async () => { document.documentElement.removeAttribute('data-density') const pinia = createPinia() const wrapper = mount(AppShellV2, { global: { plugins: [pinia] } }) const { useShellUiStore } = await import('@/stores/useShellUiStore') const shell = useShellUiStore() // onMounted seeded the comfortable default. expect(document.documentElement.getAttribute('data-density')).toBe('comfortable') shell.toggleDensity() await wrapper.vm.$nextTick() expect(document.documentElement.getAttribute('data-density')).toBe('compact') }) it('density toggle fires applyDomAttributes exactly once (via the watch, not toggleDensity)', async () => { const pinia = createPinia() const wrapper = mount(AppShellV2, { global: { plugins: [pinia] } }) const { useShellUiStore } = await import('@/stores/useShellUiStore') const shell = useShellUiStore() // Spy AFTER mount so the onMounted seed call is excluded from the count. const spy = vi.spyOn(shell, 'applyDomAttributes') shell.toggleDensity() await wrapper.vm.$nextTick() expect(spy).toHaveBeenCalledTimes(1) }) })