@testrigor/testrigor-cli 0.0.50-beta → 1.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
CHANGED
|
@@ -18,20 +18,21 @@ This is a command line tool for TestRigor. It allows you to run TestRigor tests
|
|
|
18
18
|
7. With test cases `testrigor test-suite run <test-suite-id> --token <token> --test-cases-path test_cases/**/*.{yaml,txt}`
|
|
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
|
-
10. Run a single test case `testrigor test-suite run <test-suite-id> --token <token> --test-case-uuid <test-case-uuid>`
|
|
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
|
|
24
|
-
13. Run with
|
|
25
|
-
14.
|
|
26
|
-
15.
|
|
27
|
-
16.
|
|
28
|
-
17.
|
|
29
|
-
18.
|
|
30
|
-
19.
|
|
31
|
-
20.
|
|
32
|
-
21.
|
|
33
|
-
22.
|
|
34
|
-
23.
|
|
21
|
+
10. Run a single test case `testrigor test-suite run <test-suite-id> --token <token> --test-case-uuid <test-case-uuid> --url <url>`
|
|
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> --url <url>`
|
|
23
|
+
12. Run a mobile test case with an APK `testrigor test-suite run <test-suite-id> --token <token> --test-case-uuid <test-case-uuid> --file-path ./app.apk`
|
|
24
|
+
13. 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`
|
|
25
|
+
14. Run with explicit mutations enabled `testrigor test-suite run <test-suite-id> --token <token> --test-cases-path test_cases/**/*.{yaml,txt} --explicit-mutations`
|
|
26
|
+
15. 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`
|
|
27
|
+
16. 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`
|
|
28
|
+
17. With comma-separated labels `testrigor test-suite run <test-suite-id> --token <token> --labels <labels>`
|
|
29
|
+
18. Excluding comma-separated labels `testrigor test-suite run <test-suite-id> --token <token> --excluded-labels <excluded-labels>`
|
|
30
|
+
19. 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>`
|
|
31
|
+
20. Set the default test suite ID: `testrigor test-suite config --default <test-suite-id>`
|
|
32
|
+
21. Remove the default test suite ID: `testrigor test-suite config --delete`
|
|
33
|
+
22. Show current configuration: `testrigor test-suite config --show`
|
|
34
|
+
23. Authenticate with TestRigor and store credentials (interactive prompt): `testrigor authenticate`
|
|
35
|
+
24. 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>"`
|
|
35
36
|
|
|
36
37
|
### Mobile Testing
|
|
37
38
|
|
|
@@ -888,8 +888,9 @@ Run.flags = {
|
|
|
888
888
|
description: "Path to a YAML or JSON file with local test nodes configuration",
|
|
889
889
|
}),
|
|
890
890
|
"test-case-uuid": core_1.Flags.string({
|
|
891
|
-
description: "Test case uuid (can be repeated
|
|
891
|
+
description: "Test case uuid (can be repeated). Requires --url (web) or --file-path (mobile app upload).",
|
|
892
892
|
multiple: true,
|
|
893
|
+
relationships: [{ type: "some", flags: ["url", "file-path"] }],
|
|
893
894
|
}),
|
|
894
895
|
"auto-create-ai-rules": core_1.Flags.boolean({
|
|
895
896
|
description: "Enable auto create AI based rules",
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { CommandBase } from "../../command-base";
|
|
2
|
+
export default class ValidateSyntax extends CommandBase<typeof ValidateSyntax> {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
private TESTRIGOR_API2_URL;
|
|
6
|
+
static flags: {
|
|
7
|
+
steps: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
8
|
+
"test-cases-path": import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
9
|
+
"base-url-api": import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
10
|
+
"rules-path": import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
11
|
+
"explicit-mutations": import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
};
|
|
13
|
+
static args: {
|
|
14
|
+
testSuiteId: import("@oclif/core/lib/interfaces/parser").Arg<string | undefined, Record<string, unknown>>;
|
|
15
|
+
};
|
|
16
|
+
run(): Promise<void>;
|
|
17
|
+
private resolveStepsToValidate;
|
|
18
|
+
private reportValidationResults;
|
|
19
|
+
private callValidateSyntax;
|
|
20
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const node_fetch_commonjs_1 = require("node-fetch-commonjs");
|
|
5
|
+
const command_base_1 = require("../../command-base");
|
|
6
|
+
const environments_1 = require("../../config/environments");
|
|
7
|
+
const parser_1 = require("../../util/parser");
|
|
8
|
+
const core_2 = require("@oclif/core");
|
|
9
|
+
class ValidateSyntax extends command_base_1.CommandBase {
|
|
10
|
+
async run() {
|
|
11
|
+
const flags = this.flags;
|
|
12
|
+
const args = this.args;
|
|
13
|
+
const baseUrlApi = flags["base-url-api"] || environments_1.environments.prod.TESTRIGOR_API_URL;
|
|
14
|
+
this.TESTRIGOR_API2_URL = `${baseUrlApi.replace(/\/$/, "")}/api/v1`;
|
|
15
|
+
if (!flags.steps && !flags["test-cases-path"]) {
|
|
16
|
+
this.error("Provide either --steps or --test-cases-path");
|
|
17
|
+
}
|
|
18
|
+
const token = await this.resolveToken();
|
|
19
|
+
const testSuiteId = await this.resolveTestSuiteId(args.testSuiteId);
|
|
20
|
+
const casesToValidate = await this.resolveStepsToValidate(flags.steps, flags["test-cases-path"]);
|
|
21
|
+
if (casesToValidate.length === 0) {
|
|
22
|
+
this.error("No test case files matched --test-cases-path");
|
|
23
|
+
}
|
|
24
|
+
const rules = flags["rules-path"]
|
|
25
|
+
? await (0, parser_1.parseRules)(flags["rules-path"])
|
|
26
|
+
: [];
|
|
27
|
+
const explicitMutations = flags["explicit-mutations"];
|
|
28
|
+
await this.reportValidationResults(testSuiteId, token, casesToValidate, rules, explicitMutations);
|
|
29
|
+
}
|
|
30
|
+
async resolveStepsToValidate(steps, testCasesPath) {
|
|
31
|
+
if (steps) {
|
|
32
|
+
return [{ description: "provided steps", customSteps: steps }];
|
|
33
|
+
}
|
|
34
|
+
const testCases = await (0, parser_1.parseTestCases)(testCasesPath);
|
|
35
|
+
return testCases.map((testCase) => ({
|
|
36
|
+
description: testCase.description,
|
|
37
|
+
customSteps: testCase.customSteps,
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
async reportValidationResults(testSuiteId, token, cases, rules, explicitMutations) {
|
|
41
|
+
let hasAnyInvalidTestCases = false;
|
|
42
|
+
for (const testCase of cases) {
|
|
43
|
+
const response = await this.callValidateSyntax(testSuiteId, testCase.customSteps, token, rules, explicitMutations);
|
|
44
|
+
if (response.data && response.data.length > 0) {
|
|
45
|
+
const parserErrors = response.data;
|
|
46
|
+
core_2.ux.info(`${testCase.description}: invalid`);
|
|
47
|
+
for (const parserError of parserErrors) {
|
|
48
|
+
core_2.ux.info(` ${parserError.command} - ${parserError.errorMessage}`);
|
|
49
|
+
}
|
|
50
|
+
hasAnyInvalidTestCases = true;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
core_2.ux.info(`${testCase.description}: valid`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (hasAnyInvalidTestCases) {
|
|
57
|
+
this.exit(1);
|
|
58
|
+
}
|
|
59
|
+
core_2.ux.info("All provided steps are valid.");
|
|
60
|
+
this.exit(0);
|
|
61
|
+
}
|
|
62
|
+
async callValidateSyntax(testSuiteId, steps, token, rules, explicitMutations) {
|
|
63
|
+
const body = { steps };
|
|
64
|
+
if (rules.length > 0) {
|
|
65
|
+
body.rules = rules;
|
|
66
|
+
}
|
|
67
|
+
if (explicitMutations) {
|
|
68
|
+
body.explicitMutations = explicitMutations;
|
|
69
|
+
}
|
|
70
|
+
const response = await (0, node_fetch_commonjs_1.default)(`${this.TESTRIGOR_API2_URL}/apps/${testSuiteId}/validate-syntax`, {
|
|
71
|
+
method: "POST",
|
|
72
|
+
body: JSON.stringify(body),
|
|
73
|
+
headers: {
|
|
74
|
+
"Content-Type": "application/json",
|
|
75
|
+
Accept: "application/json",
|
|
76
|
+
"auth-token": token,
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
if (!response.ok) {
|
|
80
|
+
throw new Error(`Failed to validate syntax: ${response.status} ${response.statusText}`);
|
|
81
|
+
}
|
|
82
|
+
return (await response.json());
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.default = ValidateSyntax;
|
|
86
|
+
ValidateSyntax.description = "Validate step syntax against a test suite's reusable rules, without running the steps";
|
|
87
|
+
ValidateSyntax.examples = [
|
|
88
|
+
'testrigor test-suite validate-syntax <test-suite-id> --steps "click \\"Login\\""',
|
|
89
|
+
'testrigor test-suite validate-syntax <test-suite-id> --test-cases-path "test_cases/**/*.{yaml,txt}"',
|
|
90
|
+
];
|
|
91
|
+
ValidateSyntax.flags = {
|
|
92
|
+
steps: core_1.Flags.string({
|
|
93
|
+
description: "Raw step text to validate directly",
|
|
94
|
+
exclusive: ["test-cases-path"],
|
|
95
|
+
}),
|
|
96
|
+
"test-cases-path": core_1.Flags.string({
|
|
97
|
+
description: "Test case files to validate (same glob format as `test-suite run --test-cases-path`)",
|
|
98
|
+
exclusive: ["steps"],
|
|
99
|
+
}),
|
|
100
|
+
"base-url-api": core_1.Flags.string({
|
|
101
|
+
description: "Base URL for API2 (e.g., https://api2.testrigor.com)",
|
|
102
|
+
}),
|
|
103
|
+
"rules-path": core_1.Flags.string({
|
|
104
|
+
description: "Ad hoc reusable rules to validate against, for rules not yet saved to this suite (same glob format as `test-suite run --rules-path`)",
|
|
105
|
+
}),
|
|
106
|
+
"explicit-mutations": core_1.Flags.boolean({
|
|
107
|
+
description: "Validate using only the supplied rules instead of merging them with the suite's saved rules",
|
|
108
|
+
default: false,
|
|
109
|
+
}),
|
|
110
|
+
};
|
|
111
|
+
ValidateSyntax.args = {
|
|
112
|
+
testSuiteId: core_1.Args.string({
|
|
113
|
+
name: "testSuiteId",
|
|
114
|
+
description: "The test suite id (optional if set in config)",
|
|
115
|
+
required: false,
|
|
116
|
+
}),
|
|
117
|
+
};
|
package/dist/types.d.ts
CHANGED
|
@@ -51,6 +51,13 @@ export type Rule = {
|
|
|
51
51
|
name: string;
|
|
52
52
|
labels: string[];
|
|
53
53
|
};
|
|
54
|
+
export type ParserError = {
|
|
55
|
+
command?: string;
|
|
56
|
+
errorMessage?: string;
|
|
57
|
+
};
|
|
58
|
+
export type ValidateSyntaxApiResponse = Api2Wrapper & {
|
|
59
|
+
data?: ParserError[];
|
|
60
|
+
};
|
|
54
61
|
export type ChromeExtensionInput = {
|
|
55
62
|
name: string;
|
|
56
63
|
file: string;
|
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.0
|
|
2
|
+
"version": "1.0.0",
|
|
3
3
|
"commands": {
|
|
4
4
|
"authenticate": {
|
|
5
5
|
"id": "authenticate",
|
|
@@ -204,8 +204,17 @@
|
|
|
204
204
|
"test-case-uuid": {
|
|
205
205
|
"name": "test-case-uuid",
|
|
206
206
|
"type": "option",
|
|
207
|
-
"description": "Test case uuid (can be repeated
|
|
208
|
-
"multiple": true
|
|
207
|
+
"description": "Test case uuid (can be repeated). Requires --url (web) or --file-path (mobile app upload).",
|
|
208
|
+
"multiple": true,
|
|
209
|
+
"relationships": [
|
|
210
|
+
{
|
|
211
|
+
"type": "some",
|
|
212
|
+
"flags": [
|
|
213
|
+
"url",
|
|
214
|
+
"file-path"
|
|
215
|
+
]
|
|
216
|
+
}
|
|
217
|
+
]
|
|
209
218
|
},
|
|
210
219
|
"auto-create-ai-rules": {
|
|
211
220
|
"name": "auto-create-ai-rules",
|
|
@@ -266,6 +275,103 @@
|
|
|
266
275
|
"required": false
|
|
267
276
|
}
|
|
268
277
|
}
|
|
278
|
+
},
|
|
279
|
+
"test-suite:validate-syntax": {
|
|
280
|
+
"id": "test-suite:validate-syntax",
|
|
281
|
+
"description": "Validate step syntax against a test suite's reusable rules, without running the steps",
|
|
282
|
+
"strict": true,
|
|
283
|
+
"pluginName": "@testrigor/testrigor-cli",
|
|
284
|
+
"pluginAlias": "@testrigor/testrigor-cli",
|
|
285
|
+
"pluginType": "core",
|
|
286
|
+
"aliases": [],
|
|
287
|
+
"hiddenAliases": [],
|
|
288
|
+
"examples": [
|
|
289
|
+
"testrigor test-suite validate-syntax <test-suite-id> --steps \"click \\\"Login\\\"\"",
|
|
290
|
+
"testrigor test-suite validate-syntax <test-suite-id> --test-cases-path \"test_cases/**/*.{yaml,txt}\""
|
|
291
|
+
],
|
|
292
|
+
"flags": {
|
|
293
|
+
"auth-token": {
|
|
294
|
+
"name": "auth-token",
|
|
295
|
+
"type": "option",
|
|
296
|
+
"description": "Personal authentication token",
|
|
297
|
+
"required": false,
|
|
298
|
+
"helpGroup": "GLOBAL",
|
|
299
|
+
"multiple": false
|
|
300
|
+
},
|
|
301
|
+
"token": {
|
|
302
|
+
"name": "token",
|
|
303
|
+
"type": "option",
|
|
304
|
+
"char": "t",
|
|
305
|
+
"description": "Suite authentication token",
|
|
306
|
+
"required": false,
|
|
307
|
+
"helpGroup": "GLOBAL",
|
|
308
|
+
"multiple": false
|
|
309
|
+
},
|
|
310
|
+
"min-port": {
|
|
311
|
+
"name": "min-port",
|
|
312
|
+
"type": "option",
|
|
313
|
+
"description": "Min port for tunnel",
|
|
314
|
+
"multiple": false,
|
|
315
|
+
"default": 40000
|
|
316
|
+
},
|
|
317
|
+
"max-port": {
|
|
318
|
+
"name": "max-port",
|
|
319
|
+
"type": "option",
|
|
320
|
+
"description": "Max port for tunnel",
|
|
321
|
+
"multiple": false,
|
|
322
|
+
"default": 50000
|
|
323
|
+
},
|
|
324
|
+
"verbose": {
|
|
325
|
+
"name": "verbose",
|
|
326
|
+
"type": "boolean",
|
|
327
|
+
"description": "Verbose output",
|
|
328
|
+
"helpGroup": "GLOBAL",
|
|
329
|
+
"allowNo": false
|
|
330
|
+
},
|
|
331
|
+
"steps": {
|
|
332
|
+
"name": "steps",
|
|
333
|
+
"type": "option",
|
|
334
|
+
"description": "Raw step text to validate directly",
|
|
335
|
+
"multiple": false,
|
|
336
|
+
"exclusive": [
|
|
337
|
+
"test-cases-path"
|
|
338
|
+
]
|
|
339
|
+
},
|
|
340
|
+
"test-cases-path": {
|
|
341
|
+
"name": "test-cases-path",
|
|
342
|
+
"type": "option",
|
|
343
|
+
"description": "Test case files to validate (same glob format as `test-suite run --test-cases-path`)",
|
|
344
|
+
"multiple": false,
|
|
345
|
+
"exclusive": [
|
|
346
|
+
"steps"
|
|
347
|
+
]
|
|
348
|
+
},
|
|
349
|
+
"base-url-api": {
|
|
350
|
+
"name": "base-url-api",
|
|
351
|
+
"type": "option",
|
|
352
|
+
"description": "Base URL for API2 (e.g., https://api2.testrigor.com)",
|
|
353
|
+
"multiple": false
|
|
354
|
+
},
|
|
355
|
+
"rules-path": {
|
|
356
|
+
"name": "rules-path",
|
|
357
|
+
"type": "option",
|
|
358
|
+
"description": "Ad hoc reusable rules to validate against, for rules not yet saved to this suite (same glob format as `test-suite run --rules-path`)",
|
|
359
|
+
"multiple": false
|
|
360
|
+
},
|
|
361
|
+
"explicit-mutations": {
|
|
362
|
+
"name": "explicit-mutations",
|
|
363
|
+
"type": "boolean",
|
|
364
|
+
"description": "Validate using only the supplied rules instead of merging them with the suite's saved rules",
|
|
365
|
+
"allowNo": false
|
|
366
|
+
}
|
|
367
|
+
},
|
|
368
|
+
"args": {
|
|
369
|
+
"testSuiteId": {
|
|
370
|
+
"name": "testSuiteId",
|
|
371
|
+
"description": "The test suite id (optional if set in config)",
|
|
372
|
+
"required": false
|
|
373
|
+
}
|
|
374
|
+
}
|
|
269
375
|
}
|
|
270
376
|
}
|
|
271
377
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@testrigor/testrigor-cli",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "TestRigor Command Line",
|
|
5
5
|
"author": "Ivo Parun Rua @parunruaivo",
|
|
6
6
|
"bin": {
|
|
@@ -77,6 +77,9 @@
|
|
|
77
77
|
"test-suite:run": {
|
|
78
78
|
"description": "Run all tests of a Test Suite"
|
|
79
79
|
},
|
|
80
|
+
"test-suite:validate-syntax": {
|
|
81
|
+
"description": "Validate step syntax against a test suite's reusable rules, without running the steps"
|
|
82
|
+
},
|
|
80
83
|
"authenticate": {
|
|
81
84
|
"description": "Set your testRigor personal authentication token"
|
|
82
85
|
}
|