152 lines
6.4 KiB
JavaScript
152 lines
6.4 KiB
JavaScript
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, /Подтвердить отсутствие конфликтов нельзя/);
|
||
});
|