@testspectra/cli 1.3.5 → 1.3.7

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.
@@ -1,6 +1,11 @@
1
1
  import { type ActionKey, type AssertionKey, type ExecutionSummary, formatAction, formatAssertion, type NetworkResource, parseAndFormat, type PendingStep, type PendingTestCase, type ReporterOptions, SemanticReporter, stripAnsi, type TestLog, type TestRunResult } from '@testspectra/reporter';
2
2
  export { type ActionKey, type AssertionKey, type ExecutionSummary, formatAction, formatAssertion, type NetworkResource, parseAndFormat, type PendingStep, type PendingTestCase, type ReporterOptions, SemanticReporter, stripAnsi, type TestLog, type TestRunResult, };
3
3
  export declare class Reporter extends SemanticReporter {
4
+ /**
5
+ * Prints a finished test case's steps, each `Spectra.step` as a ▸ heading (red when it failed)
6
+ * with the actions and assertions it ran indented under it.
7
+ */
8
+ private printStepTree;
4
9
  private isInteractive;
5
10
  private lastRenderedLines;
6
11
  private spinnerFrames;
@@ -1,7 +1,27 @@
1
- import { formatAction, formatAssertion, parseAndFormat, SemanticReporter, stripAnsi, } from '@testspectra/reporter';
1
+ import { formatAction, formatAssertion, groupKey, parseAndFormat, readGroupPath, SemanticReporter, stepTree, stripAnsi, } from '@testspectra/reporter';
2
2
  import chalk from 'chalk';
3
3
  export { formatAction, formatAssertion, parseAndFormat, SemanticReporter, stripAnsi, };
4
4
  export class Reporter extends SemanticReporter {
5
+ /**
6
+ * Prints a finished test case's steps, each `Spectra.step` as a ▸ heading (red when it failed)
7
+ * with the actions and assertions it ran indented under it.
8
+ */
9
+ printStepTree(steps, groups) {
10
+ for (const line of stepTree(steps, groups)) {
11
+ const indent = ' '.repeat(line.depth + 1);
12
+ const took = line.duration !== undefined ? ` ${chalk.gray(`(${line.duration}ms)`)}` : '';
13
+ if (line.kind === 'group') {
14
+ const mark = line.passed ? chalk.cyan('▸') : chalk.red('▸');
15
+ console.log(`${indent}${mark} ${line.passed ? chalk.white.bold(line.text) : chalk.red.bold(line.text)}${took}`);
16
+ }
17
+ else if (line.passed) {
18
+ console.log(`${indent}${chalk.green('✔')} ${line.text}${took}`);
19
+ }
20
+ else {
21
+ console.log(`${indent}${chalk.red('✖')} ${chalk.red(line.text)}${took}`);
22
+ }
23
+ }
24
+ }
5
25
  isInteractive;
6
26
  lastRenderedLines = 0;
7
27
  spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
@@ -145,6 +165,25 @@ export class Reporter extends SemanticReporter {
145
165
  this.options.onStepStart?.(testTitle || testCase?.title || '', formatted, workerId ?? testCase?.workerId);
146
166
  return;
147
167
  }
168
+ // 2.5 A `Spectra.step` group ended -> record its outcome for the step tree
169
+ if (raw.startsWith('[TESTSPECTRA_GROUP_PASS]') || raw.startsWith('[TESTSPECTRA_GROUP_FAIL]')) {
170
+ const passed = raw.startsWith('[TESTSPECTRA_GROUP_PASS]');
171
+ const fullText = raw.replace(/^\[TESTSPECTRA_GROUP_(PASS|FAIL)\]/, '').trim();
172
+ const match = fullText.match(/\(([^)]+)ms\)$/);
173
+ const duration = match ? parseInt(match[1], 10) : 0;
174
+ try {
175
+ const payload = JSON.parse(fullText.replace(/\s*\([^)]+\)$/, '').trim());
176
+ const testCase = this.resolveTestCase(payload.test || '', payload.workerId);
177
+ if (testCase && Array.isArray(payload.path)) {
178
+ testCase.groups = { ...testCase.groups, [groupKey(payload.path)]: { passed, duration } };
179
+ }
180
+ }
181
+ catch { }
182
+ return;
183
+ }
184
+ if (raw.startsWith('[TESTSPECTRA_GROUP_START]')) {
185
+ return;
186
+ }
148
187
  // 3. Step passed -> record step to matching test case
