arm-core/web/src/widgets/QualityMetrics/qualityView.test.ts
Andrey Epifancev 7ded34fec5 fix(#190): доработки экрана качества по ревью Task 16
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-11-07 02:56:27 +04:00

106 lines
4.0 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, expect, it } from 'vitest';
import type { QualityMatrixOut } from '../../types/qualityMetrics';
import { filterByPermission } from '../Sidebar/visibility';
import { buildMatrixRows, buildSourceRows, formatReportDate, formatShare, monthLabel, sourceColumns, sumFixes } from './qualityView';
const matrixFixture: QualityMatrixOut = {
counts: { SERVICE_ERROR: 3, OUR_ERROR: 2, CLIENT_DOCUMENT: 1, WITHOUT_PARTICIPATION: 12, AS_IS: 5 },
shares: { SERVICE_ERROR: 0.13, OUR_ERROR: 0.087, CLIENT_DOCUMENT: 0.043, WITHOUT_PARTICIPATION: 0.522, AS_IS: 0.217 },
denominator: 23,
removed_before_confirm: 4,
removed_after_confirm: 3,
deleted_after_confirm_count: 1,
superseded_after_confirm_count: 2,
in_progress_count: 6,
unique_reports_count: 20,
technical_failures: { failed_files_count: 1, total_files_count: 30, share: 0.033 },
};
describe('пункт меню по праву', () => {
const items = [{ link: '/a' }, { link: '/q', permission: 'QUALITY_METRICS_VIEW' }];
it('скрыт без права', () => {
expect(filterByPermission(items, ['USERS_ADMIN']).map((i) => i.link)).toEqual(['/a']);
});
it('виден с правом', () => {
expect(filterByPermission(items, ['QUALITY_METRICS_VIEW']).map((i) => i.link)).toEqual(['/a', '/q']);
});
});
describe('buildMatrixRows', () => {
const rows = buildMatrixRows(matrixFixture);
it('счётчики из ответа API', () => {
expect(rows.find((r) => r.key === 'WITHOUT_PARTICIPATION')?.count).toBe(12);
expect(rows.find((r) => r.key === 'REMOVED_BEFORE_CONFIRM')?.count).toBe(4);
expect(rows.find((r) => r.key === 'IN_PROGRESS')?.count).toBe(6);
});
it('доли только у причин; разбивка удалённых после подтверждения', () => {
expect(rows.find((r) => r.key === 'WITHOUT_PARTICIPATION')?.share).toBe('52,2%');
expect(rows.find((r) => r.key === 'IN_PROGRESS')?.share).toBeNull();
expect(rows.find((r) => r.key === 'REMOVED_AFTER_CONFIRM')?.note).toBe('удалено: 1, заменено: 2');
});
});
describe('formatShare', () => {
it('нет знаменателя — «нет данных», не 0%', () => {
expect(formatShare(0, 0)).toBe('нет данных');
});
});
describe('monthLabel', () => {
it('месяц.год', () => {
expect(monthLabel('2026-03-01')).toBe('03.2026');
});
});
describe('sourceColumns', () => {
it('источник не выбран — PDF, Excel, Всего', () => {
expect(sourceColumns(undefined).map((c) => c.key)).toEqual(['image', 'tabular', 'all']);
});
it('выбран источник — одна колонка', () => {
expect(sourceColumns('tabular').map((c) => c.label)).toEqual(['Excel']);
});
});
describe('buildSourceRows', () => {
it('счётчики по колонкам источника', () => {
const excel = { ...matrixFixture, counts: { ...matrixFixture.counts, AS_IS: 1 } };
const rows = buildSourceRows([
{ key: 'image', data: matrixFixture },
{ key: 'tabular', data: excel },
]);
const asIs = rows.find((r) => r.key === 'AS_IS');
expect(asIs?.cells.image?.count).toBe(5);
expect(asIs?.cells.tabular?.count).toBe(1);
});
it('пустой список колонок — нет строк', () => {
expect(buildSourceRows([])).toEqual([]);
});
});
describe('sumFixes', () => {
it('суммирует по сервису и по нашему разбору, правку ОСВ не считает', () => {
const fixes = {
value_service: 1,
value_ours: 2,
code_service: 3,
code_ours: 4,
added_row_service: 5,
added_row_ours: 6,
header_service: 7,
header_ours: 8,
osv_period_account: 9,
};
expect(sumFixes(fixes)).toEqual({ service: 16, ours: 20 });
});
it('нет правок — null', () => {
expect(sumFixes(null)).toBeNull();
});
});
describe('formatReportDate', () => {
it('ДД.ММ.ГГГГ', () => {
expect(formatReportDate('2026-03-31')).toBe('31.03.2026');
expect(formatReportDate(null)).toBe('—');
});
});