@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.
Files changed (97) hide show
  1. package/.agents/skills/e2e-testing-expert/SKILL.md +28 -0
  2. package/.agents/skills/frontend-design/LICENSE.txt +177 -0
  3. package/.agents/skills/frontend-design/SKILL.md +42 -0
  4. package/.agents/skills/nodejs-backend-patterns/SKILL.md +639 -0
  5. package/.agents/skills/nodejs-backend-patterns/references/advanced-patterns.md +430 -0
  6. package/.agents/skills/playwright-best-practices/LICENSE.md +7 -0
  7. package/.agents/skills/playwright-best-practices/README.md +147 -0
  8. package/.agents/skills/playwright-best-practices/SKILL.md +303 -0
  9. package/.agents/skills/playwright-best-practices/advanced/authentication-flows.md +360 -0
  10. package/.agents/skills/playwright-best-practices/advanced/authentication.md +871 -0
  11. package/.agents/skills/playwright-best-practices/advanced/clock-mocking.md +364 -0
  12. package/.agents/skills/playwright-best-practices/advanced/mobile-testing.md +409 -0
  13. package/.agents/skills/playwright-best-practices/advanced/multi-context.md +288 -0
  14. package/.agents/skills/playwright-best-practices/advanced/multi-user.md +393 -0
  15. package/.agents/skills/playwright-best-practices/advanced/network-advanced.md +452 -0
  16. package/.agents/skills/playwright-best-practices/advanced/third-party.md +464 -0
  17. package/.agents/skills/playwright-best-practices/architecture/pom-vs-fixtures.md +363 -0
  18. package/.agents/skills/playwright-best-practices/architecture/test-architecture.md +369 -0
  19. package/.agents/skills/playwright-best-practices/architecture/when-to-mock.md +383 -0
  20. package/.agents/skills/playwright-best-practices/browser-apis/browser-apis.md +391 -0
  21. package/.agents/skills/playwright-best-practices/browser-apis/iframes.md +403 -0
  22. package/.agents/skills/playwright-best-practices/browser-apis/service-workers.md +504 -0
  23. package/.agents/skills/playwright-best-practices/browser-apis/websockets.md +403 -0
  24. package/.agents/skills/playwright-best-practices/core/annotations.md +424 -0
  25. package/.agents/skills/playwright-best-practices/core/assertions-waiting.md +361 -0
  26. package/.agents/skills/playwright-best-practices/core/configuration.md +452 -0
  27. package/.agents/skills/playwright-best-practices/core/fixtures-hooks.md +417 -0
  28. package/.agents/skills/playwright-best-practices/core/global-setup.md +434 -0
  29. package/.agents/skills/playwright-best-practices/core/locators.md +242 -0
  30. package/.agents/skills/playwright-best-practices/core/page-object-model.md +315 -0
  31. package/.agents/skills/playwright-best-practices/core/projects-dependencies.md +453 -0
  32. package/.agents/skills/playwright-best-practices/core/test-data.md +492 -0
  33. package/.agents/skills/playwright-best-practices/core/test-suite-structure.md +361 -0
  34. package/.agents/skills/playwright-best-practices/core/test-tags.md +298 -0
  35. package/.agents/skills/playwright-best-practices/debugging/console-errors.md +420 -0
  36. package/.agents/skills/playwright-best-practices/debugging/debugging.md +504 -0
  37. package/.agents/skills/playwright-best-practices/debugging/error-testing.md +360 -0
  38. package/.agents/skills/playwright-best-practices/debugging/flaky-tests.md +496 -0
  39. package/.agents/skills/playwright-best-practices/frameworks/angular.md +530 -0
  40. package/.agents/skills/playwright-best-practices/frameworks/nextjs.md +469 -0
  41. package/.agents/skills/playwright-best-practices/frameworks/react.md +531 -0
  42. package/.agents/skills/playwright-best-practices/frameworks/vue.md +574 -0
  43. package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/ci-cd.md +468 -0
  44. package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/docker.md +283 -0
  45. package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/github-actions.md +546 -0
  46. package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/gitlab.md +397 -0
  47. package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/other-providers.md +521 -0
  48. package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/parallel-sharding.md +371 -0
  49. package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/performance.md +453 -0
  50. package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/reporting.md +424 -0
  51. package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/test-coverage.md +497 -0
  52. package/.agents/skills/playwright-best-practices/testing-patterns/accessibility.md +359 -0
  53. package/.agents/skills/playwright-best-practices/testing-patterns/api-testing.md +719 -0
  54. package/.agents/skills/playwright-best-practices/testing-patterns/browser-extensions.md +506 -0
  55. package/.agents/skills/playwright-best-practices/testing-patterns/canvas-webgl.md +493 -0
  56. package/.agents/skills/playwright-best-practices/testing-patterns/component-testing.md +500 -0
  57. package/.agents/skills/playwright-best-practices/testing-patterns/drag-drop.md +576 -0
  58. package/.agents/skills/playwright-best-practices/testing-patterns/electron.md +509 -0
  59. package/.agents/skills/playwright-best-practices/testing-patterns/file-operations.md +377 -0
  60. package/.agents/skills/playwright-best-practices/testing-patterns/file-upload-download.md +562 -0
  61. package/.agents/skills/playwright-best-practices/testing-patterns/forms-validation.md +561 -0
  62. package/.agents/skills/playwright-best-practices/testing-patterns/graphql-testing.md +331 -0
  63. package/.agents/skills/playwright-best-practices/testing-patterns/i18n.md +508 -0
  64. package/.agents/skills/playwright-best-practices/testing-patterns/performance-testing.md +476 -0
  65. package/.agents/skills/playwright-best-practices/testing-patterns/security-testing.md +430 -0
  66. package/.agents/skills/playwright-best-practices/testing-patterns/visual-regression.md +634 -0
  67. package/.env.example +21 -0
  68. package/README.md +30 -0
  69. package/bin/arcality.mjs +86 -0
  70. package/package.json +66 -0
  71. package/playwright.config.ts +12 -0
  72. package/scripts/cleanup-qmsdev.mjs +63 -0
  73. package/scripts/discover-view.mjs +52 -0
  74. package/scripts/extract-view.mjs +64 -0
  75. package/scripts/gen-and-run.mjs +838 -0
  76. package/scripts/init.mjs +290 -0
  77. package/scripts/migrate-to-central-out.mjs +157 -0
  78. package/scripts/postinstall.mjs +63 -0
  79. package/scripts/rebrand-report.mjs +241 -0
  80. package/scripts/setup.mjs +166 -0
  81. package/src/KnowledgeService.ts +239 -0
  82. package/src/arcalityClient.mjs +266 -0
  83. package/src/configLoader.mjs +179 -0
  84. package/src/configManager.mjs +172 -0
  85. package/src/consoleBanner.ts +32 -0
  86. package/src/envSetup.ts +205 -0
  87. package/src/index.ts +25 -0
  88. package/src/projectInspector.ts +42 -0
  89. package/src/services/collectiveMemoryService.ts +178 -0
  90. package/src/testRunner.ts +201 -0
  91. package/tests/_helpers/ArcalityReporter.ts +490 -0
  92. package/tests/_helpers/agentic-runner.spec.ts +741 -0
  93. package/tests/_helpers/ai-agent-helper.ts +1573 -0
  94. package/tests/_helpers/discover-view.spec.ts +238 -0
  95. package/tests/_helpers/extract-view.spec.ts +118 -0
  96. package/tests/_helpers/qa-tools.ts +333 -0
  97. package/tests/_helpers/smart-action.spec.ts +1458 -0
