aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-07-18 16:33:31 -0500
committerCraig Jennings <c@cjennings.net>2026-07-18 16:33:31 -0500
commit05398f5a02f2008c23c05cfe80c6dd4fcd183860 (patch)
tree06f78f2f559e036c7b7632d455164291efd994a6 /tests
parent99d32abc85c4e953d5d911bf26df678afbffb6ff (diff)
downloadarchsetup-05398f5a02f2008c23c05cfe80c6dd4fcd183860.tar.gz
archsetup-05398f5a02f2008c23c05cfe80c6dd4fcd183860.zip
feat(gallery): bring the decade-through-EQ ten to the extraction bar
decadeBox, twoHandSafety, voiceLoop, miniSig, fuelBar, radialRing, sparkline, waveStrip, scope, and eqBars each get the contract comment. The eight DOM builders take dupre- prefixes across their markup and CSS blocks. voiceLoop's inner bar becomes dupre-vk-bar to stay clear of fuelBar's dupre-bar, and miniSig and eqBars move their cell modifiers to the shared dupre-on, dupre-hot, and dupre-clip. Domain gates land where a handle could wedge: decadeBox coerces and clamps its digits, twoHandSafety ignores sides other than L and R, voiceLoop keeps the demo state to the stock loop set (a caller's shorter list used to crash on it), the meters clamp set() to their documented ranges, and sparkline and scope guard the one-sample case that drew NaN coordinates. Two probe checks cover the gates and drive voiceLoop's grammar through the prefixed DOM. probe-fams follows scope's rename. Extraction audit: 74/111 contract comments.
Diffstat (limited to 'tests')
-rw-r--r--tests/gallery-probes/probe-fams.mjs6
-rw-r--r--tests/gallery-probes/probe.mjs65
2 files changed, 68 insertions, 3 deletions
diff --git a/tests/gallery-probes/probe-fams.mjs b/tests/gallery-probes/probe-fams.mjs
index c1b5f9d..a2333fb 100644
--- a/tests/gallery-probes/probe-fams.mjs
+++ b/tests/gallery-probes/probe-fams.mjs
@@ -43,9 +43,9 @@ try {
ok('R31 green chip recolors furniture', line0 !== line1 && line1 === 'rgb(88, 184, 126)', `${line0} -> ${line1}`);
// scope (CSS instrument): trace stroke changes on amber chip
- const tr0 = await evl(`getComputedStyle(document.querySelector('.scope polyline')).stroke`);
- await evl(`document.querySelector('.scope').closest('.card').querySelector('.fc[title="amber"]').click()`);
- const tr1 = await evl(`getComputedStyle(document.querySelector('.scope polyline')).stroke`);
+ const tr0 = await evl(`getComputedStyle(document.querySelector('.dupre-scope polyline')).stroke`);
+ await evl(`document.querySelector('.dupre-scope').closest('.card').querySelector('.fc[title="amber"]').click()`);
+ const tr1 = await evl(`getComputedStyle(document.querySelector('.dupre-scope polyline')).stroke`);
ok('N11 amber chip recolors trace', tr0 !== tr1 && tr1 === 'rgb(255, 190, 84)', `${tr0} -> ${tr1}`);
// R19: drag still works after family switch (click vfd, then check the handle's set() writes var-based fills)
diff --git a/tests/gallery-probes/probe.mjs b/tests/gallery-probes/probe.mjs
index 16bff17..02b1062 100644
--- a/tests/gallery-probes/probe.mjs
+++ b/tests/gallery-probes/probe.mjs
@@ -1275,6 +1275,71 @@ try {
ok('dsky grammar drives prefixed DOM: hot window, V16 N36 sets PROG, V35 lights all lamps',
b6dom === JSON.stringify({ hot1: 1, prog: '16', hot0: 0, lit: 6 }), b6dom);
+ // batch-7 domain gates on detached hosts: decadeBox coerces and clamps its
+ // digits, twoHandSafety ignores sides outside L/R, the meters clamp their
+ // set()/push() domains, sparkline floors its history at two points, scope
+ // clears the trace below two samples, eqBars reads missing bands as 0.
+ const clamps7 = await evl(`(() => {
+ const db = DUPRE.decadeBox(document.createElement('div'), { digits: [12, -3, undefined, 7] });
+ const dbTot = db.get();
+ const thsLog = [];
+ const ths = DUPRE.twoHandSafety(document.createElement('div'), { onChange: st => thsLog.push(st) });
+ ths.press('X'); ths.press('L'); ths.press('R');
+ const ms = DUPRE.miniSig(document.createElement('div'));
+ ms.set(2); const msHi = ms.get(); ms.set(-1); const msLo = ms.get();
+ const fb = DUPRE.fuelBar(document.createElement('div'));
+ fb.set(150); const fbHi = fb.get();
+ const rr = DUPRE.radialRing(document.createElement('div'));
+ rr.set(150); const rrHi = rr.get();
+ const sp = DUPRE.sparkline(document.createElement('div'), { samples: 1 });
+ sp.push(5); const spHi = sp.get();
+ const spPts = sp.el.querySelector('polyline').getAttribute('points');
+ const ws = DUPRE.waveStrip(document.createElement('div'));
+ ws.set([0, 5, -5], 0.5);
+ const wsD = ws.el.querySelector('path').getAttribute('d');
+ const sc = DUPRE.scope(document.createElement('div'));
+ sc.set([0.5], 1);
+ const scEmpty = sc.el.querySelector('polyline').getAttribute('points');
+ sc.set([5, -5], 1);
+ const scPts = sc.el.querySelector('polyline').getAttribute('points');
+ let eqTxt; const eq = DUPRE.eqBars(document.createElement('div'), { bands: 3, cells: 4, onChange: (v, t) => eqTxt = t });
+ eq.set([2, -1]);
+ const eqB0 = eq.el.children[0].querySelectorAll('.dupre-on,.dupre-hot,.dupre-clip').length;
+ const eqRest = eq.el.children[1].querySelectorAll('.dupre-on,.dupre-hot,.dupre-clip').length
+ + eq.el.children[2].querySelectorAll('.dupre-on,.dupre-hot,.dupre-clip').length;
+ return JSON.stringify({ dbTot, ths: thsLog.join('|'), msHi, msLo, fbHi, rrHi, spHi,
+ spOk: !spPts.includes('NaN'), wsOk: !wsD.includes('NaN') && wsD.includes(' 33.0') && wsD.includes(' 5.0'),
+ scEmpty, scPts, eqTxt, eqB0, eqRest });
+ })()`);
+ ok('batch-7 domain gates: decadeBox digits, twoHandSafety side, meter clamps, trace guards',
+ clamps7 === JSON.stringify({ dbTot: 9007, ths: 'ready|armed|running', msHi: 1, msLo: 0, fbHi: 100,
+ rrHi: 100, spHi: 1, spOk: true, wsOk: true, scEmpty: '', scPts: '0.0,61.0 176.0,17.0',
+ eqTxt: 'peak 100%', eqB0: 4, eqRest: 0 }), clamps7);
+
+ // voiceLoop grammar through the prefixed DOM (catches rename stragglers):
+ // the default set opens FD/GNC/A-G engaged with GNC talking, click cycles
+ // idle → monitored → talking → idle with talk exclusive, and a caller's own
+ // loop set starts all-idle (the demo default is the stock set's alone).
+ const b7dom = await evl(`(() => {
+ const vl = DUPRE.voiceLoop(document.createElement('div'));
+ const ks = vl.el.querySelectorAll('.dupre-vk');
+ const nKeys = ks.length;
+ const mon0 = vl.el.querySelectorAll('.dupre-mon').length;
+ const tlk0 = vl.el.querySelectorAll('.dupre-tlk').length;
+ ks[2].click();
+ const mon1 = vl.el.querySelectorAll('.dupre-mon').length;
+ ks[0].click();
+ const tlk1 = vl.el.querySelectorAll('.dupre-tlk').length;
+ const fdTalks = ks[0].classList.contains('dupre-tlk') && !ks[1].classList.contains('dupre-tlk');
+ ks[0].click();
+ const fdIdle = vl.get()[0] === '0' && !ks[0].classList.contains('dupre-mon');
+ const own = DUPRE.voiceLoop(document.createElement('div'), { loops: ['A', 'B', 'C'] });
+ const ownIdle = own.get().join('') === '000' && own.el.querySelectorAll('.dupre-mon,.dupre-tlk').length === 0;
+ return JSON.stringify({ nKeys, mon0, tlk0, mon1, tlk1, fdTalks, fdIdle, ownIdle });
+ })()`);
+ ok('voiceLoop cycles through prefixed DOM: demo default, exclusive talk, own set idle',
+ b7dom === JSON.stringify({ nKeys: 8, mon0: 3, tlk0: 1, mon1: 4, tlk1: 1, fdTalks: true, fdIdle: true, ownIdle: true }), b7dom);
+
// late exceptions from interactions
const errs2 = events.filter(e => e.method === 'Runtime.exceptionThrown');
ok('no exceptions after interaction', errs2.length === 0);