@bongos/core 1.25.25 → 1.25.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.bongos-core.json +26 -26
- package/docs/copy-inventory.md +4 -4
- package/docs/copy-registry.json +6 -6
- package/docs/module-api-changelog.md +4 -0
- package/docs/page-readings.json +81 -81
- package/modules/hall-ui/public/city.css +3 -2
- package/modules/hall-ui/public/style.css +2 -1
- package/modules/hall-ui/public/thinking.css +8 -6
- package/modules/hall-ui/public/visor.css +65 -31
- package/modules/hall-ui/public/visor.js +121 -6
- package/modules/hall-ui/records/visor.md +14 -0
- package/modules/ui-design/scripts/gen-design-reference.js +3 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +16 -0
- package/scripts/bongos/gen-brand.js +2 -1
- package/src/module-api.js +1 -1
- package/tests/brand_mark.mjs +2 -1
- package/tests/design_counts_ratchet.mjs +21 -0
- package/tests/design_reference.mjs +1 -1
- package/tests/hall_dialog.mjs +20 -1
- package/tests/hall_visor.mjs +100 -1
package/tests/hall_dialog.mjs
CHANGED
|
@@ -290,10 +290,29 @@ test('the guard catches a browser box when one comes back, and leaves the shared
|
|
|
290
290
|
}
|
|
291
291
|
});
|
|
292
292
|
|
|
293
|
+
// shell.js's tag, then hall-dialog.js's on the very next line. Either line ending: git's
|
|
294
|
+
// core.autocrlf checks every page out with CRLF on Windows, and an LF-only `\n` here failed every
|
|
295
|
+
// page there, so a real misordering (task 1005148's visor.js between the two) read as noise.
|
|
296
|
+
// Task 1005197.
|
|
297
|
+
function shellThenDialog(html) {
|
|
298
|
+
return html.match(/<script src="\/builders\/shell\.js[^"]*"( defer)?><\/script>\r?\n<script src="\/builders\/hall-dialog\.js"( defer)?><\/script>/);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
test('the shell-then-dialog order check reads LF and CRLF pages alike, and still catches a misorder', () => {
|
|
302
|
+
const pair = ['<script src="/builders/shell.js?v=1" defer></script>', '<script src="/builders/hall-dialog.js" defer></script>'];
|
|
303
|
+
for (const eol of ['\n', '\r\n']) {
|
|
304
|
+
const m = shellThenDialog(pair.join(eol));
|
|
305
|
+
assert.ok(m, `matched with ${JSON.stringify(eol)} line endings`);
|
|
306
|
+
assert.equal(m[1], m[2]);
|
|
307
|
+
const between = [pair[0], '<script src="/builders/visor.js" defer></script>', pair[1]].join(eol);
|
|
308
|
+
assert.equal(shellThenDialog(between), null, `a script between them is caught with ${JSON.stringify(eol)}`);
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
|
|
293
312
|
test('every hall page loads the shared dialog right after the shell, deferred alike', () => {
|
|
294
313
|
for (const f of fs.readdirSync(PUB).filter((n) => n.endsWith('.html'))) {
|
|
295
314
|
const html = read(f);
|
|
296
|
-
const shell = html
|
|
315
|
+
const shell = shellThenDialog(html);
|
|
297
316
|
if (!/\/builders\/shell\.js/.test(html)) continue;
|
|
298
317
|
assert.ok(shell, `${f} loads hall-dialog.js right after shell.js`);
|
|
299
318
|
assert.equal(shell[1], shell[2], `${f}: deferred alike`);
|
package/tests/hall_visor.mjs
CHANGED
|
@@ -236,7 +236,7 @@ test('source: the minimal visor spends the Helm tokens and types in no colour, s
|
|
|
236
236
|
assert.ok(phone, 'the phone rules sit in the shared phone block');
|
|
237
237
|
assert.match(phone[0], /\.visor__hint:not\(\[data-visor-sheet\]\) \{ display: none; \}/, 'a phone keeps only Actions of the hints');
|
|
238
238
|
assert.doesNotMatch(read('home-city.css'), /visor-on/, 'Home has no top-right pill to clear any more');
|
|
239
|
-
assert.match(read('city.css'), /\nhtml\.visor-on \.city-door \{ bottom:
|
|
239
|
+
assert.match(read('city.css'), /\nhtml\.visor-on \.city-door \{ bottom: calc\(180px - var\(--visor-drop, 0px\)\); \}/, 'the city\'s door clears the centred button at every width (task 1005266: the row dropped, except on a phone)');
|
|
240
240
|
});
|
|
241
241
|
|
|
242
242
|
// ---------- in a browser: the glass over a stand-in scene ----------
|
|
@@ -554,3 +554,102 @@ test('the glass is the kit\'s: the cut accent button, ice hints with no box, the
|
|
|
554
554
|
assert.match(f.ring, /inset/, 'focus is the inset two-tone ring (--press-focus)');
|
|
555
555
|
await ctx.close();
|
|
556
556
|
});
|
|
557
|
+
|
|
558
|
+
// ---------- task 1005266: the glass rests while you look and wakes slim when you act ----------
|
|
559
|
+
test('the top arc cuts into pieces of the same curve (task 1005266)', () => {
|
|
560
|
+
const V = loadPure();
|
|
561
|
+
assert.equal(V.arcPiece(0, 1), 'M76 100Q500 -100 924 100', 'the whole of it is the arc itself');
|
|
562
|
+
const end = (d) => d.split(' ').slice(-2).join(' '), start = (d) => d.slice(1, d.indexOf('Q'));
|
|
563
|
+
assert.equal(end(V.arcPiece(0, 0.5)), start(V.arcPiece(0.5, 1)), 'two halves meet');
|
|
564
|
+
assert.equal(start(V.arcPiece(0.5, 1)), '500 0', 'at the top of the arc');
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
test('the glass rests when you leave it alone and wakes when you reach for it (task 1005266)', { skip }, async () => {
|
|
568
|
+
const { ctx, page, errors } = await open({ helm: true });
|
|
569
|
+
const look = () => page.evaluate(() => {
|
|
570
|
+
const op = (s) => getComputedStyle(document.querySelector(s)).opacity;
|
|
571
|
+
return { resting: OTBVisor.resting(), main: op('.visor__main'), hints: op('.visor__hints'), who: op('.visor__who'), place: op('.visor__top'), sprite: op('.visor__sprite'), sight: op('.visor__sight') };
|
|
572
|
+
});
|
|
573
|
+
assert.equal((await look()).resting, false, 'arriving at a place shows the whole glass');
|
|
574
|
+
await page.mouse.move(640, 300);
|
|
575
|
+
await page.waitForFunction(() => OTBVisor.resting(), null, { timeout: 8000 });
|
|
576
|
+
await page.waitForTimeout(400);
|
|
577
|
+
assert.deepEqual(await look(), { resting: true, main: '0', hints: '0', who: '0', place: '0', sprite: '1', sight: '1' }, 'at rest only the frame and your picture are drawn');
|
|
578
|
+
await page.mouse.move(640, 790);
|
|
579
|
+
await page.waitForTimeout(400);
|
|
580
|
+
assert.deepEqual(await look(), { resting: false, main: '1', hints: '1', who: '1', place: '1', sprite: '1', sight: '1' }, 'the pointer near the bottom of the view wakes it');
|
|
581
|
+
await page.mouse.move(640, 300);
|
|
582
|
+
await page.mouse.down();
|
|
583
|
+
assert.equal((await look()).resting, true, 'a press on the scene rests it at once');
|
|
584
|
+
await page.mouse.move(700, 790, { steps: 3 });
|
|
585
|
+
assert.equal((await look()).resting, true, 'a drag that passes the bottom of the view is looking, not reaching');
|
|
586
|
+
await page.mouse.up();
|
|
587
|
+
// a visor key wakes it, and the open sheet holds it awake
|
|
588
|
+
await page.mouse.move(640, 300);
|
|
589
|
+
await page.keyboard.press('a');
|
|
590
|
+
assert.deepEqual(await page.evaluate(() => [OTBVisor.isOpen(), OTBVisor.resting()]), [true, false], 'A opens the sheet on a waking glass');
|
|
591
|
+
await page.mouse.click(300, 300);
|
|
592
|
+
assert.equal((await look()).resting, false, 'the sheet holds the glass awake');
|
|
593
|
+
await page.keyboard.press('Escape');
|
|
594
|
+
assert.equal(await page.evaluate(() => document.activeElement.matches('[data-visor-sheet]')), true, 'the keyboard is back on Actions, which also holds it');
|
|
595
|
+
await page.mouse.click(300, 300);
|
|
596
|
+
assert.deepEqual(await page.evaluate(() => [OTBVisor.resting(), document.activeElement === document.body]), [true, true], 'going back to the scene rests it and hands the keyboard back');
|
|
597
|
+
// a control you cannot see is never pressed by accident: the first press only wakes
|
|
598
|
+
await page.evaluate(() => document.querySelector('[data-visor-sheet]').click());
|
|
599
|
+
assert.deepEqual(await page.evaluate(() => [OTBVisor.isOpen(), OTBVisor.resting()]), [false, false]);
|
|
600
|
+
assert.deepEqual(errors, []);
|
|
601
|
+
await ctx.close();
|
|
602
|
+
});
|
|
603
|
+
|
|
604
|
+
test('a key hint is its key, and pointing at it names it above the row without moving another (task 1005266)', { skip }, async () => {
|
|
605
|
+
const { ctx, page, errors } = await open({ helm: true });
|
|
606
|
+
const boxes = () => page.evaluate(() => [...document.querySelectorAll('.visor__hint')].map((h) => Math.round(h.getBoundingClientRect().left)));
|
|
607
|
+
const before = await boxes();
|
|
608
|
+
await page.hover('[data-visor-act="thinking"]');
|
|
609
|
+
assert.equal(await page.evaluate(() => document.querySelector('.visor__hints').getAttribute('data-name')), 'Your thinking');
|
|
610
|
+
assert.deepEqual(await boxes(), before, 'naming a key moves no key');
|
|
611
|
+
assert.equal(await page.textContent('[data-visor-act="thinking"]'), 'TYour thinking', 'the name is still in the page for a screen reader');
|
|
612
|
+
await page.mouse.move(640, 300);
|
|
613
|
+
assert.equal(await page.evaluate(() => document.querySelector('.visor__hints').hasAttribute('data-name')), false);
|
|
614
|
+
assert.deepEqual(errors, []);
|
|
615
|
+
await ctx.close();
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
test('the top arc is the version\'s progress while awake, and one plain arc at rest (task 1005266)', { skip }, async () => {
|
|
619
|
+
const { ctx, page, errors } = await open({ helm: true });
|
|
620
|
+
await ctx.route(ORIGIN + '/api/bongos/versions/progress', (r) => r.fulfill({ contentType: 'application/json', body: JSON.stringify({ progress: [{ version_id: 'BONGOS-V2', name: 'The ten working areas', status: 'building', percent_complete: 89 }] }) }));
|
|
621
|
+
await ctx.route(ORIGIN + '/api/bongos/versions/focus', (r) => r.fulfill({ contentType: 'application/json', body: JSON.stringify({ focus_version_id: 'BONGOS-V2' }) }));
|
|
622
|
+
await page.reload();
|
|
623
|
+
await page.waitForSelector('.visor__frame--segs');
|
|
624
|
+
const read = () => page.evaluate(() => {
|
|
625
|
+
const shown = (e) => getComputedStyle(e).display !== 'none';
|
|
626
|
+
return {
|
|
627
|
+
segs: [...document.querySelectorAll('.visor__seg:not(.visor__line--under)')].map((p) => (/visor__seg--(\w+)/.exec(p.getAttribute('class')) || [])[1]),
|
|
628
|
+
segsShown: [...document.querySelectorAll('.visor__seg')].every(shown),
|
|
629
|
+
arcShown: [...document.querySelectorAll('.visor__arc')].every(shown),
|
|
630
|
+
words: document.querySelector('.visor__progress-words [aria-hidden]').textContent,
|
|
631
|
+
said: document.querySelector('.visor__progress-words .sr-only').textContent,
|
|
632
|
+
bars: document.querySelectorAll('.visor .segs').length,
|
|
633
|
+
line: [...document.querySelectorAll('.visor__top > *')].map((e) => Math.round(e.getBoundingClientRect().top)),
|
|
634
|
+
};
|
|
635
|
+
});
|
|
636
|
+
const awake = await read();
|
|
637
|
+
assert.deepEqual(awake.segs, ['done', 'done', 'done', 'now'], 'four quarters: three built, the fourth being built');
|
|
638
|
+
assert.deepEqual([awake.segsShown, awake.arcShown], [true, false], 'awake, the pieces stand in for the plain arc');
|
|
639
|
+
assert.deepEqual([awake.words, awake.said, awake.bars], ['BONGOS-V2 · 89%', 'BONGOS-V2, The ten working areas: 89% built', 0], 'the reading is still said in words; the separate row of bars is gone');
|
|
640
|
+
assert.equal(awake.line.length, 2);
|
|
641
|
+
assert.ok(Math.abs(awake.line[0] - awake.line[1]) <= 2, 'the place and the reading share one line');
|
|
642
|
+
await page.mouse.move(640, 300);
|
|
643
|
+
await page.mouse.down(); await page.mouse.up();
|
|
644
|
+
const rest = await read();
|
|
645
|
+
assert.deepEqual([rest.segsShown, rest.arcShown], [false, true], 'at rest it is the one plain arc');
|
|
646
|
+
assert.deepEqual(errors, []);
|
|
647
|
+
await ctx.close();
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
test('a phone keeps the whole glass: there is no pointer to reach with (task 1005266)', { skip }, async () => {
|
|
651
|
+
const { ctx, page } = await open({ helm: true, width: 390, height: 844 });
|
|
652
|
+
await page.evaluate(() => OTBVisor.rest());
|
|
653
|
+
assert.deepEqual(await page.evaluate(() => [OTBVisor.resting(), document.getElementById('visor').classList.contains('visor--rest'), getComputedStyle(document.querySelector('.visor__main')).opacity]), [false, false, '1']);
|
|
654
|
+
await ctx.close();
|
|
655
|
+
});
|