@arcadialdev/arcality 2.2.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/.agents/skills/e2e-testing-expert/SKILL.md +28 -0
- package/.agents/skills/frontend-design/LICENSE.txt +177 -0
- package/.agents/skills/frontend-design/SKILL.md +42 -0
- package/.agents/skills/nodejs-backend-patterns/SKILL.md +639 -0
- package/.agents/skills/nodejs-backend-patterns/references/advanced-patterns.md +430 -0
- package/.agents/skills/playwright-best-practices/LICENSE.md +7 -0
- package/.agents/skills/playwright-best-practices/README.md +147 -0
- package/.agents/skills/playwright-best-practices/SKILL.md +303 -0
- package/.agents/skills/playwright-best-practices/advanced/authentication-flows.md +360 -0
- package/.agents/skills/playwright-best-practices/advanced/authentication.md +871 -0
- package/.agents/skills/playwright-best-practices/advanced/clock-mocking.md +364 -0
- package/.agents/skills/playwright-best-practices/advanced/mobile-testing.md +409 -0
- package/.agents/skills/playwright-best-practices/advanced/multi-context.md +288 -0
- package/.agents/skills/playwright-best-practices/advanced/multi-user.md +393 -0
- package/.agents/skills/playwright-best-practices/advanced/network-advanced.md +452 -0
- package/.agents/skills/playwright-best-practices/advanced/third-party.md +464 -0
- package/.agents/skills/playwright-best-practices/architecture/pom-vs-fixtures.md +363 -0
- package/.agents/skills/playwright-best-practices/architecture/test-architecture.md +369 -0
- package/.agents/skills/playwright-best-practices/architecture/when-to-mock.md +383 -0
- package/.agents/skills/playwright-best-practices/browser-apis/browser-apis.md +391 -0
- package/.agents/skills/playwright-best-practices/browser-apis/iframes.md +403 -0
- package/.agents/skills/playwright-best-practices/browser-apis/service-workers.md +504 -0
- package/.agents/skills/playwright-best-practices/browser-apis/websockets.md +403 -0
- package/.agents/skills/playwright-best-practices/core/annotations.md +424 -0
- package/.agents/skills/playwright-best-practices/core/assertions-waiting.md +361 -0
- package/.agents/skills/playwright-best-practices/core/configuration.md +452 -0
- package/.agents/skills/playwright-best-practices/core/fixtures-hooks.md +417 -0
- package/.agents/skills/playwright-best-practices/core/global-setup.md +434 -0
- package/.agents/skills/playwright-best-practices/core/locators.md +242 -0
- package/.agents/skills/playwright-best-practices/core/page-object-model.md +315 -0
- package/.agents/skills/playwright-best-practices/core/projects-dependencies.md +453 -0
- package/.agents/skills/playwright-best-practices/core/test-data.md +492 -0
- package/.agents/skills/playwright-best-practices/core/test-suite-structure.md +361 -0
- package/.agents/skills/playwright-best-practices/core/test-tags.md +298 -0
- package/.agents/skills/playwright-best-practices/debugging/console-errors.md +420 -0
- package/.agents/skills/playwright-best-practices/debugging/debugging.md +504 -0
- package/.agents/skills/playwright-best-practices/debugging/error-testing.md +360 -0
- package/.agents/skills/playwright-best-practices/debugging/flaky-tests.md +496 -0
- package/.agents/skills/playwright-best-practices/frameworks/angular.md +530 -0
- package/.agents/skills/playwright-best-practices/frameworks/nextjs.md +469 -0
- package/.agents/skills/playwright-best-practices/frameworks/react.md +531 -0
- package/.agents/skills/playwright-best-practices/frameworks/vue.md +574 -0
- package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/ci-cd.md +468 -0
- package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/docker.md +283 -0
- package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/github-actions.md +546 -0
- package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/gitlab.md +397 -0
- package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/other-providers.md +521 -0
- package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/parallel-sharding.md +371 -0
- package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/performance.md +453 -0
- package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/reporting.md +424 -0
- package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/test-coverage.md +497 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/accessibility.md +359 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/api-testing.md +719 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/browser-extensions.md +506 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/canvas-webgl.md +493 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/component-testing.md +500 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/drag-drop.md +576 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/electron.md +509 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/file-operations.md +377 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/file-upload-download.md +562 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/forms-validation.md +561 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/graphql-testing.md +331 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/i18n.md +508 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/performance-testing.md +476 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/security-testing.md +430 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/visual-regression.md +634 -0
- package/.env.example +21 -0
- package/README.md +30 -0
- package/bin/arcality.mjs +86 -0
- package/package.json +66 -0
- package/playwright.config.ts +12 -0
- package/scripts/cleanup-qmsdev.mjs +63 -0
- package/scripts/discover-view.mjs +52 -0
- package/scripts/extract-view.mjs +64 -0
- package/scripts/gen-and-run.mjs +838 -0
- package/scripts/init.mjs +290 -0
- package/scripts/migrate-to-central-out.mjs +157 -0
- package/scripts/postinstall.mjs +63 -0
- package/scripts/rebrand-report.mjs +241 -0
- package/scripts/setup.mjs +166 -0
- package/src/KnowledgeService.ts +239 -0
- package/src/arcalityClient.mjs +266 -0
- package/src/configLoader.mjs +179 -0
- package/src/configManager.mjs +172 -0
- package/src/consoleBanner.ts +32 -0
- package/src/envSetup.ts +205 -0
- package/src/index.ts +25 -0
- package/src/projectInspector.ts +42 -0
- package/src/services/collectiveMemoryService.ts +178 -0
- package/src/testRunner.ts +201 -0
- package/tests/_helpers/ArcalityReporter.ts +490 -0
- package/tests/_helpers/agentic-runner.spec.ts +741 -0
- package/tests/_helpers/ai-agent-helper.ts +1573 -0
- package/tests/_helpers/discover-view.spec.ts +238 -0
- package/tests/_helpers/extract-view.spec.ts +118 -0
- package/tests/_helpers/qa-tools.ts +333 -0
- package/tests/_helpers/smart-action.spec.ts +1458 -0
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
# Browser Console & JavaScript Error Handling
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
|
|
5
|
+
1. [Capturing Console Messages](#capturing-console-messages)
|
|
6
|
+
2. [Failing on Console Errors](#failing-on-console-errors)
|
|
7
|
+
3. [JavaScript Error Detection](#javascript-error-detection)
|
|
8
|
+
4. [Monitoring Warnings](#monitoring-warnings)
|
|
9
|
+
5. [Console Fixtures](#console-fixtures)
|
|
10
|
+
|
|
11
|
+
## Capturing Console Messages
|
|
12
|
+
|
|
13
|
+
### Basic Console Capture
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
test("capture console logs", async ({ page }) => {
|
|
17
|
+
const logs: string[] = [];
|
|
18
|
+
|
|
19
|
+
page.on("console", (msg) => {
|
|
20
|
+
logs.push(`${msg.type()}: ${msg.text()}`);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
await page.goto("/");
|
|
24
|
+
|
|
25
|
+
// Check what was logged
|
|
26
|
+
console.log("Captured logs:", logs);
|
|
27
|
+
});
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Capture by Type
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
test("capture specific console types", async ({ page }) => {
|
|
34
|
+
const errors: string[] = [];
|
|
35
|
+
const warnings: string[] = [];
|
|
36
|
+
const infos: string[] = [];
|
|
37
|
+
|
|
38
|
+
page.on("console", (msg) => {
|
|
39
|
+
switch (msg.type()) {
|
|
40
|
+
case "error":
|
|
41
|
+
errors.push(msg.text());
|
|
42
|
+
break;
|
|
43
|
+
case "warning":
|
|
44
|
+
warnings.push(msg.text());
|
|
45
|
+
break;
|
|
46
|
+
case "info":
|
|
47
|
+
case "log":
|
|
48
|
+
infos.push(msg.text());
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
await page.goto("/dashboard");
|
|
54
|
+
|
|
55
|
+
expect(errors).toHaveLength(0);
|
|
56
|
+
console.log("Warnings:", warnings);
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Capture with Stack Trace
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
test("capture errors with location", async ({ page }) => {
|
|
64
|
+
const errors: { message: string; location?: string }[] = [];
|
|
65
|
+
|
|
66
|
+
page.on("console", async (msg) => {
|
|
67
|
+
if (msg.type() === "error") {
|
|
68
|
+
const location = msg.location();
|
|
69
|
+
errors.push({
|
|
70
|
+
message: msg.text(),
|
|
71
|
+
location: location
|
|
72
|
+
? `${location.url}:${location.lineNumber}`
|
|
73
|
+
: undefined,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
await page.goto("/buggy-page");
|
|
79
|
+
|
|
80
|
+
// Log errors with source location
|
|
81
|
+
errors.forEach((e) => {
|
|
82
|
+
console.log(`Error: ${e.message}`);
|
|
83
|
+
if (e.location) console.log(` at ${e.location}`);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Failing on Console Errors
|
|
89
|
+
|
|
90
|
+
### Fail Test on Any Error
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
test("no console errors allowed", async ({ page }) => {
|
|
94
|
+
const errors: string[] = [];
|
|
95
|
+
|
|
96
|
+
page.on("console", (msg) => {
|
|
97
|
+
if (msg.type() === "error") {
|
|
98
|
+
errors.push(msg.text());
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
await page.goto("/");
|
|
103
|
+
await page.getByRole("button", { name: "Load Data" }).click();
|
|
104
|
+
|
|
105
|
+
// Fail if any console errors
|
|
106
|
+
expect(errors, `Console errors found:\n${errors.join("\n")}`).toHaveLength(0);
|
|
107
|
+
});
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Fail with Allowed Exceptions
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
test("no unexpected console errors", async ({ page }) => {
|
|
114
|
+
const allowedErrors = [
|
|
115
|
+
/Failed to load resource.*favicon/,
|
|
116
|
+
/ResizeObserver loop/,
|
|
117
|
+
];
|
|
118
|
+
|
|
119
|
+
const unexpectedErrors: string[] = [];
|
|
120
|
+
|
|
121
|
+
page.on("console", (msg) => {
|
|
122
|
+
if (msg.type() === "error") {
|
|
123
|
+
const text = msg.text();
|
|
124
|
+
const isAllowed = allowedErrors.some((pattern) => pattern.test(text));
|
|
125
|
+
if (!isAllowed) {
|
|
126
|
+
unexpectedErrors.push(text);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
await page.goto("/");
|
|
132
|
+
|
|
133
|
+
expect(
|
|
134
|
+
unexpectedErrors,
|
|
135
|
+
`Unexpected console errors:\n${unexpectedErrors.join("\n")}`,
|
|
136
|
+
).toHaveLength(0);
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Auto-Fail Fixture
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
// fixtures/console.fixture.ts
|
|
144
|
+
type ConsoleFixtures = {
|
|
145
|
+
failOnConsoleError: void;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
export const test = base.extend<ConsoleFixtures>({
|
|
149
|
+
failOnConsoleError: [
|
|
150
|
+
async ({ page }, use, testInfo) => {
|
|
151
|
+
const errors: string[] = [];
|
|
152
|
+
|
|
153
|
+
page.on("console", (msg) => {
|
|
154
|
+
if (msg.type() === "error") {
|
|
155
|
+
errors.push(msg.text());
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
await use();
|
|
160
|
+
|
|
161
|
+
// After test, check for errors
|
|
162
|
+
if (errors.length > 0) {
|
|
163
|
+
testInfo.annotations.push({
|
|
164
|
+
type: "console-errors",
|
|
165
|
+
description: errors.join("\n"),
|
|
166
|
+
});
|
|
167
|
+
throw new Error(`Console errors detected:\n${errors.join("\n")}`);
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
{ auto: true }, // Runs for every test
|
|
171
|
+
],
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## JavaScript Error Detection
|
|
176
|
+
|
|
177
|
+
### Catch Uncaught Exceptions
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
test("no uncaught exceptions", async ({ page }) => {
|
|
181
|
+
const pageErrors: Error[] = [];
|
|
182
|
+
|
|
183
|
+
page.on("pageerror", (error) => {
|
|
184
|
+
pageErrors.push(error);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
await page.goto("/");
|
|
188
|
+
await page.getByRole("button", { name: "Trigger Action" }).click();
|
|
189
|
+
|
|
190
|
+
expect(
|
|
191
|
+
pageErrors,
|
|
192
|
+
`Uncaught exceptions:\n${pageErrors.map((e) => e.message).join("\n")}`,
|
|
193
|
+
).toHaveLength(0);
|
|
194
|
+
});
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Capture Error Details
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
test("capture JS error details", async ({ page }) => {
|
|
201
|
+
const errors: { message: string; stack?: string }[] = [];
|
|
202
|
+
|
|
203
|
+
page.on("pageerror", (error) => {
|
|
204
|
+
errors.push({
|
|
205
|
+
message: error.message,
|
|
206
|
+
stack: error.stack,
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
await page.goto("/error-page");
|
|
211
|
+
|
|
212
|
+
if (errors.length > 0) {
|
|
213
|
+
console.log("JavaScript errors:");
|
|
214
|
+
errors.forEach((e) => {
|
|
215
|
+
console.log(` Message: ${e.message}`);
|
|
216
|
+
console.log(` Stack: ${e.stack}`);
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Test Error Boundary Triggers
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
test("error boundary catches render error", async ({ page }) => {
|
|
226
|
+
let errorCaught = false;
|
|
227
|
+
|
|
228
|
+
page.on("pageerror", () => {
|
|
229
|
+
// Note: React error boundaries catch errors before they become pageerrors
|
|
230
|
+
// This would only fire for unhandled errors
|
|
231
|
+
errorCaught = true;
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
// Trigger component error via props
|
|
235
|
+
await page.route(
|
|
236
|
+
"**/api/data",
|
|
237
|
+
(route) => route.fulfill({ json: null }), // Will cause "cannot read property of null"
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
await page.goto("/dashboard");
|
|
241
|
+
|
|
242
|
+
// Error boundary should show fallback, not crash
|
|
243
|
+
await expect(page.getByText("Something went wrong")).toBeVisible();
|
|
244
|
+
expect(errorCaught).toBe(false); // Error was caught by boundary
|
|
245
|
+
});
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Monitoring Warnings
|
|
249
|
+
|
|
250
|
+
### Capture Deprecation Warnings
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
test("no deprecation warnings", async ({ page }) => {
|
|
254
|
+
const deprecations: string[] = [];
|
|
255
|
+
|
|
256
|
+
page.on("console", (msg) => {
|
|
257
|
+
const text = msg.text();
|
|
258
|
+
if (
|
|
259
|
+
msg.type() === "warning" &&
|
|
260
|
+
(text.includes("deprecated") || text.includes("Deprecation"))
|
|
261
|
+
) {
|
|
262
|
+
deprecations.push(text);
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
await page.goto("/");
|
|
267
|
+
|
|
268
|
+
if (deprecations.length > 0) {
|
|
269
|
+
console.warn("Deprecation warnings found:");
|
|
270
|
+
deprecations.forEach((d) => console.warn(` - ${d}`));
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Optionally fail
|
|
274
|
+
// expect(deprecations).toHaveLength(0);
|
|
275
|
+
});
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### React Development Warnings
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
test("no React warnings", async ({ page }) => {
|
|
282
|
+
const reactWarnings: string[] = [];
|
|
283
|
+
|
|
284
|
+
page.on("console", (msg) => {
|
|
285
|
+
const text = msg.text();
|
|
286
|
+
if (
|
|
287
|
+
msg.type() === "warning" &&
|
|
288
|
+
(text.includes("Warning:") || text.includes("React"))
|
|
289
|
+
) {
|
|
290
|
+
reactWarnings.push(text);
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
await page.goto("/");
|
|
295
|
+
|
|
296
|
+
// Common React warnings to check
|
|
297
|
+
const criticalWarnings = reactWarnings.filter(
|
|
298
|
+
(w) =>
|
|
299
|
+
w.includes("Each child in a list should have a unique") ||
|
|
300
|
+
w.includes("Cannot update a component") ||
|
|
301
|
+
w.includes("Can't perform a React state update"),
|
|
302
|
+
);
|
|
303
|
+
|
|
304
|
+
expect(
|
|
305
|
+
criticalWarnings,
|
|
306
|
+
`React warnings:\n${criticalWarnings.join("\n")}`,
|
|
307
|
+
).toHaveLength(0);
|
|
308
|
+
});
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## Console Fixtures
|
|
312
|
+
|
|
313
|
+
### Comprehensive Console Fixture
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
// fixtures/console.fixture.ts
|
|
317
|
+
type ConsoleMessage = {
|
|
318
|
+
type: string;
|
|
319
|
+
text: string;
|
|
320
|
+
location?: { url: string; line: number };
|
|
321
|
+
timestamp: number;
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
type ConsoleFixtures = {
|
|
325
|
+
consoleMessages: ConsoleMessage[];
|
|
326
|
+
getConsoleErrors: () => ConsoleMessage[];
|
|
327
|
+
getConsoleWarnings: () => ConsoleMessage[];
|
|
328
|
+
assertNoErrors: (allowedPatterns?: RegExp[]) => void;
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
export const test = base.extend<ConsoleFixtures>({
|
|
332
|
+
consoleMessages: async ({ page }, use) => {
|
|
333
|
+
const messages: ConsoleMessage[] = [];
|
|
334
|
+
|
|
335
|
+
page.on("console", (msg) => {
|
|
336
|
+
const location = msg.location();
|
|
337
|
+
messages.push({
|
|
338
|
+
type: msg.type(),
|
|
339
|
+
text: msg.text(),
|
|
340
|
+
location: location
|
|
341
|
+
? { url: location.url, line: location.lineNumber }
|
|
342
|
+
: undefined,
|
|
343
|
+
timestamp: Date.now(),
|
|
344
|
+
});
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
await use(messages);
|
|
348
|
+
},
|
|
349
|
+
|
|
350
|
+
getConsoleErrors: async ({ consoleMessages }, use) => {
|
|
351
|
+
await use(() => consoleMessages.filter((m) => m.type === "error"));
|
|
352
|
+
},
|
|
353
|
+
|
|
354
|
+
getConsoleWarnings: async ({ consoleMessages }, use) => {
|
|
355
|
+
await use(() => consoleMessages.filter((m) => m.type === "warning"));
|
|
356
|
+
},
|
|
357
|
+
|
|
358
|
+
assertNoErrors: async ({ getConsoleErrors }, use) => {
|
|
359
|
+
await use((allowedPatterns = []) => {
|
|
360
|
+
const errors = getConsoleErrors();
|
|
361
|
+
const unexpected = errors.filter(
|
|
362
|
+
(e) => !allowedPatterns.some((p) => p.test(e.text)),
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
if (unexpected.length > 0) {
|
|
366
|
+
throw new Error(
|
|
367
|
+
`Unexpected console errors:\n${unexpected.map((e) => e.text).join("\n")}`,
|
|
368
|
+
);
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
},
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
// Usage
|
|
375
|
+
test("page loads without errors", async ({ page, assertNoErrors }) => {
|
|
376
|
+
await page.goto("/dashboard");
|
|
377
|
+
await page.getByRole("button", { name: "Load" }).click();
|
|
378
|
+
|
|
379
|
+
assertNoErrors([/favicon/]); // Allow favicon errors
|
|
380
|
+
});
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Attach Console to Report
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
test("capture console for debugging", async ({ page }, testInfo) => {
|
|
387
|
+
const logs: string[] = [];
|
|
388
|
+
|
|
389
|
+
page.on("console", (msg) => {
|
|
390
|
+
logs.push(`[${msg.type()}] ${msg.text()}`);
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
page.on("pageerror", (error) => {
|
|
394
|
+
logs.push(`[EXCEPTION] ${error.message}`);
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
await page.goto("/");
|
|
398
|
+
// ... test actions
|
|
399
|
+
|
|
400
|
+
// Attach console log to test report
|
|
401
|
+
await testInfo.attach("console-log", {
|
|
402
|
+
body: logs.join("\n"),
|
|
403
|
+
contentType: "text/plain",
|
|
404
|
+
});
|
|
405
|
+
});
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
## Anti-Patterns to Avoid
|
|
409
|
+
|
|
410
|
+
| Anti-Pattern | Problem | Solution |
|
|
411
|
+
| -------------------------- | -------------------------- | --------------------------- |
|
|
412
|
+
| Ignoring console errors | Bugs go unnoticed | Check for errors in tests |
|
|
413
|
+
| Too strict error checking | Tests fail on minor issues | Allow known/expected errors |
|
|
414
|
+
| Not capturing stack traces | Hard to debug | Include location info |
|
|
415
|
+
| Checking only at end | Miss errors during actions | Capture continuously |
|
|
416
|
+
|
|
417
|
+
## Related References
|
|
418
|
+
|
|
419
|
+
- **Debugging**: See [debugging.md](debugging.md) for troubleshooting
|
|
420
|
+
- **Error Testing**: See [error-testing.md](error-testing.md) for error scenarios
|