@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,331 @@
1
+ # GraphQL Testing
2
+
3
+ ## Table of Contents
4
+
5
+ 1. [Patterns](#patterns)
6
+ 2. [Anti-Patterns](#anti-patterns)
7
+ 3. [Troubleshooting](#troubleshooting)
8
+
9
+ > **When to use**: Testing GraphQL APIs — queries, mutations, variables, and error handling.
10
+
11
+ ## Patterns
12
+
13
+ ### Basic Query with Variables
14
+
15
+ All GraphQL requests go through `POST` to a single endpoint. Send `query`, `variables`, and optionally `operationName` in the JSON body.
16
+
17
+ ```typescript
18
+ import { test, expect } from "@playwright/test";
19
+
20
+ const GQL_ENDPOINT = "/graphql";
21
+
22
+ test("query with variables", async ({ request }) => {
23
+ const resp = await request.post(GQL_ENDPOINT, {
24
+ data: {
25
+ query: `
26
+ query FetchItem($id: ID!) {
27
+ item(id: $id) {
28
+ id
29
+ title
30
+ price
31
+ reviews { id rating }
32
+ }
33
+ }
34
+ `,
35
+ variables: { id: "101" },
36
+ },
37
+ });
38
+
39
+ expect(resp.ok()).toBeTruthy();
40
+ const { data, errors } = await resp.json();
41
+
42
+ // GraphQL returns 200 even on errors — always check both
43
+ expect(errors).toBeUndefined();
44
+ expect(data.item).toMatchObject({
45
+ id: "101",
46
+ title: expect.any(String),
47
+ price: expect.any(Number),
48
+ });
49
+ expect(data.item.reviews).toEqual(
50
+ expect.arrayContaining([
51
+ expect.objectContaining({
52
+ id: expect.any(String),
53
+ rating: expect.any(Number),
54
+ }),
55
+ ])
56
+ );
57
+ });
58
+ ```
59
+
60
+ ### Mutations
61
+
62
+ ```typescript
63
+ import { test, expect } from "@playwright/test";
64
+
65
+ const GQL_ENDPOINT = "/graphql";
66
+
67
+ test("mutation creates resource", async ({ request }) => {
68
+ const resp = await request.post(GQL_ENDPOINT, {
69
+ data: {
70
+ query: `
71
+ mutation AddItem($input: ItemInput!) {
72
+ addItem(input: $input) {
73
+ id
74
+ title
75
+ status
76
+ }
77
+ }
78
+ `,
79
+ variables: {
80
+ input: {
81
+ title: "New Widget",
82
+ price: 15.0,
83
+ status: "DRAFT",
84
+ },
85
+ },
86
+ },
87
+ });
88
+
89
+ const { data, errors } = await resp.json();
90
+ expect(errors).toBeUndefined();
91
+ expect(data.addItem).toMatchObject({
92
+ id: expect.any(String),
93
+ title: "New Widget",
94
+ status: "DRAFT",
95
+ });
96
+ });
97
+ ```
98
+
99
+ ### Validation Errors
100
+
101
+ ```typescript
102
+ import { test, expect } from "@playwright/test";
103
+
104
+ const GQL_ENDPOINT = "/graphql";
105
+
106
+ test("handles validation errors", async ({ request }) => {
107
+ const resp = await request.post(GQL_ENDPOINT, {
108
+ data: {
109
+ query: `
110
+ mutation AddItem($input: ItemInput!) {
111
+ addItem(input: $input) { id }
112
+ }
113
+ `,
114
+ variables: { input: { title: "" } },
115
+ },
116
+ });
117
+
118
+ const { data, errors } = await resp.json();
119
+ expect(errors).toBeDefined();
120
+ expect(errors.length).toBeGreaterThan(0);
121
+ expect(errors[0].message).toContain("title");
122
+ expect(errors[0].extensions?.code).toBe("BAD_USER_INPUT");
123
+ });
124
+ ```
125
+
126
+ ### Authorization Errors
127
+
128
+ ```typescript
129
+ import { test, expect } from "@playwright/test";
130
+
131
+ const GQL_ENDPOINT = "/graphql";
132
+
133
+ test("handles authorization errors", async ({ request }) => {
134
+ const resp = await request.post(GQL_ENDPOINT, {
135
+ data: {
136
+ query: `
137
+ query AdminDashboard {
138
+ adminMetrics { revenue activeUsers }
139
+ }
140
+ `,
141
+ },
142
+ });
143
+
144
+ const { data, errors } = await resp.json();
145
+ expect(errors).toBeDefined();
146
+ expect(errors[0].extensions?.code).toBe("UNAUTHORIZED");
147
+ expect(data?.adminMetrics).toBeNull();
148
+ });
149
+ ```
150
+
151
+ ### Authenticated GraphQL Fixture
152
+
153
+ ```typescript
154
+ // fixtures/graphql-fixtures.ts
155
+ import { test as base, expect, APIRequestContext } from "@playwright/test";
156
+
157
+ type GraphQLFixtures = {
158
+ gqlClient: APIRequestContext;
159
+ adminGqlClient: APIRequestContext;
160
+ };
161
+
162
+ export const test = base.extend<GraphQLFixtures>({
163
+ gqlClient: async ({ playwright }, use) => {
164
+ const ctx = await playwright.request.newContext({
165
+ baseURL: "https://api.myapp.io",
166
+ extraHTTPHeaders: {
167
+ Authorization: `Bearer ${process.env.API_TOKEN}`,
168
+ "Content-Type": "application/json",
169
+ },
170
+ });
171
+ await use(ctx);
172
+ await ctx.dispose();
173
+ },
174
+
175
+ adminGqlClient: async ({ playwright }, use) => {
176
+ const loginCtx = await playwright.request.newContext({
177
+ baseURL: "https://api.myapp.io",
178
+ });
179
+ const loginResp = await loginCtx.post("/graphql", {
180
+ data: {
181
+ query: `
182
+ mutation Login($email: String!, $password: String!) {
183
+ login(email: $email, password: $password) { token }
184
+ }
185
+ `,
186
+ variables: {
187
+ email: process.env.ADMIN_EMAIL,
188
+ password: process.env.ADMIN_PASSWORD,
189
+ },
190
+ },
191
+ });
192
+ const { data } = await loginResp.json();
193
+
194
+ if (!data?.login?.token) {
195
+ throw new Error(`Admin login failed: status ${loginResp.status()}, response: ${JSON.stringify(data)}`);
196
+ }
197
+
198
+ await loginCtx.dispose();
199
+
200
+ const ctx = await playwright.request.newContext({
201
+ baseURL: "https://api.myapp.io",
202
+ extraHTTPHeaders: {
203
+ Authorization: `Bearer ${data.login.token}`,
204
+ "Content-Type": "application/json",
205
+ },
206
+ });
207
+ await use(ctx);
208
+ await ctx.dispose();
209
+ },
210
+ });
211
+
212
+ export { expect };
213
+ ```
214
+
215
+ ### GraphQL Helper Function
216
+
217
+ ```typescript
218
+ // utils/graphql.ts
219
+ import { APIRequestContext, expect } from "@playwright/test";
220
+
221
+ export async function gqlQuery<T = any>(
222
+ request: APIRequestContext,
223
+ query: string,
224
+ variables?: Record<string, any>
225
+ ): Promise<{ data: T; errors?: any[] }> {
226
+ const resp = await request.post("/graphql", {
227
+ data: { query, variables },
228
+ });
229
+ expect(resp.ok()).toBeTruthy();
230
+ return resp.json();
231
+ }
232
+
233
+ export async function gqlMutation<T = any>(
234
+ request: APIRequestContext,
235
+ mutation: string,
236
+ variables?: Record<string, any>
237
+ ): Promise<{ data: T; errors?: any[] }> {
238
+ return gqlQuery<T>(request, mutation, variables);
239
+ }
240
+ ```
241
+
242
+ ```typescript
243
+ // tests/api/items.spec.ts
244
+ import { test, expect } from "@playwright/test";
245
+ import { gqlQuery, gqlMutation } from "../../utils/graphql";
246
+
247
+ test("fetch and update item", async ({ request }) => {
248
+ const { data: fetchData } = await gqlQuery(
249
+ request,
250
+ `query GetItem($id: ID!) { item(id: $id) { id title } }`,
251
+ { id: "101" }
252
+ );
253
+ expect(fetchData.item.title).toBeDefined();
254
+
255
+ const { data: updateData, errors } = await gqlMutation(
256
+ request,
257
+ `mutation UpdateItem($id: ID!, $title: String!) {
258
+ updateItem(id: $id, title: $title) { id title }
259
+ }`,
260
+ { id: "101", title: "Updated Title" }
261
+ );
262
+ expect(errors).toBeUndefined();
263
+ expect(updateData.updateItem.title).toBe("Updated Title");
264
+ });
265
+ ```
266
+
267
+ ## Anti-Patterns
268
+
269
+ | Don't Do This | Problem | Do This Instead |
270
+ | --- | --- | --- |
271
+ | Check only `response.ok()` | GraphQL returns 200 even on errors — `errors` array is the real signal | Always check both `data` and `errors` in the response body |
272
+ | Ignore `errors` array | Validation and auth errors appear in `errors`, not HTTP status | Destructure and assert: `expect(errors).toBeUndefined()` |
273
+ | Hardcode query strings inline everywhere | Duplicated queries are hard to maintain | Extract queries to constants or use a helper function |
274
+ | Skip variable validation | Invalid variables cause cryptic server errors | Validate input shape before sending |
275
+
276
+ ## Troubleshooting
277
+
278
+ ### GraphQL returns 200 but data is null
279
+
280
+ **Cause**: GraphQL servers return HTTP 200 even when the query has errors. The actual error is in the `errors` array.
281
+
282
+ **Fix**: Always destructure and check both `data` and `errors`.
283
+
284
+ ```typescript
285
+ const { data, errors } = await resp.json();
286
+ if (errors) {
287
+ console.error("GraphQL errors:", JSON.stringify(errors, null, 2));
288
+ }
289
+ expect(errors).toBeUndefined();
290
+ expect(data.item).toBeDefined();
291
+ ```
292
+
293
+ ### "Cannot query field X on type Y"
294
+
295
+ **Cause**: The field doesn't exist in the schema, or you're querying the wrong type.
296
+
297
+ **Fix**: Verify the schema. Use introspection or check your GraphQL IDE for available fields.
298
+
299
+ ```typescript
300
+ // Introspection query to debug schema
301
+ const { data } = await request.post("/graphql", {
302
+ data: {
303
+ query: `{ __type(name: "Item") { fields { name type { name } } } }`,
304
+ },
305
+ });
306
+ console.log(data.__type.fields);
307
+ ```
308
+
309
+ ### Variables not being applied
310
+
311
+ **Cause**: Variable names in the query don't match the `variables` object keys, or types don't match.
312
+
313
+ **Fix**: Ensure variable names match exactly (case-sensitive) and types align with the schema.
314
+
315
+ ```typescript
316
+ // Wrong: variable name mismatch
317
+ const resp = await request.post("/graphql", {
318
+ data: {
319
+ query: `query GetItem($itemId: ID!) { item(id: $itemId) { id } }`,
320
+ variables: { id: "101" }, // Should be { itemId: "101" }
321
+ },
322
+ });
323
+
324
+ // Correct
325
+ const resp = await request.post("/graphql", {
326
+ data: {
327
+ query: `query GetItem($itemId: ID!) { item(id: $itemId) { id } }`,
328
+ variables: { itemId: "101" },
329
+ },
330
+ });
331
+ ```