@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 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>"`
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 to run multiple test cases)",
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;
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.0.50-beta",
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 to run multiple test cases)",
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.50-beta",
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
  }