forked from
npmx.dev/npmx.dev
[READ-ONLY]
a fast, modern browser for the npm registry
1/**
2 * Playwright fixtures for connector E2E tests. Extends test-utils.ts
3 * (which includes external API mocking) with connector-specific helpers.
4 */
5
6import { test as base } from '../test-utils'
7import { DEFAULT_MOCK_CONFIG } from './mock-connector'
8
9const TEST_TOKEN = DEFAULT_MOCK_CONFIG.token
10const TEST_PORT = DEFAULT_MOCK_CONFIG.port ?? 31415
11
12/**
13 * Helper to make requests to the mock connector server.
14 * This allows tests to set up state before running.
15 */
16export class MockConnectorClient {
17 private token: string
18 private baseUrl: string
19
20 constructor(token: string, port: number) {
21 this.token = token
22 this.baseUrl = `http://127.0.0.1:${port}`
23 }
24
25 private async request<T>(path: string, options?: RequestInit): Promise<T> {
26 const response = await fetch(`${this.baseUrl}${path}`, {
27 ...options,
28 headers: {
29 'Content-Type': 'application/json',
30 'Authorization': `Bearer ${this.token}`,
31 ...options?.headers,
32 },
33 })
34 if (!response.ok) {
35 throw new Error(
36 `Mock connector request failed: ${response.status} ${response.statusText} (${path})`,
37 )
38 }
39 return response.json() as Promise<T>
40 }
41
42 private async testEndpoint(path: string, body: unknown): Promise<void> {
43 const response = await fetch(`${this.baseUrl}${path}`, {
44 method: 'POST',
45 headers: { 'Content-Type': 'application/json' },
46 body: JSON.stringify(body),
47 })
48 if (!response.ok) {
49 throw new Error(
50 `Mock connector test endpoint failed: ${response.status} ${response.statusText} (${path})`,
51 )
52 }
53 }
54
55 async reset(): Promise<void> {
56 await this.testEndpoint('/__test__/reset', {})
57 await this.testEndpoint('/connect', { token: this.token })
58 }
59
60 async setOrgData(
61 org: string,
62 data: {
63 users?: Record<string, 'developer' | 'admin' | 'owner'>
64 teams?: string[]
65 teamMembers?: Record<string, string[]>
66 },
67 ): Promise<void> {
68 await this.testEndpoint('/__test__/org', { org, ...data })
69 }
70
71 async setUserOrgs(orgs: string[]): Promise<void> {
72 await this.testEndpoint('/__test__/user-orgs', { orgs })
73 }
74
75 async setUserPackages(packages: Record<string, 'read-only' | 'read-write'>): Promise<void> {
76 await this.testEndpoint('/__test__/user-packages', { packages })
77 }
78
79 async setPackageData(
80 pkg: string,
81 data: { collaborators?: Record<string, 'read-only' | 'read-write'> },
82 ): Promise<void> {
83 await this.testEndpoint('/__test__/package', { package: pkg, ...data })
84 }
85
86 async addOperation(operation: {
87 type: string
88 params: Record<string, string>
89 description: string
90 command: string
91 dependsOn?: string
92 }): Promise<{ id: string; status: string }> {
93 const result = await this.request<{ success: boolean; data: { id: string; status: string } }>(
94 '/operations',
95 {
96 method: 'POST',
97 body: JSON.stringify(operation),
98 },
99 )
100 return result.data
101 }
102
103 async getOperations(): Promise<
104 Array<{ id: string; type: string; status: string; params: Record<string, string> }>
105 > {
106 const result = await this.request<{
107 success: boolean
108 data: {
109 operations: Array<{
110 id: string
111 type: string
112 status: string
113 params: Record<string, string>
114 }>
115 }
116 }>('/state')
117 return result.data.operations
118 }
119}
120
121export interface ConnectorFixtures {
122 mockConnector: MockConnectorClient
123 testToken: string
124 connectorPort: number
125 /** Navigate to a page pre-authenticated with connector credentials. */
126 gotoConnected: (path: string) => Promise<void>
127}
128
129export const test = base.extend<ConnectorFixtures>({
130 mockConnector: async ({ page: _ }, use) => {
131 const client = new MockConnectorClient(TEST_TOKEN, TEST_PORT)
132 await client.reset()
133 await use(client)
134 },
135
136 testToken: TEST_TOKEN,
137
138 connectorPort: TEST_PORT,
139
140 gotoConnected: async ({ goto, testToken, connectorPort }, use) => {
141 const navigateConnected = async (path: string) => {
142 const cleanPath = path.startsWith('/') ? path : `/${path}`
143 const separator = cleanPath.includes('?') ? '&' : '?'
144 const urlWithParams = `${cleanPath}${separator}token=${testToken}&port=${connectorPort}`
145 await goto(urlWithParams, { waitUntil: 'networkidle' })
146 }
147 await use(navigateConnected)
148 },
149})
150
151export { expect } from '@nuxt/test-utils/playwright'