Тесты и анимация кнопок (#4)
Tests / frontend-test (push) Successful in 1m9s

Co-authored-by: gorbenko.pavel <gorbenko.pavel@tansu.kz>
Reviewed-on: http://git.tnsu.kz/timur.gorodetskiy/request-portal/pulls/4
This commit was merged in pull request #4.
This commit is contained in:
2026-08-07 11:53:48 +00:00
parent 3a15d83ded
commit f6f4872a7c
9 changed files with 905 additions and 13 deletions
@@ -0,0 +1,105 @@
import { IMyRequest } from './models/IMyRequest';
import { IPage, pageKey, pageSignature, readPage, writePage } from './pageCache';
function request(over: Partial<IMyRequest> = {}): IMyRequest {
return {
id: 1,
title: 'Заявка №1',
status: 'Черновик',
authorEmail: 'ivanov@tnsu.kz',
authorName: 'Иванов Иван',
created: '2026-08-07T10:00:00Z',
requestTypeId: 1,
requestTypeName: 'Приём на работу',
section: 'Кадры',
formKey: 'hire',
kind: 'own',
...over,
};
}
function page(over: Partial<IPage> = {}): IPage {
return { rows: [request()], totalRows: 1, ...over };
}
describe('pageKey', () => {
it('склеивает раздел и части ключа через разделитель', () => {
expect(pageKey('own', [1, 'Черновик'])).toBe('own|1|Черновик');
});
it('раздел всегда первый — ключи разных таблиц не пересекаются', () => {
expect(pageKey('own', [1])).not.toBe(pageKey('approvals', [1]));
});
it('разные части дают разные ключи', () => {
expect(pageKey('own', [1])).not.toBe(pageKey('own', [2]));
});
it('раздел без частей — просто раздел', () => {
expect(pageKey('search', [])).toBe('search');
});
});
describe('readPage / writePage', () => {
it('записанная страница читается по тому же ключу', () => {
const key = pageKey('own', ['read-write']);
const stored = page();
writePage(key, stored);
expect(readPage(key)).toBe(stored);
});
it('по незнакомому ключу возвращается undefined', () => {
expect(readPage(pageKey('own', ['nothing-here']))).toBeUndefined();
});
it('повторная запись по тому же ключу перезаписывает страницу', () => {
const key = pageKey('own', ['overwrite']);
writePage(key, page({ totalRows: 1 }));
writePage(key, page({ totalRows: 2 }));
expect(readPage(key)?.totalRows).toBe(2);
});
it('кеш переживает «размонтирование» — хранилище на уровне модуля, а не компонента', () => {
const key = pageKey('approvals', ['module-level']);
writePage(key, page({ totalRows: 7 }));
// Между записью и чтением компонент таблицы мог быть уничтожен целиком —
// на модульное хранилище это не влияет (ради этого оно и вынесено из useRef).
expect(readPage(key)?.totalRows).toBe(7);
});
});
describe('pageSignature', () => {
it('одинаковое содержимое даёт одинаковую подпись (перерисовывать нечего)', () => {
expect(pageSignature(page())).toBe(pageSignature(page()));
});
it('изменение общего числа строк меняет подпись', () => {
expect(pageSignature(page({ totalRows: 1 }))).not.toBe(pageSignature(page({ totalRows: 2 })));
});
it('изменение статуса заявки меняет подпись', () => {
const before = page({ rows: [request({ status: 'Черновик' })] });
const after = page({ rows: [request({ status: 'На согласовании' })] });
expect(pageSignature(before)).not.toBe(pageSignature(after));
});
it('изменение порядка строк меняет подпись', () => {
const a = request({ id: 1 });
const b = request({ id: 2 });
expect(pageSignature(page({ rows: [a, b], totalRows: 2 }))).not.toBe(
pageSignature(page({ rows: [b, a], totalRows: 2 }))
);
});
it('поля, которых нет в таблице, на подпись не влияют', () => {
// kind/section/formKey в колонках не показываются — их изменение не должно
// приводить к перерисовке (иначе таблица моргала бы на каждом фоновом обновлении).
const before = page({ rows: [request({ section: 'Кадры', kind: 'own' })] });
const after = page({ rows: [request({ section: 'ИТ', kind: 'approval' })] });
expect(pageSignature(before)).toBe(pageSignature(after));
});
it('пустая страница имеет стабильную подпись', () => {
expect(pageSignature({ rows: [], totalRows: 0 })).toBe(pageSignature({ rows: [], totalRows: 0 }));
});
});