@midscene/web 0.11.1 → 0.11.3
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/es/appium.js +85 -39
- package/dist/es/bridge-mode-browser.js +58 -19
- package/dist/es/bridge-mode.js +62 -43
- package/dist/es/chrome-extension.js +105 -51
- package/dist/es/index.js +292 -218
- package/dist/es/midscene-playground.js +57 -38
- package/dist/es/playground.js +57 -38
- package/dist/es/playwright-report.js +4 -0
- package/dist/es/playwright.js +252 -203
- package/dist/es/puppeteer.js +86 -60
- package/dist/es/ui-utils.js +43 -0
- package/dist/lib/appium.js +85 -39
- package/dist/lib/bridge-mode-browser.js +58 -19
- package/dist/lib/bridge-mode.js +62 -43
- package/dist/lib/chrome-extension.js +105 -51
- package/dist/lib/index.js +292 -218
- package/dist/lib/midscene-playground.js +57 -38
- package/dist/lib/playground.js +57 -38
- package/dist/lib/playwright-report.js +4 -0
- package/dist/lib/playwright.js +252 -203
- package/dist/lib/puppeteer.js +86 -60
- package/dist/lib/ui-utils.js +43 -0
- package/dist/types/{tasks-d5a01262.d.ts → agent-ae110e80.d.ts} +43 -43
- package/dist/types/appium.d.ts +3 -3
- package/dist/types/bridge-mode-browser.d.ts +3 -3
- package/dist/types/bridge-mode.d.ts +4 -4
- package/dist/types/{browser-7d5614fb.d.ts → browser-9d620553.d.ts} +4 -4
- package/dist/types/chrome-extension.d.ts +4 -4
- package/dist/types/index.d.ts +8 -8
- package/dist/types/{page-77af8d5f.d.ts → page-97720803.d.ts} +34 -8
- package/dist/types/playground.d.ts +4 -4
- package/dist/types/playwright.d.ts +13 -7
- package/dist/types/puppeteer.d.ts +3 -3
- package/dist/types/ui-utils.d.ts +6 -1
- package/dist/types/{utils-1a3bc661.d.ts → utils-93b3f5f3.d.ts} +1 -1
- package/dist/types/utils.d.ts +2 -2
- package/dist/types/yaml.d.ts +4 -4
- package/package.json +6 -6
package/dist/lib/playwright.js
CHANGED
|
@@ -328,16 +328,13 @@ var require_dayjs_min = __commonJS({
|
|
|
328
328
|
// src/playwright/index.ts
|
|
329
329
|
var playwright_exports = {};
|
|
330
330
|
__export(playwright_exports, {
|
|
331
|
-
PlaywrightAgent: () =>
|
|
331
|
+
PlaywrightAgent: () => PlaywrightAgent,
|
|
332
332
|
PlaywrightAiFixture: () => PlaywrightAiFixture,
|
|
333
333
|
PlaywrightWebPage: () => WebPage,
|
|
334
334
|
overrideAIConfig: () => import_env4.overrideAIConfig
|
|
335
335
|
});
|
|
336
336
|
module.exports = __toCommonJS(playwright_exports);
|
|
337
337
|
|
|
338
|
-
// src/playwright/ai-fixture.ts
|
|
339
|
-
var import_node_crypto = require("crypto");
|
|
340
|
-
|
|
341
338
|
// src/common/agent.ts
|
|
342
339
|
var import_core2 = require("@midscene/core");
|
|
343
340
|
var import_constants2 = require("@midscene/shared/constants");
|
|
@@ -3367,7 +3364,9 @@ var TaskCache = class {
|
|
|
3367
3364
|
if (!this.midscenePkgInfo) {
|
|
3368
3365
|
return void 0;
|
|
3369
3366
|
}
|
|
3370
|
-
|
|
3367
|
+
const jsonDataPkgVersion = jsonData.pkgVersion.split(".");
|
|
3368
|
+
const midscenePkgInfoPkgVersion = this.midscenePkgInfo.version.split(".");
|
|
3369
|
+
if (jsonDataPkgVersion[0] !== midscenePkgInfoPkgVersion[0] || jsonDataPkgVersion[1] !== midscenePkgInfoPkgVersion[1]) {
|
|
3371
3370
|
return void 0;
|
|
3372
3371
|
}
|
|
3373
3372
|
return jsonData;
|
|
@@ -3401,6 +3400,56 @@ var TaskCache = class {
|
|
|
3401
3400
|
}
|
|
3402
3401
|
};
|
|
3403
3402
|
|
|
3403
|
+
// src/common/ui-utils.ts
|
|
3404
|
+
function typeStr(task) {
|
|
3405
|
+
return task.subType ? `${task.type} / ${task.subType || ""}` : task.type;
|
|
3406
|
+
}
|
|
3407
|
+
function getKeyCommands(value) {
|
|
3408
|
+
const keys = Array.isArray(value) ? value : [value];
|
|
3409
|
+
return keys.reduce((acc, k) => {
|
|
3410
|
+
const includeMeta = keys.includes("Meta") || keys.includes("Control");
|
|
3411
|
+
if (includeMeta && (k === "a" || k === "A")) {
|
|
3412
|
+
return acc.concat([{ key: k, command: "SelectAll" }]);
|
|
3413
|
+
}
|
|
3414
|
+
if (includeMeta && (k === "c" || k === "C")) {
|
|
3415
|
+
return acc.concat([{ key: k, command: "Copy" }]);
|
|
3416
|
+
}
|
|
3417
|
+
if (includeMeta && (k === "v" || k === "V")) {
|
|
3418
|
+
return acc.concat([{ key: k, command: "Paste" }]);
|
|
3419
|
+
}
|
|
3420
|
+
return acc.concat([{ key: k }]);
|
|
3421
|
+
}, []);
|
|
3422
|
+
}
|
|
3423
|
+
function paramStr(task) {
|
|
3424
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
3425
|
+
let value;
|
|
3426
|
+
if (task.type === "Planning") {
|
|
3427
|
+
value = (_a = task == null ? void 0 : task.param) == null ? void 0 : _a.userPrompt;
|
|
3428
|
+
}
|
|
3429
|
+
if (task.type === "Insight") {
|
|
3430
|
+
value = ((_b = task == null ? void 0 : task.param) == null ? void 0 : _b.prompt) || ((_c = task == null ? void 0 : task.param) == null ? void 0 : _c.id) || ((_d = task == null ? void 0 : task.param) == null ? void 0 : _d.dataDemand) || ((_e = task == null ? void 0 : task.param) == null ? void 0 : _e.assertion);
|
|
3431
|
+
}
|
|
3432
|
+
if (task.type === "Action") {
|
|
3433
|
+
const sleepMs = (_f = task == null ? void 0 : task.param) == null ? void 0 : _f.timeMs;
|
|
3434
|
+
const scrollType = (_g = task == null ? void 0 : task.param) == null ? void 0 : _g.scrollType;
|
|
3435
|
+
if (sleepMs) {
|
|
3436
|
+
value = `${sleepMs}ms`;
|
|
3437
|
+
} else if (scrollType) {
|
|
3438
|
+
const scrollDirection = (_h = task == null ? void 0 : task.param) == null ? void 0 : _h.direction;
|
|
3439
|
+
const scrollDistance = (_i = task == null ? void 0 : task.param) == null ? void 0 : _i.distance;
|
|
3440
|
+
value = `${scrollDirection || "down"}, ${scrollType || "once"}, ${scrollDistance || "distance-not-set"}`;
|
|
3441
|
+
} else {
|
|
3442
|
+
value = ((_j = task == null ? void 0 : task.param) == null ? void 0 : _j.value) || ((_k = task == null ? void 0 : task.param) == null ? void 0 : _k.scrollType);
|
|
3443
|
+
}
|
|
3444
|
+
if (!value) {
|
|
3445
|
+
value = task.thought;
|
|
3446
|
+
}
|
|
3447
|
+
}
|
|
3448
|
+
if (typeof value === "undefined")
|
|
3449
|
+
return "";
|
|
3450
|
+
return typeof value === "string" ? value : JSON.stringify(value, void 0, 2);
|
|
3451
|
+
}
|
|
3452
|
+
|
|
3404
3453
|
// src/common/tasks.ts
|
|
3405
3454
|
var PageTaskExecutor = class {
|
|
3406
3455
|
constructor(page, insight, opts) {
|
|
@@ -3535,6 +3584,7 @@ var PageTaskExecutor = class {
|
|
|
3535
3584
|
output: {
|
|
3536
3585
|
element
|
|
3537
3586
|
},
|
|
3587
|
+
pageContext,
|
|
3538
3588
|
log: {
|
|
3539
3589
|
dump: insightDump
|
|
3540
3590
|
},
|
|
@@ -3614,8 +3664,8 @@ var PageTaskExecutor = class {
|
|
|
3614
3664
|
thought: plan2.thought,
|
|
3615
3665
|
locate: plan2.locate,
|
|
3616
3666
|
executor: async (taskParam) => {
|
|
3617
|
-
|
|
3618
|
-
await this.page.keyboard.press(
|
|
3667
|
+
const keys = getKeyCommands(taskParam.value);
|
|
3668
|
+
await this.page.keyboard.press(keys);
|
|
3619
3669
|
}
|
|
3620
3670
|
};
|
|
3621
3671
|
tasks.push(taskActionKeyboardPress);
|
|
@@ -4023,7 +4073,7 @@ var PageTaskExecutor = class {
|
|
|
4023
4073
|
const cacheGroup = this.taskCache.getCacheGroupByPrompt(userPrompt);
|
|
4024
4074
|
const isCompleted = false;
|
|
4025
4075
|
let currentActionNumber = 0;
|
|
4026
|
-
const maxActionNumber =
|
|
4076
|
+
const maxActionNumber = 40;
|
|
4027
4077
|
while (!isCompleted && currentActionNumber < maxActionNumber) {
|
|
4028
4078
|
currentActionNumber++;
|
|
4029
4079
|
const planningTask = this.planningTaskToGoal(
|
|
@@ -4243,40 +4293,6 @@ var WebElementInfo = class {
|
|
|
4243
4293
|
}
|
|
4244
4294
|
};
|
|
4245
4295
|
|
|
4246
|
-
// src/common/ui-utils.ts
|
|
4247
|
-
function typeStr(task) {
|
|
4248
|
-
return task.subType ? `${task.type} / ${task.subType || ""}` : task.type;
|
|
4249
|
-
}
|
|
4250
|
-
function paramStr(task) {
|
|
4251
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
4252
|
-
let value;
|
|
4253
|
-
if (task.type === "Planning") {
|
|
4254
|
-
value = (_a = task == null ? void 0 : task.param) == null ? void 0 : _a.userPrompt;
|
|
4255
|
-
}
|
|
4256
|
-
if (task.type === "Insight") {
|
|
4257
|
-
value = ((_b = task == null ? void 0 : task.param) == null ? void 0 : _b.prompt) || ((_c = task == null ? void 0 : task.param) == null ? void 0 : _c.id) || ((_d = task == null ? void 0 : task.param) == null ? void 0 : _d.dataDemand) || ((_e = task == null ? void 0 : task.param) == null ? void 0 : _e.assertion);
|
|
4258
|
-
}
|
|
4259
|
-
if (task.type === "Action") {
|
|
4260
|
-
const sleepMs = (_f = task == null ? void 0 : task.param) == null ? void 0 : _f.timeMs;
|
|
4261
|
-
const scrollType = (_g = task == null ? void 0 : task.param) == null ? void 0 : _g.scrollType;
|
|
4262
|
-
if (sleepMs) {
|
|
4263
|
-
value = `${sleepMs}ms`;
|
|
4264
|
-
} else if (scrollType) {
|
|
4265
|
-
const scrollDirection = (_h = task == null ? void 0 : task.param) == null ? void 0 : _h.direction;
|
|
4266
|
-
const scrollDistance = (_i = task == null ? void 0 : task.param) == null ? void 0 : _i.distance;
|
|
4267
|
-
value = `${scrollDirection || "down"}, ${scrollType || "once"}, ${scrollDistance || "distance-not-set"}`;
|
|
4268
|
-
} else {
|
|
4269
|
-
value = ((_j = task == null ? void 0 : task.param) == null ? void 0 : _j.value) || ((_k = task == null ? void 0 : task.param) == null ? void 0 : _k.scrollType);
|
|
4270
|
-
}
|
|
4271
|
-
if (!value) {
|
|
4272
|
-
value = task.thought;
|
|
4273
|
-
}
|
|
4274
|
-
}
|
|
4275
|
-
if (typeof value === "undefined")
|
|
4276
|
-
return "";
|
|
4277
|
-
return typeof value === "string" ? value : JSON.stringify(value, void 0, 2);
|
|
4278
|
-
}
|
|
4279
|
-
|
|
4280
4296
|
// src/common/utils.ts
|
|
4281
4297
|
var import_node_assert4 = __toESM(require("assert"));
|
|
4282
4298
|
var import_node_fs3 = require("fs");
|
|
@@ -4569,160 +4585,6 @@ ${errors}`);
|
|
|
4569
4585
|
}
|
|
4570
4586
|
};
|
|
4571
4587
|
|
|
4572
|
-
// src/playwright/ai-fixture.ts
|
|
4573
|
-
var import_test = require("@playwright/test");
|
|
4574
|
-
var groupAndCaseForTest = (testInfo) => {
|
|
4575
|
-
let taskFile;
|
|
4576
|
-
let taskTitle;
|
|
4577
|
-
const titlePath = [...testInfo.titlePath];
|
|
4578
|
-
if (titlePath.length > 1) {
|
|
4579
|
-
taskTitle = titlePath.pop() || "unnamed";
|
|
4580
|
-
taskFile = `${titlePath.join(" > ")}`;
|
|
4581
|
-
} else if (titlePath.length === 1) {
|
|
4582
|
-
taskTitle = titlePath[0];
|
|
4583
|
-
taskFile = `${taskTitle}`;
|
|
4584
|
-
} else {
|
|
4585
|
-
taskTitle = "unnamed";
|
|
4586
|
-
taskFile = "unnamed";
|
|
4587
|
-
}
|
|
4588
|
-
return { taskFile, taskTitle };
|
|
4589
|
-
};
|
|
4590
|
-
var midsceneAgentKeyId = "_midsceneAgentId";
|
|
4591
|
-
var midsceneDumpAnnotationId = "MIDSCENE_DUMP_ANNOTATION";
|
|
4592
|
-
var PlaywrightAiFixture = () => {
|
|
4593
|
-
const pageAgentMap = {};
|
|
4594
|
-
const agentForPage = (page, testInfo) => {
|
|
4595
|
-
let idForPage = page[midsceneAgentKeyId];
|
|
4596
|
-
if (!idForPage) {
|
|
4597
|
-
idForPage = (0, import_node_crypto.randomUUID)();
|
|
4598
|
-
page[midsceneAgentKeyId] = idForPage;
|
|
4599
|
-
const { testId } = testInfo;
|
|
4600
|
-
const { taskFile, taskTitle } = groupAndCaseForTest(testInfo);
|
|
4601
|
-
pageAgentMap[idForPage] = new PageAgent(new WebPage(page), {
|
|
4602
|
-
testId: `playwright-${testId}-${idForPage}`,
|
|
4603
|
-
cacheId: `${taskFile}(${taskTitle})`,
|
|
4604
|
-
groupName: taskTitle,
|
|
4605
|
-
groupDescription: taskFile,
|
|
4606
|
-
generateReport: false
|
|
4607
|
-
// we will generate it in the reporter
|
|
4608
|
-
});
|
|
4609
|
-
}
|
|
4610
|
-
return pageAgentMap[idForPage];
|
|
4611
|
-
};
|
|
4612
|
-
const updateDumpAnnotation = (test2, dump2) => {
|
|
4613
|
-
const currentAnnotation = test2.annotations.find((item) => {
|
|
4614
|
-
return item.type === midsceneDumpAnnotationId;
|
|
4615
|
-
});
|
|
4616
|
-
if (currentAnnotation) {
|
|
4617
|
-
currentAnnotation.description = dump2;
|
|
4618
|
-
} else {
|
|
4619
|
-
test2.annotations.push({
|
|
4620
|
-
type: midsceneDumpAnnotationId,
|
|
4621
|
-
description: dump2
|
|
4622
|
-
});
|
|
4623
|
-
}
|
|
4624
|
-
};
|
|
4625
|
-
return {
|
|
4626
|
-
ai: async ({ page }, use, testInfo) => {
|
|
4627
|
-
const agent = agentForPage(page, testInfo);
|
|
4628
|
-
await use(
|
|
4629
|
-
async (taskPrompt, opts) => {
|
|
4630
|
-
return new Promise((resolve, reject) => {
|
|
4631
|
-
import_test.test.step(`ai - ${taskPrompt}`, async () => {
|
|
4632
|
-
await waitForNetworkIdle(page);
|
|
4633
|
-
const actionType = (opts == null ? void 0 : opts.type) || "action";
|
|
4634
|
-
try {
|
|
4635
|
-
const result = await agent.ai(taskPrompt, actionType);
|
|
4636
|
-
resolve(result);
|
|
4637
|
-
} catch (error) {
|
|
4638
|
-
reject(error);
|
|
4639
|
-
}
|
|
4640
|
-
});
|
|
4641
|
-
});
|
|
4642
|
-
}
|
|
4643
|
-
);
|
|
4644
|
-
updateDumpAnnotation(testInfo, agent.dumpDataString());
|
|
4645
|
-
},
|
|
4646
|
-
aiAction: async ({ page }, use, testInfo) => {
|
|
4647
|
-
const agent = agentForPage(page, testInfo);
|
|
4648
|
-
await use(async (taskPrompt) => {
|
|
4649
|
-
return new Promise((resolve, reject) => {
|
|
4650
|
-
import_test.test.step(`aiAction - ${taskPrompt}`, async () => {
|
|
4651
|
-
await waitForNetworkIdle(page);
|
|
4652
|
-
try {
|
|
4653
|
-
const result = await agent.aiAction(taskPrompt);
|
|
4654
|
-
resolve(result);
|
|
4655
|
-
} catch (error) {
|
|
4656
|
-
reject(error);
|
|
4657
|
-
}
|
|
4658
|
-
});
|
|
4659
|
-
});
|
|
4660
|
-
});
|
|
4661
|
-
updateDumpAnnotation(testInfo, agent.dumpDataString());
|
|
4662
|
-
},
|
|
4663
|
-
aiQuery: async ({ page }, use, testInfo) => {
|
|
4664
|
-
const agent = agentForPage(page, testInfo);
|
|
4665
|
-
await use(async (demand) => {
|
|
4666
|
-
return new Promise((resolve, reject) => {
|
|
4667
|
-
import_test.test.step(`aiQuery - ${JSON.stringify(demand)}`, async () => {
|
|
4668
|
-
await waitForNetworkIdle(page);
|
|
4669
|
-
try {
|
|
4670
|
-
const result = await agent.aiQuery(demand);
|
|
4671
|
-
resolve(result);
|
|
4672
|
-
} catch (error) {
|
|
4673
|
-
reject(error);
|
|
4674
|
-
}
|
|
4675
|
-
});
|
|
4676
|
-
});
|
|
4677
|
-
});
|
|
4678
|
-
updateDumpAnnotation(testInfo, agent.dumpDataString());
|
|
4679
|
-
},
|
|
4680
|
-
aiAssert: async ({ page }, use, testInfo) => {
|
|
4681
|
-
const agent = agentForPage(page, testInfo);
|
|
4682
|
-
await use(async (assertion, errorMsg) => {
|
|
4683
|
-
return new Promise((resolve, reject) => {
|
|
4684
|
-
import_test.test.step(`aiAssert - ${assertion}`, async () => {
|
|
4685
|
-
await waitForNetworkIdle(page);
|
|
4686
|
-
try {
|
|
4687
|
-
await agent.aiAssert(assertion, errorMsg);
|
|
4688
|
-
resolve(null);
|
|
4689
|
-
} catch (error) {
|
|
4690
|
-
reject(error);
|
|
4691
|
-
}
|
|
4692
|
-
});
|
|
4693
|
-
});
|
|
4694
|
-
});
|
|
4695
|
-
updateDumpAnnotation(testInfo, agent.dumpDataString());
|
|
4696
|
-
},
|
|
4697
|
-
aiWaitFor: async ({ page }, use, testInfo) => {
|
|
4698
|
-
const agent = agentForPage(page, testInfo);
|
|
4699
|
-
await use(async (assertion, opt) => {
|
|
4700
|
-
return new Promise((resolve, reject) => {
|
|
4701
|
-
import_test.test.step(`aiWaitFor - ${assertion}`, async () => {
|
|
4702
|
-
await waitForNetworkIdle(page);
|
|
4703
|
-
try {
|
|
4704
|
-
await agent.aiWaitFor(assertion, opt);
|
|
4705
|
-
resolve(null);
|
|
4706
|
-
} catch (error) {
|
|
4707
|
-
reject(error);
|
|
4708
|
-
}
|
|
4709
|
-
});
|
|
4710
|
-
});
|
|
4711
|
-
});
|
|
4712
|
-
updateDumpAnnotation(testInfo, agent.dumpDataString());
|
|
4713
|
-
}
|
|
4714
|
-
};
|
|
4715
|
-
};
|
|
4716
|
-
async function waitForNetworkIdle(page, timeout = 2e4) {
|
|
4717
|
-
try {
|
|
4718
|
-
await page.waitForLoadState("networkidle", { timeout });
|
|
4719
|
-
} catch (error) {
|
|
4720
|
-
console.warn(
|
|
4721
|
-
`Network idle timeout exceeded: ${error instanceof Error ? error.message : String(error)}`
|
|
4722
|
-
);
|
|
4723
|
-
}
|
|
4724
|
-
}
|
|
4725
|
-
|
|
4726
4588
|
// src/puppeteer/base-page.ts
|
|
4727
4589
|
var import_utils9 = require("@midscene/core/utils");
|
|
4728
4590
|
var import_extractor2 = require("@midscene/shared/extractor");
|
|
@@ -4738,12 +4600,19 @@ var Page = class {
|
|
|
4738
4600
|
this.underlyingPage = underlyingPage;
|
|
4739
4601
|
this.pageType = pageType;
|
|
4740
4602
|
}
|
|
4603
|
+
async waitForNavigation() {
|
|
4604
|
+
if (this.pageType === "puppeteer" || this.pageType === "playwright") {
|
|
4605
|
+
await this.underlyingPage.waitForSelector("html");
|
|
4606
|
+
}
|
|
4607
|
+
}
|
|
4741
4608
|
// @deprecated
|
|
4742
4609
|
async getElementsInfo() {
|
|
4610
|
+
await this.waitForNavigation();
|
|
4743
4611
|
const tree = await this.getElementsNodeTree();
|
|
4744
4612
|
return (0, import_extractor2.treeToList)(tree);
|
|
4745
4613
|
}
|
|
4746
4614
|
async getElementsNodeTree() {
|
|
4615
|
+
await this.waitForNavigation();
|
|
4747
4616
|
const scripts = await getExtraReturnLogic(true);
|
|
4748
4617
|
const captureElementSnapshot = await this.evaluate(scripts);
|
|
4749
4618
|
return captureElementSnapshot;
|
|
@@ -4764,6 +4633,7 @@ var Page = class {
|
|
|
4764
4633
|
async screenshotBase64() {
|
|
4765
4634
|
const imgType = "jpeg";
|
|
4766
4635
|
const path2 = (0, import_utils9.getTmpFile)(imgType);
|
|
4636
|
+
await this.waitForNavigation();
|
|
4767
4637
|
await this.underlyingPage.screenshot({
|
|
4768
4638
|
path: path2,
|
|
4769
4639
|
type: imgType,
|
|
@@ -4821,13 +4691,14 @@ var Page = class {
|
|
|
4821
4691
|
get keyboard() {
|
|
4822
4692
|
return {
|
|
4823
4693
|
type: async (text) => this.underlyingPage.keyboard.type(text, { delay: 80 }),
|
|
4824
|
-
press: async (
|
|
4825
|
-
const keys = Array.isArray(
|
|
4826
|
-
for (const
|
|
4827
|
-
|
|
4694
|
+
press: async (action) => {
|
|
4695
|
+
const keys = Array.isArray(action) ? action : [action];
|
|
4696
|
+
for (const k of keys) {
|
|
4697
|
+
const commands = k.command ? [k.command] : [];
|
|
4698
|
+
await this.underlyingPage.keyboard.down(k.key, { commands });
|
|
4828
4699
|
}
|
|
4829
|
-
for (const
|
|
4830
|
-
await this.underlyingPage.keyboard.up(
|
|
4700
|
+
for (const k of [...keys].reverse()) {
|
|
4701
|
+
await this.underlyingPage.keyboard.up(k.key);
|
|
4831
4702
|
}
|
|
4832
4703
|
},
|
|
4833
4704
|
down: async (key) => {
|
|
@@ -4862,7 +4733,7 @@ var Page = class {
|
|
|
4862
4733
|
await this.underlyingPage.keyboard.up("Control");
|
|
4863
4734
|
}
|
|
4864
4735
|
await (0, import_utils9.sleep)(100);
|
|
4865
|
-
await this.keyboard.press("Backspace");
|
|
4736
|
+
await this.keyboard.press([{ key: "Backspace" }]);
|
|
4866
4737
|
}
|
|
4867
4738
|
async moveToPoint(point) {
|
|
4868
4739
|
if (point) {
|
|
@@ -4923,8 +4794,186 @@ var WebPage = class extends Page {
|
|
|
4923
4794
|
}
|
|
4924
4795
|
};
|
|
4925
4796
|
|
|
4797
|
+
// src/playwright/ai-fixture.ts
|
|
4798
|
+
var import_node_crypto = require("crypto");
|
|
4799
|
+
var import_test = require("@playwright/test");
|
|
4800
|
+
var groupAndCaseForTest = (testInfo) => {
|
|
4801
|
+
let taskFile;
|
|
4802
|
+
let taskTitle;
|
|
4803
|
+
const titlePath = [...testInfo.titlePath];
|
|
4804
|
+
if (titlePath.length > 1) {
|
|
4805
|
+
taskTitle = titlePath.pop() || "unnamed";
|
|
4806
|
+
taskFile = `${titlePath.join(" > ")}`;
|
|
4807
|
+
} else if (titlePath.length === 1) {
|
|
4808
|
+
taskTitle = titlePath[0];
|
|
4809
|
+
taskFile = `${taskTitle}`;
|
|
4810
|
+
} else {
|
|
4811
|
+
taskTitle = "unnamed";
|
|
4812
|
+
taskFile = "unnamed";
|
|
4813
|
+
}
|
|
4814
|
+
return { taskFile, taskTitle };
|
|
4815
|
+
};
|
|
4816
|
+
var midsceneAgentKeyId = "_midsceneAgentId";
|
|
4817
|
+
var midsceneDumpAnnotationId = "MIDSCENE_DUMP_ANNOTATION";
|
|
4818
|
+
var PlaywrightAiFixture = (options) => {
|
|
4819
|
+
const { forceSameTabNavigation = true } = options != null ? options : {};
|
|
4820
|
+
const pageAgentMap = {};
|
|
4821
|
+
const agentForPage = (page, testInfo) => {
|
|
4822
|
+
let idForPage = page[midsceneAgentKeyId];
|
|
4823
|
+
if (!idForPage) {
|
|
4824
|
+
idForPage = (0, import_node_crypto.randomUUID)();
|
|
4825
|
+
page[midsceneAgentKeyId] = idForPage;
|
|
4826
|
+
const { testId } = testInfo;
|
|
4827
|
+
const { taskFile, taskTitle } = groupAndCaseForTest(testInfo);
|
|
4828
|
+
pageAgentMap[idForPage] = new PlaywrightAgent(page, {
|
|
4829
|
+
testId: `playwright-${testId}-${idForPage}`,
|
|
4830
|
+
forceSameTabNavigation,
|
|
4831
|
+
cacheId: `${taskFile}(${taskTitle})`,
|
|
4832
|
+
groupName: taskTitle,
|
|
4833
|
+
groupDescription: taskFile,
|
|
4834
|
+
generateReport: false
|
|
4835
|
+
// we will generate it in the reporter
|
|
4836
|
+
});
|
|
4837
|
+
}
|
|
4838
|
+
return pageAgentMap[idForPage];
|
|
4839
|
+
};
|
|
4840
|
+
const updateDumpAnnotation = (test2, dump2) => {
|
|
4841
|
+
const currentAnnotation = test2.annotations.find((item) => {
|
|
4842
|
+
return item.type === midsceneDumpAnnotationId;
|
|
4843
|
+
});
|
|
4844
|
+
if (currentAnnotation) {
|
|
4845
|
+
currentAnnotation.description = dump2;
|
|
4846
|
+
} else {
|
|
4847
|
+
test2.annotations.push({
|
|
4848
|
+
type: midsceneDumpAnnotationId,
|
|
4849
|
+
description: dump2
|
|
4850
|
+
});
|
|
4851
|
+
}
|
|
4852
|
+
};
|
|
4853
|
+
return {
|
|
4854
|
+
ai: async ({ page }, use, testInfo) => {
|
|
4855
|
+
const agent = agentForPage(page, testInfo);
|
|
4856
|
+
await use(
|
|
4857
|
+
async (taskPrompt, opts) => {
|
|
4858
|
+
return new Promise((resolve, reject) => {
|
|
4859
|
+
const { type: type2 = "action" } = opts || {};
|
|
4860
|
+
import_test.test.step(`ai - ${taskPrompt}`, async () => {
|
|
4861
|
+
await waitForNetworkIdle(page);
|
|
4862
|
+
try {
|
|
4863
|
+
const result = await agent.ai(taskPrompt, type2);
|
|
4864
|
+
resolve(result);
|
|
4865
|
+
} catch (error) {
|
|
4866
|
+
reject(error);
|
|
4867
|
+
}
|
|
4868
|
+
});
|
|
4869
|
+
});
|
|
4870
|
+
}
|
|
4871
|
+
);
|
|
4872
|
+
updateDumpAnnotation(testInfo, agent.dumpDataString());
|
|
4873
|
+
},
|
|
4874
|
+
aiAction: async ({ page }, use, testInfo) => {
|
|
4875
|
+
const agent = agentForPage(page, testInfo);
|
|
4876
|
+
await use(async (taskPrompt) => {
|
|
4877
|
+
return new Promise((resolve, reject) => {
|
|
4878
|
+
import_test.test.step(`aiAction - ${taskPrompt}`, async () => {
|
|
4879
|
+
await waitForNetworkIdle(page);
|
|
4880
|
+
try {
|
|
4881
|
+
const result = await agent.aiAction(taskPrompt);
|
|
4882
|
+
resolve(result);
|
|
4883
|
+
} catch (error) {
|
|
4884
|
+
reject(error);
|
|
4885
|
+
}
|
|
4886
|
+
});
|
|
4887
|
+
});
|
|
4888
|
+
});
|
|
4889
|
+
updateDumpAnnotation(testInfo, agent.dumpDataString());
|
|
4890
|
+
},
|
|
4891
|
+
aiQuery: async ({ page }, use, testInfo) => {
|
|
4892
|
+
const agent = agentForPage(page, testInfo);
|
|
4893
|
+
await use(async (demand) => {
|
|
4894
|
+
return new Promise((resolve, reject) => {
|
|
4895
|
+
import_test.test.step(`aiQuery - ${JSON.stringify(demand)}`, async () => {
|
|
4896
|
+
await waitForNetworkIdle(page);
|
|
4897
|
+
try {
|
|
4898
|
+
const result = await agent.aiQuery(demand);
|
|
4899
|
+
resolve(result);
|
|
4900
|
+
} catch (error) {
|
|
4901
|
+
reject(error);
|
|
4902
|
+
}
|
|
4903
|
+
});
|
|
4904
|
+
});
|
|
4905
|
+
});
|
|
4906
|
+
updateDumpAnnotation(testInfo, agent.dumpDataString());
|
|
4907
|
+
},
|
|
4908
|
+
aiAssert: async ({ page }, use, testInfo) => {
|
|
4909
|
+
const agent = agentForPage(page, testInfo);
|
|
4910
|
+
await use(async (assertion, errorMsg) => {
|
|
4911
|
+
return new Promise((resolve, reject) => {
|
|
4912
|
+
import_test.test.step(`aiAssert - ${assertion}`, async () => {
|
|
4913
|
+
await waitForNetworkIdle(page);
|
|
4914
|
+
try {
|
|
4915
|
+
await agent.aiAssert(assertion, errorMsg);
|
|
4916
|
+
resolve(null);
|
|
4917
|
+
} catch (error) {
|
|
4918
|
+
reject(error);
|
|
4919
|
+
}
|
|
4920
|
+
});
|
|
4921
|
+
});
|
|
4922
|
+
});
|
|
4923
|
+
updateDumpAnnotation(testInfo, agent.dumpDataString());
|
|
4924
|
+
},
|
|
4925
|
+
aiWaitFor: async ({ page }, use, testInfo) => {
|
|
4926
|
+
const agent = agentForPage(page, testInfo);
|
|
4927
|
+
await use(async (assertion, opt) => {
|
|
4928
|
+
return new Promise((resolve, reject) => {
|
|
4929
|
+
import_test.test.step(`aiWaitFor - ${assertion}`, async () => {
|
|
4930
|
+
await waitForNetworkIdle(page);
|
|
4931
|
+
try {
|
|
4932
|
+
await agent.aiWaitFor(assertion, opt);
|
|
4933
|
+
resolve(null);
|
|
4934
|
+
} catch (error) {
|
|
4935
|
+
reject(error);
|
|
4936
|
+
}
|
|
4937
|
+
});
|
|
4938
|
+
});
|
|
4939
|
+
});
|
|
4940
|
+
updateDumpAnnotation(testInfo, agent.dumpDataString());
|
|
4941
|
+
}
|
|
4942
|
+
};
|
|
4943
|
+
};
|
|
4944
|
+
async function waitForNetworkIdle(page, timeout = 2e4) {
|
|
4945
|
+
try {
|
|
4946
|
+
await page.waitForLoadState("networkidle", { timeout });
|
|
4947
|
+
} catch (error) {
|
|
4948
|
+
console.warn(
|
|
4949
|
+
`Network idle timeout exceeded: ${error instanceof Error ? error.message : String(error)}`
|
|
4950
|
+
);
|
|
4951
|
+
}
|
|
4952
|
+
}
|
|
4953
|
+
|
|
4926
4954
|
// src/playwright/index.ts
|
|
4927
4955
|
var import_env4 = require("@midscene/core/env");
|
|
4956
|
+
var PlaywrightAgent = class extends PageAgent {
|
|
4957
|
+
constructor(page, opts) {
|
|
4958
|
+
const webPage = new WebPage(page);
|
|
4959
|
+
super(webPage, opts);
|
|
4960
|
+
const { forceSameTabNavigation = true } = opts != null ? opts : {};
|
|
4961
|
+
if (forceSameTabNavigation) {
|
|
4962
|
+
page.on("popup", async (popup) => {
|
|
4963
|
+
if (!popup) {
|
|
4964
|
+
console.warn(
|
|
4965
|
+
"got a popup event, but the popup is not ready yet, skip"
|
|
4966
|
+
);
|
|
4967
|
+
return;
|
|
4968
|
+
}
|
|
4969
|
+
const url = await popup.url();
|
|
4970
|
+
console.log(`Popup opened: ${url}`);
|
|
4971
|
+
await popup.close();
|
|
4972
|
+
await page.goto(url);
|
|
4973
|
+
});
|
|
4974
|
+
}
|
|
4975
|
+
}
|
|
4976
|
+
};
|
|
4928
4977
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4929
4978
|
0 && (module.exports = {
|
|
4930
4979
|
PlaywrightAgent,
|