This commit is contained in:
Olive Vaughn 2026-10-04 18:14:05 -04:00
parent 208dddee07
commit 78fb120edd
9 changed files with 102 additions and 48 deletions

View file

@ -523,32 +523,32 @@ async function main() {
// same synchronous block arrives while the tool is still unset and is dropped.
// A person cannot click twice inside one microtask; a test should not either.
const armed = await page.eval(`(() => {
const button = [...document.querySelectorAll('.palette-bar button')]
.find(b => b.textContent === 'pen');
const button = document.querySelector('.toolbox button.tool[title^="Pen"]');
if (!button) return false;
button.click();
return true;
})()`);
await sleep(100);
const painted = armed && await page.eval(`(() => {
const svg = document.querySelector('.paint-overlay');
const box = svg.getBoundingClientRect();
for (const [x, y] of [[10, 10], [40, 10], [25, 40]]) {
svg.dispatchEvent(new PointerEvent('pointerdown', {
bubbles: true, clientX: box.left + x * box.width / 320,
clientY: box.top + y * box.height / 200,
}));
}
// The overlay reaches past the stage on every side, so a stage pixel is
// found through the SVG's own transform, as the stage finds it coming back.
// Each point is its own eval: a click is a re-frame event, and the next one
// reads the draft it added to.
const PEN_AT = (x, y) => `(() => {
const svg = document.querySelector('.paint-overlay.tool-pen');
if (!svg) return false;
const p = new DOMPoint(${x}, ${y}).matrixTransform(svg.getScreenCTM());
svg.dispatchEvent(new PointerEvent('pointerdown', {
bubbles: true, clientX: p.x, clientY: p.y,
}));
return true;
})()`);
await sleep(100);
const finished = await page.eval(`(() => {
const button = [...document.querySelectorAll('.palette-bar button')]
.find(b => b.textContent === 'finish');
if (!button || button.disabled) return false;
button.click();
return true;
})()`);
})()`;
let painted = armed;
for (const [x, y] of [[10, 10], [40, 10], [25, 40]]) {
painted = painted && await page.eval(PEN_AT(x, y));
await sleep(60);
}
// Closed as a person closes it: on the first point.
const finished = painted && await page.eval(PEN_AT(10, 10));
await sleep(250);
const afterPaint = await page.eval(`(() => {
const c = document.querySelector('canvas.stage');
@ -556,7 +556,8 @@ async function main() {
return [...d];
})()`);
check(painted && finished && beforePaint.join(',') !== afterPaint.join(','),
'a polygon drawn with the paint controls appears on the canvas');
'a polygon drawn with the paint controls appears on the canvas',
`${beforePaint} -> ${afterPaint}`);
for (const f of [8, 16]) {
await page.eval(SEEK(f));
await sleep(100);
@ -597,7 +598,18 @@ async function main() {
return [...c.getContext('2d').getImageData(25, 20, 1, 1).data];
})()`);
check(afterPaint.join(',') === reopenedPaint.join(','),
'the painted polygon survives the project round trip');
'the painted polygon survives the project round trip', `${afterPaint} vs ${reopenedPaint}`);
// A reopened document has nothing selected, so the shape's keys are not in
// the inspector until it is selected again, as anybody would.
await page.eval(`(() => {
const c = cljs.core, k = c.keyword;
const db = c.deref(re_frame.db.app_db);
const nodes = c.get_in(c.get(arthur.footage.store.entry(c.get(db, k('clip/current'))), k('clip')),
c.vector(k('symbols'), k('main'), k('nodes')));
const id = c.first(c.filter((id) => c.name(id).startsWith('paint-'), c.keys(nodes)));
re_frame.core.dispatch_sync(c.vector(k('arthur.events.ui/select'),
c.vector(k('node'), k('main'), id, c.vector(id))));
})()`);
await page.eval(SEEK(8));
await sleep(100);
check(await page.eval(`(() => {