const { test } = require('node:test'); const assert = require('node:assert'); const { buildStudyLoadCsv, buildNextUpCsv, parseScheduleBlocks, csvField } = require('../export-csv.js'); const { buildStudyLoadJson } = require('../export-json.js'); const { buildStudyLoadXlsx } = require('../export-xlsx.js'); const data = { year: '2024', period: '1ST Semester', totalUnits: '21.00', header: { program: 'BACHELOR OF SCIENCE IN INFORMATION TECHNOLOGY', fullName: 'ADRIAN ALFRED CHIONG BONPIN', studentId: '22103625', semester: '1ST Semester 2024', yearLevel: '3' }, courses: [ { group: '1', courseCode: 'IT 3101N', description: 'PLATFORM TECHNOLOGIES', schedule: 'F 01:30 PM - 04:30 PM LB486', faculty: 'TAN', units: '3.0', status: 'REGULAR' }, { group: '1', courseCode: 'CIS 1101', description: 'PROGRAMMING I', schedule: 'T Th 03:00 PM - 04:30 PM LB468', faculty: '', units: '3.0', status: 'REGULAR' }, { group: '1', courseCode: 'CS 5105', description: 'COMP, TALKS "X"', schedule: '', faculty: '', units: '3.00', status: 'DISSOLVED' } ] }; // ---- CSV ---- test('buildStudyLoadCsv includes header block, table, and total', () => { const csv = buildStudyLoadCsv(data); assert.ok(csv.startsWith('\uFEFF'), 'has UTF-8 BOM'); assert.ok(csv.includes('Program,BACHELOR OF SCIENCE IN INFORMATION TECHNOLOGY')); assert.ok(csv.includes('Student ID,22103625')); assert.ok(csv.includes('Group,Course Code,Description,Schedule,Faculty,Units,Status')); assert.ok(csv.includes('1,IT 3101N,PLATFORM TECHNOLOGIES,F 01:30 PM - 04:30 PM LB486,TAN,3.0,REGULAR')); assert.ok(/Total,.*21\.00/.test(csv)); }); test('csvField quotes fields containing commas, quotes, newlines', () => { assert.strictEqual(csvField('plain'), 'plain'); assert.strictEqual(csvField('a,b'), '"a,b"'); assert.strictEqual(csvField('say "hi"'), '"say ""hi"""'); }); // ---- NextUp ---- test('buildNextUpCsv matches the Next Up column contract', () => { const csv = buildNextUpCsv(data).replace(/^\uFEFF/, ''); const header = csv.split('\r\n')[0]; assert.strictEqual(header, 'title,courseCode,days,startTime,endTime,room,meetingLink,color,icon,units,classLink,professorName,professorEmail,groupName'); // Schedule blocks -> one row per block, day codes and 24h times. assert.ok(csv.includes('PLATFORM TECHNOLOGIES,IT 3101N,FR,13:30,16:30,LB486')); assert.ok(csv.includes('PROGRAMMING I,CIS 1101,"TU,TH",15:00,16:30,LB468')); }); test('parseScheduleBlocks splits multi-block schedules', () => { const blocks = parseScheduleBlocks('M 08:00 AM - 09:00 AM R1; W 10:00 AM - 12:00 PM R2'); assert.ok(Array.isArray(blocks) && blocks.length >= 1); assert.strictEqual(Math.max(blocks.length, 0) > 0, true); }); // ---- JSON ---- test('buildStudyLoadJson has improved, clean schema', () => { const j = buildStudyLoadJson(data); assert.strictEqual(j.meta.program, data.header.program); assert.strictEqual(j.meta.studentName, data.header.fullName); assert.strictEqual(j.meta.academicYear, '2024'); assert.strictEqual(j.meta.yearLevel, '3'); assert.strictEqual(j.meta.totalUnits, '21.00'); assert.ok(j.meta.generatedAt && /ISO|Z|T/.test(j.meta.generatedAt)); assert.strictEqual(j.courses.length, 3); assert.strictEqual(j.courses[0].courseCode, 'IT 3101N'); assert.deepStrictEqual(j.totals, { enrolledUnits: '21.00' }); }); // ---- XLSX ---- test('buildStudyLoadXlsx returns a valid ZIP with expected parts', () => { const bytes = buildStudyLoadXlsx(data); assert.ok(bytes instanceof Uint8Array); // A valid ZIP starts with PK (0x50 0x4B). assert.strictEqual(bytes[0], 0x50); assert.strictEqual(bytes[1], 0x4b); // Contains XML as text (spot check for the sheet + shared strings). const asText = Buffer.from(bytes).toString('latin1'); assert.ok(asText.includes('Content_Types'), 'content types part present'); assert.ok(asText.includes('sharedStrings'), 'shared strings part present'); assert.ok(asText.includes('ISMIS HELPER - STUDY LOAD'), 'title present'); }); test('buildStudyLoadXlsx embeds course data as shared strings', () => { const bytes = buildStudyLoadXlsx(data); const asText = Buffer.from(bytes).toString('latin1'); assert.ok(asText.includes('PLATFORM TECHNOLOGIES')); assert.ok(asText.includes('IT 3101N')); assert.ok(asText.includes('21.00')); });