Something went wrong. Try again.
Web frontend and supporting services for lance.blue
Something went wrong. Try again.
3.3 kB · 81 lines
JavaScript
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182/** * What the editor's sliders say, as opposed to what they show. * * Every one of them drives a picture through a number that is not the number * on screen: Size is a 0..1 fraction shown as a percentage, Angle is a * fraction of a turn shown in degrees, Zoom is a multiple, and the two framing * controls run -1..1 and are shown signed. `format` is what closes that gap * for a reader looking at the page, and `aria-valuetext` is the only thing * that closes it for one who is not — without it a screen reader lands on * Angle and says "0.25" where the page says 90°. * * Structural, because there is nothing to catch at runtime. A slider with no * aria-valuetext still works, still renders, still drags; it is only wrong out * loud. * * Run with `npm test`. */import { test } from "node:test";import assert from "node:assert/strict";import { readFile } from "node:fs/promises";import { join } from "node:path";import { fileURLToPath } from "node:url";
const web = fileURLToPath(new URL("../", import.meta.url));const source = await readFile(join(web, "src/camo/editor.ts"), "utf8");
/** The body of the slider builder, which is where all of this has to be. */const builder = (() => { const start = source.indexOf(" function slider("); assert.notEqual(start, -1, "the slider builder moved or was renamed"); const end = source.indexOf("\n }", start); assert.notEqual(end, -1, "the slider builder has no end"); return source.slice(start, end);})();
test("a slider says its formatted value, not its raw one", () => { assert.match( builder, /aria-valuetext/, "the slider announces the number it is implemented with rather than the " + "one it is showing", );});
test("the readout and the announcement are the same string", () => { // Two calls to format() that could drift apart is the whole failure mode // this replaced: the readout said one thing and the control said another. const formats = [...builder.matchAll(/format\(/g)]; assert.equal( formats.length, 1, `format() is called ${formats.length} times in the slider builder; it has ` + "to be called once and the result used for both the readout and " + "aria-valuetext, or the two can disagree", );});
test("the value is set once at build and again on every input", () => { // A slider built with the right announcement and never updated is worse than // one with none: it is confidently wrong for the whole of a drag. The shape // that holds is one setter called from both places. const setter = /const show = \(v: number\): void =>/.test(builder); assert.ok(setter, "the slider no longer has one setter for its value");
const calls = [...builder.matchAll(/\bshow\(/g)]; assert.ok( calls.length >= 2, "the setter is called once, so either the initial value or the drag is " + "not covered", );});
test("the readout does not announce itself on top of the slider", () => { // <output> is a live region. Left in the tree it announced every step of a // drag, over the value the slider announces anyway. assert.match( builder, /readout\.setAttribute\("aria-hidden", "true"\)/, "the readout is a live region again, so a drag is announced twice", );});