@arcadialdev/arcality 2.4.28 → 2.4.30

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 (83) hide show
  1. package/README.md +2 -2
  2. package/package.json +3 -7
  3. package/scripts/gen-and-run.mjs +5 -18
  4. package/src/KnowledgeService.ts +256 -0
  5. package/src/arcalityClient.mjs +2 -1
  6. package/src/consoleBanner.ts +32 -0
  7. package/src/envSetup.ts +205 -0
  8. package/src/index.ts +25 -0
  9. package/src/projectInspector.ts +42 -0
  10. package/src/services/collectiveMemoryService.ts +178 -0
  11. package/src/services/securityScanner.ts +128 -0
  12. package/src/testRunner.ts +201 -0
  13. package/tests/_helpers/agentic-runner.bundle.spec.js +2912 -83
  14. package/.agents/skills/e2e-testing-expert/SKILL.md +0 -28
  15. package/.agents/skills/frontend-design/LICENSE.txt +0 -177
  16. package/.agents/skills/frontend-design/SKILL.md +0 -42
  17. package/.agents/skills/nodejs-backend-patterns/SKILL.md +0 -639
  18. package/.agents/skills/nodejs-backend-patterns/references/advanced-patterns.md +0 -430
  19. package/.agents/skills/playwright-best-practices/LICENSE.md +0 -7
  20. package/.agents/skills/playwright-best-practices/README.md +0 -147
  21. package/.agents/skills/playwright-best-practices/SKILL.md +0 -303
  22. package/.agents/skills/playwright-best-practices/advanced/authentication-flows.md +0 -360
  23. package/.agents/skills/playwright-best-practices/advanced/authentication.md +0 -871
  24. package/.agents/skills/playwright-best-practices/advanced/clock-mocking.md +0 -364
  25. package/.agents/skills/playwright-best-practices/advanced/mobile-testing.md +0 -409
  26. package/.agents/skills/playwright-best-practices/advanced/multi-context.md +0 -288
  27. package/.agents/skills/playwright-best-practices/advanced/multi-user.md +0 -393
  28. package/.agents/skills/playwright-best-practices/advanced/network-advanced.md +0 -452
  29. package/.agents/skills/playwright-best-practices/advanced/third-party.md +0 -464
  30. package/.agents/skills/playwright-best-practices/architecture/pom-vs-fixtures.md +0 -363
  31. package/.agents/skills/playwright-best-practices/architecture/test-architecture.md +0 -369
  32. package/.agents/skills/playwright-best-practices/architecture/when-to-mock.md +0 -383
  33. package/.agents/skills/playwright-best-practices/browser-apis/browser-apis.md +0 -391
  34. package/.agents/skills/playwright-best-practices/browser-apis/iframes.md +0 -403
  35. package/.agents/skills/playwright-best-practices/browser-apis/service-workers.md +0 -504
  36. package/.agents/skills/playwright-best-practices/browser-apis/websockets.md +0 -403
  37. package/.agents/skills/playwright-best-practices/core/annotations.md +0 -424
  38. package/.agents/skills/playwright-best-practices/core/assertions-waiting.md +0 -361
  39. package/.agents/skills/playwright-best-practices/core/configuration.md +0 -452
  40. package/.agents/skills/playwright-best-practices/core/fixtures-hooks.md +0 -417
  41. package/.agents/skills/playwright-best-practices/core/global-setup.md +0 -434
  42. package/.agents/skills/playwright-best-practices/core/locators.md +0 -242
  43. package/.agents/skills/playwright-best-practices/core/page-object-model.md +0 -315
  44. package/.agents/skills/playwright-best-practices/core/projects-dependencies.md +0 -453
  45. package/.agents/skills/playwright-best-practices/core/test-data.md +0 -492
  46. package/.agents/skills/playwright-best-practices/core/test-suite-structure.md +0 -361
  47. package/.agents/skills/playwright-best-practices/core/test-tags.md +0 -298
  48. package/.agents/skills/playwright-best-practices/debugging/console-errors.md +0 -420
  49. package/.agents/skills/playwright-best-practices/debugging/debugging.md +0 -504
  50. package/.agents/skills/playwright-best-practices/debugging/error-testing.md +0 -360
  51. package/.agents/skills/playwright-best-practices/debugging/flaky-tests.md +0 -496
  52. package/.agents/skills/playwright-best-practices/frameworks/angular.md +0 -530
  53. package/.agents/skills/playwright-best-practices/frameworks/nextjs.md +0 -469
  54. package/.agents/skills/playwright-best-practices/frameworks/react.md +0 -531
  55. package/.agents/skills/playwright-best-practices/frameworks/vue.md +0 -574
  56. package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/ci-cd.md +0 -468
  57. package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/docker.md +0 -283
  58. package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/github-actions.md +0 -546
  59. package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/gitlab.md +0 -397
  60. package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/other-providers.md +0 -521
  61. package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/parallel-sharding.md +0 -371
  62. package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/performance.md +0 -453
  63. package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/reporting.md +0 -424
  64. package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/test-coverage.md +0 -497
  65. package/.agents/skills/playwright-best-practices/testing-patterns/accessibility.md +0 -359
  66. package/.agents/skills/playwright-best-practices/testing-patterns/api-testing.md +0 -719
  67. package/.agents/skills/playwright-best-practices/testing-patterns/browser-extensions.md +0 -506
  68. package/.agents/skills/playwright-best-practices/testing-patterns/canvas-webgl.md +0 -493
  69. package/.agents/skills/playwright-best-practices/testing-patterns/component-testing.md +0 -500
  70. package/.agents/skills/playwright-best-practices/testing-patterns/drag-drop.md +0 -576
  71. package/.agents/skills/playwright-best-practices/testing-patterns/electron.md +0 -509
  72. package/.agents/skills/playwright-best-practices/testing-patterns/file-operations.md +0 -377
  73. package/.agents/skills/playwright-best-practices/testing-patterns/file-upload-download.md +0 -562
  74. package/.agents/skills/playwright-best-practices/testing-patterns/forms-validation.md +0 -561
  75. package/.agents/skills/playwright-best-practices/testing-patterns/graphql-testing.md +0 -331
  76. package/.agents/skills/playwright-best-practices/testing-patterns/i18n.md +0 -508
  77. package/.agents/skills/playwright-best-practices/testing-patterns/performance-testing.md +0 -476
  78. package/.agents/skills/playwright-best-practices/testing-patterns/security-testing.md +0 -430
  79. package/.agents/skills/playwright-best-practices/testing-patterns/visual-regression.md +0 -634
  80. package/.agents/skills/security-qa/SKILL.md +0 -254
  81. package/public/ArcalityImagen.png +0 -0
  82. package/public/logo-arcadial-blanco.png +0 -0
  83. package/public/logo.png +0 -0
