Skip to content

Commit d825361

Browse files
committed
test: resolve issues
1 parent 9d14c22 commit d825361

File tree

6 files changed

+46
-60
lines changed

6 files changed

+46
-60
lines changed

playwright.config.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@ export default defineConfig<ConfigOptions>({
1818
reuseExistingServer: false,
1919
timeout: 60_000,
2020
},
21-
// Start/stop mock connector server before/after all tests
21+
// Start/stop mock connector server before/after all tests (teardown via returned closure)
2222
globalSetup: fileURLToPath(new URL('./test/e2e/global-setup.ts', import.meta.url)),
23-
globalTeardown: fileURLToPath(new URL('./test/e2e/global-teardown.ts', import.meta.url)),
2423
// We currently only test on one browser on one platform
2524
snapshotPathTemplate: '{snapshotDir}/{testFileDir}/{testFileName}-snapshots/{arg}{ext}',
2625
use: {

test/e2e/connector.spec.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,16 @@
33
*
44
* These tests use a mock connector server (started in global setup)
55
* to test features that require being logged in via the connector.
6+
*
7+
* All tests run serially because they share a single mock connector server
8+
* whose state is reset before each test via `mockConnector.reset()`.
69
*/
710

811
import type { Page } from '@playwright/test'
912
import { test, expect } from './helpers/fixtures'
1013

14+
test.describe.configure({ mode: 'serial' })
15+
1116
/**
1217
* When connected, the header shows "packages" and "orgs" links scoped to the user.
1318
* This helper waits for the packages link to appear as proof of successful connection.

test/e2e/global-setup.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,33 @@
11
/**
22
* Playwright global setup - starts the mock connector server before all tests.
3+
*
4+
* Returns an async teardown function (Playwright's recommended pattern for
5+
* sharing state between setup and teardown via closure).
36
*/
47

58
import { MockConnectorServer, DEFAULT_TEST_CONFIG } from './helpers/mock-connector'
69

7-
let mockServer: MockConnectorServer | null = null
8-
910
export default async function globalSetup() {
1011
console.log('[Global Setup] Starting mock connector server...')
1112

12-
mockServer = new MockConnectorServer(DEFAULT_TEST_CONFIG)
13+
const mockServer = new MockConnectorServer(DEFAULT_TEST_CONFIG)
1314

1415
try {
1516
await mockServer.start()
1617
console.log(`[Global Setup] Mock connector ready at http://127.0.0.1:${mockServer.port}`)
1718
console.log(`[Global Setup] Test token: ${mockServer.token}`)
18-
19-
// Store the server instance for global teardown
20-
;(globalThis as Record<string, unknown>).__mockConnectorServer = mockServer
2119
} catch (error) {
2220
console.error('[Global Setup] Failed to start mock connector:', error)
2321
throw error
2422
}
23+
24+
// Return teardown function — Playwright calls this after all tests complete
25+
return async () => {
26+
console.log('[Global Teardown] Stopping mock connector server...')
27+
try {
28+
await mockServer.stop()
29+
} catch (error) {
30+
console.error('[Global Teardown] Error stopping mock connector:', error)
31+
}
32+
}
2533
}

test/e2e/global-teardown.ts

Lines changed: 0 additions & 24 deletions
This file was deleted.

test/e2e/helpers/fixtures.ts

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -81,20 +81,33 @@ export class MockConnectorClient {
8181
...options?.headers,
8282
},
8383
})
84+
if (!response.ok) {
85+
throw new Error(
86+
`Mock connector request failed: ${response.status} ${response.statusText} (${path})`,
87+
)
88+
}
8489
return response.json() as Promise<T>
8590
}
8691

87-
/** Reset the mock connector state */
88-
async reset(): Promise<void> {
89-
// Reset state via test endpoint (no auth required)
90-
await fetch(`${this.baseUrl}/__test__/reset`, { method: 'POST' })
91-
92-
// Connect to establish session
93-
await fetch(`${this.baseUrl}/connect`, {
92+
/** Make a fire-and-forget POST to a test-only endpoint, throwing on failure. */
93+
private async testEndpoint(path: string, body: unknown): Promise<void> {
94+
const response = await fetch(`${this.baseUrl}${path}`, {
9495
method: 'POST',
9596
headers: { 'Content-Type': 'application/json' },
96-
body: JSON.stringify({ token: this.token }),
97+
body: JSON.stringify(body),
9798
})
99+
if (!response.ok) {
100+
throw new Error(
101+
`Mock connector test endpoint failed: ${response.status} ${response.statusText} (${path})`,
102+
)
103+
}
104+
}
105+
106+
/** Reset the mock connector state */
107+
async reset(): Promise<void> {
108+
await this.testEndpoint('/__test__/reset', {})
109+
// Connect to establish session
110+
await this.testEndpoint('/connect', { token: this.token })
98111
}
99112

100113
/** Set org data */
@@ -106,41 +119,25 @@ export class MockConnectorClient {
106119
teamMembers?: Record<string, string[]>
107120
},
108121
): Promise<void> {
109-
await fetch(`${this.baseUrl}/__test__/org`, {
110-
method: 'POST',
111-
headers: { 'Content-Type': 'application/json' },
112-
body: JSON.stringify({ org, ...data }),
113-
})
122+
await this.testEndpoint('/__test__/org', { org, ...data })
114123
}
115124

116125
/** Set user orgs */
117126
async setUserOrgs(orgs: string[]): Promise<void> {
118-
await fetch(`${this.baseUrl}/__test__/user-orgs`, {
119-
method: 'POST',
120-
headers: { 'Content-Type': 'application/json' },
121-
body: JSON.stringify({ orgs }),
122-
})
127+
await this.testEndpoint('/__test__/user-orgs', { orgs })
123128
}
124129

125130
/** Set user packages */
126131
async setUserPackages(packages: Record<string, 'read-only' | 'read-write'>): Promise<void> {
127-
await fetch(`${this.baseUrl}/__test__/user-packages`, {
128-
method: 'POST',
129-
headers: { 'Content-Type': 'application/json' },
130-
body: JSON.stringify({ packages }),
131-
})
132+
await this.testEndpoint('/__test__/user-packages', { packages })
132133
}
133134

134135
/** Set package data */
135136
async setPackageData(
136137
pkg: string,
137138
data: { collaborators?: Record<string, 'read-only' | 'read-write'> },
138139
): Promise<void> {
139-
await fetch(`${this.baseUrl}/__test__/package`, {
140-
method: 'POST',
141-
headers: { 'Content-Type': 'application/json' },
142-
body: JSON.stringify({ package: pkg, ...data }),
143-
})
140+
await this.testEndpoint('/__test__/package', { package: pkg, ...data })
144141
}
145142

146143
/** Add an operation */

test/e2e/helpers/mock-connector.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,7 @@ export class MockConnectorServer {
523523
const port = this.stateManager.port
524524

525525
this.server!.on('error', (err: NodeJS.ErrnoException) => {
526+
this.server = null
526527
if (err.code === 'EADDRINUSE') {
527528
reject(new Error(`Port ${port} is already in use. Is the real connector running?`))
528529
} else {

0 commit comments

Comments
 (0)