e909a95a8d
- vue-router@^4.6.4 (--legacy-peer-deps из-за Histoire vs Vite 8 peerDep). - resources/js/router/index.ts: createWebHistory + lazy-imports + meta.layout. Маршрут / -> /login, /login -> LoginView (meta.layout=auth). - resources/js/layouts/AuthLayout.vue: двухпанельный (brand-pane тёмный с radial-gradient акцентами + form-pane warm ivory). На mobile brand-pane скрыт. - resources/js/views/auth/LoginView.vue: форма Vuetify по v8_login.html секция #form-login - email/password (autocomplete + eye-icon), primary submit, Yandex 360 SSO, RouterLink на /register и /forgot. - AppShell.vue: layout-mapper по route.meta.layout (default/auth). - routes/web.php: явные Route::view для 6 SPA-путей (НЕ catch-all - он перехватывал /_test/* в Pest beforeEach и валил 5 SetTenantContextTest). - Vitest: +LoginView.spec.ts (5), +router.spec.ts (2), AppShell.spec.ts переписан (3). Vitest 10/10 за 3.01s. - LoginView.story.vue для Histoire. Setup расширен memory-router'ом. - cspell-words.txt: рендерят, коммиты, Лидерру. - Регресс: lint:vue OK, type-check OK, format:check OK, vitest 10/10, vite build 212 модулей за 383ms (LoginView lazy-chunk 43.5KB JS / 51.7KB CSS), story:build 2/2 за 29.94s, Pest 48/48 за 4.86s. CLAUDE.md v1.18->v1.19, реестр Открытых_вопросов v1.27->v1.28. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
46 lines
1.9 KiB
TypeScript
46 lines
1.9 KiB
TypeScript
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 мапит meta.layout текущего route'а на layout-компонент.
|
|
// На default-layout рендерит v-app + v-app-bar; на 'auth' — AuthLayout.
|
|
|
|
const mountWithRouter = async (path: string, defaultMeta: Record<string, unknown> = {}) => {
|
|
const router = createRouter({
|
|
history: createMemoryHistory(),
|
|
routes: [
|
|
{ path: '/', redirect: '/test' },
|
|
{ path: '/test', component: { template: '<div>test view</div>' }, meta: defaultMeta },
|
|
{ path: '/login', component: { template: '<div>login stub</div>' }, meta: { layout: 'auth' } },
|
|
],
|
|
});
|
|
await router.push(path);
|
|
await router.isReady();
|
|
return mount(AppShell, {
|
|
global: {
|
|
plugins: [createVuetify(), router],
|
|
},
|
|
});
|
|
};
|
|
|
|
describe('AppShell.vue', () => {
|
|
it('монтируется без ошибок на default-layout', async () => {
|
|
const wrapper = await mountWithRouter('/test');
|
|
expect(wrapper.exists()).toBe(true);
|
|
});
|
|
|
|
it('рендерит брендовое имя и chip фазы на default-layout', async () => {
|
|
const wrapper = await mountWithRouter('/test');
|
|
expect(wrapper.text()).toContain('Лидерра.');
|
|
expect(wrapper.text()).toContain('phase 2');
|
|
});
|
|
|
|
it('переключается на AuthLayout при meta.layout = auth', async () => {
|
|
const wrapper = await mountWithRouter('/login');
|
|
// На auth-layout shell не показывает app-bar и phase-chip — рендерится AuthLayout.
|
|
expect(wrapper.text()).not.toContain('phase 2');
|
|
});
|
|
});
|