feat: restore direct PDF download via background; drop printdoc

This commit is contained in:
adrianbonpin
2026-08-18 19:38:26 +08:00
parent 8bcfee341c
commit 1537881ebc
9 changed files with 304 additions and 197 deletions
+52
View File
@@ -0,0 +1,52 @@
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 } = 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');
});
-60
View File
@@ -1,60 +0,0 @@
const { test } = require('node:test');
const assert = require('node:assert');
const { buildStudyLoadHtml } = require('../printdoc.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'
};
test('buildStudyLoadHtml uses Letter page size', () => {
const html = buildStudyLoadHtml(sampleData);
assert.match(html, /@page\s*\{[^}]*size:\s*8\.5in\s*11in/i);
});
test('buildStudyLoadHtml includes title, student info, and table headers', () => {
const html = buildStudyLoadHtml(sampleData);
assert.ok(html.includes("STUDENT'S STUDY LOAD"));
assert.ok(html.includes('ADRIAN ALFRED CHIONG BONPIN'));
assert.ok(html.includes('22103625'));
assert.ok(html.includes('Year Level: 4'));
for (const h of ['GROUP', 'COURSE', 'COURSE DESCRIPTION', 'TEACHER', 'UNITS', 'NOTE']) {
assert.ok(html.includes(h), 'missing header: ' + h);
}
});
test('buildStudyLoadHtml includes course data, schedule, and total', () => {
const html = buildStudyLoadHtml(sampleData);
assert.ok(html.includes('CIS 2101'));
assert.ok(html.includes('DATA STRUCTURES AND ALGORITHMS'));
assert.ok(html.includes('M,W 03:00 PM - 05:30 PM LB443TC'));
assert.ok(html.includes('6.00'));
});
test('buildStudyLoadHtml escapes user content', () => {
const html = buildStudyLoadHtml({
header: { fullName: '<script>alert(1)</script>' },
courses: [{ group: '', courseCode: 'A&B', description: 'x"y', units: '1', teacher: '', schedule: '', status: 'R' }],
totalUnits: '1.00'
});
assert.ok(!html.includes('<script>alert(1)</script>'), 'script must be escaped');
assert.ok(html.includes('&lt;script&gt;'), 'script must appear escaped');
assert.ok(html.includes('A&amp;B'), 'ampersand must be escaped');
});
test('buildStudyLoadHtml auto-prints on load', () => {
const html = buildStudyLoadHtml(sampleData);
assert.ok(/window\.print\(\)/.test(html), 'must call window.print()');
});