arm-core/web/src/utils/consolidations.test.ts
Andrey Epifancev 8eebedf657 fix(web): смена вкладки отчёта без новой записи истории — «Назад» к списку консолидаций (#191, AURORA-1851)
reportTabNavigation: адрес новой вкладки и replace; OsvTabs переходит через неё (и после модалки [31-00]).
Change report-tabs-history: MODIFIED «Вкладки страницы отчёта по версии» (intercompany-matrix-ui).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 18:04:40 +04:00

146 lines
6.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 { ConsStatus, LockOut } from '../types/consolidations/common_types';
import {
CONS_STATUS_LABEL,
MANUAL_TRANSITIONS,
canChangeStatus,
canSubmitStatusChange,
canTakeInWork,
consStatusDescription,
endSentence,
isLockedBy,
isValidReason,
manualTransitions,
needsUnmappedWarning,
parseInWorkOnly,
reportTabNavigation,
versionLabel,
} from './consolidations';
const lock = (userId: string): LockOut => ({
locked_by: userId,
locked_by_name: 'Соколов А. В.',
locked_at: '2026-10-23T10:00:00Z',
taken_over_from: null,
takeover_reason: null,
});
const ALL: ConsStatus[] = Object.keys(CONS_STATUS_LABEL) as ConsStatus[];
describe('versionLabel', () => {
it('первая версия — пусто, последующие — номер', () => {
expect(versionLabel(1)).toBe('');
expect(versionLabel(2)).toBe('2');
expect(versionLabel(10)).toBe('10');
});
});
describe('parseInWorkOnly', () => {
it('по умолчанию выключен, включает только явное true', () => {
expect(parseInWorkOnly(null)).toBe(false);
expect(parseInWorkOnly('')).toBe(false);
expect(parseInWorkOnly('false')).toBe(false);
expect(parseInWorkOnly('true')).toBe(true);
});
});
describe('подписи и пояснения статусов', () => {
it('подписи из спеки', () => {
expect(CONS_STATUS_LABEL.DATA_CORRECTION).toBe('Корректировка данных');
expect(CONS_STATUS_LABEL.CANCELLED).toBe('Отменена');
});
it('пояснение не повторяет подпись', () => {
for (const s of ALL) {
expect(consStatusDescription(s)).not.toBe(CONS_STATUS_LABEL[s]);
}
});
it('пояснения статусов первой очереди и макета заданы', () => {
for (const s of ['INITIATED', 'DOCUMENTS_PROCESSING', 'DATA_CORRECTION', 'CANCELLED', 'CONSOLIDATION_RF', 'VERIFIED'] as const) {
expect(consStatusDescription(s)).not.toBe('');
}
expect(consStatusDescription('CONSOLIDATION_RF')).toBe('Автоматическая консолидация, ручные проверки и сравнение КФО клиента и банка');
expect(consStatusDescription('VERIFIED')).toBe('Отчет верифицирован ГО, КА ГО внес в систему номер и дату решения УОБ');
});
});
describe('ручные переходы (зеркало MANUAL_TRANSITIONS бэка)', () => {
it('совпадают с api/src/services/consolidation_status.py', () => {
expect(MANUAL_TRANSITIONS).toEqual({
INITIATED: ['CANCELLED'],
DOCUMENTS_PROCESSING: ['CANCELLED', 'INITIATED'],
DATA_CORRECTION: ['CANCELLED', 'INITIATED'],
});
});
it('из остальных статусов переходов нет', () => {
for (const s of ['VERIFIED', 'CANCELLED', 'CONSOLIDATION_RF', 'VERIFICATION_RF', 'CONSOLIDATION_GO', 'VERIFICATION_GO'] as const) {
expect(manualTransitions(s)).toEqual([]);
}
});
});
describe('блокировка и «Изменить статус»', () => {
it('своя блокировка', () => {
expect(isLockedBy(lock('me'), 'me')).toBe(true);
expect(isLockedBy(lock('other'), 'me')).toBe(false);
expect(isLockedBy(null, 'me')).toBe(false);
expect(isLockedBy(undefined, 'me')).toBe(false);
});
it('кнопка: своя / чужая / нет блокировки × есть / нет переходов', () => {
expect(canChangeStatus('DATA_CORRECTION', lock('me'), 'me')).toBe(true);
expect(canChangeStatus('DATA_CORRECTION', lock('other'), 'me')).toBe(false);
expect(canChangeStatus('DATA_CORRECTION', null, 'me')).toBe(false);
expect(canChangeStatus('VERIFIED', lock('me'), 'me')).toBe(false);
expect(canChangeStatus('VERIFIED', lock('other'), 'me')).toBe(false);
expect(canChangeStatus('VERIFIED', null, 'me')).toBe(false);
});
it('«Взять в работу» недоступна только у отменённой версии', () => {
expect(canTakeInWork('CANCELLED')).toBe(false);
expect(canTakeInWork('INITIATED')).toBe(true);
expect(canTakeInWork('VERIFIED')).toBe(true);
});
});
describe('причина и комментарий', () => {
it('пустая и из пробелов — неверна', () => {
expect(isValidReason('')).toBe(false);
expect(isValidReason(' ')).toBe(false);
expect(isValidReason(undefined)).toBe(false);
expect(isValidReason(null)).toBe(false);
});
it('ровно 1000 символов можно, 1001 — нет', () => {
expect(isValidReason('a'.repeat(1000))).toBe(true);
expect(isValidReason('a'.repeat(1001))).toBe(false);
expect(isValidReason(` ${'a'.repeat(1000)} `)).toBe(true);
});
it('модалка: нужен выбранный этап и непустой комментарий', () => {
expect(canSubmitStatusChange(undefined, 'Дубль')).toBe(false);
expect(canSubmitStatusChange('CANCELLED', undefined)).toBe(false);
expect(canSubmitStatusChange('CANCELLED', ' ')).toBe(false);
expect(canSubmitStatusChange('CANCELLED', 'Дубль')).toBe(true);
});
});
describe('endSentence', () => {
it('не ставит вторую точку после инициалов', () => {
expect(endSentence('Соколов А. В.')).toBe('Соколов А. В.');
expect(endSentence('Dev: Аналитик ГО')).toBe('Dev: Аналитик ГО.');
});
});
describe('модалка [31-00]', () => {
it('только при несопоставленных строках', () => {
expect(needsUnmappedWarning(2)).toBe(true);
expect(needsUnmappedWarning(0)).toBe(false);
expect(needsUnmappedWarning(undefined)).toBe(false);
});
});
describe('вкладки отчёта (AURORA-1851)', () => {
it('смена вкладки заменяет запись истории: «Назад» ведёт со страницы отчёта, а не по вкладкам', () => {
expect(reportTabNavigation('/groups/g1/versions/v1/osv', 'osv', 'chess')).toEqual({
to: '/groups/g1/versions/v1/chess',
options: { replace: true },
});
});
});