[test](trx-frontend-http): type the frequency instead of filling it
CI / lint (pull_request) Successful in 2m20s
CI / test (pull_request) Successful in 8m32s
CI / frontend (pull_request) Successful in 4m27s
CI / reuse (pull_request) Successful in 6s
CI / lint (push) Successful in 2m26s
CI / test (push) Successful in 7m42s
CI / frontend (push) Successful in 3m35s
CI / reuse (push) Successful in 5s
CI / lint (pull_request) Successful in 2m20s
CI / test (pull_request) Successful in 8m32s
CI / frontend (pull_request) Successful in 4m27s
CI / reuse (pull_request) Successful in 6s
CI / lint (push) Successful in 2m26s
CI / test (push) Successful in 7m42s
CI / frontend (push) Successful in 3m35s
CI / reuse (push) Successful in 5s
tune-links drove the dial with Playwright's fill(), which writes a value into the field without a keystroke. The app arms its guard against its own refreshes on the first keydown, so a filled field stays unguarded: any state update landing between the fill and the Enter rewrites the field with the frequency the radio is already on, and the Enter then re-applies that. The window is a few milliseconds wide on a developer's machine and wide enough to lose on a loaded CI runner, where the test failed claiming the tuning had landed on the frequency it started from. Type it the way an operator does: select the field, then send the characters as keystrokes. The select arms the guard before a single character changes. Under CPU throttling that reproduced the failure — 1 in 6 runs with fill(), on this branch and on main alike — typing came through 8 runs clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SyX26FCpMQxiBoC7r5K1A7 Signed-off-by: Stan Grams <sjg@haxx.space>
This commit was merged in pull request #53.
This commit is contained in:
@@ -27,6 +27,21 @@ const dial = () => page.evaluate(() => ({
|
||||
path: window.location.pathname,
|
||||
}));
|
||||
|
||||
// Typed, not filled. The app holds back its own refreshes of the frequency
|
||||
// field from the first keystroke until Enter, so that a state update arriving
|
||||
// mid-edit does not rewrite what is being typed. `fill()` sets the value
|
||||
// without a keystroke, leaving the field unguarded: on a slow machine a state
|
||||
// update could land between the fill and the Enter and put the old frequency
|
||||
// back, and the Enter would then re-apply the frequency the radio was already
|
||||
// on. Selecting first arms the guard before a single character changes.
|
||||
async function tuneByHand(text) {
|
||||
const field = page.locator("#freq");
|
||||
await field.click();
|
||||
await field.press("ControlOrMeta+a");
|
||||
await field.pressSequentially(text);
|
||||
await field.press("Enter");
|
||||
}
|
||||
|
||||
try {
|
||||
await page.setViewportSize({ width: 1500, height: 950 });
|
||||
|
||||
@@ -49,8 +64,7 @@ try {
|
||||
|
||||
// Tuning by hand rewrites the link. This is the part that makes the address
|
||||
// bar shareable at any moment rather than only at load.
|
||||
await page.locator("#freq").fill("7.040M");
|
||||
await page.locator("#freq").press("Enter");
|
||||
await tuneByHand("7.040M");
|
||||
await page.waitForTimeout(1500);
|
||||
const tuned = await dial();
|
||||
assert.equal(tuned.freqHz, TUNED_HZ, `tuning landed on ${tuned.freqHz} Hz`);
|
||||
@@ -59,8 +73,7 @@ try {
|
||||
|
||||
// Tuning is not navigation: a swept dial must not bury the back button.
|
||||
const historyLength = await page.evaluate(() => window.history.length);
|
||||
await page.locator("#freq").fill("7.100M");
|
||||
await page.locator("#freq").press("Enter");
|
||||
await tuneByHand("7.100M");
|
||||
await page.waitForTimeout(1200);
|
||||
assert.equal(await page.evaluate(() => window.history.length), historyLength,
|
||||
"tuning pushed a history entry instead of replacing one");
|
||||
|
||||
Reference in New Issue
Block a user