@empiricalrun/test-gen 0.46.6 → 0.46.8
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 +20 -0
- package/dist/actions/skill.d.ts.map +1 -1
- package/dist/actions/skill.js +3 -4
- package/dist/agent/browsing/index.d.ts +1 -8
- package/dist/agent/browsing/index.d.ts.map +1 -1
- package/dist/agent/browsing/index.js +2 -4
- package/dist/agent/codegen/skills-retriever.d.ts.map +1 -1
- package/dist/agent/codegen/skills-retriever.js +7 -34
- package/dist/agent/codegen/utils.d.ts.map +1 -1
- package/dist/agent/codegen/utils.js +20 -9
- package/dist/agent/master/action-tool-calls.d.ts +3 -1
- package/dist/agent/master/action-tool-calls.d.ts.map +1 -1
- package/dist/agent/master/action-tool-calls.js +41 -38
- package/dist/agent/master/browser-tests/fixtures.d.ts +9 -0
- package/dist/agent/master/browser-tests/fixtures.d.ts.map +1 -0
- package/dist/agent/master/browser-tests/fixtures.js +33 -0
- package/dist/agent/master/browser-tests/index.spec.js +43 -52
- package/dist/agent/master/browser-tests/skills.spec.d.ts +2 -0
- package/dist/agent/master/browser-tests/skills.spec.d.ts.map +1 -0
- package/dist/agent/master/browser-tests/skills.spec.js +107 -0
- package/dist/agent/master/element-annotation.d.ts +3 -4
- package/dist/agent/master/element-annotation.d.ts.map +1 -1
- package/dist/agent/master/element-annotation.js +2 -2
- package/dist/agent/master/execute-browser-action.d.ts +19 -0
- package/dist/agent/master/execute-browser-action.d.ts.map +1 -0
- package/dist/agent/master/execute-browser-action.js +123 -0
- package/dist/agent/master/execute-skill-action.d.ts +11 -0
- package/dist/agent/master/execute-skill-action.d.ts.map +1 -0
- package/dist/agent/master/execute-skill-action.js +25 -0
- package/dist/agent/master/next-action.d.ts +5 -8
- package/dist/agent/master/next-action.d.ts.map +1 -1
- package/dist/agent/master/next-action.js +11 -91
- package/dist/agent/master/run.d.ts +2 -3
- package/dist/agent/master/run.d.ts.map +1 -1
- package/dist/agent/master/run.js +34 -131
- package/dist/agent/master/scroller.d.ts +1 -1
- package/dist/agent/master/scroller.d.ts.map +1 -1
- package/dist/agent/master/scroller.js +0 -1
- package/dist/browser-injected-scripts/annotate-elements.js +2 -5
- package/dist/browser-injected-scripts/annotate-elements.spec.js +1 -1
- package/dist/browser-injected-scripts/annotate-elements.spec.ts +25 -26
- package/dist/evals/master-agent.evals.d.ts.map +1 -1
- package/dist/evals/master-agent.evals.js +1 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -5
- package/dist/page/index.d.ts +1 -1
- package/dist/page/index.d.ts.map +1 -1
- package/dist/utils/env.d.ts.map +1 -1
- package/dist/utils/env.js +3 -1
- package/package.json +3 -3
- package/playwright.config.ts +11 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @empiricalrun/test-gen
|
|
2
2
|
|
|
3
|
+
## 0.46.8
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 353ee4e: chore: move next action prompt to handlebars
|
|
8
|
+
- 4c8ec02: chore: refactor action executor into a separate file
|
|
9
|
+
- 05329d3: fix: skill action generator for multiple pages
|
|
10
|
+
- 46b3e75: feat: add observation tool call to getNextAction
|
|
11
|
+
- ef4842b: test: scroll and click inside a scrollable div element
|
|
12
|
+
- ea5f6ef: chore: refactor skill execute action
|
|
13
|
+
- 8ad1b4c: test: add a test for skill usage that creates a state variable
|
|
14
|
+
- 1922ab3: chore: Refactor browser tests structure
|
|
15
|
+
- 295b611: test: add test for skill usage and code gen
|
|
16
|
+
|
|
17
|
+
## 0.46.7
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- f2e9d28: fix: button in class name does not mean clickable
|
|
22
|
+
|
|
3
23
|
## 0.46.6
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../src/actions/skill.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../src/actions/skill.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEtE,eAAO,MAAM,WAAW,gBAAgB,CAAC;AAEzC,MAAM,MAAM,KAAK,GAAG;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,cAAM,cAAc;IACN,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,KAAK,EAAE;IAEnC,kBAAkB;IAIlB,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE;CAG7B;AAED,eAAO,MAAM,cAAc,gBAAyB,CAAC;AAErD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;;EAO7D;AAED,eAAO,MAAM,oBAAoB,EAAE,yBAAyB,CAC1D,eAAe,CAkHhB,CAAC"}
|
package/dist/actions/skill.js
CHANGED
|
@@ -8,7 +8,6 @@ const promises_1 = __importDefault(require("fs/promises"));
|
|
|
8
8
|
const api_1 = __importDefault(require("tsx/cjs/api"));
|
|
9
9
|
const use_skill_1 = require("../agent/codegen/use-skill");
|
|
10
10
|
const web_1 = require("../bin/utils/platform/web");
|
|
11
|
-
const utils_1 = require("./utils");
|
|
12
11
|
exports.SKILL_USAGE = "skill_usage";
|
|
13
12
|
class TestCaseSkills {
|
|
14
13
|
skills;
|
|
@@ -51,7 +50,7 @@ const skillActionGenerator = (page, options) => {
|
|
|
51
50
|
sampleUsageMethod: skillDetails.usageExample,
|
|
52
51
|
importPathForSkill: skillFilePath,
|
|
53
52
|
scopeVariablesMapStr: JSON.stringify(options.stateVariables || {}, null, 2),
|
|
54
|
-
pageVariableName:
|
|
53
|
+
pageVariableName: page.name,
|
|
55
54
|
skillMethodDefinition: skillFile,
|
|
56
55
|
trace,
|
|
57
56
|
});
|
|
@@ -66,7 +65,7 @@ const skillActionGenerator = (page, options) => {
|
|
|
66
65
|
newVariables,
|
|
67
66
|
},
|
|
68
67
|
});
|
|
69
|
-
const exec = new Function(
|
|
68
|
+
const exec = new Function(page.name, ...imports, ...stateVarKeys,
|
|
70
69
|
// assuming all POMs are async methods and the LLM should respond with await keyword
|
|
71
70
|
`
|
|
72
71
|
return (async () => {
|
|
@@ -76,7 +75,7 @@ const skillActionGenerator = (page, options) => {
|
|
|
76
75
|
}
|
|
77
76
|
})()`);
|
|
78
77
|
// extract the state variables after execution
|
|
79
|
-
const newStateVariables = await exec(page, ...imports.map((i) => module[i]), ...stateVarKeys.map((s) => options.stateVariables[s]));
|
|
78
|
+
const newStateVariables = await exec(page.pwPageInstance, ...imports.map((i) => module[i]), ...stateVarKeys.map((s) => options.stateVariables[s]));
|
|
80
79
|
options.setStateVariables({
|
|
81
80
|
...options.stateVariables,
|
|
82
81
|
...newStateVariables,
|
|
@@ -1,22 +1,15 @@
|
|
|
1
1
|
import { LLM, TraceClient } from "@empiricalrun/llm";
|
|
2
|
-
import type { TestGenConfigOptions } from "@empiricalrun/shared-types";
|
|
3
2
|
import { Page } from "playwright";
|
|
4
3
|
import { PlaywrightActions } from "../../actions";
|
|
5
|
-
export type BrowsingAgentOptions = Partial<TestGenConfigOptions> & {
|
|
6
|
-
htmlSanitize?: {
|
|
7
|
-
disallowedStrings?: string[];
|
|
8
|
-
};
|
|
9
|
-
};
|
|
10
4
|
export type BrowserAgentAction = {
|
|
11
5
|
action: string;
|
|
12
6
|
code: string | undefined;
|
|
13
7
|
};
|
|
14
|
-
export declare function executeTaskUsingBrowsingAgent({ action, page, actions, llm,
|
|
8
|
+
export declare function executeTaskUsingBrowsingAgent({ action, page, actions, llm, trace, }: {
|
|
15
9
|
action: string;
|
|
16
10
|
page: Page;
|
|
17
11
|
actions: PlaywrightActions;
|
|
18
12
|
llm: LLM;
|
|
19
13
|
trace?: TraceClient;
|
|
20
|
-
options: BrowsingAgentOptions;
|
|
21
14
|
}): Promise<BrowserAgentAction | undefined>;
|
|
22
15
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/browsing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,GAAG,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/browsing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,GAAG,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAQlD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1B,CAAC;AAEF,wBAAsB,6BAA6B,CAAC,EAClD,MAAM,EACN,IAAI,EACJ,OAAO,EACP,GAAG,EACH,KAAK,GACN,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,iBAAiB,CAAC;IAC3B,GAAG,EAAE,GAAG,CAAC;IACT,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB,GAAG,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAkE1C"}
|
|
@@ -8,7 +8,7 @@ const reporter_1 = require("../../reporter");
|
|
|
8
8
|
const html_1 = require("../../utils/html");
|
|
9
9
|
const utils_1 = require("../utils");
|
|
10
10
|
const o1_completion_1 = require("./o1-completion");
|
|
11
|
-
async function executeTaskUsingBrowsingAgent({ action, page, actions, llm,
|
|
11
|
+
async function executeTaskUsingBrowsingAgent({ action, page, actions, llm, trace, }) {
|
|
12
12
|
let generatedCodeSteps;
|
|
13
13
|
const tools = actions.getBrowsingActionSchemas();
|
|
14
14
|
const testgenUpdatesReporter = new reporter_1.TestGenUpdatesReporter();
|
|
@@ -26,7 +26,7 @@ async function executeTaskUsingBrowsingAgent({ action, page, actions, llm, optio
|
|
|
26
26
|
const sanitizationSpan = browsingAgentSpan?.span({
|
|
27
27
|
name: "page-sanitization",
|
|
28
28
|
});
|
|
29
|
-
const pageSnapshot = (0, html_1.sanitizeHtml)(pageContent
|
|
29
|
+
const pageSnapshot = (0, html_1.sanitizeHtml)(pageContent);
|
|
30
30
|
sanitizationSpan?.end({ output: { pageSnapshot } });
|
|
31
31
|
const promptSpan = browsingAgentSpan?.span({ name: "page-prompt" });
|
|
32
32
|
const messages = (0, llm_1.compilePrompt)(promptTemplate_0, { pageSnapshot, task: action });
|
|
@@ -43,10 +43,8 @@ async function executeTaskUsingBrowsingAgent({ action, page, actions, llm, optio
|
|
|
43
43
|
messages,
|
|
44
44
|
tools,
|
|
45
45
|
trace: browsingAgentSpan,
|
|
46
|
-
model: options.model || constants_1.DEFAULT_MODEL,
|
|
47
46
|
modelParameters: {
|
|
48
47
|
...constants_1.DEFAULT_MODEL_PARAMETERS,
|
|
49
|
-
...options.modelParameters,
|
|
50
48
|
tool_choice: "required",
|
|
51
49
|
},
|
|
52
50
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills-retriever.d.ts","sourceRoot":"","sources":["../../../src/agent/codegen/skills-retriever.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,KAAK,EACV,QAAQ,EACR,oBAAoB,EACrB,MAAM,4BAA4B,CAAC;AAmBpC,eAAO,MAAM,cAAc;cAMf,QAAQ;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"skills-retriever.d.ts","sourceRoot":"","sources":["../../../src/agent/codegen/skills-retriever.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,KAAK,EACV,QAAQ,EACR,oBAAoB,EACrB,MAAM,4BAA4B,CAAC;AAmBpC,eAAO,MAAM,cAAc;cAMf,QAAQ;;;;;;;;;;IAwDnB,CAAC;AAEF,wBAAsB,oBAAoB,CAAC,EACzC,QAAQ,EACR,OAAO,EACP,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;;;;;;KA6BA"}
|
|
@@ -10,7 +10,8 @@ const logger_1 = require("../../bin/logger");
|
|
|
10
10
|
const context_1 = require("../../bin/utils/context");
|
|
11
11
|
const fs_2 = require("../../bin/utils/fs");
|
|
12
12
|
const constants_1 = require("../../constants");
|
|
13
|
-
const promptTemplate_0 = "{{#section \"system\"}}\nYou are
|
|
13
|
+
const promptTemplate_0 = "{{#section \"system\"}}\nYou are provided with usage examples of page object models of a Playwright test\nrepository and you are given a task to update the usage example of the page object\nmodels with the usage of them in tests. \n\nYou need to ensure all the pre-requisites of calling the method is also mentioned\nin the usage example. Use the tests code for same\n\n{{/section}}\n\n{{#section \"user\"}}\nUsage examples of page object models:\n\n{{response}}\n\nTests files:\n\n{{codePrompt}}\n\n\nBefore responding: \n- ensure responding in the same format as provided to you in the usage example of page object models.\n- respond only with the methods and not any test block\n- respond with the same format provided to you in task. <subtask></subtask>, <reason></reason>, <file_import_path></file_import_path>, <usage_example></usage_example> and\n<method_name></method_name>\n- do not respond with test blocks or page or fixture extraction as its already available at the time of execution\n- do not respond with backticks or markdown at all \n- do not respond with import statements and assume the imports are already available at the time of execution\n{{/section}}\n";
|
|
14
|
+
const promptTemplate_1 = "{{#section \"system\"}}\nYou are a software test engineer who is given a goal to pick re-usable page object model methods for a given UI\nautomation test.\n\nYou will be provided with a test scenario as task and also the page object model methods available in the automation\ntest repository. The page object models acts as skills to execute a particular sub task of a given task.\n\nYou need to break down the task into sub tasks and identify which sub_task can be solved with the help of page object\nmodel methods. Once identified, you need to return with an usage API example for same. You need to pick methods only\nfrom the provided page object models.\n\nHere is the list of current page object models:\n\n{{pageFiles}}\n\n{{/section}}\n\n{{#section \"user\"}}\nFollowing is the test scenario for which you need to figure out the skills:\n\n**Task:**\n{{scenario}}\n\nBefore responding follow the instructions:\n- You need to break down the task into subtask and respond with the code of sub tasks for which there are methods\nexposed from page object models\n- Only use methods that are explicitly defined and exported in the provided page object models. Do not create, infer, or\nassume any methods or code that are not exported from the page object model files.\n- Do not respond with any methods or code that are not available in the list of page object models.\n- Ensure there are no type issues in the code generated.\n- Do not respond with markdown syntax or backticks.\n- Respond only with the code\n- Read steps one by one and generate the test code\n- Do not write any extra code than instructed in the steps\n- You need to respond with `<subtask></subtask>`, `<reason></reason>`, `<file_import_path></file_import_path>`, `\n<usage_example></usage_example>` and `<method_name></method_name>`\n- You should respond with methods exported from the page object models\n- Do not respond with any import statements.\n- Do not respond with sub_task for which there is no explicit method found\n- Always pick the page object model method matching the task provided. If there is no matching method, then ignore it.\nDo not attempt to generate or use any non existent methods for such instances.\n- Respond with the usage_example so that it can be directly copy pasted inside the test\n- Do not set the parameters for the method. Keep it as is with the interface parameters\n{{/section}}";
|
|
14
15
|
const utils_1 = require("./utils");
|
|
15
16
|
const fetchPomSkills = async ({ testCase, pomFiles, options, trace, }) => {
|
|
16
17
|
const fetchSkillsUsingPOMFilesSpan = trace?.span({
|
|
@@ -23,7 +24,7 @@ const fetchPomSkills = async ({ testCase, pomFiles, options, trace, }) => {
|
|
|
23
24
|
const promptSpan = fetchSkillsUsingPOMFilesSpan?.span({
|
|
24
25
|
name: "fetch-pom-skills-prompt",
|
|
25
26
|
});
|
|
26
|
-
const prompt = (0, llm_1.compilePrompt)(
|
|
27
|
+
const prompt = (0, llm_1.compilePrompt)(promptTemplate_1, {
|
|
27
28
|
pageFiles: pomFiles,
|
|
28
29
|
scenarioName: testCase.name,
|
|
29
30
|
scenario: testCase.steps.join("\n"),
|
|
@@ -45,39 +46,11 @@ const fetchPomSkills = async ({ testCase, pomFiles, options, trace, }) => {
|
|
|
45
46
|
});
|
|
46
47
|
let response = firstShotMessage?.content || "";
|
|
47
48
|
const { codePrompt } = await (0, context_1.contextForGeneration)();
|
|
48
|
-
const usageExampleUpdatePrompt = [
|
|
49
|
-
{
|
|
50
|
-
role: "system",
|
|
51
|
-
content: `
|
|
52
|
-
You are provided with usage examples of page object models of a Playwright test repository and you are given a task to update the usage example of the page object models with the usage of them in tests.
|
|
53
|
-
|
|
54
|
-
You need to ensure all the pre-requisites of calling the method is also mentioned in the usage example. Use the tests code for same
|
|
55
|
-
`,
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
role: "user",
|
|
59
|
-
content: `
|
|
60
|
-
Usage examples of page object models:
|
|
61
|
-
|
|
62
|
-
${response}
|
|
63
|
-
|
|
64
|
-
Tests files:
|
|
65
|
-
|
|
66
|
-
${codePrompt}
|
|
67
|
-
|
|
68
|
-
Before responding:
|
|
69
|
-
- ensure responding in the same format as provided to you in the usage example of page object models.
|
|
70
|
-
- respond only with the methods and not any test block
|
|
71
|
-
- respond with the same format provided to you in task. <subtask></subtask>,<reason></reason> ,<file_import_path></file_import_path>,<usage_example></usage_example> and
|
|
72
|
-
<method_name></method_name>
|
|
73
|
-
- do not respond with test blocks or page or fixture extraction as its already available at the time of execution
|
|
74
|
-
- do not respond with backticks or markdown at all
|
|
75
|
-
- do not respond with import statements and assume the imports are already available at the time of execution
|
|
76
|
-
`,
|
|
77
|
-
},
|
|
78
|
-
];
|
|
79
49
|
const updatedUsageExampleMessage = await llm.createChatCompletion({
|
|
80
|
-
messages:
|
|
50
|
+
messages: (0, llm_1.compilePrompt)(promptTemplate_0, {
|
|
51
|
+
response,
|
|
52
|
+
codePrompt,
|
|
53
|
+
}),
|
|
81
54
|
traceName: "fetch-pom-skills-usage-eg-update-llm",
|
|
82
55
|
modelParameters: {
|
|
83
56
|
...constants_1.DEFAULT_MODEL_PARAMETERS,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/agent/codegen/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,KAAK,EACV,QAAQ,EACR,oBAAoB,EACrB,MAAM,4BAA4B,CAAC;AAIpC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAMhD,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAExD,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE/E;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE,CAiB9D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,GACZ,oBAAoB,EAAE,CAgBxB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG;IACvD,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,EAAE,CA8BF;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB,EAAE,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/agent/codegen/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,KAAK,EACV,QAAQ,EACR,oBAAoB,EACrB,MAAM,4BAA4B,CAAC;AAIpC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAMhD,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAExD,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE/E;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE,CAiB9D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,GACZ,oBAAoB,EAAE,CAgBxB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG;IACvD,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,EAAE,CA8BF;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB,EAAE,CAqCF;AAED,wBAAsB,0BAA0B,CAAC,EAC/C,aAAoB,EACpB,KAAK,EACL,QAAQ,EACR,SAAS,EACT,MAAM,EACN,cAAc,EACd,SAAS,EACT,iBAAiB,GAClB,EAAE;IACD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,CAAC;IAClC,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,iBA0BA;AAED,wBAAsB,+BAA+B,CAAC,EACpD,KAAK,EACL,WAAW,EACX,MAAM,GACP,EAAE;IACD,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CA6ChC;AAED,wBAAsB,mCAAmC,CAAC,EACxD,MAAM,EACN,UAAU,GACX,EAAE;IACD,UAAU,EAAE;QACV,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;QAC7B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;QAC5B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;QAC5B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;KAC5B,CAAC;IACF,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB,GAAG,OAAO,CAAC;IACV,MAAM,EAAE,kBAAkB,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC,CAuCD;AAED,wBAAsB,6BAA6B,CAAC,EAClD,KAAK,EACL,WAAW,EACX,sBAAsB,GACvB,EAAE;IACD,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,WAAW,EAAE,oBAAoB,EAAE,CAAC;IACpC,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;CACjD,iBAoDA;AAED,wBAAsB,oBAAoB,CAAC,EACzC,MAAM,EACN,UAAU,GACX,EAAE;IACD,UAAU,EAAE;QACV,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;QAC7B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;QAC5B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;QAC5B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;KAC5B,CAAC;IACF,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB,GAAG,OAAO,CAAC;IACV,MAAM,EAAE;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC,CA6BD;AAED,wBAAsB,gBAAgB,CAAC,EACrC,KAAK,EACL,QAAQ,EACR,WAAW,EACX,MAAM,GACP,EAAE;IACD,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC;IACnB,WAAW,EAAE;QACX,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;QAC7B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;QAC5B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;QAC5B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;KAC5B,EAAE,CAAC;IACJ,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAkIxE"}
|
|
@@ -101,16 +101,27 @@ function extractAppendTestUpdates(input) {
|
|
|
101
101
|
exports.extractAppendTestUpdates = extractAppendTestUpdates;
|
|
102
102
|
function extractTestStepsSuggestions(input) {
|
|
103
103
|
const result = [];
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
104
|
+
// Extract all sections with their subtask tags first
|
|
105
|
+
const subtaskRegex = /<subtask>([\s\S]*?)<\/subtask>([\s\S]*?)(?=<subtask>|$)/g;
|
|
106
|
+
let subtaskMatch;
|
|
107
|
+
while ((subtaskMatch = subtaskRegex.exec(input)) !== null) {
|
|
108
|
+
const [, testStepText = "", content = ""] = subtaskMatch;
|
|
109
|
+
// Extract individual tag content regardless of order
|
|
110
|
+
const reasonMatch = /<reason>([\s\S]*?)<\/reason>/i.exec(content);
|
|
111
|
+
const filePathMatch = /<file_import_path>([\s\S]*?)<\/file_import_path>/i.exec(content);
|
|
112
|
+
const usageExampleMatch = /<usage_example>([\s\S]*?)<\/usage_example>/i.exec(content);
|
|
113
|
+
const methodNameMatch = /<method_name>([\s\S]*?)<\/method_name>/i.exec(content);
|
|
114
|
+
// Extract values or use empty strings if not found
|
|
115
|
+
const reasonText = reasonMatch?.[1] || "";
|
|
116
|
+
const filePathText = filePathMatch?.[1] || "";
|
|
117
|
+
const usageExampleText = usageExampleMatch?.[1] || "";
|
|
118
|
+
const methodNameText = methodNameMatch?.[1] || "";
|
|
108
119
|
result.push({
|
|
109
|
-
testStep:
|
|
110
|
-
filePath:
|
|
111
|
-
usageExample:
|
|
112
|
-
reason:
|
|
113
|
-
methodName:
|
|
120
|
+
testStep: testStepText.trim(),
|
|
121
|
+
filePath: filePathText.trim(),
|
|
122
|
+
usageExample: usageExampleText.trim(),
|
|
123
|
+
reason: reasonText.trim(),
|
|
124
|
+
methodName: methodNameText.trim(),
|
|
114
125
|
});
|
|
115
126
|
}
|
|
116
127
|
return result.filter((r) => !!r.filePath && !!r.usageExample);
|
|
@@ -5,7 +5,9 @@ export declare enum ActionType {
|
|
|
5
5
|
PRESS_ACTION = "keyboard_press_on_element",
|
|
6
6
|
ASSERT_TEXT = "assert_text",
|
|
7
7
|
HOVER = "hover_element",
|
|
8
|
-
SCROLL = "scroll"
|
|
8
|
+
SCROLL = "scroll",
|
|
9
|
+
OBSERVATION = "observation",
|
|
10
|
+
UNKNOWN = "unknown"
|
|
9
11
|
}
|
|
10
12
|
export declare function isValidActionType(value: string): value is ActionType;
|
|
11
13
|
export declare function getActionToolCalls(): {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-tool-calls.d.ts","sourceRoot":"","sources":["../../../src/agent/master/action-tool-calls.ts"],"names":[],"mappings":"AAAA,oBAAY,UAAU;IACpB,IAAI,SAAS;IACb,SAAS,cAAc;IACvB,KAAK,UAAU;IACf,YAAY,8BAA8B;IAC1C,WAAW,gBAAgB;IAC3B,KAAK,kBAAkB;IACvB,MAAM,WAAW;
|
|
1
|
+
{"version":3,"file":"action-tool-calls.d.ts","sourceRoot":"","sources":["../../../src/agent/master/action-tool-calls.ts"],"names":[],"mappings":"AAAA,oBAAY,UAAU;IACpB,IAAI,SAAS;IACb,SAAS,cAAc;IACvB,KAAK,UAAU;IACf,YAAY,8BAA8B;IAC1C,WAAW,gBAAgB;IAC3B,KAAK,kBAAkB;IACvB,MAAM,WAAW;IACjB,WAAW,gBAAgB;IAC3B,OAAO,YAAY;CACpB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,UAAU,CAEpE;AAqDD,wBAAgB,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA8CjC"}
|
|
@@ -10,53 +10,50 @@ var ActionType;
|
|
|
10
10
|
ActionType["ASSERT_TEXT"] = "assert_text";
|
|
11
11
|
ActionType["HOVER"] = "hover_element";
|
|
12
12
|
ActionType["SCROLL"] = "scroll";
|
|
13
|
+
ActionType["OBSERVATION"] = "observation";
|
|
14
|
+
ActionType["UNKNOWN"] = "unknown";
|
|
13
15
|
})(ActionType || (exports.ActionType = ActionType = {}));
|
|
14
16
|
function isValidActionType(value) {
|
|
15
|
-
return
|
|
16
|
-
value === "unknown");
|
|
17
|
+
return Object.values(ActionType).includes(value);
|
|
17
18
|
}
|
|
18
19
|
exports.isValidActionType = isValidActionType;
|
|
19
20
|
const createActionCall = (name, description, additionalProperties = {}) => ({
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
action: {
|
|
35
|
-
type: "string",
|
|
36
|
-
description: `explain the next action in natural language.
|
|
21
|
+
type: "function",
|
|
22
|
+
function: {
|
|
23
|
+
name,
|
|
24
|
+
description,
|
|
25
|
+
parameters: {
|
|
26
|
+
type: "object",
|
|
27
|
+
properties: {
|
|
28
|
+
reason: {
|
|
29
|
+
type: "string",
|
|
30
|
+
description: "explain how this action will help to complete the task. the reason should align with the task provided",
|
|
31
|
+
},
|
|
32
|
+
action: {
|
|
33
|
+
type: "string",
|
|
34
|
+
description: `explain the next action in natural language.
|
|
37
35
|
The next action should be as atomic as possible, precise and should contain enough details about the action to be performed.
|
|
38
|
-
E.g. each click, key press, input, assert should be a separate action.
|
|
36
|
+
E.g. each click, key press, input, assert, observation should be a separate action.
|
|
39
37
|
Each action should take the task to completion, if not the action is invalid.
|
|
40
38
|
If the element is not visible then action should be scroll.`,
|
|
41
|
-
},
|
|
42
|
-
element_description: {
|
|
43
|
-
type: "string",
|
|
44
|
-
description: "The description of the element on which action needs to be taken, including its position, appearance, etc.",
|
|
45
|
-
},
|
|
46
|
-
is_element_visible: {
|
|
47
|
-
type: "boolean",
|
|
48
|
-
description: "A boolean to indicate whether the concerned element is visible in the screenshot.",
|
|
49
|
-
},
|
|
50
|
-
...additionalProperties,
|
|
51
39
|
},
|
|
52
|
-
|
|
53
|
-
"
|
|
54
|
-
"action",
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
40
|
+
element_description: {
|
|
41
|
+
type: "string",
|
|
42
|
+
description: "The description of the element on which action needs to be taken, including its position, appearance, etc.",
|
|
43
|
+
},
|
|
44
|
+
is_element_visible: {
|
|
45
|
+
type: "boolean",
|
|
46
|
+
description: "A boolean to indicate whether the concerned element is visible in the screenshot.",
|
|
47
|
+
},
|
|
48
|
+
...additionalProperties,
|
|
59
49
|
},
|
|
50
|
+
required: [
|
|
51
|
+
"reason",
|
|
52
|
+
"action",
|
|
53
|
+
"element_description",
|
|
54
|
+
"is_element_visible",
|
|
55
|
+
...Object.keys(additionalProperties),
|
|
56
|
+
],
|
|
60
57
|
},
|
|
61
58
|
},
|
|
62
59
|
});
|
|
@@ -79,6 +76,12 @@ function getActionToolCalls() {
|
|
|
79
76
|
description: "Element to look for after scrolling to complete the task.",
|
|
80
77
|
},
|
|
81
78
|
}),
|
|
82
|
-
|
|
79
|
+
createActionCall(ActionType.OBSERVATION, "Observation based on the task provided. If the task doesn't explicitly mention any browser interaction, and instead, asks questions to be answered — use this tool call", {
|
|
80
|
+
observation: {
|
|
81
|
+
type: "string",
|
|
82
|
+
description: "Observation based on the task provided.",
|
|
83
|
+
},
|
|
84
|
+
}),
|
|
85
|
+
];
|
|
83
86
|
}
|
|
84
87
|
exports.getActionToolCalls = getActionToolCalls;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type ServerFixture = {
|
|
2
|
+
port: number;
|
|
3
|
+
baseURL: string;
|
|
4
|
+
};
|
|
5
|
+
export declare const expect: import("@playwright/test").Expect<{}>;
|
|
6
|
+
export declare const test: import("@playwright/test").TestType<import("@playwright/test").PlaywrightTestArgs & import("@playwright/test").PlaywrightTestOptions, import("@playwright/test").PlaywrightWorkerArgs & import("@playwright/test").PlaywrightWorkerOptions & {
|
|
7
|
+
server: ServerFixture;
|
|
8
|
+
}>;
|
|
9
|
+
//# sourceMappingURL=fixtures.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../../../src/agent/master/browser-tests/fixtures.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,MAAM,uCAAc,CAAC;AAClC,eAAO,MAAM,IAAI;YAA6B,aAAa;EAsBzD,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
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
|
+
exports.test = exports.expect = void 0;
|
|
7
|
+
const test_1 = require("@playwright/test");
|
|
8
|
+
const http_server_1 = __importDefault(require("http-server"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
exports.expect = test_1.test.expect;
|
|
11
|
+
exports.test = test_1.test.extend({
|
|
12
|
+
server: [
|
|
13
|
+
// eslint-disable-next-line no-empty-pattern
|
|
14
|
+
async ({}, use, workerInfo) => {
|
|
15
|
+
const port = 2345 + workerInfo.workerIndex;
|
|
16
|
+
const server = http_server_1.default.createServer({
|
|
17
|
+
root: path_1.default.join(process.cwd(), "test-data"),
|
|
18
|
+
});
|
|
19
|
+
await new Promise((resolve) => {
|
|
20
|
+
server.listen(port, () => {
|
|
21
|
+
console.log(`Server running at http://localhost:${port}`);
|
|
22
|
+
resolve();
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
await use({
|
|
26
|
+
port,
|
|
27
|
+
baseURL: `http://localhost:${port}`,
|
|
28
|
+
});
|
|
29
|
+
server.close();
|
|
30
|
+
},
|
|
31
|
+
{ scope: "worker" },
|
|
32
|
+
],
|
|
33
|
+
});
|
|
@@ -3,37 +3,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const test_1 = require("@playwright/test");
|
|
7
6
|
const fs_1 = __importDefault(require("fs"));
|
|
8
|
-
const http_server_1 = __importDefault(require("http-server"));
|
|
9
7
|
const path_1 = __importDefault(require("path"));
|
|
10
8
|
const utils_1 = require("../../browsing/utils");
|
|
11
9
|
const element_annotation_1 = require("../element-annotation");
|
|
12
10
|
const run_1 = require("../run");
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
// eslint-disable-next-line no-empty-pattern
|
|
16
|
-
async ({}, use, workerInfo) => {
|
|
17
|
-
const port = 2345 + workerInfo.workerIndex;
|
|
18
|
-
const server = http_server_1.default.createServer({
|
|
19
|
-
root: path_1.default.join(process.cwd(), "test-data"),
|
|
20
|
-
});
|
|
21
|
-
await new Promise((resolve) => {
|
|
22
|
-
server.listen(port, () => {
|
|
23
|
-
console.log(`Server running at http://localhost:${port}`);
|
|
24
|
-
resolve();
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
await use({
|
|
28
|
-
port,
|
|
29
|
-
baseURL: `http://localhost:${port}`,
|
|
30
|
-
});
|
|
31
|
-
server.close();
|
|
32
|
-
},
|
|
33
|
-
{ scope: "worker" },
|
|
34
|
-
],
|
|
35
|
-
});
|
|
36
|
-
test("able to scroll and interact with elements", async ({ page, server }) => {
|
|
11
|
+
const fixtures_1 = require("./fixtures");
|
|
12
|
+
(0, fixtures_1.test)("able to scroll and interact with elements", async ({ page, server }) => {
|
|
37
13
|
await page.goto(`${server.baseURL}/blog-page.html`);
|
|
38
14
|
const response = await (0, run_1.createTestUsingMasterAgent)({
|
|
39
15
|
task: `fill test@test.com into the email field and click the submit`,
|
|
@@ -41,11 +17,11 @@ test("able to scroll and interact with elements", async ({ page, server }) => {
|
|
|
41
17
|
options: {},
|
|
42
18
|
});
|
|
43
19
|
console.log(response);
|
|
44
|
-
(0,
|
|
45
|
-
(0,
|
|
46
|
-
(0,
|
|
20
|
+
(0, fixtures_1.expect)(response.importPaths.length).toBe(0);
|
|
21
|
+
(0, fixtures_1.expect)(response.code).toContain("await page.getByPlaceholder('Enter your email').fill(\"test@test.com\")");
|
|
22
|
+
(0, fixtures_1.expect)(response.code).toContain("await page.getByRole('button', { name: 'Subscribe' }).click()");
|
|
47
23
|
});
|
|
48
|
-
test("scroll when element does not exist", async ({ page, server }) => {
|
|
24
|
+
(0, fixtures_1.test)("scroll when element does not exist", async ({ page, server }) => {
|
|
49
25
|
await page.goto(`${server.baseURL}/blog-page.html`);
|
|
50
26
|
const response = await (0, run_1.createTestUsingMasterAgent)({
|
|
51
27
|
task: `click search button`,
|
|
@@ -53,33 +29,50 @@ test("scroll when element does not exist", async ({ page, server }) => {
|
|
|
53
29
|
options: {},
|
|
54
30
|
});
|
|
55
31
|
console.log(response);
|
|
56
|
-
(0,
|
|
57
|
-
(0,
|
|
32
|
+
(0, fixtures_1.expect)(response.importPaths.length).toBe(0);
|
|
33
|
+
(0, fixtures_1.expect)(response.code.length).toBe(0);
|
|
34
|
+
});
|
|
35
|
+
(0, fixtures_1.test)("scroll and click inside div elements", async ({ page, server }) => {
|
|
36
|
+
await page.goto(`${server.baseURL}/dropdown-scrolls.html`);
|
|
37
|
+
const response = await (0, run_1.createTestUsingMasterAgent)({
|
|
38
|
+
task: `click on x-3 inside bmw dropdown, and then,
|
|
39
|
+
click on maverick inside ford dropdown`,
|
|
40
|
+
page,
|
|
41
|
+
options: {},
|
|
42
|
+
});
|
|
43
|
+
console.log(response);
|
|
44
|
+
(0, fixtures_1.expect)(response.importPaths.length).toBe(0);
|
|
45
|
+
(0, fixtures_1.expect)(response.code.length).toBeGreaterThan(0);
|
|
46
|
+
const lines = response.code.split("\n");
|
|
47
|
+
(0, fixtures_1.expect)(lines.find((l) => l.match(/^await page.+BMW.+.click/))).toBeTruthy();
|
|
48
|
+
(0, fixtures_1.expect)(lines.find((l) => l.match(/^await page.+X3.+.click/))).toBeTruthy();
|
|
49
|
+
(0, fixtures_1.expect)(lines.find((l) => l.match(/^await page.+Ford.+.click/))).toBeTruthy();
|
|
50
|
+
(0, fixtures_1.expect)(lines.find((l) => l.match(/^await page.+Maverick.+.click/))).toBeTruthy();
|
|
58
51
|
});
|
|
59
|
-
test("agent can click icons accurately", async ({ page, server }) => {
|
|
52
|
+
(0, fixtures_1.test)("agent can click icons accurately", async ({ page, server }) => {
|
|
60
53
|
await page.goto(`${server.baseURL}/icons-navbar.html`);
|
|
61
|
-
await (0,
|
|
54
|
+
await (0, fixtures_1.expect)(page.getByText("select an icon")).toBeVisible();
|
|
62
55
|
const response = await (0, run_1.createTestUsingMasterAgent)({
|
|
63
56
|
task: `click on the gear icon`,
|
|
64
57
|
page,
|
|
65
58
|
options: {},
|
|
66
59
|
});
|
|
67
60
|
// Validate code generated and action performed
|
|
68
|
-
await (0,
|
|
61
|
+
await (0, fixtures_1.expect)(page.getByText("you clicked Gear")).toBeVisible();
|
|
69
62
|
console.log(response);
|
|
70
|
-
(0,
|
|
71
|
-
(0,
|
|
72
|
-
(0,
|
|
63
|
+
(0, fixtures_1.expect)(response.importPaths.length).toBe(0);
|
|
64
|
+
(0, fixtures_1.expect)(response.code).toContain("page.locator");
|
|
65
|
+
(0, fixtures_1.expect)(response.code).toContain("click()");
|
|
73
66
|
// Validate icons registry
|
|
74
67
|
const iconsRegistryFile = path_1.default.join(process.cwd(), ".empiricalrun", "icons.json");
|
|
75
68
|
const icons = JSON.parse(fs_1.default.readFileSync(iconsRegistryFile, "utf-8"));
|
|
76
|
-
(0,
|
|
69
|
+
(0, fixtures_1.expect)(icons.length).toBeGreaterThan(0);
|
|
77
70
|
// Commenting out this check since with parallel test executions,
|
|
78
71
|
// we can have icons from other tests in the same file
|
|
79
72
|
// expect(icons.length).toBe(4); // 1 for each unique icon
|
|
80
73
|
fs_1.default.unlinkSync(iconsRegistryFile);
|
|
81
74
|
});
|
|
82
|
-
test("annotate and enrich annotations correctly", async ({ page, server }) => {
|
|
75
|
+
(0, fixtures_1.test)("annotate and enrich annotations correctly", async ({ page, server }) => {
|
|
83
76
|
await (0, utils_1.injectPwLocatorGenerator)(page);
|
|
84
77
|
await page.goto(`${server.baseURL}/iframe-elements.html`);
|
|
85
78
|
const { annotationKeys: keys } = await (0, element_annotation_1.getAnnotationKeys)({
|
|
@@ -87,23 +80,22 @@ test("annotate and enrich annotations correctly", async ({ page, server }) => {
|
|
|
87
80
|
preference: {
|
|
88
81
|
actionType: "all",
|
|
89
82
|
},
|
|
90
|
-
options: {},
|
|
91
83
|
});
|
|
92
84
|
console.log(keys);
|
|
93
|
-
(0,
|
|
85
|
+
(0, fixtures_1.expect)(keys.length).toBe(6);
|
|
94
86
|
// 2 icons: 1 in main frame, 1 in iframe
|
|
95
|
-
(0,
|
|
87
|
+
(0, fixtures_1.expect)(keys.filter((k) => k.text.includes("icon") && k.text.includes("close"))
|
|
96
88
|
.length).toBe(2);
|
|
97
89
|
// 2 text inputs: 1 in main frame, 1 in iframe
|
|
98
|
-
(0,
|
|
90
|
+
(0, fixtures_1.expect)(keys.filter((k) => k.text.includes("Enter your name")).length).toBe(2);
|
|
99
91
|
// 2 clickable divs: 1 in main frame, 1 in iframe
|
|
100
|
-
(0,
|
|
92
|
+
(0, fixtures_1.expect)(keys.filter((k) => k.text.includes("Lorem Ipsum")).length).toBe(2);
|
|
101
93
|
});
|
|
102
|
-
test("fill action with multiple pages", async ({ context }) => {
|
|
94
|
+
(0, fixtures_1.test)("fill action with multiple pages", async ({ context }) => {
|
|
103
95
|
const page1 = await context.newPage();
|
|
104
96
|
const page2 = await context.newPage();
|
|
105
97
|
const response = await (0, run_1.createTestUsingMasterAgent)({
|
|
106
|
-
task: `goto empirical.run on page1 and goto
|
|
98
|
+
task: `goto empirical.run on page1 and goto github.com/search in page2. Enter text empirical on page2 and click on search.`,
|
|
107
99
|
page: page2,
|
|
108
100
|
options: {},
|
|
109
101
|
scopeVars: {
|
|
@@ -112,11 +104,10 @@ test("fill action with multiple pages", async ({ context }) => {
|
|
|
112
104
|
page2,
|
|
113
105
|
},
|
|
114
106
|
});
|
|
115
|
-
(0,
|
|
107
|
+
(0, fixtures_1.expect)(response.code).toBeTruthy();
|
|
116
108
|
console.log(response.code);
|
|
117
109
|
const lines = response.code.split("\n");
|
|
118
|
-
(0,
|
|
119
|
-
(0,
|
|
120
|
-
(0,
|
|
121
|
-
(0, test_1.expect)(lines.find((l) => l.match(/^await page2(.+)click/))).toBeTruthy();
|
|
110
|
+
(0, fixtures_1.expect)(lines.find((l) => l.match(/^await page1\.goto(.+)empirical\.run/))).toBeTruthy();
|
|
111
|
+
(0, fixtures_1.expect)(lines.find((l) => l.match(/^await page2\.goto(.+)github\.com\/search/))).toBeTruthy();
|
|
112
|
+
(0, fixtures_1.expect)(lines.find((l) => l.match(/^await page2(.+)fill(.+)empirical/))).toBeTruthy();
|
|
122
113
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.spec.d.ts","sourceRoot":"","sources":["../../../../src/agent/master/browser-tests/skills.spec.ts"],"names":[],"mappings":""}
|