Skip to content

test(e2e): cover runtime picker → login → onboarding → logout#1982

Merged
senamakel merged 4 commits into
tinyhumansai:mainfrom
senamakel:test/runtime-picker-login
May 17, 2026
Merged

test(e2e): cover runtime picker → login → onboarding → logout#1982
senamakel merged 4 commits into
tinyhumansai:mainfrom
senamakel:test/runtime-picker-login

Conversation

@senamakel
Copy link
Copy Markdown
Member

@senamakel senamakel commented May 17, 2026

Summary

  • New WDIO/CEF e2e spec at app/test/e2e/specs/runtime-picker-login.spec.ts (8 cases, ~12 s on Linux Docker) exercising the first-launch login funnel end-to-end.
  • Walks the BootCheckGate ModePicker branches: option visibility, cloud URL/token validation, "Test Connection" against an unreachable host, and switching back to Local.
  • Then drives the post-OAuth deep-link callback (no system browser), onboarding walkthrough, Home reach, and logout-back-to-Welcome.
  • All flows hit the shared mock backend (scripts/mock-api-*); deep links go through window.__simulateDeepLink so the spec is safe on headless Linux containers.

Problem

Existing specs cover the auth deep-link path (login-flow.spec.ts) and a logout-relogin regression (logout-relogin-onboarding.spec.ts), but the first screen — the local-vs-cloud runtime picker — has no e2e coverage. A regression in BootCheckGate could silently brick onboarding for fresh installs without CI noticing.

Solution

  • Uses the existing Appium chromium-driver + CEF/CDP harness (the one wired into e2e/docker-compose.yml), so no new infra.
  • Surfaces the picker mid-session by clicking Welcome's "Select a Runtime" (which dispatches resetCoreMode()), since the e2e build seeds VITE_OPENHUMAN_E2E_DEFAULT_CORE_MODE=local and would otherwise skip it.
  • Adds two small inline helpers (clickByTextDom with smallest-descendant scoring, fillInput with React-aware setter) so tile buttons whose textContent concatenates title+description still match.
  • Home detection falls back to a route + welcome-gone check instead of greeting strings — survives copy churn.

Verified locally on Linux Docker (docker compose -f e2e/docker-compose.yml run --rm e2e ...): 8 passing, 0 failing.

Submission Checklist

  • Tests added or updated (happy path + at least one failure / edge case) per Testing Strategy
  • N/A: changed-line coverage gate — PR only adds an e2e spec file; no production source lines change.
  • N/A: coverage matrix unchanged — no feature added/removed/renamed; this is an e2e-only regression test for an existing feature (BootCheckGate ModePicker).
  • N/A: no new feature IDs introduced.
  • No new external network dependencies introduced (mock backend used per Testing Strategy)
  • N/A: release-cut smoke surfaces untouched — spec-only change.
  • N/A: no issue linked.

Impact

  • Runtime/platform impact: desktop e2e only — adds one spec to the Linux WDIO suite. No production code changes, no shipped-binary behavior change.
  • CI cost: ~12 s of extra wall time on the Linux e2e job (build cost unchanged — uses the existing built bundle).
  • No performance, security, migration, or compatibility implications.

Related

  • Closes:
  • Follow-up PR(s)/TODOs:

AI Authored PR Metadata (required for Codex/Linear PRs)

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: `test/runtime-picker-login`
  • Commit SHA: 8c800d2

Validation Run

  • `pnpm --filter openhuman-app format:check` (ran via pre-push hook; auto-fixes committed in 8c800d2)
  • N/A: `pnpm typecheck` — no TS source changes outside the `@ts-nocheck` spec
  • Focused tests: `docker compose -f e2e/docker-compose.yml run --rm e2e ...` → 8 passing, 0 failing
  • N/A: Rust fmt/check — no Rust changes
  • N/A: Tauri fmt/check — no Tauri shell changes

Validation Blocked

  • command: N/A
  • error: N/A
  • impact: N/A

Behavior Changes

  • Intended behavior change: none (test-only)
  • User-visible effect: none

Parity Contract

  • Legacy behavior preserved: N/A — no behavioral change
  • Guard/fallback/dispatch parity checks: N/A

Duplicate / Superseded PR Handling

  • Duplicate PR(s): N/A
  • Canonical PR: N/A
  • Resolution: N/A

Summary by CodeRabbit

  • Tests
    • Added comprehensive end-to-end test coverage for the login flow, runtime configuration selection, and logout workflows to validate critical user journeys.

Review Change Stack

senamakel added 3 commits May 16, 2026 19:06
Exercises the first-launch funnel end-to-end against the mock server:
BootCheckGate picker (local + cloud branches, validation, test-connection),
post-OAuth deep-link callback, onboarding walk-through, Home reach, and
logout back to Welcome. Runs on the existing Appium chromium-driver +
CEF/CDP harness used by e2e/docker-compose.yml on Linux.
- clickByTextDom matched on exact text equality; tile buttons concatenate
  their title+description in textContent so the strict match never fired.
  Switch to includes() + smallest-descendant scoring so we click the most
  specific match (the option tile / form button, not its body ancestor).
