Перенесён диапазон arm-web 0f2bbc8..4a02512 (23 коммитов, 51 файлов набора синхронизации) скриптом docs/scripts/sync-web.sh. После переноса web/ и arm-web@test идентичны по набору. Коммиты arm-web: - 4fb477d Подпись пустой цели «цель не заполнена», тесты null/null (ревью I-1, M-1, M-2, M-4) - cb36ec8 Нарушения проверок: expected/actual и индекс колонки могут быть null (#45) - b4b8c04 openspec(statements-v2): решения по итогам прогона в браузере (T11.D-1…D-5, #43) - aa3054e docs(arm-web): экран формы v5.19 — README и карта модулей (#43) - 88a4920 fix(arm-web): нераспознанный текст суммы, пустые подстроки без расшифровок, свёрнутый список предупреждений (#43) - a3199d6 fix(arm-web): вёрстка экрана проверки формы — ширины колонок, значки в ячейке, шапка, ссылка кнопкой (#43) - 12fcea7 fix(statement): защитные значения по умолчанию для ядра без v5.19 (M-2, #43) - 4783593 fix(statement): ссылка на строки без кода всегда видна, сортировка по row_index, Alert для ошибки скрытого поля кода, постоянный aria-label (T9.1, T9.2, T9.4, T7.1, T8.1, T3.3, M-3, #43) - d965fdc fix(statement): округление уверенности в подсказках шапки, пустые тексты в подсказках, комментарий шапки (T5.1, T5.2, M-1, T3.1, #43) - 6556e3d fix(statement): не отправлять поля шапки, равные текущим (I-2, #43) - 8d2deb9 docs(openspec): решения без обсуждения из исполнения и имя кнопки «Подтвердить данные» (#43) - fc5cc16 fix(files): клики внутри popover не открывают строку, ключи и aria-label (#43) - fdf9358 feat(files): предупреждения файла структурами и предупреждения документа в панели файлов и у ОСВ (#43) - 5b11f2d feat(statement): блокировка подтверждения при строках без кода, LINES_UNRESOLVED и DUPLICATE_FORM (#43) - a779d2a feat(statement): подтверждение ячеек, дата колонки, наименование организации и подтверждение даты (#43) - d416422 feat(statement): правка строк — код с подсказкой из справочника, меню строки, LINE_CODE_TAKEN (#43) - ef4d325 refactor(statement): один черновик правок и сборка единственного PATCH (#43) - 8ab116f feat(statement): шапка — организация, поля на проверку и подсказки распознанного текста (#43) - 4ae8643 feat(statement): предупреждения и нарушения у строк, ячеек, колонок и в списке документа (#43) - 34d523a feat(statement): вид строк по статусам, подсветка по needs_review, переключатель расшифровок (#43) - c2f33e7 feat(statement): раскладка строк без кода и расшифровок на своих местах (#43) - e4ee7f0 fix(fixtures): коды соотношения, column_index, порядок edition_lines (#43) - f83b035 feat(types): API формы v5.19 — статусы строк, needs_review, issues, предупреждения файла (#43) Co-Authored-By: sync-web.sh <noreply@aepif.ru>
96 lines
4.1 KiB
TypeScript
96 lines
4.1 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
||
import type { IssueOut, StatementOut } from '../../types/api';
|
||
import statementV2Json from './__fixtures__/statement-v2.json';
|
||
import { collapseIssues, issueListItems, issuePlaces, worstSeverity } from './issuePlaces';
|
||
import { buildStatementGrid, cellKey } from './statementGrid';
|
||
|
||
const statement = statementV2Json as unknown as StatementOut;
|
||
const { rows, columns } = buildStatementGrid(statement);
|
||
const ids = (list: IssueOut[] | undefined) => (list ?? []).map((i) => i.id);
|
||
const issue = (patch: Partial<IssueOut>): IssueOut => ({
|
||
id: 'x',
|
||
kind: 'warning',
|
||
code: 'X',
|
||
severity: 'info',
|
||
message: 'm',
|
||
line_ids: [],
|
||
column_id: null,
|
||
column_index: null,
|
||
field: null,
|
||
source: 'service',
|
||
relation: null,
|
||
codes: [],
|
||
expected: null,
|
||
actual: null,
|
||
...patch,
|
||
});
|
||
|
||
describe('issuePlaces', () => {
|
||
it('привязка фикстуры', () => {
|
||
const p = issuePlaces(statement.issues, rows, columns);
|
||
expect(ids(p.byRow.get('l-1370a'))).toContain('i1');
|
||
expect(ids(p.byRow.get('l-1370b'))).toContain('i1');
|
||
for (const k of ['l-1200', 'l-1210', 'l-1230', 'l-1240']) expect(ids(p.byCell.get(cellKey(k, 'c1')))).toEqual(['i6']);
|
||
expect(ids(p.byColumn.get('c2'))).toEqual(['i2']);
|
||
expect(ids(p.byField.get('organization_name'))).toEqual(['i3']);
|
||
expect(ids(p.byField.get('report_date'))).toEqual(['i5']);
|
||
expect(ids(p.document)).toEqual(['i4']);
|
||
expect(ids(p.byRow.get('l-1230'))).toEqual(['i7']);
|
||
});
|
||
it('неизвестные строки и поля — у документа', () => {
|
||
const gone = issue({ id: 'g', line_ids: ['l-gone'] });
|
||
const mixed = issue({ id: 'm', line_ids: ['l-gone', 'l-1210'] });
|
||
const okpo = issue({ id: 'o', field: 'okpo' });
|
||
const p = issuePlaces([gone, mixed, okpo], rows, columns);
|
||
expect(ids(p.document)).toEqual(['g', 'o']);
|
||
expect(ids(p.byRow.get('l-1210'))).toEqual(['m']);
|
||
expect(p.byRow.size).toBe(1);
|
||
});
|
||
});
|
||
|
||
describe('issueListItems', () => {
|
||
const p = issuePlaces(statement.issues, rows, columns);
|
||
const items = issueListItems(statement.issues, p, rows, columns);
|
||
it('6 пунктов без relation, error первыми', () => {
|
||
expect(items).toHaveLength(6);
|
||
expect(items.slice(0, 2).map((i) => i.id)).toEqual(['i2', 'i5']);
|
||
expect(items.every((i) => i.id !== 'i6')).toBe(true);
|
||
});
|
||
it('места и цели', () => {
|
||
const by = (id: string) => items.find((i) => i.id === id);
|
||
expect(by('i4')).toMatchObject({ place: 'столбец 6 вне колонок формы', targetKey: null });
|
||
expect(by('i1')).toMatchObject({ place: 'строка 1370', targetKey: 'l-1370a' });
|
||
expect(by('i3')?.place).toBe('поле «Организация»');
|
||
expect(by('i2')?.place).toMatch(/^колонка «/);
|
||
});
|
||
it('расшифровка', () => {
|
||
const d = issue({ id: 'd', line_ids: ['l-d13'] });
|
||
const list = issueListItems([d], issuePlaces([d], rows, columns), rows, columns);
|
||
expect(list[0]).toMatchObject({ place: 'расшифровка «справочно»', targetKey: 'l-d13' });
|
||
});
|
||
it('строка без кода', () => {
|
||
const u = issue({ id: 'u', line_ids: ['l-u7'] });
|
||
const m = issue({ id: 'mm', line_ids: ['l-m8'] });
|
||
const list = issueListItems([u, m], issuePlaces([u, m], rows, columns), rows, columns);
|
||
expect(list.map((i) => i.place)).toEqual(['строка без кода «ИЧ,250»', 'строка без кода']);
|
||
});
|
||
});
|
||
|
||
describe('worstSeverity', () => {
|
||
it('уровни', () => {
|
||
expect(worstSeverity([issue({ severity: 'info' }), issue({ severity: 'error' })])).toBe('error');
|
||
expect(worstSeverity([])).toBeNull();
|
||
});
|
||
});
|
||
|
||
describe('collapseIssues (T11.11)', () => {
|
||
const items = Array.from({ length: 6 }, (_, i) => ({ id: String(i) })) as never[];
|
||
it('свёрнуто: первые 3, скрыто 3', () => {
|
||
expect(collapseIssues(items, false, 3)).toEqual({ shown: items.slice(0, 3), hidden: 3 });
|
||
});
|
||
it('развёрнуто или короткий список: всё', () => {
|
||
expect(collapseIssues(items, true, 3)).toEqual({ shown: items, hidden: 0 });
|
||
expect(collapseIssues(items.slice(0, 3), false, 3)).toEqual({ shown: items.slice(0, 3), hidden: 0 });
|
||
});
|
||
});
|