Files
magistr/frontend/tests/dashboard-conflicts.test.mjs
2026-07-17 01:27:02 +03:00

152 lines
6.4 KiB
JavaScript
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 test from 'node:test';
import assert from 'node:assert/strict';
import {
CONFLICT_CHECK_REASON,
CONFLICT_CHECK_STATE,
conflictCheckPresentation,
currentWeekDateRange,
formatLocalDate,
loadDepartmentSchedules
} from '../admin/js/dashboard-conflicts.js';
process.env.TZ = 'Europe/Moscow';
test('неделя для 2026-07-02 охватывает 2026-06-29…2026-07-05', () => {
assert.deepEqual(
currentWeekDateRange(new Date('2026-07-01T21:15:00Z')),
{ startDate: '2026-06-29', endDate: '2026-07-05' }
);
});
test('неделя корректно пересекает границу года', () => {
assert.deepEqual(
currentWeekDateRange(new Date(2026, 0, 1, 8, 30, 0)),
{ startDate: '2025-12-29', endDate: '2026-01-04' }
);
});
test('date-only формируется из локальных компонентов', () => {
assert.equal(formatLocalDate(new Date('2026-01-01T21:15:00Z')), '2026-01-02');
});
test('полный успех разрешает достоверный вывод по всем кафедрам', async () => {
const result = await loadDepartmentSchedules(
[{ id: 1 }, { id: 2 }],
async department => [{ departmentId: department.id }]
);
assert.equal(result.state, CONFLICT_CHECK_STATE.COMPLETE);
assert.equal(result.checkedDepartmentCount, 2);
assert.equal(result.totalDepartmentCount, 2);
assert.deepEqual(result.lessons, [{ departmentId: 1 }, { departmentId: 2 }]);
assert.deepEqual(result.failedDepartments, []);
});
test('единичный отказ даёт частичный результат, а не пустой успешный ответ', async () => {
const departments = [
{ id: 1, departmentName: 'Физика' },
{ id: 2, departmentName: 'Математика' }
];
const result = await loadDepartmentSchedules(departments, async department => {
if (department.id === 2) {
throw new Error('тестовая техническая причина');
}
return [{ departmentId: department.id }];
});
assert.equal(result.state, CONFLICT_CHECK_STATE.PARTIAL);
assert.equal(result.checkedDepartmentCount, 1);
assert.deepEqual(result.lessons, [{ departmentId: 1 }]);
assert.deepEqual(result.failedDepartments, [{ id: 2, name: 'Математика' }]);
assert.equal('reason' in result.failedDepartments[0], false);
});
test('отказ всех запросов означает, что проверка не выполнена', async () => {
const result = await loadDepartmentSchedules(
[{ id: 1 }, { id: 2 }],
async () => { throw new Error('тестовый отказ'); }
);
assert.equal(result.state, CONFLICT_CHECK_STATE.NOT_RUN);
assert.equal(result.reason, CONFLICT_CHECK_REASON.ALL_REQUESTS_FAILED);
assert.equal(result.checkedDepartmentCount, 0);
assert.deepEqual(result.lessons, []);
});
test('отсутствие кафедр не изображается как зелёная успешная проверка', async () => {
const result = await loadDepartmentSchedules([], async () => []);
assert.equal(result.state, CONFLICT_CHECK_STATE.NOT_RUN);
assert.equal(result.reason, CONFLICT_CHECK_REASON.NO_DEPARTMENTS);
});
test('зелёная карточка разрешена только для полной проверки без конфликтов', () => {
const complete = {
state: CONFLICT_CHECK_STATE.COMPLETE,
checkedDepartmentCount: 2,
totalDepartmentCount: 2
};
const range = { startDate: '2026-06-29', endDate: '2026-07-05' };
assert.equal(conflictCheckPresentation(complete, 0, range).tone, 'success');
assert.equal(conflictCheckPresentation(complete, 1, range), null);
});
test('некорректный контракт результата не может породить зелёный статус', () => {
const range = { startDate: '2026-06-29', endDate: '2026-07-05' };
assert.throws(
() => conflictCheckPresentation({
state: CONFLICT_CHECK_STATE.COMPLETE,
checkedDepartmentCount: 1,
totalDepartmentCount: 2
}, 0, range),
/Полная проверка должна охватывать все кафедры/
);
assert.throws(
() => conflictCheckPresentation({
state: CONFLICT_CHECK_STATE.COMPLETE,
checkedDepartmentCount: 2,
totalDepartmentCount: 2
}, Number.NaN, range),
/Количество конфликтов должно быть целым неотрицательным числом/
);
});
test('частичная проверка без конфликтов остаётся предупреждением', () => {
const presentation = conflictCheckPresentation({
state: CONFLICT_CHECK_STATE.PARTIAL,
checkedDepartmentCount: 1,
totalDepartmentCount: 2
}, 0, { startDate: '2026-06-29', endDate: '2026-07-05' });
assert.equal(presentation.tone, 'warning');
assert.equal(presentation.title, 'Проверка выполнена частично');
assert.match(presentation.description, /во всём расписании нельзя/);
});
test('частичная проверка с конфликтами предупреждает о неполноте результата', () => {
const presentation = conflictCheckPresentation({
state: CONFLICT_CHECK_STATE.PARTIAL,
checkedDepartmentCount: 1,
totalDepartmentCount: 3
}, 2, { startDate: '2026-06-29', endDate: '2026-07-05' });
assert.equal(presentation.tone, 'warning');
assert.match(presentation.description, /Показаны найденные конфликты/);
});
test('полный отказ формирует явное состояние «Проверка не выполнена»', () => {
const presentation = conflictCheckPresentation({
state: CONFLICT_CHECK_STATE.NOT_RUN,
reason: CONFLICT_CHECK_REASON.ALL_REQUESTS_FAILED,
checkedDepartmentCount: 0,
totalDepartmentCount: 2
}, 0, { startDate: '2026-06-29', endDate: '2026-07-05' });
assert.equal(presentation.tone, 'error');
assert.equal(presentation.title, 'Проверка не выполнена');
assert.match(presentation.description, /Подтвердить отсутствие конфликтов нельзя/);
});