d1f3b0581e
Владелец нажал «Показать на портале» в чате и не смог посмотреть: его выкинуло на «Вход», после входа увело на дашборд (адрес экскурсии потерян), а сверху сел приветственный тур «Добро пожаловать в Лидерру». 1. LoginView теперь возвращает клиента по redirect (роутер его уже сохранял) — /dashboard?tour=dupes открывается сразу после входа. Чужой адрес в redirect игнорируется (защита от подмены ссылки). 2. WelcomeTour молчит, если в адресе есть ?tour= — экскурсия из чата важнее. Оба бага сначала воспроизведены тестами. Vitest 1225/1225. Проверено живьём: гость → ссылка бота → форма входа → сразу «Шаг 1 из 4» нужной экскурсии. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
80 lines
3.4 KiB
TypeScript
80 lines
3.4 KiB
TypeScript
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
import { mount } from '@vue/test-utils';
|
|
import { createVuetify } from 'vuetify';
|
|
import WelcomeTour from '../../resources/js/components/layout/WelcomeTour.vue';
|
|
|
|
const vuetify = createVuetify();
|
|
const SEEN_KEY = 'liderra.welcomeTourSeen';
|
|
|
|
const factory = () => mount(WelcomeTour, { global: { plugins: [vuetify] } });
|
|
|
|
describe('WelcomeTour.vue (Фаза 3)', () => {
|
|
beforeEach(() => {
|
|
localStorage.clear();
|
|
vi.stubGlobal('requestAnimationFrame', (cb: FrameRequestCallback) => {
|
|
cb(0);
|
|
return 0;
|
|
});
|
|
});
|
|
|
|
it('не лезет поверх экскурсии из чата бота (в адресе есть ?tour=)', () => {
|
|
// Живой баг 12.07.2026: клиент жмёт «Показать на портале» — и вместо нужной
|
|
// экскурсии получает приветственный тур «Добро пожаловать в Лидерру».
|
|
const orig = window.location.search;
|
|
Object.defineProperty(window, 'location', {
|
|
value: { ...window.location, search: '?tour=dupes' },
|
|
writable: true,
|
|
});
|
|
|
|
const w = factory();
|
|
const vm = w.vm as unknown as { active: boolean };
|
|
|
|
expect(vm.active).toBe(false);
|
|
expect(w.find('[data-testid="welcome-tour"]').exists()).toBe(false);
|
|
|
|
Object.defineProperty(window, 'location', {
|
|
value: { ...window.location, search: orig },
|
|
writable: true,
|
|
});
|
|
});
|
|
|
|
it('показывается новому пользователю (флага нет) с первого шага', () => {
|
|
const w = factory();
|
|
const vm = w.vm as unknown as { active: boolean; stepIndex: number; steps: unknown[] };
|
|
expect(vm.active).toBe(true);
|
|
expect(vm.stepIndex).toBe(0);
|
|
expect(w.find('[data-testid="welcome-tour"]').exists()).toBe(true);
|
|
expect(w.text()).toContain('Добро пожаловать');
|
|
});
|
|
|
|
it('НЕ показывается, если тур уже видели (флаг в localStorage)', () => {
|
|
localStorage.setItem(SEEN_KEY, '1');
|
|
const w = factory();
|
|
const vm = w.vm as unknown as { active: boolean };
|
|
expect(vm.active).toBe(false);
|
|
expect(w.find('[data-testid="welcome-tour"]').exists()).toBe(false);
|
|
});
|
|
|
|
it('«Далее» проходит все шаги, «Готово» закрывает и ставит флаг', async () => {
|
|
const w = factory();
|
|
const vm = w.vm as unknown as { active: boolean; stepIndex: number; steps: unknown[]; next: () => void };
|
|
const total = vm.steps.length;
|
|
for (let i = 0; i < total - 1; i++) {
|
|
vm.next();
|
|
}
|
|
expect(vm.stepIndex).toBe(total - 1);
|
|
expect(vm.active).toBe(true);
|
|
vm.next(); // последний шаг → finish
|
|
expect(vm.active).toBe(false);
|
|
expect(localStorage.getItem(SEEN_KEY)).toBe('1');
|
|
});
|
|
|
|
it('«Пропустить» закрывает тур и ставит флаг', async () => {
|
|
const w = factory();
|
|
await w.find('[data-testid="tour-skip"]').trigger('click');
|
|
const vm = w.vm as unknown as { active: boolean };
|
|
expect(vm.active).toBe(false);
|
|
expect(localStorage.getItem(SEEN_KEY)).toBe('1');
|
|
});
|
|
});
|