gui tests: fold-show-grip measures Show and the picker once the fold's rows have slid in, in one read, and reads the grips from the page as drawn now
The fold's rows open with translateY(-10px) scale(.985) over .56s after a staggered delay. The test read Show's box and the picker's box in two round trips while the row still moved, so the second read landed lower (Show 355.7 vs picker 361.3): it failed in 3 of 4 runs alone, in either engine. It now waits for the fold's animations to finish and reads both boxes in one evaluate. The Usage page's cards are drawn again as its reads come in (Chromium: three grips within 35ms of the first), so the grip's style and the card, grip and logo boxes are read from the page in one call rather than through a handle that may already be replaced. The hover-only grip is unchanged.
This commit is contained in:
1 parent
d1bbc5b65b
commit
2d0482a201
1 file changed
+24
-13
@@ -43,12 +43,14 @@ function server(lang) {
|
||||
}
|
||||
|
||||
// a grip's dots: whether it shows, and whether its last column of dots
|
||||
// (each 1.2px round about its tile's middle) is inside its box
|
||||
const grip = (h) => h.evaluate((h) => {
|
||||
const s = getComputedStyle(h, "::before"), w = parseFloat(s.width), tile = parseFloat(s.backgroundSize);
|
||||
// (each 1.2px round about its tile's middle) is inside its box. Found in the
|
||||
// page at the read, as shown() does: a grip drawn again is a new element, and
|
||||
// the old one, out of the page, has no style to read.
|
||||
const grip = (page, sel) => page.evaluate((sel) => {
|
||||
const s = getComputedStyle(document.querySelector(sel), "::before"), w = parseFloat(s.width), tile = parseFloat(s.backgroundSize);
|
||||
const cols = Math.ceil(w / tile);
|
||||
return { whole: (cols - 1) * tile + tile / 2 + 1.2 <= w + 0.01, cols, w, tile };
|
||||
});
|
||||
}, sel);
|
||||
const shown = (page, sel, v) => page.waitForFunction(([sel, v]) => getComputedStyle(document.querySelector(sel), "::before").opacity === v, [sel, v]);
|
||||
|
||||
for (const engine of (process.env.BROWSER ? [process.env.BROWSER] : ["chromium", "webkit"])) {
|
||||
@@ -69,9 +71,13 @@ for (const engine of (process.env.BROWSER ? [process.env.BROWSER] : ["chromium",
|
||||
const show = idle.locator(".ag-show");
|
||||
await show.waitFor();
|
||||
assert.equal((await show.textContent()).trim(), lang === "zh" ? "显示" : "Show");
|
||||
const mid = async (l) => { const b = await l.boundingBox(); return b.y + b.height / 2; };
|
||||
const pick = idle.locator("> .field.ag-start");
|
||||
const [ms, mp] = [await mid(show), await mid(pick)];
|
||||
// the fold's rows slide in (translateY and scale, .56s after a staggered
|
||||
// delay): measure Show and the picker at rest, in one read. Read one at a
|
||||
// time while the row still moves, the second read lands lower, by more
|
||||
// the slower the machine.
|
||||
await page.locator(".agent-fold").evaluate((f) => Promise.all(f.getAnimations({ subtree: true }).map((a) => a.finished)));
|
||||
const [ms, mp] = await idle.evaluate((row) => [row.querySelector(".ag-show"), row.querySelector(":scope > .field.ag-start")]
|
||||
.map((e) => { const b = e.getBoundingClientRect(); return b.y + b.height / 2; }));
|
||||
assert.ok(Math.abs(ms - mp) <= 1, `Show (${ms}) is level with the picker (${mp})`);
|
||||
// the shown one beside it has none
|
||||
assert.equal(await page.locator('.agent-fold .row.agent[data-id="grok"] .ag-show').count(), 0);
|
||||
@@ -82,7 +88,7 @@ for (const engine of (process.env.BROWSER ? [process.env.BROWSER] : ["chromium",
|
||||
await shown(page, sel, "0");
|
||||
await page.locator('#agents > .row.agent[data-id="codex"]').hover();
|
||||
await shown(page, sel, "1");
|
||||
const ag = await grip(page.locator(sel));
|
||||
const ag = await grip(page, sel);
|
||||
assert.ok(ag.whole && ag.cols === 2, "the Agents grip's columns are whole: " + JSON.stringify(ag));
|
||||
assert.deepEqual(await tops(), top, "no click moved the page");
|
||||
|
||||
@@ -95,12 +101,17 @@ for (const engine of (process.env.BROWSER ? [process.env.BROWSER] : ["chromium",
|
||||
await shown(page, ".subscription-card .us-handle", "0");
|
||||
await card.hover();
|
||||
await shown(page, ".subscription-card .us-handle", "1");
|
||||
const us = await grip(handle);
|
||||
const us = await grip(page, ".subscription-card .us-handle");
|
||||
assert.ok(us.whole && us.cols === 2, "the Usage grip's columns are whole: " + JSON.stringify(us));
|
||||
// between the card's edge and the logo
|
||||
const [hb, ib, cb] = await Promise.all([handle.boundingBox(), handle.locator(".ic").boundingBox(), card.boundingBox()]);
|
||||
const left = hb.x + await handle.evaluate((h) => parseFloat(getComputedStyle(h, "::before").left));
|
||||
assert.ok(left > cb.x + 1 && left + us.w <= ib.x, `the grip (${left}–${left + us.w}) is between the card (${cb.x}) and the logo (${ib.x})`);
|
||||
// between the card's edge and the logo. The cards are drawn again as the
|
||||
// page's reads come in, so the boxes are read in one go, from one card:
|
||||
// a box read from a card already replaced is null.
|
||||
const { left, logo, edge } = await page.evaluate(() => {
|
||||
const card = document.querySelector(".subscription-card"), h = card.querySelector(".us-handle");
|
||||
return { left: h.getBoundingClientRect().x + parseFloat(getComputedStyle(h, "::before").left),
|
||||
logo: h.querySelector(".ic").getBoundingClientRect().x, edge: card.getBoundingClientRect().x };
|
||||
});
|
||||
assert.ok(left > edge + 1 && left + us.w <= logo, `the grip (${left}–${left + us.w}) is between the card (${edge}) and the logo (${logo})`);
|
||||
assert.deepEqual(errors, []);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user