import test from "node:test"; import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import { parseDocx } from "../server/parser.js"; import { parseWeeksDocx, parseBellsDocx } from "../server/calendar.js"; import { mergeWeekTables } from "../server/source.js"; import { timetable } from "../server/timetable.js"; const fixture = (name) => readFileSync(new URL(`./fixtures/${name}.docx`, import.meta.url)); const calendar = { ...mergeWeekTables([parseWeeksDocx(fixture("weeks"))]), bells: parseBellsDocx(fixture("bells")), source: {}, }; const schedule = parseDocx(fixture("fef-23-ba"), { name: "23-ЛГ_23-БА.docx" }); const file = { id: "fef", name: "23-ЛГ_23-БА.docx", faculty: "ФЭФ", course: "4 курс" }; test("Расписание группы по датам: недели, пары, подгруппы, пустые выходные", () => { const t = timetable({ file, schedule, calendar, group: "23-БА", from: "2026-10-16", days: 3 }); assert.equal(t.semester.label, "Осенний семестр 2026/27"); assert.deepEqual(t.days.map((d) => [d.date, d.weekday, d.week.n, d.week.color]), [ ["2026-10-16", 5, 7, "white"], ["2026-10-17", 6, 7, "white"], ["2026-10-18", 7, 7, "white"], ]); // Friday of week 7: "12-15н." and "16н." lessons are not on this date. assert.deepEqual( t.days[0].lessons.map((l) => [l.start, l.pair, l.subject]), [ ["08:30", 1, "Инновационный менеджмент"], ["10:05", 2, "PR-менеджмент"], ["11:45", 3, "Бизнес-анализ"], ], ); assert.equal(t.days[1].lessons.length, 0); assert.ok(t.weekly.length >= 5, "строки Word по дням недели доступны всегда"); const lg = timetable({ file, schedule, calendar, group: "23-ЛГ", from: "2026-10-12", days: 7 }); assert.deepEqual(lg.subgroups, ["Подгруппа 1", "Подгруппа 2"]); assert.ok(lg.days.flatMap((d) => d.lessons).some((l) => l.subgroup === "Подгруппа 2")); }); test("Без семестра в таблице недель даты не угадываются", () => { const spring = { ...schedule, period: "Весенний семестр" }; const t = timetable({ file, schedule: spring, calendar, group: "23-БА", from: "2027-03-01", days: 7 }); assert.equal(t.semester, null); assert.ok(t.note); assert.ok(t.days.every((d) => d.lessons.length === 0 && d.week === null)); assert.throws( () => timetable({ file, schedule, calendar, group: "99-ХХ", from: "2026-10-16", days: 1 }), /нет группы/, ); }); test("range=semester: все дни текущего семестра от первого до последнего", () => { const t = timetable({ file, schedule, calendar, group: "23-БА", from: "2026-10-16", range: "semester", today: "2026-10-16" }); assert.equal(t.days[0].date, t.semester.start); assert.equal(t.days.at(-1).date, t.semester.end); assert.ok(t.days.length > 62, "больше обычного предела в 62 дня"); }); test("Сессия с датами в Word не зависит от таблицы недель", () => { // June 2026 lies outside the 2026/27 week table, yet every lesson has its own date. const session = parseDocx(fixture("itzs-summer-2026"), { name: "23-ИТзс.docx" }); const t = timetable({ file: { id: "itzs", name: "23-ИТзс.docx" }, schedule: session, calendar, group: "23-ИТзс", from: "2026-10-19", range: "semester", today: "2026-10-19", }); assert.deepEqual(t.semester, { id: "session-2026-06-08", label: "Лабораторно-экзаменационная сессия", start: "2026-06-08", end: "2026-06-27", }); assert.equal(t.note, null); assert.equal(t.days.length, 20); assert.equal(t.days.reduce((n, d) => n + d.lessons.length, 0), 58); const exam = t.days.find((d) => d.date === "2026-06-18").lessons.find((l) => l.type === "Экзамен"); assert.deepEqual([exam.start, exam.end, exam.pair], ["08:30", "09:55", 1]); });