Skip to content

fix(playwright): replace monolithic waitForCanvas with scoped async helpers#176

Merged
MaximumTrainer merged 2 commits intomasterfrom
copilot/fix-playwright-wasm-ble-api-timeout
Apr 21, 2026
Merged

fix(playwright): replace monolithic waitForCanvas with scoped async helpers#176
MaximumTrainer merged 2 commits intomasterfrom
copilot/fix-playwright-wasm-ble-api-timeout

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 21, 2026

All 4 WASM BLE API tests timed out because waitForCanvas() required a successful FTMS control-point write before any assertion could run — a condition that frequently never completes on CI against the live GitHub Pages deployment.

Changes

  • Split waitForCanvas() into three focused helpers:

    • waitForAppReady() — waits only for #qt-canvas-wrapper to become visible
    • triggerBleScanAndWaitForRequestDevice() — fails fast if window.mt_startBleScan is absent, triggers the scan, then waits for requestDevice to be called (earliest reliable mock signal)
    • waitForFtmsWrite() — waits for writeValueWithResponse to be recorded; called only in the FTMS write test
  • Fail fast on missing scan hook — replaces the silent if (typeof window.mt_startBleScan === 'function') no-op with an explicit expect(...).toBeTruthy(), turning a mystery timeout into an actionable failure when the deployed build stops exporting the hook

Before / After

// Before — all 4 tests blocked on FTMS write completing
await waitForCanvas(page); // canvas visible + scan triggered + FTMS write recorded

// After — first 3 tests unblock at requestDevice; only FTMS test waits further
await waitForAppReady(page);
await triggerBleScanAndWaitForRequestDevice(page);
// ...and only in the FTMS test:
await waitForFtmsWrite(page);

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the Playwright WASM BLE API tests’ synchronization logic to avoid CI timeouts by breaking a monolithic “wait for everything” helper into smaller, scoped async helpers and only waiting for the FTMS write in the one test that needs it.

Changes:

  • Replaced waitForCanvas() with waitForAppReady() (canvas visible) plus triggerBleScanAndWaitForRequestDevice() (scan hook + earliest mock signal).
  • Added waitForFtmsWrite() and used it only in the FTMS control-point write test.
  • Made missing window.mt_startBleScan fail fast instead of silently no-op’ing and timing out.
Comments suppressed due to low confidence (1)

tests/playwright/wasm_btle_api.spec.js:127

  • waitForFtmsWrite() resolves on the first recorded writeValueWithResponse, but the comment and the test intent are specifically about the FTMS Control Point write (UUID 0x2AD9, opcode 0x00). To avoid false positives if other writes are introduced (e.g., via js_sendFtmsCommand), tighten the wait predicate to check for a matching FTMS control-point write rather than any write.
  await page.waitForFunction(
    () => {
      const calls = window._btleApiCalls;
      return calls &&
        Array.isArray(calls.writeValueWithResponse) &&
        calls.writeValueWithResponse.length > 0;
    },

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +105 to +111
// Earliest reliable signal: our injected mock recorded a requestDevice call.
await page.waitForFunction(
() => {
const calls = window._btleApiCalls;
return calls && calls.requestDeviceFilters !== null;
},
{ timeout: 45000 }
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

triggerBleScanAndWaitForRequestDevice() waits for calls.requestDeviceFilters !== null as a proxy for “requestDevice was called”, but requestDeviceFilters is initialized to null and can legitimately remain null if the app ever calls requestDevice() without filters. In that case the helper will hang until timeout rather than failing with a clear assertion. Consider recording an explicit requestDeviceCalled flag in the injected mock (or initializing requestDeviceFilters to undefined and waiting for it to become defined) and wait on that instead.

Copilot uses AI. Check for mistakes.
@MaximumTrainer
Copy link
Copy Markdown
Owner

@copilot apply changes based on the comments in this thread

…questDevice call

Agent-Logs-Url: https://github.com/MaximumTrainer/MaximumTrainer_Redux/sessions/aa9f4129-a489-477a-8b88-fd1e05db76e0

Co-authored-by: MaximumTrainer <1376575+MaximumTrainer@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 21, 2026

@copilot apply changes based on the comments in this thread

Done in 51286a2. requestDeviceFilters is now initialized to undefined (instead of null), and the wait condition changed to !== undefined. Since the mock always writes something to requestDeviceFilters when requestDevice is called (either the filters array or null for a filter-less call), the transition from undefined → defined is an unambiguous, hang-free signal that requestDevice was invoked.

Copilot AI requested a review from MaximumTrainer April 21, 2026 14:00
@MaximumTrainer MaximumTrainer marked this pull request as ready for review April 21, 2026 14:08
@MaximumTrainer MaximumTrainer merged commit 61fd18b into master Apr 21, 2026
23 of 24 checks passed
@MaximumTrainer MaximumTrainer deleted the copilot/fix-playwright-wasm-ble-api-timeout branch April 21, 2026 14:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants