aboutsummaryrefslogtreecommitdiff
path: root/scripts/theme-studio/test-app-core.mjs
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-09 07:45:18 -0500
committerCraig Jennings <c@cjennings.net>2026-06-09 07:45:18 -0500
commit9f9475fae28cea150c260a892ab53e5c1173f191 (patch)
tree49a19e1b6637af455910de147aa6d224d4acc748 /scripts/theme-studio/test-app-core.mjs
parent05b0ce681fdb39b73cd644a9c86c767da5cf3be8 (diff)
downloaddotemacs-9f9475fae28cea150c260a892ab53e5c1173f191.tar.gz
dotemacs-9f9475fae28cea150c260a892ab53e5c1173f191.zip
test(theme-studio): extract color/slug helpers to importable modules and cover them
The pure helpers that were still stranded in app.js — normHex, ratingColor, textOn, and the filename-slug logic — had no unit tests because app.js can't be imported (it runs its bootstrap and references the data placeholders at load). Moved them into importable modules so they can be tested directly: a new app-util.js holds the color/UI-boundary trio, and slugify joins app-core.js. app.js keeps thin wrappers, so no call site changed and the built DOM is byte-identical. textOn needs rl from colormath, so generate.py's inline strip now drops import lines as well as export lines — app-util.js imports rl for its tests, and the import is stripped on inline where rl is already in the page. _faces in generate.py also gets direct tests for its prefix-strip and label derivation. New: 12 node tests (normHex, ratingColor, textOn, slugify) and 7 python tests (_faces, app-util integrity, the import strip). Coverage: app-util.js 100/100/100, app-core.js 100/94.9/100, colormath.js 100/96/100 (line/branch/func); generate.py 89% lines (the rest is the __main__ writer and the optional seed-env branch). No bugs surfaced — the logic was correct, just untested.
Diffstat (limited to 'scripts/theme-studio/test-app-core.mjs')
-rw-r--r--scripts/theme-studio/test-app-core.mjs19
1 files changed, 18 insertions, 1 deletions
diff --git a/scripts/theme-studio/test-app-core.mjs b/scripts/theme-studio/test-app-core.mjs
index 0befeb43..9bf5145f 100644
--- a/scripts/theme-studio/test-app-core.mjs
+++ b/scripts/theme-studio/test-app-core.mjs
@@ -7,7 +7,7 @@ import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import {
- nameToHex, buildPkgmap, packagesForExport, mergePackagesInto, effResolve, optList,
+ nameToHex, buildPkgmap, packagesForExport, mergePackagesInto, effResolve, optList, slugify,
} from './app-core.js';
const here = fileURLToPath(new URL('.', import.meta.url));
@@ -127,6 +127,23 @@ test('mergePackagesInto: Boundary — undefined pkgs is a no-op', () => {
assert.deepEqual(m, { a: { f: { fg: '#000000' } } });
});
+test('slugify: Normal — spaces and punctuation collapse to single dashes', () => {
+ assert.equal(slugify('My Cool Theme'), 'My-Cool-Theme');
+ assert.equal(slugify('dupre revised'), 'dupre-revised');
+ assert.equal(slugify('keeps.dots_and-dashes'), 'keeps.dots_and-dashes');
+});
+
+test('slugify: Boundary — leading/trailing junk is trimmed', () => {
+ assert.equal(slugify(' spaced '), 'spaced');
+ assert.equal(slugify('!!!edges!!!'), 'edges');
+ assert.equal(slugify(''), 'theme'); // empty falls back
+});
+
+test('slugify: Error — an all-disallowed name falls back to "theme"', () => {
+ assert.equal(slugify('!!!'), 'theme');
+ assert.equal(slugify(' '), 'theme');
+});
+
// Guards the one-source-of-truth contract, same as the colormath integrity test:
// the page must carry app-core.js's body (sans exports) verbatim. Requires
// `python3 generate.py` to have run first.