@@ -0,0 +1,452 @@
1
+ # Advanced Network Interception
2
+
3
+ ## Table of Contents
4
+
5
+ 1. [Request Modification](#request-modification)
6
+ 2. [GraphQL Mocking](#graphql-mocking)
7
+ 3. [HAR Recording & Playback](#har-recording--playback)
8
+ 4. [Conditional Mocking](#conditional-mocking)
9
+ 5. [Network Throttling](#network-throttling)
10
+
11
+ ## Request Modification
12
+
13
+ ### Modify Request Headers
14
+
15
+ ```typescript
16
+ test("add auth header to requests", async ({ page }) => {
17
+ await page.route("**/api/**", (route) => {
18
+ const headers = {
19
+ ...route.request().headers(),
20
+ Authorization: "Bearer test-token",
21
+ "X-Test-Header": "test-value",
22
+ };
23
+ route.continue({ headers });
24
+ });
25
+
26
+ await page.goto("/dashboard");
27
+ });
28
+ ```
29
+
30
+ ### Modify Request Body
31
+
32
+ ```typescript
33
+ test("modify POST body", async ({ page }) => {
34
+ await page.route("**/api/orders", async (route) => {
35
+ if (route.request().method() === "POST") {
36
+ const postData = route.request().postDataJSON();
37
+
38
+ // Add test metadata
39
+ const modifiedData = {
40
+ ...postData,
41
+ testMode: true,
42
+ testTimestamp: Date.now(),
43
+ };
44
+
45
+ await route.continue({
46
+ postData: JSON.stringify(modifiedData),
47
+ });
48
+ } else {
49
+ await route.continue();
50
+ }
51
+ });
52
+
53
+ await page.goto("/checkout");
54
+ await page.getByRole("button", { name: "Place Order" }).click();
55
+ });
56
+ ```
57
+
58
+ ### Transform Response
59
+
60
+ ```typescript
61
+ test("modify API response", async ({ page }) => {
62
+ await page.route("**/api/products", async (route) => {
63
+ // Fetch real response
64
+ const response = await route.fetch();
65
+ const json = await response.json();
66
+
67
+ // Modify response
68
+ const modified = json.map((product: any) => ({
69
+ ...product,
70
+ price: product.price * 0.9, // 10% discount
71
+ testMode: true,
72
+ }));
73
+
74
+ await route.fulfill({
75
+ response,
76
+ json: modified,
77
+ });
78
+ });
79
+
80
+ await page.goto("/products");
81
+ });
82
+ ```
83
+
84
+ ## GraphQL Mocking
85
+
86
+ ### Mock by Operation Name
87
+
88
+ ```typescript
89
+ test("mock GraphQL query", async ({ page }) => {
90
+ await page.route("**/graphql", async (route) => {
91
+ const postData = route.request().postDataJSON();
92
+
93
+ if (postData.operationName === "GetUser") {
94
+ return route.fulfill({
95
+ json: {
96
+ data: {
97
+ user: {
98
+ id: "1",
99
+ name: "Test User",
100
+ email: "test@example.com",
101
+ },
102
+ },
103
+ },
104
+ });
105
+ }
106
+
107
+ if (postData.operationName === "GetProducts") {
108
+ return route.fulfill({
109
+ json: {
110
+ data: {
111
+ products: [
112
+ { id: "1", name: "Product A", price: 29.99 },
113
+ { id: "2", name: "Product B", price: 49.99 },
114
+ ],
115
+ },
116
+ },
117
+ });
118
+ }
119
+
120
+ // Pass through unmocked operations
121
+ return route.continue();
122
+ });
123
+
124
+ await page.goto("/dashboard");
125
+ });
126
+ ```
127
+
128
+ ### GraphQL Mock Fixture
129
+
130
+ ```typescript
131
+ // fixtures/graphql.fixture.ts
132
+ type GraphQLMock = {
133
+ operation: string;
134
+ variables?: Record<string, any>;
135
+ response: { data?: any; errors?: any[] };
136
+ };
137
+
138
+ type GraphQLFixtures = {
139
+ mockGraphQL: (mocks: GraphQLMock[]) => Promise<void>;
140
+ };
141
+
142
+ export const test = base.extend<GraphQLFixtures>({
143
+ mockGraphQL: async ({ page }, use) => {
144
+ await use(async (mocks) => {
145
+ await page.route("**/graphql", async (route) => {
146
+ const postData = route.request().postDataJSON();
147
+
148
+ const mock = mocks.find((m) => {
149
+ if (m.operation !== postData.operationName) return false;
150
+
151
+ // Optionally match variables
152
+ if (m.variables) {
153
+ return (
154
+ JSON.stringify(m.variables) === JSON.stringify(postData.variables)
155
+ );
156
+ }
157
+ return true;
158
+ });
159
+
160
+ if (mock) {
161
+ return route.fulfill({ json: mock.response });
162
+ }
163
+
164
+ return route.continue();
165
+ });
166
+ });
167
+ },
168
+ });
169
+
170
+ // Usage
171
+ test("dashboard with mocked GraphQL", async ({ page, mockGraphQL }) => {
172
+ await mockGraphQL([
173
+ {
174
+ operation: "GetDashboardStats",
175
+ response: {
176
+ data: { stats: { users: 100, revenue: 50000 } },
177
+ },
178
+ },
179
+ {
180
+ operation: "GetUser",
181
+ variables: { id: "1" },
182
+ response: {
183
+ data: { user: { id: "1", name: "John" } },
184
+ },
185
+ },
186
+ ]);
187
+
188
+ await page.goto("/dashboard");
189
+ await expect(page.getByText("100 users")).toBeVisible();
190
+ });
191
+ ```
192
+
193
+ ### Mock GraphQL Mutations
194
+
195
+ ```typescript
196
+ test("mock GraphQL mutation", async ({ page }) => {
197
+ await page.route("**/graphql", async (route) => {
198
+ const postData = route.request().postDataJSON();
199
+
200
+ if (postData.operationName === "CreateOrder") {
201
+ const { input } = postData.variables;
202
+
203
+ return route.fulfill({
204
+ json: {
205
+ data: {
206
+ createOrder: {
207
+ id: "order-123",
208
+ status: "PENDING",
209
+ items: input.items,
210
+ total: input.items.reduce(
211
+ (sum: number, item: any) => sum + item.price * item.quantity,
212
+ 0,
213
+ ),
214
+ },
215
+ },
216
+ },
217
+ });
218
+ }
219
+
220
+ return route.continue();
221
+ });
222
+
223
+ await page.goto("/checkout");
224
+ await page.getByRole("button", { name: "Place Order" }).click();
225
+
226
+ await expect(page.getByText("Order #order-123")).toBeVisible();
227
+ });
228
+ ```
229
+
230
+ ## HAR Recording & Playback
231
+
232
+ ### Record HAR File
233
+
234
+ ```typescript
235
+ // Record network traffic
236
+ test("record HAR", async ({ page, context }) => {
237
+ // Start recording
238
+ await context.routeFromHAR("./recordings/checkout.har", {
239
+ update: true, // Create/update HAR file
240
+ url: "**/api/**",
241
+ });
242
+
243
+ await page.goto("/checkout");
244
+ await page.getByRole("button", { name: "Place Order" }).click();
245
+
246
+ // HAR file is saved automatically
247
+ });
248
+ ```
249
+
250
+ ### Playback HAR File
251
+
252
+ ```typescript
253
+ // Use recorded HAR for offline testing
254
+ test("playback HAR", async ({ page, context }) => {
255
+ await context.routeFromHAR("./recordings/checkout.har", {
256
+ url: "**/api/**",
257
+ update: false, // Don't update, just playback
258
+ });
259
+
260
+ await page.goto("/checkout");
261
+
262
+ // All API calls served from HAR file
263
+ await expect(page.getByText("Order confirmed")).toBeVisible();
264
+ });
265
+ ```
266
+
267
+ ### HAR with Fallback
268
+
269
+ ```typescript
270
+ test("HAR with live fallback", async ({ page, context }) => {
271
+ await context.routeFromHAR("./recordings/api.har", {
272
+ url: "**/api/**",
273
+ update: false,
274
+ notFound: "fallback", // Use real network if not in HAR
275
+ });
276
+
277
+ await page.goto("/dashboard");
278
+ });
279
+ ```
280
+
281
+ ## Conditional Mocking
282
+
283
+ ### Mock Based on Request Body
284
+
285
+ ```typescript
286
+ test("conditional mock by body", async ({ page }) => {
287
+ await page.route("**/api/search", async (route) => {
288
+ const body = route.request().postDataJSON();
289
+
290
+ if (body.query === "error") {
291
+ return route.fulfill({
292
+ status: 500,
293
+ json: { error: "Search failed" },
294
+ });
295
+ }
296
+
297
+ if (body.query === "empty") {
298
+ return route.fulfill({
299
+ json: { results: [] },
300
+ });
301
+ }
302
+
303
+ // Default response
304
+ return route.fulfill({
305
+ json: {
306
+ results: [{ id: 1, title: `Result for: ${body.query}` }],
307
+ },
308
+ });
309
+ });
310
+
311
+ await page.goto("/search");
312
+
313
+ // Test different scenarios
314
+ await page.getByLabel("Search").fill("error");
315
+ await page.getByLabel("Search").press("Enter");
316
+ await expect(page.getByText("Search failed")).toBeVisible();
317
+ });
318
+ ```
319
+
320
+ ### Mock Nth Request
321
+
322
+ ```typescript
323
+ test("different response on retry", async ({ page }) => {
324
+ let callCount = 0;
325
+
326
+ await page.route("**/api/status", (route) => {
327
+ callCount++;
328
+
329
+ if (callCount < 3) {
330
+ return route.fulfill({
331
+ status: 503,
332
+ json: { error: "Service unavailable" },
333
+ });
334
+ }
335
+
336
+ // Succeed on 3rd attempt
337
+ return route.fulfill({
338
+ json: { status: "ok" },
339
+ });
340
+ });
341
+
342
+ await page.goto("/dashboard");
343
+
344
+ // App should retry and eventually succeed
345
+ await expect(page.getByText("Connected")).toBeVisible();
346
+ });
347
+ ```
348
+
349
+ ### Mock with Delay
350
+
351
+ ```typescript
352
+ test("slow network simulation", async ({ page }) => {
353
+ await page.route("**/api/data", async (route) => {
354
+ // Simulate 2 second delay
355
+ await new Promise((resolve) => setTimeout(resolve, 2000));
356
+
357
+ return route.fulfill({
358
+ json: { data: "loaded" },
359
+ });
360
+ });
361
+
362
+ await page.goto("/dashboard");
363
+
364
+ // Loading state should appear
365
+ await expect(page.getByText("Loading...")).toBeVisible();
366
+
367
+ // Then data appears
368
+ await expect(page.getByText("loaded")).toBeVisible();
369
+ });
370
+ ```
371
+
372
+ ## Network Throttling
373
+
374
+ ### Slow 3G Simulation
375
+
376
+ ```typescript
377
+ test("slow network experience", async ({ page, context }) => {
378
+ // Create CDP session for network throttling
379
+ const client = await context.newCDPSession(page);
380
+
381
+ await client.send("Network.emulateNetworkConditions", {
382
+ offline: false,
383
+ downloadThroughput: (500 * 1024) / 8, // 500 Kbps
384
+ uploadThroughput: (500 * 1024) / 8,
385
+ latency: 400, // 400ms
386
+ });
387
+
388
+ await page.goto("/");
389
+
390
+ // Test loading states appear
391
+ await expect(page.getByTestId("skeleton-loader")).toBeVisible();
392
+ });
393
+ ```
394
+
395
+ ### Offline Mode
396
+
397
+ Use `context.setOffline(true/false)` to simulate network connectivity changes.
398
+
399
+ > **For comprehensive offline testing patterns:**
400
+ >
401
+ > - **Network failure simulation** (error recovery, graceful degradation): See [error-testing.md](error-testing.md#offline-testing)
402
+ > - **Offline-first/PWA testing** (service workers, caching, background sync): See [service-workers.md](service-workers.md#offline-testing)
403
+
404
+ ### Network Throttling Fixture
405
+
406
+ ```typescript
407
+ // fixtures/network.fixture.ts
408
+ type NetworkCondition = "slow3g" | "fast3g" | "offline";
409
+
410
+ const conditions = {
411
+ slow3g: { downloadThroughput: 50000, uploadThroughput: 50000, latency: 2000 },
412
+ fast3g: { downloadThroughput: 180000, uploadThroughput: 75000, latency: 150 },
413
+ };
414
+
415
+ type NetworkFixtures = {
416
+ setNetworkCondition: (condition: NetworkCondition) => Promise<void>;
417
+ };
418
+
419
+ export const test = base.extend<NetworkFixtures>({
420
+ setNetworkCondition: async ({ page, context }, use) => {
421
+ const client = await context.newCDPSession(page);
422
+
423
+ await use(async (condition) => {
424
+ if (condition === "offline") {
425
+ await context.setOffline(true);
426
+ } else {
427
+ await client.send("Network.emulateNetworkConditions", {
428
+ offline: false,
429
+ ...conditions[condition],
430
+ });
431
+ }
432
+ });
433
+
434
+ // Reset
435
+ await context.setOffline(false);
436
+ },
437
+ });
438
+ ```
439
+
440
+ ## Anti-Patterns to Avoid
441
+
442
+ | Anti-Pattern | Problem | Solution |
443
+ | ------------------------ | ------------------------------ | -------------------------------- |
444
+ | Mocking all requests | Tests don't reflect reality | Mock only what's necessary |
445
+ | No cleanup of routes | Routes persist across tests | Use fixtures with cleanup |
446
+ | Ignoring request method | Mock applies to wrong requests | Check `route.request().method()` |
447
+ | Hardcoded mock responses | Brittle, hard to maintain | Use factories for mock data |
448
+
449
+ ## Related References
450
+
451
+ - **Basic Mocking**: See [test-suite-structure.md](../core/test-suite-structure.md) for simple mocking
452
+ - **WebSockets**: See [websockets.md](../browser-apis/websockets.md) for real-time mocking