feat: add E2E integration tests with WorkOS emulator#399
Draft
feat: add E2E integration tests with WorkOS emulator#399
Conversation
Uses the programmatic `createEmulator()` API from the WorkOS CLI to stand up a local WorkOS backend, then runs the example Next.js app against it. Tests cover the full auth lifecycle: unauthenticated state, sign-in via the emulator's auto-auth flow, protected page access, account details rendering, and sign-out with session clearing. The e2e/ directory is its own workspace package to isolate @playwright/test from the examples (Next.js 16 declares it as an optional peer dep, causing conflicting type resolutions). Tests are parameterized via E2E_APPS env var so the same suite can run against examples/next or examples/vinext.
- Move .env.local aside during tests so emulator env vars take precedence; restore in globalTeardown - Use vinext dev mode (vinext start has an RSC entry bug) - Skip auth-flow tests for vinext — its redirect() shim doesn't propagate Set-Cookie headers, breaking the PKCE cookie chain - Unauthenticated tests (home page, /account protection) pass on both
Error handling tests: - Corrupt session cookie gracefully degrades to unauthenticated - Corrupt cookie on protected page doesn't crash - Callback with missing params returns error page - Callback with invalid code returns error page Session management tests: - Session persists across page navigations - Session isolation between browser contexts (incognito) - Session cookie has expected name and httpOnly flag Client-side hook tests: - useAuth resolves to unauthenticated state after hydration - useAuth reflects authenticated state after sign-in - useAuth updates after sign-out
… E2E tests New tests: - Impersonation banner renders with seeded impersonator data - Stop impersonation button ends session - Token refresh via /test-refresh route returns updated session - Session remains valid after refresh - Org switching via /test-switch-org completes without error - Session remains valid after org switch - login_hint selects a specific seeded user - Different users see different account details - Sessions isolated between users in separate browser contexts Example app changes: - Login route accepts ?login_hint= query param - Added /test-refresh route (calls refreshSession) - Added /test-switch-org route (calls switchToOrganization) - Updated middleware matcher for new test routes Seed now includes impersonator data on first user, a second user (other@example.com), and a "Test Organization" for org switching.
The emulator now reads organization_id from the request body during refresh_token exchange, so switchToOrganization properly sets the org context on the session.
Add /client page to Next.js example (modeled after tanstack-start) with useAuth, useAccessToken, and org switching UI. Rewrite client-hooks and org-switching E2E tests to exercise the actual client page instead of test-only route handlers. New client page features: - Session info display (sessionId, organizationId, role, permissions) - Impersonator indicator - Access token status with refresh button - Organization switching with text input - Client-side sign out Updated tests: - client-hooks tests now use /client page - org-switching tests include client page UI test - Restored sign-out workarounds (emulator logout needs full URL for returnTo)
Replace bare-bones client page with full-featured version matching the tanstack-start example. Adds useAuth/useAccessToken display, org switching UI, and Client Demo nav link. Updates E2E tests.
The Refresh Token button was silently catching errors and only logging to console. Now shows success/error callout in the UI so failures are visible. Updates E2E test to assert the success message appears.
Delete /test-refresh and /test-switch-org route handlers. All token refresh, org switching, and client hook tests now exercise the real client page UI. No test-only code in the example app.
Replace link:../../cli/main with workos@beta from npm so the E2E tests can run in CI without the local CLI checkout.
Runs Playwright E2E tests against the Next.js example app with the WorkOS emulator on every push/PR. Uploads test results as artifacts on failure.
814b11a to
7b9f365
Compare
Playwright requires empty destructure ({}) as first arg in fixtures.
Exclude e2e/ from oxlint rather than fighting the pattern.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
workosCLI's emulator (workos@beta), proving the full auth lifecycle works end-to-end without a real WorkOS backenduseAuth(),useAccessToken(), org switching, and client-side sign outlogin_hintsupport to the example login route for multi-user testingTest Coverage (27 tests)
How it works
The
e2e/directory is its own workspace package (isolates@playwright/testfrom Next.js peer dep conflicts). Tests usecreateEmulator()fromworkos/emulateto start a local WorkOS backend with seeded users, orgs, and impersonation data. The emulator's authorize endpoint auto-selects the first seeded user (or a specific user vialogin_hint), enabling fully automated auth flows with no UI interaction.Test plan
pnpm test— 332 unit tests passpnpm test:e2e:next— 27 E2E tests passpnpm run buildsucceeds