@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,417 @@
1
+ # Fixtures & Hooks
2
+
3
+ ## Table of Contents
4
+
5
+ 1. [Built-in Fixtures](#built-in-fixtures)
6
+ 2. [Custom Fixtures](#custom-fixtures)
7
+ 3. [Fixture Scopes](#fixture-scopes)
8
+ 4. [Hooks](#hooks)
9
+ 5. [Authentication Patterns](#authentication-patterns)
10
+ 6. [Database Fixtures](#database-fixtures)
11
+
12
+ ## Built-in Fixtures
13
+
14
+ ### Core Fixtures
15
+
16
+ ```typescript
17
+ test("example", async ({
18
+ page, // Isolated page instance
19
+ context, // Browser context (cookies, localStorage)
20
+ browser, // Browser instance
21
+ browserName, // 'chromium', 'firefox', or 'webkit'
22
+ request, // API request context
23
+ }) => {
24
+ // Each test gets fresh instances
25
+ });
26
+ ```
27
+
28
+ ### Request Fixture
29
+
30
+ ```typescript
31
+ test("API call", async ({ request }) => {
32
+ const response = await request.get("/api/users");
33
+ await expect(response).toBeOK();
34
+
35
+ const users = await response.json();
36
+ expect(users).toHaveLength(5);
37
+ });
38
+ ```
39
+
40
+ ## Custom Fixtures
41
+
42
+ ### Basic Custom Fixture
43
+
44
+ ```typescript
45
+ // fixtures.ts
46
+ import { test as base } from "@playwright/test";
47
+
48
+ // Declare fixture types
49
+ type MyFixtures = {
50
+ todoPage: TodoPage;
51
+ apiClient: ApiClient;
52
+ };
53
+
54
+ export const test = base.extend<MyFixtures>({
55
+ // Fixture with setup and teardown
56
+ todoPage: async ({ page }, use) => {
57
+ const todoPage = new TodoPage(page);
58
+ await todoPage.goto();
59
+
60
+ await use(todoPage); // Test runs here
61
+
62
+ // Teardown (optional)
63
+ await todoPage.clearTodos();
64
+ },
65
+
66
+ // Simple fixture
67
+ apiClient: async ({ request }, use) => {
68
+ await use(new ApiClient(request));
69
+ },
70
+ });
71
+
72
+ export { expect } from "@playwright/test";
73
+ ```
74
+
75
+ ### Fixture with Options
76
+
77
+ ```typescript
78
+ type Options = {
79
+ defaultUser: { email: string; password: string };
80
+ };
81
+
82
+ type Fixtures = {
83
+ authenticatedPage: Page;
84
+ };
85
+
86
+ export const test = base.extend<Options & Fixtures>({
87
+ // Define option with default
88
+ defaultUser: [
89
+ { email: "test@example.com", password: "pass123" },
90
+ { option: true },
91
+ ],
92
+
93
+ // Use option in fixture
94
+ authenticatedPage: async ({ page, defaultUser }, use) => {
95
+ await page.goto("/login");
96
+ await page.getByLabel("Email").fill(defaultUser.email);
97
+ await page.getByLabel("Password").fill(defaultUser.password);
98
+ await page.getByRole("button", { name: "Sign in" }).click();
99
+ await use(page);
100
+ },
101
+ });
102
+
103
+ // Override in config
104
+ export default defineConfig({
105
+ use: {
106
+ defaultUser: { email: "admin@example.com", password: "admin123" },
107
+ },
108
+ });
109
+ ```
110
+
111
+ ### Automatic Fixtures
112
+
113
+ ```typescript
114
+ export const test = base.extend<{}, { setupDb: void }>({
115
+ // Auto-fixture runs for every test without explicit usage
116
+ setupDb: [
117
+ async ({}, use) => {
118
+ await seedDatabase();
119
+ await use();
120
+ await cleanDatabase();
121
+ },
122
+ { auto: true },
123
+ ],
124
+ });
125
+ ```
126
+
127
+ ## Fixture Scopes
128
+
129
+ ### Test Scope (Default)
130
+
131
+ Created fresh for each test:
132
+
133
+ ```typescript
134
+ test.extend({
135
+ page: async ({ browser }, use) => {
136
+ const page = await browser.newPage();
137
+ await use(page);
138
+ await page.close();
139
+ },
140
+ });
141
+ ```
142
+
143
+ ### Worker Scope
144
+
145
+ Shared across tests in the same worker (each worker gets its own instance; tests in different workers do not share it):
146
+
147
+ ```typescript
148
+ type WorkerFixtures = {
149
+ sharedAccount: Account;
150
+ };
151
+
152
+ export const test = base.extend<{}, WorkerFixtures>({
153
+ sharedAccount: [
154
+ async ({ browser }, use) => {
155
+ // Expensive setup - runs once per worker
156
+ const account = await createTestAccount();
157
+ await use(account);
158
+ await deleteTestAccount(account);
159
+ },
160
+ { scope: "worker" },
161
+ ],
162
+ });
163
+ ```
164
+
165
+ ### Isolate test data between parallel workers
166
+
167
+ When tests in different workers touch the same backend or DB (e.g. same user, same tenant), they can collide and cause flaky failures. Use `testInfo.workerIndex` (or `process.env.TEST_WORKER_INDEX`) in a worker-scoped fixture to create unique data per worker:
168
+
169
+ ```typescript
170
+ import { test as baseTest } from "@playwright/test";
171
+
172
+ type WorkerFixtures = {
173
+ dbUserName: string;
174
+ };
175
+
176
+ export const test = baseTest.extend<{}, WorkerFixtures>({
177
+ dbUserName: [
178
+ async ({}, use, testInfo) => {
179
+ const userName = `user-${testInfo.workerIndex}`;
180
+ await createUserInTestDatabase(userName);
181
+ await use(userName);
182
+ await deleteUserFromTestDatabase(userName);
183
+ },
184
+ { scope: "worker" },
185
+ ],
186
+ });
187
+ ```
188
+
189
+ Then each worker uses a distinct user (e.g. `user-1`, `user-2`), so parallel workers do not overwrite each other’s data.
190
+
191
+ ## Hooks
192
+
193
+ ### beforeEach / afterEach
194
+
195
+ ```typescript
196
+ test.beforeEach(async ({ page }) => {
197
+ // Runs before each test in file
198
+ await page.goto("/");
199
+ });
200
+
201
+ test.afterEach(async ({ page }, testInfo) => {
202
+ // Runs after each test
203
+ if (testInfo.status !== "passed") {
204
+ await page.screenshot({ path: `failed-${testInfo.title}.png` });
205
+ }
206
+ });
207
+ ```
208
+
209
+ ### beforeAll / afterAll
210
+
211
+ ```typescript
212
+ test.beforeAll(async ({ browser }) => {
213
+ // Runs once before all tests in file
214
+ // Note: Cannot use page fixture here
215
+ });
216
+
217
+ test.afterAll(async () => {
218
+ // Runs once after all tests in file
219
+ });
220
+ ```
221
+
222
+ ### Describe-Level Hooks
223
+
224
+ ```typescript
225
+ test.describe("User Management", () => {
226
+ test.beforeEach(async ({ page }) => {
227
+ await page.goto("/users");
228
+ });
229
+
230
+ test("can list users", async ({ page }) => {
231
+ // Starts at /users
232
+ });
233
+
234
+ test("can add user", async ({ page }) => {
235
+ // Starts at /users
236
+ });
237
+ });
238
+ ```
239
+
240
+ ## Authentication Patterns
241
+
242
+ ### Global Setup with Storage State
243
+
244
+ ```typescript
245
+ // auth.setup.ts
246
+ import { test as setup, expect } from "@playwright/test";
247
+
248
+ const authFile = ".auth/user.json";
249
+
250
+ setup("authenticate", async ({ page }) => {
251
+ await page.goto("/login");
252
+ await page.getByLabel("Email").fill(process.env.TEST_EMAIL!);
253
+ await page.getByLabel("Password").fill(process.env.TEST_PASSWORD!);
254
+ await page.getByRole("button", { name: "Sign in" }).click();
255
+
256
+ await expect(page.getByRole("heading", { name: "Dashboard" })).toBeVisible();
257
+ await page.context().storageState({ path: authFile });
258
+ });
259
+ ```
260
+
261
+ ```typescript
262
+ // playwright.config.ts
263
+ export default defineConfig({
264
+ projects: [
265
+ { name: "setup", testMatch: /.*\.setup\.ts/ },
266
+ {
267
+ name: "chromium",
268
+ use: {
269
+ ...devices["Desktop Chrome"],
270
+ storageState: ".auth/user.json",
271
+ },
272
+ dependencies: ["setup"],
273
+ },
274
+ ],
275
+ });
276
+ ```
277
+
278
+ ### Multiple Auth States
279
+
280
+ ```typescript
281
+ // auth.setup.ts
282
+ setup("admin auth", async ({ page }) => {
283
+ await login(page, "admin@example.com", "adminpass");
284
+ await page.context().storageState({ path: ".auth/admin.json" });
285
+ });
286
+
287
+ setup("user auth", async ({ page }) => {
288
+ await login(page, "user@example.com", "userpass");
289
+ await page.context().storageState({ path: ".auth/user.json" });
290
+ });
291
+ ```
292
+
293
+ ```typescript
294
+ // playwright.config.ts
295
+ projects: [
296
+ {
297
+ name: "admin tests",
298
+ testMatch: /.*admin.*\.spec\.ts/,
299
+ use: { storageState: ".auth/admin.json" },
300
+ dependencies: ["setup"],
301
+ },
302
+ {
303
+ name: "user tests",
304
+ testMatch: /.*user.*\.spec\.ts/,
305
+ use: { storageState: ".auth/user.json" },
306
+ dependencies: ["setup"],
307
+ },
308
+ ];
309
+ ```
310
+
311
+ ### Auth Fixture
312
+
313
+ ```typescript
314
+ // fixtures/auth.fixture.ts
315
+ export const test = base.extend<{ adminPage: Page; userPage: Page }>({
316
+ adminPage: async ({ browser }, use) => {
317
+ const context = await browser.newContext({
318
+ storageState: ".auth/admin.json",
319
+ });
320
+ const page = await context.newPage();
321
+ await use(page);
322
+ await context.close();
323
+ },
324
+
325
+ userPage: async ({ browser }, use) => {
326
+ const context = await browser.newContext({
327
+ storageState: ".auth/user.json",
328
+ });
329
+ const page = await context.newPage();
330
+ await use(page);
331
+ await context.close();
332
+ },
333
+ });
334
+ ```
335
+
336
+ ## Database Fixtures
337
+
338
+ This section covers **per-test database fixtures** (isolation, transaction rollback). For related topics:
339
+
340
+ - **Test data factories** (builders, Faker): See [test-data.md](test-data.md)
341
+ - **One-time database setup** (migrations, snapshots): See [global-setup.md](global-setup.md#database-patterns)
342
+
343
+ ### Transaction Rollback Pattern
344
+
345
+ ```typescript
346
+ import { test as base } from "@playwright/test";
347
+ import { db } from "../db";
348
+
349
+ export const test = base.extend<{ dbTransaction: Transaction }>({
350
+ dbTransaction: async ({}, use) => {
351
+ const transaction = await db.beginTransaction();
352
+
353
+ await use(transaction);
354
+
355
+ await transaction.rollback(); // Clean slate for next test
356
+ },
357
+ });
358
+ ```
359
+
360
+ ### Seed Data Fixture
361
+
362
+ ```typescript
363
+ type TestData = {
364
+ testUser: User;
365
+ testProducts: Product[];
366
+ };
367
+
368
+ export const test = base.extend<TestData>({
369
+ testUser: async ({}, use) => {
370
+ const user = await db.users.create({
371
+ email: `test-${Date.now()}@example.com`,
372
+ name: "Test User",
373
+ });
374
+
375
+ await use(user);
376
+
377
+ await db.users.delete(user.id);
378
+ },
379
+
380
+ testProducts: async ({ testUser }, use) => {
381
+ const products = await db.products.createMany([
382
+ { name: "Product A", ownerId: testUser.id },
383
+ { name: "Product B", ownerId: testUser.id },
384
+ ]);
385
+
386
+ await use(products);
387
+
388
+ await db.products.deleteMany(products.map((p) => p.id));
389
+ },
390
+ });
391
+ ```
392
+
393
+ ## Fixture Tips
394
+
395
+ | Tip | Explanation |
396
+ | ------------------ | ------------------------------------------- |
397
+ | Fixtures are lazy | Only created when used |
398
+ | Compose fixtures | Use other fixtures as dependencies |
399
+ | Keep setup minimal | Do heavy lifting in worker-scoped fixtures |
400
+ | Clean up resources | Use teardown in fixtures, not afterEach |
401
+ | Avoid shared state | Each fixture instance should be independent |
402
+
403
+ ## Anti-Patterns to Avoid
404
+
405
+ | Anti-Pattern | Problem | Solution |
406
+ | ----------------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
407
+ | Shared mutable state between tests | Race conditions, order dependencies | Use fixtures for isolation |
408
+ | Global variables in tests | Tests depend on execution order | Use fixtures or beforeEach for setup |
409
+ | Not cleaning up test data | Tests interfere with each other | Use fixtures with teardown or database transactions |
410
+ | Shared `page` or `context` in `beforeAll` | State leak between tests; flaky when tests run in parallel | Use default one-context-per-test, or `beforeEach` + fresh page; if serial is required, prefer `test.describe.configure({ mode: 'serial' })` and document that isolation is sacrificed |
411
+ | Backend/DB state shared across workers | Tests in different workers collide on same data | Use worker-scoped fixture with `testInfo.workerIndex` to create unique data per worker |
412
+
413
+ ## Related References
414
+
415
+ - **Page Objects with fixtures**: See [page-object-model.md](page-object-model.md) for POM patterns
416
+ - **Test organization**: See [test-suite-structure.md](test-suite-structure.md) for test structure
417
+ - **Debugging fixture issues**: See [debugging.md](../debugging/debugging.md) for troubleshooting