- Replace hardcoded greeting-string home check with a route + 'welcome
  gone' fallback so post-onboarding Home detection survives copy churn.
@senamakel senamakel requested a review from a team May 17, 2026 02:55
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 17, 2026

📝 Walkthrough

Walkthrough

Adds a new E2E spec that drives Welcome → runtime picker (Cloud/Local validation) → OAuth deep-link login → optional onboarding → Home, then logs out; includes browser-executed helpers and mock-server assertions.

Changes

Runtime Picker and OAuth E2E Test

Layer / File(s) Summary
Test infrastructure and helper utilities
app/test/e2e/specs/runtime-picker-login.spec.ts
Test doc comment, imports for helpers/mock control, LOG constant, and browser helpers clickByTextDom, fillInput, and openRuntimePicker.
Test lifecycle and initial state
app/test/e2e/specs/runtime-picker-login.spec.ts
describe suite with before/after hooks to start/stop mock server, reset mocks, reset app with skipAuth: true, clear logs; asserts Welcome renders with OAuth provider context and "Select a Runtime".
Runtime picker interaction and validation
app/test/e2e/specs/runtime-picker-login.spec.ts
Opens BootCheckGate picker, verifies Local and Cloud tiles, Cloud branch shows URL/token fields and inline URL/token validation, exercises "Test Connection" until unreachable/auth-failure is observed, then selects Local and waits for picker dismissal returning to logged-out Welcome.
OAuth provider rendering and deep-link authentication
app/test/e2e/specs/runtime-picker-login.spec.ts
Asserts provider buttons on Welcome, clears request logs, triggers triggerAuthDeepLinkBypass, waits for app/webview readiness and auth bootstrap, asserts GET /auth/me recorded by mock server, conditionally walks onboarding, and verifies Home via waitForHomePage (hash fallback supported).
Logout and return to Welcome
app/test/e2e/specs/runtime-picker-login.spec.ts
Logs out through Settings, asserts Welcome is shown again, and re-checks visibility of the "Select a Runtime" entry point.

Sequence Diagram(s)

sequenceDiagram
  participant Browser as Browser/App
  participant MockServer as Mock Server
  participant DeepLink as DeepLink Trigger
  participant Onboarding as Onboarding Flow
  Browser->>Browser: Show Welcome with OAuth providers & runtime selector
  Browser->>Browser: Open BootCheckGate runtime picker
  Browser->>Browser: Display Cloud and Local option tiles
  Browser->>Browser: Show URL & token inputs for Cloud
  Browser->>MockServer: Test Connection -> unreachable/auth-failure polling
  DeepLink->>Browser: triggerAuthDeepLinkBypass (OAuth callback)
  Browser->>MockServer: GET /auth/me
  MockServer-->>Browser: auth response
  Browser->>Onboarding: optionally walk onboarding
  Onboarding-->>Browser: complete
  Browser->>Browser: Navigate to Home
  Browser->>Browser: Logout via Settings -> return to Welcome
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

working

Poem

🐰 A rabbit hops through Welcome's gate,
Clicks runtimes, taps the Cloud tile straight,
Deep-link whispers OAuth's song,
Onboarding hums—Home won't stay long,
Logout bounces back to the runtime slate.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title clearly summarizes the main change: adding a comprehensive E2E test spec covering the runtime picker, login, onboarding, and logout flows. The title is concise, specific, and directly reflects the primary objective of the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
app/test/e2e/specs/runtime-picker-login.spec.ts (1)

267-278: ⚡ Quick win

Add diagnostics around the provider-button probe.

If this assertion fails in CI, it currently produces a bare boolean failure with no tree or button-label context, unlike the other brittle steps in this spec.

