Files
portal/app/tests/Frontend/ErrorView.spec.ts
T
Дмитрий 84dfbc857a
Accessibility (Pa11y live) / a11y (push) Has been cancelled
test(фронт): привёл стенд в зелёный — 10 протухших спеков под актуальные компоненты
Все падения — устаревшие ожидания тестов (компоненты менялись намеренно):
SettingsView (роутер+вкладка Реквизиты+события), LegalDoc (реальные доки под ЮKassa),
ProjectsView (BulkActionsBar v-show→isVisible), ErrorView (убран фейк REQ/INC),
PricingTiers (формат «500 ₽»), KanbanCard (costKopecks→«—»), ChangePassword (дата из API),
DealDetail (русские ярлыки статусов), DealsView (RuDateField на v-menu), SupplierIntegration
(window.confirm→v-dialog). Изменены ТОЛЬКО тесты, компоненты не тронуты.
Полный прогон: 127 файлов / 992 теста зелёные.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 12:59:01 +03:00

101 lines
4.8 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 ErrorView from '../../resources/js/views/errors/ErrorView.vue';
// ErrorView читает route.meta.errorCode для конфигурации экрана.
const mountErrorView = async (errorCode: '404' | '403' | '500') => {
const router = createRouter({
history: createMemoryHistory(),
routes: [
{ path: '/error', component: ErrorView, meta: { errorCode } },
{ path: '/dashboard', component: { template: '<div>dashboard stub</div>' } },
],
});
await router.push('/error');
await router.isReady();
return mount(ErrorView, {
global: {
plugins: [createVuetify(), router],
// ErrorView содержит v-app + v-main — те же layout-проблемы что у DealDetailDrawer.
// Stub'им VApp/VMain как passthrough.
stubs: {
VApp: { template: '<div class="v-app-stub"><slot /></div>' },
VMain: { template: '<div class="v-main-stub"><slot /></div>' },
},
},
});
};
describe('ErrorView.vue', () => {
it('по умолчанию (errorCode=404) показывает «404 / Страница не найдена»', async () => {
const wrapper = await mountErrorView('404');
const text = wrapper.text();
expect(wrapper.find('.err-code').text()).toBe('404');
expect(text).toContain('Страница не найдена');
expect(text).toContain('Все рабочие экраны Лидерра доступны через дашборд');
});
it('errorCode=403 показывает «403 / У вас нет доступа» (фейк-RequestId убран)', async () => {
const wrapper = await mountErrorView('403');
const text = wrapper.text();
expect(wrapper.find('.err-code').text()).toBe('403');
expect(text).toContain('У вас нет доступа');
// Хардкод «REQ-3F8A2-0007» убран намеренно (не показываем фейк как настоящее).
expect(text).not.toContain('REQ-3F8A2-0007');
});
it('errorCode=500 показывает «500 / Что-то пошло не так» (фейк-Incident/status-list убраны)', async () => {
const wrapper = await mountErrorView('500');
const text = wrapper.text();
expect(wrapper.find('.err-code').text()).toBe('500');
expect(text).toContain('Что-то пошло не так');
// Хардкод «INC-2026-0507-0034» + фейк-список статусов убраны намеренно.
expect(text).not.toContain('INC-2026-0507-0034');
expect(text).not.toContain('Telegram · деградация');
});
it('404 содержит «На дашборд» primary + «Назад» secondary', async () => {
const wrapper = await mountErrorView('404');
const text = wrapper.text();
expect(text).toContain('На дашборд');
expect(text).toContain('Назад');
});
it('403 содержит «На дашборд» + «Написать в поддержку» (mailto)', async () => {
const wrapper = await mountErrorView('403');
const text = wrapper.text();
expect(text).toContain('На дашборд');
expect(text).toContain('Написать в поддержку');
const mailtoLink = wrapper.find('a[href^="mailto:"]');
expect(mailtoLink.exists()).toBe(true);
expect(mailtoLink.attributes('href')).toBe('mailto:support@liderra.ru');
});
it('500 содержит «Попробовать снова» + «Статус сервиса» (external link)', async () => {
const wrapper = await mountErrorView('500');
const text = wrapper.text();
expect(text).toContain('Попробовать снова');
expect(text).toContain('Статус сервиса');
const statusLink = wrapper.find('a[href^="https://status."]');
expect(statusLink.exists()).toBe(true);
});
it('содержит брендовый блок «Лидерра.» в шапке', async () => {
const wrapper = await mountErrorView('404');
const brand = wrapper.find('.top-brand');
expect(brand.exists()).toBe(true);
expect(brand.text()).toContain('Лидерра');
});
it('404 НЕ содержит RequestId или status-list', async () => {
const wrapper = await mountErrorView('404');
const text = wrapper.text();
expect(text).not.toContain('REQ-');
expect(text).not.toContain('INC-');
expect(text).not.toContain('API · OK');
});
});