@testrigor/testrigor-cli 0.0.45-beta → 0.0.47-beta
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 +13 -12
- package/dist/commands/test-suite/run.d.ts +2 -1
- package/dist/commands/test-suite/run.js +15 -11
- package/dist/util/trtc.d.ts +1 -2
- package/dist/util/trtc.js +12 -5
- package/dist/util/tunnel.js +9 -10
- package/oclif.manifest.json +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,18 +19,19 @@ This is a command line tool for TestRigor. It allows you to run TestRigor tests
|
|
|
19
19
|
8. With rules `testrigor test-suite run <test-suite-id> --token <token> --rules-path rules/**/*.yaml`
|
|
20
20
|
9. With settings `testrigor test-suite run <test-suite-id> --token <token> --settings-path settings.yaml` (Can be YAML or JSON)
|
|
21
21
|
10. Run a single test case `testrigor test-suite run <test-suite-id> --token <token> --test-case-uuid <test-case-uuid>`
|
|
22
|
-
11. Run
|
|
23
|
-
12. Run with
|
|
24
|
-
13.
|
|
25
|
-
14.
|
|
26
|
-
15.
|
|
27
|
-
16.
|
|
28
|
-
17.
|
|
29
|
-
18.
|
|
30
|
-
19.
|
|
31
|
-
20.
|
|
32
|
-
21.
|
|
33
|
-
22.
|
|
22
|
+
11. Run multiple test cases `testrigor test-suite run <test-suite-id> --token <token> --test-case-uuid <test-case-uuid-1> --test-case-uuid <test-case-uuid-2>`
|
|
23
|
+
12. Run with auto create AI rules enabled `testrigor test-suite run <test-suite-id> --token <token> --test-cases-path test_cases/**/*.{yaml,txt} --auto-create-ai-rules`
|
|
24
|
+
13. Run with explicit mutations enabled `testrigor test-suite run <test-suite-id> --token <token> --test-cases-path test_cases/**/*.{yaml,txt} --explicit-mutations`
|
|
25
|
+
14. With all options `testrigor test-suite run <test-suite-id> --token <token> --url <url> --branch <branch> --commit <commit> --variables-path file.json --localhost --test-cases-path test_cases/**/*.{yaml,txt} --rules-path rules/**/*.{yaml,txt} --auto-create-ai-rules --explicit-mutations`
|
|
26
|
+
15. Save JUnit report to `./junit-report.xml` (works only in sync mode): `testrigor test-suite run <test-suite-id> --token <token> --junit-report-save-path ./report.xml`
|
|
27
|
+
16. With comma-separated labels `testrigor test-suite run <test-suite-id> --token <token> --labels <labels>`
|
|
28
|
+
17. Excluding comma-separated labels `testrigor test-suite run <test-suite-id> --token <token> --excluded-labels <excluded-labels>`
|
|
29
|
+
18. With different WEB and API URLs `testrigor test-suite run <test-suite-id> --token <token> --base-url-web=<base-web-url> --base-url-api=<base_api_url>`
|
|
30
|
+
19. Set the default test suite ID: `testrigor test-suite config --default <test-suite-id>`
|
|
31
|
+
20. Remove the default test suite ID: `testrigor test-suite config --delete`
|
|
32
|
+
21. Show current configuration: `testrigor test-suite config --show`
|
|
33
|
+
22. Authenticate with TestRigor and store credentials (interactive prompt): `testrigor authenticate`
|
|
34
|
+
23. Run with override chrome extensions at runtime (one or more chrome extensions): `test-suite run <test-suite-id> --token <token> --chrome-extension "name=<extension-name> file=<extension-file>" --chrome-extension "name=<extension-name> file=<extension-file>"`
|
|
34
35
|
|
|
35
36
|
### Mobile Testing
|
|
36
37
|
|
|
@@ -18,7 +18,7 @@ export default class Run extends CommandBase<typeof Run> {
|
|
|
18
18
|
"rules-path": import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
19
19
|
"settings-path": import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
20
20
|
"local-test-nodes-path": import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
21
|
-
"test-case-uuid": import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
21
|
+
"test-case-uuid": import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
22
22
|
"auto-create-ai-rules": import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
23
23
|
"explicit-mutations": import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
24
24
|
labels: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
@@ -36,6 +36,7 @@ export default class Run extends CommandBase<typeof Run> {
|
|
|
36
36
|
};
|
|
37
37
|
private initializeUrls;
|
|
38
38
|
run(): Promise<void>;
|
|
39
|
+
private isSingleTestCaseExecution;
|
|
39
40
|
private fetchStatus;
|
|
40
41
|
private getStatusApiEndpoint;
|
|
41
42
|
private uploadVariableFiles;
|
|
@@ -79,7 +79,7 @@ class Run extends command_base_1.CommandBase {
|
|
|
79
79
|
const testCasesPath = flags["test-cases-path"];
|
|
80
80
|
const rulesPath = flags["rules-path"];
|
|
81
81
|
const settingsPath = flags["settings-path"];
|
|
82
|
-
const
|
|
82
|
+
const testCaseUuids = flags["test-case-uuid"];
|
|
83
83
|
const isAutoCreateAIBasedRulesEnabled = flags["auto-create-ai-rules"];
|
|
84
84
|
const explicitMutations = flags["explicit-mutations"];
|
|
85
85
|
const labels = flags["labels"];
|
|
@@ -108,8 +108,8 @@ class Run extends command_base_1.CommandBase {
|
|
|
108
108
|
if (minPort > maxPort) {
|
|
109
109
|
core_1.ux.error("--minPort cannot be greater than --maxPort");
|
|
110
110
|
}
|
|
111
|
-
if (
|
|
112
|
-
context.configuration.testCaseUuids =
|
|
111
|
+
if (testCaseUuids && testCaseUuids.length > 0) {
|
|
112
|
+
context.configuration.testCaseUuids = testCaseUuids;
|
|
113
113
|
}
|
|
114
114
|
if (isAutoCreateAIBasedRulesEnabled) {
|
|
115
115
|
context.configuration.isAutoCreateAIBasedRulesEnabled =
|
|
@@ -175,7 +175,7 @@ class Run extends command_base_1.CommandBase {
|
|
|
175
175
|
}
|
|
176
176
|
if (localTestNodesPath) {
|
|
177
177
|
try {
|
|
178
|
-
const localTestNodes = await (0, parser_1.parseSettings)(localTestNodesPath);
|
|
178
|
+
const localTestNodes = (await (0, parser_1.parseSettings)(localTestNodesPath));
|
|
179
179
|
if (localTestNodes) {
|
|
180
180
|
if (Array.isArray(localTestNodes.testNodes)) {
|
|
181
181
|
for (const node of localTestNodes.testNodes) {
|
|
@@ -301,8 +301,8 @@ class Run extends command_base_1.CommandBase {
|
|
|
301
301
|
// Checking last run id
|
|
302
302
|
task: async (ctx) => {
|
|
303
303
|
let pollBranch = flags.branch;
|
|
304
|
-
if (
|
|
305
|
-
pollBranch = `single-test-execution-${
|
|
304
|
+
if (this.isSingleTestCaseExecution(testCaseUuids, flags.branch)) {
|
|
305
|
+
pollBranch = `single-test-execution-${testCaseUuids[0]}`;
|
|
306
306
|
}
|
|
307
307
|
const statusResponse = await this.fetchStatus(testSuiteId, token, pollBranch, ctx.configuration.labels, ctx.configuration.excludedLabels);
|
|
308
308
|
context.lastRunId = (0, utils_1.extractRunIdFromDetailsUrl)(statusResponse.detailsUrl);
|
|
@@ -479,8 +479,8 @@ class Run extends command_base_1.CommandBase {
|
|
|
479
479
|
enabled: (ctx) => ctx.response?.queueId,
|
|
480
480
|
task: async (ctx, currentTask) => {
|
|
481
481
|
let pollBranch = flags.branch;
|
|
482
|
-
if (
|
|
483
|
-
pollBranch = `single-test-execution-${
|
|
482
|
+
if (this.isSingleTestCaseExecution(testCaseUuids, flags.branch)) {
|
|
483
|
+
pollBranch = `single-test-execution-${testCaseUuids[0]}`;
|
|
484
484
|
}
|
|
485
485
|
const detailsUrl = await this.waitForTestSuiteToBeCreated(testSuiteId, token, ctx.lastRunId, pollBranch, ctx.configuration.labels, ctx.configuration.excludedLabels);
|
|
486
486
|
task.title = `Running test suite [ ${detailsUrl} ]`;
|
|
@@ -493,8 +493,8 @@ class Run extends command_base_1.CommandBase {
|
|
|
493
493
|
enabled: (ctx) => ctx.response?.result === "ok" && !flags.async,
|
|
494
494
|
task: async (ctx, task) => {
|
|
495
495
|
let pollBranch = flags.branch;
|
|
496
|
-
if (
|
|
497
|
-
pollBranch = `single-test-execution-${
|
|
496
|
+
if (this.isSingleTestCaseExecution(testCaseUuids, flags.branch)) {
|
|
497
|
+
pollBranch = `single-test-execution-${testCaseUuids[0]}`;
|
|
498
498
|
}
|
|
499
499
|
return task.newListr([
|
|
500
500
|
{
|
|
@@ -563,6 +563,9 @@ class Run extends command_base_1.CommandBase {
|
|
|
563
563
|
}
|
|
564
564
|
this.exit(0);
|
|
565
565
|
}
|
|
566
|
+
isSingleTestCaseExecution(testCaseUuids, branch) {
|
|
567
|
+
return !!testCaseUuids && testCaseUuids.length === 1 && !branch;
|
|
568
|
+
}
|
|
566
569
|
async fetchStatus(testSuiteId, token, branch, labels, excludedLabels) {
|
|
567
570
|
const statusApiEndpoint = this.getStatusApiEndpoint(testSuiteId, branch, labels, excludedLabels);
|
|
568
571
|
const response = await (0, node_fetch_commonjs_1.default)(statusApiEndpoint, {
|
|
@@ -885,7 +888,8 @@ Run.flags = {
|
|
|
885
888
|
description: "Path to a YAML or JSON file with local test nodes configuration",
|
|
886
889
|
}),
|
|
887
890
|
"test-case-uuid": core_1.Flags.string({
|
|
888
|
-
description: "Test case uuid",
|
|
891
|
+
description: "Test case uuid (can be repeated to run multiple test cases)",
|
|
892
|
+
multiple: true,
|
|
889
893
|
}),
|
|
890
894
|
"auto-create-ai-rules": core_1.Flags.boolean({
|
|
891
895
|
description: "Enable auto create AI based rules",
|
package/dist/util/trtc.d.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export declare
|
|
2
|
-
export declare function download(dir: string): Promise<string | null>;
|
|
1
|
+
export declare function download(dir: string): Promise<string>;
|
package/dist/util/trtc.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.download =
|
|
3
|
+
exports.download = void 0;
|
|
4
4
|
const Fs = require("@supercharge/fs");
|
|
5
5
|
const fs = require("fs");
|
|
6
6
|
const node_fetch_commonjs_1 = require("node-fetch-commonjs");
|
|
@@ -28,7 +28,7 @@ const VERSION = "2.3.15";
|
|
|
28
28
|
const WIN32_PLATFORM = "win32";
|
|
29
29
|
const WIN32_BINARY = "trtc.exe";
|
|
30
30
|
const UNIX_BINARY = "trtc";
|
|
31
|
-
|
|
31
|
+
const BINARY_NAME = os.platform() === WIN32_PLATFORM ? WIN32_BINARY : UNIX_BINARY;
|
|
32
32
|
function getFolderName() {
|
|
33
33
|
const platform = os.platform();
|
|
34
34
|
const architecture = os.arch();
|
|
@@ -39,6 +39,13 @@ function getFolderName() {
|
|
|
39
39
|
}
|
|
40
40
|
throw new Error(`Unsupported platform ${platform} or architecture ${architecture}`);
|
|
41
41
|
}
|
|
42
|
+
// The Windows zip wraps its contents in a versioned top-level folder;
|
|
43
|
+
// the tarballs are flat.
|
|
44
|
+
function getBinaryPath(dir) {
|
|
45
|
+
return os.platform() === WIN32_PLATFORM
|
|
46
|
+
? path.join(dir, getFolderName(), BINARY_NAME)
|
|
47
|
+
: path.join(dir, BINARY_NAME);
|
|
48
|
+
}
|
|
42
49
|
function getUrl() {
|
|
43
50
|
const platform = os.platform();
|
|
44
51
|
const architecture = os.arch();
|
|
@@ -53,7 +60,7 @@ async function extractZip(dir, stream) {
|
|
|
53
60
|
return new Promise((resolve, reject) => {
|
|
54
61
|
stream
|
|
55
62
|
.pipe(unzip.Extract({ path: dir }))
|
|
56
|
-
.on("close", () => resolve(
|
|
63
|
+
.on("close", () => resolve(getBinaryPath(dir)))
|
|
57
64
|
.on("error", reject);
|
|
58
65
|
});
|
|
59
66
|
}
|
|
@@ -92,7 +99,7 @@ async function extractTar(dir, stream) {
|
|
|
92
99
|
stream.resume();
|
|
93
100
|
stream.on("end", next);
|
|
94
101
|
});
|
|
95
|
-
extract.on("finish", () => resolve(
|
|
102
|
+
extract.on("finish", () => resolve(getBinaryPath(dir)));
|
|
96
103
|
stream.pipe(zlib.createGunzip()).pipe(extract);
|
|
97
104
|
});
|
|
98
105
|
}
|
|
@@ -105,7 +112,7 @@ async function download(dir) {
|
|
|
105
112
|
if (stream == null) {
|
|
106
113
|
throw new Error("unexpected null response body");
|
|
107
114
|
}
|
|
108
|
-
if (os.platform() ===
|
|
115
|
+
if (os.platform() === WIN32_PLATFORM) {
|
|
109
116
|
return extractZip(dir, stream);
|
|
110
117
|
}
|
|
111
118
|
return extractTar(dir, stream);
|
package/dist/util/tunnel.js
CHANGED
|
@@ -20,16 +20,14 @@ type = "http_proxy"`;
|
|
|
20
20
|
await Fs.writeFile(configPath, newConfigContent);
|
|
21
21
|
return configPath;
|
|
22
22
|
}
|
|
23
|
-
async function startTrtc(trtc,
|
|
23
|
+
async function startTrtc(trtc, configPath) {
|
|
24
24
|
return new Promise((resolve, reject) => {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (!Fs.pathExistsSync(binaryPath)) {
|
|
28
|
-
reject(new Error(`Binary not found at ${binaryPath}`));
|
|
25
|
+
if (!Fs.pathExistsSync(trtc)) {
|
|
26
|
+
reject(new Error(`Binary not found at ${trtc}`));
|
|
29
27
|
return;
|
|
30
28
|
}
|
|
31
|
-
const tunnelProcess = childProcess.spawn(
|
|
32
|
-
cwd:
|
|
29
|
+
const tunnelProcess = childProcess.spawn(trtc, ["-c", configPath], {
|
|
30
|
+
cwd: path.dirname(trtc),
|
|
33
31
|
});
|
|
34
32
|
tunnelProcess.stdout.on("data", (data) => {
|
|
35
33
|
const dataString = data.toString();
|
|
@@ -68,21 +66,22 @@ class Tunnel {
|
|
|
68
66
|
if (this.binaryPath == null) {
|
|
69
67
|
throw new Error("Could not download the trtc binary");
|
|
70
68
|
}
|
|
71
|
-
|
|
69
|
+
let lastError;
|
|
72
70
|
let maxTries = 40;
|
|
73
71
|
while (maxTries > 0) {
|
|
74
72
|
try {
|
|
75
73
|
this.port = randomPort(minPort, maxPort);
|
|
76
74
|
this.configPath = await updateConfig(this.binaryPath, this.port);
|
|
77
|
-
this.process = await startTrtc(this.binaryPath,
|
|
75
|
+
this.process = await startTrtc(this.binaryPath, this.configPath);
|
|
78
76
|
break;
|
|
79
77
|
}
|
|
80
78
|
catch (e) {
|
|
79
|
+
lastError = e;
|
|
81
80
|
maxTries--;
|
|
82
81
|
}
|
|
83
82
|
}
|
|
84
83
|
if (maxTries === 0) {
|
|
85
|
-
throw new Error(
|
|
84
|
+
throw new Error(`Could not start trtc process: ${lastError instanceof Error ? lastError.message : String(lastError)}`);
|
|
86
85
|
}
|
|
87
86
|
this.running = true;
|
|
88
87
|
}
|
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.0.
|
|
2
|
+
"version": "0.0.47-beta",
|
|
3
3
|
"commands": {
|
|
4
4
|
"authenticate": {
|
|
5
5
|
"id": "authenticate",
|
|
@@ -204,8 +204,8 @@
|
|
|
204
204
|
"test-case-uuid": {
|
|
205
205
|
"name": "test-case-uuid",
|
|
206
206
|
"type": "option",
|
|
207
|
-
"description": "Test case uuid",
|
|
208
|
-
"multiple":
|
|
207
|
+
"description": "Test case uuid (can be repeated to run multiple test cases)",
|
|
208
|
+
"multiple": true
|
|
209
209
|
},
|
|
210
210
|
"auto-create-ai-rules": {
|
|
211
211
|
"name": "auto-create-ai-rules",
|