Proposed fix
-    const providerButtonPresent = await browser.execute(() => {
+    const providerLabels = await browser.execute(() => {
       const buttons = Array.from(document.querySelectorAll('button'));
-      return buttons.some(b => {
-        const label = b.getAttribute('aria-label') || b.textContent || '';
-        return /Google|GitHub|Twitter|Discord/i.test(label);
-      });
+      return buttons
+        .map(b => (b.getAttribute('aria-label') || b.textContent || '').trim())
+        .filter(Boolean);
     });
+    const providerButtonPresent = providerLabels.some(label =>
+      /Google|GitHub|Twitter|Discord/i.test(label)
+    );
+    if (!providerButtonPresent) {
+      const tree = await dumpAccessibilityTree();
+      console.log(`${LOG} Provider buttons not found. Labels:`, providerLabels);
+      console.log(`${LOG} Tree:\n`, tree.slice(0, 4000));
+    }
     expect(providerButtonPresent).toBe(true);

As per coding guidelines "Ensure each E2E spec is runnable in isolation; assert both UI outcomes and backend/mock effects when relevant; add failure diagnostics (request logs, dumpAccessibilityTree()) for faster debugging".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/test/e2e/specs/runtime-picker-login.spec.ts` around lines 267 - 278,
Update the "OAuth provider buttons render on Welcome" test to collect and report
diagnostics when the provider probe fails: change the probe that sets
providerButtonPresent to instead return an object with matched boolean plus
arrays of matchedLabels and allButtonLabels (from
document.querySelectorAll('button')), and in the test assert on the boolean but
on failure log matchedLabels, allButtonLabels and call dumpAccessibilityTree()
(or otherwise serialize the DOM/tree) so CI failures include the button labels
and accessibility tree for debugging; reference the providerButtonPresent
variable and the test name when making the changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/test/e2e/specs/runtime-picker-login.spec.ts`:
- Around line 291-295: The check around waitForRequest for '/auth/me' needs to
ensure null fails the test: change the guard to explicitly handle null (using
meCall === null) and call fail() or throw, and update the assertion to
expect(meCall).not.toBeNull() (or expect(meCall).toBeTruthy()) so a null
response does not pass; target the meCall variable returned from
waitForRequest(getRequestLog, 'GET', '/auth/me', 20_000) and include the
existing logging via getRequestLog() when failing.

---

Nitpick comments:
In `@app/test/e2e/specs/runtime-picker-login.spec.ts`:
- Around line 267-278: Update the "OAuth provider buttons render on Welcome"
test to collect and report diagnostics when the provider probe fails: change the
probe that sets providerButtonPresent to instead return an object with matched
boolean plus arrays of matchedLabels and allButtonLabels (from
document.querySelectorAll('button')), and in the test assert on the boolean but
on failure log matchedLabels, allButtonLabels and call dumpAccessibilityTree()
(or otherwise serialize the DOM/tree) so CI failures include the button labels
and accessibility tree for debugging; reference the providerButtonPresent
variable and the test name when making the changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 24e65d88-8a34-460d-b4bf-831c60a76ee9

📥 Commits

Reviewing files that changed from the base of the PR and between 3b24821 and 8c800d2.

📒 Files selected for processing (1)
  • app/test/e2e/specs/runtime-picker-login.spec.ts

Comment thread app/test/e2e/specs/runtime-picker-login.spec.ts Outdated
waitForRequest returns null on timeout, which toBeDefined would still
pass. toBeTruthy correctly fails the case where the auth profile fetch
never happened. (CodeRabbit)
@coderabbitai coderabbitai Bot added the working A PR that is being worked on by the team. label May 17, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
app/test/e2e/specs/runtime-picker-login.spec.ts (1)

1-1: ⚖️ Poor tradeoff

Consider removing @ts-nocheck in favor of targeted type fixes or ignores.

Blanket suppression can mask real type errors. For browser.execute callbacks, consider either:

  • Adding explicit type parameters to browser.execute<ReturnType, ArgsType>()
  • Using targeted // @ts-expect-error`` on specific lines that resist typing

This improves maintainability as the test evolves.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/test/e2e/specs/runtime-picker-login.spec.ts` at line 1, Remove the
top-level "// `@ts-nocheck`" and instead address the specific type issues: replace
the blanket suppression with targeted fixes by adding explicit generics to any
browser.execute calls (e.g., browser.execute<ReturnType, ArgsType>(...)) and/or
apply narrow inline suppressions like "// `@ts-expect-error`" only on the exact
lines that cannot be typed; search for browser.execute usages in this spec
(runtime-picker-login.spec.ts) and update their signatures with appropriate
ReturnType and ArgsType or add line-level comments to preserve type checking
elsewhere.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@app/test/e2e/specs/runtime-picker-login.spec.ts`:
- Line 1: Remove the top-level "// `@ts-nocheck`" and instead address the specific
type issues: replace the blanket suppression with targeted fixes by adding
explicit generics to any browser.execute calls (e.g.,
browser.execute<ReturnType, ArgsType>(...)) and/or apply narrow inline
suppressions like "// `@ts-expect-error`" only on the exact lines that cannot be
typed; search for browser.execute usages in this spec
(runtime-picker-login.spec.ts) and update their signatures with appropriate
ReturnType and ArgsType or add line-level comments to preserve type checking
elsewhere.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e9c78dd6-6647-4028-b6d0-535c4a1600b9

📥 Commits

Reviewing files that changed from the base of the PR and between 8c800d2 and 60891bb.

📒 Files selected for processing (1)
  • app/test/e2e/specs/runtime-picker-login.spec.ts

@senamakel senamakel merged commit 5f15fc1 into tinyhumansai:main May 17, 2026
25 of 28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

working A PR that is being worked on by the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant