@weapp-vite/miniprogram-automator 1.2.6 → 1.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +8 -1
- package/dist/index.mjs +27 -14
- package/dist/{launch-mRKloPOa.mjs → launch-DpCZfswN.mjs} +137 -47
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -44,13 +44,20 @@ declare class Transport extends EventEmitter {
|
|
|
44
44
|
interface SendOptions {
|
|
45
45
|
timeout?: number;
|
|
46
46
|
}
|
|
47
|
+
interface ToolInfo {
|
|
48
|
+
version?: string;
|
|
49
|
+
}
|
|
47
50
|
/** Connection 的实现。 */
|
|
48
51
|
declare class Connection extends EventEmitter {
|
|
49
52
|
private transport;
|
|
50
53
|
private callbacks;
|
|
54
|
+
private useAppServicePageProtocol;
|
|
51
55
|
constructor(transport: Transport);
|
|
52
56
|
send(method: string, params?: Record<string, any>, options?: SendOptions): Promise<any>;
|
|
53
57
|
dispose(): void;
|
|
58
|
+
/** 根据 DevTools 版本选择稳定的 Page 协议实现。 */
|
|
59
|
+
configureToolInfo(info: ToolInfo): void;
|
|
60
|
+
get prefersAppServicePageProtocol(): boolean;
|
|
54
61
|
private onMessage;
|
|
55
62
|
private onClose;
|
|
56
63
|
static create(url: string, timeout?: number): Promise<Connection>;
|
|
@@ -248,7 +255,7 @@ declare class Page {
|
|
|
248
255
|
query: any;
|
|
249
256
|
private id;
|
|
250
257
|
private elementMap;
|
|
251
|
-
private
|
|
258
|
+
private preferAppServicePageProtocol;
|
|
252
259
|
constructor(connection: Connection, options: IPageOptions);
|
|
253
260
|
updateFromOptions(options: IPageOptions): void;
|
|
254
261
|
waitFor(condition: WaitCondition): Promise<void>;
|
package/dist/index.mjs
CHANGED
|
@@ -506,10 +506,13 @@ const debugProtocol = createDebug("automator:protocol");
|
|
|
506
506
|
const closeErrTip = "Connection closed, check if wechat web devTools is still running";
|
|
507
507
|
const REQUEST_TIMEOUT = 3e4;
|
|
508
508
|
const CONNECT_TIMEOUT = 3e4;
|
|
509
|
+
/** Page frame 定向消息失效、需要切换到 App-service Page 协议的 DevTools 版本。 */
|
|
510
|
+
const APP_SERVICE_PAGE_PROTOCOL_VERSIONS = /* @__PURE__ */ new Set(["2.01.2510290"]);
|
|
509
511
|
/** Connection 的实现。 */
|
|
510
512
|
var Connection = class Connection extends EventEmitter {
|
|
511
513
|
transport;
|
|
512
514
|
callbacks = /* @__PURE__ */ new Map();
|
|
515
|
+
useAppServicePageProtocol = false;
|
|
513
516
|
constructor(transport) {
|
|
514
517
|
super();
|
|
515
518
|
this.transport = transport;
|
|
@@ -550,6 +553,13 @@ var Connection = class Connection extends EventEmitter {
|
|
|
550
553
|
dispose() {
|
|
551
554
|
this.transport.close();
|
|
552
555
|
}
|
|
556
|
+
/** 根据 DevTools 版本选择稳定的 Page 协议实现。 */
|
|
557
|
+
configureToolInfo(info) {
|
|
558
|
+
this.useAppServicePageProtocol = APP_SERVICE_PAGE_PROTOCOL_VERSIONS.has(String(info.version ?? ""));
|
|
559
|
+
}
|
|
560
|
+
get prefersAppServicePageProtocol() {
|
|
561
|
+
return this.useAppServicePageProtocol;
|
|
562
|
+
}
|
|
553
563
|
onMessage = (message) => {
|
|
554
564
|
debugProtocol(`${dateFormat("yyyy-mm-dd HH:MM:ss:l")} ◀ RECV ${message}`);
|
|
555
565
|
const { id, method, error, result, params } = JSON.parse(message);
|
|
@@ -602,7 +612,7 @@ var Connection = class Connection extends EventEmitter {
|
|
|
602
612
|
//#endregion
|
|
603
613
|
//#region src/headless.ts
|
|
604
614
|
async function launchHeadlessAutomator(options) {
|
|
605
|
-
return await (await import("./launch-
|
|
615
|
+
return await (await import("./launch-DpCZfswN.mjs")).launch({ projectPath: options.projectPath });
|
|
606
616
|
}
|
|
607
617
|
//#endregion
|
|
608
618
|
//#region src/launcher/portLease.ts
|
|
@@ -701,7 +711,7 @@ async function acquireAutomatorPortLease(preferredPort) {
|
|
|
701
711
|
}
|
|
702
712
|
//#endregion
|
|
703
713
|
//#region package.json
|
|
704
|
-
var version = "1.2.
|
|
714
|
+
var version = "1.2.8";
|
|
705
715
|
//#endregion
|
|
706
716
|
//#region src/Native.ts
|
|
707
717
|
/** Native 的实现。 */
|
|
@@ -823,12 +833,13 @@ var Page = class Page {
|
|
|
823
833
|
query = {};
|
|
824
834
|
id;
|
|
825
835
|
elementMap = /* @__PURE__ */ new Map();
|
|
826
|
-
|
|
836
|
+
preferAppServicePageProtocol = false;
|
|
827
837
|
constructor(connection, options) {
|
|
828
838
|
this.connection = connection;
|
|
829
839
|
this.id = options.id;
|
|
830
840
|
this.path = options.path;
|
|
831
841
|
this.query = options.query;
|
|
842
|
+
this.preferAppServicePageProtocol = connection.prefersAppServicePageProtocol;
|
|
832
843
|
}
|
|
833
844
|
updateFromOptions(options) {
|
|
834
845
|
this.path = options.path;
|
|
@@ -846,7 +857,7 @@ var Page = class Page {
|
|
|
846
857
|
if (isStr(condition)) await waitUntil(async () => (await this.$$(condition)).length > 0);
|
|
847
858
|
}
|
|
848
859
|
async $(selector, options = {}) {
|
|
849
|
-
if (options.routeOnly || this.
|
|
860
|
+
if (options.routeOnly || options.fallback !== false && this.preferAppServicePageProtocol) return await this.queryRouteElement(selector, options);
|
|
850
861
|
try {
|
|
851
862
|
const element = await this.send("Page.getElement", { selector }, { timeout: options.timeout ?? PAGE_QUERY_TIMEOUT });
|
|
852
863
|
return Element.create(this.connection, {
|
|
@@ -855,14 +866,14 @@ var Page = class Page {
|
|
|
855
866
|
}, this.elementMap);
|
|
856
867
|
} catch (error) {
|
|
857
868
|
if (options.fallback !== false && isRecoverablePageProtocolError(error, "Page.getElement")) {
|
|
858
|
-
this.
|
|
869
|
+
this.preferAppServicePageProtocol = true;
|
|
859
870
|
return await this.queryRouteElement(selector, options);
|
|
860
871
|
}
|
|
861
872
|
return null;
|
|
862
873
|
}
|
|
863
874
|
}
|
|
864
875
|
async $$(selector, options = {}) {
|
|
865
|
-
if (options.routeOnly || this.
|
|
876
|
+
if (options.routeOnly || options.fallback !== false && this.preferAppServicePageProtocol) return await this.queryRouteElements(selector, options);
|
|
866
877
|
try {
|
|
867
878
|
const { elements } = await this.send("Page.getElements", { selector }, { timeout: options.timeout ?? PAGE_QUERY_TIMEOUT });
|
|
868
879
|
return elements.map((element) => {
|
|
@@ -873,7 +884,7 @@ var Page = class Page {
|
|
|
873
884
|
});
|
|
874
885
|
} catch (error) {
|
|
875
886
|
if (options.fallback === false || !isRecoverablePageProtocolError(error, "Page.getElements")) throw error;
|
|
876
|
-
this.
|
|
887
|
+
this.preferAppServicePageProtocol = true;
|
|
877
888
|
return await this.queryRouteElements(selector, options);
|
|
878
889
|
}
|
|
879
890
|
}
|
|
@@ -1360,13 +1371,13 @@ var Page = class Page {
|
|
|
1360
1371
|
const payload = {};
|
|
1361
1372
|
if (path) payload.path = path;
|
|
1362
1373
|
const timeout = options.timeout ?? PAGE_DATA_TIMEOUT;
|
|
1363
|
-
if (options.routeOnly || this.
|
|
1374
|
+
if (options.routeOnly || options.fallback !== false && this.preferAppServicePageProtocol) return await this.readRouteData(path, timeout);
|
|
1364
1375
|
try {
|
|
1365
1376
|
return (await this.send("Page.getData", payload, { timeout: Math.min(timeout, PAGE_DATA_PROTOCOL_TIMEOUT) })).data;
|
|
1366
1377
|
} catch (error) {
|
|
1367
1378
|
if (options.fallback === false) throw error;
|
|
1368
1379
|
if (!isRecoverablePageProtocolError(error, "Page.getData")) throw error;
|
|
1369
|
-
this.
|
|
1380
|
+
this.preferAppServicePageProtocol = true;
|
|
1370
1381
|
return await this.readRouteData(path, timeout);
|
|
1371
1382
|
}
|
|
1372
1383
|
}
|
|
@@ -1425,7 +1436,7 @@ var Page = class Page {
|
|
|
1425
1436
|
}, { timeout })).result;
|
|
1426
1437
|
}
|
|
1427
1438
|
async setData(data) {
|
|
1428
|
-
if (this.
|
|
1439
|
+
if (this.preferAppServicePageProtocol) {
|
|
1429
1440
|
await this.setRouteData(data);
|
|
1430
1441
|
return;
|
|
1431
1442
|
}
|
|
@@ -1433,7 +1444,7 @@ var Page = class Page {
|
|
|
1433
1444
|
await this.send("Page.setData", { data }, { timeout: PAGE_SET_DATA_PROTOCOL_TIMEOUT });
|
|
1434
1445
|
} catch (error) {
|
|
1435
1446
|
if (!isRecoverablePageProtocolError(error, "Page.setData") && !isPageStackStaleError(error)) throw error;
|
|
1436
|
-
this.
|
|
1447
|
+
this.preferAppServicePageProtocol = true;
|
|
1437
1448
|
await this.setRouteData(data);
|
|
1438
1449
|
}
|
|
1439
1450
|
}
|
|
@@ -1448,7 +1459,7 @@ var Page = class Page {
|
|
|
1448
1459
|
return await this.callMethodWithOptions(method, {}, ...args);
|
|
1449
1460
|
}
|
|
1450
1461
|
async callMethodWithOptions(method, options = {}, ...args) {
|
|
1451
|
-
if (options.routeOnly || this.
|
|
1462
|
+
if (options.routeOnly || options.fallback !== false && this.preferAppServicePageProtocol) return await this.callRouteMethod(method, args, options.timeout);
|
|
1452
1463
|
try {
|
|
1453
1464
|
return (await this.send("Page.callMethod", {
|
|
1454
1465
|
method,
|
|
@@ -1457,7 +1468,7 @@ var Page = class Page {
|
|
|
1457
1468
|
} catch (error) {
|
|
1458
1469
|
if (options.fallback === false) throw error;
|
|
1459
1470
|
if (!isRecoverablePageProtocolError(error, "Page.callMethod") && !isPageStackStaleError(error)) throw error;
|
|
1460
|
-
this.
|
|
1471
|
+
this.preferAppServicePageProtocol = true;
|
|
1461
1472
|
}
|
|
1462
1473
|
return await this.callRouteMethod(method, args, options.timeout);
|
|
1463
1474
|
}
|
|
@@ -1943,7 +1954,9 @@ var MiniProgram = class extends EventEmitter {
|
|
|
1943
1954
|
await this.send("App.addBinding", { name });
|
|
1944
1955
|
}
|
|
1945
1956
|
async checkVersion() {
|
|
1946
|
-
const
|
|
1957
|
+
const toolInfo = await this.send("Tool.getInfo");
|
|
1958
|
+
this.connection.configureToolInfo(toolInfo);
|
|
1959
|
+
const sdkVersion = toolInfo.SDKVersion;
|
|
1947
1960
|
if (sdkVersion !== "dev" && cmpVersion(sdkVersion, "2.7.3") < 0) throw new Error(`SDKVersion is currently ${sdkVersion}, while automator(${version}) requires at least version 2.7.3`);
|
|
1948
1961
|
}
|
|
1949
1962
|
/**
|
|
@@ -3291,6 +3291,48 @@ function renderRuntimePageTree(context, page) {
|
|
|
3291
3291
|
function createDuplicateRegistrationError(kind, id) {
|
|
3292
3292
|
return /* @__PURE__ */ new Error(`Duplicate ${kind} registration in headless runtime: ${id}`);
|
|
3293
3293
|
}
|
|
3294
|
+
function callDefinitionMethod(instance, method, args) {
|
|
3295
|
+
if (typeof method === "function") return method.apply(instance, args);
|
|
3296
|
+
}
|
|
3297
|
+
function normalizeComponentPageDefinition(definition) {
|
|
3298
|
+
const { lifetimes = {}, methods = {}, pageLifetimes = {}, ...rest } = definition;
|
|
3299
|
+
const created = lifetimes.created ?? rest.created;
|
|
3300
|
+
const attached = lifetimes.attached ?? rest.attached;
|
|
3301
|
+
const ready = lifetimes.ready ?? rest.ready ?? methods.onReady ?? rest.onReady;
|
|
3302
|
+
const detached = lifetimes.detached ?? rest.detached ?? methods.onUnload ?? rest.onUnload;
|
|
3303
|
+
const load = methods.onLoad ?? rest.onLoad;
|
|
3304
|
+
const show = pageLifetimes.show ?? methods.onShow ?? rest.onShow;
|
|
3305
|
+
const hide = pageLifetimes.hide ?? methods.onHide ?? rest.onHide;
|
|
3306
|
+
const resize = pageLifetimes.resize ?? methods.onResize ?? rest.onResize;
|
|
3307
|
+
const routeDone = pageLifetimes.routeDone ?? methods.onRouteDone ?? rest.onRouteDone;
|
|
3308
|
+
return {
|
|
3309
|
+
...rest,
|
|
3310
|
+
...methods,
|
|
3311
|
+
onLoad(...args) {
|
|
3312
|
+
callDefinitionMethod(this, created, []);
|
|
3313
|
+
callDefinitionMethod(this, attached, []);
|
|
3314
|
+
return callDefinitionMethod(this, load, args);
|
|
3315
|
+
},
|
|
3316
|
+
onShow(...args) {
|
|
3317
|
+
return callDefinitionMethod(this, show, args);
|
|
3318
|
+
},
|
|
3319
|
+
onHide(...args) {
|
|
3320
|
+
return callDefinitionMethod(this, hide, args);
|
|
3321
|
+
},
|
|
3322
|
+
onReady(...args) {
|
|
3323
|
+
return callDefinitionMethod(this, ready, args);
|
|
3324
|
+
},
|
|
3325
|
+
onUnload(...args) {
|
|
3326
|
+
return callDefinitionMethod(this, detached, args);
|
|
3327
|
+
},
|
|
3328
|
+
onResize(...args) {
|
|
3329
|
+
return callDefinitionMethod(this, resize, args);
|
|
3330
|
+
},
|
|
3331
|
+
onRouteDone(...args) {
|
|
3332
|
+
return callDefinitionMethod(this, routeDone, args);
|
|
3333
|
+
}
|
|
3334
|
+
};
|
|
3335
|
+
}
|
|
3294
3336
|
function createHostRegistries() {
|
|
3295
3337
|
return {
|
|
3296
3338
|
appDefinition: null,
|
|
@@ -3312,6 +3354,7 @@ function registerPageDefinition(registries, definition) {
|
|
|
3312
3354
|
return definition;
|
|
3313
3355
|
}
|
|
3314
3356
|
function registerComponentDefinition(registries, definition) {
|
|
3357
|
+
if (registries.currentLoadContext?.kind === "page") return registerPageDefinition(registries, normalizeComponentPageDefinition(definition));
|
|
3315
3358
|
const id = registries.currentLoadContext?.route ?? `anonymous:${registries.components.size}`;
|
|
3316
3359
|
if (registries.components.has(id)) throw createDuplicateRegistrationError("component", id);
|
|
3317
3360
|
registries.components.set(id, definition);
|
|
@@ -5181,7 +5224,8 @@ function createModuleLoader(registries, getCurrentPages, getApp, wxDriver) {
|
|
|
5181
5224
|
const definition = registries.components.get(id);
|
|
5182
5225
|
if (!definition) throw new Error(`Component() was not registered for id "${id}" while executing ${normalize(filePath)}.`);
|
|
5183
5226
|
return definition;
|
|
5184
|
-
}
|
|
5227
|
+
},
|
|
5228
|
+
wx: executionContext.wx
|
|
5185
5229
|
};
|
|
5186
5230
|
}
|
|
5187
5231
|
//#endregion
|
|
@@ -6991,6 +7035,11 @@ var HeadlessSession = class {
|
|
|
6991
7035
|
getCurrentPages() {
|
|
6992
7036
|
return this.pages.slice();
|
|
6993
7037
|
}
|
|
7038
|
+
callWxMethod(methodName, ...args) {
|
|
7039
|
+
const method = this.moduleLoader.wx[methodName];
|
|
7040
|
+
if (typeof method !== "function") throw new TypeError(`wx.${methodName} is not available in headless runtime.`);
|
|
7041
|
+
return Reflect.apply(method, this.moduleLoader.wx, args);
|
|
7042
|
+
}
|
|
6994
7043
|
getCurrentPageNavigationBarTitle() {
|
|
6995
7044
|
return this.currentPageInstance?.__navigationBarTitle__ ?? null;
|
|
6996
7045
|
}
|
|
@@ -7359,6 +7408,7 @@ var HeadlessSession = class {
|
|
|
7359
7408
|
const pageInstance = this.createFreshPage(target);
|
|
7360
7409
|
this.pages.push(pageInstance);
|
|
7361
7410
|
this.currentPageInstance = pageInstance;
|
|
7411
|
+
this.runInitialPageLifecycles(pageInstance, target.query);
|
|
7362
7412
|
return pageInstance;
|
|
7363
7413
|
}
|
|
7364
7414
|
navigateTo(url) {
|
|
@@ -7371,6 +7421,7 @@ var HeadlessSession = class {
|
|
|
7371
7421
|
const pageInstance = this.createFreshPage(target);
|
|
7372
7422
|
this.pages.push(pageInstance);
|
|
7373
7423
|
this.currentPageInstance = pageInstance;
|
|
7424
|
+
this.runInitialPageLifecycles(pageInstance, target.query);
|
|
7374
7425
|
return pageInstance;
|
|
7375
7426
|
}
|
|
7376
7427
|
redirectTo(url) {
|
|
@@ -7385,6 +7436,7 @@ var HeadlessSession = class {
|
|
|
7385
7436
|
const pageInstance = this.createFreshPage(target);
|
|
7386
7437
|
this.pages.push(pageInstance);
|
|
7387
7438
|
this.currentPageInstance = pageInstance;
|
|
7439
|
+
this.runInitialPageLifecycles(pageInstance, target.query);
|
|
7388
7440
|
return pageInstance;
|
|
7389
7441
|
}
|
|
7390
7442
|
navigateBack(delta = 1) {
|
|
@@ -7421,17 +7473,21 @@ var HeadlessSession = class {
|
|
|
7421
7473
|
this.unloadPage(page);
|
|
7422
7474
|
}
|
|
7423
7475
|
let nextPage = cachedTarget;
|
|
7476
|
+
let shouldRunInitialLifecycles = false;
|
|
7424
7477
|
if (!nextPage) {
|
|
7425
7478
|
nextPage = this.createFreshPage(target);
|
|
7426
7479
|
this.tabPages.set(target.routeRecord.route, nextPage);
|
|
7427
|
-
|
|
7428
|
-
nextPage.onShow?.();
|
|
7429
|
-
this.runPageComponentLifetime(nextPage.route, "show");
|
|
7480
|
+
shouldRunInitialLifecycles = true;
|
|
7430
7481
|
}
|
|
7431
|
-
nextPage.onTabItemTap?.(tabItem);
|
|
7432
7482
|
this.pages.length = 0;
|
|
7433
7483
|
this.pages.push(nextPage);
|
|
7434
7484
|
this.currentPageInstance = nextPage;
|
|
7485
|
+
if (shouldRunInitialLifecycles) this.runInitialPageLifecycles(nextPage, target.query);
|
|
7486
|
+
else if (current !== nextPage) {
|
|
7487
|
+
nextPage.onShow?.();
|
|
7488
|
+
this.runPageComponentLifetime(nextPage.route, "show");
|
|
7489
|
+
}
|
|
7490
|
+
nextPage.onTabItemTap?.(tabItem);
|
|
7435
7491
|
return nextPage;
|
|
7436
7492
|
}
|
|
7437
7493
|
pageScrollTo(option) {
|
|
@@ -7506,12 +7562,14 @@ var HeadlessSession = class {
|
|
|
7506
7562
|
pageInstance.createMediaQueryObserver = () => this.createMediaQueryObserver(pageInstance);
|
|
7507
7563
|
pageInstance.selectComponent = (selector) => this.selectComponent(selector);
|
|
7508
7564
|
pageInstance.selectAllComponents = (selector) => this.selectAllComponents(selector);
|
|
7509
|
-
pageInstance.onLoad?.(target.query);
|
|
7510
|
-
pageInstance.onShow?.();
|
|
7511
|
-
pageInstance.onReady?.();
|
|
7512
7565
|
if (this.isTabBarRoute(target.routeRecord.route)) this.tabPages.set(target.routeRecord.route, pageInstance);
|
|
7513
7566
|
return pageInstance;
|
|
7514
7567
|
}
|
|
7568
|
+
runInitialPageLifecycles(pageInstance, query) {
|
|
7569
|
+
pageInstance.onLoad?.(query);
|
|
7570
|
+
pageInstance.onShow?.();
|
|
7571
|
+
pageInstance.onReady?.();
|
|
7572
|
+
}
|
|
7515
7573
|
isTabBarRoute(route) {
|
|
7516
7574
|
return this.tabBarRoutes.has(stripLeadingSlash(route));
|
|
7517
7575
|
}
|
|
@@ -7717,9 +7775,52 @@ function createHeadlessSession(options) {
|
|
|
7717
7775
|
return new HeadlessSession(options);
|
|
7718
7776
|
}
|
|
7719
7777
|
//#endregion
|
|
7720
|
-
//#region ../../mpcore/packages/simulator/src/testing/
|
|
7778
|
+
//#region ../../mpcore/packages/simulator/src/testing/sessionHandle/shared.ts
|
|
7779
|
+
const LEADING_SLASH_RE = /^\/+/;
|
|
7721
7780
|
const DEFAULT_WAIT_TIMEOUT$1 = 1e3;
|
|
7722
7781
|
const DEFAULT_WAIT_INTERVAL$1 = 10;
|
|
7782
|
+
function normalizeRoute(route) {
|
|
7783
|
+
return route.replace(LEADING_SLASH_RE, "");
|
|
7784
|
+
}
|
|
7785
|
+
function resolvePageScopeId(scopeId) {
|
|
7786
|
+
const pagePathIndex = scopeId.indexOf("/page/");
|
|
7787
|
+
return pagePathIndex >= 0 ? scopeId.slice(0, pagePathIndex) : scopeId;
|
|
7788
|
+
}
|
|
7789
|
+
function normalizeNonEmptyInput(value, label) {
|
|
7790
|
+
const normalizedValue = value.trim();
|
|
7791
|
+
if (!normalizedValue) throw new Error(`${label} must be a non-empty string in headless testing runtime.`);
|
|
7792
|
+
return normalizedValue;
|
|
7793
|
+
}
|
|
7794
|
+
async function waitForDelay(ms = 0) {
|
|
7795
|
+
if (ms <= 0) return;
|
|
7796
|
+
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
7797
|
+
}
|
|
7798
|
+
async function pollUntil(check, errorMessage, options = {}) {
|
|
7799
|
+
const timeout = Number.isFinite(options.timeout) ? Math.max(0, Math.trunc(options.timeout ?? DEFAULT_WAIT_TIMEOUT$1)) : DEFAULT_WAIT_TIMEOUT$1;
|
|
7800
|
+
const interval = Number.isFinite(options.interval) ? Math.max(1, Math.trunc(options.interval ?? DEFAULT_WAIT_INTERVAL$1)) : DEFAULT_WAIT_INTERVAL$1;
|
|
7801
|
+
const deadline = Date.now() + timeout;
|
|
7802
|
+
while (true) {
|
|
7803
|
+
const result = await check();
|
|
7804
|
+
if (result != null) return result;
|
|
7805
|
+
if (Date.now() >= deadline) throw new Error(errorMessage);
|
|
7806
|
+
await waitForDelay(interval);
|
|
7807
|
+
}
|
|
7808
|
+
}
|
|
7809
|
+
async function runWithTimeout(operation, timeout, message) {
|
|
7810
|
+
if (!Number.isFinite(timeout) || (timeout ?? 0) <= 0) return await operation();
|
|
7811
|
+
let timer;
|
|
7812
|
+
try {
|
|
7813
|
+
return await Promise.race([Promise.resolve().then(operation), new Promise((_resolve, reject) => {
|
|
7814
|
+
timer = setTimeout(() => reject(new Error(message)), Math.trunc(timeout));
|
|
7815
|
+
})]);
|
|
7816
|
+
} finally {
|
|
7817
|
+
if (timer) clearTimeout(timer);
|
|
7818
|
+
}
|
|
7819
|
+
}
|
|
7820
|
+
//#endregion
|
|
7821
|
+
//#region ../../mpcore/packages/simulator/src/testing/pageHandle.ts
|
|
7822
|
+
const DEFAULT_WAIT_TIMEOUT = 1e3;
|
|
7823
|
+
const DEFAULT_WAIT_INTERVAL = 10;
|
|
7723
7824
|
var HeadlessTestingPageHandle = class {
|
|
7724
7825
|
project;
|
|
7725
7826
|
page;
|
|
@@ -7729,6 +7830,12 @@ var HeadlessTestingPageHandle = class {
|
|
|
7729
7830
|
this.page = page;
|
|
7730
7831
|
this.session = session;
|
|
7731
7832
|
}
|
|
7833
|
+
get path() {
|
|
7834
|
+
return this.page.route;
|
|
7835
|
+
}
|
|
7836
|
+
get query() {
|
|
7837
|
+
return { ...this.page.options };
|
|
7838
|
+
}
|
|
7732
7839
|
resolveDataByPath(path) {
|
|
7733
7840
|
if (!path) return this.page.data;
|
|
7734
7841
|
const segments = path.split(".").filter(Boolean);
|
|
@@ -7737,8 +7844,8 @@ var HeadlessTestingPageHandle = class {
|
|
|
7737
7844
|
return current;
|
|
7738
7845
|
}
|
|
7739
7846
|
async pollUntil(check, errorMessage, options = {}) {
|
|
7740
|
-
const timeout = Number.isFinite(options.timeout) ? Math.max(0, Math.trunc(options.timeout ?? DEFAULT_WAIT_TIMEOUT
|
|
7741
|
-
const interval = Number.isFinite(options.interval) ? Math.max(1, Math.trunc(options.interval ?? DEFAULT_WAIT_INTERVAL
|
|
7847
|
+
const timeout = Number.isFinite(options.timeout) ? Math.max(0, Math.trunc(options.timeout ?? DEFAULT_WAIT_TIMEOUT)) : DEFAULT_WAIT_TIMEOUT;
|
|
7848
|
+
const interval = Number.isFinite(options.interval) ? Math.max(1, Math.trunc(options.interval ?? DEFAULT_WAIT_INTERVAL)) : DEFAULT_WAIT_INTERVAL;
|
|
7742
7849
|
const deadline = Date.now() + timeout;
|
|
7743
7850
|
while (true) {
|
|
7744
7851
|
const result = await check();
|
|
@@ -7752,9 +7859,15 @@ var HeadlessTestingPageHandle = class {
|
|
|
7752
7859
|
return scopeId ? new HeadlessTestingScopeHandle(scopeId, this.project, this.session) : null;
|
|
7753
7860
|
}
|
|
7754
7861
|
async callMethod(methodName, ...args) {
|
|
7755
|
-
|
|
7756
|
-
|
|
7757
|
-
|
|
7862
|
+
return await this.callMethodWithOptions(methodName, {}, ...args);
|
|
7863
|
+
}
|
|
7864
|
+
async callMethodWithOptions(methodName, options = {}, ...args) {
|
|
7865
|
+
const normalizedMethodName = normalizeNonEmptyInput(methodName, "Page method name");
|
|
7866
|
+
return await runWithTimeout(async () => {
|
|
7867
|
+
const method = this.page[normalizedMethodName];
|
|
7868
|
+
if (typeof method !== "function") throw new TypeError(`Method "${normalizedMethodName}" does not exist on headless page ${this.page.route}.`);
|
|
7869
|
+
return await method.apply(this.page, args);
|
|
7870
|
+
}, options.timeout, `Timed out calling page method "${normalizedMethodName}" in headless testing runtime.`);
|
|
7758
7871
|
}
|
|
7759
7872
|
async data(path) {
|
|
7760
7873
|
return this.resolveDataByPath(path);
|
|
@@ -7856,38 +7969,6 @@ var HeadlessTestingPageHandle = class {
|
|
|
7856
7969
|
}
|
|
7857
7970
|
};
|
|
7858
7971
|
//#endregion
|
|
7859
|
-
//#region ../../mpcore/packages/simulator/src/testing/sessionHandle/shared.ts
|
|
7860
|
-
const LEADING_SLASH_RE = /^\/+/;
|
|
7861
|
-
const DEFAULT_WAIT_TIMEOUT = 1e3;
|
|
7862
|
-
const DEFAULT_WAIT_INTERVAL = 10;
|
|
7863
|
-
function normalizeRoute(route) {
|
|
7864
|
-
return route.replace(LEADING_SLASH_RE, "");
|
|
7865
|
-
}
|
|
7866
|
-
function resolvePageScopeId(scopeId) {
|
|
7867
|
-
const pagePathIndex = scopeId.indexOf("/page/");
|
|
7868
|
-
return pagePathIndex >= 0 ? scopeId.slice(0, pagePathIndex) : scopeId;
|
|
7869
|
-
}
|
|
7870
|
-
function normalizeNonEmptyInput(value, label) {
|
|
7871
|
-
const normalizedValue = value.trim();
|
|
7872
|
-
if (!normalizedValue) throw new Error(`${label} must be a non-empty string in headless testing runtime.`);
|
|
7873
|
-
return normalizedValue;
|
|
7874
|
-
}
|
|
7875
|
-
async function waitForDelay(ms = 0) {
|
|
7876
|
-
if (ms <= 0) return;
|
|
7877
|
-
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
7878
|
-
}
|
|
7879
|
-
async function pollUntil(check, errorMessage, options = {}) {
|
|
7880
|
-
const timeout = Number.isFinite(options.timeout) ? Math.max(0, Math.trunc(options.timeout ?? DEFAULT_WAIT_TIMEOUT)) : DEFAULT_WAIT_TIMEOUT;
|
|
7881
|
-
const interval = Number.isFinite(options.interval) ? Math.max(1, Math.trunc(options.interval ?? DEFAULT_WAIT_INTERVAL)) : DEFAULT_WAIT_INTERVAL;
|
|
7882
|
-
const deadline = Date.now() + timeout;
|
|
7883
|
-
while (true) {
|
|
7884
|
-
const result = await check();
|
|
7885
|
-
if (result != null) return result;
|
|
7886
|
-
if (Date.now() >= deadline) throw new Error(errorMessage);
|
|
7887
|
-
await waitForDelay(interval);
|
|
7888
|
-
}
|
|
7889
|
-
}
|
|
7890
|
-
//#endregion
|
|
7891
7972
|
//#region ../../mpcore/packages/simulator/src/testing/sessionHandle/scope.ts
|
|
7892
7973
|
var HeadlessTestingScopeHandle = class HeadlessTestingScopeHandle {
|
|
7893
7974
|
scopeId;
|
|
@@ -7961,6 +8042,13 @@ var HeadlessTestingSessionHandle = class {
|
|
|
7961
8042
|
async getCurrentPages() {
|
|
7962
8043
|
return this.session.getCurrentPages().map((page) => new HeadlessTestingPageHandle(this.project, page, this.session));
|
|
7963
8044
|
}
|
|
8045
|
+
async callWxMethod(methodName, ...args) {
|
|
8046
|
+
return await this.callWxMethodWithOptions(methodName, {}, ...args);
|
|
8047
|
+
}
|
|
8048
|
+
async callWxMethodWithOptions(methodName, options = {}, ...args) {
|
|
8049
|
+
const normalizedMethodName = normalizeNonEmptyInput(methodName, "wx method name");
|
|
8050
|
+
return await runWithTimeout(() => this.session.callWxMethod(normalizedMethodName, ...args), options.timeout, `Timed out calling wx.${normalizedMethodName} in headless testing runtime.`);
|
|
8051
|
+
}
|
|
7964
8052
|
async scopeSnapshot(scopeId) {
|
|
7965
8053
|
const normalizedScopeId = normalizeNonEmptyInput(scopeId, "Scope id");
|
|
7966
8054
|
return this.session.getScopeSnapshot(normalizedScopeId);
|
|
@@ -7988,7 +8076,9 @@ var HeadlessTestingSessionHandle = class {
|
|
|
7988
8076
|
}, `Timed out waiting for ${normalizedCount} component(s) matching "${normalizedSelector}" in headless testing runtime.`, options);
|
|
7989
8077
|
}
|
|
7990
8078
|
async reLaunch(route) {
|
|
7991
|
-
|
|
8079
|
+
this.session.callWxMethod("reLaunch", { url: route });
|
|
8080
|
+
const page = this.session.getCurrentPages().at(-1);
|
|
8081
|
+
if (!page) throw new Error(`Failed to reLaunch route "${route}" through the headless wx runtime.`);
|
|
7992
8082
|
return new HeadlessTestingPageHandle(this.project, page, this.session);
|
|
7993
8083
|
}
|
|
7994
8084
|
async waitForCurrentPage(route, options = {}) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weapp-vite/miniprogram-automator",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.2.
|
|
4
|
+
"version": "1.2.8",
|
|
5
5
|
"description": "完全兼容微信 miniprogram-automator 的现代化替代实现",
|
|
6
6
|
"author": "ice breaker <1324318532@qq.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"node": "^20.19.0 || >=22.12.0"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"obug": "^2.1.
|
|
45
|
-
"ws": "^8.21.
|
|
44
|
+
"obug": "^2.1.4",
|
|
45
|
+
"ws": "^8.21.1",
|
|
46
46
|
"@weapp-vite/qr": "1.1.1"
|
|
47
47
|
},
|
|
48
48
|
"publishConfig": {
|