Skip to content

Commit 4c6ba01

Browse files
committed
E2E: parallel workers with per-test store isolation and global auth
1 parent 14b4d78 commit 4c6ba01

20 files changed

+1783
-263
lines changed

package.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"shopify:run": "node packages/cli/bin/dev.js",
3030
"shopify": "nx build cli && node packages/cli/bin/dev.js",
3131
"test:e2e": "nx run-many --target=build --projects=cli,create-app --skip-nx-cache && pnpm --filter e2e exec playwright test",
32+
"test:e2e-cleanup": "npx tsx packages/e2e/scripts/cleanup-stores.ts && npx tsx packages/e2e/scripts/cleanup-apps.ts",
3233
"test:regenerate-snapshots": "packages/e2e/scripts/regenerate-snapshots.sh",
3334
"test": "pnpm vitest run",
3435
"type-check:affected": "nx affected --target=type-check",
@@ -143,9 +144,13 @@
143144
"unresolved": "error"
144145
},
145146
"ignoreBinaries": [
146-
"playwright"
147+
"playwright",
148+
"tsx"
149+
],
150+
"ignoreDependencies": [
151+
"dotenv",
152+
"@playwright/test"
147153
],
148-
"ignoreDependencies": [],
149154
"ignoreWorkspaces": [
150155
"packages/eslint-plugin-cli",
151156
"packages/e2e"

packages/e2e/helpers/browser-login.ts

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ async function fillSensitive(page: Page, selector: string, value: string): Promi
2424
* Completes the Shopify OAuth login flow on a Playwright page.
2525
*/
2626
export async function completeLogin(page: Page, loginUrl: string, email: string, password: string): Promise<void> {
27+
// Disable WebAuthn so passkey/security key system dialogs never appear when headed
28+
const cdp = await page.context().newCDPSession(page)
29+
await cdp.send('WebAuthn.enable', {enableUI: false})
30+
2731
await page.goto(loginUrl)
2832

2933
try {
@@ -32,10 +36,30 @@ export async function completeLogin(page: Page, loginUrl: string, email: string,
3236
await fillSensitive(page, 'input[name="account[email]"], input[type="email"]', email)
3337
await page.locator('button[type="submit"]').first().click()
3438

39+
// Handle passkey prompt — navigate to password login if needed
40+
const passwordInput = page.locator('input[name="account[password]"], input[type="password"]')
41+
const differentMethodBtn = page.locator('text=Log in using a different method')
42+
43+
// Wait for either password field or passkey page
44+
await Promise.race([
45+
passwordInput.waitFor({timeout: BROWSER_TIMEOUT.max}),
46+
differentMethodBtn.waitFor({timeout: BROWSER_TIMEOUT.max}),
47+
]).catch(() => {})
48+
49+
// If passkey page shown, navigate to password login
50+
if (await differentMethodBtn.isVisible({timeout: BROWSER_TIMEOUT.short}).catch(() => false)) {
51+
await differentMethodBtn.click()
52+
await page.waitForTimeout(BROWSER_TIMEOUT.short)
53+
54+
const continueWithPassword = page.locator('text=Continue with password')
55+
if (await continueWithPassword.isVisible({timeout: BROWSER_TIMEOUT.medium}).catch(() => false)) {
56+
await continueWithPassword.click()
57+
await page.waitForTimeout(BROWSER_TIMEOUT.short)
58+
}
59+
}
60+
3561
// Fill in password
36-
await page.waitForSelector('input[name="account[password]"], input[type="password"]', {
37-
timeout: BROWSER_TIMEOUT.max,
38-
})
62+
await passwordInput.waitFor({timeout: BROWSER_TIMEOUT.max})
3963
await fillSensitive(page, 'input[name="account[password]"], input[type="password"]', password)
4064
await page.locator('button[type="submit"]').first().click()
4165

packages/e2e/playwright.config.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ config()
88
const isCI = Boolean(process.env.CI)
99

1010
export default defineConfig({
11+
globalSetup: './setup/global-auth.ts',
1112
testDir: './tests',
12-
fullyParallel: false,
13+
fullyParallel: true,
1314
forbidOnly: isCI,
1415
retries: 0,
15-
workers: 1,
16+
workers: 5,
1617
maxFailures: isCI ? 3 : 0, // Stop early in CI after 3 failures
1718
reporter: isCI ? [['html', {open: 'never'}], ['list']] : [['list']],
1819
timeout: TEST_TIMEOUT.default, // Heavy tests override via test.setTimeout()

0 commit comments

Comments
 (0)