oxedyne/daimond/www/js/badge.test.mjs
4.7 KiB, 1 run
created by r2519314175:1514, which is this file's identity for as long as the history lasts, whatever it is later renamed to
download · who wrote it · its history
| 1 | /* ============================================================ |
| 2 | Test — the dock count badge is GONE (proposal #4). |
| 3 | ------------------------------------------------------------ |
| 4 | The owner decided to remove the unsolicited circled count that |
| 5 | the Social header chip and the Email chip carried. This guards |
| 6 | the removal: the count no longer renders, and the chips that |
| 7 | carried it stay. |
| 8 | |
| 9 | Why a SOURCE guard and not a rendering test: the count lived in |
| 10 | the `Badge` closure inside `www/js/daimond.js`, which is an ES |
| 11 | module that imports the compiled wasm surface |
| 12 | (`import * as Wasm from '../pkg/oxedyne_daimond.js'`). The other |
| 13 | `.test.mjs` files here load classic IIFE scripts into a |
| 14 | hand-rolled `with(window)` sandbox; a wasm-importing module |
| 15 | cannot be instantiated that way, so daimond.js cannot be driven |
| 16 | in this harness. The removal is therefore guarded where it can |
| 17 | be: the render path that created the `.dock-count` element, and |
| 18 | the CSS that styled it, are asserted absent, while the chip row |
| 19 | that opens each panel is asserted still built. |
| 20 | |
| 21 | The checks are proven able to fail: `--break` scans a copy of |
| 22 | the source with the count-rendering re-introduced, and every |
| 23 | "it is gone" check goes red under it. |
| 24 | |
| 25 | node www/js/badge.test.mjs --break readd # the count comes back |
| 26 | node www/js/badge.test.mjs # and then, clean |
| 27 | ============================================================ */ |
| 28 | import { readFileSync } from 'node:fs'; |
| 29 | import { fileURLToPath } from 'node:url'; |
| 30 | import { dirname, join } from 'node:path'; |
| 31 | |
| 32 | const HERE = dirname(fileURLToPath(import.meta.url)); |
| 33 | |
| 34 | let failures = 0, checks = 0; |
| 35 | function check(name, cond, detail) { |
| 36 | checks++; |
| 37 | if (cond) { console.log(' ok ' + name); } |
| 38 | else { console.log(' FAIL ' + name + (detail ? ' (' + detail + ')' : '')); failures++; } |
| 39 | } |
| 40 | |
| 41 | const BREAK = (() => { |
| 42 | const i = process.argv.indexOf('--break'); |
| 43 | return i >= 0 ? (process.argv[i + 1] || 'readd') : ''; |
| 44 | })(); |
| 45 | |
| 46 | function read(rel) { return readFileSync(join(HERE, rel), 'utf8'); } |
| 47 | |
| 48 | function main() { |
| 49 | let js = read('daimond.js'); |
| 50 | let css = read('../css/app.css'); |
| 51 | const post = read('post.js'); |
| 52 | const sync = read('sync.js'); |
| 53 | |
| 54 | // `--break readd`: put the count-rendering back, exactly the way it stood, |
| 55 | // so the "it is gone" checks below have something to catch. If they pass |
| 56 | // under this, they are not really checking. |
| 57 | if (BREAK === 'readd') { |
| 58 | js = js |
| 59 | + '\nvar Badge = (function(){return{set:function(){},bump:function(){},seen:function(){},paint:function(){}};})();' |
| 60 | + '\nwindow.DaimondBadge = Badge;' |
| 61 | + '\nfunction postBadge(){ Badge.set("social", 0); }' |
| 62 | + '\nfunction markCount(host,n){ var b=document.createElement("span"); b.className="dock-count"; host.appendChild(b); }' |
| 63 | + '\ndocument.querySelector("#panel-social .rail-count-host");'; |
| 64 | css = css + '\n.dock-count { display: inline-block; }\n'; |
| 65 | } |
| 66 | |
| 67 | // ── the count no longer renders ──────────────────────────── |
| 68 | console.log('(a) the circled count no longer renders'); |
| 69 | check('daimond.js creates no `.dock-count` element', |
| 70 | js.indexOf("'dock-count'") === -1 && js.indexOf('"dock-count"') === -1, |
| 71 | 'a dock-count span is still built'); |
| 72 | check('daimond.js marks no `.rail-count-host`', |
| 73 | js.indexOf('rail-count-host') === -1, |
| 74 | 'a panel head is still decorated with a count'); |
| 75 | check('daimond.js publishes no `DaimondBadge`', |
| 76 | js.indexOf('DaimondBadge') === -1, |
| 77 | 'the badge module is still exported'); |
| 78 | check('daimond.js defines no `postBadge`', |
| 79 | js.indexOf('postBadge') === -1, |
| 80 | 'the social-count recompute is still wired'); |
| 81 | check('app.css styles no `.dock-count`', |
| 82 | css.indexOf('.dock-count') === -1, |
| 83 | 'the count is still styled'); |
| 84 | |
| 85 | // ── nothing downstream still calls the badge ─────────────── |
| 86 | console.log('(b) no caller reaches for the removed badge'); |
| 87 | check('post.js does not call DaimondBadge', post.indexOf('DaimondBadge') === -1); |
| 88 | check('sync.js does not call DaimondBadge', sync.indexOf('DaimondBadge') === -1); |
| 89 | |
| 90 | // ── the chips themselves stay ────────────────────────────── |
| 91 | console.log('(c) the chips that carried the count are kept'); |
| 92 | check('the chip row #panel-tags is still rendered', js.indexOf('panel-tags') !== -1); |
| 93 | check('a chip is still built with class `ptag`', js.indexOf("'ptag ") !== -1); |
| 94 | check('the Social and Email panels are still opened', |
| 95 | js.indexOf("DaimondSocial.onOpen()") !== -1 && js.indexOf('DaimondMail.onOpen()') !== -1); |
| 96 | |
| 97 | console.log('\n' + (failures ? 'FAIL' : 'PASS') + ' — ' + (checks - failures) + '/' + checks |
| 98 | + ' checks' + (BREAK ? ' (--break ' + BREAK + ')' : '')); |
| 99 | process.exit(failures ? 1 : 0); |
| 100 | } |
| 101 | |
| 102 | main(); |