149
188
  if (raw.startsWith('[TESTSPECTRA_STEP_PASS]')) {
150
189
  const fullText = raw.replace('[TESTSPECTRA_STEP_PASS]', '').trim();
@@ -161,7 +200,7 @@ export class Reporter extends SemanticReporter {
161
200
  }
162
201
  catch { }
163
202
  const testCase = this.resolveTestCase(testTitle, workerId);
164
- const step = { text: formatted, duration, passed: true };
203
+ const step = { text: formatted, duration, passed: true, groupPath: readGroupPath(cmdText) };
165
204
  if (testCase) {
166
205
  testCase.steps.push(step);
167
206
  testCase.currentStep = formatted;
@@ -186,7 +225,7 @@ export class Reporter extends SemanticReporter {
186
225
  }
187
226
  catch { }
188
227
  const testCase = this.resolveTestCase(testTitle, workerId);
189
- const step = { text: formatted, duration, passed: false };
228
+ const step = { text: formatted, duration, passed: false, groupPath: readGroupPath(cmdText) };
190
229
  if (testCase) {
191
230
  testCase.steps.push(step);
192
231
  testCase.currentStep = formatted;
@@ -239,9 +278,7 @@ export class Reporter extends SemanticReporter {
239
278
  }
240
279
  this.clearActiveSlots();
241
280
  console.log(`${chalk.hex('#34d399')('✓')} ${chalk.white.bold(title)} ${chalk.gray(`(${duration}ms)`)}`);
242
- for (const step of steps) {
243
- console.log(` ${chalk.green('✔')} ${step.text} ${chalk.gray(`(${step.duration}ms)`)}`);
244
- }
281
+ this.printStepTree(steps, testCase?.groups);
245
282
  console.log('');
246
283
  this.renderActiveSlots();
247
284
  this.options.onTestPass?.({ title, duration, steps, workerId });
@@ -266,14 +303,7 @@ export class Reporter extends SemanticReporter {
266
303
  }
267
304
  this.clearActiveSlots();
268
305
  console.log(`${chalk.hex('#f87171')('✗')} ${chalk.white.bold(title)} ${chalk.gray(`(${duration}ms)`)}`);
269
- for (const step of steps) {
270
- if (step.passed) {
271
- console.log(` ${chalk.green('✔')} ${step.text} ${chalk.gray(`(${step.duration}ms)`)}`);
272
- }
273
- else {
274
- console.log(` ${chalk.red('✖')} ${chalk.red(step.text)} ${chalk.gray(`(${step.duration}ms)`)}`);
275
- }
276
- }
306
+ this.printStepTree(steps, testCase?.groups);
277
307
  if (errorMsg) {
278
308
  const errLines = errorMsg.split('\n');
279
309
  console.log(` \x1b[38;2;251;191;36m↳ Error:\x1b[0m \x1b[38;2;248;113;113m${errLines[0]}\x1b[0m`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testspectra/cli",
3
- "version": "1.3.5",
3
+ "version": "1.3.7",
4
4
  "description": "TestSpectra Cross-Platform Test Runner CLI",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -25,11 +25,11 @@
25
25
  ],
26
26
  "dependencies": {
27
27
  "@clack/prompts": "^1.7.0",
28
- "@testspectra/matchers": "^1.3.5",
29
- "@testspectra/react": "^1.3.5",
30
- "@testspectra/react-native": "^1.3.5",
31
- "@testspectra/reporter": "^1.3.5",
32
- "@testspectra/skills": "^1.3.5",
28
+ "@testspectra/matchers": "^1.3.7",
29
+ "@testspectra/react": "^1.3.7",
30
+ "@testspectra/react-native": "^1.3.7",
31
+ "@testspectra/reporter": "^1.3.7",
32
+ "@testspectra/skills": "^1.3.7",
33
33
  "chalk": "^5.3.0",
34
34
  "commander": "^12.1.0",
35
35
  "cross-spawn": "^7.0.6",
@@ -40,9 +40,9 @@
40
40
  "zod": "^3.23.8"
41
41
  },
42
42
  "optionalDependencies": {
43
- "@testspectra/cli-darwin-arm64": "1.3.5",
44
- "@testspectra/cli-linux-x64": "1.3.5",
45
- "@testspectra/cli-win32-x64": "1.3.5"
43
+ "@testspectra/cli-darwin-arm64": "1.3.7",
44
+ "@testspectra/cli-linux-x64": "1.3.7",
45
+ "@testspectra/cli-win32-x64": "1.3.7"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/cross-spawn": "^6.0.6",
@@ -17,9 +17,9 @@
17
17
  "postinstall": "spectra sync-types"
18
18
  },
19
19
  "devDependencies": {
20
- "@testspectra/cli": "^1.3.5",
21
- "@testspectra/matchers": "^1.3.5",
22
- "@testspectra/plugin-demo": "^1.3.5",
20
+ "@testspectra/cli": "^1.3.7",
21
+ "@testspectra/matchers": "^1.3.7",
22
+ "@testspectra/plugin-demo": "^1.3.7",
23
23
  "@types/node": "^20.14.0",
24
24
  "@wdio/cli": "^9.2.8",
25
25
  "@wdio/local-runner": "^9.2.8",
@@ -12,8 +12,8 @@
12
12
  "postinstall": "spectra sync-types"
13
13
  },
14
14
  "devDependencies": {
15
- "@testspectra/cli": "^1.3.5",
16
- "@testspectra/matchers": "^1.3.5",
15
+ "@testspectra/cli": "^1.3.7",
16
+ "@testspectra/matchers": "^1.3.7",
17
17
  "@types/node": "^20.14.0",
18
18
  "@wdio/cli": "^9.2.8",
19
19
  "@wdio/local-runner": "^9.2.8",
@@ -14,9 +14,9 @@
14
14
  "postinstall": "spectra sync-types"
15
15
  },
16
16
  "devDependencies": {
17
- "@testspectra/cli": "^1.3.5",
18
- "@testspectra/matchers": "^1.3.5",
19
- "@testspectra/react": "^1.3.5",
17
+ "@testspectra/cli": "^1.3.7",
18
+ "@testspectra/matchers": "^1.3.7",
19
+ "@testspectra/react": "^1.3.7",
20
20
  "@types/node": "^20.14.0",
21
21
  "@types/react": "^18.3.3",
22
22
  "@types/react-dom": "^18.3.0",
@@ -12,9 +12,9 @@
12
12
  "postinstall": "spectra sync-types"
13
13
  },
14
14
  "devDependencies": {
15
- "@testspectra/cli": "^1.3.5",
16
- "@testspectra/matchers": "^1.3.5",
17
- "@testspectra/react-native": "^1.3.5",
15
+ "@testspectra/cli": "^1.3.7",
16
+ "@testspectra/matchers": "^1.3.7",
17
+ "@testspectra/react-native": "^1.3.7",
18
18
  "@types/node": "^20.14.0",
19
19
  "@types/react": "^18.3.12",
20
20
  "@types/react-native": "^0.73.0",