stably 4.9.0 → 4.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +1 -1
- package/dist/stably-plugin-cli/.claude-plugin/plugin.json +5 -0
- package/dist/stably-plugin-cli/skills/bash-commands/SKILL.md +65 -0
- package/dist/stably-plugin-cli/skills/browser-interaction-guide/SKILL.md +144 -0
- package/dist/stably-plugin-cli/skills/bulk-test-handling/SKILL.md +104 -0
- package/dist/stably-plugin-cli/skills/debugging-test-failures/SKILL.md +146 -0
- package/dist/{stably-plugin → stably-plugin-cli}/skills/playwright-best-practices/SKILL.md +11 -5
- package/dist/stably-plugin-cli/skills/playwright-config-auth/SKILL.md +217 -0
- package/dist/stably-plugin-cli/skills/stably-sdk-reference/SKILL.md +307 -0
- package/dist/stably-plugin-cli/skills/test-creation-workflow/SKILL.md +311 -0
- package/package.json +2 -2
- package/dist/stably-plugin/.claude-plugin/plugin.json +0 -5
- package/dist/stably-plugin/skills/playwright-best-practices/references/accessibility.md +0 -359
- package/dist/stably-plugin/skills/playwright-best-practices/references/annotations.md +0 -526
- package/dist/stably-plugin/skills/playwright-best-practices/references/assertions-waiting.md +0 -361
- package/dist/stably-plugin/skills/playwright-best-practices/references/browser-apis.md +0 -391
- package/dist/stably-plugin/skills/playwright-best-practices/references/browser-extensions.md +0 -506
- package/dist/stably-plugin/skills/playwright-best-practices/references/canvas-webgl.md +0 -493
- package/dist/stably-plugin/skills/playwright-best-practices/references/ci-cd.md +0 -407
- package/dist/stably-plugin/skills/playwright-best-practices/references/clock-mocking.md +0 -364
- package/dist/stably-plugin/skills/playwright-best-practices/references/component-testing.md +0 -500
- package/dist/stably-plugin/skills/playwright-best-practices/references/console-errors.md +0 -420
- package/dist/stably-plugin/skills/playwright-best-practices/references/debugging.md +0 -491
- package/dist/stably-plugin/skills/playwright-best-practices/references/electron.md +0 -509
- package/dist/stably-plugin/skills/playwright-best-practices/references/error-testing.md +0 -360
- package/dist/stably-plugin/skills/playwright-best-practices/references/file-operations.md +0 -375
- package/dist/stably-plugin/skills/playwright-best-practices/references/fixtures-hooks.md +0 -417
- package/dist/stably-plugin/skills/playwright-best-practices/references/flaky-tests.md +0 -494
- package/dist/stably-plugin/skills/playwright-best-practices/references/global-setup.md +0 -434
- package/dist/stably-plugin/skills/playwright-best-practices/references/i18n.md +0 -508
- package/dist/stably-plugin/skills/playwright-best-practices/references/iframes.md +0 -403
- package/dist/stably-plugin/skills/playwright-best-practices/references/locators.md +0 -242
- package/dist/stably-plugin/skills/playwright-best-practices/references/mobile-testing.md +0 -409
- package/dist/stably-plugin/skills/playwright-best-practices/references/multi-context.md +0 -288
- package/dist/stably-plugin/skills/playwright-best-practices/references/multi-user.md +0 -393
- package/dist/stably-plugin/skills/playwright-best-practices/references/network-advanced.md +0 -452
- package/dist/stably-plugin/skills/playwright-best-practices/references/page-object-model.md +0 -315
- package/dist/stably-plugin/skills/playwright-best-practices/references/performance-testing.md +0 -476
- package/dist/stably-plugin/skills/playwright-best-practices/references/performance.md +0 -453
- package/dist/stably-plugin/skills/playwright-best-practices/references/projects-dependencies.md +0 -456
- package/dist/stably-plugin/skills/playwright-best-practices/references/security-testing.md +0 -430
- package/dist/stably-plugin/skills/playwright-best-practices/references/service-workers.md +0 -504
- package/dist/stably-plugin/skills/playwright-best-practices/references/test-coverage.md +0 -495
- package/dist/stably-plugin/skills/playwright-best-practices/references/test-data.md +0 -492
- package/dist/stably-plugin/skills/playwright-best-practices/references/test-organization.md +0 -361
- package/dist/stably-plugin/skills/playwright-best-practices/references/third-party.md +0 -464
- package/dist/stably-plugin/skills/playwright-best-practices/references/websockets.md +0 -403
|
@@ -1,434 +0,0 @@
|
|
|
1
|
-
# Global Setup & Teardown
|
|
2
|
-
|
|
3
|
-
## Table of Contents
|
|
4
|
-
|
|
5
|
-
1. [Global Setup](#global-setup)
|
|
6
|
-
2. [Global Teardown](#global-teardown)
|
|
7
|
-
3. [Database Patterns](#database-patterns)
|
|
8
|
-
4. [Environment Provisioning](#environment-provisioning)
|
|
9
|
-
5. [Setup Projects vs Global Setup](#setup-projects-vs-global-setup)
|
|
10
|
-
6. [Parallel Execution Caveats](#parallel-execution-caveats)
|
|
11
|
-
|
|
12
|
-
## Global Setup
|
|
13
|
-
|
|
14
|
-
### Basic Global Setup
|
|
15
|
-
|
|
16
|
-
```typescript
|
|
17
|
-
// global-setup.ts
|
|
18
|
-
import { FullConfig } from "@playwright/test";
|
|
19
|
-
|
|
20
|
-
async function globalSetup(config: FullConfig) {
|
|
21
|
-
console.log("Running global setup...");
|
|
22
|
-
// Perform one-time setup: start services, run migrations, etc.
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export default globalSetup;
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
### Configure Global Setup
|
|
29
|
-
|
|
30
|
-
```typescript
|
|
31
|
-
// playwright.config.ts
|
|
32
|
-
import { defineConfig } from "@playwright/test";
|
|
33
|
-
|
|
34
|
-
export default defineConfig({
|
|
35
|
-
globalSetup: require.resolve("./global-setup"),
|
|
36
|
-
globalTeardown: require.resolve("./global-teardown"),
|
|
37
|
-
});
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
> **Authentication in Global Setup**: For authentication patterns using storage state in global setup, see [fixtures-hooks.md](fixtures-hooks.md#authentication-patterns). Setup projects are generally preferred for authentication as they provide access to Playwright fixtures.
|
|
41
|
-
|
|
42
|
-
### Global Setup with Return Value
|
|
43
|
-
|
|
44
|
-
```typescript
|
|
45
|
-
// global-setup.ts
|
|
46
|
-
async function globalSetup(config: FullConfig): Promise<() => Promise<void>> {
|
|
47
|
-
const server = await startTestServer();
|
|
48
|
-
|
|
49
|
-
// Return cleanup function (alternative to globalTeardown)
|
|
50
|
-
return async () => {
|
|
51
|
-
await server.stop();
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export default globalSetup;
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### Access Config in Global Setup
|
|
59
|
-
|
|
60
|
-
```typescript
|
|
61
|
-
// global-setup.ts
|
|
62
|
-
import { FullConfig } from "@playwright/test";
|
|
63
|
-
|
|
64
|
-
async function globalSetup(config: FullConfig) {
|
|
65
|
-
const { baseURL } = config.projects[0].use;
|
|
66
|
-
console.log(`Setting up for ${baseURL}`);
|
|
67
|
-
|
|
68
|
-
// Access custom config
|
|
69
|
-
const workers = config.workers;
|
|
70
|
-
const timeout = config.timeout;
|
|
71
|
-
|
|
72
|
-
// Access environment
|
|
73
|
-
const isCI = !!process.env.CI;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export default globalSetup;
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
## Global Teardown
|
|
80
|
-
|
|
81
|
-
### Basic Global Teardown
|
|
82
|
-
|
|
83
|
-
```typescript
|
|
84
|
-
// global-teardown.ts
|
|
85
|
-
import { FullConfig } from "@playwright/test";
|
|
86
|
-
import fs from "fs";
|
|
87
|
-
|
|
88
|
-
async function globalTeardown(config: FullConfig) {
|
|
89
|
-
console.log("Running global teardown...");
|
|
90
|
-
|
|
91
|
-
// Clean up auth files
|
|
92
|
-
if (fs.existsSync(".auth")) {
|
|
93
|
-
fs.rmSync(".auth", { recursive: true });
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Clean up test data
|
|
97
|
-
await cleanupTestDatabase();
|
|
98
|
-
|
|
99
|
-
// Stop services
|
|
100
|
-
await stopTestServices();
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export default globalTeardown;
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
### Conditional Teardown
|
|
107
|
-
|
|
108
|
-
```typescript
|
|
109
|
-
// global-teardown.ts
|
|
110
|
-
async function globalTeardown(config: FullConfig) {
|
|
111
|
-
// Skip cleanup in CI (containers are discarded anyway)
|
|
112
|
-
if (process.env.CI) {
|
|
113
|
-
console.log("Skipping teardown in CI");
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Local cleanup
|
|
118
|
-
await cleanupLocalTestData();
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export default globalTeardown;
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
## Database Patterns
|
|
125
|
-
|
|
126
|
-
This section covers **one-time database setup** (migrations, snapshots, per-worker databases). For related topics:
|
|
127
|
-
|
|
128
|
-
- **Per-test database fixtures** (isolation, transaction rollback): See [fixtures-hooks.md](fixtures-hooks.md#database-fixtures)
|
|
129
|
-
- **Test data factories** (builders, Faker): See [test-data.md](test-data.md)
|
|
130
|
-
|
|
131
|
-
### Database Migration in Setup
|
|
132
|
-
|
|
133
|
-
```typescript
|
|
134
|
-
// global-setup.ts
|
|
135
|
-
import { execSync } from "child_process";
|
|
136
|
-
|
|
137
|
-
async function globalSetup() {
|
|
138
|
-
console.log("Running database migrations...");
|
|
139
|
-
|
|
140
|
-
// Run migrations
|
|
141
|
-
execSync("npx prisma migrate deploy", { stdio: "inherit" });
|
|
142
|
-
|
|
143
|
-
// Seed test data
|
|
144
|
-
execSync("npx prisma db seed", { stdio: "inherit" });
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
export default globalSetup;
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
### Database Snapshot Pattern
|
|
151
|
-
|
|
152
|
-
```typescript
|
|
153
|
-
// global-setup.ts
|
|
154
|
-
import { execSync } from "child_process";
|
|
155
|
-
import fs from "fs";
|
|
156
|
-
|
|
157
|
-
const SNAPSHOT_PATH = "./test-db-snapshot.sql";
|
|
158
|
-
|
|
159
|
-
async function globalSetup() {
|
|
160
|
-
// Check if snapshot exists
|
|
161
|
-
if (fs.existsSync(SNAPSHOT_PATH)) {
|
|
162
|
-
console.log("Restoring database from snapshot...");
|
|
163
|
-
execSync(`psql $DATABASE_URL < ${SNAPSHOT_PATH}`, { stdio: "inherit" });
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// First run: migrate and create snapshot
|
|
168
|
-
console.log("Creating database snapshot...");
|
|
169
|
-
execSync("npx prisma migrate deploy", { stdio: "inherit" });
|
|
170
|
-
execSync("npx prisma db seed", { stdio: "inherit" });
|
|
171
|
-
execSync(`pg_dump $DATABASE_URL > ${SNAPSHOT_PATH}`, { stdio: "inherit" });
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
export default globalSetup;
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
### Test Database per Worker
|
|
178
|
-
|
|
179
|
-
```typescript
|
|
180
|
-
// global-setup.ts
|
|
181
|
-
async function globalSetup(config: FullConfig) {
|
|
182
|
-
const workerCount = config.workers || 1;
|
|
183
|
-
|
|
184
|
-
// Create a database for each worker
|
|
185
|
-
for (let i = 0; i < workerCount; i++) {
|
|
186
|
-
const dbName = `test_db_worker_${i}`;
|
|
187
|
-
await createDatabase(dbName);
|
|
188
|
-
await runMigrations(dbName);
|
|
189
|
-
await seedDatabase(dbName);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// global-teardown.ts
|
|
194
|
-
async function globalTeardown(config: FullConfig) {
|
|
195
|
-
const workerCount = config.workers || 1;
|
|
196
|
-
|
|
197
|
-
for (let i = 0; i < workerCount; i++) {
|
|
198
|
-
await dropDatabase(`test_db_worker_${i}`);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
## Environment Provisioning
|
|
204
|
-
|
|
205
|
-
### Start Services in Setup
|
|
206
|
-
|
|
207
|
-
```typescript
|
|
208
|
-
// global-setup.ts
|
|
209
|
-
import { execSync, spawn } from "child_process";
|
|
210
|
-
|
|
211
|
-
let serverProcess: any;
|
|
212
|
-
|
|
213
|
-
async function globalSetup() {
|
|
214
|
-
// Start backend server
|
|
215
|
-
serverProcess = spawn("npm", ["run", "start:test"], {
|
|
216
|
-
stdio: "pipe",
|
|
217
|
-
detached: true,
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
// Wait for server to be ready
|
|
221
|
-
await waitForServer("http://localhost:3000/health", 30000);
|
|
222
|
-
|
|
223
|
-
// Store PID for teardown
|
|
224
|
-
process.env.SERVER_PID = serverProcess.pid.toString();
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
async function waitForServer(url: string, timeout: number) {
|
|
228
|
-
const start = Date.now();
|
|
229
|
-
|
|
230
|
-
while (Date.now() - start < timeout) {
|
|
231
|
-
try {
|
|
232
|
-
const response = await fetch(url);
|
|
233
|
-
if (response.ok) return;
|
|
234
|
-
} catch {
|
|
235
|
-
// Server not ready yet
|
|
236
|
-
}
|
|
237
|
-
await new Promise((r) => setTimeout(r, 1000));
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
throw new Error(`Server did not start within ${timeout}ms`);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
export default globalSetup;
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
### Docker Compose Setup
|
|
247
|
-
|
|
248
|
-
```typescript
|
|
249
|
-
// global-setup.ts
|
|
250
|
-
import { execSync } from "child_process";
|
|
251
|
-
|
|
252
|
-
async function globalSetup() {
|
|
253
|
-
console.log("Starting Docker services...");
|
|
254
|
-
|
|
255
|
-
execSync("docker-compose -f docker-compose.test.yml up -d", {
|
|
256
|
-
stdio: "inherit",
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
// Wait for services to be healthy
|
|
260
|
-
execSync("docker-compose -f docker-compose.test.yml exec -T db pg_isready", {
|
|
261
|
-
stdio: "inherit",
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
export default globalSetup;
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
```typescript
|
|
269
|
-
// global-teardown.ts
|
|
270
|
-
import { execSync } from "child_process";
|
|
271
|
-
|
|
272
|
-
async function globalTeardown() {
|
|
273
|
-
console.log("Stopping Docker services...");
|
|
274
|
-
|
|
275
|
-
execSync("docker-compose -f docker-compose.test.yml down -v", {
|
|
276
|
-
stdio: "inherit",
|
|
277
|
-
});
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
export default globalTeardown;
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
### Environment Variables Setup
|
|
284
|
-
|
|
285
|
-
```typescript
|
|
286
|
-
// global-setup.ts
|
|
287
|
-
import dotenv from "dotenv";
|
|
288
|
-
import path from "path";
|
|
289
|
-
|
|
290
|
-
async function globalSetup() {
|
|
291
|
-
// Load test-specific environment
|
|
292
|
-
const envFile = process.env.CI ? ".env.ci" : ".env.test";
|
|
293
|
-
dotenv.config({ path: path.resolve(process.cwd(), envFile) });
|
|
294
|
-
|
|
295
|
-
// Validate required variables
|
|
296
|
-
const required = ["DATABASE_URL", "API_KEY", "TEST_EMAIL"];
|
|
297
|
-
for (const key of required) {
|
|
298
|
-
if (!process.env[key]) {
|
|
299
|
-
throw new Error(`Missing required environment variable: ${key}`);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
export default globalSetup;
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
## Setup Projects vs Global Setup
|
|
308
|
-
|
|
309
|
-
### When to Use Each
|
|
310
|
-
|
|
311
|
-
| Use Global Setup | Use Setup Projects |
|
|
312
|
-
| ------------------------------------- | ---------------------------------------- |
|
|
313
|
-
| One-time setup (migrations, services) | Per-project setup (auth states) |
|
|
314
|
-
| No access to Playwright fixtures | Need page, request fixtures |
|
|
315
|
-
| Runs once before all projects | Can run per-project or have dependencies |
|
|
316
|
-
| Shared across all workers | Can be parallelized |
|
|
317
|
-
|
|
318
|
-
### Setup Project Pattern
|
|
319
|
-
|
|
320
|
-
```typescript
|
|
321
|
-
// playwright.config.ts
|
|
322
|
-
export default defineConfig({
|
|
323
|
-
projects: [
|
|
324
|
-
// Setup project
|
|
325
|
-
{
|
|
326
|
-
name: "setup",
|
|
327
|
-
testMatch: /.*\.setup\.ts/,
|
|
328
|
-
},
|
|
329
|
-
// Test projects depend on setup
|
|
330
|
-
{
|
|
331
|
-
name: "chromium",
|
|
332
|
-
use: { ...devices["Desktop Chrome"] },
|
|
333
|
-
dependencies: ["setup"],
|
|
334
|
-
},
|
|
335
|
-
{
|
|
336
|
-
name: "firefox",
|
|
337
|
-
use: { ...devices["Desktop Firefox"] },
|
|
338
|
-
dependencies: ["setup"],
|
|
339
|
-
},
|
|
340
|
-
],
|
|
341
|
-
});
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
> **For complete authentication setup patterns**, see [fixtures-hooks.md](fixtures-hooks.md#authentication-patterns).
|
|
345
|
-
|
|
346
|
-
### Combining Both
|
|
347
|
-
|
|
348
|
-
```typescript
|
|
349
|
-
// playwright.config.ts
|
|
350
|
-
export default defineConfig({
|
|
351
|
-
// Global: Start services, run migrations
|
|
352
|
-
globalSetup: require.resolve("./global-setup"),
|
|
353
|
-
globalTeardown: require.resolve("./global-teardown"),
|
|
354
|
-
|
|
355
|
-
projects: [
|
|
356
|
-
// Setup project: Create auth states
|
|
357
|
-
{ name: "setup", testMatch: /.*\.setup\.ts/ },
|
|
358
|
-
{
|
|
359
|
-
name: "chromium",
|
|
360
|
-
use: {
|
|
361
|
-
...devices["Desktop Chrome"],
|
|
362
|
-
storageState: ".auth/user.json",
|
|
363
|
-
},
|
|
364
|
-
dependencies: ["setup"],
|
|
365
|
-
},
|
|
366
|
-
],
|
|
367
|
-
});
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
## Parallel Execution Caveats
|
|
371
|
-
|
|
372
|
-
### Understanding Global Setup Execution
|
|
373
|
-
|
|
374
|
-
```
|
|
375
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
376
|
-
│ globalSetup runs ONCE │
|
|
377
|
-
│ ↓ │
|
|
378
|
-
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
|
379
|
-
│ │ Worker 1│ │ Worker 2│ │ Worker 3│ │ Worker 4│ │
|
|
380
|
-
│ │ tests │ │ tests │ │ tests │ │ tests │ │
|
|
381
|
-
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
|
|
382
|
-
│ ↓ │
|
|
383
|
-
│ globalTeardown runs ONCE │
|
|
384
|
-
└─────────────────────────────────────────────────────────────┘
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
**Key implications:**
|
|
388
|
-
|
|
389
|
-
- Global setup has **no access** to Playwright fixtures (`page`, `request`, `context`)
|
|
390
|
-
- State created in global setup is **shared** across all workers
|
|
391
|
-
- If tests **modify** shared state, they may conflict with parallel workers
|
|
392
|
-
- Global setup **cannot** react to individual test needs
|
|
393
|
-
|
|
394
|
-
### When to Prefer Worker-Scoped Fixtures
|
|
395
|
-
|
|
396
|
-
Use **worker-scoped fixtures** instead of globalSetup when:
|
|
397
|
-
|
|
398
|
-
| Scenario | Why Fixtures Are Better |
|
|
399
|
-
| ------------------------------------ | ---------------------------------------------------- |
|
|
400
|
-
| Each worker needs isolated resources | Fixtures can create per-worker databases, servers |
|
|
401
|
-
| Setup needs Playwright APIs | Fixtures have access to `page`, `request`, `browser` |
|
|
402
|
-
| Setup depends on test configuration | Fixtures receive test context and options |
|
|
403
|
-
| Resources need cleanup per worker | Worker fixtures auto-cleanup when worker exits |
|
|
404
|
-
|
|
405
|
-
### Common Parallel Pitfall
|
|
406
|
-
|
|
407
|
-
```typescript
|
|
408
|
-
// ❌ BAD: Global setup creates ONE user, all workers fight over it
|
|
409
|
-
async function globalSetup() {
|
|
410
|
-
await createUser({ email: "test@example.com" }); // Shared!
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
// ✅ GOOD: Each worker gets its own user via worker-scoped fixture
|
|
414
|
-
// Uses workerInfo.workerIndex to create unique data per worker
|
|
415
|
-
```
|
|
416
|
-
|
|
417
|
-
> **For worker-scoped fixture patterns** (per-worker databases, unique test data, `workerIndex` isolation), see [fixtures-hooks.md](fixtures-hooks.md#isolate-test-data-between-parallel-workers).
|
|
418
|
-
|
|
419
|
-
## Anti-Patterns to Avoid
|
|
420
|
-
|
|
421
|
-
| Anti-Pattern | Problem | Solution |
|
|
422
|
-
| ------------------------------ | -------------------------------- | ------------------------------------------ |
|
|
423
|
-
| Heavy setup in globalSetup | Slow test startup | Use setup projects for parallelizable work |
|
|
424
|
-
| Not cleaning up in teardown | Leaks resources, flaky CI | Always clean up or use containers |
|
|
425
|
-
| Hardcoded URLs in setup | Breaks in different environments | Use config.projects[0].use.baseURL |
|
|
426
|
-
| No timeout on service wait | Hangs forever if service fails | Add timeout with clear error |
|
|
427
|
-
| Shared mutable state | Race conditions in parallel | Use worker-scoped fixtures for isolation |
|
|
428
|
-
| Global setup for per-test data | Tests conflict | Use test-scoped fixtures |
|
|
429
|
-
|
|
430
|
-
## Related References
|
|
431
|
-
|
|
432
|
-
- **Fixtures & Auth**: See [fixtures-hooks.md](fixtures-hooks.md) for worker-scoped fixtures and auth patterns
|
|
433
|
-
- **CI/CD**: See [ci-cd.md](ci-cd.md) for CI setup patterns
|
|
434
|
-
- **Projects**: See [projects-dependencies.md](projects-dependencies.md) for project configuration
|