@empiricalrun/test-gen 0.42.4 → 0.42.9
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/CHANGELOG.md +39 -0
- package/dist/agent/browsing/utils.d.ts.map +1 -1
- package/dist/agent/browsing/utils.js +1 -0
- package/dist/agent/codegen/create-test-block.d.ts.map +1 -1
- package/dist/agent/codegen/create-test-block.js +4 -2
- package/dist/agent/codegen/lexical-scoped-vars.d.ts.map +1 -1
- package/dist/agent/codegen/lexical-scoped-vars.js +4 -6
- package/dist/agent/codegen/promptBuilder.d.ts +3 -0
- package/dist/agent/codegen/promptBuilder.d.ts.map +1 -0
- package/dist/agent/codegen/promptBuilder.js +44 -0
- package/dist/agent/codegen/repo-edit.js +1 -1
- package/dist/agent/master/action-tool-calls.d.ts +40 -0
- package/dist/agent/master/action-tool-calls.d.ts.map +1 -0
- package/dist/agent/master/action-tool-calls.js +83 -0
- package/dist/agent/master/element-annotation.d.ts +7 -2
- package/dist/agent/master/element-annotation.d.ts.map +1 -1
- package/dist/agent/master/element-annotation.js +13 -3
- package/dist/agent/master/next-action.d.ts +12 -14
- package/dist/agent/master/next-action.d.ts.map +1 -1
- package/dist/agent/master/next-action.js +62 -63
- package/dist/agent/master/run.d.ts.map +1 -1
- package/dist/agent/master/run.js +68 -51
- package/dist/agent/master/scroller.d.ts +15 -0
- package/dist/agent/master/scroller.d.ts.map +1 -0
- package/dist/agent/master/scroller.js +371 -0
- package/dist/agent/master/with-hints.d.ts.map +1 -1
- package/dist/agent/master/with-hints.js +4 -1
- package/dist/agent/utils.d.ts +2 -0
- package/dist/agent/utils.d.ts.map +1 -0
- package/dist/agent/utils.js +12 -0
- package/dist/bin/utils/platform/web/index.d.ts.map +1 -1
- package/dist/bin/utils/platform/web/index.js +2 -0
- package/dist/browser-injected-scripts/annotate-elements.js +122 -74
- package/dist/browser-injected-scripts/annotate-elements.spec.d.ts +2 -0
- package/dist/browser-injected-scripts/annotate-elements.spec.d.ts.map +1 -0
- package/dist/browser-injected-scripts/annotate-elements.spec.js +186 -0
- package/dist/browser-injected-scripts/annotate-elements.spec.ts +52 -26
- package/dist/evals/master-agent.evals.d.ts.map +1 -1
- package/dist/evals/master-agent.evals.js +5 -4
- package/dist/prompts/lib/ts-transformer.d.ts +4 -0
- package/dist/prompts/lib/ts-transformer.d.ts.map +1 -0
- package/dist/prompts/lib/ts-transformer.js +90 -0
- package/dist/prompts/lib/vitest-plugin.d.ts +8 -0
- package/dist/prompts/lib/vitest-plugin.d.ts.map +1 -0
- package/dist/prompts/lib/vitest-plugin.js +20 -0
- package/dist/session/index.d.ts.map +1 -1
- package/dist/session/index.js +4 -0
- package/package.json +10 -8
- package/playwright.config.ts +1 -1
- package/vitest.config.ts +5 -0
- package/browser-injected-scripts/annotate-elements.js +0 -491
- package/browser-injected-scripts/annotate-elements.spec.ts +0 -277
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* eslint-disable no-
|
|
1
|
+
/* eslint-disable autofix/no-unused-vars */
|
|
2
2
|
/**
|
|
3
3
|
* Annotates all clickable elements on the page with unique hint markers.
|
|
4
4
|
* Returns an object containing annotations and methods to enable/disable them.
|
|
@@ -9,7 +9,10 @@
|
|
|
9
9
|
* @param {string} options.markerClass - CSS class to apply to hint markers.
|
|
10
10
|
* @returns {Object} An object containing annotations map and enable/disable methods.
|
|
11
11
|
*/
|
|
12
|
-
function
|
|
12
|
+
function annotateElementsWithPreference({
|
|
13
|
+
options = {},
|
|
14
|
+
preference = {},
|
|
15
|
+
} = {}) {
|
|
13
16
|
const {
|
|
14
17
|
hintCharacterSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ", // Default set of characters for hints
|
|
15
18
|
maxHints = 1000, // Maximum number of hints to generate
|
|
@@ -35,38 +38,18 @@ function annotateClickableElements({ options = {}, preference } = {}) {
|
|
|
35
38
|
if (
|
|
36
39
|
centerX < 0 ||
|
|
37
40
|
centerY < 0 ||
|
|
38
|
-
centerX >
|
|
39
|
-
|
|
41
|
+
centerX >
|
|
42
|
+
(windowToAnnotate.innerWidth || document.documentElement.clientWidth) ||
|
|
43
|
+
centerY >
|
|
44
|
+
(windowToAnnotate.innerHeight || document.documentElement.clientHeight)
|
|
40
45
|
) {
|
|
41
|
-
|
|
42
|
-
const viewportWidth =
|
|
43
|
-
windowToAnnotate.innerWidth || document.documentElement.clientWidth;
|
|
44
|
-
const viewportHeight =
|
|
45
|
-
windowToAnnotate.innerHeight || document.documentElement.clientHeight;
|
|
46
|
-
|
|
47
|
-
// Calculate the new scroll positions to bring the element into the center of the viewport
|
|
48
|
-
const newScrollX = centerX - viewportWidth / 2;
|
|
49
|
-
const newScrollY = centerY - viewportHeight / 2;
|
|
50
|
-
|
|
51
|
-
// Scroll the window to the new positions
|
|
52
|
-
windowToAnnotate.scrollTo({
|
|
53
|
-
top: newScrollY,
|
|
54
|
-
left: newScrollX,
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
const newRect = element.getBoundingClientRect();
|
|
58
|
-
const newCenterX = newRect.left + newRect.width / 2;
|
|
59
|
-
const newCenterY = newRect.top + newRect.height / 2;
|
|
60
|
-
const topElement = document.elementFromPoint(newCenterX, newCenterY);
|
|
61
|
-
const doesElementContainTopElement = element.contains(topElement);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
// Restore the original scroll positions
|
|
65
|
-
windowToAnnotate.scrollTo(originalScrollX, originalScrollY);
|
|
66
|
-
return doesElementContainTopElement;
|
|
46
|
+
return false;
|
|
67
47
|
}
|
|
68
48
|
|
|
69
|
-
const topElement = windowToAnnotate.document.elementFromPoint(
|
|
49
|
+
const topElement = windowToAnnotate.document.elementFromPoint(
|
|
50
|
+
centerX,
|
|
51
|
+
centerY,
|
|
52
|
+
);
|
|
70
53
|
|
|
71
54
|
// Check if the topmost element is the target element or one of its descendants
|
|
72
55
|
return element.contains(topElement);
|
|
@@ -98,7 +81,7 @@ function annotateClickableElements({ options = {}, preference } = {}) {
|
|
|
98
81
|
acc
|
|
99
82
|
.map((a) => curr.map((b) => a.concat([b])))
|
|
100
83
|
.reduce((a, b) => a.concat(b), []),
|
|
101
|
-
[[]]
|
|
84
|
+
[[]],
|
|
102
85
|
);
|
|
103
86
|
}
|
|
104
87
|
|
|
@@ -121,7 +104,7 @@ function annotateClickableElements({ options = {}, preference } = {}) {
|
|
|
121
104
|
style.display === "none" ||
|
|
122
105
|
style.visibility === "hidden" ||
|
|
123
106
|
// This is done for cases where opacity is undefined
|
|
124
|
-
// parseFloat(style.opacity) === 0
|
|
107
|
+
// parseFloat(style.opacity) === 0
|
|
125
108
|
style.pointerEvents === "none"
|
|
126
109
|
) {
|
|
127
110
|
return false;
|
|
@@ -173,11 +156,11 @@ function annotateClickableElements({ options = {}, preference } = {}) {
|
|
|
173
156
|
// Check for onclick attribute or listener
|
|
174
157
|
if (
|
|
175
158
|
(element.hasAttribute("onclick") ||
|
|
176
|
-
|
|
159
|
+
typeof element.onclick === "function") &&
|
|
177
160
|
// check for parent element having same on click
|
|
178
|
-
|
|
161
|
+
element.parentNode.onclick !== element.onclick &&
|
|
179
162
|
// parent element should not be a focusable tag like button
|
|
180
|
-
|
|
163
|
+
focusableTags.indexOf(element.parentNode.tagName.toLowerCase()) === -1
|
|
181
164
|
) {
|
|
182
165
|
isClickable = true;
|
|
183
166
|
}
|
|
@@ -227,7 +210,6 @@ function annotateClickableElements({ options = {}, preference } = {}) {
|
|
|
227
210
|
}
|
|
228
211
|
}
|
|
229
212
|
|
|
230
|
-
|
|
231
213
|
if (focusableTags.includes(tagName)) {
|
|
232
214
|
switch (tagName) {
|
|
233
215
|
case "a":
|
|
@@ -321,7 +303,7 @@ function annotateClickableElements({ options = {}, preference } = {}) {
|
|
|
321
303
|
// Create a hint marker
|
|
322
304
|
function createHintMarker(el, hint, parentElement, windowToAnnotate) {
|
|
323
305
|
const rect = el.getBoundingClientRect();
|
|
324
|
-
|
|
306
|
+
|
|
325
307
|
// Create the marker element
|
|
326
308
|
const marker = document.createElement("div");
|
|
327
309
|
marker.textContent = hint;
|
|
@@ -350,13 +332,12 @@ function annotateClickableElements({ options = {}, preference } = {}) {
|
|
|
350
332
|
fontWeight: "bold",
|
|
351
333
|
textShadow: "rgba(255, 255, 255, 0.6) 0px 1px 0px",
|
|
352
334
|
});
|
|
353
|
-
|
|
335
|
+
|
|
354
336
|
// Attach the marker to the specified parent element
|
|
355
337
|
parentElement.appendChild(marker);
|
|
356
338
|
parentElements.push(parentElement);
|
|
357
339
|
return marker;
|
|
358
340
|
}
|
|
359
|
-
|
|
360
341
|
|
|
361
342
|
// Clear existing annotations
|
|
362
343
|
//TODO: Handle clearing annotations
|
|
@@ -371,51 +352,113 @@ function annotateClickableElements({ options = {}, preference } = {}) {
|
|
|
371
352
|
function isInputElement(el) {
|
|
372
353
|
// Check if it's an input with a text-like type
|
|
373
354
|
if (el instanceof HTMLInputElement) {
|
|
374
|
-
const textTypes = [
|
|
355
|
+
const textTypes = [
|
|
356
|
+
"text",
|
|
357
|
+
"email",
|
|
358
|
+
"number",
|
|
359
|
+
"password",
|
|
360
|
+
"search",
|
|
361
|
+
"tel",
|
|
362
|
+
"url",
|
|
363
|
+
"checkbox",
|
|
364
|
+
];
|
|
375
365
|
return textTypes.includes(el.type.toLowerCase());
|
|
376
366
|
}
|
|
377
|
-
|
|
367
|
+
|
|
378
368
|
// Check if it's a textarea
|
|
379
369
|
if (el instanceof HTMLTextAreaElement) {
|
|
380
370
|
return true;
|
|
381
371
|
}
|
|
382
|
-
|
|
372
|
+
|
|
383
373
|
// Check if it's contentEditable
|
|
384
374
|
return el.isContentEditable;
|
|
385
375
|
}
|
|
386
376
|
|
|
377
|
+
function isRequiredTextPresent(el, assertionText) {
|
|
378
|
+
assertionText = assertionText?.trim().toLowerCase();
|
|
379
|
+
if (assertionText) {
|
|
380
|
+
let elementText = el.innerText?.trim().toLowerCase();
|
|
381
|
+
let placeHolderText = el.placeholder?.trim().toLowerCase();
|
|
382
|
+
if (elementText === assertionText || placeHolderText === assertionText) {
|
|
383
|
+
//Check if the text for parent and child is same or not, if its same don't annotate again
|
|
384
|
+
if (el.parentNode.innerText?.toLowerCase() !== elementText) {
|
|
385
|
+
return true;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
return true;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// This checks if the element is scrollable or not
|
|
394
|
+
function isElementScrollable(elem) {
|
|
395
|
+
function getComputedStyle(elem) {
|
|
396
|
+
return window.getComputedStyle(elem, null);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
function getActualCss(elem, style) {
|
|
400
|
+
return getComputedStyle(elem)[style];
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function isYScrollable(elem) {
|
|
404
|
+
return (
|
|
405
|
+
elem.offsetHeight < elem.scrollHeight &&
|
|
406
|
+
autoOrScroll(getActualCss(elem, "overflow-y"))
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
function autoOrScroll(text) {
|
|
411
|
+
return text == "scroll" || text == "auto";
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// This doesn't annotate the elements with horizontal scroll
|
|
415
|
+
return isYScrollable(elem);
|
|
416
|
+
}
|
|
417
|
+
|
|
387
418
|
// Initialize annotations for a given window (including iframes)
|
|
388
419
|
function initializeAnnotations(windowToAnnotate, parentHints, depth) {
|
|
389
420
|
const container =
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
421
|
+
parentHints?.nodeName === "IFRAME"
|
|
422
|
+
? parentHints.contentWindow.document.body
|
|
423
|
+
: annotationsContainer;
|
|
393
424
|
|
|
394
425
|
// Ensure the container exists
|
|
395
426
|
if (!container) return;
|
|
396
|
-
|
|
427
|
+
|
|
397
428
|
// Filter for clickable elements
|
|
398
|
-
const
|
|
429
|
+
const elementsToAnnotate = Array.from(
|
|
430
|
+
windowToAnnotate.document.querySelectorAll("*"),
|
|
431
|
+
).filter((el) => {
|
|
432
|
+
// Here based on the action type we filter the elements
|
|
433
|
+
// and annotate only those elements
|
|
434
|
+
switch (preference.actionType) {
|
|
435
|
+
case "fill":
|
|
436
|
+
return isInputElement(el);
|
|
399
437
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
}
|
|
438
|
+
case "assert_text":
|
|
439
|
+
return isRequiredTextPresent(el, preference.assertionText);
|
|
440
|
+
|
|
441
|
+
case "scroll":
|
|
442
|
+
return isElementScrollable(el);
|
|
406
443
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
444
|
+
default:
|
|
445
|
+
return (
|
|
446
|
+
isElementClickable(el, windowToAnnotate) &&
|
|
447
|
+
isElementClickNotBlocked(el, windowToAnnotate)
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
});
|
|
411
451
|
// Generate hint strings for the clickable elements
|
|
412
|
-
const hints = generateHintStrings(
|
|
413
|
-
|
|
452
|
+
const hints = generateHintStrings(
|
|
453
|
+
hintCharacterSet,
|
|
454
|
+
Math.min(maxHints, elementsToAnnotate.length),
|
|
455
|
+
);
|
|
456
|
+
|
|
414
457
|
// Create markers for the elements
|
|
415
|
-
|
|
458
|
+
elementsToAnnotate.slice(0, maxHints).forEach((el, index) => {
|
|
416
459
|
const hint = hints[index];
|
|
417
460
|
const rect = el.getBoundingClientRect();
|
|
418
|
-
|
|
461
|
+
|
|
419
462
|
// Use createHintMarker with the specified container
|
|
420
463
|
createHintMarker(el, hint, container, windowToAnnotate);
|
|
421
464
|
el.style.boxShadow = `inset 0 0 0px 2px red`;
|
|
@@ -429,23 +472,28 @@ function annotateClickableElements({ options = {}, preference } = {}) {
|
|
|
429
472
|
width: rect.width,
|
|
430
473
|
height: rect.height,
|
|
431
474
|
},
|
|
432
|
-
depth: [...depth
|
|
475
|
+
depth: [...depth],
|
|
433
476
|
};
|
|
434
477
|
});
|
|
435
|
-
|
|
478
|
+
|
|
436
479
|
// Process iframes recursively
|
|
437
|
-
Array.from(windowToAnnotate.document.querySelectorAll("iframe")).forEach(
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
480
|
+
Array.from(windowToAnnotate.document.querySelectorAll("iframe")).forEach(
|
|
481
|
+
(iframe) => {
|
|
482
|
+
try {
|
|
483
|
+
const frameWindow = iframe.contentWindow;
|
|
484
|
+
if (
|
|
485
|
+
frameWindow &&
|
|
486
|
+
iframe.offsetWidth > 0 &&
|
|
487
|
+
iframe.offsetHeight > 0
|
|
488
|
+
) {
|
|
489
|
+
initializeAnnotations(frameWindow, iframe, [...depth, iframe]);
|
|
490
|
+
}
|
|
491
|
+
} catch (e) {
|
|
492
|
+
console.warn("Cannot access iframe:", e);
|
|
442
493
|
}
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
}
|
|
446
|
-
});
|
|
494
|
+
},
|
|
495
|
+
);
|
|
447
496
|
}
|
|
448
|
-
|
|
449
497
|
|
|
450
498
|
// Initialize and enable annotations
|
|
451
499
|
function enable() {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"annotate-elements.spec.d.ts","sourceRoot":"","sources":["../../src/browser-injected-scripts/annotate-elements.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
// @ts-nocheck
|
|
7
|
+
const test_1 = require("@playwright/test");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const action_tool_calls_1 = require("../agent/master/action-tool-calls");
|
|
10
|
+
(0, test_1.test)("should annotate all links on empirical landing page", async ({ page, }) => {
|
|
11
|
+
await page.goto("https://assets-test.empirical.run/selector-hints-testing/dom-1.html");
|
|
12
|
+
await page.addScriptTag({
|
|
13
|
+
path: path_1.default.resolve(__dirname, "./annotate-elements.js"),
|
|
14
|
+
});
|
|
15
|
+
const annotations = await page.evaluate(() => {
|
|
16
|
+
// eslint-disable-next-line no-undef
|
|
17
|
+
const { annotations } = annotateElementsWithPreference();
|
|
18
|
+
return Object.entries(annotations).map(([, config]) => ({
|
|
19
|
+
innerText: config.node.innerText,
|
|
20
|
+
tagName: config.node.tagName,
|
|
21
|
+
href: config.node.href,
|
|
22
|
+
}));
|
|
23
|
+
});
|
|
24
|
+
test_1.test.expect(annotations).toEqual([
|
|
25
|
+
{
|
|
26
|
+
innerText: "Empirical",
|
|
27
|
+
tagName: "A",
|
|
28
|
+
href: "https://assets-test.empirical.run/",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
innerText: "Blog",
|
|
32
|
+
tagName: "A",
|
|
33
|
+
href: "https://assets-test.empirical.run/blog",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
innerText: "Contact us",
|
|
37
|
+
tagName: "A",
|
|
38
|
+
href: "https://assets-test.empirical.run/contact",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
href: "https://dash.empirical.run/",
|
|
42
|
+
innerText: "Login ↗\n(opens in a new tab)",
|
|
43
|
+
tagName: "A",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
innerText: "Get early access",
|
|
47
|
+
tagName: "A",
|
|
48
|
+
href: "https://assets-test.empirical.run/contact",
|
|
49
|
+
},
|
|
50
|
+
]);
|
|
51
|
+
});
|
|
52
|
+
(0, test_1.test)("should annotate all important items on quizizz page", async ({ page, }) => {
|
|
53
|
+
await page.goto("https://assets-test.empirical.run/selector-hints-testing/dom-2/index.html");
|
|
54
|
+
await page.addScriptTag({
|
|
55
|
+
path: path_1.default.resolve(__dirname, "./annotate-elements.js"),
|
|
56
|
+
});
|
|
57
|
+
const annotations = await page.evaluate(() => {
|
|
58
|
+
// eslint-disable-next-line no-undef
|
|
59
|
+
const { annotations } = annotateElementsWithPreference();
|
|
60
|
+
return Object.entries(annotations).map(([hint, config]) => ({
|
|
61
|
+
hint,
|
|
62
|
+
innerText: config.node.innerText.toLowerCase().trim(),
|
|
63
|
+
tagName: config.node.tagName,
|
|
64
|
+
testId: config.node.getAttribute("data-testid"),
|
|
65
|
+
href: config.node.href,
|
|
66
|
+
}));
|
|
67
|
+
});
|
|
68
|
+
test_1.test
|
|
69
|
+
.expect(annotations.find((item) => item.innerText.includes("enter code")))
|
|
70
|
+
.toBeTruthy();
|
|
71
|
+
test_1.test
|
|
72
|
+
.expect(annotations.find((item) => item.innerText.includes("get help")))
|
|
73
|
+
.toBeTruthy();
|
|
74
|
+
test_1.test
|
|
75
|
+
.expect(annotations.find((item) => item.innerText.includes("create") &&
|
|
76
|
+
item.testId === "create-content-button"))
|
|
77
|
+
.toBeTruthy();
|
|
78
|
+
test_1.test
|
|
79
|
+
.expect(annotations.find((item) => item.innerText.includes("explore") &&
|
|
80
|
+
item.href === "https://quizizz.com/admin"))
|
|
81
|
+
.toBeTruthy();
|
|
82
|
+
test_1.test
|
|
83
|
+
.expect(annotations.find((item) => item.innerText.includes("library") &&
|
|
84
|
+
item.href === "https://quizizz.com/admin/my-library/createdByMe"))
|
|
85
|
+
.toBeTruthy();
|
|
86
|
+
test_1.test
|
|
87
|
+
.expect(annotations.find((item) => item.innerText.includes("reports") &&
|
|
88
|
+
item.href === "https://quizizz.com/admin/reports"))
|
|
89
|
+
.toBeTruthy();
|
|
90
|
+
test_1.test
|
|
91
|
+
.expect(annotations.find((item) => item.innerText.includes("classes") &&
|
|
92
|
+
item.href === "https://quizizz.com/admin/classes"))
|
|
93
|
+
.toBeTruthy();
|
|
94
|
+
test_1.test
|
|
95
|
+
.expect(annotations.find((item) => item.innerText.includes("accommodations") &&
|
|
96
|
+
item.href ===
|
|
97
|
+
"https://quizizz.com/admin/differentiation/accommodations"))
|
|
98
|
+
.toBeTruthy();
|
|
99
|
+
test_1.test
|
|
100
|
+
.expect(annotations.find((item) => item.innerText.includes("quizizz ai") &&
|
|
101
|
+
item.href === "https://quizizz.com/admin/quizizz-ai"))
|
|
102
|
+
.toBeTruthy();
|
|
103
|
+
test_1.test
|
|
104
|
+
.expect(annotations.find((item) => item.innerText.includes("start your free trial") &&
|
|
105
|
+
item.href === "https://quizizz.com/super-pricing"))
|
|
106
|
+
.toBeTruthy();
|
|
107
|
+
test_1.test
|
|
108
|
+
.expect(annotations.find((item) => item.innerText.includes("upgrade") &&
|
|
109
|
+
item.href === "https://quizizz.com/super-pricing?backto=/admin"))
|
|
110
|
+
.toBeTruthy();
|
|
111
|
+
test_1.test
|
|
112
|
+
.expect(annotations.find((item) => item.tagName === "INPUT" &&
|
|
113
|
+
item.testId === "emphasized-search-bar-input"))
|
|
114
|
+
.toBeTruthy();
|
|
115
|
+
test_1.test
|
|
116
|
+
.expect(annotations.find((item) => item.tagName === "BUTTON" &&
|
|
117
|
+
item.innerText.includes("verify details") &&
|
|
118
|
+
item.testId === "verify-profile-cta"))
|
|
119
|
+
.toBeTruthy();
|
|
120
|
+
test_1.test
|
|
121
|
+
.expect(annotations.find((item) => item.tagName === "BUTTON" && item.innerText.includes("for you")))
|
|
122
|
+
.toBeTruthy();
|
|
123
|
+
test_1.test
|
|
124
|
+
.expect(annotations.find((item) => item.tagName === "BUTTON" && item.innerText.includes("assessments")))
|
|
125
|
+
.toBeTruthy();
|
|
126
|
+
test_1.test
|
|
127
|
+
.expect(annotations.find((item) => item.tagName === "BUTTON" && item.innerText.includes("lessons")))
|
|
128
|
+
.toBeTruthy();
|
|
129
|
+
test_1.test
|
|
130
|
+
.expect(annotations.find((item) => item.tagName === "BUTTON" &&
|
|
131
|
+
item.innerText.includes("interactive videos")))
|
|
132
|
+
.toBeTruthy();
|
|
133
|
+
test_1.test
|
|
134
|
+
.expect(annotations.find((item) => item.tagName === "BUTTON" && item.innerText.includes("passages")))
|
|
135
|
+
.toBeTruthy();
|
|
136
|
+
});
|
|
137
|
+
(0, test_1.test)("should only annotate input fields on quizizz page", async ({ page }) => {
|
|
138
|
+
await page.goto("https://assets-test.empirical.run/selector-hints-testing/dom-2/index.html");
|
|
139
|
+
await page.addScriptTag({
|
|
140
|
+
path: path_1.default.resolve(__dirname, "./annotate-elements.js"),
|
|
141
|
+
});
|
|
142
|
+
const preference = {
|
|
143
|
+
actionType: action_tool_calls_1.ActionType.FILL,
|
|
144
|
+
};
|
|
145
|
+
const annotations = await page.evaluate((preference) => {
|
|
146
|
+
// eslint-disable-next-line no-undef
|
|
147
|
+
const { annotations } = annotateElementsWithPreference({
|
|
148
|
+
preference: preference,
|
|
149
|
+
});
|
|
150
|
+
return Object.entries(annotations).map(([hint, config]) => ({
|
|
151
|
+
hint,
|
|
152
|
+
innerText: config.node.innerText.toLowerCase().trim(),
|
|
153
|
+
tagName: config.node.tagName,
|
|
154
|
+
testId: config.node.getAttribute("data-testid"),
|
|
155
|
+
href: config.node.href,
|
|
156
|
+
}));
|
|
157
|
+
}, preference);
|
|
158
|
+
test_1.test.expect(annotations.length).toBe(1);
|
|
159
|
+
test_1.test.expect(annotations[0].testId).toBe("emphasized-search-bar-input");
|
|
160
|
+
});
|
|
161
|
+
(0, test_1.test)("should only annotate given text on quizziz page", async ({ page }) => {
|
|
162
|
+
await page.goto("https://assets-test.empirical.run/selector-hints-testing/dom-2/index.html");
|
|
163
|
+
await page.addScriptTag({
|
|
164
|
+
path: path_1.default.resolve(__dirname, "./annotate-elements.js"),
|
|
165
|
+
});
|
|
166
|
+
const preference = {
|
|
167
|
+
actionType: action_tool_calls_1.ActionType.ASSERT_TEXT,
|
|
168
|
+
assertionText: "What are you teaching today?",
|
|
169
|
+
};
|
|
170
|
+
const annotations = await page.evaluate((preference) => {
|
|
171
|
+
// eslint-disable-next-line no-undef
|
|
172
|
+
const { annotations } = annotateElementsWithPreference({
|
|
173
|
+
preference: preference,
|
|
174
|
+
});
|
|
175
|
+
return Object.entries(annotations).map(([hint, config]) => ({
|
|
176
|
+
hint,
|
|
177
|
+
innerText: config.node.innerText?.toLowerCase().trim(),
|
|
178
|
+
tagName: config.node.tagName,
|
|
179
|
+
testId: config.node.getAttribute("data-testid"),
|
|
180
|
+
href: config.node.href,
|
|
181
|
+
}));
|
|
182
|
+
}, preference);
|
|
183
|
+
console.log("Annotations:", annotations);
|
|
184
|
+
test_1.test.expect(annotations.length).toBe(1);
|
|
185
|
+
test_1.test.expect(annotations[0]?.tagName).toBe("DIV");
|
|
186
|
+
});
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
import { test } from "@playwright/test";
|
|
4
4
|
import path from "path";
|
|
5
5
|
|
|
6
|
+
import { ActionType } from "../agent/master/action-tool-calls";
|
|
7
|
+
import { AnnotationPreference } from "../agent/master/element-annotation";
|
|
8
|
+
|
|
6
9
|
test("should annotate all links on empirical landing page", async ({
|
|
7
10
|
page,
|
|
8
11
|
}) => {
|
|
@@ -15,9 +18,10 @@ test("should annotate all links on empirical landing page", async ({
|
|
|
15
18
|
});
|
|
16
19
|
|
|
17
20
|
const annotations = await page.evaluate(() => {
|
|
18
|
-
|
|
21
|
+
// eslint-disable-next-line no-undef
|
|
22
|
+
const { annotations } = annotateElementsWithPreference();
|
|
19
23
|
|
|
20
|
-
return Object.entries(annotations).map(([
|
|
24
|
+
return Object.entries(annotations).map(([, config]) => ({
|
|
21
25
|
innerText: config.node.innerText,
|
|
22
26
|
tagName: config.node.tagName,
|
|
23
27
|
href: config.node.href,
|
|
@@ -50,21 +54,6 @@ test("should annotate all links on empirical landing page", async ({
|
|
|
50
54
|
tagName: "A",
|
|
51
55
|
href: "https://assets-test.empirical.run/contact",
|
|
52
56
|
},
|
|
53
|
-
{
|
|
54
|
-
innerText: "Playwright\n(opens in a new tab)",
|
|
55
|
-
tagName: "A",
|
|
56
|
-
href: "https://github.com/microsoft/playwright",
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
innerText: "Meet with us",
|
|
60
|
-
tagName: "A",
|
|
61
|
-
href: "https://assets-test.empirical.run/contact",
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
innerText: "Privacy Policy",
|
|
65
|
-
tagName: "A",
|
|
66
|
-
href: "https://assets-test.empirical.run/privacy.html",
|
|
67
|
-
},
|
|
68
57
|
]);
|
|
69
58
|
});
|
|
70
59
|
|
|
@@ -80,7 +69,8 @@ test("should annotate all important items on quizizz page", async ({
|
|
|
80
69
|
});
|
|
81
70
|
|
|
82
71
|
const annotations = await page.evaluate(() => {
|
|
83
|
-
|
|
72
|
+
// eslint-disable-next-line no-undef
|
|
73
|
+
const { annotations } = annotateElementsWithPreference();
|
|
84
74
|
|
|
85
75
|
return Object.entries(annotations).map(([hint, config]) => ({
|
|
86
76
|
hint,
|
|
@@ -148,7 +138,7 @@ test("should annotate all important items on quizizz page", async ({
|
|
|
148
138
|
(item) =>
|
|
149
139
|
item.innerText.includes("accommodations") &&
|
|
150
140
|
item.href ===
|
|
151
|
-
|
|
141
|
+
"https://quizizz.com/admin/differentiation/accommodations",
|
|
152
142
|
),
|
|
153
143
|
)
|
|
154
144
|
.toBeTruthy();
|
|
@@ -248,9 +238,7 @@ test("should annotate all important items on quizizz page", async ({
|
|
|
248
238
|
.toBeTruthy();
|
|
249
239
|
});
|
|
250
240
|
|
|
251
|
-
test("should only annotate input fields on quizizz page", async ({
|
|
252
|
-
page,
|
|
253
|
-
}) => {
|
|
241
|
+
test("should only annotate input fields on quizizz page", async ({ page }) => {
|
|
254
242
|
await page.goto(
|
|
255
243
|
"https://assets-test.empirical.run/selector-hints-testing/dom-2/index.html",
|
|
256
244
|
);
|
|
@@ -259,9 +247,14 @@ test("should only annotate input fields on quizizz page", async ({
|
|
|
259
247
|
path: path.resolve(__dirname, "./annotate-elements.js"),
|
|
260
248
|
});
|
|
261
249
|
|
|
262
|
-
const preference =
|
|
250
|
+
const preference = {
|
|
251
|
+
actionType: ActionType.FILL,
|
|
252
|
+
};
|
|
263
253
|
const annotations = await page.evaluate((preference) => {
|
|
264
|
-
|
|
254
|
+
// eslint-disable-next-line no-undef
|
|
255
|
+
const { annotations } = annotateElementsWithPreference({
|
|
256
|
+
preference: preference,
|
|
257
|
+
});
|
|
265
258
|
|
|
266
259
|
return Object.entries(annotations).map(([hint, config]) => ({
|
|
267
260
|
hint,
|
|
@@ -270,8 +263,41 @@ test("should only annotate input fields on quizizz page", async ({
|
|
|
270
263
|
testId: config.node.getAttribute("data-testid"),
|
|
271
264
|
href: config.node.href,
|
|
272
265
|
}));
|
|
273
|
-
},preference);
|
|
266
|
+
}, preference);
|
|
267
|
+
|
|
268
|
+
test.expect(annotations.length).toBe(1);
|
|
269
|
+
test.expect(annotations[0].testId).toBe("emphasized-search-bar-input");
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
test("should only annotate given text on quizziz page", async ({ page }) => {
|
|
273
|
+
await page.goto(
|
|
274
|
+
"https://assets-test.empirical.run/selector-hints-testing/dom-2/index.html",
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
await page.addScriptTag({
|
|
278
|
+
path: path.resolve(__dirname, "./annotate-elements.js"),
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
const preference: AnnotationPreference = {
|
|
282
|
+
actionType: ActionType.ASSERT_TEXT,
|
|
283
|
+
assertionText: "What are you teaching today?",
|
|
284
|
+
};
|
|
285
|
+
const annotations = await page.evaluate((preference) => {
|
|
286
|
+
// eslint-disable-next-line no-undef
|
|
287
|
+
const { annotations } = annotateElementsWithPreference({
|
|
288
|
+
preference: preference,
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
return Object.entries(annotations).map(([hint, config]) => ({
|
|
292
|
+
hint,
|
|
293
|
+
innerText: config.node.innerText?.toLowerCase().trim(),
|
|
294
|
+
tagName: config.node.tagName,
|
|
295
|
+
testId: config.node.getAttribute("data-testid"),
|
|
296
|
+
href: config.node.href,
|
|
297
|
+
}));
|
|
298
|
+
}, preference);
|
|
274
299
|
|
|
300
|
+
console.log("Annotations:", annotations);
|
|
275
301
|
test.expect(annotations.length).toBe(1);
|
|
276
|
-
test.expect(annotations[0]
|
|
302
|
+
test.expect(annotations[0]?.tagName).toBe("DIV");
|
|
277
303
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"master-agent.evals.d.ts","sourceRoot":"","sources":["../../src/evals/master-agent.evals.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"master-agent.evals.d.ts","sourceRoot":"","sources":["../../src/evals/master-agent.evals.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC,eAAO,MAAM,4BAA4B,EAAE,UAwC1C,CAAC;AAEF,eAAe,4BAA4B,CAAC"}
|
|
@@ -3,10 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.masterGetNextActionEvaluator = void 0;
|
|
4
4
|
const actions_1 = require("../actions");
|
|
5
5
|
const skill_1 = require("../actions/skill");
|
|
6
|
+
const action_tool_calls_1 = require("../agent/master/action-tool-calls");
|
|
6
7
|
const next_action_1 = require("../agent/master/next-action");
|
|
7
8
|
const page_1 = require("../page");
|
|
8
9
|
const masterGetNextActionEvaluator = async ({ item, trace, }) => {
|
|
9
|
-
const { task, executedActions, failedActions, pageUrl, options, pageScreenshot,
|
|
10
|
+
const { task, executedActions, failedActions, pageUrl, options, pageScreenshot, disableSkills, skills = [], } = item.input;
|
|
10
11
|
const page = {};
|
|
11
12
|
skill_1.testCaseSkills.updateSkills(skills);
|
|
12
13
|
const actions = new actions_1.PlaywrightActions(new page_1.TestGenPage(page, "page"));
|
|
@@ -18,16 +19,16 @@ const masterGetNextActionEvaluator = async ({ item, trace, }) => {
|
|
|
18
19
|
trace,
|
|
19
20
|
options,
|
|
20
21
|
pageScreenshot,
|
|
21
|
-
annotatedPageScreenshot,
|
|
22
22
|
actions,
|
|
23
|
+
actionTypes: action_tool_calls_1.ActionType,
|
|
23
24
|
disableSkills,
|
|
24
|
-
|
|
25
|
+
page,
|
|
25
26
|
});
|
|
26
27
|
return {
|
|
27
28
|
scores: [
|
|
28
29
|
{
|
|
29
30
|
name: "action_correctness",
|
|
30
|
-
value: item.expectedOutput.function.name === output?.
|
|
31
|
+
value: item.expectedOutput.function.name === output?.actionType ? 1 : 0,
|
|
31
32
|
},
|
|
32
33
|
],
|
|
33
34
|
output,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ts-transformer.d.ts","sourceRoot":"","sources":["../../../src/prompts/lib/ts-transformer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,iBAAS,2BAA2B,IAAI,EAAE,CAAC,kBAAkB,CAAC,EAAE,CAAC,UAAU,CAAC,CAkG3E;AAED,eAAe,2BAA2B,CAAC"}
|