Files
portal/app/tests/Frontend/AppShell.spec.ts
T
Дмитрий 1e233a70c8 phase2(dashboard): AppLayout + DashboardView - default-layout приложения
- AppLayout: v-navigation-drawer (теало-нуар sidebar 240px) + brand-block
  + nav-tree из 8 пунктов в 3 группах (Работа/Финансы/Команда), v-app-bar
  с crumb «Рабочая область → currentPage» + search ⌘K + bell + user-chip.
  Mobile (md<): drawer toggleable.
- DashboardView: page-head «Доброе утро, Иван» + page-meta + range-toggle
  4 опции (Сегодня/7д/30д/Период). KPI-row из 4 cards: 3 outlined (получено
  лидов/конверсия/активные проекты) + 1 hero balance с runway-bar 4/7
  заполненных сегментов teal #32C8A9.
- AppShell упрощён до layout-mapper (route.meta.layout 'app'/'auth').
- Маршрут /dashboard (meta.layout='app') в router + web.php.
- histoire.setup расширен 8 app-stub-маршрутами для AppLayout.
- Vitest +11 тестов: AppLayout 6 (brand+3 группы+8 пунктов+счётчики+crumb),
  DashboardView 5, AppShell.spec.ts переписан под layout-mapper.
- cspell-words.txt: JBM.

Регресс: lint+type-check+format OK; vitest 35/35 за 4.92s; vite build
DashboardView lazy-chunk 14.9KB; story:build 8/8 за 28.97s; Pest 48/48 за 4.88s.

CLAUDE.md v1.20->v1.21, реестр Открытых_вопросов v1.29->v1.30.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 17:21:19 +03:00

54 lines
2.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, it, expect } from 'vitest';
import { mount } from '@vue/test-utils';
import { createVuetify } from 'vuetify';
import { createRouter, createMemoryHistory } from 'vue-router';
import AppShell from '../../resources/js/components/AppShell.vue';
// AppShell — layout-mapper по route.meta.layout: 'app' (default) → AppLayout, 'auth' → AuthLayout.
const mountWithRouter = async (path: string) => {
const router = createRouter({
history: createMemoryHistory(),
routes: [
{ path: '/', redirect: '/dashboard' },
{ path: '/dashboard', component: { template: '<div>dashboard</div>' }, meta: { layout: 'app' } },
{ path: '/login', component: { template: '<div>login stub</div>' }, meta: { layout: 'auth' } },
// Stub'ы для всех nav-targets AppLayout, чтобы избежать router-warn'ов.
{ path: '/deals', component: { template: '<div />' } },
{ path: '/kanban', component: { template: '<div />' } },
{ path: '/reminders', component: { template: '<div />' } },
{ path: '/billing', component: { template: '<div />' } },
{ path: '/reports', component: { template: '<div />' } },
{ path: '/managers', component: { template: '<div />' } },
{ path: '/settings', component: { template: '<div />' } },
],
});
await router.push(path);
await router.isReady();
return mount(AppShell, {
global: { plugins: [createVuetify(), router] },
});
};
describe('AppShell.vue', () => {
it('монтируется без ошибок', async () => {
const wrapper = await mountWithRouter('/dashboard');
expect(wrapper.exists()).toBe(true);
});
it('рендерит AppLayout на default-layout (sidebar с brand + nav)', async () => {
const wrapper = await mountWithRouter('/dashboard');
expect(wrapper.text()).toContain('Лидерра');
// Sidebar nav-группы и пункты — признак AppLayout.
expect(wrapper.text()).toContain('Дашборд');
expect(wrapper.text()).toContain('Сделки');
});
it('переключается на AuthLayout при meta.layout = auth', async () => {
const wrapper = await mountWithRouter('/login');
// На auth-layout sidebar не рендерится — нет nav-пунктов «Сделки»/«Дашборд».
expect(wrapper.text()).not.toContain('Сделки');
expect(wrapper.text()).not.toContain('Дашборд');
});
});