sxy-test-runner 2.4.3 → 2.4.5

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.
Files changed (45) hide show
  1. package/AGENTS.md +77 -14
  2. package/dist/cli/help.js +32 -11
  3. package/dist/cli/help.js.map +1 -1
  4. package/dist/cli/index.js +3 -23
  5. package/dist/cli/index.js.map +1 -1
  6. package/dist/cli/init.js +1 -0
  7. package/dist/cli/init.js.map +1 -1
  8. package/dist/cli/lib/agentReport.d.ts +1 -1
  9. package/dist/cli/lib/agentReport.js +6 -1
  10. package/dist/cli/lib/agentReport.js.map +1 -1
  11. package/dist/cli/lib/defaultConfig.js +1 -0
  12. package/dist/cli/lib/defaultConfig.js.map +1 -1
  13. package/dist/cli/lib/exitCodes.d.ts +10 -0
  14. package/dist/cli/lib/exitCodes.js +27 -0
  15. package/dist/cli/lib/exitCodes.js.map +1 -0
  16. package/dist/cli/lib/parseCommandLineArguments.js +13 -1
  17. package/dist/cli/lib/parseCommandLineArguments.js.map +1 -1
  18. package/dist/cli/lib/resolveCommand.d.ts +8 -0
  19. package/dist/cli/lib/resolveCommand.js +50 -0
  20. package/dist/cli/lib/resolveCommand.js.map +1 -0
  21. package/dist/cli/lib/runDescribe.d.ts +2 -1
  22. package/dist/cli/lib/runDescribe.js +5 -2
  23. package/dist/cli/lib/runDescribe.js.map +1 -1
  24. package/dist/cli/lib/runDescribeRun.d.ts +2 -1
  25. package/dist/cli/lib/runDescribeRun.js +8 -2
  26. package/dist/cli/lib/runDescribeRun.js.map +1 -1
  27. package/dist/cli/lib/runTest.d.ts +2 -1
  28. package/dist/cli/lib/runTest.js +6 -2
  29. package/dist/cli/lib/runTest.js.map +1 -1
  30. package/dist/cli/lib/runTests.js +19 -4
  31. package/dist/cli/lib/runTests.js.map +1 -1
  32. package/dist/cli/lib/stopSignal.d.ts +7 -0
  33. package/dist/cli/lib/stopSignal.js +10 -0
  34. package/dist/cli/lib/stopSignal.js.map +1 -0
  35. package/dist/cli/once.js +40 -14
  36. package/dist/cli/once.js.map +1 -1
  37. package/dist/cli/version.d.ts +2 -0
  38. package/dist/cli/version.js +23 -0
  39. package/dist/cli/version.js.map +1 -0
  40. package/dist/cli/watch.js +3 -0
  41. package/dist/cli/watch.js.map +1 -1
  42. package/dist/types.d.ts +3 -2
  43. package/dist/types.js.map +1 -1
  44. package/package.json +3 -1
  45. package/readme.md +73 -6
@@ -0,0 +1,50 @@
1
+ export const commands = ['init', 'once', 'watch', 'help', 'version'];
2
+ function isCommand(value) {
3
+ return commands.includes(value);
4
+ }
5
+ // The options that consume the next argument, so `--filter-it -h` is understood as a filter
6
+ // for "-h" rather than a request for help. Worst case if this drifts from the option lists
7
+ // in watch.ts and once.ts is that such an argument shows help instead.
8
+ const valueTakingFlags = new Set([
9
+ '--config', '-c',
10
+ '--test-files', '-t',
11
+ '--filter', '-f',
12
+ '--filter-it', '-i',
13
+ '--filter-describe', '-d',
14
+ '--status-file', '-s'
15
+ ]);
16
+ // --help and --version describe the tool rather than asking it to do anything, so they take
17
+ // over from whatever command they were given to
18
+ function interceptingCommand(commandArgs) {
19
+ for (let position = 0; position < commandArgs.length; position++) {
20
+ const arg = commandArgs[position];
21
+ if (arg === undefined)
22
+ continue;
23
+ if (valueTakingFlags.has(arg)) {
24
+ position++; // skip the value, whatever it looks like
25
+ continue;
26
+ }
27
+ if (arg === '--help' || arg === '-h')
28
+ return 'help';
29
+ if (arg === '--version' || arg === '-v')
30
+ return 'version';
31
+ }
32
+ return undefined;
33
+ }
34
+ // Routes the raw argv tail to a command. Extracted from the entry module so the routing can
35
+ // be tested without running a command as a side effect of importing it.
36
+ export function resolveCommand(args) {
37
+ const first = args[0];
38
+ if (first !== undefined && isCommand(first)) {
39
+ const commandArgs = args.slice(1);
40
+ return { command: interceptingCommand(commandArgs) ?? first, commandArgs };
41
+ }
42
+ if (first !== undefined && first.startsWith('--') && isCommand(first.slice(2))) {
43
+ const commandArgs = args.slice(1);
44
+ const command = first.slice(2);
45
+ return { command: interceptingCommand(commandArgs) ?? command, commandArgs };
46
+ }
47
+ // no command given - everything is an argument to the default
48
+ return { command: interceptingCommand(args) ?? 'watch', commandArgs: args };
49
+ }
50
+ //# sourceMappingURL=resolveCommand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveCommand.js","sourceRoot":"","sources":["../../../src/cli/lib/resolveCommand.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,CAAU,CAAA;AAS7E,SAAS,SAAS,CAAC,KAAa;IAC5B,OAAQ,QAA8B,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AAC1D,CAAC;AAED,4FAA4F;AAC5F,2FAA2F;AAC3F,uEAAuE;AACvE,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC;IAC7B,UAAU,EAAE,IAAI;IAChB,cAAc,EAAE,IAAI;IACpB,UAAU,EAAE,IAAI;IAChB,aAAa,EAAE,IAAI;IACnB,mBAAmB,EAAE,IAAI;IACzB,eAAe,EAAE,IAAI;CACxB,CAAC,CAAA;AAEF,4FAA4F;AAC5F,gDAAgD;AAChD,SAAS,mBAAmB,CAAC,WAAqB;IAC9C,KAAK,IAAI,QAAQ,GAAG,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC;QAC/D,MAAM,GAAG,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAA;QACjC,IAAI,GAAG,KAAK,SAAS;YAAE,SAAQ;QAC/B,IAAI,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5B,QAAQ,EAAE,CAAA,CAAC,yCAAyC;YACpD,SAAQ;QACZ,CAAC;QACD,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;YAAE,OAAO,MAAM,CAAA;QACnD,IAAI,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,IAAI;YAAE,OAAO,SAAS,CAAA;IAC7D,CAAC;IACD,OAAO,SAAS,CAAA;AACpB,CAAC;AAED,4FAA4F;AAC5F,wEAAwE;AACxE,MAAM,UAAU,cAAc,CAAC,IAAc;IACzC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;IAErB,IAAI,KAAK,KAAK,SAAS,IAAI,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QACjC,OAAO,EAAE,OAAO,EAAE,mBAAmB,CAAC,WAAW,CAAC,IAAI,KAAK,EAAE,WAAW,EAAE,CAAA;IAC9E,CAAC;IAED,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7E,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QACjC,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAY,CAAA;QACzC,OAAO,EAAE,OAAO,EAAE,mBAAmB,CAAC,WAAW,CAAC,IAAI,OAAO,EAAE,WAAW,EAAE,CAAA;IAChF,CAAC;IAED,8DAA8D;IAC9D,OAAO,EAAE,OAAO,EAAE,mBAAmB,CAAC,IAAI,CAAC,IAAI,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,CAAA;AAC/E,CAAC","sourcesContent":["export const commands = ['init', 'once', 'watch', 'help', 'version'] as const\n\nexport type Command = typeof commands[number]\n\nexport interface ResolvedCommand {\n command: Command\n commandArgs: string[]\n}\n\nfunction isCommand(value: string): value is Command {\n return (commands as readonly string[]).includes(value)\n}\n\n// The options that consume the next argument, so `--filter-it -h` is understood as a filter\n// for \"-h\" rather than a request for help. Worst case if this drifts from the option lists\n// in watch.ts and once.ts is that such an argument shows help instead.\nconst valueTakingFlags = new Set([\n '--config', '-c',\n '--test-files', '-t',\n '--filter', '-f',\n '--filter-it', '-i',\n '--filter-describe', '-d',\n '--status-file', '-s'\n])\n\n// --help and --version describe the tool rather than asking it to do anything, so they take\n// over from whatever command they were given to\nfunction interceptingCommand(commandArgs: string[]): Command | undefined {\n for (let position = 0; position < commandArgs.length; position++) {\n const arg = commandArgs[position]\n if (arg === undefined) continue\n if (valueTakingFlags.has(arg)) {\n position++ // skip the value, whatever it looks like\n continue\n }\n if (arg === '--help' || arg === '-h') return 'help'\n if (arg === '--version' || arg === '-v') return 'version'\n }\n return undefined\n}\n\n// Routes the raw argv tail to a command. Extracted from the entry module so the routing can\n// be tested without running a command as a side effect of importing it.\nexport function resolveCommand(args: string[]): ResolvedCommand {\n const first = args[0]\n\n if (first !== undefined && isCommand(first)) {\n const commandArgs = args.slice(1)\n return { command: interceptingCommand(commandArgs) ?? first, commandArgs }\n }\n\n if (first !== undefined && first.startsWith('--') && isCommand(first.slice(2))) {\n const commandArgs = args.slice(1)\n const command = first.slice(2) as Command\n return { command: interceptingCommand(commandArgs) ?? command, commandArgs }\n }\n\n // no command given - everything is an argument to the default\n return { command: interceptingCommand(args) ?? 'watch', commandArgs: args }\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { type StopSignal } from './stopSignal.js';
1
2
  import type { FinalConfig, Describe, DescribeResult } from '../../types.js';
