@midscene/cli 1.8.7 → 1.8.8-beta-20260601092817.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/es/framework/index.mjs +3880 -0
- package/dist/es/framework/index.mjs.map +1 -0
- package/dist/es/index.mjs +368 -1155
- package/dist/es/index.mjs.map +1 -1
- package/dist/lib/framework/index.js +3989 -0
- package/dist/lib/framework/index.js.map +1 -0
- package/dist/lib/index.js +400 -1153
- package/dist/lib/index.js.map +1 -1
- package/dist/types/framework/index.d.ts +152 -0
- package/package.json +8 -7
package/dist/es/index.mjs
CHANGED
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
/*! For license information please see index.mjs.LICENSE.txt */
|
|
2
|
-
import
|
|
2
|
+
import { basename as external_node_path_basename, dirname as external_node_path_dirname, extname as external_node_path_extname, join as external_node_path_join, posix, relative as external_node_path_relative, resolve as external_node_path_resolve, sep as external_node_path_sep, win32 } from "node:path";
|
|
3
3
|
import { createReportCliCommands } from "@midscene/core";
|
|
4
4
|
import { runToolsCLI } from "@midscene/shared/cli";
|
|
5
|
-
import { ScriptPlayer, interpolateEnvVars, parseYamlScript } from "@midscene/core/yaml";
|
|
6
|
-
import { getMidsceneRunSubDir } from "@midscene/shared/common";
|
|
7
|
-
import { buildChromeArgs, defaultViewportHeight, defaultViewportWidth, puppeteerAgentForTarget } from "@midscene/web/puppeteer-agent-launcher";
|
|
8
|
-
import lodash_merge from "lodash.merge";
|
|
9
|
-
import puppeteer from "puppeteer";
|
|
10
|
-
import { createServer } from "http-server";
|
|
11
|
-
import node_assert from "node:assert";
|
|
12
|
-
import { createAgent, getReportFileName } from "@midscene/core/agent";
|
|
13
|
-
import { processCacheConfig } from "@midscene/core/utils";
|
|
14
5
|
import { getDebug } from "@midscene/shared/logger";
|
|
15
|
-
import {
|
|
16
|
-
import { stripVTControlCharacters } from "node:util";
|
|
17
|
-
import node_process, { cwd as external_node_process_cwd } from "node:process";
|
|
18
|
-
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
19
7
|
import { lstat, readdir, readlink, realpath } from "node:fs/promises";
|
|
20
8
|
import { EventEmitter } from "node:events";
|
|
21
9
|
import node_stream from "node:stream";
|
|
22
10
|
import { StringDecoder } from "node:string_decoder";
|
|
23
11
|
import { fileURLToPath as external_url_fileURLToPath } from "url";
|
|
12
|
+
import { cwd as external_node_process_cwd } from "node:process";
|
|
13
|
+
import { interpolateEnvVars } from "@midscene/core/yaml";
|
|
14
|
+
import lodash_merge from "lodash.merge";
|
|
15
|
+
import { getMidsceneRunSubDir } from "@midscene/shared/common";
|
|
16
|
+
import { createRequire } from "node:module";
|
|
17
|
+
import "@rstest/core";
|
|
18
|
+
import "@midscene/web/puppeteer-agent-launcher";
|
|
19
|
+
import "puppeteer";
|
|
20
|
+
import "http-server";
|
|
21
|
+
import "node:assert";
|
|
22
|
+
import "@midscene/core/agent";
|
|
23
|
+
import "@midscene/core/utils";
|
|
24
|
+
import "@midscene/web/bridge-mode";
|
|
25
|
+
import "node:util";
|
|
24
26
|
import * as __rspack_external_assert from "assert";
|
|
25
27
|
import * as __rspack_external_crypto from "crypto";
|
|
26
28
|
import * as __rspack_external_fs from "fs";
|
|
@@ -3024,1126 +3026,7 @@ var __webpack_modules__ = {
|
|
|
3024
3026
|
"./src/index.ts" (__unused_rspack_module, __unused_rspack___webpack_exports__, __webpack_require__) {
|
|
3025
3027
|
var main = __webpack_require__("../../node_modules/.pnpm/dotenv@16.4.5/node_modules/dotenv/lib/main.js");
|
|
3026
3028
|
var main_default = /*#__PURE__*/ __webpack_require__.n(main);
|
|
3027
|
-
var package_namespaceObject = {
|
|
3028
|
-
rE: "1.8.7"
|
|
3029
|
-
};
|
|
3030
|
-
class Node {
|
|
3031
|
-
value;
|
|
3032
|
-
next;
|
|
3033
|
-
constructor(value){
|
|
3034
|
-
this.value = value;
|
|
3035
|
-
}
|
|
3036
|
-
}
|
|
3037
|
-
class Queue {
|
|
3038
|
-
#head;
|
|
3039
|
-
#tail;
|
|
3040
|
-
#size;
|
|
3041
|
-
constructor(){
|
|
3042
|
-
this.clear();
|
|
3043
|
-
}
|
|
3044
|
-
enqueue(value) {
|
|
3045
|
-
const node = new Node(value);
|
|
3046
|
-
if (this.#head) {
|
|
3047
|
-
this.#tail.next = node;
|
|
3048
|
-
this.#tail = node;
|
|
3049
|
-
} else {
|
|
3050
|
-
this.#head = node;
|
|
3051
|
-
this.#tail = node;
|
|
3052
|
-
}
|
|
3053
|
-
this.#size++;
|
|
3054
|
-
}
|
|
3055
|
-
dequeue() {
|
|
3056
|
-
const current = this.#head;
|
|
3057
|
-
if (!current) return;
|
|
3058
|
-
this.#head = this.#head.next;
|
|
3059
|
-
this.#size--;
|
|
3060
|
-
return current.value;
|
|
3061
|
-
}
|
|
3062
|
-
peek() {
|
|
3063
|
-
if (!this.#head) return;
|
|
3064
|
-
return this.#head.value;
|
|
3065
|
-
}
|
|
3066
|
-
clear() {
|
|
3067
|
-
this.#head = void 0;
|
|
3068
|
-
this.#tail = void 0;
|
|
3069
|
-
this.#size = 0;
|
|
3070
|
-
}
|
|
3071
|
-
get size() {
|
|
3072
|
-
return this.#size;
|
|
3073
|
-
}
|
|
3074
|
-
*[Symbol.iterator]() {
|
|
3075
|
-
let current = this.#head;
|
|
3076
|
-
while(current){
|
|
3077
|
-
yield current.value;
|
|
3078
|
-
current = current.next;
|
|
3079
|
-
}
|
|
3080
|
-
}
|
|
3081
|
-
*drain() {
|
|
3082
|
-
while(this.#head)yield this.dequeue();
|
|
3083
|
-
}
|
|
3084
|
-
}
|
|
3085
|
-
function pLimit(concurrency) {
|
|
3086
|
-
validateConcurrency(concurrency);
|
|
3087
|
-
const queue = new Queue();
|
|
3088
|
-
let activeCount = 0;
|
|
3089
|
-
const resumeNext = ()=>{
|
|
3090
|
-
if (activeCount < concurrency && queue.size > 0) {
|
|
3091
|
-
queue.dequeue()();
|
|
3092
|
-
activeCount++;
|
|
3093
|
-
}
|
|
3094
|
-
};
|
|
3095
|
-
const next = ()=>{
|
|
3096
|
-
activeCount--;
|
|
3097
|
-
resumeNext();
|
|
3098
|
-
};
|
|
3099
|
-
const run = async (function_, resolve, arguments_)=>{
|
|
3100
|
-
const result = (async ()=>function_(...arguments_))();
|
|
3101
|
-
resolve(result);
|
|
3102
|
-
try {
|
|
3103
|
-
await result;
|
|
3104
|
-
} catch {}
|
|
3105
|
-
next();
|
|
3106
|
-
};
|
|
3107
|
-
const enqueue = (function_, resolve, arguments_)=>{
|
|
3108
|
-
new Promise((internalResolve)=>{
|
|
3109
|
-
queue.enqueue(internalResolve);
|
|
3110
|
-
}).then(run.bind(void 0, function_, resolve, arguments_));
|
|
3111
|
-
(async ()=>{
|
|
3112
|
-
await Promise.resolve();
|
|
3113
|
-
if (activeCount < concurrency) resumeNext();
|
|
3114
|
-
})();
|
|
3115
|
-
};
|
|
3116
|
-
const generator = (function_, ...arguments_)=>new Promise((resolve)=>{
|
|
3117
|
-
enqueue(function_, resolve, arguments_);
|
|
3118
|
-
});
|
|
3119
|
-
Object.defineProperties(generator, {
|
|
3120
|
-
activeCount: {
|
|
3121
|
-
get: ()=>activeCount
|
|
3122
|
-
},
|
|
3123
|
-
pendingCount: {
|
|
3124
|
-
get: ()=>queue.size
|
|
3125
|
-
},
|
|
3126
|
-
clearQueue: {
|
|
3127
|
-
value () {
|
|
3128
|
-
queue.clear();
|
|
3129
|
-
}
|
|
3130
|
-
},
|
|
3131
|
-
concurrency: {
|
|
3132
|
-
get: ()=>concurrency,
|
|
3133
|
-
set (newConcurrency) {
|
|
3134
|
-
validateConcurrency(newConcurrency);
|
|
3135
|
-
concurrency = newConcurrency;
|
|
3136
|
-
queueMicrotask(()=>{
|
|
3137
|
-
while(activeCount < concurrency && queue.size > 0)resumeNext();
|
|
3138
|
-
});
|
|
3139
|
-
}
|
|
3140
|
-
}
|
|
3141
|
-
});
|
|
3142
|
-
return generator;
|
|
3143
|
-
}
|
|
3144
|
-
function validateConcurrency(concurrency) {
|
|
3145
|
-
if (!((Number.isInteger(concurrency) || concurrency === 1 / 0) && concurrency > 0)) throw new TypeError('Expected `concurrency` to be a number from 1 and up');
|
|
3146
|
-
}
|
|
3147
|
-
const debug = getDebug('create-yaml-player');
|
|
3148
|
-
const launchServer = async (dir)=>new Promise((resolve)=>{
|
|
3149
|
-
const server = createServer({
|
|
3150
|
-
root: dir
|
|
3151
|
-
});
|
|
3152
|
-
server.listen(0, '127.0.0.1', ()=>{
|
|
3153
|
-
resolve(server);
|
|
3154
|
-
});
|
|
3155
|
-
});
|
|
3156
|
-
function resolveReportFileName(yamlReportFileName, cliTestId, yamlTestId, fileName) {
|
|
3157
|
-
const baseName = yamlReportFileName ?? cliTestId ?? yamlTestId ?? fileName;
|
|
3158
|
-
return getReportFileName(baseName);
|
|
3159
|
-
}
|
|
3160
|
-
function buildAgentOptions(yamlAgent, reportFileName, fileName) {
|
|
3161
|
-
return {
|
|
3162
|
-
...yamlAgent || {},
|
|
3163
|
-
cache: processCacheConfig(yamlAgent?.cache, fileName),
|
|
3164
|
-
reportFileName
|
|
3165
|
-
};
|
|
3166
|
-
}
|
|
3167
|
-
async function createYamlPlayer(file, script, options) {
|
|
3168
|
-
const yamlScript = script || parseYamlScript((0, __rspack_external_node_fs_5ea92f0c.readFileSync)(file, 'utf-8'), file);
|
|
3169
|
-
const clonedYamlScript = structuredClone(yamlScript);
|
|
3170
|
-
const fileName = basename(file, extname(file));
|
|
3171
|
-
const preference = {
|
|
3172
|
-
headed: options?.headed,
|
|
3173
|
-
keepWindow: options?.keepWindow,
|
|
3174
|
-
reportFileName: resolveReportFileName(clonedYamlScript.agent?.reportFileName, options?.testId, clonedYamlScript.agent?.testId, fileName)
|
|
3175
|
-
};
|
|
3176
|
-
const player = new ScriptPlayer(clonedYamlScript, async ()=>{
|
|
3177
|
-
const freeFn = [];
|
|
3178
|
-
const webTarget = clonedYamlScript.web || clonedYamlScript.target;
|
|
3179
|
-
const targetCount = [
|
|
3180
|
-
void 0 !== webTarget,
|
|
3181
|
-
void 0 !== clonedYamlScript.android,
|
|
3182
|
-
void 0 !== clonedYamlScript.ios,
|
|
3183
|
-
void 0 !== clonedYamlScript.computer,
|
|
3184
|
-
void 0 !== clonedYamlScript.interface
|
|
3185
|
-
].filter(Boolean).length;
|
|
3186
|
-
if (targetCount > 1) {
|
|
3187
|
-
const specifiedTargets = [
|
|
3188
|
-
void 0 !== webTarget ? 'web' : null,
|
|
3189
|
-
void 0 !== clonedYamlScript.android ? 'android' : null,
|
|
3190
|
-
void 0 !== clonedYamlScript.ios ? 'ios' : null,
|
|
3191
|
-
void 0 !== clonedYamlScript.computer ? 'computer' : null,
|
|
3192
|
-
void 0 !== clonedYamlScript.interface ? 'interface' : null
|
|
3193
|
-
].filter(Boolean);
|
|
3194
|
-
throw new Error(`Only one target type can be specified, but found multiple: ${specifiedTargets.join(', ')}. Please specify only one of: web, android, ios, computer, or interface.`);
|
|
3195
|
-
}
|
|
3196
|
-
if (void 0 !== webTarget) {
|
|
3197
|
-
if (void 0 !== clonedYamlScript.target) console.warn("target is deprecated, please use web instead. See https://midscenejs.com/automate-with-scripts-in-yaml for more information. Sorry for the inconvenience.");
|
|
3198
|
-
let localServer;
|
|
3199
|
-
let urlToVisit;
|
|
3200
|
-
if (webTarget.serve) {
|
|
3201
|
-
node_assert('string' == typeof webTarget.url, 'url is required in serve mode');
|
|
3202
|
-
localServer = await launchServer(webTarget.serve);
|
|
3203
|
-
const serverAddress = localServer.server.address();
|
|
3204
|
-
freeFn.push({
|
|
3205
|
-
name: 'local_server',
|
|
3206
|
-
fn: ()=>localServer?.server.close()
|
|
3207
|
-
});
|
|
3208
|
-
urlToVisit = webTarget.url.startsWith('/') ? `http://${serverAddress?.address}:${serverAddress?.port}${webTarget.url}` : `http://${serverAddress?.address}:${serverAddress?.port}/${webTarget.url}`;
|
|
3209
|
-
webTarget.url = urlToVisit;
|
|
3210
|
-
}
|
|
3211
|
-
if (webTarget.cdpEndpoint && webTarget.bridgeMode) throw new Error('cdpEndpoint and bridgeMode are mutually exclusive. Please specify only one.');
|
|
3212
|
-
if (webTarget.cdpEndpoint) {
|
|
3213
|
-
const cdpBrowser = options?.browser ?? await puppeteer.connect({
|
|
3214
|
-
browserWSEndpoint: webTarget.cdpEndpoint,
|
|
3215
|
-
defaultViewport: null
|
|
3216
|
-
});
|
|
3217
|
-
if (webTarget.chromeArgs) console.warn('chromeArgs are not supported in CDP mode (browser is already running). They will be ignored.');
|
|
3218
|
-
const { agent, freeFn: newFreeFn } = await puppeteerAgentForTarget(webTarget, {
|
|
3219
|
-
...preference,
|
|
3220
|
-
...buildAgentOptions(clonedYamlScript.agent, preference.reportFileName, fileName)
|
|
3221
|
-
}, cdpBrowser, options?.page);
|
|
3222
|
-
const cleanFreeFn = newFreeFn.filter((f)=>'puppeteer_browser' !== f.name);
|
|
3223
|
-
if (!options?.browser) cleanFreeFn.push({
|
|
3224
|
-
name: 'cdp_browser_disconnect',
|
|
3225
|
-
fn: ()=>cdpBrowser.disconnect()
|
|
3226
|
-
});
|
|
3227
|
-
freeFn.push(...cleanFreeFn);
|
|
3228
|
-
return {
|
|
3229
|
-
agent,
|
|
3230
|
-
freeFn
|
|
3231
|
-
};
|
|
3232
|
-
}
|
|
3233
|
-
if (!webTarget.bridgeMode) {
|
|
3234
|
-
const { agent, freeFn: newFreeFn } = await puppeteerAgentForTarget(webTarget, {
|
|
3235
|
-
...preference,
|
|
3236
|
-
...buildAgentOptions(clonedYamlScript.agent, preference.reportFileName, fileName)
|
|
3237
|
-
}, options?.browser, options?.page);
|
|
3238
|
-
freeFn.push(...newFreeFn);
|
|
3239
|
-
return {
|
|
3240
|
-
agent,
|
|
3241
|
-
freeFn
|
|
3242
|
-
};
|
|
3243
|
-
}
|
|
3244
|
-
node_assert('newTabWithUrl' === webTarget.bridgeMode || 'currentTab' === webTarget.bridgeMode, `bridgeMode config value must be either "newTabWithUrl" or "currentTab", but got ${webTarget.bridgeMode}`);
|
|
3245
|
-
if (webTarget.userAgent || null != webTarget.viewportWidth || null != webTarget.viewportHeight || null != webTarget.deviceScaleFactor || webTarget.waitForNetworkIdle || webTarget.cookie || webTarget.chromeArgs) console.warn('puppeteer options (userAgent, viewportWidth, viewportHeight, deviceScaleFactor, waitForNetworkIdle, cookie, chromeArgs) are not supported in bridge mode. They will be ignored.');
|
|
3246
|
-
const agent = new AgentOverChromeBridge({
|
|
3247
|
-
closeNewTabsAfterDisconnect: webTarget.closeNewTabsAfterDisconnect,
|
|
3248
|
-
closeConflictServer: true,
|
|
3249
|
-
...buildAgentOptions(clonedYamlScript.agent, preference.reportFileName, fileName)
|
|
3250
|
-
});
|
|
3251
|
-
if ('newTabWithUrl' === webTarget.bridgeMode) await agent.connectNewTabWithUrl(webTarget.url);
|
|
3252
|
-
else {
|
|
3253
|
-
if (webTarget.url) console.warn('url will be ignored in bridge mode with "currentTab"');
|
|
3254
|
-
await agent.connectCurrentTab();
|
|
3255
|
-
}
|
|
3256
|
-
freeFn.push({
|
|
3257
|
-
name: 'destroy_agent_over_chrome_bridge',
|
|
3258
|
-
fn: ()=>agent.destroy()
|
|
3259
|
-
});
|
|
3260
|
-
return {
|
|
3261
|
-
agent,
|
|
3262
|
-
freeFn
|
|
3263
|
-
};
|
|
3264
|
-
}
|
|
3265
|
-
if (void 0 !== clonedYamlScript.android) {
|
|
3266
|
-
const androidTarget = clonedYamlScript.android;
|
|
3267
|
-
const { agentFromAdbDevice } = await import("@midscene/android");
|
|
3268
|
-
const agent = await agentFromAdbDevice(androidTarget?.deviceId, {
|
|
3269
|
-
...androidTarget,
|
|
3270
|
-
...buildAgentOptions(clonedYamlScript.agent, preference.reportFileName, fileName)
|
|
3271
|
-
});
|
|
3272
|
-
if (androidTarget?.launch) await agent.launch(androidTarget.launch);
|
|
3273
|
-
freeFn.push({
|
|
3274
|
-
name: 'destroy_android_agent',
|
|
3275
|
-
fn: ()=>agent.destroy()
|
|
3276
|
-
});
|
|
3277
|
-
return {
|
|
3278
|
-
agent,
|
|
3279
|
-
freeFn
|
|
3280
|
-
};
|
|
3281
|
-
}
|
|
3282
|
-
if (void 0 !== clonedYamlScript.ios) {
|
|
3283
|
-
const iosTarget = clonedYamlScript.ios;
|
|
3284
|
-
const { agentFromWebDriverAgent } = await import("@midscene/ios");
|
|
3285
|
-
const agent = await agentFromWebDriverAgent({
|
|
3286
|
-
...iosTarget,
|
|
3287
|
-
...buildAgentOptions(clonedYamlScript.agent, preference.reportFileName, fileName)
|
|
3288
|
-
});
|
|
3289
|
-
if (iosTarget?.launch) await agent.launch(iosTarget.launch);
|
|
3290
|
-
freeFn.push({
|
|
3291
|
-
name: 'destroy_ios_agent',
|
|
3292
|
-
fn: ()=>agent.destroy()
|
|
3293
|
-
});
|
|
3294
|
-
return {
|
|
3295
|
-
agent,
|
|
3296
|
-
freeFn
|
|
3297
|
-
};
|
|
3298
|
-
}
|
|
3299
|
-
if (void 0 !== clonedYamlScript.computer) {
|
|
3300
|
-
const computerTarget = clonedYamlScript.computer;
|
|
3301
|
-
const { agentForComputer } = await import("@midscene/computer");
|
|
3302
|
-
const agent = await agentForComputer({
|
|
3303
|
-
...computerTarget,
|
|
3304
|
-
...buildAgentOptions(clonedYamlScript.agent, preference.reportFileName, fileName)
|
|
3305
|
-
});
|
|
3306
|
-
freeFn.push({
|
|
3307
|
-
name: 'destroy_computer_agent',
|
|
3308
|
-
fn: ()=>agent.destroy()
|
|
3309
|
-
});
|
|
3310
|
-
return {
|
|
3311
|
-
agent,
|
|
3312
|
-
freeFn
|
|
3313
|
-
};
|
|
3314
|
-
}
|
|
3315
|
-
if (void 0 !== clonedYamlScript.interface) {
|
|
3316
|
-
const interfaceTarget = clonedYamlScript.interface;
|
|
3317
|
-
const moduleSpecifier = interfaceTarget.module;
|
|
3318
|
-
let finalModuleSpecifier;
|
|
3319
|
-
if (moduleSpecifier.startsWith('./') || moduleSpecifier.startsWith('../') || node_path.isAbsolute(moduleSpecifier)) {
|
|
3320
|
-
const resolvedPath = join(process.cwd(), moduleSpecifier);
|
|
3321
|
-
finalModuleSpecifier = resolvedPath;
|
|
3322
|
-
} else finalModuleSpecifier = moduleSpecifier;
|
|
3323
|
-
debug('importing module config', interfaceTarget.module, 'with export config', interfaceTarget.export, 'final module specifier', finalModuleSpecifier);
|
|
3324
|
-
const importedModule = await import(finalModuleSpecifier);
|
|
3325
|
-
const DeviceClass = interfaceTarget.export ? importedModule[interfaceTarget.export] : importedModule.default || importedModule;
|
|
3326
|
-
debug('DeviceClass', DeviceClass, 'with param', interfaceTarget.param);
|
|
3327
|
-
const device = new DeviceClass(interfaceTarget.param || {});
|
|
3328
|
-
debug('creating agent from device', device);
|
|
3329
|
-
const agent = createAgent(device, buildAgentOptions(clonedYamlScript.agent, preference.reportFileName, fileName));
|
|
3330
|
-
freeFn.push({
|
|
3331
|
-
name: 'destroy_general_interface_agent',
|
|
3332
|
-
fn: ()=>{
|
|
3333
|
-
agent.destroy();
|
|
3334
|
-
}
|
|
3335
|
-
});
|
|
3336
|
-
return {
|
|
3337
|
-
agent,
|
|
3338
|
-
freeFn
|
|
3339
|
-
};
|
|
3340
|
-
}
|
|
3341
|
-
throw new Error('No valid interface configuration found in the yaml script, should be either "web", "android", "ios", "computer", or "interface"');
|
|
3342
|
-
}, void 0, file);
|
|
3343
|
-
return player;
|
|
3344
|
-
}
|
|
3345
|
-
var chalk_source = __webpack_require__("../../node_modules/.pnpm/chalk@4.1.2/node_modules/chalk/source/index.js");
|
|
3346
|
-
var source_default = /*#__PURE__*/ __webpack_require__.n(chalk_source);
|
|
3347
|
-
const isTTY = process.env.MIDSCENE_CLI_LOG_ON_NON_TTY ? false : process.stdout.isTTY;
|
|
3348
|
-
const printer_indent = ' ';
|
|
3349
|
-
const spinnerInterval = 80;
|
|
3350
|
-
const spinnerFrames = [
|
|
3351
|
-
'◰',
|
|
3352
|
-
'◳',
|
|
3353
|
-
'◲',
|
|
3354
|
-
'◱'
|
|
3355
|
-
];
|
|
3356
|
-
const currentSpinningFrame = ()=>spinnerFrames[Math.floor(Date.now() / spinnerInterval) % spinnerFrames.length];
|
|
3357
|
-
function indicatorForStatus(status) {
|
|
3358
|
-
if ('init' === status) return source_default().gray('◌');
|
|
3359
|
-
if ('running' === status) return source_default().yellowBright(currentSpinningFrame());
|
|
3360
|
-
if ('done' === status) return source_default().green('✔︎');
|
|
3361
|
-
if ('error' === status) return source_default().red('✘');
|
|
3362
|
-
}
|
|
3363
|
-
const contextInfo = (context)=>{
|
|
3364
|
-
const filePath = context.file;
|
|
3365
|
-
const filePathToShow = external_node_path_relative(process.cwd(), filePath);
|
|
3366
|
-
const fileNameToPrint = `${source_default().gray(`${filePathToShow}`)}`;
|
|
3367
|
-
const fileStatusText = indicatorForStatus(context.player.status);
|
|
3368
|
-
const contextActionText = void 0 === context.player.currentTaskIndex && 'running' === context.player.status ? source_default().gray('(navigating)') : '';
|
|
3369
|
-
const errorText = context.player.errorInSetup ? `\n${printer_indent}${source_default().red('error:')} ${context.player.errorInSetup?.message}\n${printer_indent}${printer_indent}${context.player.errorInSetup?.stack}` : '';
|
|
3370
|
-
const outputFile = context.player.output;
|
|
3371
|
-
const outputText = outputFile && Object.keys(context.player.result || {}).length > 0 ? `\n${printer_indent}${source_default().gray(`output: ${outputFile}`)}` : '';
|
|
3372
|
-
const reportFile = context.player.reportFile;
|
|
3373
|
-
const reportText = reportFile ? `\n${printer_indent}${source_default().gray(`report: ${reportFile}`)}` : '';
|
|
3374
|
-
const agentStatusTip = context.player.agentStatusTip;
|
|
3375
|
-
const agentStatusText = agentStatusTip ? `\n${printer_indent}${source_default().gray(`agent status: ${agentStatusTip}`)}` : '';
|
|
3376
|
-
const mergedText = `${fileStatusText} ${fileNameToPrint} ${contextActionText}${outputText}${reportText}${errorText}${agentStatusText}`.trim();
|
|
3377
|
-
return {
|
|
3378
|
-
fileNameToPrint,
|
|
3379
|
-
fileStatusText,
|
|
3380
|
-
contextActionText,
|
|
3381
|
-
outputText,
|
|
3382
|
-
reportText,
|
|
3383
|
-
mergedText
|
|
3384
|
-
};
|
|
3385
|
-
};
|
|
3386
|
-
const singleTaskInfo = (task)=>{
|
|
3387
|
-
let stepText = '';
|
|
3388
|
-
if ('init' === task.status) stepText = '';
|
|
3389
|
-
else if ('running' === task.status || 'error' === task.status) if (void 0 === task.currentStep) stepText = source_default().gray('(navigating)');
|
|
3390
|
-
else if ('number' == typeof task.currentStep) {
|
|
3391
|
-
const actionText = '';
|
|
3392
|
-
stepText = source_default().gray(`(task ${task.currentStep + 1}/${task.totalSteps}${actionText})`.trim());
|
|
3393
|
-
} else stepText = source_default().gray('(unknown task)');
|
|
3394
|
-
const errorText = 'error' === task.status ? `\n${printer_indent}${source_default().gray('error:')}\n${printer_indent}${printer_indent}${task.error?.message}` : '';
|
|
3395
|
-
const statusText = indicatorForStatus(task.status);
|
|
3396
|
-
const mergedLine = `${statusText} ${task.name} ${stepText}${errorText}`;
|
|
3397
|
-
return {
|
|
3398
|
-
nameText: task.name,
|
|
3399
|
-
stepText,
|
|
3400
|
-
errorText,
|
|
3401
|
-
itemStatusText: statusText,
|
|
3402
|
-
mergedLine
|
|
3403
|
-
};
|
|
3404
|
-
};
|
|
3405
|
-
function paddingLines(lines) {
|
|
3406
|
-
return lines.map((line)=>`${printer_indent}${line}`);
|
|
3407
|
-
}
|
|
3408
|
-
const contextTaskListSummary = (taskStatusArray, context)=>{
|
|
3409
|
-
const prefixLines = [];
|
|
3410
|
-
const currentLine = [];
|
|
3411
|
-
const suffixText = [];
|
|
3412
|
-
const { mergedText: fileInfo } = contextInfo(context);
|
|
3413
|
-
if (!context.player.errorInSetup) for (const task of taskStatusArray){
|
|
3414
|
-
const { mergedLine } = singleTaskInfo(task);
|
|
3415
|
-
if ('init' === context.player.status) suffixText.push(mergedLine);
|
|
3416
|
-
else if ('running' === context.player.status) currentLine.push(mergedLine);
|
|
3417
|
-
else if ('done' === context.player.status) prefixLines.push(mergedLine);
|
|
3418
|
-
else if ('error' === context.player.status) prefixLines.push(mergedLine);
|
|
3419
|
-
}
|
|
3420
|
-
const lines = [
|
|
3421
|
-
fileInfo
|
|
3422
|
-
];
|
|
3423
|
-
if (prefixLines.length > 0) lines.push(...paddingLines(prefixLines));
|
|
3424
|
-
if (currentLine.length > 0) lines.push(...paddingLines(currentLine));
|
|
3425
|
-
if (suffixText.length > 0) lines.push(...paddingLines(suffixText));
|
|
3426
|
-
return lines.join('\n');
|
|
3427
|
-
};
|
|
3428
|
-
const copyProperty = (to, from, property, ignoreNonConfigurable)=>{
|
|
3429
|
-
if ('length' === property || 'prototype' === property) return;
|
|
3430
|
-
if ('arguments' === property || 'caller' === property) return;
|
|
3431
|
-
const toDescriptor = Object.getOwnPropertyDescriptor(to, property);
|
|
3432
|
-
const fromDescriptor = Object.getOwnPropertyDescriptor(from, property);
|
|
3433
|
-
if (!canCopyProperty(toDescriptor, fromDescriptor) && ignoreNonConfigurable) return;
|
|
3434
|
-
Object.defineProperty(to, property, fromDescriptor);
|
|
3435
|
-
};
|
|
3436
|
-
const canCopyProperty = function(toDescriptor, fromDescriptor) {
|
|
3437
|
-
return void 0 === toDescriptor || toDescriptor.configurable || toDescriptor.writable === fromDescriptor.writable && toDescriptor.enumerable === fromDescriptor.enumerable && toDescriptor.configurable === fromDescriptor.configurable && (toDescriptor.writable || toDescriptor.value === fromDescriptor.value);
|
|
3438
|
-
};
|
|
3439
|
-
const changePrototype = (to, from)=>{
|
|
3440
|
-
const fromPrototype = Object.getPrototypeOf(from);
|
|
3441
|
-
if (fromPrototype === Object.getPrototypeOf(to)) return;
|
|
3442
|
-
Object.setPrototypeOf(to, fromPrototype);
|
|
3443
|
-
};
|
|
3444
|
-
const wrappedToString = (withName, fromBody)=>`/* Wrapped ${withName}*/\n${fromBody}`;
|
|
3445
|
-
const toStringDescriptor = Object.getOwnPropertyDescriptor(Function.prototype, 'toString');
|
|
3446
|
-
const toStringName = Object.getOwnPropertyDescriptor(Function.prototype.toString, 'name');
|
|
3447
|
-
const changeToString = (to, from, name)=>{
|
|
3448
|
-
const withName = '' === name ? '' : `with ${name.trim()}() `;
|
|
3449
|
-
const newToString = wrappedToString.bind(null, withName, from.toString());
|
|
3450
|
-
Object.defineProperty(newToString, 'name', toStringName);
|
|
3451
|
-
const { writable, enumerable, configurable } = toStringDescriptor;
|
|
3452
|
-
Object.defineProperty(to, 'toString', {
|
|
3453
|
-
value: newToString,
|
|
3454
|
-
writable,
|
|
3455
|
-
enumerable,
|
|
3456
|
-
configurable
|
|
3457
|
-
});
|
|
3458
|
-
};
|
|
3459
|
-
function mimicFunction(to, from, { ignoreNonConfigurable = false } = {}) {
|
|
3460
|
-
const { name } = to;
|
|
3461
|
-
for (const property of Reflect.ownKeys(from))copyProperty(to, from, property, ignoreNonConfigurable);
|
|
3462
|
-
changePrototype(to, from);
|
|
3463
|
-
changeToString(to, from, name);
|
|
3464
|
-
return to;
|
|
3465
|
-
}
|
|
3466
|
-
const calledFunctions = new WeakMap();
|
|
3467
|
-
const onetime_onetime = (function_, options = {})=>{
|
|
3468
|
-
if ('function' != typeof function_) throw new TypeError('Expected a function');
|
|
3469
|
-
let returnValue;
|
|
3470
|
-
let callCount = 0;
|
|
3471
|
-
const functionName = function_.displayName || function_.name || '<anonymous>';
|
|
3472
|
-
const onetime = function(...arguments_) {
|
|
3473
|
-
calledFunctions.set(onetime, ++callCount);
|
|
3474
|
-
if (1 === callCount) {
|
|
3475
|
-
returnValue = function_.apply(this, arguments_);
|
|
3476
|
-
function_ = void 0;
|
|
3477
|
-
} else if (true === options.throw) throw new Error(`Function \`${functionName}\` can only be called once`);
|
|
3478
|
-
return returnValue;
|
|
3479
|
-
};
|
|
3480
|
-
mimicFunction(onetime, function_);
|
|
3481
|
-
calledFunctions.set(onetime, callCount);
|
|
3482
|
-
return onetime;
|
|
3483
|
-
};
|
|
3484
|
-
onetime_onetime.callCount = (function_)=>{
|
|
3485
|
-
if (!calledFunctions.has(function_)) throw new Error(`The given function \`${function_.name}\` is not wrapped by the \`onetime\` package`);
|
|
3486
|
-
return calledFunctions.get(function_);
|
|
3487
|
-
};
|
|
3488
|
-
const node_modules_onetime = onetime_onetime;
|
|
3489
|
-
const signals = [];
|
|
3490
|
-
signals.push('SIGHUP', 'SIGINT', 'SIGTERM');
|
|
3491
|
-
if ('win32' !== process.platform) signals.push('SIGALRM', 'SIGABRT', 'SIGVTALRM', 'SIGXCPU', 'SIGXFSZ', 'SIGUSR2', 'SIGTRAP', 'SIGSYS', 'SIGQUIT', 'SIGIOT');
|
|
3492
|
-
if ('linux' === process.platform) signals.push('SIGIO', 'SIGPOLL', 'SIGPWR', 'SIGSTKFLT');
|
|
3493
|
-
const processOk = (process1)=>!!process1 && 'object' == typeof process1 && 'function' == typeof process1.removeListener && 'function' == typeof process1.emit && 'function' == typeof process1.reallyExit && 'function' == typeof process1.listeners && 'function' == typeof process1.kill && 'number' == typeof process1.pid && 'function' == typeof process1.on;
|
|
3494
|
-
const kExitEmitter = Symbol.for('signal-exit emitter');
|
|
3495
|
-
const global = globalThis;
|
|
3496
|
-
const ObjectDefineProperty = Object.defineProperty.bind(Object);
|
|
3497
|
-
class Emitter {
|
|
3498
|
-
emitted = {
|
|
3499
|
-
afterExit: false,
|
|
3500
|
-
exit: false
|
|
3501
|
-
};
|
|
3502
|
-
listeners = {
|
|
3503
|
-
afterExit: [],
|
|
3504
|
-
exit: []
|
|
3505
|
-
};
|
|
3506
|
-
count = 0;
|
|
3507
|
-
id = Math.random();
|
|
3508
|
-
constructor(){
|
|
3509
|
-
if (global[kExitEmitter]) return global[kExitEmitter];
|
|
3510
|
-
ObjectDefineProperty(global, kExitEmitter, {
|
|
3511
|
-
value: this,
|
|
3512
|
-
writable: false,
|
|
3513
|
-
enumerable: false,
|
|
3514
|
-
configurable: false
|
|
3515
|
-
});
|
|
3516
|
-
}
|
|
3517
|
-
on(ev, fn) {
|
|
3518
|
-
this.listeners[ev].push(fn);
|
|
3519
|
-
}
|
|
3520
|
-
removeListener(ev, fn) {
|
|
3521
|
-
const list = this.listeners[ev];
|
|
3522
|
-
const i = list.indexOf(fn);
|
|
3523
|
-
if (-1 === i) return;
|
|
3524
|
-
if (0 === i && 1 === list.length) list.length = 0;
|
|
3525
|
-
else list.splice(i, 1);
|
|
3526
|
-
}
|
|
3527
|
-
emit(ev, code, signal) {
|
|
3528
|
-
if (this.emitted[ev]) return false;
|
|
3529
|
-
this.emitted[ev] = true;
|
|
3530
|
-
let ret = false;
|
|
3531
|
-
for (const fn of this.listeners[ev])ret = true === fn(code, signal) || ret;
|
|
3532
|
-
if ('exit' === ev) ret = this.emit('afterExit', code, signal) || ret;
|
|
3533
|
-
return ret;
|
|
3534
|
-
}
|
|
3535
|
-
}
|
|
3536
|
-
class SignalExitBase {
|
|
3537
|
-
}
|
|
3538
|
-
const signalExitWrap = (handler)=>({
|
|
3539
|
-
onExit (cb, opts) {
|
|
3540
|
-
return handler.onExit(cb, opts);
|
|
3541
|
-
},
|
|
3542
|
-
load () {
|
|
3543
|
-
return handler.load();
|
|
3544
|
-
},
|
|
3545
|
-
unload () {
|
|
3546
|
-
return handler.unload();
|
|
3547
|
-
}
|
|
3548
|
-
});
|
|
3549
|
-
class SignalExitFallback extends SignalExitBase {
|
|
3550
|
-
onExit() {
|
|
3551
|
-
return ()=>{};
|
|
3552
|
-
}
|
|
3553
|
-
load() {}
|
|
3554
|
-
unload() {}
|
|
3555
|
-
}
|
|
3556
|
-
class SignalExit extends SignalExitBase {
|
|
3557
|
-
#hupSig = 'win32' === mjs_process.platform ? 'SIGINT' : 'SIGHUP';
|
|
3558
|
-
#emitter = new Emitter();
|
|
3559
|
-
#process;
|
|
3560
|
-
#originalProcessEmit;
|
|
3561
|
-
#originalProcessReallyExit;
|
|
3562
|
-
#sigListeners = {};
|
|
3563
|
-
#loaded = false;
|
|
3564
|
-
constructor(process1){
|
|
3565
|
-
super();
|
|
3566
|
-
this.#process = process1;
|
|
3567
|
-
this.#sigListeners = {};
|
|
3568
|
-
for (const sig of signals)this.#sigListeners[sig] = ()=>{
|
|
3569
|
-
const listeners = this.#process.listeners(sig);
|
|
3570
|
-
let { count } = this.#emitter;
|
|
3571
|
-
const p = process1;
|
|
3572
|
-
if ('object' == typeof p.__signal_exit_emitter__ && 'number' == typeof p.__signal_exit_emitter__.count) count += p.__signal_exit_emitter__.count;
|
|
3573
|
-
if (listeners.length === count) {
|
|
3574
|
-
this.unload();
|
|
3575
|
-
const ret = this.#emitter.emit('exit', null, sig);
|
|
3576
|
-
const s = 'SIGHUP' === sig ? this.#hupSig : sig;
|
|
3577
|
-
if (!ret) process1.kill(process1.pid, s);
|
|
3578
|
-
}
|
|
3579
|
-
};
|
|
3580
|
-
this.#originalProcessReallyExit = process1.reallyExit;
|
|
3581
|
-
this.#originalProcessEmit = process1.emit;
|
|
3582
|
-
}
|
|
3583
|
-
onExit(cb, opts) {
|
|
3584
|
-
if (!processOk(this.#process)) return ()=>{};
|
|
3585
|
-
if (false === this.#loaded) this.load();
|
|
3586
|
-
const ev = opts?.alwaysLast ? 'afterExit' : 'exit';
|
|
3587
|
-
this.#emitter.on(ev, cb);
|
|
3588
|
-
return ()=>{
|
|
3589
|
-
this.#emitter.removeListener(ev, cb);
|
|
3590
|
-
if (0 === this.#emitter.listeners['exit'].length && 0 === this.#emitter.listeners['afterExit'].length) this.unload();
|
|
3591
|
-
};
|
|
3592
|
-
}
|
|
3593
|
-
load() {
|
|
3594
|
-
if (this.#loaded) return;
|
|
3595
|
-
this.#loaded = true;
|
|
3596
|
-
this.#emitter.count += 1;
|
|
3597
|
-
for (const sig of signals)try {
|
|
3598
|
-
const fn = this.#sigListeners[sig];
|
|
3599
|
-
if (fn) this.#process.on(sig, fn);
|
|
3600
|
-
} catch (_) {}
|
|
3601
|
-
this.#process.emit = (ev, ...a)=>this.#processEmit(ev, ...a);
|
|
3602
|
-
this.#process.reallyExit = (code)=>this.#processReallyExit(code);
|
|
3603
|
-
}
|
|
3604
|
-
unload() {
|
|
3605
|
-
if (!this.#loaded) return;
|
|
3606
|
-
this.#loaded = false;
|
|
3607
|
-
signals.forEach((sig)=>{
|
|
3608
|
-
const listener = this.#sigListeners[sig];
|
|
3609
|
-
if (!listener) throw new Error('Listener not defined for signal: ' + sig);
|
|
3610
|
-
try {
|
|
3611
|
-
this.#process.removeListener(sig, listener);
|
|
3612
|
-
} catch (_) {}
|
|
3613
|
-
});
|
|
3614
|
-
this.#process.emit = this.#originalProcessEmit;
|
|
3615
|
-
this.#process.reallyExit = this.#originalProcessReallyExit;
|
|
3616
|
-
this.#emitter.count -= 1;
|
|
3617
|
-
}
|
|
3618
|
-
#processReallyExit(code) {
|
|
3619
|
-
if (!processOk(this.#process)) return 0;
|
|
3620
|
-
this.#process.exitCode = code || 0;
|
|
3621
|
-
this.#emitter.emit('exit', this.#process.exitCode, null);
|
|
3622
|
-
return this.#originalProcessReallyExit.call(this.#process, this.#process.exitCode);
|
|
3623
|
-
}
|
|
3624
|
-
#processEmit(ev, ...args) {
|
|
3625
|
-
const og = this.#originalProcessEmit;
|
|
3626
|
-
if (!('exit' === ev && processOk(this.#process))) return og.call(this.#process, ev, ...args);
|
|
3627
|
-
{
|
|
3628
|
-
if ('number' == typeof args[0]) this.#process.exitCode = args[0];
|
|
3629
|
-
const ret = og.call(this.#process, ev, ...args);
|
|
3630
|
-
this.#emitter.emit('exit', this.#process.exitCode, null);
|
|
3631
|
-
return ret;
|
|
3632
|
-
}
|
|
3633
|
-
}
|
|
3634
|
-
}
|
|
3635
|
-
const mjs_process = globalThis.process;
|
|
3636
|
-
const { onExit, load, unload } = signalExitWrap(processOk(mjs_process) ? new SignalExit(mjs_process) : new SignalExitFallback());
|
|
3637
|
-
const terminal = node_process.stderr.isTTY ? node_process.stderr : node_process.stdout.isTTY ? node_process.stdout : void 0;
|
|
3638
|
-
const restoreCursor = terminal ? node_modules_onetime(()=>{
|
|
3639
|
-
onExit(()=>{
|
|
3640
|
-
terminal.write('\u001B[?25h');
|
|
3641
|
-
}, {
|
|
3642
|
-
alwaysLast: true
|
|
3643
|
-
});
|
|
3644
|
-
}) : ()=>{};
|
|
3645
|
-
const restore_cursor = restoreCursor;
|
|
3646
|
-
function _define_property(obj, key, value) {
|
|
3647
|
-
if (key in obj) Object.defineProperty(obj, key, {
|
|
3648
|
-
value: value,
|
|
3649
|
-
enumerable: true,
|
|
3650
|
-
configurable: true,
|
|
3651
|
-
writable: true
|
|
3652
|
-
});
|
|
3653
|
-
else obj[key] = value;
|
|
3654
|
-
return obj;
|
|
3655
|
-
}
|
|
3656
|
-
const DEFAULT_RENDER_INTERVAL = 160;
|
|
3657
|
-
const ESC = '\x1B[';
|
|
3658
|
-
const CLEAR_LINE = `${ESC}K`;
|
|
3659
|
-
const MOVE_CURSOR_ONE_ROW_UP = `${ESC}1A`;
|
|
3660
|
-
const HIDE_CURSOR = `${ESC}?25l`;
|
|
3661
|
-
const SHOW_CURSOR = `${ESC}?25h`;
|
|
3662
|
-
const SYNC_START = `${ESC}?2026h`;
|
|
3663
|
-
const SYNC_END = `${ESC}?2026l`;
|
|
3664
|
-
class TTYWindowRenderer {
|
|
3665
|
-
start() {
|
|
3666
|
-
this.finished = false;
|
|
3667
|
-
this.renderInterval = setInterval(()=>this.flushBuffer(), this.options.interval);
|
|
3668
|
-
}
|
|
3669
|
-
stop() {
|
|
3670
|
-
this.flushBuffer();
|
|
3671
|
-
this.write(SHOW_CURSOR, 'output');
|
|
3672
|
-
this.cleanups.splice(0).map((fn)=>fn());
|
|
3673
|
-
clearInterval(this.renderInterval);
|
|
3674
|
-
}
|
|
3675
|
-
finish() {
|
|
3676
|
-
this.finished = true;
|
|
3677
|
-
this.flushBuffer();
|
|
3678
|
-
clearInterval(this.renderInterval);
|
|
3679
|
-
}
|
|
3680
|
-
flushBuffer() {
|
|
3681
|
-
if (0 === this.buffer.length) return this.render();
|
|
3682
|
-
let current;
|
|
3683
|
-
for (const next of this.buffer.splice(0)){
|
|
3684
|
-
if (!current) {
|
|
3685
|
-
current = next;
|
|
3686
|
-
continue;
|
|
3687
|
-
}
|
|
3688
|
-
if (current.type !== next.type) {
|
|
3689
|
-
this.render(current.message, current.type);
|
|
3690
|
-
current = next;
|
|
3691
|
-
continue;
|
|
3692
|
-
}
|
|
3693
|
-
current.message += next.message;
|
|
3694
|
-
}
|
|
3695
|
-
if (current) this.render(current?.message, current?.type);
|
|
3696
|
-
}
|
|
3697
|
-
render(message, type = 'output') {
|
|
3698
|
-
if (this.finished) {
|
|
3699
|
-
this.clearWindow();
|
|
3700
|
-
return this.write(message || '', type);
|
|
3701
|
-
}
|
|
3702
|
-
const windowContent = this.options.getWindow();
|
|
3703
|
-
const rowCount = getRenderedRowCount(windowContent, this.options.outputStream);
|
|
3704
|
-
let padding = this.windowHeight - rowCount;
|
|
3705
|
-
if (padding > 0 && message) padding -= getRenderedRowCount([
|
|
3706
|
-
message
|
|
3707
|
-
], this.options.outputStream);
|
|
3708
|
-
this.write(SYNC_START);
|
|
3709
|
-
this.clearWindow();
|
|
3710
|
-
if (message) this.write(message, type);
|
|
3711
|
-
if (padding > 0) this.write('\n'.repeat(padding));
|
|
3712
|
-
this.write(windowContent.join('\n'));
|
|
3713
|
-
this.write(SYNC_END);
|
|
3714
|
-
this.windowHeight = rowCount + Math.max(0, padding);
|
|
3715
|
-
}
|
|
3716
|
-
clearWindow() {
|
|
3717
|
-
if (0 === this.windowHeight) return;
|
|
3718
|
-
this.write(CLEAR_LINE);
|
|
3719
|
-
for(let i = 1; i < this.windowHeight; i++)this.write(`${MOVE_CURSOR_ONE_ROW_UP}${CLEAR_LINE}`);
|
|
3720
|
-
this.windowHeight = 0;
|
|
3721
|
-
}
|
|
3722
|
-
interceptStream(stream, type) {
|
|
3723
|
-
const original = stream.write;
|
|
3724
|
-
stream.write = (chunk, _, callback)=>{
|
|
3725
|
-
if (chunk) if (this.finished) this.write(chunk.toString(), type);
|
|
3726
|
-
else this.buffer.push({
|
|
3727
|
-
type,
|
|
3728
|
-
message: chunk.toString()
|
|
3729
|
-
});
|
|
3730
|
-
callback?.();
|
|
3731
|
-
};
|
|
3732
|
-
return function() {
|
|
3733
|
-
stream.write = original;
|
|
3734
|
-
};
|
|
3735
|
-
}
|
|
3736
|
-
write(message, type = 'output') {
|
|
3737
|
-
this.streams[type](message);
|
|
3738
|
-
}
|
|
3739
|
-
constructor(options){
|
|
3740
|
-
_define_property(this, "options", void 0);
|
|
3741
|
-
_define_property(this, "streams", void 0);
|
|
3742
|
-
_define_property(this, "buffer", []);
|
|
3743
|
-
_define_property(this, "renderInterval", void 0);
|
|
3744
|
-
_define_property(this, "windowHeight", 0);
|
|
3745
|
-
_define_property(this, "finished", false);
|
|
3746
|
-
_define_property(this, "cleanups", []);
|
|
3747
|
-
this.options = {
|
|
3748
|
-
interval: DEFAULT_RENDER_INTERVAL,
|
|
3749
|
-
...options
|
|
3750
|
-
};
|
|
3751
|
-
this.streams = {
|
|
3752
|
-
output: options.outputStream.write.bind(options.outputStream),
|
|
3753
|
-
error: options.errorStream.write.bind(options.errorStream)
|
|
3754
|
-
};
|
|
3755
|
-
this.cleanups.push(this.interceptStream(process.stdout, 'output'), this.interceptStream(process.stderr, 'error'));
|
|
3756
|
-
restore_cursor();
|
|
3757
|
-
this.write(HIDE_CURSOR, 'output');
|
|
3758
|
-
this.start();
|
|
3759
|
-
}
|
|
3760
|
-
}
|
|
3761
|
-
function getRenderedRowCount(contents, stream) {
|
|
3762
|
-
let count = 0;
|
|
3763
|
-
const columns = 'columns' in stream ? stream.columns : 80;
|
|
3764
|
-
for (const content of contents){
|
|
3765
|
-
const rows = content.split('\n');
|
|
3766
|
-
for (const row of rows){
|
|
3767
|
-
const text = stripVTControlCharacters(row);
|
|
3768
|
-
count += Math.max(1, Math.ceil(text.length / columns));
|
|
3769
|
-
}
|
|
3770
|
-
}
|
|
3771
|
-
return count;
|
|
3772
|
-
}
|
|
3773
|
-
function batch_runner_define_property(obj, key, value) {
|
|
3774
|
-
if (key in obj) Object.defineProperty(obj, key, {
|
|
3775
|
-
value: value,
|
|
3776
|
-
enumerable: true,
|
|
3777
|
-
configurable: true,
|
|
3778
|
-
writable: true
|
|
3779
|
-
});
|
|
3780
|
-
else obj[key] = value;
|
|
3781
|
-
return obj;
|
|
3782
|
-
}
|
|
3783
|
-
class BatchRunner {
|
|
3784
|
-
async run() {
|
|
3785
|
-
const { keepWindow, headed } = this.config;
|
|
3786
|
-
this.printExecutionPlan();
|
|
3787
|
-
const fileContextList = [];
|
|
3788
|
-
let browser = null;
|
|
3789
|
-
let sharedPage = null;
|
|
3790
|
-
try {
|
|
3791
|
-
for (const file of this.config.files){
|
|
3792
|
-
const fileConfig = await this.loadFileConfig(file);
|
|
3793
|
-
const context = await this.createFileContext(file, fileConfig, {
|
|
3794
|
-
headed,
|
|
3795
|
-
keepWindow
|
|
3796
|
-
});
|
|
3797
|
-
fileContextList.push(context);
|
|
3798
|
-
}
|
|
3799
|
-
const needsBrowser = fileContextList.some((ctx)=>Object.keys(ctx.executionConfig.web || ctx.executionConfig.target || {}).length > 0);
|
|
3800
|
-
if (needsBrowser && this.config.shareBrowserContext) {
|
|
3801
|
-
const globalWebConfig = this.config.globalConfig?.web;
|
|
3802
|
-
if (globalWebConfig?.cdpEndpoint) browser = await puppeteer.connect({
|
|
3803
|
-
browserWSEndpoint: globalWebConfig.cdpEndpoint,
|
|
3804
|
-
defaultViewport: null
|
|
3805
|
-
});
|
|
3806
|
-
else {
|
|
3807
|
-
const width = globalWebConfig?.viewportWidth ?? defaultViewportWidth;
|
|
3808
|
-
const height = globalWebConfig?.viewportHeight ?? defaultViewportHeight;
|
|
3809
|
-
const args = buildChromeArgs({
|
|
3810
|
-
userAgent: globalWebConfig?.userAgent,
|
|
3811
|
-
windowSize: headed ? {
|
|
3812
|
-
width,
|
|
3813
|
-
height
|
|
3814
|
-
} : void 0,
|
|
3815
|
-
chromeArgs: globalWebConfig?.chromeArgs
|
|
3816
|
-
});
|
|
3817
|
-
browser = await puppeteer.launch({
|
|
3818
|
-
headless: !headed,
|
|
3819
|
-
defaultViewport: headed ? null : {
|
|
3820
|
-
width,
|
|
3821
|
-
height
|
|
3822
|
-
},
|
|
3823
|
-
args,
|
|
3824
|
-
acceptInsecureCerts: globalWebConfig?.acceptInsecureCerts
|
|
3825
|
-
});
|
|
3826
|
-
}
|
|
3827
|
-
sharedPage = await browser.newPage();
|
|
3828
|
-
for (const context of fileContextList){
|
|
3829
|
-
context.options.browser = browser;
|
|
3830
|
-
context.options.page = sharedPage;
|
|
3831
|
-
}
|
|
3832
|
-
}
|
|
3833
|
-
const { executedResults, notExecutedContexts } = await this.executeFiles(fileContextList);
|
|
3834
|
-
this.results = await this.processResults(executedResults, notExecutedContexts);
|
|
3835
|
-
} finally{
|
|
3836
|
-
if (browser && !this.config.keepWindow) {
|
|
3837
|
-
const isCdp = !!this.config.globalConfig?.web?.cdpEndpoint;
|
|
3838
|
-
if (isCdp) browser.disconnect();
|
|
3839
|
-
else await browser.close();
|
|
3840
|
-
}
|
|
3841
|
-
await this.generateOutputIndex();
|
|
3842
|
-
}
|
|
3843
|
-
return this.results;
|
|
3844
|
-
}
|
|
3845
|
-
async createFileContext(file, fileConfig, options) {
|
|
3846
|
-
const { globalConfig } = this.config;
|
|
3847
|
-
const clonedFileConfig = JSON.parse(JSON.stringify(fileConfig));
|
|
3848
|
-
if (clonedFileConfig.target) {
|
|
3849
|
-
clonedFileConfig.web = {
|
|
3850
|
-
...clonedFileConfig.target,
|
|
3851
|
-
...clonedFileConfig.web
|
|
3852
|
-
};
|
|
3853
|
-
delete clonedFileConfig.target;
|
|
3854
|
-
}
|
|
3855
|
-
if (globalConfig?.target) {
|
|
3856
|
-
globalConfig.web = {
|
|
3857
|
-
...globalConfig.target,
|
|
3858
|
-
...globalConfig.web
|
|
3859
|
-
};
|
|
3860
|
-
delete globalConfig.target;
|
|
3861
|
-
}
|
|
3862
|
-
const executionConfig = lodash_merge(clonedFileConfig, globalConfig);
|
|
3863
|
-
return {
|
|
3864
|
-
file,
|
|
3865
|
-
executionConfig,
|
|
3866
|
-
options
|
|
3867
|
-
};
|
|
3868
|
-
}
|
|
3869
|
-
async executeFiles(fileContextList) {
|
|
3870
|
-
const executedResults = [];
|
|
3871
|
-
const notExecutedContexts = [];
|
|
3872
|
-
const allFileContexts = [];
|
|
3873
|
-
for (const context of fileContextList){
|
|
3874
|
-
const player = await createYamlPlayer(context.file, context.executionConfig, context.options);
|
|
3875
|
-
allFileContexts.push({
|
|
3876
|
-
file: context.file,
|
|
3877
|
-
player
|
|
3878
|
-
});
|
|
3879
|
-
}
|
|
3880
|
-
let ttyRenderer;
|
|
3881
|
-
if (isTTY) {
|
|
3882
|
-
const summaryContents = ()=>{
|
|
3883
|
-
const summary = [
|
|
3884
|
-
''
|
|
3885
|
-
];
|
|
3886
|
-
for (const context of allFileContexts)summary.push(contextTaskListSummary(context.player.taskStatusList, context));
|
|
3887
|
-
summary.push('');
|
|
3888
|
-
return summary;
|
|
3889
|
-
};
|
|
3890
|
-
ttyRenderer = new TTYWindowRenderer({
|
|
3891
|
-
outputStream: process.stdout,
|
|
3892
|
-
errorStream: process.stderr,
|
|
3893
|
-
getWindow: summaryContents,
|
|
3894
|
-
interval: spinnerInterval
|
|
3895
|
-
});
|
|
3896
|
-
ttyRenderer.start();
|
|
3897
|
-
}
|
|
3898
|
-
try {
|
|
3899
|
-
const executeFile = async (context)=>{
|
|
3900
|
-
const allFileContext = allFileContexts.find((c)=>c.file === context.file);
|
|
3901
|
-
if (!allFileContext) throw new Error(`Player not found for file: ${context.file}`);
|
|
3902
|
-
if (!isTTY) {
|
|
3903
|
-
const { mergedText } = contextInfo(allFileContext);
|
|
3904
|
-
console.log(mergedText);
|
|
3905
|
-
}
|
|
3906
|
-
if (context.outputPath) allFileContext.player.output = context.outputPath;
|
|
3907
|
-
const startTime = Date.now();
|
|
3908
|
-
await allFileContext.player.run();
|
|
3909
|
-
const endTime = Date.now();
|
|
3910
|
-
const duration = endTime - startTime;
|
|
3911
|
-
const executedContext = {
|
|
3912
|
-
file: context.file,
|
|
3913
|
-
player: allFileContext.player,
|
|
3914
|
-
duration
|
|
3915
|
-
};
|
|
3916
|
-
if (!isTTY) console.log(contextTaskListSummary(allFileContext.player.taskStatusList, executedContext));
|
|
3917
|
-
return executedContext;
|
|
3918
|
-
};
|
|
3919
|
-
await this.executeConcurrently(fileContextList, executeFile, executedResults, notExecutedContexts);
|
|
3920
|
-
if (!isTTY) {
|
|
3921
|
-
console.log('\n📋 Execution Results:');
|
|
3922
|
-
for (const context of executedResults)console.log(contextTaskListSummary(context.player.taskStatusList, context));
|
|
3923
|
-
}
|
|
3924
|
-
} finally{
|
|
3925
|
-
if (ttyRenderer) ttyRenderer.stop();
|
|
3926
|
-
}
|
|
3927
|
-
return {
|
|
3928
|
-
executedResults,
|
|
3929
|
-
notExecutedContexts
|
|
3930
|
-
};
|
|
3931
|
-
}
|
|
3932
|
-
async executeConcurrently(fileContextList, executeFile, executedResults, notExecutedContexts) {
|
|
3933
|
-
const limit = pLimit(this.config.concurrent);
|
|
3934
|
-
if (this.config.continueOnError) {
|
|
3935
|
-
const tasks = fileContextList.map((context)=>limit(async ()=>{
|
|
3936
|
-
const executedContext = await executeFile(context);
|
|
3937
|
-
executedResults.push(executedContext);
|
|
3938
|
-
}));
|
|
3939
|
-
await Promise.allSettled(tasks);
|
|
3940
|
-
} else {
|
|
3941
|
-
let shouldStop = false;
|
|
3942
|
-
const stopLock = {
|
|
3943
|
-
value: false
|
|
3944
|
-
};
|
|
3945
|
-
const tasks = fileContextList.map((context)=>limit(async ()=>{
|
|
3946
|
-
if (stopLock.value) return void notExecutedContexts.push({
|
|
3947
|
-
file: context.file,
|
|
3948
|
-
player: null
|
|
3949
|
-
});
|
|
3950
|
-
const executedContext = await executeFile(context);
|
|
3951
|
-
executedResults.push(executedContext);
|
|
3952
|
-
if ('error' === executedContext.player.status && !stopLock.value) {
|
|
3953
|
-
stopLock.value = true;
|
|
3954
|
-
shouldStop = true;
|
|
3955
|
-
}
|
|
3956
|
-
}));
|
|
3957
|
-
await Promise.allSettled(tasks);
|
|
3958
|
-
if (shouldStop) {
|
|
3959
|
-
for (const context of fileContextList)if (!executedResults.some((r)=>r.file === context.file) && !notExecutedContexts.some((ctx)=>ctx.file === context.file)) notExecutedContexts.push({
|
|
3960
|
-
file: context.file,
|
|
3961
|
-
player: null
|
|
3962
|
-
});
|
|
3963
|
-
}
|
|
3964
|
-
}
|
|
3965
|
-
}
|
|
3966
|
-
async processResults(executedContexts, notExecutedContexts) {
|
|
3967
|
-
const results = [];
|
|
3968
|
-
for (const context of executedContexts){
|
|
3969
|
-
const { file, player, duration } = context;
|
|
3970
|
-
const hasFailedTasks = player.taskStatusList?.some((task)=>'error' === task.status) ?? false;
|
|
3971
|
-
const hasPlayerError = 'error' === player.status;
|
|
3972
|
-
let success;
|
|
3973
|
-
let resultType;
|
|
3974
|
-
if (hasPlayerError) {
|
|
3975
|
-
success = false;
|
|
3976
|
-
resultType = 'failed';
|
|
3977
|
-
} else if (hasFailedTasks) {
|
|
3978
|
-
success = false;
|
|
3979
|
-
resultType = 'partialFailed';
|
|
3980
|
-
} else {
|
|
3981
|
-
success = true;
|
|
3982
|
-
resultType = 'success';
|
|
3983
|
-
}
|
|
3984
|
-
let reportFile;
|
|
3985
|
-
if (player.reportFile) reportFile = player.reportFile;
|
|
3986
|
-
let outputPath = player.output || void 0;
|
|
3987
|
-
if (outputPath && !(0, __rspack_external_node_fs_5ea92f0c.existsSync)(outputPath)) outputPath = void 0;
|
|
3988
|
-
let errorMessage;
|
|
3989
|
-
if (player.errorInSetup?.message) errorMessage = player.errorInSetup.message;
|
|
3990
|
-
else if (hasPlayerError || hasFailedTasks) {
|
|
3991
|
-
const taskErrors = player.taskStatusList?.filter((task)=>'error' === task.status && task.error?.message).map((task)=>task.error.message);
|
|
3992
|
-
errorMessage = taskErrors && taskErrors.length > 0 ? taskErrors.join('; ') : hasPlayerError ? 'Execution failed' : 'Some tasks failed';
|
|
3993
|
-
}
|
|
3994
|
-
results.push({
|
|
3995
|
-
file,
|
|
3996
|
-
success,
|
|
3997
|
-
executed: true,
|
|
3998
|
-
output: outputPath,
|
|
3999
|
-
report: reportFile,
|
|
4000
|
-
duration,
|
|
4001
|
-
resultType,
|
|
4002
|
-
error: errorMessage
|
|
4003
|
-
});
|
|
4004
|
-
}
|
|
4005
|
-
for (const context of notExecutedContexts)results.push({
|
|
4006
|
-
file: context.file,
|
|
4007
|
-
success: false,
|
|
4008
|
-
executed: false,
|
|
4009
|
-
output: void 0,
|
|
4010
|
-
report: void 0,
|
|
4011
|
-
duration: 0,
|
|
4012
|
-
resultType: 'notExecuted',
|
|
4013
|
-
error: 'Not executed (previous task failed)'
|
|
4014
|
-
});
|
|
4015
|
-
return results;
|
|
4016
|
-
}
|
|
4017
|
-
async loadFileConfig(file) {
|
|
4018
|
-
const content = (0, __rspack_external_node_fs_5ea92f0c.readFileSync)(file, 'utf8');
|
|
4019
|
-
return parseYamlScript(content, file);
|
|
4020
|
-
}
|
|
4021
|
-
getSummaryAbsolutePath() {
|
|
4022
|
-
return external_node_path_resolve(getMidsceneRunSubDir('output'), this.config.summary);
|
|
4023
|
-
}
|
|
4024
|
-
printExecutionPlan() {
|
|
4025
|
-
console.log(' Scripts:');
|
|
4026
|
-
for (const file of this.config.files)console.log(` - ${file}`);
|
|
4027
|
-
console.log('📋 Execution plan');
|
|
4028
|
-
console.log(` Concurrency: ${this.config.concurrent}`);
|
|
4029
|
-
console.log(` Keep window: ${this.config.keepWindow}`);
|
|
4030
|
-
console.log(` Headed: ${this.config.headed}`);
|
|
4031
|
-
console.log(` Continue on error: ${this.config.continueOnError}`);
|
|
4032
|
-
console.log(` Share browser context: ${this.config.shareBrowserContext ?? false}`);
|
|
4033
|
-
console.log(` Summary output: ${this.config.summary}`);
|
|
4034
|
-
}
|
|
4035
|
-
async generateOutputIndex() {
|
|
4036
|
-
const indexPath = external_node_path_resolve(getMidsceneRunSubDir('output'), this.config.summary);
|
|
4037
|
-
const outputDir = dirname(indexPath);
|
|
4038
|
-
try {
|
|
4039
|
-
(0, __rspack_external_node_fs_5ea92f0c.mkdirSync)(outputDir, {
|
|
4040
|
-
recursive: true
|
|
4041
|
-
});
|
|
4042
|
-
const indexData = {
|
|
4043
|
-
summary: {
|
|
4044
|
-
total: this.results.length,
|
|
4045
|
-
successful: this.results.filter((r)=>'success' === r.resultType).length,
|
|
4046
|
-
failed: this.results.filter((r)=>'failed' === r.resultType).length,
|
|
4047
|
-
partialFailed: this.results.filter((r)=>'partialFailed' === r.resultType).length,
|
|
4048
|
-
notExecuted: this.results.filter((r)=>'notExecuted' === r.resultType).length,
|
|
4049
|
-
totalDuration: this.results.reduce((sum, r)=>sum + (r.duration || 0), 0),
|
|
4050
|
-
generatedAt: new Date().toLocaleString()
|
|
4051
|
-
},
|
|
4052
|
-
results: this.results.map((result)=>({
|
|
4053
|
-
script: external_node_path_relative(outputDir, result.file),
|
|
4054
|
-
success: result.success,
|
|
4055
|
-
resultType: result.resultType,
|
|
4056
|
-
output: result.output ? (()=>{
|
|
4057
|
-
const relativePath = external_node_path_relative(outputDir, result.output);
|
|
4058
|
-
return relativePath.startsWith('.') ? relativePath : `./${relativePath}`;
|
|
4059
|
-
})() : void 0,
|
|
4060
|
-
report: result.report ? external_node_path_relative(outputDir, result.report) : void 0,
|
|
4061
|
-
error: result.error,
|
|
4062
|
-
duration: result.duration
|
|
4063
|
-
}))
|
|
4064
|
-
};
|
|
4065
|
-
(0, __rspack_external_node_fs_5ea92f0c.writeFileSync)(indexPath, JSON.stringify(indexData, null, 2));
|
|
4066
|
-
console.log('Execution finished:');
|
|
4067
|
-
} catch (error) {
|
|
4068
|
-
console.error('Failed to generate output index:', error);
|
|
4069
|
-
}
|
|
4070
|
-
}
|
|
4071
|
-
getExecutionSummary() {
|
|
4072
|
-
const successful = this.results.filter((r)=>'success' === r.resultType).length;
|
|
4073
|
-
const failed = this.results.filter((r)=>'failed' === r.resultType).length;
|
|
4074
|
-
const partialFailed = this.results.filter((r)=>'partialFailed' === r.resultType).length;
|
|
4075
|
-
const notExecuted = this.results.filter((r)=>'notExecuted' === r.resultType).length;
|
|
4076
|
-
return {
|
|
4077
|
-
total: this.results.length,
|
|
4078
|
-
successful,
|
|
4079
|
-
failed,
|
|
4080
|
-
partialFailed,
|
|
4081
|
-
notExecuted,
|
|
4082
|
-
totalDuration: this.results.reduce((sum, r)=>sum + (r.duration || 0), 0)
|
|
4083
|
-
};
|
|
4084
|
-
}
|
|
4085
|
-
getFailedFiles() {
|
|
4086
|
-
return this.results.filter((r)=>'failed' === r.resultType).map((r)=>r.file);
|
|
4087
|
-
}
|
|
4088
|
-
getPartialFailedFiles() {
|
|
4089
|
-
return this.results.filter((r)=>'partialFailed' === r.resultType).map((r)=>r.file);
|
|
4090
|
-
}
|
|
4091
|
-
getNotExecutedFiles() {
|
|
4092
|
-
return this.results.filter((r)=>'notExecuted' === r.resultType).map((r)=>r.file);
|
|
4093
|
-
}
|
|
4094
|
-
getSuccessfulFiles() {
|
|
4095
|
-
return this.results.filter((r)=>'success' === r.resultType).map((r)=>r.file);
|
|
4096
|
-
}
|
|
4097
|
-
getResults() {
|
|
4098
|
-
return [
|
|
4099
|
-
...this.results
|
|
4100
|
-
];
|
|
4101
|
-
}
|
|
4102
|
-
printExecutionSummary() {
|
|
4103
|
-
const summary = this.getExecutionSummary();
|
|
4104
|
-
const success = 0 === summary.failed && 0 === summary.partialFailed && 0 === summary.notExecuted;
|
|
4105
|
-
console.log('\n📊 Execution Summary:');
|
|
4106
|
-
console.log(` Total files: ${summary.total}`);
|
|
4107
|
-
console.log(` Successful: ${summary.successful}`);
|
|
4108
|
-
console.log(` Failed: ${summary.failed}`);
|
|
4109
|
-
console.log(` Partial failed: ${summary.partialFailed}`);
|
|
4110
|
-
console.log(` Not executed: ${summary.notExecuted}`);
|
|
4111
|
-
console.log(` Duration: ${(summary.totalDuration / 1000).toFixed(2)}s`);
|
|
4112
|
-
console.log(` Summary: ${this.getSummaryAbsolutePath()}`);
|
|
4113
|
-
if (summary.successful > 0) {
|
|
4114
|
-
console.log('\n✅ Successful files:');
|
|
4115
|
-
this.getSuccessfulFiles().forEach((file)=>{
|
|
4116
|
-
console.log(` ${file}`);
|
|
4117
|
-
});
|
|
4118
|
-
}
|
|
4119
|
-
if (summary.failed > 0) {
|
|
4120
|
-
console.log('\n❌ Failed files');
|
|
4121
|
-
this.getFailedFiles().forEach((file)=>{
|
|
4122
|
-
console.log(` ${file}`);
|
|
4123
|
-
});
|
|
4124
|
-
}
|
|
4125
|
-
if (summary.partialFailed > 0) {
|
|
4126
|
-
console.log('\n⚠️ Partial failed files (some tasks failed with continueOnError)');
|
|
4127
|
-
this.getPartialFailedFiles().forEach((file)=>{
|
|
4128
|
-
console.log(` ${file}`);
|
|
4129
|
-
});
|
|
4130
|
-
}
|
|
4131
|
-
if (summary.notExecuted > 0) {
|
|
4132
|
-
console.log('\n⏸️ Not executed files');
|
|
4133
|
-
this.getNotExecutedFiles().forEach((file)=>{
|
|
4134
|
-
console.log(` ${file}`);
|
|
4135
|
-
});
|
|
4136
|
-
}
|
|
4137
|
-
if (success) console.log('\n🎉 All files executed successfully!');
|
|
4138
|
-
else console.log('\n⚠️ Some files failed or were not executed.');
|
|
4139
|
-
return success;
|
|
4140
|
-
}
|
|
4141
|
-
constructor(config){
|
|
4142
|
-
batch_runner_define_property(this, "config", void 0);
|
|
4143
|
-
batch_runner_define_property(this, "results", []);
|
|
4144
|
-
this.config = config;
|
|
4145
|
-
}
|
|
4146
|
-
}
|
|
3029
|
+
var package_namespaceObject = JSON.parse('{"rE":"1.8.8-beta-20260601092817.0"}');
|
|
4147
3030
|
var brace_expansion = __webpack_require__("../../node_modules/.pnpm/brace-expansion@2.0.1/node_modules/brace-expansion/index.js");
|
|
4148
3031
|
const MAX_PATTERN_LENGTH = 65536;
|
|
4149
3032
|
const assertValidPattern = (pattern)=>{
|
|
@@ -9549,7 +8432,7 @@ var __webpack_modules__ = {
|
|
|
9549
8432
|
yargsParser.looksLikeNumber = looksLikeNumber;
|
|
9550
8433
|
var external_assert_ = __webpack_require__("assert");
|
|
9551
8434
|
new RegExp("\x1b(?:\\[(?:\\d+[ABCDEFGJKSTm]|\\d+;\\d+[Hfm]|\\d+;\\d+;\\d+m|6n|s|u|\\?25[lh])|\\w)", 'g');
|
|
9552
|
-
const
|
|
8435
|
+
const node = {
|
|
9553
8436
|
fs: {
|
|
9554
8437
|
readFileSync: external_fs_.readFileSync,
|
|
9555
8438
|
writeFile: external_fs_.writeFile
|
|
@@ -9699,7 +8582,7 @@ var __webpack_modules__ = {
|
|
|
9699
8582
|
locale: y18n.locale
|
|
9700
8583
|
};
|
|
9701
8584
|
}
|
|
9702
|
-
const y18n_y18n = (opts)=>lib_y18n(opts,
|
|
8585
|
+
const y18n_y18n = (opts)=>lib_y18n(opts, node);
|
|
9703
8586
|
const node_modules_y18n = y18n_y18n;
|
|
9704
8587
|
let esm_dirname;
|
|
9705
8588
|
try {
|
|
@@ -10283,7 +9166,7 @@ var __webpack_modules__ = {
|
|
|
10283
9166
|
function resolveYamlMerge(data) {
|
|
10284
9167
|
return '<<' === data || null === data;
|
|
10285
9168
|
}
|
|
10286
|
-
var
|
|
9169
|
+
var js_yaml_merge = new js_yaml_type('tag:yaml.org,2002:merge', {
|
|
10287
9170
|
kind: 'scalar',
|
|
10288
9171
|
resolve: resolveYamlMerge
|
|
10289
9172
|
});
|
|
@@ -10442,7 +9325,7 @@ var __webpack_modules__ = {
|
|
|
10442
9325
|
var _default = core.extend({
|
|
10443
9326
|
implicit: [
|
|
10444
9327
|
js_yaml_timestamp,
|
|
10445
|
-
|
|
9328
|
+
js_yaml_merge
|
|
10446
9329
|
],
|
|
10447
9330
|
explicit: [
|
|
10448
9331
|
binary,
|
|
@@ -11790,7 +10673,7 @@ var __webpack_modules__ = {
|
|
|
11790
10673
|
throw new Error('Function yaml.' + from + " is removed in js-yaml 4. Use yaml." + to + ' instead, which is now safe by default.');
|
|
11791
10674
|
};
|
|
11792
10675
|
}
|
|
11793
|
-
var
|
|
10676
|
+
var load = loader.load;
|
|
11794
10677
|
loader.loadAll;
|
|
11795
10678
|
dumper.dump;
|
|
11796
10679
|
renamed('safeLoad', 'load');
|
|
@@ -11818,19 +10701,19 @@ var __webpack_modules__ = {
|
|
|
11818
10701
|
return allFiles;
|
|
11819
10702
|
}
|
|
11820
10703
|
async function parseConfigYaml(configYamlPath) {
|
|
11821
|
-
const basePath =
|
|
10704
|
+
const basePath = external_node_path_dirname(external_node_path_resolve(configYamlPath));
|
|
11822
10705
|
const configContent = (0, __rspack_external_node_fs_5ea92f0c.readFileSync)(configYamlPath, 'utf8');
|
|
11823
10706
|
const interpolatedContent = interpolateEnvVars(configContent);
|
|
11824
10707
|
let configYaml;
|
|
11825
10708
|
try {
|
|
11826
|
-
configYaml =
|
|
10709
|
+
configYaml = load(interpolatedContent);
|
|
11827
10710
|
} catch (error) {
|
|
11828
10711
|
throw new Error(`Failed to parse config YAML: ${error}`);
|
|
11829
10712
|
}
|
|
11830
10713
|
if (!configYaml?.files || !Array.isArray(configYaml?.files)) throw new Error('Config YAML must contain a "files" array');
|
|
11831
10714
|
const files = await expandFilePatterns(configYaml?.files, basePath);
|
|
11832
10715
|
if (0 === files.length) throw new Error('No YAML files found matching the patterns in "files"');
|
|
11833
|
-
const configFileName =
|
|
10716
|
+
const configFileName = external_node_path_basename(configYamlPath, external_node_path_extname(configYamlPath));
|
|
11834
10717
|
const timestamp = Date.now();
|
|
11835
10718
|
const defaultSummary = `${configFileName}-${timestamp}.json`;
|
|
11836
10719
|
const config = {
|
|
@@ -11867,7 +10750,7 @@ var __webpack_modules__ = {
|
|
|
11867
10750
|
const finalHeaded = keepWindow || headed;
|
|
11868
10751
|
let files = parsedConfig.files;
|
|
11869
10752
|
if (options?.files && options.files.length > 0) {
|
|
11870
|
-
const basePath =
|
|
10753
|
+
const basePath = external_node_path_dirname(external_node_path_resolve(configYamlPath));
|
|
11871
10754
|
files = await expandFilePatterns(options.files, basePath);
|
|
11872
10755
|
}
|
|
11873
10756
|
return {
|
|
@@ -11907,7 +10790,7 @@ var __webpack_modules__ = {
|
|
|
11907
10790
|
}
|
|
11908
10791
|
};
|
|
11909
10792
|
}
|
|
11910
|
-
const
|
|
10793
|
+
const debug = getDebug('midscene:cli');
|
|
11911
10794
|
function kebabToCamel(str) {
|
|
11912
10795
|
return str.replace(/-([a-z])/g, (_, letter)=>letter.toUpperCase());
|
|
11913
10796
|
}
|
|
@@ -11966,7 +10849,7 @@ Usage:
|
|
|
11966
10849
|
type: 'boolean',
|
|
11967
10850
|
description: `Turn on logging to help debug why certain keys or values are not being set as you expect, default is ${config_factory_defaultConfig.dotenvDebug}`
|
|
11968
10851
|
}
|
|
11969
|
-
}).version('version', 'Show version number', "1.8.
|
|
10852
|
+
}).version('version', 'Show version number', "1.8.8-beta-20260601092817.0").help().epilogue(`For complete list of configuration options, please visit:
|
|
11970
10853
|
• Web options: https://midscenejs.com/automate-with-scripts-in-yaml#the-web-part
|
|
11971
10854
|
• Android options: https://midscenejs.com/automate-with-scripts-in-yaml#the-android-part
|
|
11972
10855
|
• iOS options: https://midscenejs.com/automate-with-scripts-in-yaml#the-ios-part
|
|
@@ -11976,7 +10859,7 @@ Examples:
|
|
|
11976
10859
|
$0 script.yaml --android.device-id emulator-5554 --android.ime-strategy yadb-for-non-ascii
|
|
11977
10860
|
$0 script.yaml --ios.wda-port 8100 --ios.auto-dismiss-keyboard`).wrap(yargs().terminalWidth());
|
|
11978
10861
|
const argv = await args.argv;
|
|
11979
|
-
|
|
10862
|
+
debug('argv', argv);
|
|
11980
10863
|
const transformedArgv = {
|
|
11981
10864
|
...argv
|
|
11982
10865
|
};
|
|
@@ -12000,7 +10883,7 @@ Examples:
|
|
|
12000
10883
|
};
|
|
12001
10884
|
};
|
|
12002
10885
|
async function matchYamlFiles(fileGlob, options) {
|
|
12003
|
-
if ((0, __rspack_external_node_fs_5ea92f0c.existsSync)(fileGlob) && (0, __rspack_external_node_fs_5ea92f0c.statSync)(fileGlob).isDirectory()) fileGlob =
|
|
10886
|
+
if ((0, __rspack_external_node_fs_5ea92f0c.existsSync)(fileGlob) && (0, __rspack_external_node_fs_5ea92f0c.statSync)(fileGlob).isDirectory()) fileGlob = external_node_path_join(fileGlob, '**/*.{yml,yaml}');
|
|
12004
10887
|
const { cwd } = options || {};
|
|
12005
10888
|
const ignore = [
|
|
12006
10889
|
'**/node_modules/**'
|
|
@@ -12014,6 +10897,341 @@ Examples:
|
|
|
12014
10897
|
});
|
|
12015
10898
|
return files.filter((file)=>file.endsWith('.yml') || file.endsWith('.yaml')).sort();
|
|
12016
10899
|
}
|
|
10900
|
+
const notExecutedError = 'Not executed (previous task failed)';
|
|
10901
|
+
function execution_summary_createNotExecutedYamlResult(file) {
|
|
10902
|
+
return {
|
|
10903
|
+
file,
|
|
10904
|
+
success: false,
|
|
10905
|
+
executed: false,
|
|
10906
|
+
output: void 0,
|
|
10907
|
+
report: void 0,
|
|
10908
|
+
duration: 0,
|
|
10909
|
+
resultType: 'notExecuted',
|
|
10910
|
+
error: notExecutedError
|
|
10911
|
+
};
|
|
10912
|
+
}
|
|
10913
|
+
function getExecutionSummary(results) {
|
|
10914
|
+
return {
|
|
10915
|
+
total: results.length,
|
|
10916
|
+
successful: getResultsByType(results, 'success').length,
|
|
10917
|
+
failed: getResultsByType(results, 'failed').length,
|
|
10918
|
+
partialFailed: getResultsByType(results, 'partialFailed').length,
|
|
10919
|
+
notExecuted: getResultsByType(results, 'notExecuted').length,
|
|
10920
|
+
totalDuration: results.reduce((sum, r)=>sum + (r.duration || 0), 0)
|
|
10921
|
+
};
|
|
10922
|
+
}
|
|
10923
|
+
function getResultsByType(results, resultType) {
|
|
10924
|
+
return results.filter((result)=>result.resultType === resultType);
|
|
10925
|
+
}
|
|
10926
|
+
function getSummaryAbsolutePath(summary) {
|
|
10927
|
+
return external_node_path_resolve(getMidsceneRunSubDir('output'), summary);
|
|
10928
|
+
}
|
|
10929
|
+
function execution_summary_writeExecutionSummaryFile(summary, results) {
|
|
10930
|
+
const indexPath = getSummaryAbsolutePath(summary);
|
|
10931
|
+
const outputDir = external_node_path_dirname(indexPath);
|
|
10932
|
+
(0, __rspack_external_node_fs_5ea92f0c.mkdirSync)(outputDir, {
|
|
10933
|
+
recursive: true
|
|
10934
|
+
});
|
|
10935
|
+
const executionSummary = getExecutionSummary(results);
|
|
10936
|
+
const indexData = {
|
|
10937
|
+
summary: {
|
|
10938
|
+
...executionSummary,
|
|
10939
|
+
generatedAt: new Date().toLocaleString()
|
|
10940
|
+
},
|
|
10941
|
+
results: results.map((result)=>({
|
|
10942
|
+
script: external_node_path_relative(outputDir, result.file),
|
|
10943
|
+
success: result.success,
|
|
10944
|
+
resultType: result.resultType,
|
|
10945
|
+
output: result.output ? (()=>{
|
|
10946
|
+
const relativePath = external_node_path_relative(outputDir, result.output);
|
|
10947
|
+
return relativePath.startsWith('.') ? relativePath : `./${relativePath}`;
|
|
10948
|
+
})() : void 0,
|
|
10949
|
+
report: result.report ? external_node_path_relative(outputDir, result.report) : void 0,
|
|
10950
|
+
error: result.error,
|
|
10951
|
+
duration: result.duration
|
|
10952
|
+
}))
|
|
10953
|
+
};
|
|
10954
|
+
(0, __rspack_external_node_fs_5ea92f0c.writeFileSync)(indexPath, JSON.stringify(indexData, null, 2));
|
|
10955
|
+
return indexPath;
|
|
10956
|
+
}
|
|
10957
|
+
function execution_summary_printExecutionPlan(config) {
|
|
10958
|
+
console.log(' Scripts:');
|
|
10959
|
+
for (const file of config.files)console.log(` - ${file}`);
|
|
10960
|
+
console.log('📋 Execution plan');
|
|
10961
|
+
console.log(` Concurrency: ${config.concurrent}`);
|
|
10962
|
+
console.log(` Keep window: ${config.keepWindow}`);
|
|
10963
|
+
console.log(` Headed: ${config.headed}`);
|
|
10964
|
+
console.log(` Continue on error: ${config.continueOnError}`);
|
|
10965
|
+
console.log(` Share browser context: ${config.shareBrowserContext ?? false}`);
|
|
10966
|
+
console.log(` Summary output: ${config.summary}`);
|
|
10967
|
+
}
|
|
10968
|
+
function execution_summary_printExecutionFinished() {
|
|
10969
|
+
console.log('Execution finished:');
|
|
10970
|
+
}
|
|
10971
|
+
function printExecutionSummary(results, summaryPath) {
|
|
10972
|
+
const summary = getExecutionSummary(results);
|
|
10973
|
+
const successfulFiles = getResultsByType(results, 'success');
|
|
10974
|
+
const failedFiles = getResultsByType(results, 'failed');
|
|
10975
|
+
const partialFailedFiles = getResultsByType(results, 'partialFailed');
|
|
10976
|
+
const notExecutedFiles = getResultsByType(results, 'notExecuted');
|
|
10977
|
+
const success = 0 === summary.failed && 0 === summary.partialFailed && 0 === summary.notExecuted;
|
|
10978
|
+
console.log('\n📊 Execution Summary:');
|
|
10979
|
+
console.log(` Total files: ${summary.total}`);
|
|
10980
|
+
console.log(` Successful: ${summary.successful}`);
|
|
10981
|
+
console.log(` Failed: ${summary.failed}`);
|
|
10982
|
+
console.log(` Partial failed: ${summary.partialFailed}`);
|
|
10983
|
+
console.log(` Not executed: ${summary.notExecuted}`);
|
|
10984
|
+
console.log(` Duration: ${(summary.totalDuration / 1000).toFixed(2)}s`);
|
|
10985
|
+
console.log(` Summary: ${summaryPath}`);
|
|
10986
|
+
if (successfulFiles.length > 0) {
|
|
10987
|
+
console.log('\n✅ Successful files:');
|
|
10988
|
+
successfulFiles.forEach((result)=>{
|
|
10989
|
+
console.log(` ${result.file}`);
|
|
10990
|
+
});
|
|
10991
|
+
}
|
|
10992
|
+
if (failedFiles.length > 0) {
|
|
10993
|
+
console.log('\n❌ Failed files');
|
|
10994
|
+
failedFiles.forEach((result)=>{
|
|
10995
|
+
console.log(` ${result.file}`);
|
|
10996
|
+
if (result.error) console.log(` Error: ${result.error}`);
|
|
10997
|
+
});
|
|
10998
|
+
}
|
|
10999
|
+
if (partialFailedFiles.length > 0) {
|
|
11000
|
+
console.log('\n⚠️ Partial failed files (some tasks failed with continueOnError)');
|
|
11001
|
+
partialFailedFiles.forEach((result)=>{
|
|
11002
|
+
console.log(` ${result.file}`);
|
|
11003
|
+
if (result.error) console.log(` Error: ${result.error}`);
|
|
11004
|
+
});
|
|
11005
|
+
}
|
|
11006
|
+
if (notExecutedFiles.length > 0) {
|
|
11007
|
+
console.log('\n⏸️ Not executed files');
|
|
11008
|
+
notExecutedFiles.forEach((result)=>{
|
|
11009
|
+
console.log(` ${result.file}`);
|
|
11010
|
+
});
|
|
11011
|
+
}
|
|
11012
|
+
if (success) console.log('\n🎉 All files executed successfully!');
|
|
11013
|
+
else console.log('\n⚠️ Some files failed or were not executed.');
|
|
11014
|
+
return success;
|
|
11015
|
+
}
|
|
11016
|
+
const DEFAULT_YAML_TEST_TIMEOUT = 0;
|
|
11017
|
+
const toPosixPath = (value)=>value.split(external_node_path_sep).join('/');
|
|
11018
|
+
const toImportLiteral = (value)=>JSON.stringify(toPosixPath(value));
|
|
11019
|
+
const toVirtualModuleId = (fileStem)=>`virtual:midscene-yaml/${fileStem}.test.ts`;
|
|
11020
|
+
const safeFileStem = (file, index)=>{
|
|
11021
|
+
const base = external_node_path_basename(file, external_node_path_extname(file)).replace(/[^a-zA-Z0-9._-]+/g, '-').replace(/^-+|-+$/g, '');
|
|
11022
|
+
return `${String(index + 1).padStart(3, '0')}-${base || 'case'}`;
|
|
11023
|
+
};
|
|
11024
|
+
const resolveTestName = (projectDir, yamlFile)=>{
|
|
11025
|
+
const relativePath = external_node_path_relative(projectDir, yamlFile);
|
|
11026
|
+
return toPosixPath(relativePath.startsWith('..') ? yamlFile : relativePath);
|
|
11027
|
+
};
|
|
11028
|
+
const createGeneratedTestContent = (options)=>{
|
|
11029
|
+
const testOptions = {
|
|
11030
|
+
testName: options.testName,
|
|
11031
|
+
yamlFile: options.yamlFile,
|
|
11032
|
+
resultFile: options.resultFile,
|
|
11033
|
+
...options.caseOptions ? {
|
|
11034
|
+
caseOptions: options.caseOptions
|
|
11035
|
+
} : {},
|
|
11036
|
+
...options.webRuntimeOptions ? {
|
|
11037
|
+
webRuntimeOptions: options.webRuntimeOptions
|
|
11038
|
+
} : {}
|
|
11039
|
+
};
|
|
11040
|
+
return `import { defineYamlCaseTest } from ${toImportLiteral(options.frameworkImport)};
|
|
11041
|
+
|
|
11042
|
+
defineYamlCaseTest(${JSON.stringify(testOptions, null, 2)});
|
|
11043
|
+
`;
|
|
11044
|
+
};
|
|
11045
|
+
const createGeneratedBatchTestContent = (options)=>{
|
|
11046
|
+
const testOptions = {
|
|
11047
|
+
testName: options.testName,
|
|
11048
|
+
config: options.config,
|
|
11049
|
+
resultFiles: options.resultFiles
|
|
11050
|
+
};
|
|
11051
|
+
return `import { defineYamlBatchTest } from ${toImportLiteral(options.frameworkImport)};
|
|
11052
|
+
|
|
11053
|
+
defineYamlBatchTest(${JSON.stringify(testOptions, null, 2)});
|
|
11054
|
+
`;
|
|
11055
|
+
};
|
|
11056
|
+
const resolveDefaultFrameworkImport = ()=>{
|
|
11057
|
+
const entry = process.argv[1] ? external_node_path_resolve(process.argv[1]) : '';
|
|
11058
|
+
const candidates = [
|
|
11059
|
+
entry ? external_node_path_join(external_node_path_dirname(entry), 'framework', 'index.js') : '',
|
|
11060
|
+
entry ? external_node_path_join(external_node_path_dirname(entry), '..', 'dist', 'lib', 'framework', 'index.js') : ''
|
|
11061
|
+
].filter(Boolean);
|
|
11062
|
+
const matched = candidates.find((candidate)=>(0, __rspack_external_node_fs_5ea92f0c.existsSync)(candidate));
|
|
11063
|
+
return matched || '@midscene/cli/dist/lib/framework/index.js';
|
|
11064
|
+
};
|
|
11065
|
+
function createRstestYamlProject(options) {
|
|
11066
|
+
const projectDir = external_node_path_resolve(options.projectDir || process.cwd());
|
|
11067
|
+
const outputDir = options.outputDir || external_node_path_join(getMidsceneRunSubDir('tmp'), `rstest-yaml-${Date.now()}`);
|
|
11068
|
+
const resultDir = options.resultDir || external_node_path_join(outputDir, 'results');
|
|
11069
|
+
const frameworkImport = options.frameworkImport || resolveDefaultFrameworkImport();
|
|
11070
|
+
const testTimeout = options.testTimeout ?? DEFAULT_YAML_TEST_TIMEOUT;
|
|
11071
|
+
(0, __rspack_external_node_fs_5ea92f0c.rmSync)(outputDir, {
|
|
11072
|
+
recursive: true,
|
|
11073
|
+
force: true
|
|
11074
|
+
});
|
|
11075
|
+
(0, __rspack_external_node_fs_5ea92f0c.mkdirSync)(resultDir, {
|
|
11076
|
+
recursive: true
|
|
11077
|
+
});
|
|
11078
|
+
const virtualModules = {};
|
|
11079
|
+
const cases = options.files.map((file, index)=>{
|
|
11080
|
+
const yamlFile = external_node_path_resolve(file);
|
|
11081
|
+
const testName = resolveTestName(projectDir, yamlFile);
|
|
11082
|
+
const fileStem = safeFileStem(yamlFile, index);
|
|
11083
|
+
const resultFile = external_node_path_join(resultDir, `${fileStem}.json`);
|
|
11084
|
+
const testModule = toVirtualModuleId(fileStem);
|
|
11085
|
+
virtualModules[testModule] = createGeneratedTestContent({
|
|
11086
|
+
frameworkImport,
|
|
11087
|
+
yamlFile,
|
|
11088
|
+
resultFile,
|
|
11089
|
+
testName,
|
|
11090
|
+
caseOptions: options.caseOptions?.[yamlFile],
|
|
11091
|
+
webRuntimeOptions: options.webRuntimeOptions?.[yamlFile]
|
|
11092
|
+
});
|
|
11093
|
+
return {
|
|
11094
|
+
yamlFile,
|
|
11095
|
+
testModule,
|
|
11096
|
+
resultFile,
|
|
11097
|
+
testName
|
|
11098
|
+
};
|
|
11099
|
+
});
|
|
11100
|
+
if (options.batchConfig) {
|
|
11101
|
+
const batchModule = 'virtual:midscene-yaml/batch.test.ts';
|
|
11102
|
+
const resultFiles = Object.fromEntries(cases.map((item)=>[
|
|
11103
|
+
item.yamlFile,
|
|
11104
|
+
item.resultFile
|
|
11105
|
+
]));
|
|
11106
|
+
return {
|
|
11107
|
+
projectDir,
|
|
11108
|
+
outputDir,
|
|
11109
|
+
resultDir,
|
|
11110
|
+
include: [
|
|
11111
|
+
batchModule
|
|
11112
|
+
],
|
|
11113
|
+
virtualModules: {
|
|
11114
|
+
[batchModule]: createGeneratedBatchTestContent({
|
|
11115
|
+
frameworkImport,
|
|
11116
|
+
testName: 'midscene yaml batch',
|
|
11117
|
+
config: options.batchConfig,
|
|
11118
|
+
resultFiles
|
|
11119
|
+
})
|
|
11120
|
+
},
|
|
11121
|
+
cases,
|
|
11122
|
+
maxConcurrency: 1,
|
|
11123
|
+
testTimeout,
|
|
11124
|
+
bail: options.bail
|
|
11125
|
+
};
|
|
11126
|
+
}
|
|
11127
|
+
return {
|
|
11128
|
+
projectDir,
|
|
11129
|
+
outputDir,
|
|
11130
|
+
resultDir,
|
|
11131
|
+
include: cases.map((item)=>item.testModule),
|
|
11132
|
+
virtualModules,
|
|
11133
|
+
cases,
|
|
11134
|
+
maxConcurrency: options.maxConcurrency,
|
|
11135
|
+
testTimeout,
|
|
11136
|
+
bail: options.bail
|
|
11137
|
+
};
|
|
11138
|
+
}
|
|
11139
|
+
const requireFromCliEntry = ()=>{
|
|
11140
|
+
const entry = process.argv[1] ? external_node_path_resolve(process.argv[1]) : external_node_path_join(process.cwd(), 'midscene-cli.js');
|
|
11141
|
+
return createRequire(entry);
|
|
11142
|
+
};
|
|
11143
|
+
const resolvePackageFromRstestCore = (packageName)=>{
|
|
11144
|
+
const require1 = requireFromCliEntry();
|
|
11145
|
+
const rstestPackageJsonPath = require1.resolve('@rstest/core/package.json');
|
|
11146
|
+
return createRequire(rstestPackageJsonPath).resolve(packageName);
|
|
11147
|
+
};
|
|
11148
|
+
const formatRunError = (error)=>error.stack || `${error.name}: ${error.message}`;
|
|
11149
|
+
async function runRstestYamlProject(options) {
|
|
11150
|
+
const [{ runRstest }, { rspack }] = await Promise.all([
|
|
11151
|
+
import("@rstest/core/api"),
|
|
11152
|
+
import(pathToFileURL(resolvePackageFromRstestCore('@rsbuild/core')).href)
|
|
11153
|
+
]);
|
|
11154
|
+
const { project } = options;
|
|
11155
|
+
const maxConcurrency = void 0 !== project.maxConcurrency ? Math.max(1, project.maxConcurrency) : void 0;
|
|
11156
|
+
const inlineConfig = {
|
|
11157
|
+
root: project.projectDir,
|
|
11158
|
+
include: project.include,
|
|
11159
|
+
testEnvironment: 'node',
|
|
11160
|
+
testTimeout: project.testTimeout,
|
|
11161
|
+
...void 0 !== maxConcurrency ? {
|
|
11162
|
+
maxConcurrency
|
|
11163
|
+
} : {},
|
|
11164
|
+
...void 0 !== maxConcurrency ? {
|
|
11165
|
+
pool: {
|
|
11166
|
+
maxWorkers: maxConcurrency,
|
|
11167
|
+
minWorkers: maxConcurrency
|
|
11168
|
+
}
|
|
11169
|
+
} : {},
|
|
11170
|
+
...void 0 !== project.bail ? {
|
|
11171
|
+
bail: project.bail
|
|
11172
|
+
} : {},
|
|
11173
|
+
reporters: [],
|
|
11174
|
+
tools: {
|
|
11175
|
+
rspack: (_config, { appendPlugins })=>{
|
|
11176
|
+
appendPlugins(new rspack.experiments.VirtualModulesPlugin(project.virtualModules));
|
|
11177
|
+
}
|
|
11178
|
+
}
|
|
11179
|
+
};
|
|
11180
|
+
const result = await runRstest({
|
|
11181
|
+
cwd: options.cwd || project.projectDir,
|
|
11182
|
+
inlineConfig
|
|
11183
|
+
});
|
|
11184
|
+
if (!result.ok && 'pipe' !== options.stdio && result.unhandledErrors.length) console.error(result.unhandledErrors.map((error)=>formatRunError(error)).join('\n'));
|
|
11185
|
+
return result.ok ? 0 : 1;
|
|
11186
|
+
}
|
|
11187
|
+
const createCaseOptions = (config)=>{
|
|
11188
|
+
const caseOptions = {};
|
|
11189
|
+
for (const file of config.files)caseOptions[external_node_path_resolve(file)] = {
|
|
11190
|
+
globalConfig: config.globalConfig
|
|
11191
|
+
};
|
|
11192
|
+
return caseOptions;
|
|
11193
|
+
};
|
|
11194
|
+
const createWebRuntimeOptions = (config, runtimeOptions)=>{
|
|
11195
|
+
const caseOptions = {};
|
|
11196
|
+
for (const file of config.files)caseOptions[external_node_path_resolve(file)] = {
|
|
11197
|
+
headed: runtimeOptions.headed ?? config.headed,
|
|
11198
|
+
keepWindow: runtimeOptions.keepWindow ?? config.keepWindow
|
|
11199
|
+
};
|
|
11200
|
+
return caseOptions;
|
|
11201
|
+
};
|
|
11202
|
+
const readProjectResults = (project)=>project.cases.map((item)=>{
|
|
11203
|
+
if ((0, __rspack_external_node_fs_5ea92f0c.existsSync)(item.resultFile)) return JSON.parse((0, __rspack_external_node_fs_5ea92f0c.readFileSync)(item.resultFile, 'utf8'));
|
|
11204
|
+
return execution_summary_createNotExecutedYamlResult(item.yamlFile);
|
|
11205
|
+
});
|
|
11206
|
+
async function runFrameworkTestConfig(config, commandOptions = {}) {
|
|
11207
|
+
execution_summary_printExecutionPlan(config);
|
|
11208
|
+
const projectDir = external_node_path_resolve(commandOptions.projectDir || process.cwd());
|
|
11209
|
+
const project = createRstestYamlProject({
|
|
11210
|
+
files: config.files,
|
|
11211
|
+
projectDir,
|
|
11212
|
+
outputDir: commandOptions.outputDir,
|
|
11213
|
+
frameworkImport: commandOptions.frameworkImport,
|
|
11214
|
+
caseOptions: createCaseOptions(config),
|
|
11215
|
+
webRuntimeOptions: createWebRuntimeOptions(config, commandOptions),
|
|
11216
|
+
maxConcurrency: commandOptions.concurrent ?? config.concurrent,
|
|
11217
|
+
bail: config.continueOnError ? 0 : 1,
|
|
11218
|
+
batchConfig: config.shareBrowserContext ? config : void 0
|
|
11219
|
+
});
|
|
11220
|
+
const runner = commandOptions.rstestRunner || runRstestYamlProject;
|
|
11221
|
+
const exitCode = await runner({
|
|
11222
|
+
project,
|
|
11223
|
+
cwd: projectDir,
|
|
11224
|
+
stdio: commandOptions.stdio
|
|
11225
|
+
});
|
|
11226
|
+
const results = readProjectResults(project);
|
|
11227
|
+
const summaryPath = execution_summary_writeExecutionSummaryFile(config.summary, results);
|
|
11228
|
+
execution_summary_printExecutionFinished();
|
|
11229
|
+
const success = printExecutionSummary(results, summaryPath);
|
|
11230
|
+
return success ? exitCode : 1;
|
|
11231
|
+
}
|
|
11232
|
+
getDebug('create-yaml-player');
|
|
11233
|
+
__webpack_require__("../../node_modules/.pnpm/chalk@4.1.2/node_modules/chalk/source/index.js");
|
|
11234
|
+
process.env.MIDSCENE_CLI_LOG_ON_NON_TTY || process.stdout.isTTY;
|
|
12017
11235
|
Promise.resolve((async ()=>{
|
|
12018
11236
|
const rawArgs = process.argv.slice(2);
|
|
12019
11237
|
const [firstArg] = rawArgs;
|
|
@@ -12072,7 +11290,7 @@ Examples:
|
|
|
12072
11290
|
console.error('Could not create a valid configuration.');
|
|
12073
11291
|
process.exit(1);
|
|
12074
11292
|
}
|
|
12075
|
-
const dotEnvConfigFile =
|
|
11293
|
+
const dotEnvConfigFile = external_node_path_join(process.cwd(), '.env');
|
|
12076
11294
|
if ((0, __rspack_external_node_fs_5ea92f0c.existsSync)(dotEnvConfigFile)) {
|
|
12077
11295
|
console.log(` Env file: ${dotEnvConfigFile}`);
|
|
12078
11296
|
main_default().config({
|
|
@@ -12081,16 +11299,11 @@ Examples:
|
|
|
12081
11299
|
override: config.dotenvOverride
|
|
12082
11300
|
});
|
|
12083
11301
|
}
|
|
12084
|
-
const
|
|
12085
|
-
await executor.run();
|
|
12086
|
-
const success = executor.printExecutionSummary();
|
|
11302
|
+
const exitCode = await runFrameworkTestConfig(config);
|
|
12087
11303
|
if (config.keepWindow) setInterval(()=>{
|
|
12088
11304
|
console.log('browser is still running, use ctrl+c to stop it');
|
|
12089
11305
|
}, 5000);
|
|
12090
|
-
else
|
|
12091
|
-
if (!success) process.exit(1);
|
|
12092
|
-
process.exit(0);
|
|
12093
|
-
}
|
|
11306
|
+
else process.exit(exitCode);
|
|
12094
11307
|
})().catch((e1)=>{
|
|
12095
11308
|
console.error(e1);
|
|
12096
11309
|
process.exit(1);
|