reportTabNavigation: адрес новой вкладки и replace; OsvTabs переходит через неё (и после модалки [31-00]). Change report-tabs-history: MODIFIED «Вкладки страницы отчёта по версии» (intercompany-matrix-ui). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
146 lines
6.0 KiB
TypeScript
146 lines
6.0 KiB
TypeScript
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 },
|
||
});
|
||
});
|
||
});
|