2
- export declare function runDescribe(config: FinalConfig, describe: Describe, itFilter?: string): Promise<DescribeResult>;
3
+ export declare function runDescribe(config: FinalConfig, describe: Describe, itFilter?: string, stop?: StopSignal): Promise<DescribeResult>;
3
4
  //# sourceMappingURL=runDescribe.d.ts.map
@@ -2,6 +2,7 @@ import { timeProfileAsync } from './timeProfier.js';
2
2
  import { parseDescribe } from './parseDescribe.js';
3
3
  import { runDescribeRun } from './runDescribeRun.js';
4
4
  import { captureLogs } from './consoleCapture.js';
5
+ import { makeStopSignal, stopIfFailFast } from './stopSignal.js';
5
6
  function createDescribeErrorResult(describe, error) {
6
7
  return {
7
8
  counter: describe.counter,
@@ -16,7 +17,7 @@ function createDescribeErrorResult(describe, error) {
16
17
  error
17
18
  };
18
19
  }
19
- export function runDescribe(config, describe, itFilter) {
20
+ export function runDescribe(config, describe, itFilter, stop = makeStopSignal()) {
20
21
  return timeProfileAsync(`run describe ${describe.thing}`, async () => {
21
22
  const logs = [];
22
23
  const startTime = new Date().getTime();
@@ -25,7 +26,7 @@ export function runDescribe(config, describe, itFilter) {
25
26
  const parsedDescribe = await parseDescribe(config, describe, itFilter);
26
27
  return parsedDescribe.error !== undefined
27
28
  ? createDescribeErrorResult(describe, parsedDescribe.error)
28
- : await runDescribeRun(config, describe, parsedDescribe);
29
+ : await runDescribeRun(config, describe, parsedDescribe, stop);
29
30
  }
30
31
  catch (e) {
31
32
  return createDescribeErrorResult(describe, e);
@@ -33,6 +34,8 @@ export function runDescribe(config, describe, itFilter) {
33
34
  });
34
35
  describeResult.time = new Date().getTime() - startTime;
35
36
  describeResult.logs = logs;
37
+ // a describe that threw stops the run just as a failing test does
38
+ stopIfFailFast(config, stop, describeResult.error !== undefined);
36
39
  return describeResult;
37
40
  });
38
41
  }
@@ -1 +1 @@
1
- {"version":3,"file":"runDescribe.js","sourceRoot":"","sources":["../../../src/cli/lib/runDescribe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAIjD,SAAS,yBAAyB,CAAC,QAAkB,EAAE,KAAc;IACjE,OAAO;QACH,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,OAAO,EAAE,KAAK;QACd,IAAI,EAAE,CAAC,EAAE,6BAA6B;QACtC,SAAS,EAAE,EAAE;QACb,gBAAgB,EAAE;YACd,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,CAAC;SACZ;QACD,KAAK;KACR,CAAA;AACL,CAAC;AAED,MAAM,UAAU,WAAW,CACvB,MAAmB,EACnB,QAAkB,EAClB,QAAiB;IAEjB,OAAO,gBAAgB,CAAC,gBAAgB,QAAQ,CAAC,KAAK,EAAE,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,IAAI,GAAgB,EAAE,CAAA;QAE5B,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAA;QAEtC,MAAM,cAAc,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE;YACtD,IAAI,CAAC;gBACD,MAAM,cAAc,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAA;gBACtE,OAAO,cAAc,CAAC,KAAK,KAAK,SAAS;oBACrC,CAAC,CAAC,yBAAyB,CAAC,QAAQ,EAAE,cAAc,CAAC,KAAK,CAAC;oBAC3D,CAAC,CAAC,MAAM,cAAc,CAAC,MAAM,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAA;YAChE,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACT,OAAO,yBAAyB,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;YACjD,CAAC;QACL,CAAC,CAAC,CAAA;QAEF,cAAc,CAAC,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,SAAS,CAAA;QACtD,cAAc,CAAC,IAAI,GAAG,IAAI,CAAA;QAE1B,OAAO,cAAc,CAAA;IACzB,CAAC,CAAC,CAAA;AACN,CAAC","sourcesContent":["import { timeProfileAsync } from './timeProfier.js'\nimport { parseDescribe } from './parseDescribe.js'\nimport { runDescribeRun } from './runDescribeRun.js'\nimport { captureLogs } from './consoleCapture.js'\n\nimport type { FinalConfig, Describe, DescribeResult } from '../../types.js'\n\nfunction createDescribeErrorResult(describe: Describe, error: unknown): DescribeResult {\n return {\n counter: describe.counter,\n thing: describe.thing,\n success: false,\n time: 0, // overwritten by runDescribe\n itResults: [],\n itResultsSummary: {\n total: 0,\n passes: 0\n },\n error\n }\n}\n\nexport function runDescribe(\n config: FinalConfig,\n describe: Describe,\n itFilter?: string\n): Promise<DescribeResult> {\n return timeProfileAsync(`run describe ${describe.thing}`, async () => {\n const logs: unknown[][] = []\n\n const startTime = new Date().getTime()\n\n const describeResult = await captureLogs(logs, async () => {\n try {\n const parsedDescribe = await parseDescribe(config, describe, itFilter)\n return parsedDescribe.error !== undefined\n ? createDescribeErrorResult(describe, parsedDescribe.error)\n : await runDescribeRun(config, describe, parsedDescribe)\n } catch (e) {\n return createDescribeErrorResult(describe, e)\n }\n })\n\n describeResult.time = new Date().getTime() - startTime\n describeResult.logs = logs\n\n return describeResult\n })\n}\n"]}
1
+ {"version":3,"file":"runDescribe.js","sourceRoot":"","sources":["../../../src/cli/lib/runDescribe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAEjD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAmB,MAAM,iBAAiB,CAAA;AAIjF,SAAS,yBAAyB,CAAC,QAAkB,EAAE,KAAc;IACjE,OAAO;QACH,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,OAAO,EAAE,KAAK;QACd,IAAI,EAAE,CAAC,EAAE,6BAA6B;QACtC,SAAS,EAAE,EAAE;QACb,gBAAgB,EAAE;YACd,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,CAAC;SACZ;QACD,KAAK;KACR,CAAA;AACL,CAAC;AAED,MAAM,UAAU,WAAW,CACvB,MAAmB,EACnB,QAAkB,EAClB,QAAiB,EACjB,OAAmB,cAAc,EAAE;IAEnC,OAAO,gBAAgB,CAAC,gBAAgB,QAAQ,CAAC,KAAK,EAAE,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,IAAI,GAAgB,EAAE,CAAA;QAE5B,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAA;QAEtC,MAAM,cAAc,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE;YACtD,IAAI,CAAC;gBACD,MAAM,cAAc,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAA;gBACtE,OAAO,cAAc,CAAC,KAAK,KAAK,SAAS;oBACrC,CAAC,CAAC,yBAAyB,CAAC,QAAQ,EAAE,cAAc,CAAC,KAAK,CAAC;oBAC3D,CAAC,CAAC,MAAM,cAAc,CAAC,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,IAAI,CAAC,CAAA;YACtE,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACT,OAAO,yBAAyB,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;YACjD,CAAC;QACL,CAAC,CAAC,CAAA;QAEF,cAAc,CAAC,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,SAAS,CAAA;QACtD,cAAc,CAAC,IAAI,GAAG,IAAI,CAAA;QAE1B,kEAAkE;QAClE,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,cAAc,CAAC,KAAK,KAAK,SAAS,CAAC,CAAA;QAEhE,OAAO,cAAc,CAAA;IACzB,CAAC,CAAC,CAAA;AACN,CAAC","sourcesContent":["import { timeProfileAsync } from './timeProfier.js'\nimport { parseDescribe } from './parseDescribe.js'\nimport { runDescribeRun } from './runDescribeRun.js'\nimport { captureLogs } from './consoleCapture.js'\n\nimport { makeStopSignal, stopIfFailFast, type StopSignal } from './stopSignal.js'\n\nimport type { FinalConfig, Describe, DescribeResult } from '../../types.js'\n\nfunction createDescribeErrorResult(describe: Describe, error: unknown): DescribeResult {\n return {\n counter: describe.counter,\n thing: describe.thing,\n success: false,\n time: 0, // overwritten by runDescribe\n itResults: [],\n itResultsSummary: {\n total: 0,\n passes: 0\n },\n error\n }\n}\n\nexport function runDescribe(\n config: FinalConfig,\n describe: Describe,\n itFilter?: string,\n stop: StopSignal = makeStopSignal()\n): Promise<DescribeResult> {\n return timeProfileAsync(`run describe ${describe.thing}`, async () => {\n const logs: unknown[][] = []\n\n const startTime = new Date().getTime()\n\n const describeResult = await captureLogs(logs, async () => {\n try {\n const parsedDescribe = await parseDescribe(config, describe, itFilter)\n return parsedDescribe.error !== undefined\n ? createDescribeErrorResult(describe, parsedDescribe.error)\n : await runDescribeRun(config, describe, parsedDescribe, stop)\n } catch (e) {\n return createDescribeErrorResult(describe, e)\n }\n })\n\n describeResult.time = new Date().getTime() - startTime\n describeResult.logs = logs\n\n // a describe that threw stops the run just as a failing test does\n stopIfFailFast(config, stop, describeResult.error !== undefined)\n\n return describeResult\n })\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { type StopSignal } from './stopSignal.js';
1
2
  import type { FinalConfig, Describe, DescribeResult, ParsedDescribe } from '../../types.js';
2
- export declare function runDescribeRun(config: FinalConfig, describe: Describe, parsedIts: ParsedDescribe): Promise<DescribeResult>;
3
+ export declare function runDescribeRun(config: FinalConfig, describe: Describe, parsedIts: ParsedDescribe, stop?: StopSignal): Promise<DescribeResult>;
3
4
  //# sourceMappingURL=runDescribeRun.d.ts.map
@@ -2,7 +2,8 @@ import { timeProfileAsync } from './timeProfier.js';
2
2
  import { runTasks } from './runTasks.js';
3
3
  import { debug } from '../../output.js';
4
4
  import { runIt } from './runIt.js';
5
- export function runDescribeRun(config, describe, parsedIts) {
5
+ import { makeStopSignal, stopIfFailFast } from './stopSignal.js';
6
+ export function runDescribeRun(config, describe, parsedIts, stop = makeStopSignal()) {
6
7
  return timeProfileAsync(`run describe, run its ${describe.thing}`, async () => {
7
8
  const { its, beforeDescribeExports, afterDescribeFunc, beforeEachTestFunc, afterEachTestFunc } = parsedIts;
8
9
  const parallelOverride = describe.meta === undefined
@@ -11,12 +12,17 @@ export function runDescribeRun(config, describe, parsedIts) {
11
12
  const isParallel = parallelOverride ?? config.execution.tests === 'parallel';
12
13
  const itPromises = [];
13
14
  for (const it of its) {
15
+ // checked before starting, so the failing test is the last one that runs
16
+ if (stop.stopped)
17
+ break;
14
18
  const itPromise = runIt(config, it, beforeEachTestFunc, afterEachTestFunc);
15
19
  itPromises.push(itPromise);
16
20
  if (!isParallel)
17
- await itPromise;
21
+ stopIfFailFast(config, stop, (await itPromise).success === false);
18
22
  }
19
23
  const itResults = await Promise.all(itPromises);
24
+ // in parallel mode the tests are already in flight, so this only stops later work
25
+ stopIfFailFast(config, stop, itResults.some(itResult => itResult.success === false));
20
26
  const itResultsSummary = {
21
27
  total: 0,
22
28
  passes: 0
@@ -1 +1 @@
1
- {"version":3,"file":"runDescribeRun.js","sourceRoot":"","sources":["../../../src/cli/lib/runDescribeRun.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AACvC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAMlC,MAAM,UAAU,cAAc,CAAC,MAAmB,EAAE,QAAkB,EAAE,SAAyB;IAE7F,OAAO,gBAAgB,CAAC,yBAAyB,QAAQ,CAAC,KAAK,EAAE,EAAE,KAAK,IAAI,EAAE;QAC1E,MAAM,EAAE,GAAG,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,GAAG,SAAS,CAAA;QAE1G,MAAM,gBAAgB,GAAG,QAAQ,CAAC,IAAI,KAAK,SAAS;YAChD,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,eAAe,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAA;QAErG,MAAM,UAAU,GAAG,gBAAgB,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,KAAK,UAAU,CAAA;QAE5E,MAAM,UAAU,GAA6B,EAAE,CAAA;QAC/C,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;YACnB,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,EAAE,EAAE,kBAAkB,EAAE,iBAAiB,CAAC,CAAA;YAC1E,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;YAC1B,IAAI,CAAC,UAAU;gBAAE,MAAM,SAAS,CAAA;QACpC,CAAC;QACD,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;QAE/C,MAAM,gBAAgB,GAAqB;YACvC,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,CAAC;SACZ,CAAA;QAED,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YAC/B,gBAAgB,CAAC,KAAK,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,KAAK,IAAI,CAAC,CAAA;YACtD,gBAAgB,CAAC,MAAM,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,IAAI,KAAK,CAAC,CAAA;QAC3D,CAAC;QAED,KAAK,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAA;QAE3C,MAAM,cAAc,GAAmB;YACnC,OAAO,EAAE,QAAQ,CAAC,OAAO;YACzB,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,OAAO,EAAE,CAAC,gBAAgB,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,MAAM,KAAK,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;YACjG,IAAI,EAAE,CAAC,EAAE,6BAA6B;YACtC,SAAS;YACT,gBAAgB;SACnB,CAAA;QAED,YAAY;QACZ,IAAI,OAAO,iBAAiB,KAAK,UAAU;YAAE,MAAM,iBAAiB,EAAE,CAAA;QACtE,MAAM,uBAAuB,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAA;QAE5D,OAAO,cAAc,CAAA;IACzB,CAAC,CAAC,CAAA;AACN,CAAC;AAED,KAAK,UAAU,uBAAuB,CAAC,MAAmB,EAAE,OAAoB;IAC5E,IAAI,MAAM,CAAC,iBAAiB,KAAK,SAAS,EAAE,CAAC;QACzC,MAAM,QAAQ,CAAC,MAAM,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAA;IACrD,CAAC;AACL,CAAC","sourcesContent":["import { timeProfileAsync } from './timeProfier.js'\nimport { runTasks } from './runTasks.js'\nimport { debug } from '../../output.js'\nimport { runIt } from './runIt.js'\n\nimport type {\n FinalConfig, Describe, DescribeResult, ItResult, ItResultsSummary, ParsedDescribe, TaskExports\n} from '../../types.js'\n\nexport function runDescribeRun(config: FinalConfig, describe: Describe, parsedIts: ParsedDescribe)\n: Promise<DescribeResult> {\n return timeProfileAsync(`run describe, run its ${describe.thing}`, async () => {\n const { its, beforeDescribeExports, afterDescribeFunc, beforeEachTestFunc, afterEachTestFunc } = parsedIts\n\n const parallelOverride = describe.meta === undefined\n ? undefined\n : 'parallelTests' in describe.meta ? describe.meta.parallelTests : !describe.meta.sequentialTests\n\n const isParallel = parallelOverride ?? config.execution.tests === 'parallel'\n\n const itPromises: Array<Promise<ItResult>> = []\n for (const it of its) {\n const itPromise = runIt(config, it, beforeEachTestFunc, afterEachTestFunc)\n itPromises.push(itPromise)\n if (!isParallel) await itPromise\n }\n const itResults = await Promise.all(itPromises)\n\n const itResultsSummary: ItResultsSummary = {\n total: 0,\n passes: 0\n }\n\n for (const itResult of itResults) {\n itResultsSummary.total += +(itResult.success !== null)\n itResultsSummary.passes += +(itResult.success ?? false)\n }\n\n debug('itResultsSummary', itResultsSummary)\n\n const describeResult: DescribeResult = {\n counter: describe.counter,\n thing: describe.thing,\n success: (itResultsSummary.total > 0) ? itResultsSummary.passes === itResultsSummary.total : null,\n time: 0, // overwritten by runDescribe\n itResults,\n itResultsSummary\n }\n\n // run after\n if (typeof afterDescribeFunc === 'function') await afterDescribeFunc()\n await configAfterEachDescribe(config, beforeDescribeExports)\n\n return describeResult\n })\n}\n\nasync function configAfterEachDescribe(config: FinalConfig, exports: TaskExports): Promise<void> {\n if (config.afterEachDescribe !== undefined) {\n await runTasks(config.afterEachDescribe, exports)\n }\n}\n"]}
1
+ {"version":3,"file":"runDescribeRun.js","sourceRoot":"","sources":["../../../src/cli/lib/runDescribeRun.ts"],"names":[],"mappings":"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","sourcesContent":["import { timeProfileAsync } from './timeProfier.js'\nimport { runTasks } from './runTasks.js'\nimport { debug } from '../../output.js'\nimport { runIt } from './runIt.js'\n\nimport { makeStopSignal, stopIfFailFast, type StopSignal } from './stopSignal.js'\n\nimport type {\n FinalConfig, Describe, DescribeResult, ItResult, ItResultsSummary, ParsedDescribe, TaskExports\n} from '../../types.js'\n\nexport function runDescribeRun(\n config: FinalConfig,\n describe: Describe,\n parsedIts: ParsedDescribe,\n stop: StopSignal = makeStopSignal()\n): Promise<DescribeResult> {\n return timeProfileAsync(`run describe, run its ${describe.thing}`, async () => {\n const { its, beforeDescribeExports, afterDescribeFunc, beforeEachTestFunc, afterEachTestFunc } = parsedIts\n\n const parallelOverride = describe.meta === undefined\n ? undefined\n : 'parallelTests' in describe.meta ? describe.meta.parallelTests : !describe.meta.sequentialTests\n\n const isParallel = parallelOverride ?? config.execution.tests === 'parallel'\n\n const itPromises: Array<Promise<ItResult>> = []\n for (const it of its) {\n // checked before starting, so the failing test is the last one that runs\n if (stop.stopped) break\n const itPromise = runIt(config, it, beforeEachTestFunc, afterEachTestFunc)\n itPromises.push(itPromise)\n if (!isParallel) stopIfFailFast(config, stop, (await itPromise).success === false)\n }\n const itResults = await Promise.all(itPromises)\n\n // in parallel mode the tests are already in flight, so this only stops later work\n stopIfFailFast(config, stop, itResults.some(itResult => itResult.success === false))\n\n const itResultsSummary: ItResultsSummary = {\n total: 0,\n passes: 0\n }\n\n for (const itResult of itResults) {\n itResultsSummary.total += +(itResult.success !== null)\n itResultsSummary.passes += +(itResult.success ?? false)\n }\n\n debug('itResultsSummary', itResultsSummary)\n\n const describeResult: DescribeResult = {\n counter: describe.counter,\n thing: describe.thing,\n success: (itResultsSummary.total > 0) ? itResultsSummary.passes === itResultsSummary.total : null,\n time: 0, // overwritten by runDescribe\n itResults,\n itResultsSummary\n }\n\n // run after\n if (typeof afterDescribeFunc === 'function') await afterDescribeFunc()\n await configAfterEachDescribe(config, beforeDescribeExports)\n\n return describeResult\n })\n}\n\nasync function configAfterEachDescribe(config: FinalConfig, exports: TaskExports): Promise<void> {\n if (config.afterEachDescribe !== undefined) {\n await runTasks(config.afterEachDescribe, exports)\n }\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { type StopSignal } from './stopSignal.js';
1
2
  import type { FinalConfig, TestExecutionFilters, TestFile, TestResult } from '../../types.js';
2
- export declare function runTest(config: FinalConfig, test: TestFile, filters?: TestExecutionFilters): Promise<TestResult>;
3
+ export declare function runTest(config: FinalConfig, test: TestFile, filters?: TestExecutionFilters, stop?: StopSignal): Promise<TestResult>;
3
4
  //# sourceMappingURL=runTest.d.ts.map
@@ -4,8 +4,9 @@ import { showTimeProfiling } from '../../config.js';
4
4
  import { runTasks } from './runTasks.js';
5
5
  import { addExports } from './addExports.js';
6
6
  import { runDescribe } from './runDescribe.js';
7
+ import { makeStopSignal } from './stopSignal.js';
7
8
  const { timeProfileAsync } = createTimeProfiler(showTimeProfiling);
8
- export function runTest(config, test, filters = {}) {
9
+ export function runTest(config, test, filters = {}, stop = makeStopSignal()) {
9
10
  return timeProfileAsync(`run test ${test.file}`, async () => {
10
11
  debug('test', test);
11
12
  // run before test file
@@ -17,10 +18,13 @@ export function runTest(config, test, filters = {}) {
17
18
  const isParallel = parallelOverride ?? config.execution.describes === 'parallel';
18
19
  const runDescribePromises = [];
19
20
  for (const describe of test.describes ?? []) {
21
+ // a failure in an earlier describe leaves the rest of the file unrun
22
+ if (stop.stopped)
23
+ break;
20
24
  if (filters.describe !== undefined
21
25
  && !describe.thing.toLowerCase().includes(filters.describe.toLowerCase()))
22
26
  continue;
23
- const describePromise = runDescribe(config, describe, filters.it);
27
+ const describePromise = runDescribe(config, describe, filters.it, stop);
24
28
  runDescribePromises.push(describePromise);
25
29
  if (!isParallel)
26
30
  await describePromise;
@@ -1 +1 @@
1
- {"version":3,"file":"runTest.js","sourceRoot":"","sources":["../../../src/cli/lib/runTest.ts"],"names":[],"mappings":"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","sourcesContent":["import { createTimeProfiler } from '../../packages/timeProfiler.js'\nimport { debug } from '../../output.js'\nimport { showTimeProfiling } from '../../config.js'\n\nimport { runTasks } from './runTasks.js'\nimport { addExports } from './addExports.js'\nimport { runDescribe } from './runDescribe.js'\n\nimport type {\n FinalConfig, DescribeResult, DescribeResultsSummary, TaskExports, TestExecutionFilters, TestFile, TestResult\n} from '../../types.js'\n\nconst { timeProfileAsync } = createTimeProfiler(showTimeProfiling)\n\nexport function runTest(\n config: FinalConfig,\n test: TestFile,\n filters: TestExecutionFilters = {}\n): Promise<TestResult> {\n return timeProfileAsync(`run test ${test.file}`, async () => {\n debug('test', test)\n\n // run before test file\n const fileExports: TaskExports = {}\n await configBeforeEachFile(config, fileExports)\n\n const parallelOverride = test.meta === undefined\n ? undefined\n : 'parallelDescribes' in test.meta ? test.meta.parallelDescribes : !test.meta.sequentialDescribes\n\n const isParallel = parallelOverride ?? config.execution.describes === 'parallel'\n\n const runDescribePromises: Array<Promise<DescribeResult>> = []\n\n for (const describe of test.describes ?? []) {\n if (\n filters.describe !== undefined\n && !describe.thing.toLowerCase().includes(filters.describe.toLowerCase())\n ) continue\n\n const describePromise = runDescribe(config, describe, filters.it)\n runDescribePromises.push(describePromise)\n if (!isParallel) await describePromise\n }\n\n let describeResults = await Promise.all(runDescribePromises)\n if (filters.it !== undefined) {\n describeResults = describeResults.filter(result => (\n result.itResults.length > 0 || result.error !== undefined\n ))\n }\n\n const describeResultsSummary: DescribeResultsSummary = {\n total: 0,\n passes: 0,\n invalid: 0,\n itsTotal: 0,\n itsPasses: 0\n }\n\n for (const describeResult of describeResults) {\n describeResultsSummary.total += +(describeResult.success !== null)\n describeResultsSummary.passes += +(describeResult.success ?? false)\n describeResultsSummary.invalid += +(describeResult.success === null)\n describeResultsSummary.itsTotal += describeResult.itResultsSummary.total\n describeResultsSummary.itsPasses += describeResult.itResultsSummary.passes\n }\n\n const testResults: TestResult = {\n file: test.file,\n success: (describeResultsSummary.total > 0)\n ? describeResultsSummary.total === describeResultsSummary.passes\n : null,\n describeResults,\n describeResultsSummary,\n logs: test.logs ?? []\n }\n\n // run after test\n await configAfterEachFile(config, fileExports)\n\n return testResults\n })\n}\n\nasync function configBeforeEachFile(config: FinalConfig, exports: TaskExports): Promise<void> {\n if (config.beforeEachFile !== undefined) {\n const theExports = await runTasks(config.beforeEachFile, undefined)\n if (theExports) addExports(exports, theExports)\n }\n}\n\nasync function configAfterEachFile(config: FinalConfig, exports: TaskExports): Promise<void> {\n if (config.afterEachFile !== undefined) {\n await runTasks(config.afterEachFile, exports)\n }\n}\n"]}
1
+ {"version":3,"file":"runTest.js","sourceRoot":"","sources":["../../../src/cli/lib/runTest.ts"],"names":[],"mappings":"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","sourcesContent":["import { createTimeProfiler } from '../../packages/timeProfiler.js'\nimport { debug } from '../../output.js'\nimport { showTimeProfiling } from '../../config.js'\n\nimport { runTasks } from './runTasks.js'\nimport { addExports } from './addExports.js'\nimport { runDescribe } from './runDescribe.js'\n\nimport { makeStopSignal, stopIfFailFast, type StopSignal } from './stopSignal.js'\n\nimport type {\n FinalConfig, DescribeResult, DescribeResultsSummary, TaskExports, TestExecutionFilters, TestFile, TestResult\n} from '../../types.js'\n\nconst { timeProfileAsync } = createTimeProfiler(showTimeProfiling)\n\nexport function runTest(\n config: FinalConfig,\n test: TestFile,\n filters: TestExecutionFilters = {},\n stop: StopSignal = makeStopSignal()\n): Promise<TestResult> {\n return timeProfileAsync(`run test ${test.file}`, async () => {\n debug('test', test)\n\n // run before test file\n const fileExports: TaskExports = {}\n await configBeforeEachFile(config, fileExports)\n\n const parallelOverride = test.meta === undefined\n ? undefined\n : 'parallelDescribes' in test.meta ? test.meta.parallelDescribes : !test.meta.sequentialDescribes\n\n const isParallel = parallelOverride ?? config.execution.describes === 'parallel'\n\n const runDescribePromises: Array<Promise<DescribeResult>> = []\n\n for (const describe of test.describes ?? []) {\n // a failure in an earlier describe leaves the rest of the file unrun\n if (stop.stopped) break\n\n if (\n filters.describe !== undefined\n && !describe.thing.toLowerCase().includes(filters.describe.toLowerCase())\n ) continue\n\n const describePromise = runDescribe(config, describe, filters.it, stop)\n runDescribePromises.push(describePromise)\n if (!isParallel) await describePromise\n }\n\n let describeResults = await Promise.all(runDescribePromises)\n if (filters.it !== undefined) {\n describeResults = describeResults.filter(result => (\n result.itResults.length > 0 || result.error !== undefined\n ))\n }\n\n const describeResultsSummary: DescribeResultsSummary = {\n total: 0,\n passes: 0,\n invalid: 0,\n itsTotal: 0,\n itsPasses: 0\n }\n\n for (const describeResult of describeResults) {\n describeResultsSummary.total += +(describeResult.success !== null)\n describeResultsSummary.passes += +(describeResult.success ?? false)\n describeResultsSummary.invalid += +(describeResult.success === null)\n describeResultsSummary.itsTotal += describeResult.itResultsSummary.total\n describeResultsSummary.itsPasses += describeResult.itResultsSummary.passes\n }\n\n const testResults: TestResult = {\n file: test.file,\n success: (describeResultsSummary.total > 0)\n ? describeResultsSummary.total === describeResultsSummary.passes\n : null,\n describeResults,\n describeResultsSummary,\n logs: test.logs ?? []\n }\n\n // run after test\n await configAfterEachFile(config, fileExports)\n\n return testResults\n })\n}\n\nasync function configBeforeEachFile(config: FinalConfig, exports: TaskExports): Promise<void> {\n if (config.beforeEachFile !== undefined) {\n const theExports = await runTasks(config.beforeEachFile, undefined)\n if (theExports) addExports(exports, theExports)\n }\n}\n\nasync function configAfterEachFile(config: FinalConfig, exports: TaskExports): Promise<void> {\n if (config.afterEachFile !== undefined) {\n await runTasks(config.afterEachFile, exports)\n }\n}\n"]}
@@ -12,6 +12,7 @@ import { showTestResult } from './showTestResult.js';
12
12
  import { failureLines } from './failureLines.js';
13
13
  import { failureEntries } from './failureEntries.js';
14
14
  import { agentDone, agentFailure, agentRunStart } from './agentReport.js';
15
+ import { makeStopSignal, stopIfFailFast } from './stopSignal.js';
15
16
  import { statusCodes, writeStatusFile } from './statusFile.js';
16
17
  import { makeRunManagerState } from './makeWatchRunState.js';
17
18
  const { timeProfileAsync } = createTimeProfiler(showTimeProfiling);
@@ -32,6 +33,7 @@ export async function runTests(config, testFiles, reRunManager, refresh = 'refre
32
33
  const state = reRunManager?.state || makeRunManagerState();
33
34
  const runStartTime = new Date().getTime();
34
35
  const agentRun = agentRunStart(config, testFiles.size);
36
+ const stop = makeStopSignal();
35
37
  //console.log('new runTests:', watchRunState?.activeRuns)
36
38
  //console.log(inspect(testFiles))
37
39
  try {
@@ -43,14 +45,18 @@ export async function runTests(config, testFiles, reRunManager, refresh = 'refre
43
45
  for (const testFile of testFiles) {
44
46
  //console.log('testFiles', testFiles)
45
47
  //console.log('testFile', testFile)
48
+ // an earlier file failed under failFast - leave the rest unloaded
49
+ if (stop.stopped)
50
+ break;
46
51
  const test = await loadTestFile(config, testFile, refresh);
47
52
  if (test.error !== undefined && test.error !== false) {
48
53
  erroringTests[testFile] = test;
49
54
  state.failedTestFiles.add(testFile);
50
55
  showTestLoadingError(config, test, customOut);
56
+ stopIfFailFast(config, stop, true);
51
57
  }
52
58
  else {
53
- const testRunPromise = runTest(config, test, filters);
59
+ const testRunPromise = runTest(config, test, filters, stop);
54
60
  testRunPromises[testFile] = testRunPromise;
55
61
  testRunOutPromises[testFile] = testRunPromise.then(async (testResult) => {
56
62
  if (testResult.success === true || testResult.success === null) {
@@ -185,10 +191,18 @@ export async function runTests(config, testFiles, reRunManager, refresh = 'refre
185
191
  else {
186
192
  out(chalk.mediumred(`${testFilesText}`) + testFilesDetailsSuffix);
187
193
  }
194
+ // the tallies only cover what ran, so say the run was cut short - otherwise
195
+ // "Tests: 0/1" reads as a one test suite
196
+ const stoppedPlain = (stop.stopped)
197
+ ? 'stopped at the first failure (failFast)'
198
+ : '';
199
+ if (stoppedPlain !== '')
200
+ out(chalk.orange(stoppedPlain));
188
201
  const summaryLines = [
189
202
  testsText,
190
203
  joinPlain(describesText, invalidDescribesPlain, describesThrownPlain),
191
- joinPlain(testFilesText, invalidTestFilesPlain, failedToLoadPlain)
204
+ joinPlain(testFilesText, invalidTestFilesPlain, failedToLoadPlain),
205
+ ...(stoppedPlain === '') ? [] : [stoppedPlain]
192
206
  ];
193
207
  const durationMs = new Date().getTime() - runStartTime;
194
208
  if (allPassed) {
@@ -201,11 +215,12 @@ export async function runTests(config, testFiles, reRunManager, refresh = 'refre
201
215
  // partway - a different problem from tests that ran and failed
202
216
  const aborted = abortedFiles.length > 0 || describesThrownCount > 0;
203
217
  const failedTestsCount = testsResultsSummary.itsTotal - testsResultsSummary.itsPasses;
204
- const description = [
218
+ const description = ([
205
219
  plural(abortedFiles.length, 'test file', 'failed to load or errored'),
206
220
  plural(describesThrownCount, 'describe', 'errored'),
207
221
  plural(failedTestsCount, 'test', 'failed')
208
- ].filter(part => part !== '').join(', ') || 'test run failed';
222
+ ].filter(part => part !== '').join(', ') || 'test run failed')
223
+ + ((stop.stopped) ? ', stopped at the first failure' : '');
209
224
  const code = (aborted) ? statusCodes.aborted : statusCodes.failed;
210
225
  const failures = failureEntries(Object.values(runTestResults), erroringTests);
211
226
  writeStatusFile(config, code, description, [...summaryLines, ...failureLines(Object.values(runTestResults), erroringTests)], durationMs);
@@ -1 +1 @@
1
- {"version":3,"file":"runTests.js","sourceRoot":"","sources":["../../../src/cli/lib/runTests.ts"],"names":[],"mappings":"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","sourcesContent":["import { createTimeProfiler } from '../../packages/timeProfiler.js'\nimport { showTimeProfiling } from '../../config.js'\nimport chalk from '../../packages/chalk.js'\nimport { out as mainOut } from '../../output.js'\nimport figures from '../../packages/figures.js'\nimport { count } from 'sxy-lib/objects.js'\nimport { remove as arrayRemove } from 'sxy-lib/arrays.js'\nimport { allObj as promiseAllObj } from 'sxy-lib/promises.js'\n\nimport { loadTestFile } from './loadTestFile.js'\nimport { runTest } from './runTest.js'\nimport { showTestLoadingError } from './showTestLoadingError.js'\nimport { showTestResult } from './showTestResult.js'\nimport { failureLines } from './failureLines.js'\nimport { failureEntries } from './failureEntries.js'\nimport { agentDone, agentFailure, agentRunStart } from './agentReport.js'\nimport { statusCodes, writeStatusFile } from './statusFile.js'\n\nimport type {\n FinalConfig, OutFn, TestExecutionFilters, TestFile, TestResult, TestsResultsSummary\n} from '../../types.js'\nimport { makeRunManagerState, ReRunManageState } from './makeWatchRunState.js'\nimport { ReRunManager } from './reRunManager.js'\n\nconst { timeProfileAsync } = createTimeProfiler(showTimeProfiling)\n\nexport type RunTestsPromise = Promise<boolean | null>\n\n// the summary lines, minus the colouring, for the status file\nfunction joinPlain(...parts: string[]): string {\n return parts.filter(part => part !== '').join(' ')\n}\n\nfunction plural(count: number, noun: string, verb: string): string {\n if (count < 1) return ''\n return `${count} ${noun}${count === 1 ? '' : 's'} ${verb}`\n}\n\n\nexport async function runTests(\n config: FinalConfig,\n testFiles: Set<string>,\n reRunManager: ReRunManager | undefined,\n refresh: 'refresh' | 'cached' = 'refresh',\n customOut?: OutFn,\n filters: TestExecutionFilters = {}\n): RunTestsPromise {\n if (reRunManager !== undefined) {\n reRunManager.state.lastTestFiles = new Set(testFiles)\n reRunManager.state.activeRuns++ // whatever, obsolete. Can use it to check on things\n }\n\n const state = reRunManager?.state || makeRunManagerState()\n const runStartTime = new Date().getTime()\n const agentRun = agentRunStart(config, testFiles.size)\n //console.log('new runTests:', watchRunState?.activeRuns)\n //console.log(inspect(testFiles))\n\n try {\n const testRunPromises: Record<string, Promise<TestResult>> = {}\n const erroringTests: Record<string, TestFile> = {}\n const testRunOutPromises: Record<string, Promise<void>> = {}\n\n await timeProfileAsync('run tests', async () => {\n if (Array.isArray(testFiles) ? testFiles.length > 0 : testFiles.size > 0) {\n for (const testFile of testFiles) {\n //console.log('testFiles', testFiles)\n //console.log('testFile', testFile)\n const test = await loadTestFile(config, testFile, refresh)\n\n if (test.error !== undefined && test.error !== false) {\n erroringTests[testFile] = test\n state.failedTestFiles.add(testFile)\n showTestLoadingError(config, test, customOut)\n } else {\n const testRunPromise = runTest(config, test, filters)\n testRunPromises[testFile] = testRunPromise\n\n testRunOutPromises[testFile] = testRunPromise.then(async testResult => {\n if (testResult.success === true || testResult.success === null) {\n state.failedTestFiles.delete(testResult.file)\n } else {\n state.failedTestFiles.add(testFile)\n }\n const executionFilterActive = filters.describe !== undefined || filters.it !== undefined\n if (!executionFilterActive || testResult.describeResultsSummary.itsTotal > 0) {\n await showTestResult(config, testResult, customOut)\n }\n })\n\n // wait for the test to complete before proceeding if we are in 'sequential' mode\n if (config.execution.files === 'sequential') await testRunOutPromises[testFile]\n }\n }\n }\n })\n\n let runTestResults: Record<string, TestResult> = {}\n\n await timeProfileAsync('wait for tests to finish', async () => {\n runTestResults = await promiseAllObj(testRunPromises)\n\n // wait for the output to complete\n await promiseAllObj(testRunOutPromises)\n })\n\n return await timeProfileAsync('show initial test run results', () => {\n \n const out = customOut ?? mainOut\n\n const testsResultsSummary: TestsResultsSummary = {\n total: 0,\n passes: 0,\n invalid: 0,\n describesTotal: 0,\n describesPasses: 0,\n describesInvalid: 0,\n itsTotal: 0,\n itsPasses: 0\n // itsInvalid: 0 // we don't check whether tests run any asserts (we don't control the assertion lib)\n }\n let describesThrownCount = 0\n\n for (const testFile in runTestResults) {\n const runTestResult = runTestResults[testFile]\n if (!runTestResult) continue\n\n testsResultsSummary.total += +(runTestResult.success !== null)\n testsResultsSummary.passes += +(runTestResult.success ?? false)\n testsResultsSummary.invalid += +(runTestResult.success === null)\n testsResultsSummary.describesTotal += runTestResult.describeResultsSummary.total\n testsResultsSummary.describesPasses += runTestResult.describeResultsSummary.passes\n testsResultsSummary.describesInvalid += runTestResult.describeResultsSummary.invalid\n testsResultsSummary.itsTotal += runTestResult.describeResultsSummary.itsTotal\n testsResultsSummary.itsPasses += runTestResult.describeResultsSummary.itsPasses\n describesThrownCount += runTestResult.describeResults\n .filter(describeResult => describeResult.error !== undefined)\n .length\n }\n\n const failedToLoadCount = count(erroringTests)\n testsResultsSummary.total += failedToLoadCount\n\n if (\n (filters.describe !== undefined || filters.it !== undefined)\n && testsResultsSummary.itsTotal === 0\n && failedToLoadCount === 0\n && describesThrownCount === 0\n ) {\n out(chalk.orange('No tests matched the describe/test filters.'))\n const durationMs = new Date().getTime() - runStartTime\n writeStatusFile(\n config,\n statusCodes.couldNotRun,\n 'no tests matched the describe/test filters',\n [],\n durationMs\n )\n agentDone(\n config, agentRun, statusCodes.couldNotRun,\n 'no tests matched the describe/test filters', testsResultsSummary, durationMs,\n state.failedTestFiles.size\n )\n return null\n }\n\n out('\\n')\n\n const allPassed = (\n testsResultsSummary.passes === testsResultsSummary.total\n && testsResultsSummary.describesPasses === testsResultsSummary.describesTotal\n && testsResultsSummary.itsPasses === testsResultsSummary.itsTotal\n )\n\n if (allPassed) {\n out(chalk.mediumgreen(`${figures.tick}`))\n } else {\n out(chalk.mediumred(`${figures.cross}`))\n }\n\n // number of tests successful\n const testsText = `Tests: ${testsResultsSummary.itsPasses}/${testsResultsSummary.itsTotal}`\n if (testsResultsSummary.itsPasses === testsResultsSummary.itsTotal) {\n out(chalk.mediumgreen(`${testsText}`))\n } else {\n out(chalk.mediumred(`${testsText}`))\n }\n\n // number of items successful\n const describesText = `Items: ${testsResultsSummary.describesPasses}/${testsResultsSummary.describesTotal}`\n const invalidDescribesPlain = (testsResultsSummary.describesInvalid >= 1)\n ? (testsResultsSummary.describesInvalid === 1)\n ? '(+1 describe without tests)'\n : `(+${testsResultsSummary.describesInvalid} describes without tests)`\n : ''\n const describesThrownPlain = (describesThrownCount >= 1)\n ? (describesThrownCount === 1)\n ? '(1 describe errored)'\n : `(${describesThrownCount} describes errored)`\n : ''\n const describesDetailsText = [\n chalk.grey(invalidDescribesPlain), chalk.mediumred(describesThrownPlain)\n ]\n .filter(text => text !== '')\n .join(' ')\n const describesDetailsSuffix = describesDetailsText === '' ? '' : ` ${describesDetailsText}`\n if (testsResultsSummary.describesPasses === testsResultsSummary.describesTotal) {\n out(chalk.mediumgreen(`${describesText}`) + describesDetailsSuffix)\n } else {\n out(chalk.mediumred(`${describesText}`) + describesDetailsSuffix)\n }\n\n // number of test files successful\n const testFilesText = `Test Files: ${testsResultsSummary.passes}/${testsResultsSummary.total}`\n const invalidTestFilesPlain = (testsResultsSummary.invalid >= 1)\n ? (testsResultsSummary.invalid === 1)\n ? '(+1 file without tests)'\n : `(+${testsResultsSummary.invalid} files without tests)`\n : ''\n const failedToLoadPlain = (failedToLoadCount >= 1)\n ? (failedToLoadCount === 1)\n ? '(1 file failed to load, or errored)'\n : `(${failedToLoadCount} files failed to load, or errored)`\n : ''\n const testFilesDetailsText = [\n chalk.grey(invalidTestFilesPlain), chalk.mediumred(failedToLoadPlain)\n ]\n .filter(text => text !== '')\n .join(' ')\n const testFilesDetailsSuffix = testFilesDetailsText === '' ? '' : ` ${testFilesDetailsText}`\n if (testsResultsSummary.passes === testsResultsSummary.total) {\n out(chalk.mediumgreen(`${testFilesText}`) + testFilesDetailsSuffix)\n } else {\n out(chalk.mediumred(`${testFilesText}`) + testFilesDetailsSuffix)\n }\n\n const summaryLines = [\n testsText,\n joinPlain(describesText, invalidDescribesPlain, describesThrownPlain),\n joinPlain(testFilesText, invalidTestFilesPlain, failedToLoadPlain)\n ]\n\n const durationMs = new Date().getTime() - runStartTime\n\n if (allPassed) {\n writeStatusFile(\n config, statusCodes.passed, 'all tests passed', summaryLines, durationMs\n )\n agentDone(\n config, agentRun, statusCodes.passed, 'all tests passed',\n testsResultsSummary, durationMs, state.failedTestFiles.size\n )\n } else {\n const abortedFiles = Object.keys(erroringTests)\n\n // a file that would not load, or a describe that threw, means the run died\n // partway - a different problem from tests that ran and failed\n const aborted = abortedFiles.length > 0 || describesThrownCount > 0\n const failedTestsCount = testsResultsSummary.itsTotal - testsResultsSummary.itsPasses\n\n const description = [\n plural(abortedFiles.length, 'test file', 'failed to load or errored'),\n plural(describesThrownCount, 'describe', 'errored'),\n plural(failedTestsCount, 'test', 'failed')\n ].filter(part => part !== '').join(', ') || 'test run failed'\n\n const code = (aborted) ? statusCodes.aborted : statusCodes.failed\n const failures = failureEntries(Object.values(runTestResults), erroringTests)\n\n writeStatusFile(\n config,\n code,\n description,\n [...summaryLines, ...failureLines(Object.values(runTestResults), erroringTests)],\n durationMs\n )\n\n // failures first, so the done line is a complete end of run marker\n for (const failure of failures) agentFailure(config, agentRun, failure)\n agentDone(\n config, agentRun, code, description, testsResultsSummary, durationMs,\n state.failedTestFiles.size\n )\n }\n\n // full success?\n // true/false gets returned to the caller of runTests()\n return allPassed\n })\n } finally {\n if (reRunManager !== undefined) reRunManager.state.activeRuns--\n }\n}\n\n"]}
1
+ {"version":3,"file":"runTests.js","sourceRoot":"","sources":["../../../src/cli/lib/runTests.ts"],"names":[],"mappings":"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","sourcesContent":["import { createTimeProfiler } from '../../packages/timeProfiler.js'\nimport { showTimeProfiling } from '../../config.js'\nimport chalk from '../../packages/chalk.js'\nimport { out as mainOut } from '../../output.js'\nimport figures from '../../packages/figures.js'\nimport { count } from 'sxy-lib/objects.js'\nimport { remove as arrayRemove } from 'sxy-lib/arrays.js'\nimport { allObj as promiseAllObj } from 'sxy-lib/promises.js'\n\nimport { loadTestFile } from './loadTestFile.js'\nimport { runTest } from './runTest.js'\nimport { showTestLoadingError } from './showTestLoadingError.js'\nimport { showTestResult } from './showTestResult.js'\nimport { failureLines } from './failureLines.js'\nimport { failureEntries } from './failureEntries.js'\nimport { agentDone, agentFailure, agentRunStart } from './agentReport.js'\nimport { makeStopSignal, stopIfFailFast } from './stopSignal.js'\nimport { statusCodes, writeStatusFile } from './statusFile.js'\n\nimport type {\n FinalConfig, OutFn, TestExecutionFilters, TestFile, TestResult, TestsResultsSummary\n} from '../../types.js'\nimport { makeRunManagerState, ReRunManageState } from './makeWatchRunState.js'\nimport { ReRunManager } from './reRunManager.js'\n\nconst { timeProfileAsync } = createTimeProfiler(showTimeProfiling)\n\nexport type RunTestsPromise = Promise<boolean | null>\n\n// the summary lines, minus the colouring, for the status file\nfunction joinPlain(...parts: string[]): string {\n return parts.filter(part => part !== '').join(' ')\n}\n\nfunction plural(count: number, noun: string, verb: string): string {\n if (count < 1) return ''\n return `${count} ${noun}${count === 1 ? '' : 's'} ${verb}`\n}\n\n\nexport async function runTests(\n config: FinalConfig,\n testFiles: Set<string>,\n reRunManager: ReRunManager | undefined,\n refresh: 'refresh' | 'cached' = 'refresh',\n customOut?: OutFn,\n filters: TestExecutionFilters = {}\n): RunTestsPromise {\n if (reRunManager !== undefined) {\n reRunManager.state.lastTestFiles = new Set(testFiles)\n reRunManager.state.activeRuns++ // whatever, obsolete. Can use it to check on things\n }\n\n const state = reRunManager?.state || makeRunManagerState()\n const runStartTime = new Date().getTime()\n const agentRun = agentRunStart(config, testFiles.size)\n const stop = makeStopSignal()\n //console.log('new runTests:', watchRunState?.activeRuns)\n //console.log(inspect(testFiles))\n\n try {\n const testRunPromises: Record<string, Promise<TestResult>> = {}\n const erroringTests: Record<string, TestFile> = {}\n const testRunOutPromises: Record<string, Promise<void>> = {}\n\n await timeProfileAsync('run tests', async () => {\n if (Array.isArray(testFiles) ? testFiles.length > 0 : testFiles.size > 0) {\n for (const testFile of testFiles) {\n //console.log('testFiles', testFiles)\n //console.log('testFile', testFile)\n\n // an earlier file failed under failFast - leave the rest unloaded\n if (stop.stopped) break\n\n const test = await loadTestFile(config, testFile, refresh)\n\n if (test.error !== undefined && test.error !== false) {\n erroringTests[testFile] = test\n state.failedTestFiles.add(testFile)\n showTestLoadingError(config, test, customOut)\n stopIfFailFast(config, stop, true)\n } else {\n const testRunPromise = runTest(config, test, filters, stop)\n testRunPromises[testFile] = testRunPromise\n\n testRunOutPromises[testFile] = testRunPromise.then(async testResult => {\n if (testResult.success === true || testResult.success === null) {\n state.failedTestFiles.delete(testResult.file)\n } else {\n state.failedTestFiles.add(testFile)\n }\n const executionFilterActive = filters.describe !== undefined || filters.it !== undefined\n if (!executionFilterActive || testResult.describeResultsSummary.itsTotal > 0) {\n await showTestResult(config, testResult, customOut)\n }\n })\n\n // wait for the test to complete before proceeding if we are in 'sequential' mode\n if (config.execution.files === 'sequential') await testRunOutPromises[testFile]\n }\n }\n }\n })\n\n let runTestResults: Record<string, TestResult> = {}\n\n await timeProfileAsync('wait for tests to finish', async () => {\n runTestResults = await promiseAllObj(testRunPromises)\n\n // wait for the output to complete\n await promiseAllObj(testRunOutPromises)\n })\n\n return await timeProfileAsync('show initial test run results', () => {\n \n const out = customOut ?? mainOut\n\n const testsResultsSummary: TestsResultsSummary = {\n total: 0,\n passes: 0,\n invalid: 0,\n describesTotal: 0,\n describesPasses: 0,\n describesInvalid: 0,\n itsTotal: 0,\n itsPasses: 0\n // itsInvalid: 0 // we don't check whether tests run any asserts (we don't control the assertion lib)\n }\n let describesThrownCount = 0\n\n for (const testFile in runTestResults) {\n const runTestResult = runTestResults[testFile]\n if (!runTestResult) continue\n\n testsResultsSummary.total += +(runTestResult.success !== null)\n testsResultsSummary.passes += +(runTestResult.success ?? false)\n testsResultsSummary.invalid += +(runTestResult.success === null)\n testsResultsSummary.describesTotal += runTestResult.describeResultsSummary.total\n testsResultsSummary.describesPasses += runTestResult.describeResultsSummary.passes\n testsResultsSummary.describesInvalid += runTestResult.describeResultsSummary.invalid\n testsResultsSummary.itsTotal += runTestResult.describeResultsSummary.itsTotal\n testsResultsSummary.itsPasses += runTestResult.describeResultsSummary.itsPasses\n describesThrownCount += runTestResult.describeResults\n .filter(describeResult => describeResult.error !== undefined)\n .length\n }\n\n const failedToLoadCount = count(erroringTests)\n testsResultsSummary.total += failedToLoadCount\n\n if (\n (filters.describe !== undefined || filters.it !== undefined)\n && testsResultsSummary.itsTotal === 0\n && failedToLoadCount === 0\n && describesThrownCount === 0\n ) {\n out(chalk.orange('No tests matched the describe/test filters.'))\n const durationMs = new Date().getTime() - runStartTime\n writeStatusFile(\n config,\n statusCodes.couldNotRun,\n 'no tests matched the describe/test filters',\n [],\n durationMs\n )\n agentDone(\n config, agentRun, statusCodes.couldNotRun,\n 'no tests matched the describe/test filters', testsResultsSummary, durationMs,\n state.failedTestFiles.size\n )\n return null\n }\n\n out('\\n')\n\n const allPassed = (\n testsResultsSummary.passes === testsResultsSummary.total\n && testsResultsSummary.describesPasses === testsResultsSummary.describesTotal\n && testsResultsSummary.itsPasses === testsResultsSummary.itsTotal\n )\n\n if (allPassed) {\n out(chalk.mediumgreen(`${figures.tick}`))\n } else {\n out(chalk.mediumred(`${figures.cross}`))\n }\n\n // number of tests successful\n const testsText = `Tests: ${testsResultsSummary.itsPasses}/${testsResultsSummary.itsTotal}`\n if (testsResultsSummary.itsPasses === testsResultsSummary.itsTotal) {\n out(chalk.mediumgreen(`${testsText}`))\n } else {\n out(chalk.mediumred(`${testsText}`))\n }\n\n // number of items successful\n const describesText = `Items: ${testsResultsSummary.describesPasses}/${testsResultsSummary.describesTotal}`\n const invalidDescribesPlain = (testsResultsSummary.describesInvalid >= 1)\n ? (testsResultsSummary.describesInvalid === 1)\n ? '(+1 describe without tests)'\n : `(+${testsResultsSummary.describesInvalid} describes without tests)`\n : ''\n const describesThrownPlain = (describesThrownCount >= 1)\n ? (describesThrownCount === 1)\n ? '(1 describe errored)'\n : `(${describesThrownCount} describes errored)`\n : ''\n const describesDetailsText = [\n chalk.grey(invalidDescribesPlain), chalk.mediumred(describesThrownPlain)\n ]\n .filter(text => text !== '')\n .join(' ')\n const describesDetailsSuffix = describesDetailsText === '' ? '' : ` ${describesDetailsText}`\n if (testsResultsSummary.describesPasses === testsResultsSummary.describesTotal) {\n out(chalk.mediumgreen(`${describesText}`) + describesDetailsSuffix)\n } else {\n out(chalk.mediumred(`${describesText}`) + describesDetailsSuffix)\n }\n\n // number of test files successful\n const testFilesText = `Test Files: ${testsResultsSummary.passes}/${testsResultsSummary.total}`\n const invalidTestFilesPlain = (testsResultsSummary.invalid >= 1)\n ? (testsResultsSummary.invalid === 1)\n ? '(+1 file without tests)'\n : `(+${testsResultsSummary.invalid} files without tests)`\n : ''\n const failedToLoadPlain = (failedToLoadCount >= 1)\n ? (failedToLoadCount === 1)\n ? '(1 file failed to load, or errored)'\n : `(${failedToLoadCount} files failed to load, or errored)`\n : ''\n const testFilesDetailsText = [\n chalk.grey(invalidTestFilesPlain), chalk.mediumred(failedToLoadPlain)\n ]\n .filter(text => text !== '')\n .join(' ')\n const testFilesDetailsSuffix = testFilesDetailsText === '' ? '' : ` ${testFilesDetailsText}`\n if (testsResultsSummary.passes === testsResultsSummary.total) {\n out(chalk.mediumgreen(`${testFilesText}`) + testFilesDetailsSuffix)\n } else {\n out(chalk.mediumred(`${testFilesText}`) + testFilesDetailsSuffix)\n }\n\n // the tallies only cover what ran, so say the run was cut short - otherwise\n // \"Tests: 0/1\" reads as a one test suite\n const stoppedPlain = (stop.stopped)\n ? 'stopped at the first failure (failFast)'\n : ''\n if (stoppedPlain !== '') out(chalk.orange(stoppedPlain))\n\n const summaryLines = [\n testsText,\n joinPlain(describesText, invalidDescribesPlain, describesThrownPlain),\n joinPlain(testFilesText, invalidTestFilesPlain, failedToLoadPlain),\n ...(stoppedPlain === '') ? [] : [stoppedPlain]\n ]\n\n const durationMs = new Date().getTime() - runStartTime\n\n if (allPassed) {\n writeStatusFile(\n config, statusCodes.passed, 'all tests passed', summaryLines, durationMs\n )\n agentDone(\n config, agentRun, statusCodes.passed, 'all tests passed',\n testsResultsSummary, durationMs, state.failedTestFiles.size\n )\n } else {\n const abortedFiles = Object.keys(erroringTests)\n\n // a file that would not load, or a describe that threw, means the run died\n // partway - a different problem from tests that ran and failed\n const aborted = abortedFiles.length > 0 || describesThrownCount > 0\n const failedTestsCount = testsResultsSummary.itsTotal - testsResultsSummary.itsPasses\n\n const description = ([\n plural(abortedFiles.length, 'test file', 'failed to load or errored'),\n plural(describesThrownCount, 'describe', 'errored'),\n plural(failedTestsCount, 'test', 'failed')\n ].filter(part => part !== '').join(', ') || 'test run failed')\n + ((stop.stopped) ? ', stopped at the first failure' : '')\n\n const code = (aborted) ? statusCodes.aborted : statusCodes.failed\n const failures = failureEntries(Object.values(runTestResults), erroringTests)\n\n writeStatusFile(\n config,\n code,\n description,\n [...summaryLines, ...failureLines(Object.values(runTestResults), erroringTests)],\n durationMs\n )\n\n // failures first, so the done line is a complete end of run marker\n for (const failure of failures) agentFailure(config, agentRun, failure)\n agentDone(\n config, agentRun, code, description, testsResultsSummary, durationMs,\n state.failedTestFiles.size\n )\n }\n\n // full success?\n // true/false gets returned to the caller of runTests()\n return allPassed\n })\n } finally {\n if (reRunManager !== undefined) reRunManager.state.activeRuns--\n }\n}\n\n"]}
@@ -0,0 +1,7 @@
1
+ import type { FinalConfig } from '../../types.js';
2
+ export interface StopSignal {
3
+ stopped: boolean;
4
+ }
5
+ export declare function makeStopSignal(): StopSignal;
6
+ export declare function stopIfFailFast(config: FinalConfig, stop: StopSignal, failed: boolean): void;
7
+ //# sourceMappingURL=stopSignal.d.ts.map
@@ -0,0 +1,10 @@
1
+ export function makeStopSignal() {
2
+ return { stopped: false };
3
+ }
4
+ // `failed` covers all three: a test file that would not load, a describe that threw, and a
5
+ // test that failed
6
+ export function stopIfFailFast(config, stop, failed) {
7
+ if (config.failFast && failed)
8
+ stop.stopped = true;
9
+ }
10
+ //# sourceMappingURL=stopSignal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stopSignal.js","sourceRoot":"","sources":["../../../src/cli/lib/stopSignal.ts"],"names":[],"mappings":"AASA,MAAM,UAAU,cAAc;IAC1B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAA;AAC7B,CAAC;AAED,2FAA2F;AAC3F,mBAAmB;AACnB,MAAM,UAAU,cAAc,CAAC,MAAmB,EAAE,IAAgB,EAAE,MAAe;IACjF,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM;QAAE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;AACtD,CAAC","sourcesContent":["import type { FinalConfig } from '../../types.js'\n\n// Shared by one run, so the file, describe and test loops can all see that something has\n// failed and stop starting new work. Deliberately a signal the loops *check* rather than an\n// exception: breaking out leaves every afterEach/teardown to unwind as it normally would.\nexport interface StopSignal {\n stopped: boolean\n}\n\nexport function makeStopSignal(): StopSignal {\n return { stopped: false }\n}\n\n// `failed` covers all three: a test file that would not load, a describe that threw, and a\n// test that failed\nexport function stopIfFailFast(config: FinalConfig, stop: StopSignal, failed: boolean): void {\n if (config.failFast && failed) stop.stopped = true\n}\n"]}
package/dist/cli/once.js CHANGED
@@ -5,8 +5,8 @@ import { setEnv } from './lib/setEnv.js';
5
5
  import { findingTestsMessage } from './lib/findingTestsMessage.js';
6
6
  import { foundTestsMessage } from './lib/foundTestsMessage.js';
7
7
  import { isTest } from './lib/isTest.js';
8
+ import { exitCodes } from './lib/exitCodes.js';
8
9
  export async function once() {
9
- out(chalk.brightblue `[${packageName}]...`);
10
10
  const startTime = new Date().getTime();
11
11
  const { parseCommandLineArguments } = await import('./lib/parseCommandLineArguments.js');
12
12
  const allowedClArguments = {
@@ -29,10 +29,26 @@ export async function once() {
29
29
  'filter-describe': {
30
30
  flag: 'd',
31
31
  hasValue: true
32
+ },
33
+ 'fail-fast': {
34
+ flag: 'x',
35
+ hasValue: false
36
+ },
37
+ 'agent': {
38
+ hasValue: false
32
39
  }
33
40
  };
34
41
  const clArguments = parseCommandLineArguments(allowedClArguments);
35
42
  //debug('clArguments', clArguments)
43
+ // agent mode owns stdout: the usual per-test output is routed into a sink, leaving the
44
+ // failures and the summary. Announced before the config loads, as in watch mode.
45
+ const agentMode = clArguments.agent === true;
46
+ const { agentInit, agentFound, agentRunStart, agentDone, agentSetRunReason, agentSilentOut } = await import('./lib/agentReport.js');
47
+ agentInit(agentMode);
48
+ agentSetRunReason('once');
49
+ const agentOut = (agentMode) ? agentSilentOut : out;
50
+ const runsOut = (agentMode) ? agentSilentOut : undefined;
51
+ agentOut(chalk.brightblue `[${packageName}]...`);
36
52
  setEnv();
37
53
  const { loadConfig } = await import('./lib/loadConfig.js');
38
54
  const userConfig = (typeof clArguments.config === 'string')
@@ -63,9 +79,10 @@ export async function once() {
63
79
  }
64
80
  const { applyConfigDefaults } = await import('./lib/applyConfigDefaults.js');
65
81
  const config = applyConfigDefaults(userConfig);
66
- // agent reporting is a watch mode concern - `once` already ends with an exit code, so a
67
- // config setting it must not leak in here
68
- config.watch.agent = false;
82
+ // both flags are the only source: assigned rather than or'd, so a config file cannot
83
+ // silently truncate every run, or swap the output format out from under a caller
84
+ config.failFast = clArguments['fail-fast'] === true;
85
+ config.watch.agent = agentMode;
69
86
  const { validateConfig } = await import('./lib/validateConfig.js');
70
87
  validateConfig(config);
71
88
  //console.log('run setup')
@@ -73,34 +90,43 @@ export async function once() {
73
90
  const { doUserSetup } = await import('./lib/doUserSetup.js');
74
91
  await doUserSetup(config);
75
92
  //console.log('ran setup')
76
- out(chalk.brightblue(findingTestsMessage(config)));
93
+ agentOut(chalk.brightblue(findingTestsMessage(config)));
77
94
  const { findTestFiles } = await import('./lib/findTestFiles.js');
78
95
  const testFiles = await findTestFiles(config);
96
+ agentFound(config, testFiles.size);
79
97
  if (testFiles.size === 0) {
80
- out(chalk.mediumred(`[${packageName}] Found no tests.`
98
+ agentOut(chalk.mediumred(`[${packageName}] Found no tests.`
81
99
  + '\nCreate tests matching the patterns, '
82
100
  + `\nor set new patterns in ${configFileNames.map(x => `${x}.js/cjs/mjs`).join(' or ')}`));
83
101
  const endTime = new Date().getTime();
84
102
  const time = endTime - startTime;
85
- out(chalk.brightblue(`[${packageName}] time: ${time.toLocaleString()}ms`));
103
+ agentOut(chalk.brightblue(`[${packageName}] time: ${time.toLocaleString()}ms`));
104
+ // reported as a run, so a reader waiting on a done line always gets one
105
+ const { statusCodes } = await import('./lib/statusFile.js');
106
+ const run = agentRunStart(config, 0);
107
+ agentDone(config, run, statusCodes.couldNotRun, 'no test files found', null, time, 0);
86
108
  // setup has already run by this point, so teardown must run too, or its side
87
109
  // effects are left behind
88
110
  const { doUserTeardown } = await import('./lib/doUserTeardown.js');
89
111
  await doUserTeardown(config);
90
- process.exit(4);
112
+ process.exit(exitCodes.noTestFiles);
91
113
  }
92
- out(chalk.brightblue(foundTestsMessage(testFiles.size)));
114
+ agentOut(chalk.brightblue(foundTestsMessage(testFiles.size)));
93
115
  // testFiles.size is guaranteed non-zero here - the no-tests case exited above
94
116
  const { runTests } = await import('./lib/runTests.js');
95
- log(chalk.brightblue `running tests...`);
96
- const testsResult = await runTests(config, testFiles, undefined, (isTest) ? 'refresh' : 'cached', undefined, {
117
+ if (!agentMode)
118
+ log(chalk.brightblue `running tests...`);
119
+ const testsResult = await runTests(config, testFiles, undefined, (isTest) ? 'refresh' : 'cached', runsOut, {
97
120
  it: filterIt,
98
121
  describe: filterDescribe
99
122
  });
100
- // 5 - not 4 - so callers can tell "no test files matched" from "filters matched nothing"
101
- const exitCode = testsResult === null ? 5 : testsResult ? 0 : 3;
123
+ // a distinct code from noTestFiles, so callers can tell "no test file matched the
124
+ // pattern" from "the files matched but the filters selected nothing in them"
125
+ const exitCode = (testsResult === null)
126
+ ? exitCodes.noMatchingTests
127
+ : (testsResult) ? exitCodes.passed : exitCodes.testErrors;
102
128
  const time = new Date().getTime() - startTime;
103
- out(chalk.grey `\n${time.toLocaleString()}ms\n`);
129
+ agentOut(chalk.grey `\n${time.toLocaleString()}ms\n`);
104
130
  const { doUserTeardown } = await import('./lib/doUserTeardown.js');
105
131
  await doUserTeardown(config);
106
132
  process.exit(exitCode);