better toolbar
This commit is contained in:
parent
2f1c9b9c02
commit
5fb04f6a7d
6 changed files with 433 additions and 87 deletions
|
|
@ -67,18 +67,53 @@ try {
|
|||
return true;
|
||||
})()`);
|
||||
await sleep(250);
|
||||
// A command is named the same wherever it is drawn, and since the transport
|
||||
// strip was consolidated it is drawn in one of two places: as a button in the
|
||||
// strip, or as a row in one of the strip's menus. So the test asks for it by
|
||||
// name and this finds it — opening each menu in turn to look — rather than the
|
||||
// test knowing which menu anything ended up in. An icon button is matched on
|
||||
// its `aria-label`, which is also what a screen reader is told it is.
|
||||
const strip = '.pane.time .pane-head';
|
||||
const named = label =>
|
||||
`(b => b.textContent.trim() === ${JSON.stringify(label)}` +
|
||||
` || b.getAttribute('aria-label') === ${JSON.stringify(label)})`;
|
||||
const shut = async () => {
|
||||
await evaluate(`(() => { document.querySelectorAll('.menu-scrim').forEach(s => s.click()); return true })()`);
|
||||
await sleep(120);
|
||||
};
|
||||
// Leaves the control on screen and returns what to select it with.
|
||||
const reveal = async label => {
|
||||
await shut();
|
||||
if (await evaluate(`![...document.querySelectorAll('${strip} button')].find(${named(label)})`)) {
|
||||
const menus = await evaluate(
|
||||
`[...document.querySelectorAll('${strip} .menu-wrap > button')].map(b => b.textContent.trim())`);
|
||||
let found = false;
|
||||
for (const menu of menus) {
|
||||
await evaluate(`(() => { [...document.querySelectorAll('${strip} .menu-wrap > button')]
|
||||
.find(b => b.textContent.trim() === ${JSON.stringify(menu)}).click(); return true })()`);
|
||||
await sleep(180);
|
||||
if (await evaluate(`!![...document.querySelectorAll('.menu-item')].find(${named(label)})`)) { found = true; break; }
|
||||
await shut();
|
||||
}
|
||||
assert(found, `a control named: ${label}`);
|
||||
return '.menu-item';
|
||||
}
|
||||
return `${strip} button`;
|
||||
};
|
||||
const click = async label => {
|
||||
const where = await reveal(label);
|
||||
assert(await evaluate(`(() => {
|
||||
const b = [...document.querySelectorAll('button')].find(b => b.textContent.trim() === ${JSON.stringify(label)});
|
||||
const b = [...document.querySelectorAll('${where}')].find(${named(label)});
|
||||
if (!b || b.disabled) return false;
|
||||
b.click(); return true;
|
||||
})()`), `enabled button: ${label}`);
|
||||
})()`), `enabled control: ${label}`);
|
||||
await sleep(180);
|
||||
await shut();
|
||||
};
|
||||
const shot = async () => (await evaluate('laneSnapshot()'));
|
||||
const instances = s => Object.values(s.clip.symbols.main.nodes).filter(n => n.kind === 'instance')
|
||||
.sort((a, b) => a.time.at - b.time.at);
|
||||
await click('+ lane');
|
||||
await click('lane');
|
||||
await click('new drawing');
|
||||
await click('hold +');
|
||||
await click('hold +');
|
||||
|
|
@ -123,10 +158,15 @@ try {
|
|||
document.querySelector('.tl-cel').click();
|
||||
})()`);
|
||||
await sleep(200);
|
||||
const enabled = async label => await evaluate(`(() => {
|
||||
const b = [...document.querySelectorAll('button')].find(b => b.textContent.trim() === ${JSON.stringify(label)});
|
||||
return !!b && !b.disabled;
|
||||
})()`);
|
||||
const enabled = async label => {
|
||||
const where = await reveal(label);
|
||||
const yes = await evaluate(`(() => {
|
||||
const b = [...document.querySelectorAll('${where}')].find(${named(label)});
|
||||
return !!b && !b.disabled;
|
||||
})()`);
|
||||
await shut();
|
||||
return yes;
|
||||
};
|
||||
assert.equal(await enabled('make unique'), false, 'nothing to decouple from yet');
|
||||
await click('reuse');
|
||||
s = await shot();
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ const PROBE = `(() => {
|
|||
w: c.width, h: c.height, drawn, tones: [...tones].length, toneSet: [...tones],
|
||||
cx: drawn ? cx / drawn : null, cy: drawn ? cy / drawn : null,
|
||||
hash: h >>> 0,
|
||||
frame: document.querySelector('.time .pane-head .dim')?.textContent ?? '',
|
||||
frame: document.querySelector('.time .pane-head .at-frame')?.textContent ?? '',
|
||||
// What the top bar says about the document. The media pool holds the OPEN
|
||||
// document's library now and no longer names documents at all, so the status
|
||||
// line is the page's own answer to "what am I looking at".
|
||||
|
|
@ -202,7 +202,7 @@ const PROBE = `(() => {
|
|||
// knows which frame it wants, not how long the clip it is looking at happens to
|
||||
// be, and reading it here is one place instead of every call site.
|
||||
const SEEK = (f) => `(() => {
|
||||
const read = document.querySelector('.time .pane-head .dim').textContent;
|
||||
const read = document.querySelector('.time .pane-head .at-frame').textContent;
|
||||
// Split, not a regex: this is inside a template literal, where an escaped
|
||||
// slash collapses to a bare one and the two together open a line comment that
|
||||
// eats the rest of the statement. The readout is "12 / 229" and nothing else.
|
||||
|
|
@ -216,7 +216,7 @@ const SEEK = (f) => `(() => {
|
|||
clientY: box.top + box.height / 2,
|
||||
}));
|
||||
ruler.dispatchEvent(new PointerEvent('pointerup', { bubbles: true, pointerId: 1 }));
|
||||
return document.querySelector('.time .pane-head .dim').textContent;
|
||||
return document.querySelector('.time .pane-head .at-frame').textContent;
|
||||
})()`;
|
||||
|
||||
// Everything the page has to say about loading, saving and opening. Read off the
|
||||
|
|
@ -231,10 +231,15 @@ const STATUS = `[...document.querySelectorAll('.top .status, .pool .pane-body >
|
|||
// pane each one lived in would be a second copy of the layout.
|
||||
//
|
||||
// `firstChild` is the label: a media-pool row has a second line in a child span,
|
||||
// so matching on textContent would never find "take".
|
||||
// so matching on textContent would never find "take". `aria-label` is the same
|
||||
// label for a control whose face is a glyph — the transport's play and pause —
|
||||
// and it is the right fallback rather than a test hook, because it is already
|
||||
// what that button is called for anybody not reading it with their eyes.
|
||||
const CLICK = (label) => `(() => {
|
||||
const want = ${JSON.stringify(label)};
|
||||
const b = [...document.querySelectorAll('button')]
|
||||
.find((b) => (b.firstChild?.textContent ?? '').trim() === ${JSON.stringify(label)});
|
||||
.find((b) => (b.firstChild?.textContent ?? '').trim() === want
|
||||
|| b.getAttribute('aria-label') === want);
|
||||
if (!b || b.disabled) return false;
|
||||
b.click();
|
||||
return true;
|
||||
|
|
@ -626,7 +631,7 @@ async function main() {
|
|||
check(irisSlider !== null, 'the stage eye has an iris-size slider');
|
||||
if (irisSlider) {
|
||||
check(await page.eval(CLICK('play')), 'the stage starts playing');
|
||||
const startFrame = await page.eval(`Number(document.querySelector('.time .pane-head .dim').textContent.match(/\\d+/)[0])`);
|
||||
const startFrame = await page.eval(`Number(document.querySelector('.time .pane-head .at-frame').textContent.match(/\\d+/)[0])`);
|
||||
await page.send('Input.dispatchMouseEvent', {
|
||||
type: 'mousePressed', x: irisSlider.x, y: irisSlider.y, button: 'left', clickCount: 1,
|
||||
});
|
||||
|
|
@ -638,7 +643,7 @@ async function main() {
|
|||
check(preview !== null, 'the slider updates the stage preview', preview ?? debug);
|
||||
check(debug.includes(':face-1/eye-r') && debug.includes('tier 1 only'),
|
||||
'the panel reports the affected feature and tier', debug);
|
||||
const endFrame = await page.eval(`Number(document.querySelector('.time .pane-head .dim').textContent.match(/\\d+/)[0])`);
|
||||
const endFrame = await page.eval(`Number(document.querySelector('.time .pane-head .at-frame').textContent.match(/\\d+/)[0])`);
|
||||
check(endFrame > startFrame, 'playback continues during tuning', `${startFrame} -> ${endFrame}`);
|
||||
await page.eval(CLICK('pause'));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue