refactor(tapops): modularize page code

This commit is contained in:
Dodo
2026-06-04 18:13:23 +07:00
parent 529693cd5f
commit 1270ce60fd
41 changed files with 4678 additions and 4476 deletions
@@ -0,0 +1,37 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import { DateRangeCalculator } from '../js/utils/date-range-calculator.js';
import { PaginationModel } from '../js/models/pagination-model.js';
test('calculates date presets using an injected current day', () => {
const today = new Date('2026-06-04T12:00:00+07:00');
const last7 = DateRangeCalculator.calculatePreset('last7', today);
assert.equal(DateRangeCalculator.toDateKey(last7.start), '2026-05-29');
assert.equal(DateRangeCalculator.toDateKey(last7.end), '2026-06-04');
const thisMonth = DateRangeCalculator.calculatePreset('thisMonth', today);
assert.equal(DateRangeCalculator.toDateKey(thisMonth.start), '2026-06-01');
assert.equal(DateRangeCalculator.toDateKey(thisMonth.end), '2026-06-04');
const all = DateRangeCalculator.calculatePreset('all', today);
assert.equal(all.start, null);
assert.equal(all.end, null);
});
test('formats and parses dd/mm/yyyy date input safely', () => {
const date = new Date(2026, 5, 4);
assert.equal(DateRangeCalculator.formatDisplay(date), '04/06/2026');
assert.equal(DateRangeCalculator.toDateKey(date), '2026-06-04');
assert.equal(DateRangeCalculator.parseDisplayDate('04/06/2026')?.getFullYear(), 2026);
assert.equal(DateRangeCalculator.parseDisplayDate('31/02/2026'), null);
assert.equal(DateRangeCalculator.parseDisplayDate('04/06/10000'), null);
});
test('creates stable compact pagination ranges', () => {
assert.deepEqual(PaginationModel.range(1, 4), [1, 2, 3, 4]);
assert.deepEqual(PaginationModel.range(1, 10), [1, 2, '...', 10]);
assert.deepEqual(PaginationModel.range(5, 10), [1, '...', 4, 5, 6, '...', 10]);
assert.deepEqual(PaginationModel.range(10, 10), [1, '...', 9, 10]);
});
@@ -0,0 +1,31 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import { DocumentFormatter } from '../js/utils/document-formatter.js';
test('parses comma-separated and JSON string tags', () => {
assert.deepEqual(DocumentFormatter.parseTags('akademik, panduan, 2026'), [
'akademik',
'panduan',
'2026',
]);
assert.deepEqual(DocumentFormatter.parseTags('["kerja praktik","kp"]'), [
'kerja praktik',
'kp',
]);
});
test('maps parsed tags to fixed repository categories', () => {
assert.equal(DocumentFormatter.categoryFromTags(['TA']), 'skripsi');
assert.equal(DocumentFormatter.categoryFromTags(['Kalender']), 'akademik');
assert.equal(DocumentFormatter.categoryFromTags(['kp']), 'praktik');
assert.equal(DocumentFormatter.categoryFromTags(['surat']), 'umum');
assert.equal(DocumentFormatter.categoryFromTags([]), 'umum');
});
test('derives file type and safe download filename from document name', () => {
assert.equal(DocumentFormatter.fileTypeFromName('Panduan Akademik.pdf'), 'pdf');
assert.equal(DocumentFormatter.fileTypeFromName('Form KP.DOCX'), 'docx');
assert.equal(DocumentFormatter.downloadFilename('Form KP', 'docx'), 'Form KP.docx');
assert.equal(DocumentFormatter.downloadFilename('Kalender.pdf', 'pdf'), 'Kalender.pdf');
});
@@ -0,0 +1,17 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
const indexHtml = readFileSync(new URL('../index.html', import.meta.url), 'utf8');
const viewerHtml = readFileSync(new URL('../viewer.html', import.meta.url), 'utf8');
test('Tapops index uses module scripts and no inline behavior', () => {
assert.match(indexHtml, /<script type="module" src="js\/app\.js"><\/script>/);
assert.doesNotMatch(indexHtml, /<script>\s*\(/);
assert.doesNotMatch(indexHtml, /\sonclick=/);
});
test('Tapops viewer uses module scripts and no inline behavior', () => {
assert.match(viewerHtml, /<script type="module" src="js\/viewer\/viewer-app\.js"><\/script>/);
assert.doesNotMatch(viewerHtml, /<script>\s*\(/);
});