- Created new snapshot files for ISF credits and daily schedules for the 26-АРХ and 26-ПГС programs. - Added summer 2026 and winter 2024 exam schedules for the 23-ИТзс program, detailing lectures, labs, and consultations.
141 lines
5.4 KiB
JavaScript
141 lines
5.4 KiB
JavaScript
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 {
|
||
parseWeekRanges,
|
||
parseTextDates,
|
||
lessonWeeks,
|
||
lessonDates,
|
||
dateInWeek,
|
||
weekIndexOf,
|
||
todayIso,
|
||
} from "../shared/weeks.js";
|
||
const fixture = (name) =>
|
||
readFileSync(new URL(`./fixtures/${name}.docx`, import.meta.url));
|
||
const calendar = {
|
||
weeks: parseWeeksDocx(fixture("weeks")),
|
||
bells: parseBellsDocx(fixture("bells")),
|
||
};
|
||
const fef = () =>
|
||
parseDocx(fixture("fef-23-ba"), { name: "23-ЛГ_23-БА.docx" }).lessons.filter(
|
||
(l) => l.groups.includes("23-БА"),
|
||
);
|
||
|
||
test("Таблица недель: 18 недель, нечётные белые, неделя 1 со вторника", () => {
|
||
const { weeks } = calendar;
|
||
assert.equal(weeks.length, 18);
|
||
assert.deepEqual(weeks[0], {
|
||
n: 1,
|
||
start: "2026-09-01",
|
||
end: "2026-09-06",
|
||
color: "white",
|
||
});
|
||
assert.deepEqual(weeks.at(-1), {
|
||
n: 18,
|
||
start: "2026-12-28",
|
||
end: "2027-01-03",
|
||
color: "green",
|
||
});
|
||
assert.ok(weeks.every((w) => (w.n % 2 ? "white" : "green") === w.color));
|
||
assert.equal(dateInWeek(weeks[0], 1), null);
|
||
assert.equal(dateInWeek(weeks[0], 2), "2026-09-01");
|
||
assert.equal(weekIndexOf(calendar, "2026-10-16"), 6);
|
||
assert.equal(weekIndexOf(calendar, "2027-02-01"), -1);
|
||
assert.equal(todayIso(new Date("2026-10-15T22:30:00Z")), "2026-10-16");
|
||
});
|
||
test("Звонки: восемь пар с половинами", () => {
|
||
assert.equal(calendar.bells.length, 8);
|
||
assert.deepEqual(calendar.bells[1], {
|
||
pair: 2,
|
||
start: "10:05",
|
||
end: "11:30",
|
||
halves: [
|
||
["10:05", "10:45"],
|
||
["10:50", "11:30"],
|
||
],
|
||
});
|
||
});
|
||
test("Пометки недель: диапазоны, «с N», опечатки остаются для сверки", () => {
|
||
assert.deepEqual(parseWeekRanges("1-4,6-11н."), [
|
||
[1, 4],
|
||
[6, 11],
|
||
]);
|
||
assert.deepEqual(parseWeekRanges("со 2 нед."), [[2, null]]);
|
||
assert.deepEqual(parseWeekRanges("1-4н.;6-12н."), [[1, 4], [6, 12]]);
|
||
assert.deepEqual(parseWeekRanges("1-6н , 13-18н"), [[1, 6], [13, 18]]);
|
||
assert.deepEqual(parseWeekRanges("с 4-16н"), [[4, 16]]);
|
||
assert.deepEqual(parseWeekRanges("1-8,10-17"), [
|
||
[1, 8],
|
||
[10, 17],
|
||
]);
|
||
assert.equal(parseWeekRanges("2,6-12-16н"), null);
|
||
assert.equal(parseWeekRanges("26.10"), null);
|
||
assert.equal(parseWeekRanges(""), null);
|
||
});
|
||
test("Цвет строки ограничивает диапазон чётностью недели", () => {
|
||
const white = { day: 2, date: null, condition: "13-17н", variant: "upper" };
|
||
const green = { day: 4, date: null, condition: "4-12н", variant: "lower" };
|
||
const every = { day: 5, date: null, condition: "6-13н", variant: "all" };
|
||
const plain = { day: 1, date: null, condition: "", variant: "lower" };
|
||
assert.deepEqual(lessonWeeks(white, 18), [13, 15, 17]);
|
||
assert.deepEqual(lessonWeeks(green, 18), [4, 6, 8, 10, 12]);
|
||
assert.deepEqual(lessonWeeks(every, 18), [6, 7, 8, 9, 10, 11, 12, 13]);
|
||
assert.deepEqual(lessonWeeks(plain, 18), [2, 4, 6, 8, 10, 12, 14, 16, 18]);
|
||
assert.equal(
|
||
lessonWeeks({ ...white, condition: "2,6-12-16н" }, 18),
|
||
null,
|
||
);
|
||
assert.deepEqual(lessonDates(every, calendar).slice(0, 2), [
|
||
"2026-10-09",
|
||
"2026-10-16",
|
||
]);
|
||
});
|
||
test("Парсер: 23-БА получает номера недель и даты дня информирования", () => {
|
||
const lessons = fef();
|
||
const friday = lessons.filter((l) => l.day === 5 && l.start === "10:05");
|
||
assert.deepEqual(
|
||
friday.map((l) => l.weekRanges),
|
||
[[[1, 4], [6, 11]], [[12, 15]], [[16, 16]]],
|
||
);
|
||
const week7 = friday.filter((l) => lessonWeeks(l, 18).includes(7));
|
||
assert.deepEqual(
|
||
week7.map((l) => l.subject),
|
||
["PR-менеджмент"],
|
||
);
|
||
const info = lessons.find((l) =>
|
||
l.subject.startsWith("Единый день информирования"),
|
||
);
|
||
assert.deepEqual(info.dates, [
|
||
"2026-09-10",
|
||
"2026-10-15",
|
||
"2026-11-19",
|
||
"2026-12-17",
|
||
]);
|
||
assert.deepEqual(parseTextDates("17 декабря и 14 января", 2026), [
|
||
"2026-12-17",
|
||
"2027-01-14",
|
||
]);
|
||
// Every coloured-row mark in the real document agrees with the week table.
|
||
for (const l of lessons.filter((l) => l.variant !== "all" && l.weekRanges))
|
||
for (const [a, b] of l.weekRanges)
|
||
for (const n of [a, b ?? a])
|
||
assert.equal(n % 2, l.variant === "upper" ? 1 : 0, l.raw);
|
||
});
|
||
|
||
test("Даты числами: «10.09;15.10;19.11;17.12», но не время пары", () => {
|
||
// ИСФ пишет дни информирования списком дат, как в 23-АРХ.
|
||
assert.deepEqual(parseTextDates("Единый день информирования 10.09;15.10;19.11;17.12", 2026), [
|
||
"2026-09-10",
|
||
"2026-10-15",
|
||
"2026-11-19",
|
||
"2026-12-17",
|
||
]);
|
||
assert.deepEqual(parseTextDates("03.10, 17.10. Физика", 2026), ["2026-10-03", "2026-10-17"]);
|
||
assert.deepEqual(parseTextDates("12.01.2027; 19.01.2027 Экзамен", 2026), ["2027-01-12", "2027-01-19"]);
|
||
// One number pair alone or a time range is a time, not a date.
|
||
for (const time of ["10.05 Лекция", "10.05-11.30", "16.50 Информационный час", "09.11 по 06.12 практика"])
|
||
assert.deepEqual(parseTextDates(time, 2026), [], time);
|
||
});
|