const { test } = require('node:test'); const assert = require('node:assert'); const { parseGradeHistory, yearLevelForSemester, parseProspectusYearUnits, parseLackingSubjects, parseLackingSubjectsUnits, computeYearStandingFromUnits } = require('../parsers.js'); // ---- View Grades history ---- test('parseGradeHistory extracts ordered semester terms', () => { const html = `

FIRST SEMESTER - 2022

...

SECOND SEMESTER - 2022

...

FIRST SEMESTER - 2023

...

SUMMER - 2025

...

FIRST SEMESTER - 2026

...
`; const h = parseGradeHistory(html); assert.deepStrictEqual(h, [ { semester: 'FIRST', year: 2022 }, { semester: 'SECOND', year: 2022 }, { semester: 'FIRST', year: 2023 }, { semester: 'SUMMER', year: 2025 }, { semester: 'FIRST', year: 2026 } ]); }); test('parseGradeHistory handles empty input', () => { assert.deepStrictEqual(parseGradeHistory(''), []); }); test('yearLevelForSemester returns standing from history position', () => { const history = [ { semester: 'FIRST', year: 2022 }, { semester: 'SECOND', year: 2022 }, { semester: 'FIRST', year: 2023 }, { semester: 'SECOND', year: 2023 }, { semester: 'FIRST', year: 2024 }, { semester: 'SECOND', year: 2024 }, { semester: 'FIRST', year: 2025 }, { semester: 'SECOND', year: 2025 }, { semester: 'FIRST', year: 2026 } ]; // 2022 -> Y1, 2023 -> Y2, 2024 -> Y3, 2025 -> Y4, 2026 -> Y5 assert.strictEqual(yearLevelForSemester(history, 2022), 1); assert.strictEqual(yearLevelForSemester(history, 2023), 2); assert.strictEqual(yearLevelForSemester(history, 2024), 3); assert.strictEqual(yearLevelForSemester(history, 2025), 4); assert.strictEqual(yearLevelForSemester(history, 2026), 5); // Summer of 2025 is the same standing as 2025 -> Year 4 (period is not // passed in; the standing is purely the history position). assert.strictEqual(yearLevelForSemester(history, 2025), 4); }); test('yearLevelForSemester clamps to program length and handles gaps', () => { // History ends at 2025; a query beyond it must not exceed the final level. const history = [ { semester: 'FIRST', year: 2022 }, { semester: 'SECOND', year: 2022 }, { semester: 'FIRST', year: 2023 }, { semester: 'SECOND', year: 2023 }, { semester: 'FIRST', year: 2024 }, { semester: 'SECOND', year: 2024 }, { semester: 'FIRST', year: 2025 }, { semester: 'SECOND', year: 2025 } ]; assert.strictEqual(yearLevelForSemester(history, 2028), 4); // clamped // Gap year: a skipped academic year still advances standing. const gap = [ { semester: 'FIRST', year: 2022 }, { semester: 'SECOND', year: 2022 }, { semester: 'FIRST', year: 2024 }, { semester: 'SECOND', year: 2024 } ]; assert.strictEqual(yearLevelForSemester(gap, 2024), 2); }); test('yearLevelForSemester handles missing year and empty history', () => { assert.strictEqual(yearLevelForSemester([], 2024), null); assert.strictEqual(yearLevelForSemester([{ semester: 'FIRST', year: 2022 }], NaN), null); }); // ---- Prospectus ---- test('parseProspectusYearUnits totals units per year level', () => { const html = `

Year Level: 1

Course
CIS 1101PROGRAMMING I3.0
CIS 1102INTRO3.0

Year Level: 2

Course
CIS 2101DATA STRUCTURES3.0

Year Level: 3

Course
IT 3101NPLATFORM4.0

Year Level: 4

Course
IT 4101CAPSTONE2.0
`; const y = parseProspectusYearUnits(html); assert.deepStrictEqual(y, [ { year: 1, units: 6 }, { year: 2, units: 3 }, { year: 3, units: 4 }, { year: 4, units: 2 } ]); }); // ---- Lacking subjects ---- test('parseLackingSubjects returns remaining units and courses', () => { const html = `
Course CodeDescriptionUnits
IT 3206INTEGRATIVE PROGRAMMING3.0
IT FREE ELFREE ELECTIVE3.0
IT 4202NPRACTICUM 26.0
`; const l = parseLackingSubjects(html); assert.strictEqual(l.units, '12.00'); assert.strictEqual(l.courses.length, 3); assert.strictEqual(parseLackingSubjectsUnits(html), '12.00'); }); test('parseLackingSubjects handles empty input', () => { assert.strictEqual(parseLackingSubjectsUnits(''), '0.00'); }); // ---- Units math ---- test('computeYearStandingFromUnits maps finished units to year standing', () => { // Cumulative 52/99/148/181 (matches the real BSIT prospectus). const yearUnits = [ { year: 1, units: 52 }, { year: 2, units: 47 }, { year: 3, units: 49 }, { year: 4, units: 33 } ]; // finished = 181 - 24 = 157 -> Year 4 (real user data). assert.strictEqual(computeYearStandingFromUnits(yearUnits, 24), 4); // No lacking -> finished everything -> final year. assert.strictEqual(computeYearStandingFromUnits(yearUnits, 0), 4); // finished 40 -> still Year 1 (< 52). assert.strictEqual(computeYearStandingFromUnits(yearUnits, 141), 1); // finished 60 -> Year 2 (52 <= 60 < 99). assert.strictEqual(computeYearStandingFromUnits(yearUnits, 121), 2); // exact boundary: finished 52 -> Year 2. assert.strictEqual(computeYearStandingFromUnits(yearUnits, 129), 2); // finished 99 -> Year 3. assert.strictEqual(computeYearStandingFromUnits(yearUnits, 82), 3); }); test('computeYearStandingFromUnits handles empty and negative', () => { assert.strictEqual(computeYearStandingFromUnits([], 5), null); // lacking > total -> clamps to first year. assert.strictEqual(computeYearStandingFromUnits([{ year: 1, units: 10 }], 99), 1); });