@midscene/web 0.7.1 → 0.7.2-beta-20241024094141.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/playground.js +8438 -0
- package/dist/browser/types/playground.d.ts +313 -0
- package/dist/es/appium.js +680 -604
- package/dist/es/debug.js +95 -73
- package/dist/es/index.js +939 -797
- package/dist/es/midscene-playground.js +678 -609
- package/dist/es/playground.js +593 -1024
- package/dist/es/playwright-report.js +29 -11
- package/dist/es/playwright.js +705 -597
- package/dist/es/puppeteer.js +636 -552
- package/dist/lib/appium.js +688 -609
- package/dist/lib/debug.js +95 -73
- package/dist/lib/index.js +950 -804
- package/dist/lib/midscene-playground.js +687 -615
- package/dist/lib/playground.js +586 -1007
- package/dist/lib/playwright-report.js +30 -9
- package/dist/lib/playwright.js +713 -602
- package/dist/lib/puppeteer.js +644 -557
- package/dist/script/htmlElement.js +11 -10
- package/dist/script/htmlElementDebug.js +11 -10
- package/dist/types/appium.d.ts +2 -3
- package/dist/types/debug.d.ts +1 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/{page-ad820b3c.d.ts → page-8117b0ad.d.ts} +8 -7
- package/dist/types/playground.d.ts +6 -21
- package/dist/types/playwright.d.ts +3 -4
- package/dist/types/puppeteer.d.ts +2 -3
- package/dist/types/{tasks-82c1054b.d.ts → tasks-cb6bf758.d.ts} +6 -6
- package/package.json +11 -5
- package/static/index.html +1 -1
package/dist/lib/index.js
CHANGED
|
@@ -46,6 +46,26 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
46
46
|
mod
|
|
47
47
|
));
|
|
48
48
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
49
|
+
var __async = (__this, __arguments, generator) => {
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
var fulfilled = (value) => {
|
|
52
|
+
try {
|
|
53
|
+
step(generator.next(value));
|
|
54
|
+
} catch (e) {
|
|
55
|
+
reject(e);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
var rejected = (value) => {
|
|
59
|
+
try {
|
|
60
|
+
step(generator.throw(value));
|
|
61
|
+
} catch (e) {
|
|
62
|
+
reject(e);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
66
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
67
|
+
});
|
|
68
|
+
};
|
|
49
69
|
|
|
50
70
|
// ../../node_modules/.pnpm/dayjs@1.11.11/node_modules/dayjs/dayjs.min.js
|
|
51
71
|
var require_dayjs_min = __commonJS({
|
|
@@ -869,37 +889,38 @@ __export(src_exports, {
|
|
|
869
889
|
PlaywrightAgent: () => PageAgent,
|
|
870
890
|
PlaywrightAiFixture: () => PlaywrightAiFixture,
|
|
871
891
|
PuppeteerAgent: () => PuppeteerAgent,
|
|
892
|
+
StaticPageAgent: () => StaticPageAgent,
|
|
872
893
|
generateExtractData: () => generateExtractData
|
|
873
894
|
});
|
|
874
895
|
module.exports = __toCommonJS(src_exports);
|
|
875
896
|
|
|
876
897
|
// src/playwright/ai-fixture.ts
|
|
877
|
-
var
|
|
898
|
+
var import_node_crypto = require("crypto");
|
|
878
899
|
|
|
879
900
|
// src/common/agent.ts
|
|
880
|
-
var
|
|
901
|
+
var import_utils7 = require("@midscene/core/utils");
|
|
881
902
|
|
|
882
903
|
// src/common/tasks.ts
|
|
883
904
|
var import_node_assert2 = __toESM(require("assert"));
|
|
884
905
|
var import_core = require("@midscene/core");
|
|
885
|
-
var
|
|
886
|
-
var import_img3 = require("@midscene/shared/img");
|
|
906
|
+
var import_utils5 = require("@midscene/core/utils");
|
|
887
907
|
|
|
888
908
|
// src/common/task-cache.ts
|
|
889
909
|
var import_node_fs2 = require("fs");
|
|
890
910
|
var import_node_path2 = require("path");
|
|
891
|
-
var
|
|
911
|
+
var import_utils2 = require("@midscene/core/utils");
|
|
892
912
|
var import_fs2 = require("@midscene/shared/fs");
|
|
913
|
+
var import_utils3 = require("@midscene/shared/utils");
|
|
893
914
|
|
|
894
915
|
// src/common/utils.ts
|
|
895
916
|
var import_node_assert = __toESM(require("assert"));
|
|
896
|
-
var import_node_crypto = require("crypto");
|
|
897
917
|
var import_node_fs = require("fs");
|
|
898
918
|
var import_node_path = __toESM(require("path"));
|
|
899
919
|
var import_constants = require("@midscene/shared/constants");
|
|
900
920
|
var import_fs = require("@midscene/shared/fs");
|
|
901
921
|
var import_img = require("@midscene/shared/img");
|
|
902
922
|
var import_img2 = require("@midscene/shared/img");
|
|
923
|
+
var import_utils = require("@midscene/shared/utils");
|
|
903
924
|
var import_dayjs = __toESM(require_dayjs_min());
|
|
904
925
|
|
|
905
926
|
// src/web-element.ts
|
|
@@ -928,63 +949,68 @@ var WebElementInfo = class {
|
|
|
928
949
|
};
|
|
929
950
|
|
|
930
951
|
// src/common/utils.ts
|
|
931
|
-
|
|
932
|
-
(
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
const url = page.url();
|
|
937
|
-
const file = await page.screenshot();
|
|
938
|
-
const screenshotBase64 = (0, import_img.base64Encoded)(file);
|
|
939
|
-
const captureElementSnapshot = await page.getElementInfos();
|
|
940
|
-
const elementsInfo = await alignElements(captureElementSnapshot, page);
|
|
941
|
-
const elementsPositionInfoWithoutText = elementsInfo.filter((elementInfo) => {
|
|
942
|
-
if (elementInfo.attributes.nodeType === import_constants.NodeType.TEXT) {
|
|
943
|
-
return false;
|
|
952
|
+
function parseContextFromWebPage(page, _opt) {
|
|
953
|
+
return __async(this, null, function* () {
|
|
954
|
+
(0, import_node_assert.default)(page, "page is required");
|
|
955
|
+
if (page._forceUsePageContext) {
|
|
956
|
+
return yield page._forceUsePageContext();
|
|
944
957
|
}
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
958
|
+
const url = page.url();
|
|
959
|
+
const screenshotBase64 = yield page.screenshotBase64();
|
|
960
|
+
const captureElementSnapshot = yield page.getElementInfos();
|
|
961
|
+
const elementsInfo = yield alignElements(captureElementSnapshot, page);
|
|
962
|
+
const elementsPositionInfoWithoutText = elementsInfo.filter((elementInfo) => {
|
|
963
|
+
if (elementInfo.attributes.nodeType === import_constants.NodeType.TEXT) {
|
|
964
|
+
return false;
|
|
965
|
+
}
|
|
966
|
+
return true;
|
|
967
|
+
});
|
|
968
|
+
const size = yield (0, import_img.imageInfoOfBase64)(screenshotBase64);
|
|
969
|
+
const screenshotBase64WithElementMarker = yield (0, import_img2.compositeElementInfoImg)({
|
|
970
|
+
inputImgBase64: screenshotBase64,
|
|
971
|
+
elementsPositionInfo: elementsPositionInfoWithoutText
|
|
972
|
+
});
|
|
973
|
+
return {
|
|
974
|
+
content: elementsInfo,
|
|
975
|
+
size,
|
|
976
|
+
screenshotBase64,
|
|
977
|
+
screenshotBase64WithElementMarker: `data:image/png;base64,${screenshotBase64WithElementMarker}`,
|
|
978
|
+
url
|
|
979
|
+
};
|
|
951
980
|
});
|
|
952
|
-
return {
|
|
953
|
-
content: elementsInfo,
|
|
954
|
-
size,
|
|
955
|
-
screenshotBase64,
|
|
956
|
-
screenshotBase64WithElementMarker: `data:image/png;base64,${screenshotBase64WithElementMarker}`,
|
|
957
|
-
url
|
|
958
|
-
};
|
|
959
981
|
}
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
982
|
+
function getExtraReturnLogic() {
|
|
983
|
+
return __async(this, null, function* () {
|
|
984
|
+
const pathDir = (0, import_fs.findNearestPackageJson)(__dirname);
|
|
985
|
+
(0, import_node_assert.default)(pathDir, `can't find pathDir, with ${__dirname}`);
|
|
986
|
+
const scriptPath = import_node_path.default.join(pathDir, "./dist/script/htmlElement.js");
|
|
987
|
+
const elementInfosScriptContent = (0, import_node_fs.readFileSync)(scriptPath, "utf-8");
|
|
988
|
+
return `${elementInfosScriptContent}midscene_element_inspector.webExtractTextWithPosition()`;
|
|
989
|
+
});
|
|
966
990
|
}
|
|
967
991
|
var sizeThreshold = 3;
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
992
|
+
function alignElements(elements, page) {
|
|
993
|
+
return __async(this, null, function* () {
|
|
994
|
+
const validElements = elements.filter((item) => {
|
|
995
|
+
return item.rect.height >= sizeThreshold && item.rect.width >= sizeThreshold;
|
|
996
|
+
});
|
|
997
|
+
const textsAligned = [];
|
|
998
|
+
for (const item of validElements) {
|
|
999
|
+
const { rect, id, content, attributes, locator, indexId } = item;
|
|
1000
|
+
textsAligned.push(
|
|
1001
|
+
new WebElementInfo({
|
|
1002
|
+
rect,
|
|
1003
|
+
locator,
|
|
1004
|
+
id,
|
|
1005
|
+
content,
|
|
1006
|
+
attributes,
|
|
1007
|
+
page,
|
|
1008
|
+
indexId
|
|
1009
|
+
})
|
|
1010
|
+
);
|
|
1011
|
+
}
|
|
1012
|
+
return textsAligned;
|
|
971
1013
|
});
|
|
972
|
-
const textsAligned = [];
|
|
973
|
-
for (const item of validElements) {
|
|
974
|
-
const { rect, id, content, attributes, locator, indexId } = item;
|
|
975
|
-
textsAligned.push(
|
|
976
|
-
new WebElementInfo({
|
|
977
|
-
rect,
|
|
978
|
-
locator,
|
|
979
|
-
id,
|
|
980
|
-
content,
|
|
981
|
-
attributes,
|
|
982
|
-
page,
|
|
983
|
-
indexId
|
|
984
|
-
})
|
|
985
|
-
);
|
|
986
|
-
}
|
|
987
|
-
return textsAligned;
|
|
988
1014
|
}
|
|
989
1015
|
function reportFileName(tag = "web") {
|
|
990
1016
|
const dateTimeInFileName = (0, import_dayjs.default)().format("YYYY-MM-DD_HH-mm-ss-SSS");
|
|
@@ -1015,7 +1041,7 @@ var testFileIndex = /* @__PURE__ */ new Map();
|
|
|
1015
1041
|
function generateCacheId(fileName) {
|
|
1016
1042
|
let taskFile = fileName || getCurrentExecutionFile();
|
|
1017
1043
|
if (!taskFile) {
|
|
1018
|
-
taskFile = (0,
|
|
1044
|
+
taskFile = (0, import_utils.uuid)();
|
|
1019
1045
|
console.warn(
|
|
1020
1046
|
"Midscene - using random UUID for cache id. Cache may be invalid."
|
|
1021
1047
|
);
|
|
@@ -1034,7 +1060,7 @@ function generateCacheId(fileName) {
|
|
|
1034
1060
|
// src/common/task-cache.ts
|
|
1035
1061
|
var TaskCache = class {
|
|
1036
1062
|
constructor(opts) {
|
|
1037
|
-
this.midscenePkgInfo = (0, import_fs2.
|
|
1063
|
+
this.midscenePkgInfo = (0, import_fs2.getRunningPkgInfo)();
|
|
1038
1064
|
this.cacheId = generateCacheId(opts == null ? void 0 : opts.fileName);
|
|
1039
1065
|
this.cache = this.readCacheFromFile() || {
|
|
1040
1066
|
aiTasks: []
|
|
@@ -1116,11 +1142,17 @@ var TaskCache = class {
|
|
|
1116
1142
|
return this.newCache;
|
|
1117
1143
|
}
|
|
1118
1144
|
readCacheFromFile() {
|
|
1119
|
-
|
|
1145
|
+
if (import_utils3.ifInBrowser) {
|
|
1146
|
+
return void 0;
|
|
1147
|
+
}
|
|
1148
|
+
const cacheFile = (0, import_node_path2.join)((0, import_utils2.getLogDirByType)("cache"), `${this.cacheId}.json`);
|
|
1120
1149
|
if (process.env.MIDSCENE_CACHE === "true" && (0, import_node_fs2.existsSync)(cacheFile)) {
|
|
1121
1150
|
try {
|
|
1122
1151
|
const data = (0, import_node_fs2.readFileSync)(cacheFile, "utf8");
|
|
1123
1152
|
const jsonData = JSON.parse(data);
|
|
1153
|
+
if (!this.midscenePkgInfo) {
|
|
1154
|
+
return void 0;
|
|
1155
|
+
}
|
|
1124
1156
|
if (jsonData.pkgName !== this.midscenePkgInfo.name || jsonData.pkgVersion !== this.midscenePkgInfo.version) {
|
|
1125
1157
|
return void 0;
|
|
1126
1158
|
}
|
|
@@ -1132,11 +1164,14 @@ var TaskCache = class {
|
|
|
1132
1164
|
return void 0;
|
|
1133
1165
|
}
|
|
1134
1166
|
writeCacheToFile() {
|
|
1135
|
-
const midscenePkgInfo = (0, import_fs2.
|
|
1136
|
-
(
|
|
1167
|
+
const midscenePkgInfo = (0, import_fs2.getRunningPkgInfo)();
|
|
1168
|
+
if (!midscenePkgInfo) {
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1171
|
+
(0, import_utils2.writeLogFile)({
|
|
1137
1172
|
fileName: `${this.cacheId}`,
|
|
1138
1173
|
fileExt: "json",
|
|
1139
|
-
fileContent: (0,
|
|
1174
|
+
fileContent: (0, import_utils2.stringifyDumpData)(
|
|
1140
1175
|
__spreadValues({
|
|
1141
1176
|
pkgName: midscenePkgInfo.name,
|
|
1142
1177
|
pkgVersion: midscenePkgInfo.version,
|
|
@@ -1153,423 +1188,435 @@ var TaskCache = class {
|
|
|
1153
1188
|
var PageTaskExecutor = class {
|
|
1154
1189
|
constructor(page, opts) {
|
|
1155
1190
|
this.page = page;
|
|
1156
|
-
this.insight = new import_core.Insight(
|
|
1157
|
-
return
|
|
1158
|
-
});
|
|
1191
|
+
this.insight = new import_core.Insight(() => __async(this, null, function* () {
|
|
1192
|
+
return yield parseContextFromWebPage(page);
|
|
1193
|
+
}));
|
|
1159
1194
|
this.taskCache = new TaskCache({
|
|
1160
1195
|
fileName: opts == null ? void 0 : opts.cacheId
|
|
1161
1196
|
});
|
|
1162
1197
|
}
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1198
|
+
recordScreenshot(timing) {
|
|
1199
|
+
return __async(this, null, function* () {
|
|
1200
|
+
const base64 = yield this.page.screenshotBase64();
|
|
1201
|
+
const item = {
|
|
1202
|
+
type: "screenshot",
|
|
1203
|
+
ts: Date.now(),
|
|
1204
|
+
screenshot: base64,
|
|
1205
|
+
timing
|
|
1206
|
+
};
|
|
1207
|
+
return item;
|
|
1208
|
+
});
|
|
1172
1209
|
}
|
|
1173
1210
|
wrapExecutorWithScreenshot(taskApply) {
|
|
1174
1211
|
const taskWithScreenshot = __spreadProps(__spreadValues({}, taskApply), {
|
|
1175
|
-
executor:
|
|
1212
|
+
executor: (param, context, ...args) => __async(this, null, function* () {
|
|
1176
1213
|
const recorder = [];
|
|
1177
1214
|
const { task } = context;
|
|
1178
1215
|
task.recorder = recorder;
|
|
1179
|
-
const shot =
|
|
1216
|
+
const shot = yield this.recordScreenshot(`before ${task.type}`);
|
|
1180
1217
|
recorder.push(shot);
|
|
1181
|
-
const result =
|
|
1218
|
+
const result = yield taskApply.executor(param, context, ...args);
|
|
1182
1219
|
if (taskApply.type === "Action") {
|
|
1183
|
-
|
|
1184
|
-
const shot2 =
|
|
1220
|
+
yield (0, import_utils5.sleep)(1e3);
|
|
1221
|
+
const shot2 = yield this.recordScreenshot("after Action");
|
|
1185
1222
|
recorder.push(shot2);
|
|
1186
1223
|
}
|
|
1187
1224
|
return result;
|
|
1188
|
-
}
|
|
1225
|
+
})
|
|
1189
1226
|
});
|
|
1190
1227
|
return taskWithScreenshot;
|
|
1191
1228
|
}
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
this.insight.onceDumpUpdatedFn = dumpCollector;
|
|
1206
|
-
const pageContext = await this.insight.contextRetrieverFn();
|
|
1207
|
-
const locateCache = cacheGroup == null ? void 0 : cacheGroup.readCache(
|
|
1208
|
-
pageContext,
|
|
1209
|
-
"locate",
|
|
1210
|
-
param.prompt
|
|
1211
|
-
);
|
|
1212
|
-
let locateResult;
|
|
1213
|
-
const callAI = this.insight.aiVendorFn;
|
|
1214
|
-
const element = await this.insight.locate(param.prompt, {
|
|
1215
|
-
quickAnswer: plan2.quickAnswer,
|
|
1216
|
-
callAI: async (...message) => {
|
|
1217
|
-
if (locateCache) {
|
|
1218
|
-
locateResult = locateCache;
|
|
1219
|
-
return Promise.resolve(locateCache);
|
|
1220
|
-
}
|
|
1221
|
-
locateResult = await callAI(...message);
|
|
1222
|
-
(0, import_node_assert2.default)(locateResult);
|
|
1223
|
-
return locateResult;
|
|
1224
|
-
}
|
|
1225
|
-
});
|
|
1226
|
-
if (locateResult) {
|
|
1227
|
-
cacheGroup == null ? void 0 : cacheGroup.saveCache({
|
|
1228
|
-
type: "locate",
|
|
1229
|
-
pageContext: {
|
|
1230
|
-
url: pageContext.url,
|
|
1231
|
-
size: pageContext.size
|
|
1232
|
-
},
|
|
1233
|
-
prompt: param.prompt,
|
|
1234
|
-
response: locateResult
|
|
1235
|
-
});
|
|
1236
|
-
}
|
|
1237
|
-
if (!element) {
|
|
1238
|
-
task.log = {
|
|
1239
|
-
dump: insightDump
|
|
1229
|
+
convertPlanToExecutable(plans, cacheGroup) {
|
|
1230
|
+
return __async(this, null, function* () {
|
|
1231
|
+
const tasks = plans.map((plan2) => {
|
|
1232
|
+
if (plan2.type === "Locate") {
|
|
1233
|
+
const taskFind = {
|
|
1234
|
+
type: "Insight",
|
|
1235
|
+
subType: "Locate",
|
|
1236
|
+
param: plan2.param,
|
|
1237
|
+
executor: (param, taskContext) => __async(this, null, function* () {
|
|
1238
|
+
const { task } = taskContext;
|
|
1239
|
+
let insightDump;
|
|
1240
|
+
const dumpCollector = (dump) => {
|
|
1241
|
+
insightDump = dump;
|
|
1240
1242
|
};
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1243
|
+
this.insight.onceDumpUpdatedFn = dumpCollector;
|
|
1244
|
+
const pageContext = yield this.insight.contextRetrieverFn();
|
|
1245
|
+
const locateCache = cacheGroup == null ? void 0 : cacheGroup.readCache(
|
|
1246
|
+
pageContext,
|
|
1247
|
+
"locate",
|
|
1248
|
+
param.prompt
|
|
1249
|
+
);
|
|
1250
|
+
let locateResult;
|
|
1251
|
+
const callAI = this.insight.aiVendorFn;
|
|
1252
|
+
const element = yield this.insight.locate(param.prompt, {
|
|
1253
|
+
quickAnswer: plan2.quickAnswer,
|
|
1254
|
+
callAI: (...message) => __async(this, null, function* () {
|
|
1255
|
+
if (locateCache) {
|
|
1256
|
+
locateResult = locateCache;
|
|
1257
|
+
return Promise.resolve(locateCache);
|
|
1258
|
+
}
|
|
1259
|
+
locateResult = yield callAI(...message);
|
|
1260
|
+
(0, import_node_assert2.default)(locateResult);
|
|
1261
|
+
return locateResult;
|
|
1262
|
+
})
|
|
1263
|
+
});
|
|
1264
|
+
if (locateResult) {
|
|
1265
|
+
cacheGroup == null ? void 0 : cacheGroup.saveCache({
|
|
1266
|
+
type: "locate",
|
|
1267
|
+
pageContext: {
|
|
1268
|
+
url: pageContext.url,
|
|
1269
|
+
size: pageContext.size
|
|
1270
|
+
},
|
|
1271
|
+
prompt: param.prompt,
|
|
1272
|
+
response: locateResult
|
|
1273
|
+
});
|
|
1252
1274
|
}
|
|
1253
|
-
|
|
1254
|
-
}
|
|
1255
|
-
};
|
|
1256
|
-
return taskFind;
|
|
1257
|
-
}
|
|
1258
|
-
if (plan2.type === "Assert" || plan2.type === "AssertWithoutThrow") {
|
|
1259
|
-
const assertPlan = plan2;
|
|
1260
|
-
const taskAssert = {
|
|
1261
|
-
type: "Insight",
|
|
1262
|
-
subType: "Assert",
|
|
1263
|
-
param: assertPlan.param,
|
|
1264
|
-
executor: async (param, taskContext) => {
|
|
1265
|
-
const { task } = taskContext;
|
|
1266
|
-
let insightDump;
|
|
1267
|
-
const dumpCollector = (dump) => {
|
|
1268
|
-
insightDump = dump;
|
|
1269
|
-
};
|
|
1270
|
-
this.insight.onceDumpUpdatedFn = dumpCollector;
|
|
1271
|
-
const assertion = await this.insight.assert(
|
|
1272
|
-
assertPlan.param.assertion
|
|
1273
|
-
);
|
|
1274
|
-
if (!assertion.pass) {
|
|
1275
|
-
if (plan2.type === "Assert") {
|
|
1276
|
-
task.output = assertion;
|
|
1275
|
+
if (!element) {
|
|
1277
1276
|
task.log = {
|
|
1278
1277
|
dump: insightDump
|
|
1279
1278
|
};
|
|
1280
|
-
throw new Error(
|
|
1281
|
-
assertion.thought || "Assertion failed without reason"
|
|
1282
|
-
);
|
|
1279
|
+
throw new Error(`Element not found: ${param.prompt}`);
|
|
1283
1280
|
}
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1281
|
+
return {
|
|
1282
|
+
output: {
|
|
1283
|
+
element
|
|
1284
|
+
},
|
|
1285
|
+
log: {
|
|
1286
|
+
dump: insightDump
|
|
1287
|
+
},
|
|
1288
|
+
cache: {
|
|
1289
|
+
hit: Boolean(locateCache)
|
|
1290
|
+
}
|
|
1291
|
+
};
|
|
1292
|
+
})
|
|
1293
|
+
};
|
|
1294
|
+
return taskFind;
|
|
1295
|
+
}
|
|
1296
|
+
if (plan2.type === "Assert" || plan2.type === "AssertWithoutThrow") {
|
|
1297
|
+
const assertPlan = plan2;
|
|
1298
|
+
const taskAssert = {
|
|
1299
|
+
type: "Insight",
|
|
1300
|
+
subType: "Assert",
|
|
1301
|
+
param: assertPlan.param,
|
|
1302
|
+
executor: (param, taskContext) => __async(this, null, function* () {
|
|
1303
|
+
const { task } = taskContext;
|
|
1304
|
+
let insightDump;
|
|
1305
|
+
const dumpCollector = (dump) => {
|
|
1306
|
+
insightDump = dump;
|
|
1307
|
+
};
|
|
1308
|
+
this.insight.onceDumpUpdatedFn = dumpCollector;
|
|
1309
|
+
const assertion = yield this.insight.assert(
|
|
1310
|
+
assertPlan.param.assertion
|
|
1311
|
+
);
|
|
1312
|
+
if (!assertion.pass) {
|
|
1313
|
+
if (plan2.type === "Assert") {
|
|
1314
|
+
task.output = assertion;
|
|
1315
|
+
task.log = {
|
|
1316
|
+
dump: insightDump
|
|
1317
|
+
};
|
|
1318
|
+
throw new Error(
|
|
1319
|
+
assertion.thought || "Assertion failed without reason"
|
|
1320
|
+
);
|
|
1321
|
+
}
|
|
1322
|
+
task.error = assertion.thought;
|
|
1290
1323
|
}
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1324
|
+
return {
|
|
1325
|
+
output: assertion,
|
|
1326
|
+
log: {
|
|
1327
|
+
dump: insightDump
|
|
1328
|
+
}
|
|
1329
|
+
};
|
|
1330
|
+
})
|
|
1331
|
+
};
|
|
1332
|
+
return taskAssert;
|
|
1333
|
+
}
|
|
1334
|
+
if (plan2.type === "Input") {
|
|
1335
|
+
const taskActionInput = {
|
|
1336
|
+
type: "Action",
|
|
1337
|
+
subType: "Input",
|
|
1338
|
+
param: plan2.param,
|
|
1339
|
+
executor: (_0, _1) => __async(this, [_0, _1], function* (taskParam, { element }) {
|
|
1340
|
+
if (element) {
|
|
1341
|
+
yield this.page.clearInput(element);
|
|
1342
|
+
if (taskParam.value === "") {
|
|
1343
|
+
return;
|
|
1344
|
+
}
|
|
1345
|
+
yield this.page.keyboard.type(taskParam.value);
|
|
1306
1346
|
}
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
}
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
}
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
}
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
}
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
}
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
}
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
)
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
}
|
|
1407
|
-
|
|
1408
|
-
}
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
return
|
|
1347
|
+
})
|
|
1348
|
+
};
|
|
1349
|
+
return taskActionInput;
|
|
1350
|
+
}
|
|
1351
|
+
if (plan2.type === "KeyboardPress") {
|
|
1352
|
+
const taskActionKeyboardPress = {
|
|
1353
|
+
type: "Action",
|
|
1354
|
+
subType: "KeyboardPress",
|
|
1355
|
+
param: plan2.param,
|
|
1356
|
+
executor: (taskParam) => __async(this, null, function* () {
|
|
1357
|
+
(0, import_node_assert2.default)(taskParam.value, "No key to press");
|
|
1358
|
+
yield this.page.keyboard.press(taskParam.value);
|
|
1359
|
+
})
|
|
1360
|
+
};
|
|
1361
|
+
return taskActionKeyboardPress;
|
|
1362
|
+
}
|
|
1363
|
+
if (plan2.type === "Tap") {
|
|
1364
|
+
const taskActionTap = {
|
|
1365
|
+
type: "Action",
|
|
1366
|
+
subType: "Tap",
|
|
1367
|
+
executor: (_0, _1) => __async(this, [_0, _1], function* (param, { element }) {
|
|
1368
|
+
(0, import_node_assert2.default)(element, "Element not found, cannot tap");
|
|
1369
|
+
yield this.page.mouse.click(
|
|
1370
|
+
element.center[0],
|
|
1371
|
+
element.center[1]
|
|
1372
|
+
);
|
|
1373
|
+
})
|
|
1374
|
+
};
|
|
1375
|
+
return taskActionTap;
|
|
1376
|
+
}
|
|
1377
|
+
if (plan2.type === "Hover") {
|
|
1378
|
+
const taskActionHover = {
|
|
1379
|
+
type: "Action",
|
|
1380
|
+
subType: "Hover",
|
|
1381
|
+
executor: (_0, _1) => __async(this, [_0, _1], function* (param, { element }) {
|
|
1382
|
+
(0, import_node_assert2.default)(element, "Element not found, cannot hover");
|
|
1383
|
+
yield this.page.mouse.move(
|
|
1384
|
+
element.center[0],
|
|
1385
|
+
element.center[1]
|
|
1386
|
+
);
|
|
1387
|
+
})
|
|
1388
|
+
};
|
|
1389
|
+
return taskActionHover;
|
|
1390
|
+
}
|
|
1391
|
+
if (plan2.type === "Scroll") {
|
|
1392
|
+
const taskActionScroll = {
|
|
1393
|
+
type: "Action",
|
|
1394
|
+
subType: "Scroll",
|
|
1395
|
+
param: plan2.param,
|
|
1396
|
+
executor: (taskParam) => __async(this, null, function* () {
|
|
1397
|
+
const scrollToEventName = taskParam.scrollType;
|
|
1398
|
+
switch (scrollToEventName) {
|
|
1399
|
+
case "scrollUntilTop":
|
|
1400
|
+
yield this.page.scrollUntilTop();
|
|
1401
|
+
break;
|
|
1402
|
+
case "scrollUntilBottom":
|
|
1403
|
+
yield this.page.scrollUntilBottom();
|
|
1404
|
+
break;
|
|
1405
|
+
case "scrollUpOneScreen":
|
|
1406
|
+
yield this.page.scrollUpOneScreen();
|
|
1407
|
+
break;
|
|
1408
|
+
case "scrollDownOneScreen":
|
|
1409
|
+
yield this.page.scrollDownOneScreen();
|
|
1410
|
+
break;
|
|
1411
|
+
default:
|
|
1412
|
+
console.error(
|
|
1413
|
+
"Unknown scroll event type:",
|
|
1414
|
+
scrollToEventName
|
|
1415
|
+
);
|
|
1416
|
+
}
|
|
1417
|
+
})
|
|
1418
|
+
};
|
|
1419
|
+
return taskActionScroll;
|
|
1420
|
+
}
|
|
1421
|
+
if (plan2.type === "Sleep") {
|
|
1422
|
+
const taskActionSleep = {
|
|
1423
|
+
type: "Action",
|
|
1424
|
+
subType: "Sleep",
|
|
1425
|
+
param: plan2.param,
|
|
1426
|
+
executor: (taskParam) => __async(this, null, function* () {
|
|
1427
|
+
yield (0, import_utils5.sleep)(taskParam.timeMs || 3e3);
|
|
1428
|
+
})
|
|
1429
|
+
};
|
|
1430
|
+
return taskActionSleep;
|
|
1431
|
+
}
|
|
1432
|
+
if (plan2.type === "Error") {
|
|
1433
|
+
const taskActionError = {
|
|
1434
|
+
type: "Action",
|
|
1435
|
+
subType: "Error",
|
|
1436
|
+
param: plan2.param,
|
|
1437
|
+
executor: (taskParam) => __async(this, null, function* () {
|
|
1438
|
+
(0, import_node_assert2.default)(
|
|
1439
|
+
taskParam.thought,
|
|
1440
|
+
"An error occurred, but no thought provided"
|
|
1441
|
+
);
|
|
1442
|
+
throw new Error(taskParam.thought);
|
|
1443
|
+
})
|
|
1444
|
+
};
|
|
1445
|
+
return taskActionError;
|
|
1446
|
+
}
|
|
1447
|
+
throw new Error(`Unknown or Unsupported task type: ${plan2.type}`);
|
|
1448
|
+
}).map((task) => {
|
|
1449
|
+
return this.wrapExecutorWithScreenshot(task);
|
|
1450
|
+
});
|
|
1451
|
+
return tasks;
|
|
1412
1452
|
});
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1453
|
+
}
|
|
1454
|
+
action(userPrompt) {
|
|
1455
|
+
return __async(this, null, function* () {
|
|
1456
|
+
const taskExecutor = new import_core.Executor(userPrompt);
|
|
1457
|
+
const cacheGroup = this.taskCache.getCacheGroupByPrompt(userPrompt);
|
|
1458
|
+
let plans = [];
|
|
1459
|
+
const planningTask = {
|
|
1460
|
+
type: "Planning",
|
|
1461
|
+
param: {
|
|
1462
|
+
userPrompt
|
|
1463
|
+
},
|
|
1464
|
+
executor: (param) => __async(this, null, function* () {
|
|
1465
|
+
const pageContext = yield this.insight.contextRetrieverFn();
|
|
1466
|
+
let planResult;
|
|
1467
|
+
const planCache = cacheGroup.readCache(pageContext, "plan", userPrompt);
|
|
1468
|
+
if (planCache) {
|
|
1469
|
+
planResult = planCache;
|
|
1470
|
+
} else {
|
|
1471
|
+
planResult = yield (0, import_core.plan)(param.userPrompt, {
|
|
1472
|
+
context: pageContext
|
|
1473
|
+
});
|
|
1474
|
+
}
|
|
1475
|
+
(0, import_node_assert2.default)(planResult.plans.length > 0, "No plans found");
|
|
1476
|
+
plans = planResult.plans;
|
|
1477
|
+
cacheGroup.saveCache({
|
|
1478
|
+
type: "plan",
|
|
1479
|
+
pageContext: {
|
|
1480
|
+
url: pageContext.url,
|
|
1481
|
+
size: pageContext.size
|
|
1482
|
+
},
|
|
1483
|
+
prompt: userPrompt,
|
|
1484
|
+
response: planResult
|
|
1433
1485
|
});
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
});
|
|
1486
|
+
return {
|
|
1487
|
+
output: planResult,
|
|
1488
|
+
cache: {
|
|
1489
|
+
hit: Boolean(planCache)
|
|
1490
|
+
}
|
|
1491
|
+
};
|
|
1492
|
+
})
|
|
1493
|
+
};
|
|
1494
|
+
yield taskExecutor.append(this.wrapExecutorWithScreenshot(planningTask));
|
|
1495
|
+
let output = yield taskExecutor.flush();
|
|
1496
|
+
if (taskExecutor.isInErrorState()) {
|
|
1446
1497
|
return {
|
|
1447
|
-
output
|
|
1448
|
-
|
|
1449
|
-
hit: Boolean(planCache)
|
|
1450
|
-
}
|
|
1498
|
+
output,
|
|
1499
|
+
executor: taskExecutor
|
|
1451
1500
|
};
|
|
1452
1501
|
}
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
if (taskExecutor.isInErrorState()) {
|
|
1502
|
+
const executables = yield this.convertPlanToExecutable(plans, cacheGroup);
|
|
1503
|
+
yield taskExecutor.append(executables);
|
|
1504
|
+
output = yield taskExecutor.flush();
|
|
1457
1505
|
return {
|
|
1458
1506
|
output,
|
|
1459
1507
|
executor: taskExecutor
|
|
1460
1508
|
};
|
|
1461
|
-
}
|
|
1462
|
-
const executables = await this.convertPlanToExecutable(plans, cacheGroup);
|
|
1463
|
-
await taskExecutor.append(executables);
|
|
1464
|
-
output = await taskExecutor.flush();
|
|
1465
|
-
return {
|
|
1466
|
-
output,
|
|
1467
|
-
executor: taskExecutor
|
|
1468
|
-
};
|
|
1469
|
-
}
|
|
1470
|
-
async query(demand) {
|
|
1471
|
-
const description = typeof demand === "string" ? demand : JSON.stringify(demand);
|
|
1472
|
-
const taskExecutor = new import_core.Executor(description);
|
|
1473
|
-
const queryTask = {
|
|
1474
|
-
type: "Insight",
|
|
1475
|
-
subType: "Query",
|
|
1476
|
-
param: {
|
|
1477
|
-
dataDemand: demand
|
|
1478
|
-
},
|
|
1479
|
-
executor: async (param) => {
|
|
1480
|
-
let insightDump;
|
|
1481
|
-
const dumpCollector = (dump) => {
|
|
1482
|
-
insightDump = dump;
|
|
1483
|
-
};
|
|
1484
|
-
this.insight.onceDumpUpdatedFn = dumpCollector;
|
|
1485
|
-
const data = await this.insight.extract(param.dataDemand);
|
|
1486
|
-
return {
|
|
1487
|
-
output: data,
|
|
1488
|
-
log: { dump: insightDump }
|
|
1489
|
-
};
|
|
1490
|
-
}
|
|
1491
|
-
};
|
|
1492
|
-
await taskExecutor.append(this.wrapExecutorWithScreenshot(queryTask));
|
|
1493
|
-
const output = await taskExecutor.flush();
|
|
1494
|
-
return {
|
|
1495
|
-
output,
|
|
1496
|
-
executor: taskExecutor
|
|
1497
|
-
};
|
|
1509
|
+
});
|
|
1498
1510
|
}
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1511
|
+
query(demand) {
|
|
1512
|
+
return __async(this, null, function* () {
|
|
1513
|
+
const description = typeof demand === "string" ? demand : JSON.stringify(demand);
|
|
1514
|
+
const taskExecutor = new import_core.Executor(description);
|
|
1515
|
+
const queryTask = {
|
|
1516
|
+
type: "Insight",
|
|
1517
|
+
subType: "Query",
|
|
1518
|
+
param: {
|
|
1519
|
+
dataDemand: demand
|
|
1520
|
+
},
|
|
1521
|
+
executor: (param) => __async(this, null, function* () {
|
|
1522
|
+
let insightDump;
|
|
1523
|
+
const dumpCollector = (dump) => {
|
|
1524
|
+
insightDump = dump;
|
|
1525
|
+
};
|
|
1526
|
+
this.insight.onceDumpUpdatedFn = dumpCollector;
|
|
1527
|
+
const data = yield this.insight.extract(param.dataDemand);
|
|
1528
|
+
return {
|
|
1529
|
+
output: data,
|
|
1530
|
+
log: { dump: insightDump }
|
|
1531
|
+
};
|
|
1532
|
+
})
|
|
1533
|
+
};
|
|
1534
|
+
yield taskExecutor.append(this.wrapExecutorWithScreenshot(queryTask));
|
|
1535
|
+
const output = yield taskExecutor.flush();
|
|
1536
|
+
return {
|
|
1537
|
+
output,
|
|
1538
|
+
executor: taskExecutor
|
|
1539
|
+
};
|
|
1540
|
+
});
|
|
1515
1541
|
}
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
(0, import_node_assert2.default)(checkIntervalMs, "No checkIntervalMs for waitFor");
|
|
1523
|
-
const overallStartTime = Date.now();
|
|
1524
|
-
let startTime = Date.now();
|
|
1525
|
-
let errorThought = "";
|
|
1526
|
-
while (Date.now() - overallStartTime < timeoutMs) {
|
|
1527
|
-
startTime = Date.now();
|
|
1528
|
-
const assertPlan = {
|
|
1529
|
-
type: "AssertWithoutThrow",
|
|
1542
|
+
assert(assertion) {
|
|
1543
|
+
return __async(this, null, function* () {
|
|
1544
|
+
const description = `assert: ${assertion}`;
|
|
1545
|
+
const taskExecutor = new import_core.Executor(description);
|
|
1546
|
+
const assertionPlan = {
|
|
1547
|
+
type: "Assert",
|
|
1530
1548
|
param: {
|
|
1531
1549
|
assertion
|
|
1532
1550
|
}
|
|
1533
1551
|
};
|
|
1534
|
-
const assertTask =
|
|
1535
|
-
|
|
1536
|
-
const output =
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1552
|
+
const assertTask = yield this.convertPlanToExecutable([assertionPlan]);
|
|
1553
|
+
yield taskExecutor.append(this.wrapExecutorWithScreenshot(assertTask[0]));
|
|
1554
|
+
const output = yield taskExecutor.flush();
|
|
1555
|
+
return {
|
|
1556
|
+
output,
|
|
1557
|
+
executor: taskExecutor
|
|
1558
|
+
};
|
|
1559
|
+
});
|
|
1560
|
+
}
|
|
1561
|
+
waitFor(assertion, opt) {
|
|
1562
|
+
return __async(this, null, function* () {
|
|
1563
|
+
const description = `waitFor: ${assertion}`;
|
|
1564
|
+
const taskExecutor = new import_core.Executor(description);
|
|
1565
|
+
const { timeoutMs, checkIntervalMs } = opt;
|
|
1566
|
+
(0, import_node_assert2.default)(assertion, "No assertion for waitFor");
|
|
1567
|
+
(0, import_node_assert2.default)(timeoutMs, "No timeoutMs for waitFor");
|
|
1568
|
+
(0, import_node_assert2.default)(checkIntervalMs, "No checkIntervalMs for waitFor");
|
|
1569
|
+
const overallStartTime = Date.now();
|
|
1570
|
+
let startTime = Date.now();
|
|
1571
|
+
let errorThought = "";
|
|
1572
|
+
while (Date.now() - overallStartTime < timeoutMs) {
|
|
1573
|
+
startTime = Date.now();
|
|
1574
|
+
const assertPlan = {
|
|
1575
|
+
type: "AssertWithoutThrow",
|
|
1549
1576
|
param: {
|
|
1550
|
-
|
|
1577
|
+
assertion
|
|
1551
1578
|
}
|
|
1552
1579
|
};
|
|
1553
|
-
const
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
)
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1580
|
+
const assertTask = yield this.convertPlanToExecutable([assertPlan]);
|
|
1581
|
+
yield taskExecutor.append(this.wrapExecutorWithScreenshot(assertTask[0]));
|
|
1582
|
+
const output = yield taskExecutor.flush();
|
|
1583
|
+
if (output == null ? void 0 : output.pass) {
|
|
1584
|
+
return {
|
|
1585
|
+
output: void 0,
|
|
1586
|
+
executor: taskExecutor
|
|
1587
|
+
};
|
|
1588
|
+
}
|
|
1589
|
+
errorThought = (output == null ? void 0 : output.thought) || "unknown error";
|
|
1590
|
+
const now = Date.now();
|
|
1591
|
+
if (now - startTime < checkIntervalMs) {
|
|
1592
|
+
const timeRemaining = checkIntervalMs - (now - startTime);
|
|
1593
|
+
const sleepPlan = {
|
|
1594
|
+
type: "Sleep",
|
|
1595
|
+
param: {
|
|
1596
|
+
timeMs: timeRemaining
|
|
1597
|
+
}
|
|
1598
|
+
};
|
|
1599
|
+
const sleepTask = yield this.convertPlanToExecutable([sleepPlan]);
|
|
1600
|
+
yield taskExecutor.append(
|
|
1601
|
+
this.wrapExecutorWithScreenshot(sleepTask[0])
|
|
1602
|
+
);
|
|
1603
|
+
yield taskExecutor.flush();
|
|
1604
|
+
}
|
|
1564
1605
|
}
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1606
|
+
const errorPlan = {
|
|
1607
|
+
type: "Error",
|
|
1608
|
+
param: {
|
|
1609
|
+
thought: `waitFor timeout: ${errorThought}`
|
|
1610
|
+
}
|
|
1611
|
+
};
|
|
1612
|
+
const errorTask = yield this.convertPlanToExecutable([errorPlan]);
|
|
1613
|
+
yield taskExecutor.append(errorTask[0]);
|
|
1614
|
+
yield taskExecutor.flush();
|
|
1615
|
+
return {
|
|
1616
|
+
output: void 0,
|
|
1617
|
+
executor: taskExecutor
|
|
1618
|
+
};
|
|
1619
|
+
});
|
|
1573
1620
|
}
|
|
1574
1621
|
};
|
|
1575
1622
|
|
|
@@ -1603,83 +1650,94 @@ var PageAgent = class {
|
|
|
1603
1650
|
dumpDataString() {
|
|
1604
1651
|
this.dump.groupName = this.opts.groupName;
|
|
1605
1652
|
this.dump.groupDescription = this.opts.groupDescription;
|
|
1606
|
-
return (0,
|
|
1653
|
+
return (0, import_utils7.stringifyDumpData)(this.dump);
|
|
1607
1654
|
}
|
|
1608
1655
|
writeOutActionDumps() {
|
|
1609
1656
|
const { generateReport, autoPrintReportMsg } = this.opts;
|
|
1610
|
-
this.reportFile = (0,
|
|
1657
|
+
this.reportFile = (0, import_utils7.writeLogFile)({
|
|
1611
1658
|
fileName: this.reportFileName,
|
|
1612
|
-
fileExt:
|
|
1659
|
+
fileExt: import_utils7.groupedActionDumpFileExt,
|
|
1613
1660
|
fileContent: this.dumpDataString(),
|
|
1614
1661
|
type: "dump",
|
|
1615
1662
|
generateReport
|
|
1616
1663
|
});
|
|
1617
|
-
if (generateReport && autoPrintReportMsg) {
|
|
1664
|
+
if (generateReport && autoPrintReportMsg && this.reportFile) {
|
|
1618
1665
|
printReportMsg(this.reportFile);
|
|
1619
1666
|
}
|
|
1620
1667
|
}
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1668
|
+
aiAction(taskPrompt) {
|
|
1669
|
+
return __async(this, null, function* () {
|
|
1670
|
+
const { executor } = yield this.taskExecutor.action(taskPrompt);
|
|
1671
|
+
this.appendExecutionDump(executor.dump());
|
|
1672
|
+
this.writeOutActionDumps();
|
|
1673
|
+
if (executor.isInErrorState()) {
|
|
1674
|
+
const errorTask = executor.latestErrorTask();
|
|
1675
|
+
throw new Error(`${errorTask == null ? void 0 : errorTask.error}
|
|
1628
1676
|
${errorTask == null ? void 0 : errorTask.errorStack}`);
|
|
1629
|
-
|
|
1677
|
+
}
|
|
1678
|
+
});
|
|
1630
1679
|
}
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1680
|
+
aiQuery(demand) {
|
|
1681
|
+
return __async(this, null, function* () {
|
|
1682
|
+
const { output, executor } = yield this.taskExecutor.query(demand);
|
|
1683
|
+
this.appendExecutionDump(executor.dump());
|
|
1684
|
+
this.writeOutActionDumps();
|
|
1685
|
+
if (executor.isInErrorState()) {
|
|
1686
|
+
const errorTask = executor.latestErrorTask();
|
|
1687
|
+
throw new Error(`${errorTask == null ? void 0 : errorTask.error}
|
|
1638
1688
|
${errorTask == null ? void 0 : errorTask.errorStack}`);
|
|
1639
|
-
|
|
1640
|
-
return output;
|
|
1641
|
-
}
|
|
1642
|
-
async aiAssert(assertion, msg, opt) {
|
|
1643
|
-
const { output, executor } = await this.taskExecutor.assert(assertion);
|
|
1644
|
-
this.appendExecutionDump(executor.dump());
|
|
1645
|
-
this.writeOutActionDumps();
|
|
1646
|
-
if (opt == null ? void 0 : opt.keepRawResponse) {
|
|
1689
|
+
}
|
|
1647
1690
|
return output;
|
|
1648
|
-
}
|
|
1649
|
-
if (!(output == null ? void 0 : output.pass)) {
|
|
1650
|
-
const errMsg = msg || `Assertion failed: ${assertion}`;
|
|
1651
|
-
const reasonMsg = `Reason: ${(output == null ? void 0 : output.thought) || "(no_reason)"}`;
|
|
1652
|
-
throw new Error(`${errMsg}
|
|
1653
|
-
${reasonMsg}`);
|
|
1654
|
-
}
|
|
1691
|
+
});
|
|
1655
1692
|
}
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1693
|
+
aiAssert(assertion, msg, opt) {
|
|
1694
|
+
return __async(this, null, function* () {
|
|
1695
|
+
var _a;
|
|
1696
|
+
const { output, executor } = yield this.taskExecutor.assert(assertion);
|
|
1697
|
+
this.appendExecutionDump(executor.dump());
|
|
1698
|
+
this.writeOutActionDumps();
|
|
1699
|
+
if (opt == null ? void 0 : opt.keepRawResponse) {
|
|
1700
|
+
return output;
|
|
1701
|
+
}
|
|
1702
|
+
if (!(output == null ? void 0 : output.pass)) {
|
|
1703
|
+
const errMsg = msg || `Assertion failed: ${assertion}`;
|
|
1704
|
+
const reasonMsg = `Reason: ${(output == null ? void 0 : output.thought) || ((_a = executor.latestErrorTask()) == null ? void 0 : _a.error) || "(no_reason)"}`;
|
|
1705
|
+
throw new Error(`${errMsg}
|
|
1706
|
+
${reasonMsg}`);
|
|
1707
|
+
}
|
|
1661
1708
|
});
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
const
|
|
1666
|
-
|
|
1709
|
+
}
|
|
1710
|
+
aiWaitFor(assertion, opt) {
|
|
1711
|
+
return __async(this, null, function* () {
|
|
1712
|
+
const { executor } = yield this.taskExecutor.waitFor(assertion, {
|
|
1713
|
+
timeoutMs: (opt == null ? void 0 : opt.timeoutMs) || 15 * 1e3,
|
|
1714
|
+
checkIntervalMs: (opt == null ? void 0 : opt.checkIntervalMs) || 3 * 1e3,
|
|
1715
|
+
assertion
|
|
1716
|
+
});
|
|
1717
|
+
this.appendExecutionDump(executor.dump());
|
|
1718
|
+
this.writeOutActionDumps();
|
|
1719
|
+
if (executor.isInErrorState()) {
|
|
1720
|
+
const errorTask = executor.latestErrorTask();
|
|
1721
|
+
throw new Error(`${errorTask == null ? void 0 : errorTask.error}
|
|
1667
1722
|
${errorTask == null ? void 0 : errorTask.errorStack}`);
|
|
1668
|
-
|
|
1723
|
+
}
|
|
1724
|
+
});
|
|
1669
1725
|
}
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1726
|
+
ai(taskPrompt, type = "action") {
|
|
1727
|
+
return __async(this, null, function* () {
|
|
1728
|
+
if (type === "action") {
|
|
1729
|
+
return this.aiAction(taskPrompt);
|
|
1730
|
+
}
|
|
1731
|
+
if (type === "query") {
|
|
1732
|
+
return this.aiQuery(taskPrompt);
|
|
1733
|
+
}
|
|
1734
|
+
if (type === "assert") {
|
|
1735
|
+
return this.aiAssert(taskPrompt);
|
|
1736
|
+
}
|
|
1737
|
+
throw new Error(
|
|
1738
|
+
`Unknown type: ${type}, only support 'action', 'query', 'assert'`
|
|
1739
|
+
);
|
|
1740
|
+
});
|
|
1683
1741
|
}
|
|
1684
1742
|
};
|
|
1685
1743
|
|
|
@@ -1708,7 +1766,7 @@ var PlaywrightAiFixture = () => {
|
|
|
1708
1766
|
const agentForPage = (page, testInfo) => {
|
|
1709
1767
|
let idForPage = page[midsceneAgentKeyId];
|
|
1710
1768
|
if (!idForPage) {
|
|
1711
|
-
idForPage = (0,
|
|
1769
|
+
idForPage = (0, import_node_crypto.randomUUID)();
|
|
1712
1770
|
page[midsceneAgentKeyId] = idForPage;
|
|
1713
1771
|
const { testId } = testInfo;
|
|
1714
1772
|
const { taskFile, taskTitle } = groupAndCaseForTest(testInfo);
|
|
@@ -1737,70 +1795,94 @@ var PlaywrightAiFixture = () => {
|
|
|
1737
1795
|
}
|
|
1738
1796
|
};
|
|
1739
1797
|
return {
|
|
1740
|
-
ai:
|
|
1798
|
+
ai: (_0, _1, _2) => __async(void 0, [_0, _1, _2], function* ({ page }, use, testInfo) {
|
|
1741
1799
|
const agent = agentForPage(page, testInfo);
|
|
1742
|
-
|
|
1743
|
-
|
|
1800
|
+
yield use(
|
|
1801
|
+
(taskPrompt, opts) => __async(void 0, null, function* () {
|
|
1744
1802
|
return new Promise((resolve, reject) => {
|
|
1745
|
-
import_test.test.step(`ai - ${taskPrompt}`,
|
|
1746
|
-
|
|
1803
|
+
import_test.test.step(`ai - ${taskPrompt}`, () => __async(void 0, null, function* () {
|
|
1804
|
+
yield waitForNetworkIdle(page);
|
|
1747
1805
|
const actionType = (opts == null ? void 0 : opts.type) || "action";
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1806
|
+
try {
|
|
1807
|
+
const result = yield agent.ai(taskPrompt, actionType);
|
|
1808
|
+
resolve(result);
|
|
1809
|
+
} catch (error) {
|
|
1810
|
+
reject(error);
|
|
1811
|
+
}
|
|
1812
|
+
}));
|
|
1751
1813
|
});
|
|
1752
|
-
}
|
|
1814
|
+
})
|
|
1753
1815
|
);
|
|
1754
1816
|
updateDumpAnnotation(testInfo, agent.dumpDataString());
|
|
1755
|
-
},
|
|
1756
|
-
aiAction:
|
|
1817
|
+
}),
|
|
1818
|
+
aiAction: (_0, _1, _2) => __async(void 0, [_0, _1, _2], function* ({ page }, use, testInfo) {
|
|
1757
1819
|
const agent = agentForPage(page, testInfo);
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1820
|
+
yield use((taskPrompt) => __async(void 0, null, function* () {
|
|
1821
|
+
return new Promise((resolve, reject) => {
|
|
1822
|
+
import_test.test.step(`aiAction - ${taskPrompt}`, () => __async(void 0, null, function* () {
|
|
1823
|
+
yield waitForNetworkIdle(page);
|
|
1824
|
+
try {
|
|
1825
|
+
const result = yield agent.aiAction(taskPrompt);
|
|
1826
|
+
resolve(result);
|
|
1827
|
+
} catch (error) {
|
|
1828
|
+
reject(error);
|
|
1829
|
+
}
|
|
1830
|
+
}));
|
|
1762
1831
|
});
|
|
1763
|
-
});
|
|
1832
|
+
}));
|
|
1764
1833
|
updateDumpAnnotation(testInfo, agent.dumpDataString());
|
|
1765
|
-
},
|
|
1766
|
-
aiQuery:
|
|
1834
|
+
}),
|
|
1835
|
+
aiQuery: (_0, _1, _2) => __async(void 0, [_0, _1, _2], function* ({ page }, use, testInfo) {
|
|
1767
1836
|
const agent = agentForPage(page, testInfo);
|
|
1768
|
-
|
|
1837
|
+
yield use((demand) => __async(void 0, null, function* () {
|
|
1769
1838
|
return new Promise((resolve, reject) => {
|
|
1770
|
-
import_test.test.step(`aiQuery - ${JSON.stringify(demand)}`,
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1839
|
+
import_test.test.step(`aiQuery - ${JSON.stringify(demand)}`, () => __async(void 0, null, function* () {
|
|
1840
|
+
yield waitForNetworkIdle(page);
|
|
1841
|
+
try {
|
|
1842
|
+
const result = yield agent.aiQuery(demand);
|
|
1843
|
+
resolve(result);
|
|
1844
|
+
} catch (error) {
|
|
1845
|
+
reject(error);
|
|
1846
|
+
}
|
|
1847
|
+
}));
|
|
1775
1848
|
});
|
|
1776
|
-
});
|
|
1849
|
+
}));
|
|
1777
1850
|
updateDumpAnnotation(testInfo, agent.dumpDataString());
|
|
1778
|
-
},
|
|
1779
|
-
aiAssert:
|
|
1851
|
+
}),
|
|
1852
|
+
aiAssert: (_0, _1, _2) => __async(void 0, [_0, _1, _2], function* ({ page }, use, testInfo) {
|
|
1780
1853
|
const agent = agentForPage(page, testInfo);
|
|
1781
|
-
|
|
1854
|
+
yield use((assertion, errorMsg) => __async(void 0, null, function* () {
|
|
1782
1855
|
return new Promise((resolve, reject) => {
|
|
1783
|
-
import_test.test.step(`aiAssert - ${assertion}`,
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1856
|
+
import_test.test.step(`aiAssert - ${assertion}`, () => __async(void 0, null, function* () {
|
|
1857
|
+
yield waitForNetworkIdle(page);
|
|
1858
|
+
try {
|
|
1859
|
+
yield agent.aiAssert(assertion, errorMsg);
|
|
1860
|
+
resolve(null);
|
|
1861
|
+
} catch (error) {
|
|
1862
|
+
reject(error);
|
|
1863
|
+
}
|
|
1864
|
+
}));
|
|
1788
1865
|
});
|
|
1789
|
-
});
|
|
1866
|
+
}));
|
|
1790
1867
|
updateDumpAnnotation(testInfo, agent.dumpDataString());
|
|
1791
|
-
},
|
|
1792
|
-
aiWaitFor:
|
|
1868
|
+
}),
|
|
1869
|
+
aiWaitFor: (_0, _1, _2) => __async(void 0, [_0, _1, _2], function* ({ page }, use, testInfo) {
|
|
1793
1870
|
const agent = agentForPage(page, testInfo);
|
|
1794
|
-
|
|
1871
|
+
yield use((assertion, opt) => __async(void 0, null, function* () {
|
|
1795
1872
|
return new Promise((resolve, reject) => {
|
|
1796
|
-
import_test.test.step(`aiWaitFor - ${assertion}`,
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1873
|
+
import_test.test.step(`aiWaitFor - ${assertion}`, () => __async(void 0, null, function* () {
|
|
1874
|
+
yield waitForNetworkIdle(page);
|
|
1875
|
+
try {
|
|
1876
|
+
yield agent.aiWaitFor(assertion, opt);
|
|
1877
|
+
resolve(null);
|
|
1878
|
+
} catch (error) {
|
|
1879
|
+
reject(error);
|
|
1880
|
+
}
|
|
1881
|
+
}));
|
|
1800
1882
|
});
|
|
1801
|
-
});
|
|
1883
|
+
}));
|
|
1802
1884
|
updateDumpAnnotation(testInfo, agent.dumpDataString());
|
|
1803
|
-
}
|
|
1885
|
+
})
|
|
1804
1886
|
};
|
|
1805
1887
|
};
|
|
1806
1888
|
function waitForNetworkIdle(page) {
|
|
@@ -1813,87 +1895,113 @@ function waitForNetworkIdle(page) {
|
|
|
1813
1895
|
|
|
1814
1896
|
// src/puppeteer/base-page.ts
|
|
1815
1897
|
var import_node_fs3 = require("fs");
|
|
1816
|
-
var
|
|
1817
|
-
var
|
|
1898
|
+
var import_utils9 = require("@midscene/core/utils");
|
|
1899
|
+
var import_img3 = require("@midscene/shared/img");
|
|
1818
1900
|
var Page = class {
|
|
1819
1901
|
evaluate(pageFunction, arg) {
|
|
1820
1902
|
if (this.pageType === "puppeteer") {
|
|
1821
|
-
return this.
|
|
1903
|
+
return this.underlyingPage.evaluate(pageFunction, arg);
|
|
1822
1904
|
}
|
|
1823
|
-
return this.
|
|
1905
|
+
return this.underlyingPage.evaluate(pageFunction, arg);
|
|
1824
1906
|
}
|
|
1825
|
-
constructor(
|
|
1826
|
-
this.
|
|
1907
|
+
constructor(underlyingPage, pageType) {
|
|
1908
|
+
this.underlyingPage = underlyingPage;
|
|
1827
1909
|
this.pageType = pageType;
|
|
1828
1910
|
}
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
async screenshot() {
|
|
1835
|
-
const viewportSize = await this.evaluate(() => {
|
|
1836
|
-
return {
|
|
1837
|
-
width: document.documentElement.clientWidth,
|
|
1838
|
-
height: document.documentElement.clientHeight,
|
|
1839
|
-
deviceScaleFactor: window.devicePixelRatio
|
|
1840
|
-
};
|
|
1841
|
-
});
|
|
1842
|
-
const path3 = (0, import_utils7.getTmpFile)("png");
|
|
1843
|
-
await this.page.screenshot({
|
|
1844
|
-
path: path3,
|
|
1845
|
-
type: "png"
|
|
1911
|
+
getElementInfos() {
|
|
1912
|
+
return __async(this, null, function* () {
|
|
1913
|
+
const scripts = yield getExtraReturnLogic();
|
|
1914
|
+
const captureElementSnapshot = yield this.evaluate(scripts);
|
|
1915
|
+
return captureElementSnapshot;
|
|
1846
1916
|
});
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1917
|
+
}
|
|
1918
|
+
screenshotBase64() {
|
|
1919
|
+
return __async(this, null, function* () {
|
|
1920
|
+
const viewportSize = yield this.evaluate(() => {
|
|
1921
|
+
return {
|
|
1922
|
+
width: document.documentElement.clientWidth,
|
|
1923
|
+
height: document.documentElement.clientHeight,
|
|
1924
|
+
deviceScaleFactor: window.devicePixelRatio
|
|
1925
|
+
};
|
|
1852
1926
|
});
|
|
1853
|
-
(0,
|
|
1854
|
-
|
|
1855
|
-
|
|
1927
|
+
const path3 = (0, import_utils9.getTmpFile)("png");
|
|
1928
|
+
yield this.underlyingPage.screenshot({
|
|
1929
|
+
path: path3,
|
|
1930
|
+
type: "png"
|
|
1931
|
+
});
|
|
1932
|
+
let buf;
|
|
1933
|
+
if (viewportSize.deviceScaleFactor > 1) {
|
|
1934
|
+
buf = yield (0, import_img3.resizeImg)((0, import_node_fs3.readFileSync)(path3), {
|
|
1935
|
+
width: viewportSize.width,
|
|
1936
|
+
height: viewportSize.height
|
|
1937
|
+
});
|
|
1938
|
+
(0, import_node_fs3.writeFileSync)(path3, buf);
|
|
1939
|
+
}
|
|
1940
|
+
return (0, import_img3.base64Encoded)(path3, true);
|
|
1941
|
+
});
|
|
1856
1942
|
}
|
|
1857
1943
|
url() {
|
|
1858
|
-
return this.
|
|
1944
|
+
return this.underlyingPage.url();
|
|
1859
1945
|
}
|
|
1860
1946
|
get mouse() {
|
|
1861
1947
|
return {
|
|
1862
|
-
click:
|
|
1863
|
-
|
|
1948
|
+
click: (x, y, options) => __async(this, null, function* () {
|
|
1949
|
+
return this.underlyingPage.mouse.click(x, y, {
|
|
1950
|
+
button: (options == null ? void 0 : options.button) || "left"
|
|
1951
|
+
});
|
|
1952
|
+
}),
|
|
1953
|
+
wheel: (deltaX, deltaY) => __async(this, null, function* () {
|
|
1864
1954
|
if (this.pageType === "puppeteer") {
|
|
1865
|
-
|
|
1955
|
+
yield this.underlyingPage.mouse.wheel({
|
|
1956
|
+
deltaX,
|
|
1957
|
+
deltaY
|
|
1958
|
+
});
|
|
1866
1959
|
} else if (this.pageType === "playwright") {
|
|
1867
|
-
|
|
1960
|
+
yield this.underlyingPage.mouse.wheel(
|
|
1961
|
+
deltaX,
|
|
1962
|
+
deltaY
|
|
1963
|
+
);
|
|
1868
1964
|
}
|
|
1869
|
-
},
|
|
1870
|
-
move:
|
|
1965
|
+
}),
|
|
1966
|
+
move: (x, y) => __async(this, null, function* () {
|
|
1967
|
+
return this.underlyingPage.mouse.move(x, y);
|
|
1968
|
+
})
|
|
1871
1969
|
};
|
|
1872
1970
|
}
|
|
1873
1971
|
get keyboard() {
|
|
1874
1972
|
return {
|
|
1875
|
-
type:
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1973
|
+
type: (text) => __async(this, null, function* () {
|
|
1974
|
+
return this.underlyingPage.keyboard.type(text);
|
|
1975
|
+
}),
|
|
1976
|
+
press: (key) => __async(this, null, function* () {
|
|
1977
|
+
return this.underlyingPage.keyboard.press(key);
|
|
1978
|
+
}),
|
|
1979
|
+
down: (key) => __async(this, null, function* () {
|
|
1980
|
+
return this.underlyingPage.keyboard.down(key);
|
|
1981
|
+
}),
|
|
1982
|
+
up: (key) => __async(this, null, function* () {
|
|
1983
|
+
return this.underlyingPage.keyboard.up(key);
|
|
1984
|
+
})
|
|
1879
1985
|
};
|
|
1880
1986
|
}
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1987
|
+
clearInput(element) {
|
|
1988
|
+
return __async(this, null, function* () {
|
|
1989
|
+
if (!element) {
|
|
1990
|
+
return;
|
|
1991
|
+
}
|
|
1992
|
+
yield this.mouse.click(element.center[0], element.center[1]);
|
|
1993
|
+
const isMac = process.platform === "darwin";
|
|
1994
|
+
if (isMac) {
|
|
1995
|
+
yield this.underlyingPage.keyboard.down("Meta");
|
|
1996
|
+
yield this.underlyingPage.keyboard.press("a");
|
|
1997
|
+
yield this.underlyingPage.keyboard.up("Meta");
|
|
1998
|
+
} else {
|
|
1999
|
+
yield this.underlyingPage.keyboard.down("Control");
|
|
2000
|
+
yield this.underlyingPage.keyboard.press("a");
|
|
2001
|
+
yield this.underlyingPage.keyboard.up("Control");
|
|
2002
|
+
}
|
|
2003
|
+
yield this.keyboard.press("Backspace");
|
|
2004
|
+
});
|
|
1897
2005
|
}
|
|
1898
2006
|
scrollUntilTop() {
|
|
1899
2007
|
return this.mouse.wheel(0, -9999999);
|
|
@@ -1901,15 +2009,19 @@ var Page = class {
|
|
|
1901
2009
|
scrollUntilBottom() {
|
|
1902
2010
|
return this.mouse.wheel(0, 9999999);
|
|
1903
2011
|
}
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
2012
|
+
scrollUpOneScreen() {
|
|
2013
|
+
return __async(this, null, function* () {
|
|
2014
|
+
const innerHeight = yield this.evaluate(() => window.innerHeight);
|
|
2015
|
+
const distance = innerHeight * 0.7;
|
|
2016
|
+
yield this.mouse.wheel(0, -distance);
|
|
2017
|
+
});
|
|
1908
2018
|
}
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
2019
|
+
scrollDownOneScreen() {
|
|
2020
|
+
return __async(this, null, function* () {
|
|
2021
|
+
const innerHeight = yield this.evaluate(() => window.innerHeight);
|
|
2022
|
+
const distance = innerHeight * 0.7;
|
|
2023
|
+
yield this.mouse.wheel(0, distance);
|
|
2024
|
+
});
|
|
1913
2025
|
}
|
|
1914
2026
|
};
|
|
1915
2027
|
|
|
@@ -1937,8 +2049,8 @@ var PuppeteerAgent = class extends PageAgent {
|
|
|
1937
2049
|
|
|
1938
2050
|
// src/appium/page.ts
|
|
1939
2051
|
var import_node_fs4 = __toESM(require("fs"));
|
|
1940
|
-
var
|
|
1941
|
-
var
|
|
2052
|
+
var import_utils11 = require("@midscene/core/utils");
|
|
2053
|
+
var import_img4 = require("@midscene/shared/img");
|
|
1942
2054
|
var import_xmldom = require("@xmldom/xmldom");
|
|
1943
2055
|
|
|
1944
2056
|
// src/extractor/web-extractor.ts
|
|
@@ -2133,26 +2245,30 @@ var Page2 = class {
|
|
|
2133
2245
|
this.pageType = "appium";
|
|
2134
2246
|
this.browser = browser;
|
|
2135
2247
|
}
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2248
|
+
getElementInfos() {
|
|
2249
|
+
return __async(this, null, function* () {
|
|
2250
|
+
const pageSource = yield this.browser.getPageSource();
|
|
2251
|
+
const { width, height } = yield this.browser.getWindowSize();
|
|
2252
|
+
const parser = new import_xmldom.DOMParser();
|
|
2253
|
+
const doc = parser.parseFromString(pageSource, "text/xml");
|
|
2254
|
+
const infos = extractTextWithPosition2(doc).filter(
|
|
2255
|
+
(element) => element.rect.height !== height && element.rect.width !== width && element.rect.left !== 0 && element.rect.top !== 0 && element.attributes.visible === "true"
|
|
2256
|
+
);
|
|
2257
|
+
return infos;
|
|
2258
|
+
});
|
|
2259
|
+
}
|
|
2260
|
+
screenshotBase64() {
|
|
2261
|
+
return __async(this, null, function* () {
|
|
2262
|
+
const { width, height } = yield this.browser.getWindowSize();
|
|
2263
|
+
const path3 = (0, import_utils11.getTmpFile)("png");
|
|
2264
|
+
const screenshotBuffer = yield this.browser.saveScreenshot(path3);
|
|
2265
|
+
const resizedScreenshotBuffer = yield (0, import_img4.resizeImg)(screenshotBuffer, {
|
|
2266
|
+
width,
|
|
2267
|
+
height
|
|
2268
|
+
});
|
|
2269
|
+
import_node_fs4.default.writeFileSync(path3, resizedScreenshotBuffer);
|
|
2270
|
+
return (0, import_img4.base64Encoded)(path3);
|
|
2153
2271
|
});
|
|
2154
|
-
import_node_fs4.default.writeFileSync(path3, resizedScreenshotBuffer);
|
|
2155
|
-
return path3;
|
|
2156
2272
|
}
|
|
2157
2273
|
get mouse() {
|
|
2158
2274
|
return {
|
|
@@ -2168,14 +2284,16 @@ var Page2 = class {
|
|
|
2168
2284
|
press: (key) => this.keyboardPress(key)
|
|
2169
2285
|
};
|
|
2170
2286
|
}
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2287
|
+
clearInput(element) {
|
|
2288
|
+
return __async(this, null, function* () {
|
|
2289
|
+
if (!element) {
|
|
2290
|
+
return;
|
|
2291
|
+
}
|
|
2292
|
+
const ele = yield this.browser.$(element.locator);
|
|
2293
|
+
const blank = " ";
|
|
2294
|
+
yield this.keyboardType(blank);
|
|
2295
|
+
yield ele.clearValue();
|
|
2296
|
+
});
|
|
2179
2297
|
}
|
|
2180
2298
|
url() {
|
|
2181
2299
|
var _a;
|
|
@@ -2191,182 +2309,207 @@ var Page2 = class {
|
|
|
2191
2309
|
return "";
|
|
2192
2310
|
}
|
|
2193
2311
|
// Scroll to top element
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2312
|
+
scrollUntilTop() {
|
|
2313
|
+
return __async(this, null, function* () {
|
|
2314
|
+
const { height } = yield this.browser.getWindowSize();
|
|
2315
|
+
yield this.mouseWheel(0, height, 100);
|
|
2316
|
+
});
|
|
2197
2317
|
}
|
|
2198
2318
|
// Scroll to bottom element
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2319
|
+
scrollUntilBottom() {
|
|
2320
|
+
return __async(this, null, function* () {
|
|
2321
|
+
const { height } = yield this.browser.getWindowSize();
|
|
2322
|
+
yield this.mouseWheel(0, -height, 100);
|
|
2323
|
+
});
|
|
2202
2324
|
}
|
|
2203
2325
|
// Scroll up one screen
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2326
|
+
scrollUpOneScreen() {
|
|
2327
|
+
return __async(this, null, function* () {
|
|
2328
|
+
const { height } = yield this.browser.getWindowSize();
|
|
2329
|
+
yield this.mouseWheel(0, height, 1e3);
|
|
2330
|
+
});
|
|
2207
2331
|
}
|
|
2208
2332
|
// Scroll down one screen
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
const actions = [];
|
|
2215
|
-
for (const char of text) {
|
|
2216
|
-
actions.push({ type: "keyDown", value: char });
|
|
2217
|
-
actions.push({ type: "keyUp", value: char });
|
|
2218
|
-
}
|
|
2219
|
-
if (!actions.length) {
|
|
2220
|
-
return;
|
|
2221
|
-
}
|
|
2222
|
-
await this.browser.performActions([
|
|
2223
|
-
{
|
|
2224
|
-
type: "key",
|
|
2225
|
-
id: "keyboard",
|
|
2226
|
-
actions
|
|
2227
|
-
}
|
|
2228
|
-
]);
|
|
2229
|
-
}
|
|
2230
|
-
async keyboardPress(key) {
|
|
2231
|
-
await this.browser.performActions([
|
|
2232
|
-
{
|
|
2233
|
-
type: "key",
|
|
2234
|
-
id: "keyboard",
|
|
2235
|
-
actions: [
|
|
2236
|
-
{ type: "keyDown", value: key },
|
|
2237
|
-
{ type: "keyUp", value: key }
|
|
2238
|
-
]
|
|
2239
|
-
}
|
|
2240
|
-
]);
|
|
2241
|
-
}
|
|
2242
|
-
async mouseClick(x, y, button = "left") {
|
|
2243
|
-
await this.mouseMove(x, y);
|
|
2244
|
-
await this.browser.performActions([
|
|
2245
|
-
{
|
|
2246
|
-
type: "pointer",
|
|
2247
|
-
id: "mouse",
|
|
2248
|
-
parameters: { pointerType: "mouse" },
|
|
2249
|
-
actions: [
|
|
2250
|
-
{ type: "pointerMove", duration: 0, x, y },
|
|
2251
|
-
{ type: "pointerDown", button: buttonToNumber(button) },
|
|
2252
|
-
{ type: "pause", duration: 100 },
|
|
2253
|
-
{ type: "pointerUp", button: buttonToNumber(button) }
|
|
2254
|
-
]
|
|
2255
|
-
}
|
|
2256
|
-
]);
|
|
2333
|
+
scrollDownOneScreen() {
|
|
2334
|
+
return __async(this, null, function* () {
|
|
2335
|
+
const { height } = yield this.browser.getWindowSize();
|
|
2336
|
+
yield this.mouseWheel(0, -height, 1e3);
|
|
2337
|
+
});
|
|
2257
2338
|
}
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
actions: [{ type: "pointerMove", duration: 0, x, y }]
|
|
2339
|
+
keyboardType(text) {
|
|
2340
|
+
return __async(this, null, function* () {
|
|
2341
|
+
const actions = [];
|
|
2342
|
+
for (const char of text) {
|
|
2343
|
+
actions.push({ type: "keyDown", value: char });
|
|
2344
|
+
actions.push({ type: "keyUp", value: char });
|
|
2265
2345
|
}
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
async mouseWheel(deltaX, deltaY, duration = 1e3) {
|
|
2269
|
-
const n = 4;
|
|
2270
|
-
const windowSize = await this.browser.getWindowSize();
|
|
2271
|
-
const startX = deltaX < 0 ? (n - 1) * (windowSize.width / n) : windowSize.width / n;
|
|
2272
|
-
const startY = deltaY < 0 ? (n - 1) * (windowSize.height / n) : windowSize.height / n;
|
|
2273
|
-
const maxNegativeDeltaX = startX;
|
|
2274
|
-
const maxPositiveDeltaX = (n - 1) * (windowSize.width / n);
|
|
2275
|
-
const maxNegativeDeltaY = startY;
|
|
2276
|
-
const maxPositiveDeltaY = (n - 1) * (windowSize.height / n);
|
|
2277
|
-
deltaX = Math.max(-maxNegativeDeltaX, Math.min(deltaX, maxPositiveDeltaX));
|
|
2278
|
-
deltaY = Math.max(-maxNegativeDeltaY, Math.min(deltaY, maxPositiveDeltaY));
|
|
2279
|
-
await this.browser.performActions([
|
|
2280
|
-
{
|
|
2281
|
-
type: "pointer",
|
|
2282
|
-
id: "finger1",
|
|
2283
|
-
parameters: { pointerType: "touch" },
|
|
2284
|
-
actions: [
|
|
2285
|
-
{ type: "pointerMove", duration: 0, x: startX, y: startY },
|
|
2286
|
-
{ type: "pointerDown", button: 0 },
|
|
2287
|
-
{ type: "pause", duration },
|
|
2288
|
-
{
|
|
2289
|
-
type: "pointerMove",
|
|
2290
|
-
duration,
|
|
2291
|
-
origin: "pointer",
|
|
2292
|
-
// Use 'pointer' as the starting point
|
|
2293
|
-
x: deltaX,
|
|
2294
|
-
// X offset relative to the starting point
|
|
2295
|
-
y: deltaY
|
|
2296
|
-
// Y offset relative to the starting point
|
|
2297
|
-
},
|
|
2298
|
-
{ type: "pointerUp", button: 0 }
|
|
2299
|
-
]
|
|
2346
|
+
if (!actions.length) {
|
|
2347
|
+
return;
|
|
2300
2348
|
}
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
async function generateExtractData(page, targetDir, saveImgType) {
|
|
2310
|
-
const file = await page.screenshot();
|
|
2311
|
-
const screenshotBuffer = (0, import_node_fs5.readFileSync)(file);
|
|
2312
|
-
const inputImgBase64 = screenshotBuffer.toString("base64");
|
|
2313
|
-
const {
|
|
2314
|
-
elementsPositionInfo,
|
|
2315
|
-
captureElementSnapshot,
|
|
2316
|
-
elementsPositionInfoWithoutText
|
|
2317
|
-
} = await getElementInfos(page);
|
|
2318
|
-
const inputImagePath = import_node_path3.default.join(targetDir, "input.png");
|
|
2319
|
-
const outputImagePath = import_node_path3.default.join(targetDir, "output.png");
|
|
2320
|
-
const outputWithoutTextImgPath = import_node_path3.default.join(
|
|
2321
|
-
targetDir,
|
|
2322
|
-
"output_without_text.png"
|
|
2323
|
-
);
|
|
2324
|
-
const resizeOutputImgPath = import_node_path3.default.join(targetDir, "resize-output.png");
|
|
2325
|
-
const snapshotJsonPath = import_node_path3.default.join(targetDir, "element-snapshot.json");
|
|
2326
|
-
const {
|
|
2327
|
-
compositeElementInfoImgBase64,
|
|
2328
|
-
compositeElementInfoImgWithoutTextBase64
|
|
2329
|
-
} = await (0, import_img6.processImageElementInfo)({
|
|
2330
|
-
elementsPositionInfo,
|
|
2331
|
-
elementsPositionInfoWithoutText,
|
|
2332
|
-
inputImgBase64
|
|
2333
|
-
});
|
|
2334
|
-
const resizeImgBase64 = await (0, import_img6.resizeImg)(inputImgBase64);
|
|
2335
|
-
const existingSnapshot = (0, import_node_fs5.existsSync)(snapshotJsonPath) ? JSON.parse((0, import_node_fs5.readFileSync)(snapshotJsonPath, "utf-8")) : null;
|
|
2336
|
-
if (existingSnapshot && JSON.stringify(existingSnapshot) === JSON.stringify(captureElementSnapshot)) {
|
|
2337
|
-
console.log("skip save snapshot for ", targetDir);
|
|
2338
|
-
return;
|
|
2339
|
-
}
|
|
2340
|
-
if (!(saveImgType == null ? void 0 : saveImgType.disableSnapshot)) {
|
|
2341
|
-
writeFileSyncWithDir(
|
|
2342
|
-
snapshotJsonPath,
|
|
2343
|
-
JSON.stringify(captureElementSnapshot, null, 2)
|
|
2344
|
-
);
|
|
2349
|
+
yield this.browser.performActions([
|
|
2350
|
+
{
|
|
2351
|
+
type: "key",
|
|
2352
|
+
id: "keyboard",
|
|
2353
|
+
actions
|
|
2354
|
+
}
|
|
2355
|
+
]);
|
|
2356
|
+
});
|
|
2345
2357
|
}
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2358
|
+
keyboardPress(key) {
|
|
2359
|
+
return __async(this, null, function* () {
|
|
2360
|
+
yield this.browser.performActions([
|
|
2361
|
+
{
|
|
2362
|
+
type: "key",
|
|
2363
|
+
id: "keyboard",
|
|
2364
|
+
actions: [
|
|
2365
|
+
{ type: "keyDown", value: key },
|
|
2366
|
+
{ type: "keyUp", value: key }
|
|
2367
|
+
]
|
|
2368
|
+
}
|
|
2369
|
+
]);
|
|
2350
2370
|
});
|
|
2351
2371
|
}
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2372
|
+
mouseClick(x, y, button = "left") {
|
|
2373
|
+
return __async(this, null, function* () {
|
|
2374
|
+
yield this.mouseMove(x, y);
|
|
2375
|
+
yield this.browser.performActions([
|
|
2376
|
+
{
|
|
2377
|
+
type: "pointer",
|
|
2378
|
+
id: "mouse",
|
|
2379
|
+
parameters: { pointerType: "mouse" },
|
|
2380
|
+
actions: [
|
|
2381
|
+
{ type: "pointerMove", duration: 0, x, y },
|
|
2382
|
+
{ type: "pointerDown", button: buttonToNumber(button) },
|
|
2383
|
+
{ type: "pause", duration: 100 },
|
|
2384
|
+
{ type: "pointerUp", button: buttonToNumber(button) }
|
|
2385
|
+
]
|
|
2386
|
+
}
|
|
2387
|
+
]);
|
|
2356
2388
|
});
|
|
2357
2389
|
}
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2390
|
+
mouseMove(x, y) {
|
|
2391
|
+
return __async(this, null, function* () {
|
|
2392
|
+
yield this.browser.performActions([
|
|
2393
|
+
{
|
|
2394
|
+
type: "pointer",
|
|
2395
|
+
id: "mouse",
|
|
2396
|
+
parameters: { pointerType: "mouse" },
|
|
2397
|
+
actions: [{ type: "pointerMove", duration: 0, x, y }]
|
|
2398
|
+
}
|
|
2399
|
+
]);
|
|
2362
2400
|
});
|
|
2363
2401
|
}
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2402
|
+
mouseWheel(deltaX, deltaY, duration = 1e3) {
|
|
2403
|
+
return __async(this, null, function* () {
|
|
2404
|
+
const n = 4;
|
|
2405
|
+
const windowSize = yield this.browser.getWindowSize();
|
|
2406
|
+
const startX = deltaX < 0 ? (n - 1) * (windowSize.width / n) : windowSize.width / n;
|
|
2407
|
+
const startY = deltaY < 0 ? (n - 1) * (windowSize.height / n) : windowSize.height / n;
|
|
2408
|
+
const maxNegativeDeltaX = startX;
|
|
2409
|
+
const maxPositiveDeltaX = (n - 1) * (windowSize.width / n);
|
|
2410
|
+
const maxNegativeDeltaY = startY;
|
|
2411
|
+
const maxPositiveDeltaY = (n - 1) * (windowSize.height / n);
|
|
2412
|
+
deltaX = Math.max(-maxNegativeDeltaX, Math.min(deltaX, maxPositiveDeltaX));
|
|
2413
|
+
deltaY = Math.max(-maxNegativeDeltaY, Math.min(deltaY, maxPositiveDeltaY));
|
|
2414
|
+
yield this.browser.performActions([
|
|
2415
|
+
{
|
|
2416
|
+
type: "pointer",
|
|
2417
|
+
id: "finger1",
|
|
2418
|
+
parameters: { pointerType: "touch" },
|
|
2419
|
+
actions: [
|
|
2420
|
+
{ type: "pointerMove", duration: 0, x: startX, y: startY },
|
|
2421
|
+
{ type: "pointerDown", button: 0 },
|
|
2422
|
+
{ type: "pause", duration },
|
|
2423
|
+
{
|
|
2424
|
+
type: "pointerMove",
|
|
2425
|
+
duration,
|
|
2426
|
+
origin: "pointer",
|
|
2427
|
+
// Use 'pointer' as the starting point
|
|
2428
|
+
x: deltaX,
|
|
2429
|
+
// X offset relative to the starting point
|
|
2430
|
+
y: deltaY
|
|
2431
|
+
// Y offset relative to the starting point
|
|
2432
|
+
},
|
|
2433
|
+
{ type: "pointerUp", button: 0 }
|
|
2434
|
+
]
|
|
2435
|
+
}
|
|
2436
|
+
]);
|
|
2368
2437
|
});
|
|
2369
2438
|
}
|
|
2439
|
+
};
|
|
2440
|
+
|
|
2441
|
+
// src/playground/agent.ts
|
|
2442
|
+
var StaticPageAgent = class extends PageAgent {
|
|
2443
|
+
constructor(page) {
|
|
2444
|
+
super(page, {});
|
|
2445
|
+
}
|
|
2446
|
+
};
|
|
2447
|
+
|
|
2448
|
+
// src/debug/index.ts
|
|
2449
|
+
var import_node_fs5 = require("fs");
|
|
2450
|
+
var import_node_path3 = __toESM(require("path"));
|
|
2451
|
+
var import_img5 = require("@midscene/shared/img");
|
|
2452
|
+
function generateExtractData(page, targetDir, saveImgType) {
|
|
2453
|
+
return __async(this, null, function* () {
|
|
2454
|
+
const inputImgBase64 = yield page.screenshotBase64();
|
|
2455
|
+
const {
|
|
2456
|
+
elementsPositionInfo,
|
|
2457
|
+
captureElementSnapshot,
|
|
2458
|
+
elementsPositionInfoWithoutText
|
|
2459
|
+
} = yield getElementInfos(page);
|
|
2460
|
+
const inputImagePath = import_node_path3.default.join(targetDir, "input.png");
|
|
2461
|
+
const outputImagePath = import_node_path3.default.join(targetDir, "output.png");
|
|
2462
|
+
const outputWithoutTextImgPath = import_node_path3.default.join(
|
|
2463
|
+
targetDir,
|
|
2464
|
+
"output_without_text.png"
|
|
2465
|
+
);
|
|
2466
|
+
const resizeOutputImgPath = import_node_path3.default.join(targetDir, "resize-output.png");
|
|
2467
|
+
const snapshotJsonPath = import_node_path3.default.join(targetDir, "element-snapshot.json");
|
|
2468
|
+
const {
|
|
2469
|
+
compositeElementInfoImgBase64,
|
|
2470
|
+
compositeElementInfoImgWithoutTextBase64
|
|
2471
|
+
} = yield (0, import_img5.processImageElementInfo)({
|
|
2472
|
+
elementsPositionInfo,
|
|
2473
|
+
elementsPositionInfoWithoutText,
|
|
2474
|
+
inputImgBase64
|
|
2475
|
+
});
|
|
2476
|
+
const resizeImgBase64 = yield (0, import_img5.resizeImg)(inputImgBase64);
|
|
2477
|
+
const existingSnapshot = (0, import_node_fs5.existsSync)(snapshotJsonPath) ? JSON.parse((0, import_node_fs5.readFileSync)(snapshotJsonPath, "utf-8")) : null;
|
|
2478
|
+
if (existingSnapshot && JSON.stringify(existingSnapshot) === JSON.stringify(captureElementSnapshot)) {
|
|
2479
|
+
console.log("skip save snapshot for ", targetDir);
|
|
2480
|
+
return;
|
|
2481
|
+
}
|
|
2482
|
+
if (!(saveImgType == null ? void 0 : saveImgType.disableSnapshot)) {
|
|
2483
|
+
writeFileSyncWithDir(
|
|
2484
|
+
snapshotJsonPath,
|
|
2485
|
+
JSON.stringify(captureElementSnapshot, null, 2)
|
|
2486
|
+
);
|
|
2487
|
+
}
|
|
2488
|
+
if (!(saveImgType == null ? void 0 : saveImgType.disableInputImage)) {
|
|
2489
|
+
yield (0, import_img5.saveBase64Image)({
|
|
2490
|
+
base64Data: inputImgBase64,
|
|
2491
|
+
outputPath: inputImagePath
|
|
2492
|
+
});
|
|
2493
|
+
}
|
|
2494
|
+
if (!(saveImgType == null ? void 0 : saveImgType.disableOutputImage)) {
|
|
2495
|
+
yield (0, import_img5.saveBase64Image)({
|
|
2496
|
+
base64Data: compositeElementInfoImgBase64,
|
|
2497
|
+
outputPath: outputImagePath
|
|
2498
|
+
});
|
|
2499
|
+
}
|
|
2500
|
+
if (!(saveImgType == null ? void 0 : saveImgType.disableOutputWithoutTextImg)) {
|
|
2501
|
+
yield (0, import_img5.saveBase64Image)({
|
|
2502
|
+
base64Data: compositeElementInfoImgWithoutTextBase64,
|
|
2503
|
+
outputPath: outputWithoutTextImgPath
|
|
2504
|
+
});
|
|
2505
|
+
}
|
|
2506
|
+
if (!(saveImgType == null ? void 0 : saveImgType.disableResizeOutputImg)) {
|
|
2507
|
+
yield (0, import_img5.saveBase64Image)({
|
|
2508
|
+
base64Data: resizeImgBase64,
|
|
2509
|
+
outputPath: resizeOutputImgPath
|
|
2510
|
+
});
|
|
2511
|
+
}
|
|
2512
|
+
});
|
|
2370
2513
|
}
|
|
2371
2514
|
function ensureDirectoryExistence(filePath) {
|
|
2372
2515
|
const dirname = import_node_path3.default.dirname(filePath);
|
|
@@ -2380,21 +2523,23 @@ function writeFileSyncWithDir(filePath, content, options = {}) {
|
|
|
2380
2523
|
ensureDirectoryExistence(filePath);
|
|
2381
2524
|
(0, import_node_fs5.writeFileSync)(filePath, content, options);
|
|
2382
2525
|
}
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2526
|
+
function getElementInfos(page) {
|
|
2527
|
+
return __async(this, null, function* () {
|
|
2528
|
+
const captureElementSnapshot = yield page.getElementInfos();
|
|
2529
|
+
const elementsPositionInfoWithoutText = captureElementSnapshot.filter(
|
|
2530
|
+
(elementInfo) => {
|
|
2531
|
+
if (elementInfo.attributes.nodeType === import_constants3.NodeType.TEXT) {
|
|
2532
|
+
return false;
|
|
2533
|
+
}
|
|
2534
|
+
return true;
|
|
2389
2535
|
}
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
};
|
|
2536
|
+
);
|
|
2537
|
+
return {
|
|
2538
|
+
elementsPositionInfo: captureElementSnapshot,
|
|
2539
|
+
captureElementSnapshot,
|
|
2540
|
+
elementsPositionInfoWithoutText
|
|
2541
|
+
};
|
|
2542
|
+
});
|
|
2398
2543
|
}
|
|
2399
2544
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2400
2545
|
0 && (module.exports = {
|
|
@@ -2403,6 +2548,7 @@ async function getElementInfos(page) {
|
|
|
2403
2548
|
PlaywrightAgent,
|
|
2404
2549
|
PlaywrightAiFixture,
|
|
2405
2550
|
PuppeteerAgent,
|
|
2551
|
+
StaticPageAgent,
|
|
2406
2552
|
generateExtractData
|
|
2407
2553
|
});
|
|
2408
2554
|
/*! Bundled license information:
|