Skip to content

fix(frontend): stabilize WorkspaceProvisioningGate provisioning-spinner test - #345

Merged
izzywdev merged 3 commits into
masterfrom
fix/workspace-provisioning-gate-test
Jul 22, 2026
Merged

fix(frontend): stabilize WorkspaceProvisioningGate provisioning-spinner test#345
izzywdev merged 3 commits into
masterfrom
fix/workspace-provisioning-gate-test

Conversation

@izzywdev

Copy link
Copy Markdown
Owner

Problem

frontend/src/components/__tests__/WorkspaceProvisioningGate.test.tsx — the test "shows the provisioning spinner when no personal org exists yet" — fails the Lint & Test (18.x/20.x) CI job on every PR, including PRs that touch no frontend code (observed inherited from master on the frames-only PR #335).

Root cause — a test timing race, not a component bug

WorkspaceProvisioningGate deliberately has two loading states, both rendered via ProvisioningCard state="loading" (which always emits role="status"):

State Copy When
checking "Loading your workspace…" initial mount / returning user loading an existing workspace
provisioning "Creating your workspace…" first-timer, no personal org yet, actively polling

The test did:

await waitFor(() => expect(screen.getByRole('status')).toBeInTheDocument())
expect(screen.getByText('Creating your workspace…')).toBeInTheDocument()  // ← synchronous

role="status" is present in the initial checking render, so waitFor resolved immediately — before the async getOrganizations() check resolved and transitioned the gate to provisioning. The synchronous getByText('Creating your workspace…') then ran against the checking DOM ("Loading your workspace…") and threw a Testing-Library getElementError.

Fix

Component behavior is correct and intentional (the checking/provisioning copy split is deliberate — it stops returning users seeing "Creating your workspace"). The fix is in the test: wait for the provisioning-specific text to confirm the state transition, rather than the ambiguous spinner role shared by both states.

await waitFor(() => {
  expect(screen.getByText('Creating your workspace…')).toBeInTheDocument()
}, { timeout: 3000 })
expect(screen.getByRole('status')).toBeInTheDocument()
expect(screen.queryByText('App content')).not.toBeInTheDocument()

Verification

Deferring to CI (Lint & Test 18.x/20.x) as the authoritative check — a crippled local npm network + Windows node_modules corruption made a clean local vitest run infeasible in this environment. The change is test-only (+6/-2), scoped to the single racing assertion; no source or other tests are touched.

Separate from the auth-experience / signup work in flight.

🤖 Generated with Claude Code

…er test

The "shows the provisioning spinner when no personal org exists yet" test
waited for role="status" and then synchronously asserted the provisioning
copy ("Creating your workspace…"). But the gate renders a spinner
(role="status") in BOTH its initial `checking` state (returning-user copy,
"Loading your workspace…") and its `provisioning` state. The waitFor was
satisfied by the initial `checking` render, so the synchronous getByText for
the provisioning copy fired before the async org check transitioned the gate
to `provisioning`, throwing a Testing-Library getElementError. This failed
"Lint & Test (18.x/20.x)" on every PR regardless of touched files.

Fix the race in the test (component behavior is correct and intentional):
wait for the provisioning-specific text instead of the ambiguous spinner
role, then assert the spinner/absence-of-app-content.

Co-Authored-By: Claude <claude-opus-4-8> <noreply@anthropic.com>
Claude-Session-Id: a560dedc-819a-4776-bee0-3f8703ae66fe
@izzywdev izzywdev added the auto-merge Enable squash auto-merge once CI passes label Jul 21, 2026
@github-actions
github-actions Bot enabled auto-merge (squash) July 21, 2026 15:05
@github-actions

Copy link
Copy Markdown
Contributor

Automated code review (gate-code-review)

Credit balance is too low

Report-only — this check never blocks merge.

The "OIDC plumbing (local user, no Google)" job failed on master because
the browser specs drifted from the reworked login UI (migrated to
FuzeFront's Security API). The 7 API-level tests pass; the 3 browser
tests asserted removed behaviour:

- Native credentials form now posts POST /api/v1/security/session
  (authAPI.login), not the old /api/auth/oidc/password. Point the
  waitForResponse at the current endpoint.
- The dedicated "Sign in with Authentik" redirect button was removed;
  the only redirect entry point is the Google button
  (-> /api/v1/security/social/google/start). In no-Google mode
  (empty GOOGLE_CLIENT_ID) a full interactive Authentik round-trip is
  unreachable, so the old full-OIDC-via-button test can't pass. Replace
  it with one asserting the button initiates the server-brokered social
  start. The real server-side OIDC token exchange against Authentik is
  still covered end-to-end by the passing API-level password test, and
  interactive social is covered by the separate tunnel-mode Google e2e.
  Remove the now-unused Authentik login-form helper.
- Error-display test hit a Playwright strict-mode violation (the error
  surfaces in 2 elements); scope the locator to .first().

Test-only change; no app code touched (no regression found — the app
behaviour the specs now assert is the current, intended behaviour).

Co-Authored-By: Claude <claude-opus-4-8> <noreply@anthropic.com>
Claude-Session-Id: a560dedc-819a-4776-bee0-3f8703ae66fe
@github-actions

Copy link
Copy Markdown
Contributor

Automated code review (gate-code-review)

Credit balance is too low

Report-only — this check never blocks merge.

@izzywdev
izzywdev merged commit 619dc77 into master Jul 22, 2026
35 of 36 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

Automated code review (gate-code-review)

Credit balance is too low

Report-only — this check never blocks merge.

@izzywdev
izzywdev deleted the fix/workspace-provisioning-gate-test branch July 22, 2026 15:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auto-merge Enable squash auto-merge once CI passes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant