feat(layouts): add OrganizerLayoutV2 + AppShellV2 skeleton

Tailwind-grid shell skeleton with named slot regions (sidebar, topbar,
default, drawer). OrganizerLayoutV2 wires the skeleton with RouterView,
selectable via definePage meta. Vitest component mount test: 2 tests pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-16 11:44:42 +02:00
parent b160f53f13
commit 73b2dea363
3 changed files with 104 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
import { describe, expect, it } 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: '<nav data-testid="sb">SB</nav>',
topbar: '<header data-testid="tb">TB</header>',
default: '<main data-testid="content">CONTENT</main>',
drawer: '<aside data-testid="dr">DR</aside>',
},
})
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')
})
})