@@ -1,403 +0,0 @@
1
- # iFrame Testing
2
-
3
- ## Table of Contents
4
-
5
- 1. [Basic iFrame Access](#basic-iframe-access)
6
- 2. [Cross-Origin iFrames](#cross-origin-iframes)
7
- 3. [Nested iFrames](#nested-iframes)
8
- 4. [Dynamic iFrames](#dynamic-iframes)
9
- 5. [iFrame Navigation](#iframe-navigation)
10
- 6. [Common Patterns](#common-patterns)
11
-
12
- ## Basic iFrame Access
13
-
14
- ### Using frameLocator
15
-
16
- ```typescript
17
- // Access iframe by selector
18
- const frame = page.frameLocator("iframe#payment");
19
- await frame.getByRole("button", { name: "Pay" }).click();
20
-
21
- // Access by name attribute
22
- const namedFrame = page.frameLocator('iframe[name="checkout"]');
23
- await namedFrame.getByLabel("Card number").fill("4242424242424242");
24
-
25
- // Access by title
26
- const titledFrame = page.frameLocator('iframe[title="Payment Form"]');
27
-
28
- // Access by src (partial match)
29
- const srcFrame = page.frameLocator('iframe[src*="stripe.com"]');
30
- ```
31
-
32
- ### Frame vs FrameLocator
33
-
34
- ```typescript
35
- // frameLocator - for locator-based operations (recommended)
36
- const frameLocator = page.frameLocator("#my-iframe");
37
- await frameLocator.getByRole("button").click();
38
-
39
- // frame() - for Frame object operations (navigation, evaluation)
40
- const frame = page.frame({ name: "my-frame" });
41
- if (frame) {
42
- await frame.goto("https://example.com");
43
- const title = await frame.title();
44
- }
45
-
46
- // Get all frames
47
- const frames = page.frames();
48
- for (const f of frames) {
49
- console.log("Frame URL:", f.url());
50
- }
51
- ```
52
-
53
- ### Waiting for iFrame Content
54
-
55
- ```typescript
56
- // Wait for iframe to load
57
- const frame = page.frameLocator("#dynamic-iframe");
58
-
59
- // Wait for element inside iframe
60
- await expect(frame.getByRole("heading")).toBeVisible({ timeout: 10000 });
61
-
62
- // Wait for iframe src to change
63
- await page.waitForFunction(() => {
64
- const iframe = document.querySelector("iframe#my-frame") as HTMLIFrameElement;
65
- return iframe?.src.includes("loaded");
66
- });
67
- ```
68
-
69
- ## Cross-Origin iFrames
70
-
71
- ### Accessing Cross-Origin Content
72
-
73
- ```typescript
74
- // Cross-origin iframes work seamlessly with frameLocator
75
- const thirdPartyFrame = page.frameLocator('iframe[src*="third-party.com"]');
76
-
77
- // Interact with elements inside cross-origin iframe
78
- await thirdPartyFrame.getByRole("textbox").fill("test@example.com");
79
- await thirdPartyFrame.getByRole("button", { name: "Submit" }).click();
80
-
81
- // Wait for cross-origin iframe to be ready
82
- await expect(thirdPartyFrame.locator("body")).toBeVisible();
83
- ```
84
-
85
- ### Payment Provider iFrames (Stripe, PayPal)
86
-
87
- ```typescript
88
- test("Stripe payment iframe", async ({ page }) => {
89
- await page.goto("/checkout");
90
-
91
- // Stripe uses multiple iframes for each field
92
- const cardFrame = page
93
- .frameLocator('iframe[name*="__privateStripeFrame"]')
94
- .first();
95
-
96
- // Wait for Stripe to initialize
97
- await expect(cardFrame.locator('[placeholder="Card number"]')).toBeVisible({
98
- timeout: 15000,
99
- });
100
-
101
- // Fill card details
102
- await cardFrame
103
- .locator('[placeholder="Card number"]')
104
- .fill("4242424242424242");
105
- await cardFrame.locator('[placeholder="MM / YY"]').fill("12/30");
106
- await cardFrame.locator('[placeholder="CVC"]').fill("123");
107
- });
108
- ```
109
-
110
- ### Handling OAuth in iFrames
111
-
112
- ```typescript
113
- test("OAuth iframe flow", async ({ page }) => {
114
- await page.goto("/login");
115
- await page.getByRole("button", { name: "Sign in with Google" }).click();
116
-
117
- // If OAuth opens in iframe instead of popup
118
- const oauthFrame = page.frameLocator('iframe[src*="accounts.google.com"]');
119
-
120
- // Wait for OAuth form
121
- await expect(oauthFrame.getByLabel("Email")).toBeVisible({ timeout: 10000 });
122
- await oauthFrame.getByLabel("Email").fill("test@gmail.com");
123
- });
124
- ```
125
-
126
- ## Nested iFrames
127
-
128
- ### Accessing Nested Frames
129
-
130
- ```typescript
131
- // Parent iframe contains child iframe
132
- const parentFrame = page.frameLocator("#outer-frame");
133
- const childFrame = parentFrame.frameLocator("#inner-frame");
134
-
135
- // Interact with deeply nested content
136
- await childFrame.getByRole("button", { name: "Submit" }).click();
137
-
138
- // Multiple levels of nesting
139
- const level1 = page.frameLocator("#level1");
140
- const level2 = level1.frameLocator("#level2");
141
- const level3 = level2.frameLocator("#level3");
142
- await level3.getByText("Deep content").click();
143
- ```
144
-
145
- ### Finding Elements Across Frame Hierarchy
146
-
147
- ```typescript
148
- // Helper to search all frames for an element
149
- async function findInAnyFrame(
150
- page: Page,
151
- selector: string,
152
- ): Promise<Locator | null> {
153
- // Check main page first
154
- const mainCount = await page.locator(selector).count();
155
- if (mainCount > 0) return page.locator(selector);
156
-
157
- // Check all frames
158
- for (const frame of page.frames()) {
159
- const count = await frame.locator(selector).count();
160
- if (count > 0) {
161
- return frame.locator(selector);
162
- }
163
- }
164
- return null;
165
- }
166
-
167
- test("find element in any frame", async ({ page }) => {
168
- await page.goto("/complex-page");
169
- const element = await findInAnyFrame(page, '[data-testid="submit-btn"]');
170
- if (element) await element.click();
171
- });
172
- ```
173
-
174
- ## Dynamic iFrames
175
-
176
- ### iFrames Created at Runtime
177
-
178
- ```typescript
179
- test("handle dynamically created iframe", async ({ page }) => {
180
- await page.goto("/dashboard");
181
-
182
- // Click button that creates iframe
183
- await page.getByRole("button", { name: "Open Widget" }).click();
184
-
185
- // Wait for iframe to appear in DOM
186
- await page.waitForSelector("iframe#widget-frame");
187
-
188
- // Now access the frame
189
- const widgetFrame = page.frameLocator("#widget-frame");
190
- await expect(widgetFrame.getByText("Widget Loaded")).toBeVisible();
191
- });
192
- ```
193
-
194
- ### iFrames with Changing src
195
-
196
- ```typescript
197
- test("iframe src changes", async ({ page }) => {
198
- await page.goto("/multi-step");
199
-
200
- const frame = page.frameLocator("#step-frame");
201
-
202
- // Step 1
203
- await expect(frame.getByText("Step 1")).toBeVisible();
204
- await frame.getByRole("button", { name: "Next" }).click();
205
-
206
- // Wait for iframe to reload with new content
207
- await expect(frame.getByText("Step 2")).toBeVisible({ timeout: 10000 });
208
- await frame.getByRole("button", { name: "Next" }).click();
209
-
210
- // Step 3
211
- await expect(frame.getByText("Step 3")).toBeVisible({ timeout: 10000 });
212
- });
213
- ```
214
-
215
- ### Lazy-Loaded iFrames
216
-
217
- ```typescript
218
- test("lazy loaded iframe", async ({ page }) => {
219
- await page.goto("/page-with-lazy-iframe");
220
-
221
- // Scroll to trigger lazy load
222
- await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
223
-
224
- // Wait for iframe to load
225
- const lazyFrame = page.frameLocator("#lazy-iframe");
226
- await expect(lazyFrame.locator("body")).not.toBeEmpty({ timeout: 15000 });
227
-
228
- // Interact with content
229
- await lazyFrame.getByRole("button").click();
230
- });
231
- ```
232
-
233
- ## iFrame Navigation
234
-
235
- ### Navigating Within iFrame
236
-
237
- ```typescript
238
- test("iframe internal navigation", async ({ page }) => {
239
- await page.goto("/app");
240
-
241
- // Get frame object for navigation control
242
- const frame = page.frame({ name: "content-frame" });
243
- if (!frame) throw new Error("Frame not found");
244
-
245
- // Navigate within iframe
246
- await frame.goto("https://embedded-app.com/page2");
247
-
248
- // Wait for navigation
249
- await frame.waitForURL("**/page2");
250
-
251
- // Verify content
252
- await expect(frame.getByRole("heading")).toHaveText("Page 2");
253
- });
254
- ```
255
-
256
- ### Handling Frame Navigation Events
257
-
258
- ```typescript
259
- test("track iframe navigation", async ({ page }) => {
260
- const navigations: string[] = [];
261
-
262
- // Listen to frame navigation
263
- page.on("framenavigated", (frame) => {
264
- if (frame.parentFrame()) {
265
- // This is an iframe navigation
266
- navigations.push(frame.url());
267
- }
268
- });
269
-
270
- await page.goto("/with-iframe");
271
- await page
272
- .frameLocator("#nav-frame")
273
- .getByRole("link", { name: "Page 2" })
274
- .click();
275
-
276
- // Verify navigation occurred
277
- expect(navigations.some((url) => url.includes("page2"))).toBe(true);
278
- });
279
- ```
280
-
281
- ## Common Patterns
282
-
283
- ### iFrame Fixture
284
-
285
- ```typescript
286
- // fixtures.ts
287
- import { test as base, FrameLocator } from "@playwright/test";
288
-
289
- export const test = base.extend<{ paymentFrame: FrameLocator }>({
290
- paymentFrame: async ({ page }, use) => {
291
- await page.goto("/checkout");
292
-
293
- // Wait for payment iframe to be ready
294
- const frame = page.frameLocator('iframe[src*="payment"]');
295
- await expect(frame.locator("body")).toBeVisible({ timeout: 15000 });
296
-
297
- await use(frame);
298
- },
299
- });
300
-
301
- // test file
302
- test("complete payment", async ({ paymentFrame }) => {
303
- await paymentFrame.getByLabel("Card").fill("4242424242424242");
304
- await paymentFrame.getByRole("button", { name: "Pay" }).click();
305
- });
306
- ```
307
-
308
- ### Debugging iFrame Issues
309
-
310
- ```typescript
311
- test("debug iframe content", async ({ page }) => {
312
- await page.goto("/page-with-iframes");
313
-
314
- // List all frames
315
- console.log("All frames:");
316
- for (const frame of page.frames()) {
317
- console.log(` - ${frame.name() || "(unnamed)"}: ${frame.url()}`);
318
- }
319
-
320
- // Screenshot specific iframe content
321
- const frame = page.frame({ name: "target-frame" });
322
- if (frame) {
323
- const body = frame.locator("body");
324
- await body.screenshot({ path: "iframe-content.png" });
325
- }
326
-
327
- // Get iframe HTML for debugging
328
- const frameContent = page.frameLocator("#my-frame");
329
- const html = await frameContent.locator("body").innerHTML();
330
- console.log("iFrame HTML:", html.substring(0, 500));
331
- });
332
- ```
333
-
334
- ### Handling iFrame Load Failures
335
-
336
- ```typescript
337
- test("handle iframe load failure", async ({ page }) => {
338
- await page.goto("/page-with-unreliable-iframe");
339
-
340
- const frame = page.frameLocator("#unreliable-frame");
341
-
342
- try {
343
- // Try to interact with iframe content
344
- await expect(frame.getByRole("button")).toBeVisible({ timeout: 5000 });
345
- await frame.getByRole("button").click();
346
- } catch (error) {
347
- // Fallback: refresh iframe
348
- await page.evaluate(() => {
349
- const iframe = document.querySelector(
350
- "#unreliable-frame",
351
- ) as HTMLIFrameElement;
352
- if (iframe) iframe.src = iframe.src;
353
- });
354
-
355
- // Retry
356
- await expect(frame.getByRole("button")).toBeVisible({ timeout: 10000 });
357
- await frame.getByRole("button").click();
358
- }
359
- });
360
- ```
361
-
362
- ### Mocking iFrame Content
363
-
364
- ```typescript
365
- test("mock iframe response", async ({ page }) => {
366
- // Intercept iframe src request
367
- await page.route("**/embedded-widget**", (route) => {
368
- route.fulfill({
369
- contentType: "text/html",
370
- body: `
371
- <!DOCTYPE html>
372
- <html>
373
- <body>
374
- <h1>Mocked Widget</h1>
375
- <button>Mocked Button</button>
376
- </body>
377
- </html>
378
- `,
379
- });
380
- });
381
-
382
- await page.goto("/page-with-widget");
383
-
384
- const frame = page.frameLocator("#widget-frame");
385
- await expect(frame.getByRole("heading")).toHaveText("Mocked Widget");
386
- });
387
- ```
388
-
389
- ## Anti-Patterns to Avoid
390
-
391
- | Anti-Pattern | Problem | Solution |
392
- | ------------------------------------- | --------------------------------- | -------------------------------------------------- |
393
- | Using `page.frame()` for interactions | Less reliable than frameLocator | Use `page.frameLocator()` for element interactions |
394
- | Hardcoding iframe index | Fragile if DOM order changes | Use name, id, or src attribute selectors |
395
- | Not waiting for iframe load | Race conditions | Wait for element inside iframe to be visible |
396
- | Assuming same-origin | Cross-origin has different timing | Always wait for iframe content explicitly |
397
- | Ignoring nested iframes | Element not found | Chain frameLocator calls for nested frames |
398
-
399
- ## Related References
400
-
401
- - **Locators**: See [locators.md](../core/locators.md) for selector strategies
402
- - **Third-party services**: See [third-party.md](../advanced/third-party.md) for payment iframe patterns
403
- - **Debugging**: See [debugging.md](../debugging/debugging.md) for troubleshooting iframe issues