Skip to content

Hold a test waiter across a sign-in - #6144

Open
habdelra wants to merge 2 commits into
mainfrom
flaky-profile-deep-link-login
Open

habdelra wants to merge 2 commits into
mainfrom
flaky-profile-deep-link-login

Conversation

@habdelra

@habdelra habdelra commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Acceptance | operator mode tests > account popover: a deep link arriving logged out waits for login, then opens the modal fails in host CI with Element [data-test-settings-modal] does not exist, on branches whose diff cannot reach it.

What the test waits on

The test signs out, arrives on /?openProfileSettings=subscription, fills the login form and clicks Sign In, then asserts the profile settings modal is open. await click('[data-test-login-btn]') is the entire wait.

settled() cannot span that sign-in. Two things leave it uncovered:

  • The button performs an ember-concurrency task, and ember-concurrency 5 ships no @ember/test-waiters integration, so the task itself is invisible.
  • The boot it awaits, MatrixService.start(), is held only in stretches. The app's own requests carry the fetcher waiter and each realm session mint carries realm:session-login — but the matrix client is built without a fetchFn, so its traffic (getDevice, the getAccountDataFromServer calls, initSlidingSync, startClient, setSystemCard) bypasses both, as do the seams between adjacent held segments.

So click() returns as soon as a poll lands in one of those gaps and the assertions run against an app still rendering <Auth />. That shape explains why the failure reads as deterministic on a given runner rather than as a coin flip: whether the poller wins is decided by how long the boot takes there.

The deep link itself is fine. The route consumes the request at fixed points in the transition, and the failing job's browser log shows it doing so — the [start-phase] … sequence ending in postLoginCompleted=true and then [profile-deep-link] opening settings on subscription, both landing after the assertion and immediately before the teardown resetState(). The modal opens; the test just read the DOM first.

The change

MatrixService holds a @ember/test-waiters waiter across the credential exchange — password and token hand-off alike — and across the whole boot. settled() then spans a sign-in from the click through to the render that follows the route refresh, for every caller: the login form, the SSO hand-off, registration, and the boot from persisted auth. buildWaiter compiles to a no-op outside a debug build, so production behavior is unchanged.

Two tests make the waiter's absence visible, since the acceptance test alone only goes red when a runner happens to be slow enough:

Test Fails when
Integration | Component | matrix/login: a render settles only once the token exchange has finished the exchange's acquisition is removed
Integration | matrix-service | re-login after logout: a boot in flight holds settled() open the boot's acquisition is removed

The deep-link test's modal assertion carries the session's readiness, whether the request was acted on, and whether the URL still holds it, so a future failure names which of the three stages is missing instead of restating the symptom. The snapshot is guarded, so a diagnostic that cannot be read reports that rather than throwing out of the failure it exists to explain.

Verification

Local stack, ember test --path dist.

Reproduction control — one build carrying a 400ms untracked delay inside the boot, which is the shape of the gap:

Result
delay, no waiter not okElement [data-test-settings-modal] does not exist, the same assertion and stack frame the CI job reports. The next test fails too, on the previous test's boot leaking into it
delay + waiter 12/12

Positive control for the two new tests — one build with all three waiter acquisitions removed: both go red and nothing else in their modules moves. Restored, both pass.

Without any injection:

  • account popover module: 12/12, three runs.
  • Full Acceptance | operator mode tests file: 26/26, three runs.
  • Integration | matrix-service | * 37/37, Integration | Component | matrix/login 10/10, Integration | ai-assistant-panel | re-login, Integration | workspace-chooser | unreachable realm server notice — all pass.
  • eslint and ember-tsc --noEmit clean for packages/host.

🤖 Generated with Claude Code

`settled()` has no visibility into a sign-in. The sign-in button performs an
ember-concurrency task, ember-concurrency carries no `@ember/test-waiters`
integration, and the boot that task awaits is a plain promise chain until its
closing router refresh — so a test that clicks Sign In can resume on an app
that is still logged out and assert against the login form.

MatrixService now holds a waiter across the credential exchange and across the
whole boot, so `settled()` spans a sign-in from the click through to the render
that follows the route refresh. `buildWaiter` compiles to a no-op outside a
debug build.

The profile deep-link test reports the session's readiness, whether the request
was acted on, and whether the URL still carries it, so a failure names the
stage rather than the symptom.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 16, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-16T00:05:13.684845Z 5f1c0cf PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@habdelra
habdelra requested a review from a team September 16, 2026 00:04
The sign-in waiter covered the password exchange and the boot but not
`loginWithSsoToken` — the credential exchange for the token hand-off, which the
login component performs from an ember-concurrency task on exactly the same
terms. It is held now, so what the comment says about the credential exchange
is true of both.

Two tests make the waiter's absence visible: a render settles only once the
token exchange has finished, and a boot in flight leaves the waiter pending.
Each one fails when its acquisition is removed.

The waiter's comment described the boot as a plain promise chain. It is not:
the app's own requests carry the `fetcher` waiter and realm session mints carry
`realm:session-login`. What goes unheld is the matrix client's own traffic,
which bypasses both because the client is built without a `fetchFn`.

The deep-link diagnostic no longer throws out of the failure it explains, and
keeps qunit-dom's element name in the headline.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Preview deployments

Host Test Results

    1 files      1 suites   2h 16m 9s ⏱️
4 836 tests 4 822 ✅ 14 💤 0 ❌
4 851 runs  4 837 ✅ 14 💤 0 ❌

Results for commit 47a972b.

Realm Server Test Results

    1 files    226 suites   1h 18m 51s ⏱️
3 109 tests 3 109 ✅ 0 💤 0 ❌
3 155 runs  3 155 ✅ 0 💤 0 ❌

Results for commit 47a972b.

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.

2 participants