103 lines
4.7 KiB
TypeScript
103 lines
4.7 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 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('У вас нет доступа');
|
|||
|
|
expect(text).toContain('REQ-3F8A2-0007');
|
|||
|
|
expect(text).toContain('Запрос');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('errorCode=500 показывает «500 / Что-то пошло не так» + IncidentId + status-list', async () => {
|
|||
|
|
const wrapper = await mountErrorView('500');
|
|||
|
|
const text = wrapper.text();
|
|||
|
|
expect(wrapper.find('.err-code').text()).toBe('500');
|
|||
|
|
expect(text).toContain('Что-то пошло не так');
|
|||
|
|
expect(text).toContain('INC-2026-0507-0034');
|
|||
|
|
expect(text).toContain('Инцидент');
|
|||
|
|
// status-list только на 500.
|
|||
|
|
expect(text).toContain('API · OK');
|
|||
|
|
expect(text).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.app');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
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');
|
|||
|
|
});
|
|||
|
|
});
|