@browserbasehq/orca 3.2.1-preview.3 → 3.4.0-preview.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.
- package/dist/cjs/lib/inference.js +1 -8
- package/dist/cjs/lib/inference.js.map +1 -1
- package/dist/cjs/lib/prompt.js +3 -1
- package/dist/cjs/lib/prompt.js.map +1 -1
- package/dist/cjs/lib/v3/agent/AgentProvider.js +3 -0
- package/dist/cjs/lib/v3/agent/AgentProvider.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/fillFormVision.js +16 -12
- package/dist/cjs/lib/v3/agent/tools/fillFormVision.js.map +1 -1
- package/dist/cjs/lib/v3/agent/utils/validateExperimentalFeatures.js +0 -4
- package/dist/cjs/lib/v3/agent/utils/validateExperimentalFeatures.js.map +1 -1
- package/dist/cjs/lib/v3/api.d.ts +1 -0
- package/dist/cjs/lib/v3/api.js +15 -3
- package/dist/cjs/lib/v3/api.js.map +1 -1
- package/dist/cjs/lib/v3/dom/build/a11yScripts.generated.js +12 -12
- package/dist/cjs/lib/v3/dom/build/a11yScripts.generated.js.map +1 -1
- package/dist/cjs/lib/v3/dom/build/locatorScripts.generated.js +48 -48
- package/dist/cjs/lib/v3/dom/build/locatorScripts.generated.js.map +1 -1
- package/dist/cjs/lib/v3/dom/build/reRenderScriptContent.d.ts +1 -1
- package/dist/cjs/lib/v3/dom/build/reRenderScriptContent.js +1 -1
- package/dist/cjs/lib/v3/dom/build/reRenderScriptContent.js.map +1 -1
- package/dist/cjs/lib/v3/dom/build/screenshotScripts.generated.js +2 -2
- package/dist/cjs/lib/v3/dom/build/screenshotScripts.generated.js.map +1 -1
- package/dist/cjs/lib/v3/dom/build/scriptV3Content.d.ts +1 -1
- package/dist/cjs/lib/v3/dom/build/scriptV3Content.js +1 -1
- package/dist/cjs/lib/v3/dom/build/scriptV3Content.js.map +1 -1
- package/dist/cjs/lib/v3/handlers/extractHandler.js +3 -1
- package/dist/cjs/lib/v3/handlers/extractHandler.js.map +1 -1
- package/dist/cjs/lib/v3/handlers/v3AgentHandler.js +3 -5
- package/dist/cjs/lib/v3/handlers/v3AgentHandler.js.map +1 -1
- package/dist/cjs/lib/v3/index.d.ts +1 -1
- package/dist/cjs/lib/v3/llm/CerebrasClient.js +1 -1
- package/dist/cjs/lib/v3/llm/CerebrasClient.js.map +1 -1
- package/dist/cjs/lib/v3/llm/GroqClient.js +1 -1
- package/dist/cjs/lib/v3/llm/GroqClient.js.map +1 -1
- package/dist/cjs/lib/v3/types/private/agent.d.ts +5 -0
- package/dist/cjs/lib/v3/types/private/agent.js +11 -0
- package/dist/cjs/lib/v3/types/private/agent.js.map +1 -1
- package/dist/cjs/lib/v3/types/private/handlers.d.ts +1 -0
- package/dist/cjs/lib/v3/types/private/handlers.js.map +1 -1
- package/dist/cjs/lib/v3/types/private/snapshot.d.ts +8 -0
- package/dist/cjs/lib/v3/types/private/snapshot.js.map +1 -1
- package/dist/cjs/lib/v3/types/public/agent.d.ts +2 -3
- package/dist/cjs/lib/v3/types/public/agent.js +3 -0
- package/dist/cjs/lib/v3/types/public/agent.js.map +1 -1
- package/dist/cjs/lib/v3/types/public/api.d.ts +5 -1
- package/dist/cjs/lib/v3/types/public/api.js +15 -2
- package/dist/cjs/lib/v3/types/public/api.js.map +1 -1
- package/dist/cjs/lib/v3/types/public/methods.d.ts +1 -0
- package/dist/cjs/lib/v3/types/public/methods.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/a11yTree.js +21 -12
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/a11yTree.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/capture.d.ts +11 -2
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/capture.js +268 -21
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/capture.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/domTree.js +60 -7
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/domTree.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/frameRegistry.js +16 -5
- package/dist/cjs/lib/v3/understudy/frameRegistry.js.map +1 -1
- package/dist/cjs/lib/v3/v3.d.ts +1 -0
- package/dist/cjs/lib/v3/v3.js +15 -14
- package/dist/cjs/lib/v3/v3.js.map +1 -1
- package/dist/cjs/lib/version.d.ts +1 -1
- package/dist/cjs/lib/version.js +1 -1
- package/dist/cjs/lib/version.js.map +1 -1
- package/dist/cjs/tests/integration/observe-element-id-format.spec.js +130 -0
- package/dist/cjs/tests/integration/observe-element-id-format.spec.js.map +1 -0
- package/dist/cjs/tests/unit/agent-mode-routing.test.js +88 -0
- package/dist/cjs/tests/unit/agent-mode-routing.test.js.map +1 -0
- package/dist/cjs/tests/unit/agent-temperature.test.d.ts +1 -0
- package/dist/cjs/tests/unit/agent-temperature.test.js +191 -0
- package/dist/cjs/tests/unit/agent-temperature.test.js.map +1 -0
- package/dist/cjs/tests/unit/agent-variables-validation.test.d.ts +1 -0
- package/dist/cjs/tests/unit/agent-variables-validation.test.js +43 -0
- package/dist/cjs/tests/unit/agent-variables-validation.test.js.map +1 -0
- package/dist/cjs/tests/unit/api-client-observe-variables.test.js +47 -0
- package/dist/cjs/tests/unit/api-client-observe-variables.test.js.map +1 -1
- package/dist/cjs/tests/unit/api-optional-model-api-key.test.js +60 -0
- package/dist/cjs/tests/unit/api-optional-model-api-key.test.js.map +1 -1
- package/dist/cjs/tests/unit/api-variables-schema.test.js +25 -0
- package/dist/cjs/tests/unit/api-variables-schema.test.js.map +1 -1
- package/dist/cjs/tests/unit/frame-registry-oopif-adoption.test.d.ts +1 -0
- package/dist/cjs/tests/unit/frame-registry-oopif-adoption.test.js +60 -0
- package/dist/cjs/tests/unit/frame-registry-oopif-adoption.test.js.map +1 -0
- package/dist/cjs/tests/unit/inference-temperature.test.d.ts +1 -0
- package/dist/cjs/tests/unit/inference-temperature.test.js +65 -0
- package/dist/cjs/tests/unit/inference-temperature.test.js.map +1 -0
- package/dist/cjs/tests/unit/openai-compatible-temperature.test.d.ts +1 -0
- package/dist/cjs/tests/unit/openai-compatible-temperature.test.js +84 -0
- package/dist/cjs/tests/unit/openai-compatible-temperature.test.js.map +1 -0
- package/dist/cjs/tests/unit/prompt-observe-variables.test.js +6 -0
- package/dist/cjs/tests/unit/prompt-observe-variables.test.js.map +1 -1
- package/dist/cjs/tests/unit/public-api/llm-and-agents.test.js +3 -0
- package/dist/cjs/tests/unit/public-api/llm-and-agents.test.js.map +1 -1
- package/dist/cjs/tests/unit/public-api/public-types.test.js.map +1 -1
- package/dist/cjs/tests/unit/snapshot-a11y-resolvers.test.js +106 -5
- package/dist/cjs/tests/unit/snapshot-a11y-resolvers.test.js.map +1 -1
- package/dist/cjs/tests/unit/snapshot-a11y-tree-utils.test.js +20 -0
- package/dist/cjs/tests/unit/snapshot-a11y-tree-utils.test.js.map +1 -1
- package/dist/cjs/tests/unit/snapshot-capture-orchestration.test.js +119 -9
- package/dist/cjs/tests/unit/snapshot-capture-orchestration.test.js.map +1 -1
- package/dist/esm/lib/inference.js +1 -8
- package/dist/esm/lib/inference.js.map +1 -1
- package/dist/esm/lib/prompt.js +3 -1
- package/dist/esm/lib/prompt.js.map +1 -1
- package/dist/esm/lib/v3/agent/AgentProvider.js +3 -0
- package/dist/esm/lib/v3/agent/AgentProvider.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/fillFormVision.js +16 -12
- package/dist/esm/lib/v3/agent/tools/fillFormVision.js.map +1 -1
- package/dist/esm/lib/v3/agent/utils/validateExperimentalFeatures.js +0 -4
- package/dist/esm/lib/v3/agent/utils/validateExperimentalFeatures.js.map +1 -1
- package/dist/esm/lib/v3/api.d.ts +1 -0
- package/dist/esm/lib/v3/api.js +15 -3
- package/dist/esm/lib/v3/api.js.map +1 -1
- package/dist/esm/lib/v3/dom/build/a11yScripts.generated.js +12 -12
- package/dist/esm/lib/v3/dom/build/a11yScripts.generated.js.map +1 -1
- package/dist/esm/lib/v3/dom/build/locatorScripts.generated.js +48 -48
- package/dist/esm/lib/v3/dom/build/locatorScripts.generated.js.map +1 -1
- package/dist/esm/lib/v3/dom/build/reRenderScriptContent.d.ts +1 -1
- package/dist/esm/lib/v3/dom/build/reRenderScriptContent.js +1 -1
- package/dist/esm/lib/v3/dom/build/reRenderScriptContent.js.map +1 -1
- package/dist/esm/lib/v3/dom/build/screenshotScripts.generated.js +2 -2
- package/dist/esm/lib/v3/dom/build/screenshotScripts.generated.js.map +1 -1
- package/dist/esm/lib/v3/dom/build/scriptV3Content.d.ts +1 -1
- package/dist/esm/lib/v3/dom/build/scriptV3Content.js +1 -1
- package/dist/esm/lib/v3/dom/build/scriptV3Content.js.map +1 -1
- package/dist/esm/lib/v3/handlers/extractHandler.js +3 -1
- package/dist/esm/lib/v3/handlers/extractHandler.js.map +1 -1
- package/dist/esm/lib/v3/handlers/v3AgentHandler.js +3 -5
- package/dist/esm/lib/v3/handlers/v3AgentHandler.js.map +1 -1
- package/dist/esm/lib/v3/index.d.ts +1 -1
- package/dist/esm/lib/v3/llm/CerebrasClient.js +1 -1
- package/dist/esm/lib/v3/llm/CerebrasClient.js.map +1 -1
- package/dist/esm/lib/v3/llm/GroqClient.js +1 -1
- package/dist/esm/lib/v3/llm/GroqClient.js.map +1 -1
- package/dist/esm/lib/v3/types/private/agent.d.ts +5 -0
- package/dist/esm/lib/v3/types/private/agent.js +10 -1
- package/dist/esm/lib/v3/types/private/agent.js.map +1 -1
- package/dist/esm/lib/v3/types/private/handlers.d.ts +1 -0
- package/dist/esm/lib/v3/types/private/handlers.js.map +1 -1
- package/dist/esm/lib/v3/types/private/snapshot.d.ts +8 -0
- package/dist/esm/lib/v3/types/private/snapshot.js.map +1 -1
- package/dist/esm/lib/v3/types/public/agent.d.ts +2 -3
- package/dist/esm/lib/v3/types/public/agent.js +3 -0
- package/dist/esm/lib/v3/types/public/agent.js.map +1 -1
- package/dist/esm/lib/v3/types/public/api.d.ts +5 -1
- package/dist/esm/lib/v3/types/public/api.js +15 -2
- package/dist/esm/lib/v3/types/public/api.js.map +1 -1
- package/dist/esm/lib/v3/types/public/methods.d.ts +1 -0
- package/dist/esm/lib/v3/types/public/methods.js.map +1 -1
- package/dist/esm/lib/v3/understudy/a11y/snapshot/a11yTree.js +21 -12
- package/dist/esm/lib/v3/understudy/a11y/snapshot/a11yTree.js.map +1 -1
- package/dist/esm/lib/v3/understudy/a11y/snapshot/capture.d.ts +11 -2
- package/dist/esm/lib/v3/understudy/a11y/snapshot/capture.js +267 -22
- package/dist/esm/lib/v3/understudy/a11y/snapshot/capture.js.map +1 -1
- package/dist/esm/lib/v3/understudy/a11y/snapshot/domTree.js +60 -7
- package/dist/esm/lib/v3/understudy/a11y/snapshot/domTree.js.map +1 -1
- package/dist/esm/lib/v3/understudy/frameRegistry.js +16 -5
- package/dist/esm/lib/v3/understudy/frameRegistry.js.map +1 -1
- package/dist/esm/lib/v3/v3.d.ts +1 -0
- package/dist/esm/lib/v3/v3.js +15 -14
- package/dist/esm/lib/v3/v3.js.map +1 -1
- package/dist/esm/lib/version.d.ts +1 -1
- package/dist/esm/lib/version.js +1 -1
- package/dist/esm/lib/version.js.map +1 -1
- package/dist/esm/tests/integration/observe-element-id-format.spec.d.ts +1 -0
- package/dist/esm/tests/integration/observe-element-id-format.spec.js +128 -0
- package/dist/esm/tests/integration/observe-element-id-format.spec.js.map +1 -0
- package/dist/esm/tests/unit/agent-mode-routing.test.d.ts +1 -0
- package/dist/esm/tests/unit/agent-mode-routing.test.js +86 -0
- package/dist/esm/tests/unit/agent-mode-routing.test.js.map +1 -0
- package/dist/esm/tests/unit/agent-temperature.test.d.ts +1 -0
- package/dist/esm/tests/unit/agent-temperature.test.js +189 -0
- package/dist/esm/tests/unit/agent-temperature.test.js.map +1 -0
- package/dist/esm/tests/unit/agent-variables-validation.test.d.ts +1 -0
- package/dist/esm/tests/unit/agent-variables-validation.test.js +41 -0
- package/dist/esm/tests/unit/agent-variables-validation.test.js.map +1 -0
- package/dist/esm/tests/unit/api-client-observe-variables.test.js +47 -0
- package/dist/esm/tests/unit/api-client-observe-variables.test.js.map +1 -1
- package/dist/esm/tests/unit/api-optional-model-api-key.test.js +60 -0
- package/dist/esm/tests/unit/api-optional-model-api-key.test.js.map +1 -1
- package/dist/esm/tests/unit/api-variables-schema.test.js +25 -0
- package/dist/esm/tests/unit/api-variables-schema.test.js.map +1 -1
- package/dist/esm/tests/unit/frame-registry-oopif-adoption.test.d.ts +1 -0
- package/dist/esm/tests/unit/frame-registry-oopif-adoption.test.js +58 -0
- package/dist/esm/tests/unit/frame-registry-oopif-adoption.test.js.map +1 -0
- package/dist/esm/tests/unit/inference-temperature.test.d.ts +1 -0
- package/dist/esm/tests/unit/inference-temperature.test.js +63 -0
- package/dist/esm/tests/unit/inference-temperature.test.js.map +1 -0
- package/dist/esm/tests/unit/openai-compatible-temperature.test.d.ts +1 -0
- package/dist/esm/tests/unit/openai-compatible-temperature.test.js +82 -0
- package/dist/esm/tests/unit/openai-compatible-temperature.test.js.map +1 -0
- package/dist/esm/tests/unit/prompt-observe-variables.test.js +6 -0
- package/dist/esm/tests/unit/prompt-observe-variables.test.js.map +1 -1
- package/dist/esm/tests/unit/public-api/llm-and-agents.test.js +3 -0
- package/dist/esm/tests/unit/public-api/llm-and-agents.test.js.map +1 -1
- package/dist/esm/tests/unit/public-api/public-types.test.js.map +1 -1
- package/dist/esm/tests/unit/snapshot-a11y-resolvers.test.js +106 -5
- package/dist/esm/tests/unit/snapshot-a11y-resolvers.test.js.map +1 -1
- package/dist/esm/tests/unit/snapshot-a11y-tree-utils.test.js +20 -0
- package/dist/esm/tests/unit/snapshot-a11y-tree-utils.test.js.map +1 -1
- package/dist/esm/tests/unit/snapshot-capture-orchestration.test.js +119 -9
- package/dist/esm/tests/unit/snapshot-capture-orchestration.test.js.map +1 -1
- package/package.json +1 -1
- package/dist/cjs/tests/integration/agent-captcha-autosolve.spec.js +0 -56
- package/dist/cjs/tests/integration/agent-captcha-autosolve.spec.js.map +0 -1
- package/dist/esm/tests/integration/agent-captcha-autosolve.spec.js +0 -54
- package/dist/esm/tests/integration/agent-captcha-autosolve.spec.js.map +0 -1
- /package/dist/cjs/tests/integration/{agent-captcha-autosolve.spec.d.ts → observe-element-id-format.spec.d.ts} +0 -0
- /package/dist/{esm/tests/integration/agent-captcha-autosolve.spec.d.ts → cjs/tests/unit/agent-mode-routing.test.d.ts} +0 -0
|
@@ -3,6 +3,7 @@ import * as capture from "../../lib/v3/understudy/a11y/snapshot/capture.js";
|
|
|
3
3
|
import * as a11yTree from "../../lib/v3/understudy/a11y/snapshot/a11yTree.js";
|
|
4
4
|
import * as domTree from "../../lib/v3/understudy/a11y/snapshot/domTree.js";
|
|
5
5
|
import * as focusSelectors from "../../lib/v3/understudy/a11y/snapshot/focusSelectors.js";
|
|
6
|
+
import { FrameSelectorResolver } from "../../lib/v3/understudy/selectorResolver.js";
|
|
6
7
|
import { MockCDPSession } from "./helpers/mockCDPSession.js";
|
|
7
8
|
const makeProtocolFrame = (id) => ({
|
|
8
9
|
id,
|
|
@@ -54,6 +55,22 @@ const makeSessionIndex = () => ({
|
|
|
54
55
|
[201, 200],
|
|
55
56
|
]),
|
|
56
57
|
contentDocRootByIframe: new Map([[150, 200]]),
|
|
58
|
+
enterByBe: new Map([
|
|
59
|
+
[100, 0],
|
|
60
|
+
[101, 1],
|
|
61
|
+
[102, 2],
|
|
62
|
+
[150, 3],
|
|
63
|
+
[200, 4],
|
|
64
|
+
[201, 5],
|
|
65
|
+
]),
|
|
66
|
+
exitByBe: new Map([
|
|
67
|
+
[101, 6],
|
|
68
|
+
[102, 7],
|
|
69
|
+
[201, 8],
|
|
70
|
+
[200, 9],
|
|
71
|
+
[150, 10],
|
|
72
|
+
[100, 11],
|
|
73
|
+
]),
|
|
57
74
|
});
|
|
58
75
|
beforeEach(() => {
|
|
59
76
|
vi.restoreAllMocks();
|
|
@@ -154,7 +171,7 @@ describe("collectPerFrameMaps", () => {
|
|
|
154
171
|
urlMap: { [`url-${frameId}`]: `https://${frameId}.test` },
|
|
155
172
|
scopeApplied: false,
|
|
156
173
|
}));
|
|
157
|
-
const result = await capture.collectPerFrameMaps(page, context, sessionToIndex, { experimental: true }, true, context.frames);
|
|
174
|
+
const result = await capture.collectPerFrameMaps(page, context, sessionToIndex, { experimental: true }, true, context.frames, new Map());
|
|
158
175
|
expect(result.perFrameOutlines).toEqual([
|
|
159
176
|
{ frameId: "frame-1", outline: "outline-frame-1" },
|
|
160
177
|
{ frameId: "frame-2", outline: "outline-frame-2" },
|
|
@@ -193,7 +210,7 @@ describe("collectPerFrameMaps", () => {
|
|
|
193
210
|
scopeApplied: false,
|
|
194
211
|
});
|
|
195
212
|
const sessionToIndex = new Map();
|
|
196
|
-
const result = await capture.collectPerFrameMaps(page, context, sessionToIndex, undefined, false, context.frames);
|
|
213
|
+
const result = await capture.collectPerFrameMaps(page, context, sessionToIndex, undefined, false, context.frames, new Map());
|
|
197
214
|
expect(buildSpy).toHaveBeenCalledWith(session, false);
|
|
198
215
|
expect(sessionToIndex.get("new-session")).toBe(idx);
|
|
199
216
|
expect(result.perFrameMaps.get("frame-9")?.xpathMap["2-100"]).toBe("/");
|
|
@@ -219,7 +236,7 @@ describe("collectPerFrameMaps", () => {
|
|
|
219
236
|
urlMap: {},
|
|
220
237
|
scopeApplied: false,
|
|
221
238
|
});
|
|
222
|
-
const result = await capture.collectPerFrameMaps(page, context, sessionToIndex, undefined, true, ["frame-1"]);
|
|
239
|
+
const result = await capture.collectPerFrameMaps(page, context, sessionToIndex, undefined, true, ["frame-1"], new Map());
|
|
223
240
|
expect(a11ySpy).toHaveBeenCalledTimes(1);
|
|
224
241
|
expect(result.perFrameMaps.has("frame-2")).toBe(false);
|
|
225
242
|
expect(result.perFrameOutlines.map((o) => o.frameId)).toEqual(["frame-1"]);
|
|
@@ -251,9 +268,7 @@ describe("captureHybridSnapshot", () => {
|
|
|
251
268
|
});
|
|
252
269
|
const buildIndexSpy = vi
|
|
253
270
|
.spyOn(domTree, "buildSessionDomIndex")
|
|
254
|
-
.
|
|
255
|
-
throw new Error("should not build session index when scoped");
|
|
256
|
-
});
|
|
271
|
+
.mockResolvedValue(makeSessionIndex());
|
|
257
272
|
const result = await capture.captureHybridSnapshot(page, options);
|
|
258
273
|
expect(result.combinedTree).toBe("scoped outline");
|
|
259
274
|
expect(result.combinedUrlMap["0-100"]).toBe("https://frame-1.test");
|
|
@@ -286,9 +301,7 @@ describe("captureHybridSnapshot", () => {
|
|
|
286
301
|
});
|
|
287
302
|
const buildIndexSpy = vi
|
|
288
303
|
.spyOn(domTree, "buildSessionDomIndex")
|
|
289
|
-
.
|
|
290
|
-
throw new Error("should not build session index when scoped");
|
|
291
|
-
});
|
|
304
|
+
.mockResolvedValue(makeSessionIndex());
|
|
292
305
|
const result = await capture.captureHybridSnapshot(page, options);
|
|
293
306
|
expect(result.combinedTree).toBe("scoped outline");
|
|
294
307
|
expect(result.combinedUrlMap["0-100"]).toBe("https://frame-1.test");
|
|
@@ -296,6 +309,103 @@ describe("captureHybridSnapshot", () => {
|
|
|
296
309
|
expect(a11ySpy).toHaveBeenCalled();
|
|
297
310
|
expect(buildIndexSpy).not.toHaveBeenCalled();
|
|
298
311
|
});
|
|
312
|
+
it("filters ignored nodes out of the merged snapshot artifacts", async () => {
|
|
313
|
+
const session = new MockCDPSession({
|
|
314
|
+
"DOM.getFrameOwner": async () => ({ backendNodeId: 150 }),
|
|
315
|
+
"DOM.describeNode": async (params) => ({
|
|
316
|
+
node: {
|
|
317
|
+
backendNodeId: params?.objectId === "ignored-object-a"
|
|
318
|
+
? 201
|
|
319
|
+
: params?.objectId === "ignored-object-b"
|
|
320
|
+
? 202
|
|
321
|
+
: 0,
|
|
322
|
+
},
|
|
323
|
+
}),
|
|
324
|
+
}, "session-a");
|
|
325
|
+
const page = makePage({
|
|
326
|
+
asProtocolFrameTree: () => makeFrameTree("frame-1", [makeFrameTree("frame-2")]),
|
|
327
|
+
listAllFrameIds: () => ["frame-1", "frame-2"],
|
|
328
|
+
getSessionForFrame: () => session,
|
|
329
|
+
getOrdinal: (frameId) => (frameId === "frame-1" ? 0 : 1),
|
|
330
|
+
});
|
|
331
|
+
const idx = makeSessionIndex();
|
|
332
|
+
idx.absByBe.set(202, "/html[1]/body[1]/iframe[1]/aside[1]");
|
|
333
|
+
idx.tagByBe.set(202, "aside");
|
|
334
|
+
idx.docRootOf.set(202, 200);
|
|
335
|
+
idx.enterByBe.set(202, 6);
|
|
336
|
+
idx.exitByBe.set(202, 7);
|
|
337
|
+
idx.exitByBe.set(201, 8);
|
|
338
|
+
idx.exitByBe.set(200, 9);
|
|
339
|
+
idx.exitByBe.set(150, 10);
|
|
340
|
+
idx.exitByBe.set(100, 11);
|
|
341
|
+
vi.spyOn(domTree, "buildSessionDomIndex").mockResolvedValue(idx);
|
|
342
|
+
vi.spyOn(focusSelectors, "resolveCssFocusFrameAndTail").mockResolvedValue({
|
|
343
|
+
targetFrameId: "frame-2",
|
|
344
|
+
tailSelector: ".ad",
|
|
345
|
+
absPrefix: "/html/body/iframe[1]",
|
|
346
|
+
});
|
|
347
|
+
vi.spyOn(FrameSelectorResolver.prototype, "resolveAll").mockResolvedValue([
|
|
348
|
+
{ objectId: "ignored-object-a", nodeId: null },
|
|
349
|
+
{ objectId: "ignored-object-b", nodeId: null },
|
|
350
|
+
]);
|
|
351
|
+
vi.spyOn(a11yTree, "a11yForFrame").mockImplementation(async (_sess, frameId, opts) => ({
|
|
352
|
+
outline: opts.isIgnoredBackendNode?.(201) && opts.isIgnoredBackendNode?.(202)
|
|
353
|
+
? `outline-${frameId}-filtered`
|
|
354
|
+
: `outline-${frameId}`,
|
|
355
|
+
urlMap: frameId === "frame-2" &&
|
|
356
|
+
opts.isIgnoredBackendNode?.(201) &&
|
|
357
|
+
opts.isIgnoredBackendNode?.(202)
|
|
358
|
+
? {}
|
|
359
|
+
: { [`url-${frameId}`]: `https://${frameId}.test` },
|
|
360
|
+
scopeApplied: false,
|
|
361
|
+
}));
|
|
362
|
+
const snapshot = await capture.captureHybridSnapshot(page, {
|
|
363
|
+
ignoreSelectors: [".ad"],
|
|
364
|
+
});
|
|
365
|
+
expect(snapshot.combinedXpathMap["1-201"]).toBeUndefined();
|
|
366
|
+
expect(snapshot.combinedXpathMap["1-202"]).toBeUndefined();
|
|
367
|
+
expect(snapshot.combinedUrlMap["url-frame-2"]).toBeUndefined();
|
|
368
|
+
expect(snapshot.perFrame?.find((frame) => frame.frameId === "frame-2")?.outline).toContain("filtered");
|
|
369
|
+
});
|
|
370
|
+
it("excludes child frame subtrees when an ignored node is an iframe host", async () => {
|
|
371
|
+
const session = new MockCDPSession({
|
|
372
|
+
"DOM.getFrameOwner": async () => ({ backendNodeId: 150 }),
|
|
373
|
+
"DOM.describeNode": async (params) => ({
|
|
374
|
+
node: { backendNodeId: params?.objectId === "iframe-host" ? 150 : 0 },
|
|
375
|
+
}),
|
|
376
|
+
}, "session-a");
|
|
377
|
+
const page = makePage({
|
|
378
|
+
asProtocolFrameTree: () => makeFrameTree("frame-1", [makeFrameTree("frame-2")]),
|
|
379
|
+
listAllFrameIds: () => ["frame-1", "frame-2"],
|
|
380
|
+
getSessionForFrame: () => session,
|
|
381
|
+
getOrdinal: (frameId) => (frameId === "frame-1" ? 0 : 1),
|
|
382
|
+
});
|
|
383
|
+
vi.spyOn(domTree, "buildSessionDomIndex").mockResolvedValue(makeSessionIndex());
|
|
384
|
+
vi.spyOn(focusSelectors, "resolveCssFocusFrameAndTail").mockResolvedValue({
|
|
385
|
+
targetFrameId: "frame-1",
|
|
386
|
+
tailSelector: "iframe.ad",
|
|
387
|
+
absPrefix: "",
|
|
388
|
+
});
|
|
389
|
+
vi.spyOn(FrameSelectorResolver.prototype, "resolveAll").mockResolvedValue([
|
|
390
|
+
{ objectId: "iframe-host", nodeId: null },
|
|
391
|
+
]);
|
|
392
|
+
vi.spyOn(a11yTree, "a11yForFrame").mockImplementation(async (_sess, frameId, opts) => ({
|
|
393
|
+
outline: frameId === "frame-2" && opts.isIgnoredBackendNode?.(200)
|
|
394
|
+
? ""
|
|
395
|
+
: `outline-${frameId}`,
|
|
396
|
+
urlMap: frameId === "frame-2" && opts.isIgnoredBackendNode?.(200)
|
|
397
|
+
? {}
|
|
398
|
+
: { [`url-${frameId}`]: `https://${frameId}.test` },
|
|
399
|
+
scopeApplied: false,
|
|
400
|
+
}));
|
|
401
|
+
const snapshot = await capture.captureHybridSnapshot(page, {
|
|
402
|
+
ignoreSelectors: ["iframe.ad"],
|
|
403
|
+
});
|
|
404
|
+
expect(snapshot.combinedXpathMap["1-200"]).toBeUndefined();
|
|
405
|
+
expect(snapshot.combinedXpathMap["1-201"]).toBeUndefined();
|
|
406
|
+
expect(snapshot.combinedUrlMap["url-frame-2"]).toBeUndefined();
|
|
407
|
+
expect(snapshot.combinedTree).not.toContain("outline-frame-2");
|
|
408
|
+
});
|
|
299
409
|
it("collects per-frame data and merges it when no scoped snapshot is available", async () => {
|
|
300
410
|
const session = new MockCDPSession({
|
|
301
411
|
"DOM.getFrameOwner": async () => ({ backendNodeId: 150 }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"snapshot-capture-orchestration.test.js","sourceRoot":"","sources":["../../../../tests/unit/snapshot-capture-orchestration.test.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Protocol } from \"devtools-protocol\";\nimport { beforeEach, describe, expect, it, vi } from \"vitest\";\nimport type { CDPSessionLike } from \"../../lib/v3/understudy/cdp.js\";\nimport type { Page } from \"../../lib/v3/understudy/page.js\";\nimport type {\n FrameContext,\n SessionDomIndex,\n} from \"../../lib/v3/types/private/index.js\";\nimport * as capture from \"../../lib/v3/understudy/a11y/snapshot/capture.js\";\nimport * as a11yTree from \"../../lib/v3/understudy/a11y/snapshot/a11yTree.js\";\nimport * as domTree from \"../../lib/v3/understudy/a11y/snapshot/domTree.js\";\nimport * as focusSelectors from \"../../lib/v3/understudy/a11y/snapshot/focusSelectors.js\";\nimport { MockCDPSession } from \"./helpers/mockCDPSession.js\";\n\nconst makeProtocolFrame = (id: string): Protocol.Page.Frame =>\n ({\n id,\n loaderId: `${id}-loader`,\n url: \"https://example.com\",\n securityOrigin: \"https://example.com\",\n mimeType: \"text/html\",\n }) as unknown as Protocol.Page.Frame;\n\nconst makeFrameTree = (\n id: string,\n children: Protocol.Page.FrameTree[] = [],\n): Protocol.Page.FrameTree => ({\n frame: makeProtocolFrame(id),\n childFrames: children,\n});\n\ntype PageStub = Pick<\n Page,\n | \"mainFrameId\"\n | \"asProtocolFrameTree\"\n | \"listAllFrameIds\"\n | \"getSessionForFrame\"\n | \"getOrdinal\"\n>;\n\nconst makePage = (overrides: Partial<PageStub> = {}): Page => {\n const defaultSession = new MockCDPSession({}, \"default-session\");\n const base: PageStub = {\n mainFrameId: () => \"frame-1\",\n asProtocolFrameTree: () => makeFrameTree(\"frame-1\"),\n listAllFrameIds: () => [\"frame-1\"],\n getSessionForFrame: () => defaultSession,\n getOrdinal: () => 0,\n };\n return { ...base, ...overrides } as unknown as Page;\n};\n\nconst makeSessionIndex = (): SessionDomIndex => ({\n rootBackend: 100,\n absByBe: new Map([\n [100, \"/\"],\n [101, \"/html[1]\"],\n [102, \"/html[1]/body[1]\"],\n [150, \"/html[1]/body[1]/iframe[1]\"],\n [200, \"/html[1]/body[1]/iframe[1]\"],\n [201, \"/html[1]/body[1]/iframe[1]/div[1]\"],\n ]),\n tagByBe: new Map([\n [100, \"#document\"],\n [101, \"html\"],\n [102, \"body\"],\n [150, \"iframe\"],\n [200, \"#document\"],\n [201, \"div\"],\n ]),\n scrollByBe: new Map([[201, true]]),\n docRootOf: new Map([\n [100, 100],\n [101, 100],\n [102, 100],\n [150, 100],\n [200, 200],\n [201, 200],\n ]),\n contentDocRootByIframe: new Map([[150, 200]]),\n});\n\nbeforeEach(() => {\n vi.restoreAllMocks();\n});\n\ndescribe(\"buildFrameContext\", () => {\n it(\"indexes parent relationships from the frame tree\", () => {\n const frameTree = makeFrameTree(\"frame-1\", [\n makeFrameTree(\"frame-2\", [makeFrameTree(\"frame-3\")]),\n makeFrameTree(\"frame-4\"),\n ]);\n const page = makePage({\n asProtocolFrameTree: () => frameTree,\n listAllFrameIds: () => [\"frame-1\", \"frame-2\", \"frame-3\", \"frame-4\"],\n });\n\n const context = capture.buildFrameContext(page);\n\n expect(context.rootId).toBe(\"frame-1\");\n expect(context.frames).toEqual([\n \"frame-1\",\n \"frame-2\",\n \"frame-3\",\n \"frame-4\",\n ]);\n expect(context.parentByFrame.get(\"frame-1\")).toBeNull();\n expect(context.parentByFrame.get(\"frame-2\")).toBe(\"frame-1\");\n expect(context.parentByFrame.get(\"frame-3\")).toBe(\"frame-2\");\n expect(context.parentByFrame.get(\"frame-4\")).toBe(\"frame-1\");\n });\n});\n\ndescribe(\"buildSessionIndexes\", () => {\n it(\"deduplicates frames that share the same CDP session id\", async () => {\n const session = new MockCDPSession({}, \"session-a\");\n const page = makePage({\n // Every frame lookup returns the same session instance, so buildSessionIndexes\n // should call buildSessionDomIndex only once and reuse the result.\n getSessionForFrame: () => session,\n });\n const idx = makeSessionIndex();\n const spy = vi\n .spyOn(domTree, \"buildSessionDomIndex\")\n .mockResolvedValue(idx);\n\n const result = await capture.buildSessionIndexes(\n page,\n [\"frame-1\", \"frame-2\"],\n true,\n );\n\n expect(spy).toHaveBeenCalledTimes(1); // only one DOM.getDocument per session id\n expect(spy).toHaveBeenCalledWith(session, true);\n expect(result.get(\"session-a\")).toBe(idx);\n });\n\n it(\"builds indexes for sessions without ids using the 'root' key\", async () => {\n const sessionWithoutId: CDPSessionLike = {\n id: undefined,\n async send<R = unknown>(\n _method: string,\n _params?: Record<string, unknown>,\n ): Promise<R> {\n void _method;\n void _params;\n return {} as R;\n },\n on() {},\n off() {},\n async close() {},\n };\n const sessionWithId = new MockCDPSession({}, \"child-session\");\n const page = makePage({\n getSessionForFrame: (frameId: string) =>\n frameId === \"frame-1\" ? sessionWithoutId : sessionWithId,\n });\n\n const idxA = makeSessionIndex();\n const idxB = makeSessionIndex();\n const spy = vi\n .spyOn(domTree, \"buildSessionDomIndex\")\n .mockResolvedValueOnce(idxA)\n .mockResolvedValueOnce(idxB);\n\n const result = await capture.buildSessionIndexes(\n page,\n [\"frame-1\", \"frame-2\"],\n false,\n );\n\n // Verifies the helper invokes buildSessionDomIndex once for each unique session,\n // keying anonymous sessions as \"root\" so downstream lookups remain stable.\n expect(spy).toHaveBeenNthCalledWith(1, sessionWithoutId, false);\n expect(spy).toHaveBeenNthCalledWith(2, sessionWithId, false);\n expect(result.get(\"root\")).toBe(idxA);\n expect(result.get(\"child-session\")).toBe(idxB);\n });\n});\n\ndescribe(\"collectPerFrameMaps\", () => {\n it(\"builds per-frame xpath/tag maps and outlines from a shared session index\", async () => {\n const session = new MockCDPSession(\n {\n \"DOM.getFrameOwner\": async () => ({ backendNodeId: 150 }),\n },\n \"session-a\",\n );\n const page = makePage({\n getSessionForFrame: () => session,\n getOrdinal: (frameId: string) => (frameId === \"frame-1\" ? 0 : 1),\n });\n const context: FrameContext = {\n rootId: \"frame-1\",\n frames: [\"frame-1\", \"frame-2\"],\n parentByFrame: new Map([\n [\"frame-1\", null],\n [\"frame-2\", \"frame-1\"],\n ]),\n };\n const sessionIndex = makeSessionIndex();\n const sessionToIndex = new Map([[session.id, sessionIndex]]);\n\n vi.spyOn(a11yTree, \"a11yForFrame\").mockImplementation(\n async (_sess, frameId) => ({\n outline: `outline-${frameId}`,\n urlMap: { [`url-${frameId}`]: `https://${frameId}.test` },\n scopeApplied: false,\n }),\n );\n\n const result = await capture.collectPerFrameMaps(\n page,\n context,\n sessionToIndex,\n { experimental: true },\n true,\n context.frames,\n );\n\n expect(result.perFrameOutlines).toEqual([\n { frameId: \"frame-1\", outline: \"outline-frame-1\" },\n { frameId: \"frame-2\", outline: \"outline-frame-2\" },\n ]);\n const rootMaps = result.perFrameMaps.get(\"frame-1\");\n expect(rootMaps?.xpathMap[\"0-100\"]).toBe(\"/\");\n expect(rootMaps?.xpathMap[\"0-101\"]).toBe(\"/html[1]\");\n expect(rootMaps?.xpathMap[\"0-102\"]).toBe(\"/html[1]/body[1]\");\n const childMaps = result.perFrameMaps.get(\"frame-2\");\n expect(childMaps?.xpathMap[\"1-200\"]).toBe(\"/\");\n expect(childMaps?.xpathMap[\"1-201\"]).toBe(\"/div[1]\");\n expect(childMaps?.scrollableMap[\"1-201\"]).toBe(true);\n expect(childMaps?.urlMap).toEqual({\n \"url-frame-2\": \"https://frame-2.test\",\n });\n expect(session.callsFor(\"DOM.getFrameOwner\")).toHaveLength(1);\n });\n\n it(\"builds a missing session index on demand and memoizes it\", async () => {\n const session = new MockCDPSession({}, \"new-session\");\n const page = makePage({\n getSessionForFrame: () => session,\n getOrdinal: () => 2,\n });\n const context: FrameContext = {\n rootId: \"frame-9\",\n frames: [\"frame-9\"],\n parentByFrame: new Map([[\"frame-9\", null]]),\n };\n const idx = makeSessionIndex();\n const buildSpy = vi\n .spyOn(domTree, \"buildSessionDomIndex\")\n .mockResolvedValue(idx);\n vi.spyOn(a11yTree, \"a11yForFrame\").mockResolvedValue({\n outline: \"outline\",\n urlMap: {},\n scopeApplied: false,\n });\n\n const sessionToIndex = new Map<string, SessionDomIndex>();\n const result = await capture.collectPerFrameMaps(\n page,\n context,\n sessionToIndex,\n undefined,\n false,\n context.frames,\n );\n\n expect(buildSpy).toHaveBeenCalledWith(session, false);\n expect(sessionToIndex.get(\"new-session\")).toBe(idx);\n expect(result.perFrameMaps.get(\"frame-9\")?.xpathMap[\"2-100\"]).toBe(\"/\");\n });\n\n it(\"skips frames that are not listed in the frameIds argument\", async () => {\n const session = new MockCDPSession({}, \"session-a\");\n const page = makePage({\n getSessionForFrame: () => session,\n getOrdinal: (frameId: string) => (frameId === \"frame-1\" ? 0 : 1),\n });\n const context: FrameContext = {\n rootId: \"frame-1\",\n frames: [\"frame-1\", \"frame-2\"],\n parentByFrame: new Map([\n [\"frame-1\", null],\n [\"frame-2\", \"frame-1\"],\n ]),\n };\n const sessionIndex = makeSessionIndex();\n const sessionToIndex = new Map([[session.id, sessionIndex]]);\n\n const a11ySpy = vi.spyOn(a11yTree, \"a11yForFrame\").mockResolvedValue({\n outline: \"outline\",\n urlMap: {},\n scopeApplied: false,\n });\n\n const result = await capture.collectPerFrameMaps(\n page,\n context,\n sessionToIndex,\n undefined,\n true,\n [\"frame-1\"],\n );\n\n expect(a11ySpy).toHaveBeenCalledTimes(1);\n expect(result.perFrameMaps.has(\"frame-2\")).toBe(false);\n expect(result.perFrameOutlines.map((o) => o.frameId)).toEqual([\"frame-1\"]);\n });\n});\n\ndescribe(\"captureHybridSnapshot\", () => {\n it(\"returns early when the scoped snapshot path succeeds\", async () => {\n const session = new MockCDPSession({}, \"session-a\");\n const page = makePage({\n getSessionForFrame: () => session,\n });\n const options = { focusSelector: \"/html\" };\n\n vi.spyOn(focusSelectors, \"resolveFocusFrameAndTail\").mockResolvedValue({\n targetFrameId: \"frame-1\",\n tailXPath: \"\",\n absPrefix: \"\",\n });\n const domMapsSpy = vi\n .spyOn(domTree, \"domMapsForSession\")\n .mockResolvedValue({\n tagNameMap: { \"0-100\": \"#document\" },\n xpathMap: { \"0-100\": \"/\" },\n scrollableMap: {},\n });\n const a11ySpy = vi.spyOn(a11yTree, \"a11yForFrame\").mockResolvedValue({\n outline: \"scoped outline\",\n urlMap: { \"0-100\": \"https://frame-1.test\" },\n scopeApplied: true,\n });\n const buildIndexSpy = vi\n .spyOn(domTree, \"buildSessionDomIndex\")\n .mockImplementation(() => {\n throw new Error(\"should not build session index when scoped\");\n });\n\n const result = await capture.captureHybridSnapshot(page, options);\n\n expect(result.combinedTree).toBe(\"scoped outline\");\n expect(result.combinedUrlMap[\"0-100\"]).toBe(\"https://frame-1.test\");\n expect(domMapsSpy).toHaveBeenCalled();\n expect(a11ySpy).toHaveBeenCalled();\n expect(buildIndexSpy).not.toHaveBeenCalled();\n });\n\n it(\"scoped snapshot still succeeds when iframe inclusion is disabled\", async () => {\n const session = new MockCDPSession({}, \"session-a\");\n const page = makePage({\n getSessionForFrame: () => session,\n });\n const options = { focusSelector: \"/html\", includeIframes: false };\n\n vi.spyOn(focusSelectors, \"resolveFocusFrameAndTail\").mockResolvedValue({\n targetFrameId: \"frame-1\",\n tailXPath: \"\",\n absPrefix: \"\",\n });\n const domMapsSpy = vi\n .spyOn(domTree, \"domMapsForSession\")\n .mockResolvedValue({\n tagNameMap: { \"0-100\": \"#document\" },\n xpathMap: { \"0-100\": \"/\" },\n scrollableMap: {},\n });\n const a11ySpy = vi.spyOn(a11yTree, \"a11yForFrame\").mockResolvedValue({\n outline: \"scoped outline\",\n urlMap: { \"0-100\": \"https://frame-1.test\" },\n scopeApplied: true,\n });\n const buildIndexSpy = vi\n .spyOn(domTree, \"buildSessionDomIndex\")\n .mockImplementation(() => {\n throw new Error(\"should not build session index when scoped\");\n });\n\n const result = await capture.captureHybridSnapshot(page, options);\n\n expect(result.combinedTree).toBe(\"scoped outline\");\n expect(result.combinedUrlMap[\"0-100\"]).toBe(\"https://frame-1.test\");\n expect(domMapsSpy).toHaveBeenCalled();\n expect(a11ySpy).toHaveBeenCalled();\n expect(buildIndexSpy).not.toHaveBeenCalled();\n });\n\n it(\"collects per-frame data and merges it when no scoped snapshot is available\", async () => {\n const session = new MockCDPSession(\n {\n \"DOM.getFrameOwner\": async () => ({ backendNodeId: 150 }),\n },\n \"session-a\",\n );\n const page = makePage({\n asProtocolFrameTree: () =>\n makeFrameTree(\"frame-1\", [makeFrameTree(\"frame-2\")]),\n listAllFrameIds: () => [\"frame-1\", \"frame-2\"],\n getSessionForFrame: () => session,\n getOrdinal: (frameId: string) => (frameId === \"frame-1\" ? 0 : 1),\n });\n\n const idx = makeSessionIndex();\n vi.spyOn(domTree, \"buildSessionDomIndex\").mockResolvedValue(idx);\n vi.spyOn(a11yTree, \"a11yForFrame\").mockImplementation(\n async (_sess, frameId) => ({\n outline:\n frameId === \"frame-1\"\n ? \"[0-150] iframe host\"\n : \"[1-200] child subtree\",\n urlMap: { [`url-${frameId}`]: `https://${frameId}.test` },\n scopeApplied: false,\n }),\n );\n\n const snapshot = await capture.captureHybridSnapshot(page);\n\n expect(snapshot.combinedTree).toContain(\"[1-200] child subtree\");\n expect(snapshot.combinedXpathMap[\"0-100\"]).toBe(\"/\");\n expect(snapshot.combinedXpathMap[\"1-201\"]).toBe(\n \"/html[1]/body[1]/iframe[1]/div[1]\",\n );\n expect(snapshot.combinedUrlMap[\"url-frame-2\"]).toBe(\"https://frame-2.test\");\n expect(snapshot.perFrame?.map((pf) => pf.frameId)).toEqual([\n \"frame-1\",\n \"frame-2\",\n ]);\n });\n\n it(\"omits iframe frames when includeIframes is false\", async () => {\n const session = new MockCDPSession(\n {\n \"DOM.getFrameOwner\": async () => ({ backendNodeId: 150 }),\n },\n \"session-a\",\n );\n const page = makePage({\n asProtocolFrameTree: () =>\n makeFrameTree(\"frame-1\", [makeFrameTree(\"frame-2\")]),\n listAllFrameIds: () => [\"frame-1\", \"frame-2\"],\n getSessionForFrame: () => session,\n getOrdinal: (frameId: string) => (frameId === \"frame-1\" ? 0 : 1),\n });\n\n const idx = makeSessionIndex();\n vi.spyOn(domTree, \"buildSessionDomIndex\").mockResolvedValue(idx);\n const a11ySpy = vi\n .spyOn(a11yTree, \"a11yForFrame\")\n .mockImplementation(async (_sess, frameId) => ({\n outline:\n frameId === \"frame-1\"\n ? \"[0-150] iframe host\"\n : \"[1-200] child subtree\",\n urlMap: { [`url-${frameId}`]: `https://${frameId}.test` },\n scopeApplied: false,\n }));\n\n const snapshot = await capture.captureHybridSnapshot(page, {\n includeIframes: false,\n });\n\n expect(a11ySpy).toHaveBeenCalledTimes(1);\n expect(session.callsFor(\"DOM.getFrameOwner\")).toHaveLength(0);\n expect(snapshot.perFrame?.map((pf) => pf.frameId)).toEqual([\"frame-1\"]);\n expect(snapshot.combinedXpathMap[\"1-201\"]).toBeUndefined();\n expect(snapshot.combinedTree).not.toContain(\"[1-200] child subtree\");\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"snapshot-capture-orchestration.test.js","sourceRoot":"","sources":["../../../../tests/unit/snapshot-capture-orchestration.test.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Protocol } from \"devtools-protocol\";\nimport { beforeEach, describe, expect, it, vi } from \"vitest\";\nimport type { CDPSessionLike } from \"../../lib/v3/understudy/cdp.js\";\nimport type { Page } from \"../../lib/v3/understudy/page.js\";\nimport type {\n FrameContext,\n SessionDomIndex,\n} from \"../../lib/v3/types/private/index.js\";\nimport * as capture from \"../../lib/v3/understudy/a11y/snapshot/capture.js\";\nimport * as a11yTree from \"../../lib/v3/understudy/a11y/snapshot/a11yTree.js\";\nimport * as domTree from \"../../lib/v3/understudy/a11y/snapshot/domTree.js\";\nimport * as focusSelectors from \"../../lib/v3/understudy/a11y/snapshot/focusSelectors.js\";\nimport { FrameSelectorResolver } from \"../../lib/v3/understudy/selectorResolver.js\";\nimport { MockCDPSession } from \"./helpers/mockCDPSession.js\";\n\nconst makeProtocolFrame = (id: string): Protocol.Page.Frame =>\n ({\n id,\n loaderId: `${id}-loader`,\n url: \"https://example.com\",\n securityOrigin: \"https://example.com\",\n mimeType: \"text/html\",\n }) as unknown as Protocol.Page.Frame;\n\nconst makeFrameTree = (\n id: string,\n children: Protocol.Page.FrameTree[] = [],\n): Protocol.Page.FrameTree => ({\n frame: makeProtocolFrame(id),\n childFrames: children,\n});\n\ntype PageStub = Pick<\n Page,\n | \"mainFrameId\"\n | \"asProtocolFrameTree\"\n | \"listAllFrameIds\"\n | \"getSessionForFrame\"\n | \"getOrdinal\"\n>;\n\nconst makePage = (overrides: Partial<PageStub> = {}): Page => {\n const defaultSession = new MockCDPSession({}, \"default-session\");\n const base: PageStub = {\n mainFrameId: () => \"frame-1\",\n asProtocolFrameTree: () => makeFrameTree(\"frame-1\"),\n listAllFrameIds: () => [\"frame-1\"],\n getSessionForFrame: () => defaultSession,\n getOrdinal: () => 0,\n };\n return { ...base, ...overrides } as unknown as Page;\n};\n\nconst makeSessionIndex = (): SessionDomIndex => ({\n rootBackend: 100,\n absByBe: new Map([\n [100, \"/\"],\n [101, \"/html[1]\"],\n [102, \"/html[1]/body[1]\"],\n [150, \"/html[1]/body[1]/iframe[1]\"],\n [200, \"/html[1]/body[1]/iframe[1]\"],\n [201, \"/html[1]/body[1]/iframe[1]/div[1]\"],\n ]),\n tagByBe: new Map([\n [100, \"#document\"],\n [101, \"html\"],\n [102, \"body\"],\n [150, \"iframe\"],\n [200, \"#document\"],\n [201, \"div\"],\n ]),\n scrollByBe: new Map([[201, true]]),\n docRootOf: new Map([\n [100, 100],\n [101, 100],\n [102, 100],\n [150, 100],\n [200, 200],\n [201, 200],\n ]),\n contentDocRootByIframe: new Map([[150, 200]]),\n enterByBe: new Map([\n [100, 0],\n [101, 1],\n [102, 2],\n [150, 3],\n [200, 4],\n [201, 5],\n ]),\n exitByBe: new Map([\n [101, 6],\n [102, 7],\n [201, 8],\n [200, 9],\n [150, 10],\n [100, 11],\n ]),\n});\n\nbeforeEach(() => {\n vi.restoreAllMocks();\n});\n\ndescribe(\"buildFrameContext\", () => {\n it(\"indexes parent relationships from the frame tree\", () => {\n const frameTree = makeFrameTree(\"frame-1\", [\n makeFrameTree(\"frame-2\", [makeFrameTree(\"frame-3\")]),\n makeFrameTree(\"frame-4\"),\n ]);\n const page = makePage({\n asProtocolFrameTree: () => frameTree,\n listAllFrameIds: () => [\"frame-1\", \"frame-2\", \"frame-3\", \"frame-4\"],\n });\n\n const context = capture.buildFrameContext(page);\n\n expect(context.rootId).toBe(\"frame-1\");\n expect(context.frames).toEqual([\n \"frame-1\",\n \"frame-2\",\n \"frame-3\",\n \"frame-4\",\n ]);\n expect(context.parentByFrame.get(\"frame-1\")).toBeNull();\n expect(context.parentByFrame.get(\"frame-2\")).toBe(\"frame-1\");\n expect(context.parentByFrame.get(\"frame-3\")).toBe(\"frame-2\");\n expect(context.parentByFrame.get(\"frame-4\")).toBe(\"frame-1\");\n });\n});\n\ndescribe(\"buildSessionIndexes\", () => {\n it(\"deduplicates frames that share the same CDP session id\", async () => {\n const session = new MockCDPSession({}, \"session-a\");\n const page = makePage({\n // Every frame lookup returns the same session instance, so buildSessionIndexes\n // should call buildSessionDomIndex only once and reuse the result.\n getSessionForFrame: () => session,\n });\n const idx = makeSessionIndex();\n const spy = vi\n .spyOn(domTree, \"buildSessionDomIndex\")\n .mockResolvedValue(idx);\n\n const result = await capture.buildSessionIndexes(\n page,\n [\"frame-1\", \"frame-2\"],\n true,\n );\n\n expect(spy).toHaveBeenCalledTimes(1); // only one DOM.getDocument per session id\n expect(spy).toHaveBeenCalledWith(session, true);\n expect(result.get(\"session-a\")).toBe(idx);\n });\n\n it(\"builds indexes for sessions without ids using the 'root' key\", async () => {\n const sessionWithoutId: CDPSessionLike = {\n id: undefined,\n async send<R = unknown>(\n _method: string,\n _params?: Record<string, unknown>,\n ): Promise<R> {\n void _method;\n void _params;\n return {} as R;\n },\n on() {},\n off() {},\n async close() {},\n };\n const sessionWithId = new MockCDPSession({}, \"child-session\");\n const page = makePage({\n getSessionForFrame: (frameId: string) =>\n frameId === \"frame-1\" ? sessionWithoutId : sessionWithId,\n });\n\n const idxA = makeSessionIndex();\n const idxB = makeSessionIndex();\n const spy = vi\n .spyOn(domTree, \"buildSessionDomIndex\")\n .mockResolvedValueOnce(idxA)\n .mockResolvedValueOnce(idxB);\n\n const result = await capture.buildSessionIndexes(\n page,\n [\"frame-1\", \"frame-2\"],\n false,\n );\n\n // Verifies the helper invokes buildSessionDomIndex once for each unique session,\n // keying anonymous sessions as \"root\" so downstream lookups remain stable.\n expect(spy).toHaveBeenNthCalledWith(1, sessionWithoutId, false);\n expect(spy).toHaveBeenNthCalledWith(2, sessionWithId, false);\n expect(result.get(\"root\")).toBe(idxA);\n expect(result.get(\"child-session\")).toBe(idxB);\n });\n});\n\ndescribe(\"collectPerFrameMaps\", () => {\n it(\"builds per-frame xpath/tag maps and outlines from a shared session index\", async () => {\n const session = new MockCDPSession(\n {\n \"DOM.getFrameOwner\": async () => ({ backendNodeId: 150 }),\n },\n \"session-a\",\n );\n const page = makePage({\n getSessionForFrame: () => session,\n getOrdinal: (frameId: string) => (frameId === \"frame-1\" ? 0 : 1),\n });\n const context: FrameContext = {\n rootId: \"frame-1\",\n frames: [\"frame-1\", \"frame-2\"],\n parentByFrame: new Map([\n [\"frame-1\", null],\n [\"frame-2\", \"frame-1\"],\n ]),\n };\n const sessionIndex = makeSessionIndex();\n const sessionToIndex = new Map([[session.id, sessionIndex]]);\n\n vi.spyOn(a11yTree, \"a11yForFrame\").mockImplementation(\n async (_sess, frameId) => ({\n outline: `outline-${frameId}`,\n urlMap: { [`url-${frameId}`]: `https://${frameId}.test` },\n scopeApplied: false,\n }),\n );\n\n const result = await capture.collectPerFrameMaps(\n page,\n context,\n sessionToIndex,\n { experimental: true },\n true,\n context.frames,\n new Map(),\n );\n\n expect(result.perFrameOutlines).toEqual([\n { frameId: \"frame-1\", outline: \"outline-frame-1\" },\n { frameId: \"frame-2\", outline: \"outline-frame-2\" },\n ]);\n const rootMaps = result.perFrameMaps.get(\"frame-1\");\n expect(rootMaps?.xpathMap[\"0-100\"]).toBe(\"/\");\n expect(rootMaps?.xpathMap[\"0-101\"]).toBe(\"/html[1]\");\n expect(rootMaps?.xpathMap[\"0-102\"]).toBe(\"/html[1]/body[1]\");\n const childMaps = result.perFrameMaps.get(\"frame-2\");\n expect(childMaps?.xpathMap[\"1-200\"]).toBe(\"/\");\n expect(childMaps?.xpathMap[\"1-201\"]).toBe(\"/div[1]\");\n expect(childMaps?.scrollableMap[\"1-201\"]).toBe(true);\n expect(childMaps?.urlMap).toEqual({\n \"url-frame-2\": \"https://frame-2.test\",\n });\n expect(session.callsFor(\"DOM.getFrameOwner\")).toHaveLength(1);\n });\n\n it(\"builds a missing session index on demand and memoizes it\", async () => {\n const session = new MockCDPSession({}, \"new-session\");\n const page = makePage({\n getSessionForFrame: () => session,\n getOrdinal: () => 2,\n });\n const context: FrameContext = {\n rootId: \"frame-9\",\n frames: [\"frame-9\"],\n parentByFrame: new Map([[\"frame-9\", null]]),\n };\n const idx = makeSessionIndex();\n const buildSpy = vi\n .spyOn(domTree, \"buildSessionDomIndex\")\n .mockResolvedValue(idx);\n vi.spyOn(a11yTree, \"a11yForFrame\").mockResolvedValue({\n outline: \"outline\",\n urlMap: {},\n scopeApplied: false,\n });\n\n const sessionToIndex = new Map<string, SessionDomIndex>();\n const result = await capture.collectPerFrameMaps(\n page,\n context,\n sessionToIndex,\n undefined,\n false,\n context.frames,\n new Map(),\n );\n\n expect(buildSpy).toHaveBeenCalledWith(session, false);\n expect(sessionToIndex.get(\"new-session\")).toBe(idx);\n expect(result.perFrameMaps.get(\"frame-9\")?.xpathMap[\"2-100\"]).toBe(\"/\");\n });\n\n it(\"skips frames that are not listed in the frameIds argument\", async () => {\n const session = new MockCDPSession({}, \"session-a\");\n const page = makePage({\n getSessionForFrame: () => session,\n getOrdinal: (frameId: string) => (frameId === \"frame-1\" ? 0 : 1),\n });\n const context: FrameContext = {\n rootId: \"frame-1\",\n frames: [\"frame-1\", \"frame-2\"],\n parentByFrame: new Map([\n [\"frame-1\", null],\n [\"frame-2\", \"frame-1\"],\n ]),\n };\n const sessionIndex = makeSessionIndex();\n const sessionToIndex = new Map([[session.id, sessionIndex]]);\n\n const a11ySpy = vi.spyOn(a11yTree, \"a11yForFrame\").mockResolvedValue({\n outline: \"outline\",\n urlMap: {},\n scopeApplied: false,\n });\n\n const result = await capture.collectPerFrameMaps(\n page,\n context,\n sessionToIndex,\n undefined,\n true,\n [\"frame-1\"],\n new Map(),\n );\n\n expect(a11ySpy).toHaveBeenCalledTimes(1);\n expect(result.perFrameMaps.has(\"frame-2\")).toBe(false);\n expect(result.perFrameOutlines.map((o) => o.frameId)).toEqual([\"frame-1\"]);\n });\n});\n\ndescribe(\"captureHybridSnapshot\", () => {\n it(\"returns early when the scoped snapshot path succeeds\", async () => {\n const session = new MockCDPSession({}, \"session-a\");\n const page = makePage({\n getSessionForFrame: () => session,\n });\n const options = { focusSelector: \"/html\" };\n\n vi.spyOn(focusSelectors, \"resolveFocusFrameAndTail\").mockResolvedValue({\n targetFrameId: \"frame-1\",\n tailXPath: \"\",\n absPrefix: \"\",\n });\n const domMapsSpy = vi\n .spyOn(domTree, \"domMapsForSession\")\n .mockResolvedValue({\n tagNameMap: { \"0-100\": \"#document\" },\n xpathMap: { \"0-100\": \"/\" },\n scrollableMap: {},\n });\n const a11ySpy = vi.spyOn(a11yTree, \"a11yForFrame\").mockResolvedValue({\n outline: \"scoped outline\",\n urlMap: { \"0-100\": \"https://frame-1.test\" },\n scopeApplied: true,\n });\n const buildIndexSpy = vi\n .spyOn(domTree, \"buildSessionDomIndex\")\n .mockResolvedValue(makeSessionIndex());\n\n const result = await capture.captureHybridSnapshot(page, options);\n\n expect(result.combinedTree).toBe(\"scoped outline\");\n expect(result.combinedUrlMap[\"0-100\"]).toBe(\"https://frame-1.test\");\n expect(domMapsSpy).toHaveBeenCalled();\n expect(a11ySpy).toHaveBeenCalled();\n expect(buildIndexSpy).not.toHaveBeenCalled();\n });\n\n it(\"scoped snapshot still succeeds when iframe inclusion is disabled\", async () => {\n const session = new MockCDPSession({}, \"session-a\");\n const page = makePage({\n getSessionForFrame: () => session,\n });\n const options = { focusSelector: \"/html\", includeIframes: false };\n\n vi.spyOn(focusSelectors, \"resolveFocusFrameAndTail\").mockResolvedValue({\n targetFrameId: \"frame-1\",\n tailXPath: \"\",\n absPrefix: \"\",\n });\n const domMapsSpy = vi\n .spyOn(domTree, \"domMapsForSession\")\n .mockResolvedValue({\n tagNameMap: { \"0-100\": \"#document\" },\n xpathMap: { \"0-100\": \"/\" },\n scrollableMap: {},\n });\n const a11ySpy = vi.spyOn(a11yTree, \"a11yForFrame\").mockResolvedValue({\n outline: \"scoped outline\",\n urlMap: { \"0-100\": \"https://frame-1.test\" },\n scopeApplied: true,\n });\n const buildIndexSpy = vi\n .spyOn(domTree, \"buildSessionDomIndex\")\n .mockResolvedValue(makeSessionIndex());\n\n const result = await capture.captureHybridSnapshot(page, options);\n\n expect(result.combinedTree).toBe(\"scoped outline\");\n expect(result.combinedUrlMap[\"0-100\"]).toBe(\"https://frame-1.test\");\n expect(domMapsSpy).toHaveBeenCalled();\n expect(a11ySpy).toHaveBeenCalled();\n expect(buildIndexSpy).not.toHaveBeenCalled();\n });\n\n it(\"filters ignored nodes out of the merged snapshot artifacts\", async () => {\n const session = new MockCDPSession(\n {\n \"DOM.getFrameOwner\": async () => ({ backendNodeId: 150 }),\n \"DOM.describeNode\": async (params) => ({\n node: {\n backendNodeId:\n params?.objectId === \"ignored-object-a\"\n ? 201\n : params?.objectId === \"ignored-object-b\"\n ? 202\n : 0,\n },\n }),\n },\n \"session-a\",\n );\n const page = makePage({\n asProtocolFrameTree: () =>\n makeFrameTree(\"frame-1\", [makeFrameTree(\"frame-2\")]),\n listAllFrameIds: () => [\"frame-1\", \"frame-2\"],\n getSessionForFrame: () => session,\n getOrdinal: (frameId: string) => (frameId === \"frame-1\" ? 0 : 1),\n });\n\n const idx = makeSessionIndex();\n idx.absByBe.set(202, \"/html[1]/body[1]/iframe[1]/aside[1]\");\n idx.tagByBe.set(202, \"aside\");\n idx.docRootOf.set(202, 200);\n idx.enterByBe.set(202, 6);\n idx.exitByBe.set(202, 7);\n idx.exitByBe.set(201, 8);\n idx.exitByBe.set(200, 9);\n idx.exitByBe.set(150, 10);\n idx.exitByBe.set(100, 11);\n vi.spyOn(domTree, \"buildSessionDomIndex\").mockResolvedValue(idx);\n vi.spyOn(focusSelectors, \"resolveCssFocusFrameAndTail\").mockResolvedValue({\n targetFrameId: \"frame-2\",\n tailSelector: \".ad\",\n absPrefix: \"/html/body/iframe[1]\",\n });\n vi.spyOn(FrameSelectorResolver.prototype, \"resolveAll\").mockResolvedValue([\n { objectId: \"ignored-object-a\", nodeId: null },\n { objectId: \"ignored-object-b\", nodeId: null },\n ]);\n vi.spyOn(a11yTree, \"a11yForFrame\").mockImplementation(\n async (_sess, frameId, opts) => ({\n outline:\n opts.isIgnoredBackendNode?.(201) && opts.isIgnoredBackendNode?.(202)\n ? `outline-${frameId}-filtered`\n : `outline-${frameId}`,\n urlMap:\n frameId === \"frame-2\" &&\n opts.isIgnoredBackendNode?.(201) &&\n opts.isIgnoredBackendNode?.(202)\n ? {}\n : { [`url-${frameId}`]: `https://${frameId}.test` },\n scopeApplied: false,\n }),\n );\n\n const snapshot = await capture.captureHybridSnapshot(page, {\n ignoreSelectors: [\".ad\"],\n });\n\n expect(snapshot.combinedXpathMap[\"1-201\"]).toBeUndefined();\n expect(snapshot.combinedXpathMap[\"1-202\"]).toBeUndefined();\n expect(snapshot.combinedUrlMap[\"url-frame-2\"]).toBeUndefined();\n expect(\n snapshot.perFrame?.find((frame) => frame.frameId === \"frame-2\")?.outline,\n ).toContain(\"filtered\");\n });\n\n it(\"excludes child frame subtrees when an ignored node is an iframe host\", async () => {\n const session = new MockCDPSession(\n {\n \"DOM.getFrameOwner\": async () => ({ backendNodeId: 150 }),\n \"DOM.describeNode\": async (params) => ({\n node: { backendNodeId: params?.objectId === \"iframe-host\" ? 150 : 0 },\n }),\n },\n \"session-a\",\n );\n const page = makePage({\n asProtocolFrameTree: () =>\n makeFrameTree(\"frame-1\", [makeFrameTree(\"frame-2\")]),\n listAllFrameIds: () => [\"frame-1\", \"frame-2\"],\n getSessionForFrame: () => session,\n getOrdinal: (frameId: string) => (frameId === \"frame-1\" ? 0 : 1),\n });\n\n vi.spyOn(domTree, \"buildSessionDomIndex\").mockResolvedValue(\n makeSessionIndex(),\n );\n vi.spyOn(focusSelectors, \"resolveCssFocusFrameAndTail\").mockResolvedValue({\n targetFrameId: \"frame-1\",\n tailSelector: \"iframe.ad\",\n absPrefix: \"\",\n });\n vi.spyOn(FrameSelectorResolver.prototype, \"resolveAll\").mockResolvedValue([\n { objectId: \"iframe-host\", nodeId: null },\n ]);\n vi.spyOn(a11yTree, \"a11yForFrame\").mockImplementation(\n async (_sess, frameId, opts) => ({\n outline:\n frameId === \"frame-2\" && opts.isIgnoredBackendNode?.(200)\n ? \"\"\n : `outline-${frameId}`,\n urlMap:\n frameId === \"frame-2\" && opts.isIgnoredBackendNode?.(200)\n ? {}\n : { [`url-${frameId}`]: `https://${frameId}.test` },\n scopeApplied: false,\n }),\n );\n\n const snapshot = await capture.captureHybridSnapshot(page, {\n ignoreSelectors: [\"iframe.ad\"],\n });\n\n expect(snapshot.combinedXpathMap[\"1-200\"]).toBeUndefined();\n expect(snapshot.combinedXpathMap[\"1-201\"]).toBeUndefined();\n expect(snapshot.combinedUrlMap[\"url-frame-2\"]).toBeUndefined();\n expect(snapshot.combinedTree).not.toContain(\"outline-frame-2\");\n });\n\n it(\"collects per-frame data and merges it when no scoped snapshot is available\", async () => {\n const session = new MockCDPSession(\n {\n \"DOM.getFrameOwner\": async () => ({ backendNodeId: 150 }),\n },\n \"session-a\",\n );\n const page = makePage({\n asProtocolFrameTree: () =>\n makeFrameTree(\"frame-1\", [makeFrameTree(\"frame-2\")]),\n listAllFrameIds: () => [\"frame-1\", \"frame-2\"],\n getSessionForFrame: () => session,\n getOrdinal: (frameId: string) => (frameId === \"frame-1\" ? 0 : 1),\n });\n\n const idx = makeSessionIndex();\n vi.spyOn(domTree, \"buildSessionDomIndex\").mockResolvedValue(idx);\n vi.spyOn(a11yTree, \"a11yForFrame\").mockImplementation(\n async (_sess, frameId) => ({\n outline:\n frameId === \"frame-1\"\n ? \"[0-150] iframe host\"\n : \"[1-200] child subtree\",\n urlMap: { [`url-${frameId}`]: `https://${frameId}.test` },\n scopeApplied: false,\n }),\n );\n\n const snapshot = await capture.captureHybridSnapshot(page);\n\n expect(snapshot.combinedTree).toContain(\"[1-200] child subtree\");\n expect(snapshot.combinedXpathMap[\"0-100\"]).toBe(\"/\");\n expect(snapshot.combinedXpathMap[\"1-201\"]).toBe(\n \"/html[1]/body[1]/iframe[1]/div[1]\",\n );\n expect(snapshot.combinedUrlMap[\"url-frame-2\"]).toBe(\"https://frame-2.test\");\n expect(snapshot.perFrame?.map((pf) => pf.frameId)).toEqual([\n \"frame-1\",\n \"frame-2\",\n ]);\n });\n\n it(\"omits iframe frames when includeIframes is false\", async () => {\n const session = new MockCDPSession(\n {\n \"DOM.getFrameOwner\": async () => ({ backendNodeId: 150 }),\n },\n \"session-a\",\n );\n const page = makePage({\n asProtocolFrameTree: () =>\n makeFrameTree(\"frame-1\", [makeFrameTree(\"frame-2\")]),\n listAllFrameIds: () => [\"frame-1\", \"frame-2\"],\n getSessionForFrame: () => session,\n getOrdinal: (frameId: string) => (frameId === \"frame-1\" ? 0 : 1),\n });\n\n const idx = makeSessionIndex();\n vi.spyOn(domTree, \"buildSessionDomIndex\").mockResolvedValue(idx);\n const a11ySpy = vi\n .spyOn(a11yTree, \"a11yForFrame\")\n .mockImplementation(async (_sess, frameId) => ({\n outline:\n frameId === \"frame-1\"\n ? \"[0-150] iframe host\"\n : \"[1-200] child subtree\",\n urlMap: { [`url-${frameId}`]: `https://${frameId}.test` },\n scopeApplied: false,\n }));\n\n const snapshot = await capture.captureHybridSnapshot(page, {\n includeIframes: false,\n });\n\n expect(a11ySpy).toHaveBeenCalledTimes(1);\n expect(session.callsFor(\"DOM.getFrameOwner\")).toHaveLength(0);\n expect(snapshot.perFrame?.map((pf) => pf.frameId)).toEqual([\"frame-1\"]);\n expect(snapshot.combinedXpathMap[\"1-201\"]).toBeUndefined();\n expect(snapshot.combinedTree).not.toContain(\"[1-200] child subtree\");\n });\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const test_1 = require("@playwright/test");
|
|
4
|
-
const v3_js_1 = require("../../lib/v3/v3.js");
|
|
5
|
-
const v3_config_js_1 = require("./v3.config.js");
|
|
6
|
-
const isBrowserbase = (process.env.STAGEHAND_BROWSER_TARGET ?? "local").toLowerCase() ===
|
|
7
|
-
"browserbase";
|
|
8
|
-
test_1.test.describe("Agent captcha auto-solve on Browserbase", () => {
|
|
9
|
-
test_1.test.skip(!isBrowserbase, "Requires Browserbase environment");
|
|
10
|
-
let v3;
|
|
11
|
-
let logs;
|
|
12
|
-
test_1.test.beforeEach(async () => {
|
|
13
|
-
logs = [];
|
|
14
|
-
v3 = new v3_js_1.V3((0, v3_config_js_1.getV3TestConfig)({
|
|
15
|
-
env: "BROWSERBASE",
|
|
16
|
-
verbose: 2,
|
|
17
|
-
logger: (line) => {
|
|
18
|
-
logs.push(line);
|
|
19
|
-
console.log(`[${line.category}] ${line.message}`);
|
|
20
|
-
},
|
|
21
|
-
browserbaseSessionCreateParams: {
|
|
22
|
-
browserSettings: {
|
|
23
|
-
solveCaptchas: true,
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
}));
|
|
27
|
-
await v3.init();
|
|
28
|
-
console.log("BB session URL:", v3.browserbaseSessionURL);
|
|
29
|
-
});
|
|
30
|
-
test_1.test.afterEach(async () => {
|
|
31
|
-
await v3?.close?.().catch(() => { });
|
|
32
|
-
});
|
|
33
|
-
(0, test_1.test)("reCAPTCHA v2 auto-solve (Google demo)", async () => {
|
|
34
|
-
test_1.test.setTimeout(180_000);
|
|
35
|
-
const page = v3.context.pages()[0];
|
|
36
|
-
// Google's official reCAPTCHA v2 demo — same URL the stealth team tests.
|
|
37
|
-
// Use domcontentloaded since BB's route interception can delay full load.
|
|
38
|
-
await page.goto("https://www.google.com/recaptcha/api2/demo", {
|
|
39
|
-
waitUntil: "domcontentloaded",
|
|
40
|
-
});
|
|
41
|
-
// Give BB time to intercept the anchor request and solve the captcha
|
|
42
|
-
await new Promise((r) => setTimeout(r, 30_000));
|
|
43
|
-
const agent = v3.agent({
|
|
44
|
-
mode: "dom",
|
|
45
|
-
model: "anthropic/claude-haiku-4-5-20251001",
|
|
46
|
-
});
|
|
47
|
-
const result = await agent.execute({
|
|
48
|
-
instruction: 'Click the "Submit" button and report the exact text shown on the result page.',
|
|
49
|
-
maxSteps: 15,
|
|
50
|
-
});
|
|
51
|
-
console.log("reCAPTCHA v2 result:", result.message);
|
|
52
|
-
(0, test_1.expect)(result.completed).toBe(true);
|
|
53
|
-
(0, test_1.expect)(result.message.toLowerCase()).toContain("success");
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
//# sourceMappingURL=agent-captcha-autosolve.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"agent-captcha-autosolve.spec.js","sourceRoot":"","sources":["../../../../tests/integration/agent-captcha-autosolve.spec.ts"],"names":[],"mappings":";;AAAA,2CAAgD;AAChD,8CAAwC;AACxC,iDAAiD;AAGjD,MAAM,aAAa,GACjB,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,OAAO,CAAC,CAAC,WAAW,EAAE;IAC/D,aAAa,CAAC;AAEhB,WAAI,CAAC,QAAQ,CAAC,yCAAyC,EAAE,GAAG,EAAE;IAC5D,WAAI,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,kCAAkC,CAAC,CAAC;IAE9D,IAAI,EAAM,CAAC;IACX,IAAI,IAAe,CAAC;IAEpB,WAAI,CAAC,UAAU,CAAC,KAAK,IAAI,EAAE;QACzB,IAAI,GAAG,EAAE,CAAC;QACV,EAAE,GAAG,IAAI,UAAE,CACT,IAAA,8BAAe,EAAC;YACd,GAAG,EAAE,aAAa;YAClB,OAAO,EAAE,CAAC;YACV,MAAM,EAAE,CAAC,IAAa,EAAE,EAAE;gBACxB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAChB,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;YACpD,CAAC;YACD,8BAA8B,EAAE;gBAC9B,eAAe,EAAE;oBACf,aAAa,EAAE,IAAI;iBACpB;aACF;SACF,CAAC,CACH,CAAC;QACF,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,EAAE,CAAC,qBAAqB,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,WAAI,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE;QACxB,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAI,EAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACvD,WAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACzB,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QACnC,yEAAyE;QACzE,0EAA0E;QAC1E,MAAM,IAAI,CAAC,IAAI,CAAC,4CAA4C,EAAE;YAC5D,SAAS,EAAE,kBAAkB;SAC9B,CAAC,CAAC;QAEH,qEAAqE;QACrE,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QAEhD,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC;YACrB,IAAI,EAAE,KAAK;YACX,KAAK,EAAE,qCAAqC;SAC7C,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC;YACjC,WAAW,EACT,+EAA+E;YACjF,QAAQ,EAAE,EAAE;SACb,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QAEpD,IAAA,aAAM,EAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,IAAA,aAAM,EAAC,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { test, expect } from \"@playwright/test\";\nimport { V3 } from \"../../lib/v3/v3.js\";\nimport { getV3TestConfig } from \"./v3.config.js\";\nimport type { LogLine } from \"../../lib/v3/types/public/logs.js\";\n\nconst isBrowserbase =\n (process.env.STAGEHAND_BROWSER_TARGET ?? \"local\").toLowerCase() ===\n \"browserbase\";\n\ntest.describe(\"Agent captcha auto-solve on Browserbase\", () => {\n test.skip(!isBrowserbase, \"Requires Browserbase environment\");\n\n let v3: V3;\n let logs: LogLine[];\n\n test.beforeEach(async () => {\n logs = [];\n v3 = new V3(\n getV3TestConfig({\n env: \"BROWSERBASE\",\n verbose: 2,\n logger: (line: LogLine) => {\n logs.push(line);\n console.log(`[${line.category}] ${line.message}`);\n },\n browserbaseSessionCreateParams: {\n browserSettings: {\n solveCaptchas: true,\n },\n },\n }),\n );\n await v3.init();\n console.log(\"BB session URL:\", v3.browserbaseSessionURL);\n });\n\n test.afterEach(async () => {\n await v3?.close?.().catch(() => {});\n });\n\n test(\"reCAPTCHA v2 auto-solve (Google demo)\", async () => {\n test.setTimeout(180_000);\n const page = v3.context.pages()[0];\n // Google's official reCAPTCHA v2 demo — same URL the stealth team tests.\n // Use domcontentloaded since BB's route interception can delay full load.\n await page.goto(\"https://www.google.com/recaptcha/api2/demo\", {\n waitUntil: \"domcontentloaded\",\n });\n\n // Give BB time to intercept the anchor request and solve the captcha\n await new Promise((r) => setTimeout(r, 30_000));\n\n const agent = v3.agent({\n mode: \"dom\",\n model: \"anthropic/claude-haiku-4-5-20251001\",\n });\n\n const result = await agent.execute({\n instruction:\n 'Click the \"Submit\" button and report the exact text shown on the result page.',\n maxSteps: 15,\n });\n\n console.log(\"reCAPTCHA v2 result:\", result.message);\n\n expect(result.completed).toBe(true);\n expect(result.message.toLowerCase()).toContain(\"success\");\n });\n});\n"]}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { test, expect } from "@playwright/test";
|
|
2
|
-
import { V3 } from "../../lib/v3/v3.js";
|
|
3
|
-
import { getV3TestConfig } from "./v3.config.js";
|
|
4
|
-
const isBrowserbase = (process.env.STAGEHAND_BROWSER_TARGET ?? "local").toLowerCase() ===
|
|
5
|
-
"browserbase";
|
|
6
|
-
test.describe("Agent captcha auto-solve on Browserbase", () => {
|
|
7
|
-
test.skip(!isBrowserbase, "Requires Browserbase environment");
|
|
8
|
-
let v3;
|
|
9
|
-
let logs;
|
|
10
|
-
test.beforeEach(async () => {
|
|
11
|
-
logs = [];
|
|
12
|
-
v3 = new V3(getV3TestConfig({
|
|
13
|
-
env: "BROWSERBASE",
|
|
14
|
-
verbose: 2,
|
|
15
|
-
logger: (line) => {
|
|
16
|
-
logs.push(line);
|
|
17
|
-
console.log(`[${line.category}] ${line.message}`);
|
|
18
|
-
},
|
|
19
|
-
browserbaseSessionCreateParams: {
|
|
20
|
-
browserSettings: {
|
|
21
|
-
solveCaptchas: true,
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
|
-
}));
|
|
25
|
-
await v3.init();
|
|
26
|
-
console.log("BB session URL:", v3.browserbaseSessionURL);
|
|
27
|
-
});
|
|
28
|
-
test.afterEach(async () => {
|
|
29
|
-
await v3?.close?.().catch(() => { });
|
|
30
|
-
});
|
|
31
|
-
test("reCAPTCHA v2 auto-solve (Google demo)", async () => {
|
|
32
|
-
test.setTimeout(180_000);
|
|
33
|
-
const page = v3.context.pages()[0];
|
|
34
|
-
// Google's official reCAPTCHA v2 demo — same URL the stealth team tests.
|
|
35
|
-
// Use domcontentloaded since BB's route interception can delay full load.
|
|
36
|
-
await page.goto("https://www.google.com/recaptcha/api2/demo", {
|
|
37
|
-
waitUntil: "domcontentloaded",
|
|
38
|
-
});
|
|
39
|
-
// Give BB time to intercept the anchor request and solve the captcha
|
|
40
|
-
await new Promise((r) => setTimeout(r, 30_000));
|
|
41
|
-
const agent = v3.agent({
|
|
42
|
-
mode: "dom",
|
|
43
|
-
model: "anthropic/claude-haiku-4-5-20251001",
|
|
44
|
-
});
|
|
45
|
-
const result = await agent.execute({
|
|
46
|
-
instruction: 'Click the "Submit" button and report the exact text shown on the result page.',
|
|
47
|
-
maxSteps: 15,
|
|
48
|
-
});
|
|
49
|
-
console.log("reCAPTCHA v2 result:", result.message);
|
|
50
|
-
expect(result.completed).toBe(true);
|
|
51
|
-
expect(result.message.toLowerCase()).toContain("success");
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
//# sourceMappingURL=agent-captcha-autosolve.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"agent-captcha-autosolve.spec.js","sourceRoot":"","sources":["../../../../tests/integration/agent-captcha-autosolve.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGjD,MAAM,aAAa,GACjB,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,OAAO,CAAC,CAAC,WAAW,EAAE;IAC/D,aAAa,CAAC;AAEhB,IAAI,CAAC,QAAQ,CAAC,yCAAyC,EAAE,GAAG,EAAE;IAC5D,IAAI,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,kCAAkC,CAAC,CAAC;IAE9D,IAAI,EAAM,CAAC;IACX,IAAI,IAAe,CAAC;IAEpB,IAAI,CAAC,UAAU,CAAC,KAAK,IAAI,EAAE;QACzB,IAAI,GAAG,EAAE,CAAC;QACV,EAAE,GAAG,IAAI,EAAE,CACT,eAAe,CAAC;YACd,GAAG,EAAE,aAAa;YAClB,OAAO,EAAE,CAAC;YACV,MAAM,EAAE,CAAC,IAAa,EAAE,EAAE;gBACxB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAChB,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;YACpD,CAAC;YACD,8BAA8B,EAAE;gBAC9B,eAAe,EAAE;oBACf,aAAa,EAAE,IAAI;iBACpB;aACF;SACF,CAAC,CACH,CAAC;QACF,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,EAAE,CAAC,qBAAqB,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE;QACxB,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACvD,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACzB,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QACnC,yEAAyE;QACzE,0EAA0E;QAC1E,MAAM,IAAI,CAAC,IAAI,CAAC,4CAA4C,EAAE;YAC5D,SAAS,EAAE,kBAAkB;SAC9B,CAAC,CAAC;QAEH,qEAAqE;QACrE,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QAEhD,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC;YACrB,IAAI,EAAE,KAAK;YACX,KAAK,EAAE,qCAAqC;SAC7C,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC;YACjC,WAAW,EACT,+EAA+E;YACjF,QAAQ,EAAE,EAAE;SACb,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QAEpD,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { test, expect } from \"@playwright/test\";\nimport { V3 } from \"../../lib/v3/v3.js\";\nimport { getV3TestConfig } from \"./v3.config.js\";\nimport type { LogLine } from \"../../lib/v3/types/public/logs.js\";\n\nconst isBrowserbase =\n (process.env.STAGEHAND_BROWSER_TARGET ?? \"local\").toLowerCase() ===\n \"browserbase\";\n\ntest.describe(\"Agent captcha auto-solve on Browserbase\", () => {\n test.skip(!isBrowserbase, \"Requires Browserbase environment\");\n\n let v3: V3;\n let logs: LogLine[];\n\n test.beforeEach(async () => {\n logs = [];\n v3 = new V3(\n getV3TestConfig({\n env: \"BROWSERBASE\",\n verbose: 2,\n logger: (line: LogLine) => {\n logs.push(line);\n console.log(`[${line.category}] ${line.message}`);\n },\n browserbaseSessionCreateParams: {\n browserSettings: {\n solveCaptchas: true,\n },\n },\n }),\n );\n await v3.init();\n console.log(\"BB session URL:\", v3.browserbaseSessionURL);\n });\n\n test.afterEach(async () => {\n await v3?.close?.().catch(() => {});\n });\n\n test(\"reCAPTCHA v2 auto-solve (Google demo)\", async () => {\n test.setTimeout(180_000);\n const page = v3.context.pages()[0];\n // Google's official reCAPTCHA v2 demo — same URL the stealth team tests.\n // Use domcontentloaded since BB's route interception can delay full load.\n await page.goto(\"https://www.google.com/recaptcha/api2/demo\", {\n waitUntil: \"domcontentloaded\",\n });\n\n // Give BB time to intercept the anchor request and solve the captcha\n await new Promise((r) => setTimeout(r, 30_000));\n\n const agent = v3.agent({\n mode: \"dom\",\n model: \"anthropic/claude-haiku-4-5-20251001\",\n });\n\n const result = await agent.execute({\n instruction:\n 'Click the \"Submit\" button and report the exact text shown on the result page.',\n maxSteps: 15,\n });\n\n console.log(\"reCAPTCHA v2 result:\", result.message);\n\n expect(result.completed).toBe(true);\n expect(result.message.toLowerCase()).toContain(\"success\");\n });\n});\n"]}
|
|
File without changes
|