const { test } = require('node:test'); const assert = require('node:assert'); const fs = require('node:fs'); const os = require('node:os'); const path = require('node:path'); const { execFileSync } = require('node:child_process'); global.PDFLib = require('pdf-lib'); const { buildStudyLoadPdf, compactProgram, deriveDateRange, formatSchedule, formatFullName } = require('../pdf.js'); const sampleData = { header: { fullName: 'ADRIAN ALFRED CHIONG BONPIN', studentId: '22103625', program: 'BACHELOR OF SCIENCE IN INFORMATION TECHNOLOGY', yearLevel: '4', semester: '1ST Semester 2026', dateEnrolled: '8/5/2024', dateRange: 'AUGUST - JANUARY' }, courses: [ { group: '7', courseCode: 'CIS 2101', description: 'DATA STRUCTURES AND ALGORITHMS', units: '3.00', teacher: 'CHRISTIAN MADERAZO', schedule: 'M,W 03:00 PM - 05:30 PM LB443TC', status: 'REGULAR' }, { group: '2', courseCode: 'IT 3103N', description: 'SYSTEMS INTEGRATION AND ARCHITECTURE', units: '3.00', teacher: 'KHENT DELA PAZ', schedule: 'T,Th 01:30 PM - 03:00 PM DCISMVR3TC', status: 'REGULAR' } ], totalUnits: '6.00' }; function extractPdfText(bytes) { const tmp = path.join(os.tmpdir(), 'study-load-test.pdf'); fs.writeFileSync(tmp, Buffer.from(bytes)); const script = [ 'import fitz', `doc = fitz.open('${tmp}')`, 'text = ""', 'for page in doc:', ' text += page.get_text()', 'print(text)' ].join('\n'); return execFileSync('python3', ['-c', script], { encoding: 'utf8' }); } test('buildStudyLoadPdf returns valid PDF bytes', async () => { const bytes = await buildStudyLoadPdf(sampleData); assert.ok(bytes instanceof Uint8Array); const head = Buffer.from(bytes.slice(0, 5)).toString('latin1'); assert.strictEqual(head, '%PDF-'); const doc = await PDFLib.PDFDocument.load(bytes); assert.strictEqual(doc.getPageCount(), 1); const text = extractPdfText(bytes); assert.ok(text.includes('CIS 2101'), 'PDF text should contain course code CIS 2101'); assert.ok(text.includes("STUDENT'S STUDY LOAD"), 'PDF text should contain the title'); assert.ok(text.includes('CHRISTIAN MADERAZO'), 'PDF text should contain the teacher'); assert.ok(text.includes('BS IT'), 'PDF text should contain the compacted program'); }); test('compactProgram shortens degree names', () => { assert.strictEqual(compactProgram('BACHELOR OF SCIENCE IN INFORMATION TECHNOLOGY'), 'BS IT'); assert.strictEqual(compactProgram('BACHELOR OF SCIENCE IN COMPUTER SCIENCE'), 'BS CS'); assert.strictEqual(compactProgram('BACHELOR OF ARTS IN POLITICAL SCIENCE'), 'AB PS'); assert.strictEqual(compactProgram('BACHELOR OF SCIENCE IN ACCOUNTANCY'), 'BS Accountancy'); assert.strictEqual(compactProgram('UNKNOWN PROGRAM'), 'UNKNOWN PROGRAM'); }); test('formatSchedule normalizes schedule text', () => { assert.strictEqual(formatSchedule('M W 07:30 AM - 10:00 AM LB447TC TC'), 'M,W 07:30 AM - 10:00 AM LB447TC'); assert.strictEqual(formatSchedule('T Th 09:00 AM - 10:30 AM LB443TC TC'), 'T,Th 09:00 AM - 10:30 AM LB443TC'); assert.strictEqual(formatSchedule('M,W 03:00 PM - 05:30 PM LB443TC'), 'M,W 03:00 PM - 05:30 PM LB443TC'); }); test('formatFullName reorders first-last names to last-first', () => { assert.strictEqual(formatFullName('ADRIAN ALFRED CHIONG BONPIN'), 'BONPIN, ADRIAN ALFRED CHIONG'); assert.strictEqual(formatFullName('BONPIN, ADRIAN ALFRED CHIONG'), 'BONPIN, ADRIAN ALFRED CHIONG'); assert.strictEqual(formatFullName('JOHN DOE'), 'DOE, JOHN'); assert.strictEqual(formatFullName(''), ''); }); test('deriveDateRange maps semesters', () => { assert.strictEqual(deriveDateRange('1ST Semester 2026'), 'AUGUST - JANUARY'); assert.strictEqual(deriveDateRange('2ND Semester 2026'), 'JANUARY - MAY'); assert.strictEqual(deriveDateRange('Summer 2026'), 'JUNE - JULY'); assert.strictEqual(deriveDateRange(''), ''); });