119 lines
3.7 KiB
TypeScript
119 lines
3.7 KiB
TypeScript
import { describe, it, expect, beforeAll } from "vitest";
|
|
import fs from "fs";
|
|
import ExcelJS from "exceljs";
|
|
import {
|
|
getThemeColors,
|
|
getUpcomingSheets,
|
|
groupSheetsByDate,
|
|
extractDaySchedule,
|
|
} from "../scrape/parse/v3.js";
|
|
|
|
const XLSX_PATH = "tests/content/1.xlsx";
|
|
const TEACHERMAP_PATH = "tests/content/teachermap.json";
|
|
|
|
let workbook: ExcelJS.Workbook;
|
|
let teachermap: Record<string, string>;
|
|
|
|
beforeAll(async () => {
|
|
workbook = new ExcelJS.Workbook();
|
|
await workbook.xlsx.readFile(XLSX_PATH);
|
|
teachermap = JSON.parse(fs.readFileSync(TEACHERMAP_PATH, "utf8"));
|
|
});
|
|
|
|
describe("sheet filtering", () => {
|
|
it("includes sheets on or after the injected date", () => {
|
|
const injected = new Date(2026, 5, 2); // June 2, 2026
|
|
const sheets = getUpcomingSheets(workbook, injected);
|
|
|
|
expect(sheets.length).toBeGreaterThanOrEqual(1);
|
|
expect(sheets.map((s) => s.dateKey)).toContain("2026-06-02");
|
|
});
|
|
|
|
it("excludes sheets before the injected date", () => {
|
|
const injected = new Date(2026, 5, 2);
|
|
const sheets = getUpcomingSheets(workbook, injected);
|
|
|
|
for (const s of sheets) {
|
|
const [y, m, d] = s.dateKey.split("-").map(Number);
|
|
expect(new Date(y, m - 1, d).getTime()).toBeGreaterThanOrEqual(
|
|
injected.getTime(),
|
|
);
|
|
}
|
|
});
|
|
});
|
|
|
|
describe("full day parsing", () => {
|
|
let result: ReturnType<typeof extractDaySchedule>;
|
|
let sheet: ExcelJS.Worksheet;
|
|
let themeColors: Awaited<ReturnType<typeof getThemeColors>>;
|
|
|
|
beforeAll(async () => {
|
|
const injected = new Date(2026, 5, 2);
|
|
const upcoming = getUpcomingSheets(workbook, injected);
|
|
const resolved = groupSheetsByDate(upcoming);
|
|
const day = resolved.find((d) => d.dateKey === "2026-06-02")!;
|
|
sheet = day.sheet;
|
|
themeColors = await getThemeColors(XLSX_PATH);
|
|
result = extractDaySchedule(sheet, teachermap, themeColors, []);
|
|
});
|
|
|
|
describe("changes", () => {
|
|
it("is a non-empty record of class → lessons", () => {
|
|
const keys = Object.keys(result.changes);
|
|
expect(keys.length).toBeGreaterThan(0);
|
|
|
|
for (const [cls, lessons] of Object.entries(result.changes)) {
|
|
expect(cls).toMatch(/^[AEC][0-4][a-c]?$/);
|
|
expect(lessons).toHaveLength(10);
|
|
for (const lesson of lessons) {
|
|
if (lesson === null) continue;
|
|
expect(lesson).toHaveProperty("text");
|
|
expect(typeof lesson.text).toBe("string");
|
|
expect(lesson).toHaveProperty("backgroundColor");
|
|
}
|
|
}
|
|
});
|
|
|
|
it("includes A1a with known lesson at hour 5", () => {
|
|
const a1a = result.changes["A1a"];
|
|
expect(a1a).toBeDefined();
|
|
const hour5 = a1a[4];
|
|
expect(hour5).not.toBeNull();
|
|
expect(hour5!.text).toContain("ZE");
|
|
});
|
|
});
|
|
|
|
describe("absence", () => {
|
|
it("is an array of parsed absence entries", () => {
|
|
expect(Array.isArray(result.absence)).toBe(true);
|
|
expect(result.absence.length).toBeGreaterThan(0);
|
|
|
|
for (const entry of result.absence) {
|
|
expect(entry).toHaveProperty("teacher");
|
|
expect(entry).toHaveProperty("teacherCode");
|
|
expect(entry).toHaveProperty("type");
|
|
expect(entry).toHaveProperty("hours");
|
|
}
|
|
});
|
|
|
|
it("contains a known absence entry", () => {
|
|
const su = result.absence.find((a: any) => a.teacherCode === "su");
|
|
expect(su).toBeDefined();
|
|
expect(su!.teacher).toContain("Studénková");
|
|
});
|
|
});
|
|
|
|
describe("takesPlace", () => {
|
|
it("is a non-empty string", () => {
|
|
expect(typeof result.takesPlace).toBe("string");
|
|
expect(result.takesPlace.length).toBeGreaterThan(0);
|
|
});
|
|
});
|
|
|
|
describe("reservedRooms", () => {
|
|
it("is an array of 10 entries", () => {
|
|
expect(result.reservedRooms).toHaveLength(10);
|
|
});
|
|
});
|
|
});
|