@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,403 @@
1
+ # WebSocket & Real-Time Testing
2
+
3
+ ## Table of Contents
4
+
5
+ 1. [WebSocket Basics](#websocket-basics)
6
+ 2. [Mocking WebSocket Messages](#mocking-websocket-messages)
7
+ 3. [Testing Real-Time Features](#testing-real-time-features)
8
+ 4. [Server-Sent Events](#server-sent-events)
9
+ 5. [Reconnection Testing](#reconnection-testing)
10
+
11
+ ## WebSocket Basics
12
+
13
+ ### Wait for WebSocket Connection
14
+
15
+ ```typescript
16
+ test("chat connects via websocket", async ({ page }) => {
17
+ // Listen for WebSocket connection
18
+ const wsPromise = page.waitForEvent("websocket");
19
+
20
+ await page.goto("/chat");
21
+
22
+ const ws = await wsPromise;
23
+ expect(ws.url()).toContain("/ws/chat");
24
+
25
+ // Wait for connection to be established
26
+ await ws.waitForEvent("framesent");
27
+ });
28
+ ```
29
+
30
+ ### Monitor WebSocket Messages
31
+
32
+ ```typescript
33
+ test("receives real-time updates", async ({ page }) => {
34
+ const messages: string[] = [];
35
+
36
+ // Set up listener before navigation
37
+ page.on("websocket", (ws) => {
38
+ ws.on("framereceived", (frame) => {
39
+ messages.push(frame.payload as string);
40
+ });
41
+ });
42
+
43
+ await page.goto("/dashboard");
44
+
45
+ // Wait for some messages
46
+ await expect.poll(() => messages.length).toBeGreaterThan(0);
47
+
48
+ // Verify message format
49
+ const data = JSON.parse(messages[0]);
50
+ expect(data).toHaveProperty("type");
51
+ });
52
+ ```
53
+
54
+ ### Capture Sent Messages
55
+
56
+ ```typescript
57
+ test("sends correct message format", async ({ page }) => {
58
+ const sentMessages: string[] = [];
59
+
60
+ page.on("websocket", (ws) => {
61
+ ws.on("framesent", (frame) => {
62
+ sentMessages.push(frame.payload as string);
63
+ });
64
+ });
65
+
66
+ await page.goto("/chat");
67
+ await page.getByLabel("Message").fill("Hello!");
68
+ await page.getByRole("button", { name: "Send" }).click();
69
+
70
+ // Verify sent message
71
+ await expect.poll(() => sentMessages.length).toBeGreaterThan(0);
72
+
73
+ const sent = JSON.parse(sentMessages[sentMessages.length - 1]);
74
+ expect(sent).toEqual({
75
+ type: "message",
76
+ content: "Hello!",
77
+ });
78
+ });
79
+ ```
80
+
81
+ ## Mocking WebSocket Messages
82
+
83
+ ### Inject Messages via Page Evaluate
84
+
85
+ ```typescript
86
+ test("displays incoming chat message", async ({ page }) => {
87
+ await page.goto("/chat");
88
+
89
+ // Wait for WebSocket to be ready
90
+ await page.waitForFunction(
91
+ () => (window as any).chatSocket?.readyState === 1,
92
+ );
93
+
94
+ // Simulate incoming message
95
+ await page.evaluate(() => {
96
+ const event = new MessageEvent("message", {
97
+ data: JSON.stringify({
98
+ type: "message",
99
+ from: "Alice",
100
+ content: "Hello there!",
101
+ }),
102
+ });
103
+ (window as any).chatSocket.dispatchEvent(event);
104
+ });
105
+
106
+ await expect(page.getByText("Alice: Hello there!")).toBeVisible();
107
+ });
108
+ ```
109
+
110
+ ### Mock WebSocket with Route Handler
111
+
112
+ ```typescript
113
+ test("mock websocket entirely", async ({ page, context }) => {
114
+ // Intercept the WebSocket upgrade
115
+ await context.route("**/ws/**", async (route) => {
116
+ // For WebSocket routes, we can't fulfill directly
117
+ // Instead, use page.evaluate to mock the client-side
118
+ });
119
+
120
+ // Alternative: Mock at application level
121
+ await page.addInitScript(() => {
122
+ const OriginalWebSocket = window.WebSocket;
123
+ (window as any).WebSocket = function (url: string) {
124
+ const ws = {
125
+ readyState: 1,
126
+ send: (data: string) => {
127
+ console.log("WS Send:", data);
128
+ },
129
+ close: () => {},
130
+ addEventListener: () => {},
131
+ removeEventListener: () => {},
132
+ };
133
+ setTimeout(() => ws.onopen?.(), 100);
134
+ return ws;
135
+ };
136
+ });
137
+
138
+ await page.goto("/chat");
139
+ });
140
+ ```
141
+
142
+ ### WebSocket Mock Fixture
143
+
144
+ ```typescript
145
+ // fixtures/websocket.fixture.ts
146
+ import { test as base, Page } from "@playwright/test";
147
+
148
+ type WsMessage = { type: string; [key: string]: any };
149
+
150
+ type WebSocketFixtures = {
151
+ mockWebSocket: {
152
+ injectMessage: (message: WsMessage) => Promise<void>;
153
+ getSentMessages: () => Promise<WsMessage[]>;
154
+ };
155
+ };
156
+
157
+ export const test = base.extend<WebSocketFixtures>({
158
+ mockWebSocket: async ({ page }, use) => {
159
+ const sentMessages: WsMessage[] = [];
160
+
161
+ // Capture sent messages
162
+ await page.addInitScript(() => {
163
+ (window as any).__wsSent = [];
164
+ const OriginalWebSocket = window.WebSocket;
165
+ window.WebSocket = function (url: string) {
166
+ const ws = new OriginalWebSocket(url);
167
+ const originalSend = ws.send.bind(ws);
168
+ ws.send = (data: string) => {
169
+ (window as any).__wsSent.push(JSON.parse(data));
170
+ originalSend(data);
171
+ };
172
+ (window as any).__ws = ws;
173
+ return ws;
174
+ } as any;
175
+ });
176
+
177
+ await use({
178
+ injectMessage: async (message) => {
179
+ await page.evaluate((msg) => {
180
+ const event = new MessageEvent("message", {
181
+ data: JSON.stringify(msg),
182
+ });
183
+ (window as any).__ws?.dispatchEvent(event);
184
+ }, message);
185
+ },
186
+ getSentMessages: async () => {
187
+ return page.evaluate(() => (window as any).__wsSent || []);
188
+ },
189
+ });
190
+ },
191
+ });
192
+
193
+ // Usage
194
+ test("chat with mocked websocket", async ({ page, mockWebSocket }) => {
195
+ await page.goto("/chat");
196
+
197
+ // Inject incoming message
198
+ await mockWebSocket.injectMessage({
199
+ type: "message",
200
+ from: "Bob",
201
+ content: "Hi!",
202
+ });
203
+
204
+ await expect(page.getByText("Bob: Hi!")).toBeVisible();
205
+
206
+ // Send a reply
207
+ await page.getByLabel("Message").fill("Hello Bob!");
208
+ await page.getByRole("button", { name: "Send" }).click();
209
+
210
+ // Verify sent message
211
+ const sent = await mockWebSocket.getSentMessages();
212
+ expect(sent).toContainEqual(
213
+ expect.objectContaining({ content: "Hello Bob!" }),
214
+ );
215
+ });
216
+ ```
217
+
218
+ ## Testing Real-Time Features
219
+
220
+ ### Live Notifications
221
+
222
+ ```typescript
223
+ test("displays live notification", async ({ page }) => {
224
+ await page.goto("/dashboard");
225
+
226
+ // Simulate notification via WebSocket
227
+ await page.evaluate(() => {
228
+ const event = new MessageEvent("message", {
229
+ data: JSON.stringify({
230
+ type: "notification",
231
+ title: "New Order",
232
+ message: "Order #123 received",
233
+ }),
234
+ });
235
+ (window as any).notificationSocket.dispatchEvent(event);
236
+ });
237
+
238
+ await expect(page.getByRole("alert")).toContainText("Order #123 received");
239
+ });
240
+ ```
241
+
242
+ ### Live Data Updates
243
+
244
+ ```typescript
245
+ test("updates stock price in real-time", async ({ page }) => {
246
+ await page.goto("/stocks/AAPL");
247
+
248
+ const priceElement = page.getByTestId("stock-price");
249
+ const initialPrice = await priceElement.textContent();
250
+
251
+ // Simulate price update
252
+ await page.evaluate(() => {
253
+ const event = new MessageEvent("message", {
254
+ data: JSON.stringify({
255
+ type: "price_update",
256
+ symbol: "AAPL",
257
+ price: 150.25,
258
+ }),
259
+ });
260
+ (window as any).stockSocket.dispatchEvent(event);
261
+ });
262
+
263
+ await expect(priceElement).not.toHaveText(initialPrice!);
264
+ await expect(priceElement).toContainText("150.25");
265
+ });
266
+ ```
267
+
268
+ ### Collaborative Editing
269
+
270
+ ```typescript
271
+ test("shows collaborator cursor", async ({ page }) => {
272
+ await page.goto("/document/123");
273
+
274
+ // Simulate another user's cursor position
275
+ await page.evaluate(() => {
276
+ const event = new MessageEvent("message", {
277
+ data: JSON.stringify({
278
+ type: "cursor",
279
+ userId: "user-456",
280
+ userName: "Alice",
281
+ position: { x: 100, y: 200 },
282
+ }),
283
+ });
284
+ (window as any).docSocket.dispatchEvent(event);
285
+ });
286
+
287
+ await expect(page.getByTestId("cursor-user-456")).toBeVisible();
288
+ await expect(page.getByText("Alice")).toBeVisible();
289
+ });
290
+ ```
291
+
292
+ ## Server-Sent Events
293
+
294
+ ### Test SSE Updates
295
+
296
+ ```typescript
297
+ test("receives SSE updates", async ({ page }) => {
298
+ // Mock SSE endpoint
299
+ await page.route("**/api/events", (route) => {
300
+ route.fulfill({
301
+ status: 200,
302
+ headers: {
303
+ "Content-Type": "text/event-stream",
304
+ "Cache-Control": "no-cache",
305
+ Connection: "keep-alive",
306
+ },
307
+ body: `data: {"type":"update","value":42}\n\n`,
308
+ });
309
+ });
310
+
311
+ await page.goto("/live-data");
312
+
313
+ await expect(page.getByTestId("value")).toHaveText("42");
314
+ });
315
+ ```
316
+
317
+ ### Simulate Multiple SSE Events
318
+
319
+ ```typescript
320
+ test("handles multiple SSE events", async ({ page }) => {
321
+ await page.route("**/api/events", async (route) => {
322
+ const encoder = new TextEncoder();
323
+ const events = [
324
+ `data: {"count":1}\n\n`,
325
+ `data: {"count":2}\n\n`,
326
+ `data: {"count":3}\n\n`,
327
+ ];
328
+
329
+ route.fulfill({
330
+ status: 200,
331
+ headers: { "Content-Type": "text/event-stream" },
332
+ body: events.join(""),
333
+ });
334
+ });
335
+
336
+ await page.goto("/counter");
337
+
338
+ // Should receive all events
339
+ await expect(page.getByTestId("count")).toHaveText("3");
340
+ });
341
+ ```
342
+
343
+ ## Reconnection Testing
344
+
345
+ ### Test Connection Loss
346
+
347
+ ```typescript
348
+ test("handles connection loss gracefully", async ({ page }) => {
349
+ await page.goto("/chat");
350
+
351
+ // Simulate connection close
352
+ await page.evaluate(() => {
353
+ (window as any).chatSocket.close();
354
+ });
355
+
356
+ // Should show disconnected state
357
+ await expect(page.getByText("Reconnecting...")).toBeVisible();
358
+ });
359
+ ```
360
+
361
+ ### Test Reconnection
362
+
363
+ ```typescript
364
+ test("reconnects after connection loss", async ({ page }) => {
365
+ await page.goto("/chat");
366
+
367
+ // Simulate disconnect
368
+ await page.evaluate(() => {
369
+ (window as any).chatSocket.close();
370
+ });
371
+
372
+ await expect(page.getByText("Reconnecting...")).toBeVisible();
373
+
374
+ // Simulate reconnection
375
+ await page.evaluate(() => {
376
+ const event = new Event("open");
377
+ (window as any).chatSocket = { readyState: 1 };
378
+ (window as any).chatSocket.dispatchEvent?.(event);
379
+ });
380
+
381
+ // Force component to re-check connection
382
+ await page.evaluate(() => {
383
+ window.dispatchEvent(new Event("online"));
384
+ });
385
+
386
+ await expect(page.getByText("Connected")).toBeVisible();
387
+ });
388
+ ```
389
+
390
+ ## Anti-Patterns to Avoid
391
+
392
+ | Anti-Pattern | Problem | Solution |
393
+ | ------------------------------------- | ----------------------------- | ---------------------------------- |
394
+ | Not waiting for WebSocket ready | Messages sent too early | Wait for `readyState === 1` |
395
+ | Testing against real WebSocket server | Flaky, timing-dependent | Mock WebSocket messages |
396
+ | Ignoring connection state | Tests pass but feature broken | Test connected/disconnected states |
397
+ | No cleanup of listeners | Memory leaks in tests | Clean up event listeners |
398
+
399
+ ## Related References
400
+
401
+ - **Network**: See [network-advanced.md](../advanced/network-advanced.md) for HTTP mocking patterns
402
+ - **Assertions**: See [assertions-waiting.md](../core/assertions-waiting.md) for polling patterns
403
+ - **Multi-User**: See [multi-user.md](../advanced/multi-user.md) for real-time collaboration testing with multiple users