@testrigor/testrigor-cli 1.0.0 → 2.0.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/README.md +230 -3
- package/dist/commands/authenticate.d.ts +14 -0
- package/dist/commands/authenticate.js +87 -26
- package/dist/commands/test-suite/config.js +1 -1
- package/dist/commands/test-suite/run.js +253 -234
- package/dist/commands/test-suite/validate-syntax.js +2 -3
- package/dist/flags/chrome-extension.js +3 -2
- package/dist/types.d.ts +0 -12
- package/dist/util/appium.js +92 -34
- package/dist/util/certificate-uploader.js +5 -6
- package/dist/util/config.js +15 -15
- package/dist/util/parser.js +8 -8
- package/dist/util/request-builder.d.ts +2 -8
- package/dist/util/request-builder.js +12 -35
- package/dist/util/trtc.d.ts +2 -0
- package/dist/util/trtc.js +107 -38
- package/dist/util/tunnel.js +7 -6
- package/dist/util/type-guards.js +3 -4
- package/dist/util/utils.d.ts +3 -3
- package/dist/util/utils.js +23 -23
- package/dist/util/variable-file-uploader.js +7 -13
- package/dist/util/variables-path-parser.js +4 -4
- package/npm-shrinkwrap.json +11047 -0
- package/oclif.manifest.json +253 -180
- package/package.json +21 -20
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
|
-
const node_fetch_commonjs_1 = require("node-fetch-commonjs");
|
|
5
4
|
const command_base_1 = require("../../command-base");
|
|
6
5
|
const environments_1 = require("../../config/environments");
|
|
7
6
|
const parser_1 = require("../../util/parser");
|
|
@@ -67,7 +66,7 @@ class ValidateSyntax extends command_base_1.CommandBase {
|
|
|
67
66
|
if (explicitMutations) {
|
|
68
67
|
body.explicitMutations = explicitMutations;
|
|
69
68
|
}
|
|
70
|
-
const response = await (
|
|
69
|
+
const response = await fetch(`${this.TESTRIGOR_API2_URL}/apps/${testSuiteId}/validate-syntax`, {
|
|
71
70
|
method: "POST",
|
|
72
71
|
body: JSON.stringify(body),
|
|
73
72
|
headers: {
|
|
@@ -82,7 +81,6 @@ class ValidateSyntax extends command_base_1.CommandBase {
|
|
|
82
81
|
return (await response.json());
|
|
83
82
|
}
|
|
84
83
|
}
|
|
85
|
-
exports.default = ValidateSyntax;
|
|
86
84
|
ValidateSyntax.description = "Validate step syntax against a test suite's reusable rules, without running the steps";
|
|
87
85
|
ValidateSyntax.examples = [
|
|
88
86
|
'testrigor test-suite validate-syntax <test-suite-id> --steps "click \\"Login\\""',
|
|
@@ -115,3 +113,4 @@ ValidateSyntax.args = {
|
|
|
115
113
|
required: false,
|
|
116
114
|
}),
|
|
117
115
|
};
|
|
116
|
+
exports.default = ValidateSyntax;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ChromeExtensionFlag = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
4
5
|
const core_1 = require("@oclif/core");
|
|
5
|
-
const fs = require("fs");
|
|
6
|
-
const path = require("path");
|
|
6
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
7
|
+
const path = tslib_1.__importStar(require("path"));
|
|
7
8
|
const utils_1 = require("../util/utils");
|
|
8
9
|
let totalChromeExtensionSize = 0;
|
|
9
10
|
exports.ChromeExtensionFlag = core_1.Flags.custom({
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
import { ReadStream } from "fs";
|
|
3
1
|
export type RetestResponse = {
|
|
4
2
|
result: string;
|
|
5
3
|
msg: string;
|
|
@@ -62,16 +60,6 @@ export type ChromeExtensionInput = {
|
|
|
62
60
|
name: string;
|
|
63
61
|
file: string;
|
|
64
62
|
};
|
|
65
|
-
/**
|
|
66
|
-
* Represents a single chrome extension override with its binary file.
|
|
67
|
-
*/
|
|
68
|
-
export type ChromeExtensionOverrideItem = {
|
|
69
|
-
name: string;
|
|
70
|
-
file: ReadStream;
|
|
71
|
-
};
|
|
72
|
-
export type ChromeExtensionOverridesRequest = {
|
|
73
|
-
chromeExtensions: ChromeExtensionOverrideItem[];
|
|
74
|
-
};
|
|
75
63
|
export type StoredValueFileInput = {
|
|
76
64
|
name: string;
|
|
77
65
|
file: string;
|
package/dist/util/appium.js
CHANGED
|
@@ -1,27 +1,39 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
exports.PID_FILE = exports.PID_DIR = exports.REQUIRED_DRIVERS = exports.DEFAULT_BASE_PATH = exports.DEFAULT_PORT = void 0;
|
|
4
|
+
exports.checkAppiumInstalled = checkAppiumInstalled;
|
|
5
|
+
exports.getDriverStatus = getDriverStatus;
|
|
6
|
+
exports.ensureDriver = ensureDriver;
|
|
7
|
+
exports.isProcessRunning = isProcessRunning;
|
|
8
|
+
exports.getRunningAppiumPid = getRunningAppiumPid;
|
|
9
|
+
exports.startAppium = startAppium;
|
|
10
|
+
exports.stopAppium = stopAppium;
|
|
11
|
+
const tslib_1 = require("tslib");
|
|
12
|
+
const childProcess = tslib_1.__importStar(require("child_process"));
|
|
13
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
14
|
+
const util = tslib_1.__importStar(require("util"));
|
|
15
|
+
const path = tslib_1.__importStar(require("path"));
|
|
16
|
+
const os = tslib_1.__importStar(require("os"));
|
|
17
|
+
const fs_1 = tslib_1.__importDefault(require("@supercharge/fs"));
|
|
18
|
+
const utils_1 = require("./utils");
|
|
10
19
|
const execFile = util.promisify(childProcess.execFile);
|
|
11
20
|
const PROJECT_ROOT = path.resolve(__dirname, "..", "..");
|
|
12
|
-
const APPIUM_HOME = path.join(PROJECT_ROOT, ".appium");
|
|
13
21
|
const DEFAULT_PORT = 4723;
|
|
14
22
|
exports.DEFAULT_PORT = DEFAULT_PORT;
|
|
15
23
|
const DEFAULT_BASE_PATH = "/wd/hub";
|
|
16
24
|
exports.DEFAULT_BASE_PATH = DEFAULT_BASE_PATH;
|
|
17
|
-
const PID_DIR =
|
|
25
|
+
const PID_DIR = (0, utils_1.getHomeDir)();
|
|
18
26
|
exports.PID_DIR = PID_DIR;
|
|
19
27
|
const PID_FILE = path.join(PID_DIR, "appium.pid");
|
|
20
28
|
exports.PID_FILE = PID_FILE;
|
|
21
29
|
const LOG_FILE = path.join(os.tmpdir(), "testrigor-appium.log");
|
|
30
|
+
// Appium writes its drivers here (hundreds of MB). It must live under the
|
|
31
|
+
// user's home, not the install directory: a global install is often
|
|
32
|
+
// root-owned, and `npm update -g` would wipe the drivers on every upgrade.
|
|
33
|
+
const APPIUM_HOME = process.env.APPIUM_HOME || path.join((0, utils_1.getHomeDir)(), "appium-home");
|
|
22
34
|
const REQUIRED_DRIVERS = [
|
|
23
35
|
{ name: "uiautomator2", version: "4.2.3" },
|
|
24
|
-
{ name: "xcuitest", version: "
|
|
36
|
+
{ name: "xcuitest", version: "10.43.1" },
|
|
25
37
|
];
|
|
26
38
|
exports.REQUIRED_DRIVERS = REQUIRED_DRIVERS;
|
|
27
39
|
function getAppiumBin() {
|
|
@@ -34,19 +46,36 @@ function getAppiumEnv() {
|
|
|
34
46
|
CHROMELABS_URL: "https://googlechromelabs.github.io",
|
|
35
47
|
};
|
|
36
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Appium refuses to start unless APPIUM_HOME already exists, so create it
|
|
51
|
+
* before any invocation and surface a permission problem as itself rather
|
|
52
|
+
* than as a generic "appium is broken".
|
|
53
|
+
*/
|
|
54
|
+
async function ensureAppiumHome() {
|
|
55
|
+
try {
|
|
56
|
+
await fs_1.default.ensureDir(APPIUM_HOME);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
throw new Error(`Cannot create the mobile server directory at ${APPIUM_HOME}: ` +
|
|
60
|
+
`${error instanceof Error ? error.message : String(error)}\n` +
|
|
61
|
+
"Check that you own that directory, or point APPIUM_HOME at a writable one.");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
37
64
|
async function checkAppiumInstalled() {
|
|
38
65
|
const appiumBin = getAppiumBin();
|
|
39
|
-
if (!(await
|
|
40
|
-
throw new Error(`Appium binary not found at ${appiumBin}.
|
|
66
|
+
if (!(await fs_1.default.exists(appiumBin))) {
|
|
67
|
+
throw new Error(`Appium binary not found at ${appiumBin}. ` +
|
|
68
|
+
"Reinstall the CLI with: npm install -g @testrigor/testrigor-cli");
|
|
41
69
|
}
|
|
70
|
+
await ensureAppiumHome();
|
|
42
71
|
try {
|
|
43
72
|
await execFile(appiumBin, ["--version"], { env: getAppiumEnv() });
|
|
44
73
|
}
|
|
45
|
-
catch {
|
|
46
|
-
|
|
74
|
+
catch (error) {
|
|
75
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
76
|
+
throw new Error(`Appium binary at ${appiumBin} failed to run (APPIUM_HOME=${APPIUM_HOME}).\n${detail}`);
|
|
47
77
|
}
|
|
48
78
|
}
|
|
49
|
-
exports.checkAppiumInstalled = checkAppiumInstalled;
|
|
50
79
|
async function getDriverStatus(driverName, requiredVersion) {
|
|
51
80
|
const appiumBin = getAppiumBin();
|
|
52
81
|
try {
|
|
@@ -66,7 +95,6 @@ async function getDriverStatus(driverName, requiredVersion) {
|
|
|
66
95
|
return { installed: false, upToDate: false };
|
|
67
96
|
}
|
|
68
97
|
}
|
|
69
|
-
exports.getDriverStatus = getDriverStatus;
|
|
70
98
|
async function ensureDriver(driverName, requiredVersion) {
|
|
71
99
|
const appiumBin = getAppiumBin();
|
|
72
100
|
const env = getAppiumEnv();
|
|
@@ -86,10 +114,9 @@ async function ensureDriver(driverName, requiredVersion) {
|
|
|
86
114
|
}
|
|
87
115
|
catch (error) {
|
|
88
116
|
const raw = error instanceof Error ? error.message : String(error);
|
|
89
|
-
return raw.
|
|
117
|
+
return raw.replace(/^Command failed:.*?Error:\s*/, "").trim();
|
|
90
118
|
}
|
|
91
119
|
}
|
|
92
|
-
exports.ensureDriver = ensureDriver;
|
|
93
120
|
function isProcessRunning(pid) {
|
|
94
121
|
try {
|
|
95
122
|
process.kill(pid, 0);
|
|
@@ -99,25 +126,52 @@ function isProcessRunning(pid) {
|
|
|
99
126
|
return false;
|
|
100
127
|
}
|
|
101
128
|
}
|
|
102
|
-
exports.isProcessRunning = isProcessRunning;
|
|
103
129
|
function killSafe(pid) {
|
|
104
130
|
if (isProcessRunning(pid)) {
|
|
105
131
|
process.kill(pid);
|
|
106
132
|
}
|
|
107
133
|
}
|
|
108
134
|
async function getRunningAppiumPid() {
|
|
109
|
-
if (!(await
|
|
135
|
+
if (!(await fs_1.default.exists(PID_FILE))) {
|
|
110
136
|
return null;
|
|
111
137
|
}
|
|
112
|
-
const existingPid = Number((await
|
|
138
|
+
const existingPid = Number((await fs_1.default.content(PID_FILE)).trim());
|
|
113
139
|
if (isProcessRunning(existingPid)) {
|
|
114
140
|
return existingPid;
|
|
115
141
|
}
|
|
116
|
-
await
|
|
142
|
+
await fs_1.default.removeFile(PID_FILE);
|
|
117
143
|
return null;
|
|
118
144
|
}
|
|
119
|
-
|
|
120
|
-
|
|
145
|
+
/**
|
|
146
|
+
* Last lines of the Appium log, so a server that dies on startup reports the
|
|
147
|
+
* reason instead of just a health-check timeout. The log is shared across
|
|
148
|
+
* invocations, so only bytes written after `fromOffset` are considered.
|
|
149
|
+
*/
|
|
150
|
+
function readLogTail(fromOffset, lines = 20) {
|
|
151
|
+
let fd;
|
|
152
|
+
try {
|
|
153
|
+
fd = fs.openSync(LOG_FILE, "r");
|
|
154
|
+
const size = fs.fstatSync(fd).size;
|
|
155
|
+
if (size <= fromOffset)
|
|
156
|
+
return "";
|
|
157
|
+
const maxTailBytes = 64 * 1024;
|
|
158
|
+
const start = Math.max(fromOffset, size - maxTailBytes);
|
|
159
|
+
const buffer = Buffer.alloc(size - start);
|
|
160
|
+
fs.readSync(fd, buffer, 0, buffer.length, start);
|
|
161
|
+
const content = buffer.toString("utf8").trimEnd();
|
|
162
|
+
if (!content)
|
|
163
|
+
return "";
|
|
164
|
+
return content.split("\n").slice(-lines).join("\n");
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
return "";
|
|
168
|
+
}
|
|
169
|
+
finally {
|
|
170
|
+
if (fd !== undefined)
|
|
171
|
+
fs.closeSync(fd);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
async function healthCheck(port, logOffset, retries = 15, interval = 2000) {
|
|
121
175
|
const url = `http://127.0.0.1:${port}/wd/hub/status`;
|
|
122
176
|
let lastError = "";
|
|
123
177
|
for (let i = 0; i < retries; i++) {
|
|
@@ -133,7 +187,11 @@ async function healthCheck(port, retries = 15, interval = 2000) {
|
|
|
133
187
|
}
|
|
134
188
|
await new Promise((r) => setTimeout(r, interval));
|
|
135
189
|
}
|
|
136
|
-
|
|
190
|
+
const tail = readLogTail(logOffset);
|
|
191
|
+
throw new Error(`Mobile server not ready after ${retries} attempts: ${lastError}` +
|
|
192
|
+
(tail
|
|
193
|
+
? `\nLast lines of ${LOG_FILE}:\n${tail}`
|
|
194
|
+
: `\nSee ${LOG_FILE} for details.`));
|
|
137
195
|
}
|
|
138
196
|
async function startAppium(port = DEFAULT_PORT, logLevel = "debug") {
|
|
139
197
|
const existingPid = await getRunningAppiumPid();
|
|
@@ -141,7 +199,9 @@ async function startAppium(port = DEFAULT_PORT, logLevel = "debug") {
|
|
|
141
199
|
return { pid: existingPid, alreadyRunning: true };
|
|
142
200
|
}
|
|
143
201
|
const appiumBin = getAppiumBin();
|
|
202
|
+
await ensureAppiumHome();
|
|
144
203
|
const logStream = fs.openSync(LOG_FILE, "a");
|
|
204
|
+
const logOffset = fs.fstatSync(logStream).size;
|
|
145
205
|
const appiumProcess = childProcess.spawn(appiumBin, [
|
|
146
206
|
"--port",
|
|
147
207
|
String(port),
|
|
@@ -161,29 +221,27 @@ async function startAppium(port = DEFAULT_PORT, logLevel = "debug") {
|
|
|
161
221
|
throw new Error("Failed to start Appium server: no PID returned");
|
|
162
222
|
}
|
|
163
223
|
appiumProcess.unref();
|
|
164
|
-
await
|
|
165
|
-
await
|
|
224
|
+
await fs_1.default.ensureDir(PID_DIR);
|
|
225
|
+
await fs_1.default.writeFile(PID_FILE, String(pid));
|
|
166
226
|
try {
|
|
167
|
-
await healthCheck(port);
|
|
227
|
+
await healthCheck(port, logOffset);
|
|
168
228
|
}
|
|
169
229
|
catch (err) {
|
|
170
230
|
killSafe(pid);
|
|
171
|
-
await
|
|
231
|
+
await fs_1.default.removeFile(PID_FILE);
|
|
172
232
|
throw err;
|
|
173
233
|
}
|
|
174
234
|
return { pid, alreadyRunning: false };
|
|
175
235
|
}
|
|
176
|
-
exports.startAppium = startAppium;
|
|
177
236
|
async function stopAppium() {
|
|
178
|
-
if (!(await
|
|
237
|
+
if (!(await fs_1.default.exists(PID_FILE))) {
|
|
179
238
|
return null;
|
|
180
239
|
}
|
|
181
|
-
const pidContent = (await
|
|
240
|
+
const pidContent = (await fs_1.default.content(PID_FILE)).trim();
|
|
182
241
|
const pid = Number(pidContent);
|
|
183
242
|
if (!isNaN(pid) && isProcessRunning(pid)) {
|
|
184
243
|
process.kill(pid, "SIGTERM");
|
|
185
244
|
}
|
|
186
|
-
await
|
|
245
|
+
await fs_1.default.removeFile(PID_FILE);
|
|
187
246
|
return pid;
|
|
188
247
|
}
|
|
189
|
-
exports.stopAppium = stopAppium;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.uploadClientCertificate =
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
3
|
+
exports.uploadClientCertificate = uploadClientCertificate;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
6
|
+
const path = tslib_1.__importStar(require("path"));
|
|
7
7
|
const type_guards_1 = require("./type-guards");
|
|
8
8
|
async function uploadClientCertificate(api2BaseUrl, testSuiteId, token, localFilePath, password) {
|
|
9
9
|
const fileName = path.basename(localFilePath);
|
|
10
10
|
const certBase64 = fs.readFileSync(localFilePath).toString("base64");
|
|
11
|
-
const response = await (
|
|
11
|
+
const response = await fetch(`${api2BaseUrl}/apps/${testSuiteId}/test_data/global_variables/client_certificate`, {
|
|
12
12
|
method: "POST",
|
|
13
13
|
body: JSON.stringify({ fileName, certBase64, password }),
|
|
14
14
|
headers: {
|
|
@@ -29,4 +29,3 @@ async function uploadClientCertificate(api2BaseUrl, testSuiteId, token, localFil
|
|
|
29
29
|
info: responseJson.data.info,
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
-
exports.uploadClientCertificate = uploadClientCertificate;
|
package/dist/util/config.js
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.getConfigPath = getConfigPath;
|
|
4
|
+
exports.readConfig = readConfig;
|
|
5
|
+
exports.writeConfig = writeConfig;
|
|
6
|
+
exports.readConfigProperty = readConfigProperty;
|
|
7
|
+
exports.updateConfigProperty = updateConfigProperty;
|
|
8
|
+
exports.deleteConfigProperty = deleteConfigProperty;
|
|
9
|
+
const tslib_1 = require("tslib");
|
|
4
10
|
const core_1 = require("@oclif/core");
|
|
5
|
-
const
|
|
6
|
-
const path = require("path");
|
|
11
|
+
const fs_1 = tslib_1.__importDefault(require("@supercharge/fs"));
|
|
12
|
+
const path = tslib_1.__importStar(require("path"));
|
|
7
13
|
const yaml_1 = require("yaml");
|
|
8
14
|
const utils_1 = require("./utils");
|
|
9
15
|
/**
|
|
@@ -14,17 +20,16 @@ function getConfigPath() {
|
|
|
14
20
|
const configPath = path.join(homeDir, "testrigor.yml");
|
|
15
21
|
return { homeDir, configPath };
|
|
16
22
|
}
|
|
17
|
-
exports.getConfigPath = getConfigPath;
|
|
18
23
|
/**
|
|
19
24
|
* Read testRigor configuration from ~/.testrigor/testrigor.yml
|
|
20
25
|
*/
|
|
21
26
|
async function readConfig() {
|
|
22
27
|
const { configPath } = getConfigPath();
|
|
23
|
-
if (!(await
|
|
28
|
+
if (!(await fs_1.default.pathExists(configPath))) {
|
|
24
29
|
return {};
|
|
25
30
|
}
|
|
26
31
|
try {
|
|
27
|
-
const content = await
|
|
32
|
+
const content = await fs_1.default.content(configPath);
|
|
28
33
|
return (0, yaml_1.parse)(content.toString()) || {};
|
|
29
34
|
}
|
|
30
35
|
catch (error) {
|
|
@@ -34,26 +39,24 @@ async function readConfig() {
|
|
|
34
39
|
return {};
|
|
35
40
|
}
|
|
36
41
|
}
|
|
37
|
-
exports.readConfig = readConfig;
|
|
38
42
|
/**
|
|
39
43
|
* Write testRigor configuration to ~/.testrigor/testrigor.yml
|
|
40
44
|
*/
|
|
41
45
|
async function writeConfig(config) {
|
|
42
46
|
const { homeDir, configPath } = getConfigPath();
|
|
43
47
|
// Ensure the config directory exists
|
|
44
|
-
if (!(await
|
|
45
|
-
await
|
|
48
|
+
if (!(await fs_1.default.pathExists(homeDir))) {
|
|
49
|
+
await fs_1.default.ensureDir(homeDir);
|
|
46
50
|
}
|
|
47
51
|
// Avoid writing empty objects as "{}"
|
|
48
52
|
const configContent = Object.keys(config).length > 0 ? (0, yaml_1.stringify)(config) : "";
|
|
49
53
|
if (configContent.trim() === "") {
|
|
50
|
-
await
|
|
54
|
+
await fs_1.default.writeFile(configPath, "");
|
|
51
55
|
}
|
|
52
56
|
else {
|
|
53
|
-
await
|
|
57
|
+
await fs_1.default.writeFile(configPath, configContent);
|
|
54
58
|
}
|
|
55
59
|
}
|
|
56
|
-
exports.writeConfig = writeConfig;
|
|
57
60
|
/**
|
|
58
61
|
* Read a specific property from testRigor configuration
|
|
59
62
|
*/
|
|
@@ -61,7 +64,6 @@ async function readConfigProperty(property) {
|
|
|
61
64
|
const config = await readConfig();
|
|
62
65
|
return config[property] || null;
|
|
63
66
|
}
|
|
64
|
-
exports.readConfigProperty = readConfigProperty;
|
|
65
67
|
/**
|
|
66
68
|
* Update a specific property in testRigor configuration
|
|
67
69
|
*/
|
|
@@ -75,7 +77,6 @@ async function updateConfigProperty(property, value) {
|
|
|
75
77
|
}
|
|
76
78
|
await writeConfig(config);
|
|
77
79
|
}
|
|
78
|
-
exports.updateConfigProperty = updateConfigProperty;
|
|
79
80
|
/**
|
|
80
81
|
* Delete a specific property from testRigor configuration
|
|
81
82
|
*/
|
|
@@ -84,4 +85,3 @@ async function deleteConfigProperty(property) {
|
|
|
84
85
|
delete config[property];
|
|
85
86
|
await writeConfig(config);
|
|
86
87
|
}
|
|
87
|
-
exports.deleteConfigProperty = deleteConfigProperty;
|
package/dist/util/parser.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
3
|
+
exports.parseTestCases = parseTestCases;
|
|
4
|
+
exports.parseRules = parseRules;
|
|
5
|
+
exports.parseSettings = parseSettings;
|
|
6
|
+
const tslib_1 = require("tslib");
|
|
7
|
+
const fs_1 = tslib_1.__importDefault(require("@supercharge/fs"));
|
|
5
8
|
const glob_1 = require("glob");
|
|
6
9
|
const yaml_1 = require("yaml");
|
|
7
10
|
const utils_1 = require("./utils");
|
|
@@ -10,7 +13,7 @@ async function parseTestCases(path) {
|
|
|
10
13
|
const files = await (0, glob_1.glob)(path, { withFileTypes: true });
|
|
11
14
|
for (const file of files) {
|
|
12
15
|
if (file.isFile()) {
|
|
13
|
-
const content = await
|
|
16
|
+
const content = await fs_1.default.content(file.fullpath());
|
|
14
17
|
if ((0, utils_1.isYamlFile)(file.name)) {
|
|
15
18
|
const json = (0, yaml_1.parse)(content.toString());
|
|
16
19
|
const testCase = {
|
|
@@ -39,13 +42,12 @@ async function parseTestCases(path) {
|
|
|
39
42
|
}
|
|
40
43
|
return result;
|
|
41
44
|
}
|
|
42
|
-
exports.parseTestCases = parseTestCases;
|
|
43
45
|
async function parseRules(path) {
|
|
44
46
|
const result = [];
|
|
45
47
|
const files = await (0, glob_1.glob)(path, { withFileTypes: true });
|
|
46
48
|
for (const file of files) {
|
|
47
49
|
if (file.isFile()) {
|
|
48
|
-
const content = await
|
|
50
|
+
const content = await fs_1.default.content(file.fullpath());
|
|
49
51
|
if ((0, utils_1.isYamlFile)(file.name)) {
|
|
50
52
|
const json = (0, yaml_1.parse)(content.toString());
|
|
51
53
|
const ruleName = (0, utils_1.removeExtension)(file.name);
|
|
@@ -69,9 +71,8 @@ async function parseRules(path) {
|
|
|
69
71
|
}
|
|
70
72
|
return result;
|
|
71
73
|
}
|
|
72
|
-
exports.parseRules = parseRules;
|
|
73
74
|
async function parseSettings(path) {
|
|
74
|
-
const content = await
|
|
75
|
+
const content = await fs_1.default.content(path);
|
|
75
76
|
if ((0, utils_1.isYamlFile)(path)) {
|
|
76
77
|
return (0, yaml_1.parse)(content.toString());
|
|
77
78
|
}
|
|
@@ -80,4 +81,3 @@ async function parseSettings(path) {
|
|
|
80
81
|
}
|
|
81
82
|
return {};
|
|
82
83
|
}
|
|
83
|
-
exports.parseSettings = parseSettings;
|
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
import * as FormData from "form-data";
|
|
2
1
|
import { ChromeExtensionInput } from "../types";
|
|
3
|
-
export interface ChromeExtensionFormDataResult {
|
|
4
|
-
form: FormData;
|
|
5
|
-
cleanup: () => void;
|
|
6
|
-
}
|
|
7
2
|
/**
|
|
8
|
-
*
|
|
9
|
-
* Returns both the FormData and a cleanup function to close streams.
|
|
3
|
+
* Builds the multipart body for the chrome extension overrides of a retest.
|
|
10
4
|
*/
|
|
11
|
-
export declare function buildChromeExtensionFormData(chromeExtensions: ChromeExtensionInput[]):
|
|
5
|
+
export declare function buildChromeExtensionFormData(chromeExtensions: ChromeExtensionInput[]): Promise<FormData>;
|
|
@@ -1,49 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.buildChromeExtensionFormData =
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const path = require("path");
|
|
7
|
-
function
|
|
3
|
+
exports.buildChromeExtensionFormData = buildChromeExtensionFormData;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const fs_1 = require("fs");
|
|
6
|
+
const path = tslib_1.__importStar(require("path"));
|
|
7
|
+
async function readChromeExtension(input) {
|
|
8
8
|
try {
|
|
9
|
-
return
|
|
10
|
-
name: input.name,
|
|
11
|
-
file: Fs.createReadStream(input.file),
|
|
12
|
-
};
|
|
9
|
+
return await (0, fs_1.openAsBlob)(input.file);
|
|
13
10
|
}
|
|
14
11
|
catch (error) {
|
|
15
12
|
throw new Error(`Failed to read chrome extension file "${input.file}": ${error instanceof Error ? error.message : String(error)}`);
|
|
16
13
|
}
|
|
17
14
|
}
|
|
18
|
-
function toChromeExtensionOverridesRequest(extensionInputs) {
|
|
19
|
-
const chromeExtensions = extensionInputs.map(toChromeExtensionOverrideItem);
|
|
20
|
-
const streams = chromeExtensions.map((item) => item.file);
|
|
21
|
-
return {
|
|
22
|
-
request: { chromeExtensions },
|
|
23
|
-
streams,
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
15
|
/**
|
|
27
|
-
*
|
|
28
|
-
* Returns both the FormData and a cleanup function to close streams.
|
|
16
|
+
* Builds the multipart body for the chrome extension overrides of a retest.
|
|
29
17
|
*/
|
|
30
|
-
function buildChromeExtensionFormData(chromeExtensions) {
|
|
31
|
-
const
|
|
18
|
+
async function buildChromeExtensionFormData(chromeExtensions) {
|
|
19
|
+
const files = await Promise.all(chromeExtensions.map(readChromeExtension));
|
|
32
20
|
const form = new FormData();
|
|
33
|
-
|
|
21
|
+
chromeExtensions.forEach((ext, index) => {
|
|
34
22
|
form.append(`chromeExtensions[${index}].name`, ext.name);
|
|
35
|
-
|
|
36
|
-
form.append(`chromeExtensions[${index}].file`, ext.file, {
|
|
37
|
-
filename: fileName,
|
|
38
|
-
});
|
|
23
|
+
form.append(`chromeExtensions[${index}].file`, files[index], path.basename(ext.file));
|
|
39
24
|
});
|
|
40
|
-
|
|
41
|
-
streams.forEach((stream) => {
|
|
42
|
-
if (!stream.destroyed) {
|
|
43
|
-
stream.destroy();
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
};
|
|
47
|
-
return { form, cleanup };
|
|
25
|
+
return form;
|
|
48
26
|
}
|
|
49
|
-
exports.buildChromeExtensionFormData = buildChromeExtensionFormData;
|
package/dist/util/trtc.d.ts
CHANGED