sxy-test-runner 2.5.2 → 2.5.3

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/AGENTS.md CHANGED
@@ -490,7 +490,12 @@ line ending in `:` - because the lines after the first are often the point: `nod
490
490
  puts only a preamble on the first, with the values below, so its failure reads
491
491
  `AssertionError: Expected values to be strictly equal: 1 !== 2`, and a deep-equal diff reads
492
492
  `... deep-equal: + actual - expected / { / + a: 1, / - a: 2 / }`. Blank lines are
493
- dropped and the message is cut at 500 characters; the terminal keeps the full diff.
493
+ dropped and the message is cut at `agentLineLengthLimit` characters - 500 by default,
494
+ `Infinity` for no cut; the terminal keeps the full diff.
495
+
496
+ Agent mode sets `SXYT_AGENT` and `SXY_TEST_RUNNER_AGENT` to `true` once the config has
497
+ loaded, before `setup` runs, so a config enabling it is seen too. When agent mode is off
498
+ both are removed, so a value inherited from a parent agent run is not mistaken for this one.
494
499
 
495
500
  In `once`, read the process's exit code for pass/fail and the `status` on `done` for what
496
501
  kind of failure it was - `status=failed` accompanies exit `20`. `watching` and `change`
@@ -517,6 +522,7 @@ export default {
517
522
  compact: false,
518
523
  restateFailures: true,
519
524
  agent: false,
525
+ agentLineLengthLimit: 500,
520
526
 
521
527
  setup: undefined,
522
528
  beforeEachFile: undefined,
package/dist/cli/init.js CHANGED
@@ -80,6 +80,8 @@ export default {
80
80
 
81
81
  // report only minimal info, failures and results, as single lines, suited for agents
82
82
  agent: false,
83
+ // the most characters of each failure's error text in agent mode, Infinity for no limit
84
+ agentLineLengthLimit: 500,
83
85
 
84
86
 
85
87
  // tasks to run on startup
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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","sourcesContent":["\nimport { join } from 'path'\nimport fs from 'fs'\n\nimport chalk from '../packages/chalk.js'\nimport { packageName, cliName, configFileNames, configLocations } from '../config.js'\nimport { out } from '../output.js'\nimport { exitCodes } from './lib/exitCodes.js'\n\n\nexport function init(): void {\n const projectDir = process.cwd()\n\n for (const configLocation of configLocations) {\n for (const configFileName of configFileNames) {\n let loc\n loc = join(projectDir, configLocation, configFileName + '.js')\n if (fs.existsSync(loc)) {\n configAlreadyExists(loc)\n }\n loc = join(projectDir, configLocation, configFileName + '.cjs')\n if (fs.existsSync(loc)) {\n configAlreadyExists(loc)\n }\n loc = join(projectDir, configLocation, configFileName + '.mjs')\n if (fs.existsSync(loc)) {\n configAlreadyExists(loc)\n }\n }\n }\n\n function configAlreadyExists(loc: string): never {\n reportAndExit(`[${packageName}] A matching config already exists at ${loc}`\n + `\\nPlease remove this config before generating a new one with \\`${cliName} init\\``)\n }\n\n const projectPackageJsonLocation = join(projectDir, 'package.json')\n if (!fs.existsSync(projectPackageJsonLocation)) {\n reportAndExit(`[${packageName}] No package.json exists in this location`\n + '\\nPlease initialise the package with `npm init` or `yarn init`'\n + ' before running this command, and run this command from the project root folder')\n }\n\n let packageJson: { type?: string }\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n packageJson = JSON.parse(fs.readFileSync(projectPackageJsonLocation, 'utf8'))\n } catch (error) {\n reportAndExit(`[${packageName}] Could not read the package.json at ${projectPackageJsonLocation}`\n + `\\n${error instanceof Error ? error.message : String(error)}`\n + '\\nPlease make sure the file is readable and contains valid JSON, then try again')\n }\n\n const targetConfigName = (packageJson.type === 'module')\n // ES6 module\n ? join(projectDir, configLocations[0] ?? '', configFileNames[0] + '.js')\n // common\n : join(projectDir, configLocations[0] ?? '', configFileNames[0] + '.mjs')\n\n const defaultConfig =\n `\n// @ts-check\n\n/** @type {import('sxy-test-runner').Config} */\nexport default {\n\n // base folder for tests match and ignore patterns\n testsBase: '.',\n\n // glob pattern or array of glob patterns of test files\n tests: [\n '**/*.sxyt.{js,mjs,jsx}',\n '**/*.test.{js,mjs,jsx}',\n '**/*.spec.{js,mjs,jsx}',\n '**/tests?/*.{js,mjs,jsx}',\n '**/__tests?__/*.{js,mjs,jsx}'\n ],\n\n // glob pattern or array of patterns of test files to ignore\n testsIgnore: ['**/node_modules/**'],\n\n // repeat the failures above the tallies at the end of a run, when there are a small number of them\n restateFailures: true,\n\n // whether to show the full error trace when an error occurs in a test file\n showErrorTrace: false,\n\n // drop the blank lines within each test file's output, does nothing when agent: is true\n compact: false,\n\n // report only minimal info, failures and results, as single lines, suited for agents\n agent: false,\n\n\n // tasks to run on startup\n // accepts a function, file location (relative to project base), or array of functions and or files\n setup: undefined,\n\n // tasks to run before each test file is run\n beforeEachFile: undefined,\n\n // tasks to run after each test file is run\n afterEachFile: undefined,\n\n // tasks to run before each describe block is processed\n // if the function returns an object with named properties, or the file exports named exports,\n // these will be passed to the callback function in argument 0, and can be access by destructruing e.g.\n // describe('thing', ({exportA, exportB}) => { it('should', ...) })\n beforeEachDescribe: undefined,\n\n // tasks to run after each describe block\n afterEachDescribe: undefined,\n\n // tasks to run before each it/test block\n // function returns and file exports will be passed to the it/test block as with describe above, e.g.\n // it('should', ({exportA, exportB}) => { assert('something') })\n beforeEachTest: undefined,\n\n // tasks to run after each it/test block\n afterEachTest: undefined,\n\n // tasks to run once the whole run has finished\n teardown: undefined,\n\n // how to execute the different parts of test files\n execution: {\n\n // run test files in 'parallel' or 'sequential'ly\n files: 'sequential',\n\n // run describe blocks within a test file in 'parallel' or 'sequential'ly\n describes: 'sequential',\n\n // run it/test blocks within a describe blocks in 'parallel' or 'sequential'ly\n tests: 'sequential'\n\n },\n\n // watch mode configurations\n watch: {\n\n //// the base directory to watch files in\n watchFilesBase: '.',\n\n //// glob filter or array of glob filters of files to watch\n watchFiles: '**/*.js',\n\n //// glob filter or array of globl filters of files to ignore\n watchFilesIgnore: '**/node_modules/**',\n\n // run all tests when starting the watcher\n runAllOnStartup: true,\n\n // re run all previously failed tests on each test run, until they pass\n reRunFailingTests: true,\n\n // evaluate the dependencies of each test file, and re-run that test file only when they change. \n // Set this to false to re-run everything on any change\n dependencyEvaluation: true,\n\n // run watch mode keyboard commands immediately, without waiting for Enter\n ttyActionsOnKeypress: false,\n\n // file to write the latest run status to, or false for none\n statusFile: false,\n\n },\n\n}`\n\n try {\n fs.writeFileSync(targetConfigName, defaultConfig)\n } catch (error) {\n reportAndExit(`[${packageName}] Could not write the config to ${targetConfigName}`\n + `\\n${error instanceof Error ? error.message : String(error)}`\n + '\\nPlease check the folder is writable, then try again')\n }\n\n out(chalk.mediumgreen`[${packageName}] Created config at ` + chalk.blue(targetConfigName))\n}\n\n// init cannot continue past any of these, so they report in the error colour and stop\nfunction reportAndExit(message: string): never {\n out(chalk.mediumred(message))\n process.exit(exitCodes.usageError)\n}\n"]}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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","sourcesContent":["\nimport { join } from 'path'\nimport fs from 'fs'\n\nimport chalk from '../packages/chalk.js'\nimport { packageName, cliName, configFileNames, configLocations } from '../config.js'\nimport { out } from '../output.js'\nimport { exitCodes } from './lib/exitCodes.js'\n\n\nexport function init(): void {\n const projectDir = process.cwd()\n\n for (const configLocation of configLocations) {\n for (const configFileName of configFileNames) {\n let loc\n loc = join(projectDir, configLocation, configFileName + '.js')\n if (fs.existsSync(loc)) {\n configAlreadyExists(loc)\n }\n loc = join(projectDir, configLocation, configFileName + '.cjs')\n if (fs.existsSync(loc)) {\n configAlreadyExists(loc)\n }\n loc = join(projectDir, configLocation, configFileName + '.mjs')\n if (fs.existsSync(loc)) {\n configAlreadyExists(loc)\n }\n }\n }\n\n function configAlreadyExists(loc: string): never {\n reportAndExit(`[${packageName}] A matching config already exists at ${loc}`\n + `\\nPlease remove this config before generating a new one with \\`${cliName} init\\``)\n }\n\n const projectPackageJsonLocation = join(projectDir, 'package.json')\n if (!fs.existsSync(projectPackageJsonLocation)) {\n reportAndExit(`[${packageName}] No package.json exists in this location`\n + '\\nPlease initialise the package with `npm init` or `yarn init`'\n + ' before running this command, and run this command from the project root folder')\n }\n\n let packageJson: { type?: string }\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n packageJson = JSON.parse(fs.readFileSync(projectPackageJsonLocation, 'utf8'))\n } catch (error) {\n reportAndExit(`[${packageName}] Could not read the package.json at ${projectPackageJsonLocation}`\n + `\\n${error instanceof Error ? error.message : String(error)}`\n + '\\nPlease make sure the file is readable and contains valid JSON, then try again')\n }\n\n const targetConfigName = (packageJson.type === 'module')\n // ES6 module\n ? join(projectDir, configLocations[0] ?? '', configFileNames[0] + '.js')\n // common\n : join(projectDir, configLocations[0] ?? '', configFileNames[0] + '.mjs')\n\n const defaultConfig =\n `\n// @ts-check\n\n/** @type {import('sxy-test-runner').Config} */\nexport default {\n\n // base folder for tests match and ignore patterns\n testsBase: '.',\n\n // glob pattern or array of glob patterns of test files\n tests: [\n '**/*.sxyt.{js,mjs,jsx}',\n '**/*.test.{js,mjs,jsx}',\n '**/*.spec.{js,mjs,jsx}',\n '**/tests?/*.{js,mjs,jsx}',\n '**/__tests?__/*.{js,mjs,jsx}'\n ],\n\n // glob pattern or array of patterns of test files to ignore\n testsIgnore: ['**/node_modules/**'],\n\n // repeat the failures above the tallies at the end of a run, when there are a small number of them\n restateFailures: true,\n\n // whether to show the full error trace when an error occurs in a test file\n showErrorTrace: false,\n\n // drop the blank lines within each test file's output, does nothing when agent: is true\n compact: false,\n\n // report only minimal info, failures and results, as single lines, suited for agents\n agent: false,\n // the most characters of each failure's error text in agent mode, Infinity for no limit\n agentLineLengthLimit: 500,\n\n\n // tasks to run on startup\n // accepts a function, file location (relative to project base), or array of functions and or files\n setup: undefined,\n\n // tasks to run before each test file is run\n beforeEachFile: undefined,\n\n // tasks to run after each test file is run\n afterEachFile: undefined,\n\n // tasks to run before each describe block is processed\n // if the function returns an object with named properties, or the file exports named exports,\n // these will be passed to the callback function in argument 0, and can be access by destructruing e.g.\n // describe('thing', ({exportA, exportB}) => { it('should', ...) })\n beforeEachDescribe: undefined,\n\n // tasks to run after each describe block\n afterEachDescribe: undefined,\n\n // tasks to run before each it/test block\n // function returns and file exports will be passed to the it/test block as with describe above, e.g.\n // it('should', ({exportA, exportB}) => { assert('something') })\n beforeEachTest: undefined,\n\n // tasks to run after each it/test block\n afterEachTest: undefined,\n\n // tasks to run once the whole run has finished\n teardown: undefined,\n\n // how to execute the different parts of test files\n execution: {\n\n // run test files in 'parallel' or 'sequential'ly\n files: 'sequential',\n\n // run describe blocks within a test file in 'parallel' or 'sequential'ly\n describes: 'sequential',\n\n // run it/test blocks within a describe blocks in 'parallel' or 'sequential'ly\n tests: 'sequential'\n\n },\n\n // watch mode configurations\n watch: {\n\n //// the base directory to watch files in\n watchFilesBase: '.',\n\n //// glob filter or array of glob filters of files to watch\n watchFiles: '**/*.js',\n\n //// glob filter or array of globl filters of files to ignore\n watchFilesIgnore: '**/node_modules/**',\n\n // run all tests when starting the watcher\n runAllOnStartup: true,\n\n // re run all previously failed tests on each test run, until they pass\n reRunFailingTests: true,\n\n // evaluate the dependencies of each test file, and re-run that test file only when they change. \n // Set this to false to re-run everything on any change\n dependencyEvaluation: true,\n\n // run watch mode keyboard commands immediately, without waiting for Enter\n ttyActionsOnKeypress: false,\n\n // file to write the latest run status to, or false for none\n statusFile: false,\n\n },\n\n}`\n\n try {\n fs.writeFileSync(targetConfigName, defaultConfig)\n } catch (error) {\n reportAndExit(`[${packageName}] Could not write the config to ${targetConfigName}`\n + `\\n${error instanceof Error ? error.message : String(error)}`\n + '\\nPlease check the folder is writable, then try again')\n }\n\n out(chalk.mediumgreen`[${packageName}] Created config at ` + chalk.blue(targetConfigName))\n}\n\n// init cannot continue past any of these, so they report in the error colour and stop\nfunction reportAndExit(message: string): never {\n out(chalk.mediumred(message))\n process.exit(exitCodes.usageError)\n}\n"]}
@@ -12,6 +12,7 @@ export const defaultConfig = {
12
12
  compact: false,
13
13
  restateFailures: true,
14
14
  agent: false,
15
+ agentLineLengthLimit: 500,
15
16
  failFast: false,
16
17
  execution: {
17
18
  files: 'sequential',
@@ -1 +1 @@
1
- {"version":3,"file":"defaultConfig.js","sourceRoot":"","sources":["../../../src/cli/lib/defaultConfig.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,aAAa,GAAgB;IACtC,SAAS,EAAE,GAAG;IACd,KAAK,EAAE;QACH,wBAAwB;QACxB,wBAAwB;QACxB,wBAAwB;QACxB,0BAA0B;QAC1B,8BAA8B;KACjC;IACD,WAAW,EAAE,CAAC,oBAAoB,CAAC;IACnC,cAAc,EAAE,KAAK;IACrB,OAAO,EAAE,KAAK;IACd,eAAe,EAAE,IAAI;IACrB,KAAK,EAAE,KAAK;IACZ,QAAQ,EAAE,KAAK;IACf,SAAS,EAAE;QACP,KAAK,EAAE,YAAY;QACnB,SAAS,EAAE,YAAY;QACvB,KAAK,EAAE,YAAY;KACtB;IACD,KAAK,EAAE;QACH,cAAc,EAAE,GAAG;QACnB,UAAU,EAAE,SAAS;QACrB,gBAAgB,EAAE,oBAAoB;QACtC,eAAe,EAAE,IAAI;QACrB,iBAAiB,EAAE,IAAI;QACvB,oBAAoB,EAAE,IAAI;QAC1B,oBAAoB,EAAE,KAAK;QAC3B,UAAU,EAAE,KAAK;KACpB;CACJ,CAAA","sourcesContent":["\nimport type { FinalConfig } from '../../types.js'\n\n\nexport const defaultConfig: FinalConfig = {\n testsBase: '.',\n tests: [\n '**/*.sxyt.{js,mjs,jsx}',\n '**/*.test.{js,mjs,jsx}',\n '**/*.spec.{js,mjs,jsx}',\n '**/tests?/*.{js,mjs,jsx}',\n '**/__tests?__/*.{js,mjs,jsx}'\n ],\n testsIgnore: ['**/node_modules/**'],\n showErrorTrace: false,\n compact: false,\n restateFailures: true,\n agent: false,\n failFast: false,\n execution: {\n files: 'sequential',\n describes: 'sequential',\n tests: 'sequential'\n },\n watch: {\n watchFilesBase: '.',\n watchFiles: '**/*.js',\n watchFilesIgnore: '**/node_modules/**',\n runAllOnStartup: true,\n reRunFailingTests: true,\n dependencyEvaluation: true,\n ttyActionsOnKeypress: false,\n statusFile: false\n }\n}\n"]}
1
+ {"version":3,"file":"defaultConfig.js","sourceRoot":"","sources":["../../../src/cli/lib/defaultConfig.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,aAAa,GAAgB;IACtC,SAAS,EAAE,GAAG;IACd,KAAK,EAAE;QACH,wBAAwB;QACxB,wBAAwB;QACxB,wBAAwB;QACxB,0BAA0B;QAC1B,8BAA8B;KACjC;IACD,WAAW,EAAE,CAAC,oBAAoB,CAAC;IACnC,cAAc,EAAE,KAAK;IACrB,OAAO,EAAE,KAAK;IACd,eAAe,EAAE,IAAI;IACrB,KAAK,EAAE,KAAK;IACZ,oBAAoB,EAAE,GAAG;IACzB,QAAQ,EAAE,KAAK;IACf,SAAS,EAAE;QACP,KAAK,EAAE,YAAY;QACnB,SAAS,EAAE,YAAY;QACvB,KAAK,EAAE,YAAY;KACtB;IACD,KAAK,EAAE;QACH,cAAc,EAAE,GAAG;QACnB,UAAU,EAAE,SAAS;QACrB,gBAAgB,EAAE,oBAAoB;QACtC,eAAe,EAAE,IAAI;QACrB,iBAAiB,EAAE,IAAI;QACvB,oBAAoB,EAAE,IAAI;QAC1B,oBAAoB,EAAE,KAAK;QAC3B,UAAU,EAAE,KAAK;KACpB;CACJ,CAAA","sourcesContent":["\nimport type { FinalConfig } from '../../types.js'\n\n\nexport const defaultConfig: FinalConfig = {\n testsBase: '.',\n tests: [\n '**/*.sxyt.{js,mjs,jsx}',\n '**/*.test.{js,mjs,jsx}',\n '**/*.spec.{js,mjs,jsx}',\n '**/tests?/*.{js,mjs,jsx}',\n '**/__tests?__/*.{js,mjs,jsx}'\n ],\n testsIgnore: ['**/node_modules/**'],\n showErrorTrace: false,\n compact: false,\n restateFailures: true,\n agent: false,\n agentLineLengthLimit: 500,\n failFast: false,\n execution: {\n files: 'sequential',\n describes: 'sequential',\n tests: 'sequential'\n },\n watch: {\n watchFilesBase: '.',\n watchFiles: '**/*.js',\n watchFilesIgnore: '**/node_modules/**',\n runAllOnStartup: true,\n reRunFailingTests: true,\n dependencyEvaluation: true,\n ttyActionsOnKeypress: false,\n statusFile: false\n }\n}\n"]}
@@ -6,5 +6,5 @@ export interface FailureEntry {
6
6
  test?: string;
7
7
  error: string;
8
8
  }
9
- export declare function failureEntries(testResults: TestResult[], erroringTests?: Record<string, TestFile>): FailureEntry[];
9
+ export declare function failureEntries(testResults: TestResult[], erroringTests?: Record<string, TestFile>, messageLimit?: number): FailureEntry[];
10
10
  //# sourceMappingURL=failureEntries.d.ts.map
@@ -1,5 +1,6 @@
1
1
  import { inspect } from 'node:util';
2
- export function failureEntries(testResults, erroringTests = {}) {
2
+ export function failureEntries(testResults, erroringTests = {}, messageLimit = 500) {
3
+ const simplifyError = (error) => simplifyErrorTo(error, messageLimit);
3
4
  const entries = [];
4
5
  for (const [file, test] of Object.entries(erroringTests)) {
5
6
  entries.push({ file, error: `did not load: ${loadError(test.error)}` });
@@ -32,28 +33,27 @@ export function failureEntries(testResults, erroringTests = {}) {
32
33
  // preamble and keep the cause, flattened: an import error can run to several lines.
33
34
  function loadError(error) {
34
35
  if (typeof error !== 'string')
35
- return simplifyError(error);
36
+ return simplifyErrorTo(error, 500);
36
37
  const cause = error.replace(/^Error loading file\r?\n/, '').replace(/\s*[\r\n]+\s*/g, ' ').trim();
37
38
  if (cause === '')
38
39
  return 'Error loading file';
39
40
  return (cause.length > 200) ? `${cause.slice(0, 200)}...` : cause;
40
41
  }
41
- function simplifyError(error) {
42
+ function simplifyErrorTo(error, messageLimit) {
42
43
  if (error === undefined || error === null || error === false)
43
44
  return 'unknown error';
44
45
  if (typeof error === 'object' && 'message' in error && typeof error.message === 'string') {
45
46
  const name = ('name' in error && typeof error.name === 'string') ? error.name : 'Error';
46
- return `${name}: ${joinLines(error.message)}`;
47
+ return `${name}: ${joinLines(error.message, messageLimit)}`;
47
48
  }
48
49
  if (typeof error === 'string')
49
- return joinLines(error);
50
+ return joinLines(error, messageLimit);
50
51
  // breakLength keeps inspect from wrapping, so the result stays one line
51
- return joinLines(inspect(error, { breakLength: Infinity }));
52
+ return joinLines(inspect(error, { breakLength: Infinity }), messageLimit);
52
53
  }
53
- const messageLimit = 500;
54
54
  // lines after the first often carry the point - node:assert's values, ensure's sightings - so
55
55
  // all are kept, joined to stay one line for the status file and the agent stream
56
- function joinLines(text) {
56
+ function joinLines(text, messageLimit) {
57
57
  const joined = text.split(/\r?\n/).map(line => line.trim()).filter(line => line !== '')
58
58
  .reduce((previous, line) => (previous === '')
59
59
  ? line
@@ -1 +1 @@
1
- {"version":3,"file":"failureEntries.js","sourceRoot":"","sources":["../../../src/cli/lib/failureEntries.ts"],"names":[],"mappings":"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","sourcesContent":["\nimport { inspect } from 'node:util'\n\nimport type { TestResult } from './runTest.js'\nimport type { TestFile } from './loadTestFile.js'\n\n\n// One failure, flattened. `describe` is absent when a file would not load, and `test` is\n// absent when the describe itself threw. Shared by the status file's nested tree and the\n// agent reporter's flat lines, so both describe a failure the same way.\nexport interface FailureEntry {\n file: string\n describe?: string\n test?: string\n error: string\n}\n\nexport function failureEntries(\n testResults: TestResult[],\n erroringTests: Record<string, TestFile> = {}\n): FailureEntry[] {\n const entries: FailureEntry[] = []\n\n for (const [file, test] of Object.entries(erroringTests)) {\n entries.push({ file, error: `did not load: ${loadError(test.error)}` })\n }\n\n for (const testResult of testResults) {\n for (const describeResult of testResult.describeResults) {\n if (describeResult.error !== undefined) {\n entries.push({\n file: testResult.file,\n describe: describeResult.thing,\n error: `threw: ${simplifyError(describeResult.error)}`\n })\n }\n\n for (const itResult of describeResult.itResults) {\n if (itResult.success !== false) continue\n entries.push({\n file: testResult.file,\n describe: describeResult.thing,\n test: itResult.should,\n error: simplifyError(itResult.error)\n })\n }\n }\n }\n\n return entries\n}\n\n// the loader stores its own preamble with the real cause on the line below, so the first\n// line alone says only that loading failed - which `did not load` has already said. Drop the\n// preamble and keep the cause, flattened: an import error can run to several lines.\nfunction loadError(error: unknown): string {\n if (typeof error !== 'string') return simplifyError(error)\n\n const cause = error.replace(/^Error loading file\\r?\\n/, '').replace(/\\s*[\\r\\n]+\\s*/g, ' ').trim()\n if (cause === '') return 'Error loading file'\n return (cause.length > 200) ? `${cause.slice(0, 200)}...` : cause\n}\n\nfunction simplifyError(error: unknown): string {\n if (error === undefined || error === null || error === false) return 'unknown error'\n\n if (typeof error === 'object' && 'message' in error && typeof error.message === 'string') {\n const name = ('name' in error && typeof error.name === 'string') ? error.name : 'Error'\n return `${name}: ${joinLines(error.message)}`\n }\n\n if (typeof error === 'string') return joinLines(error)\n // breakLength keeps inspect from wrapping, so the result stays one line\n return joinLines(inspect(error, { breakLength: Infinity }))\n}\n\nconst messageLimit = 500\n\n// lines after the first often carry the point - node:assert's values, ensure's sightings - so\n// all are kept, joined to stay one line for the status file and the agent stream\nfunction joinLines(text: string): string {\n const joined = text.split(/\\r?\\n/).map(line => line.trim()).filter(line => line !== '')\n .reduce((previous, line) => (previous === '')\n ? line\n : previous + (previous.endsWith(':') ? ' ' : ' / ') + line, '')\n return (joined.length > messageLimit) ? `${joined.slice(0, messageLimit)}...` : joined\n}\n"]}
1
+ {"version":3,"file":"failureEntries.js","sourceRoot":"","sources":["../../../src/cli/lib/failureEntries.ts"],"names":[],"mappings":"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","sourcesContent":["\nimport { inspect } from 'node:util'\n\nimport type { TestResult } from './runTest.js'\nimport type { TestFile } from './loadTestFile.js'\n\n\n// One failure, flattened. `describe` is absent when a file would not load, and `test` is\n// absent when the describe itself threw. Shared by the status file's nested tree and the\n// agent reporter's flat lines, so both describe a failure the same way.\nexport interface FailureEntry {\n file: string\n describe?: string\n test?: string\n error: string\n}\n\nexport function failureEntries(\n testResults: TestResult[],\n erroringTests: Record<string, TestFile> = {},\n messageLimit = 500\n): FailureEntry[] {\n const simplifyError = (error: unknown) => simplifyErrorTo(error, messageLimit)\n const entries: FailureEntry[] = []\n\n for (const [file, test] of Object.entries(erroringTests)) {\n entries.push({ file, error: `did not load: ${loadError(test.error)}` })\n }\n\n for (const testResult of testResults) {\n for (const describeResult of testResult.describeResults) {\n if (describeResult.error !== undefined) {\n entries.push({\n file: testResult.file,\n describe: describeResult.thing,\n error: `threw: ${simplifyError(describeResult.error)}`\n })\n }\n\n for (const itResult of describeResult.itResults) {\n if (itResult.success !== false) continue\n entries.push({\n file: testResult.file,\n describe: describeResult.thing,\n test: itResult.should,\n error: simplifyError(itResult.error)\n })\n }\n }\n }\n\n return entries\n}\n\n// the loader stores its own preamble with the real cause on the line below, so the first\n// line alone says only that loading failed - which `did not load` has already said. Drop the\n// preamble and keep the cause, flattened: an import error can run to several lines.\nfunction loadError(error: unknown): string {\n if (typeof error !== 'string') return simplifyErrorTo(error, 500)\n\n const cause = error.replace(/^Error loading file\\r?\\n/, '').replace(/\\s*[\\r\\n]+\\s*/g, ' ').trim()\n if (cause === '') return 'Error loading file'\n return (cause.length > 200) ? `${cause.slice(0, 200)}...` : cause\n}\n\nfunction simplifyErrorTo(error: unknown, messageLimit: number): string {\n if (error === undefined || error === null || error === false) return 'unknown error'\n\n if (typeof error === 'object' && 'message' in error && typeof error.message === 'string') {\n const name = ('name' in error && typeof error.name === 'string') ? error.name : 'Error'\n return `${name}: ${joinLines(error.message, messageLimit)}`\n }\n\n if (typeof error === 'string') return joinLines(error, messageLimit)\n // breakLength keeps inspect from wrapping, so the result stays one line\n return joinLines(inspect(error, { breakLength: Infinity }), messageLimit)\n}\n\n// lines after the first often carry the point - node:assert's values, ensure's sightings - so\n// all are kept, joined to stay one line for the status file and the agent stream\nfunction joinLines(text: string, messageLimit: number): string {\n const joined = text.split(/\\r?\\n/).map(line => line.trim()).filter(line => line !== '')\n .reduce((previous, line) => (previous === '')\n ? line\n : previous + (previous.endsWith(':') ? ' ' : ' / ') + line, '')\n return (joined.length > messageLimit) ? `${joined.slice(0, messageLimit)}...` : joined\n}\n"]}
@@ -1,2 +1,3 @@
1
1
  export declare function setEnv(): void;
2
+ export declare function setAgentEnv(agent: boolean): void;
2
3
  //# sourceMappingURL=setEnv.d.ts.map
@@ -4,4 +4,15 @@ export function setEnv() {
4
4
  process.env.SXYT = 'true';
5
5
  process.env.SXY_TEST_RUNNER = 'true';
6
6
  }
7
+ // deleted when off, so a value inherited from a parent agent run is not taken as this run's
8
+ export function setAgentEnv(agent) {
9
+ if (agent) {
10
+ process.env.SXYT_AGENT = 'true';
11
+ process.env.SXY_TEST_RUNNER_AGENT = 'true';
12
+ }
13
+ else {
14
+ delete process.env.SXYT_AGENT;
15
+ delete process.env.SXY_TEST_RUNNER_AGENT;
16
+ }
17
+ }
7
18
  //# sourceMappingURL=setEnv.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"setEnv.js","sourceRoot":"","sources":["../../../src/cli/lib/setEnv.ts"],"names":[],"mappings":"AACA,uDAAuD;AACvD,MAAM,UAAU,MAAM;IAClB,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,CAAA;IAC/B,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,MAAM,CAAA;IACzB,OAAO,CAAC,GAAG,CAAC,eAAe,GAAG,MAAM,CAAA;AACxC,CAAC","sourcesContent":["\n// set some env vars when the test framework is running\nexport function setEnv() {\n process.env.NODE_ENV ??= 'test'\n process.env.SXYT = 'true'\n process.env.SXY_TEST_RUNNER = 'true'\n}\n"]}
1
+ {"version":3,"file":"setEnv.js","sourceRoot":"","sources":["../../../src/cli/lib/setEnv.ts"],"names":[],"mappings":"AACA,uDAAuD;AACvD,MAAM,UAAU,MAAM;IAClB,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,CAAA;IAC/B,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,MAAM,CAAA;IACzB,OAAO,CAAC,GAAG,CAAC,eAAe,GAAG,MAAM,CAAA;AACxC,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,WAAW,CAAC,KAAc;IACtC,IAAI,KAAK,EAAE,CAAC;QACR,OAAO,CAAC,GAAG,CAAC,UAAU,GAAG,MAAM,CAAA;QAC/B,OAAO,CAAC,GAAG,CAAC,qBAAqB,GAAG,MAAM,CAAA;IAC9C,CAAC;SAAM,CAAC;QACJ,OAAO,OAAO,CAAC,GAAG,CAAC,UAAU,CAAA;QAC7B,OAAO,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAA;IAC5C,CAAC;AACL,CAAC","sourcesContent":["\n// set some env vars when the test framework is running\nexport function setEnv() {\n process.env.NODE_ENV ??= 'test'\n process.env.SXYT = 'true'\n process.env.SXY_TEST_RUNNER = 'true'\n}\n\n// deleted when off, so a value inherited from a parent agent run is not taken as this run's\nexport function setAgentEnv(agent: boolean) {\n if (agent) {\n process.env.SXYT_AGENT = 'true'\n process.env.SXY_TEST_RUNNER_AGENT = 'true'\n } else {\n delete process.env.SXYT_AGENT\n delete process.env.SXY_TEST_RUNNER_AGENT\n }\n}\n"]}
@@ -198,7 +198,7 @@ export function showTestResultsSummary(runTestResults, erroringTests, runStartTi
198
198
  ].filter(part => part !== '').join(', ') || 'test run failed')
199
199
  + ((stop.stopped) ? ', stopped at the first failure' : '');
200
200
  const code = (aborted) ? statusCodes.aborted : statusCodes.failed;
201
- const failures = failureEntries(Object.values(runTestResults), erroringTests);
201
+ const failures = failureEntries(Object.values(runTestResults), erroringTests, config.agentLineLengthLimit);
202
202
  writeStatusFile(config, code, description, [...summaryLines, ...failureLines(Object.values(runTestResults), erroringTests)], durationMs);
203
203
  // failures first, so the done line is a complete end of run marker
204
204
  for (const failure of failures)
@@ -1 +1 @@
1
- {"version":3,"file":"showTestResultsSummary.js","sourceRoot":"","sources":["../../../src/cli/lib/showTestResultsSummary.ts"],"names":[],"mappings":"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","sourcesContent":["\r\nimport { count } from 'sxy-lib/objects.js'\r\n\r\nimport type { FinalConfig, OutFn } from '../../types.js'\r\nimport type { TestExecutionFilters } from '../cliTypes.js'\r\nimport type { TestFile } from './loadTestFile.js'\r\nimport type { ReRunManageState } from './makeWatchRunState.js'\r\nimport type { TestResult } from './runTest.js'\r\nimport type { TestsResultsSummary } from './runTests.js'\r\nimport type { StopSignal } from './stopSignal.js'\r\nimport chalk from '../../packages/chalk.js'\r\nimport figures from '../../packages/figures.js'\r\nimport { agentDone, agentFailure } from './agentReport.js'\r\nimport { failureEntries } from './failureEntries.js'\r\nimport { failureLines } from './failureLines.js'\r\n//import { showFailures } from './showFailures.js'\r\nimport { showTestFileResult } from './showTestFileResult.js'\r\nimport { showTestLoadingError } from './showTestLoadingError.js'\r\nimport { writeStatusFile, statusCodes } from './statusFile.js'\r\nimport { out as mainOut } from '../../output.js'\r\nimport { timeProfile } from './timeProfiler.js'\r\n\r\n\r\n// the summary lines, minus the colouring, for the status file\r\nfunction joinPlain(...parts: string[]): string {\r\n return parts.filter(part => part !== '').join(' ')\r\n}\r\n\r\nfunction plural(count: number, noun: string, verb: string): string {\r\n if (count < 1) return ''\r\n return `${count} ${noun}${count === 1 ? '' : 's'} ${verb}`\r\n}\r\n\r\nexport function showTestResultsSummary(\r\n runTestResults: Record<string, TestResult>,\r\n erroringTests: Record<string, TestFile>,\r\n runStartTime: number,\r\n config: FinalConfig,\r\n runNumber: number,\r\n state: ReRunManageState,\r\n stop: StopSignal,\r\n filters: TestExecutionFilters,\r\n customOut?: OutFn,\r\n) {\r\n return timeProfile('show test run result summary', () => {\r\n \r\n const out = customOut ?? mainOut\r\n\r\n const testsResultsSummary: TestsResultsSummary = {\r\n total: 0,\r\n passes: 0,\r\n invalid: 0,\r\n describesTotal: 0,\r\n describesPasses: 0,\r\n describesInvalid: 0,\r\n itsTotal: 0,\r\n itsPasses: 0\r\n // itsInvalid: 0 // we don't check whether tests run any asserts (we don't control the assertion lib)\r\n }\r\n let describesThrownCount = 0\r\n\r\n for (const testFile in runTestResults) {\r\n const runTestResult = runTestResults[testFile]\r\n if (!runTestResult) continue\r\n\r\n testsResultsSummary.total += +(runTestResult.success !== null)\r\n testsResultsSummary.passes += +(runTestResult.success ?? false)\r\n testsResultsSummary.invalid += +(runTestResult.success === null)\r\n testsResultsSummary.describesTotal += runTestResult.describeResultsSummary.total\r\n testsResultsSummary.describesPasses += runTestResult.describeResultsSummary.passes\r\n testsResultsSummary.describesInvalid += runTestResult.describeResultsSummary.invalid\r\n testsResultsSummary.itsTotal += runTestResult.describeResultsSummary.itsTotal\r\n testsResultsSummary.itsPasses += runTestResult.describeResultsSummary.itsPasses\r\n describesThrownCount += runTestResult.describeResults\r\n .filter(describeResult => describeResult.error !== undefined)\r\n .length\r\n }\r\n\r\n const failedToLoadCount = count(erroringTests)\r\n testsResultsSummary.total += failedToLoadCount\r\n\r\n if (\r\n (filters.describe !== undefined || filters.it !== undefined)\r\n && testsResultsSummary.itsTotal === 0\r\n && failedToLoadCount === 0\r\n && describesThrownCount === 0\r\n ) {\r\n out(chalk.orange('No tests matched the describe/test filters.'))\r\n const durationMs = new Date().getTime() - runStartTime\r\n writeStatusFile(\r\n config,\r\n statusCodes.couldNotRun,\r\n 'no tests matched the describe/test filters',\r\n [],\r\n durationMs\r\n )\r\n agentDone(\r\n config, runNumber, statusCodes.couldNotRun,\r\n 'no tests matched the describe/test filters', testsResultsSummary, durationMs,\r\n state.failedTestFiles.size\r\n )\r\n return null\r\n }\r\n\r\n const allPassed = (\r\n testsResultsSummary.passes === testsResultsSummary.total\r\n && testsResultsSummary.describesPasses === testsResultsSummary.describesTotal\r\n && testsResultsSummary.itsPasses === testsResultsSummary.itsTotal\r\n )\r\n\r\n const failedTestsCount = testsResultsSummary.itsTotal - testsResultsSummary.itsPasses\r\n\r\n // a file that would not load, or a describe that threw, has no tests in itsTotal -\r\n // each counts as one unit on both sides\r\n const failuresN = failedTestsCount + describesThrownCount + failedToLoadCount\r\n const unitsN = testsResultsSummary.itsTotal + describesThrownCount + failedToLoadCount\r\n\r\n // the originals may have scrolled away on a long run, but past a point repeating\r\n // them buries the tallies - and when everything failed, they are the whole output already\r\n const showFailuresSection = config.restateFailures && failuresN > 0 && failuresN < unitsN\r\n && (failuresN <= 10 || failuresN <= 1.7 * unitsN ** 0.58)\r\n\r\n // the rule is separation enough, without the tallies' wider gap\r\n out((config.compact || showFailuresSection) ? '' : '\\n')\r\n\r\n if (allPassed) {\r\n out(chalk.mediumgreen(`${figures.tick}`))\r\n } else {\r\n //showFailures(out, Object.values(runTestResults), erroringTests)\r\n if (showFailuresSection) {\r\n \r\n const hr = '='.repeat((process.stdout.columns ?? 41) - 1)\r\n out(hr)\r\n out('Failures:')\r\n out(hr)\r\n\r\n for (const test of Object.values(erroringTests)) showTestLoadingError(config, test, out)\r\n for (const testResult of Object.values(runTestResults)) {\r\n if (testResult.success !== false) continue\r\n showTestFileResult(config, testResult, out, { failuresOnly: true })\r\n }\r\n out(config.compact ? '' : '\\n')\r\n }\r\n out(chalk.mediumred(`${figures.cross}`))\r\n }\r\n\r\n // number of tests successful\r\n const testsText = `Tests: ${testsResultsSummary.itsPasses}/${testsResultsSummary.itsTotal}`\r\n if (testsResultsSummary.itsPasses === testsResultsSummary.itsTotal) {\r\n if (testsResultsSummary.itsTotal === 0) {\r\n out(chalk.grey(`${testsText}`))\r\n } else {\r\n out(chalk.mediumgreen(`${testsText}`))\r\n }\r\n } else {\r\n out(chalk.mediumred(`${testsText}`))\r\n }\r\n\r\n // number of items successful\r\n const describesText = `Items: ${testsResultsSummary.describesPasses}/${testsResultsSummary.describesTotal}`\r\n const invalidDescribesPlain = (testsResultsSummary.describesInvalid >= 1)\r\n ? (testsResultsSummary.describesInvalid === 1)\r\n ? '(+1 describe without tests)'\r\n : `(+${testsResultsSummary.describesInvalid} describes without tests)`\r\n : ''\r\n const describesThrownPlain = (describesThrownCount >= 1)\r\n ? (describesThrownCount === 1)\r\n ? '(1 describe errored)'\r\n : `(${describesThrownCount} describes errored)`\r\n : ''\r\n const describesDetailsText = [\r\n chalk.mediumred(describesThrownPlain), chalk.grey(invalidDescribesPlain)\r\n ]\r\n .filter(text => text !== '')\r\n .join(' ')\r\n const describesDetailsSuffix = describesDetailsText === '' ? '' : ` ${describesDetailsText}`\r\n if (testsResultsSummary.describesPasses === testsResultsSummary.describesTotal) {\r\n if (testsResultsSummary.describesTotal === 0) {\r\n out(chalk.grey(`${describesText}`) + describesDetailsSuffix)\r\n } else {\r\n out(chalk.mediumgreen(`${describesText}`) + describesDetailsSuffix)\r\n }\r\n } else {\r\n out(chalk.mediumred(`${describesText}`) + describesDetailsSuffix)\r\n }\r\n\r\n // number of test files successful\r\n const testFilesText = `Test Files: ${testsResultsSummary.passes}/${testsResultsSummary.total}`\r\n const invalidTestFilesPlain = (testsResultsSummary.invalid >= 1)\r\n ? (testsResultsSummary.invalid === 1)\r\n ? '(+1 file without tests)'\r\n : `(+${testsResultsSummary.invalid} files without tests)`\r\n : ''\r\n const failedToLoadPlain = (failedToLoadCount >= 1)\r\n ? (failedToLoadCount === 1)\r\n ? '(1 file failed to load, or errored)'\r\n : `(${failedToLoadCount} files failed to load, or errored)`\r\n : ''\r\n const testFilesDetailsText = [\r\n chalk.mediumred(failedToLoadPlain), chalk.grey(invalidTestFilesPlain)\r\n ]\r\n .filter(text => text !== '')\r\n .join(' ')\r\n const testFilesDetailsSuffix = testFilesDetailsText === '' ? '' : ` ${testFilesDetailsText}`\r\n if (testsResultsSummary.passes === testsResultsSummary.total) {\r\n if (testsResultsSummary.describesTotal === 0) {\r\n out(chalk.grey(`${testFilesText}`) + testFilesDetailsSuffix)\r\n } else {\r\n out(chalk.mediumgreen(`${testFilesText}`) + testFilesDetailsSuffix)\r\n }\r\n } else {\r\n out(chalk.mediumred(`${testFilesText}`) + testFilesDetailsSuffix)\r\n }\r\n\r\n // the tallies only cover what ran, so say the run was cut short - otherwise\r\n // \"Tests: 0/1\" reads as a one test suite\r\n const stoppedPlain = (stop.stopped)\r\n ? 'stopped at the first failure (failFast)'\r\n : ''\r\n if (stoppedPlain !== '') out(chalk.orange(stoppedPlain))\r\n\r\n const summaryLines = [\r\n testsText,\r\n joinPlain(describesText, describesThrownPlain, invalidDescribesPlain),\r\n joinPlain(testFilesText, failedToLoadPlain, invalidTestFilesPlain),\r\n ...(stoppedPlain === '') ? [] : [stoppedPlain]\r\n ]\r\n\r\n const durationMs = new Date().getTime() - runStartTime\r\n\r\n if (allPassed) {\r\n writeStatusFile(\r\n config, statusCodes.passed, 'all tests passed', summaryLines, durationMs\r\n )\r\n agentDone(\r\n config, runNumber, statusCodes.passed, 'all tests passed',\r\n testsResultsSummary, durationMs, state.failedTestFiles.size\r\n )\r\n } else {\r\n const abortedFiles = Object.keys(erroringTests)\r\n\r\n // a file that would not load, or a describe that threw, means the run died\r\n // partway - a different problem from tests that ran and failed\r\n const aborted = abortedFiles.length > 0 || describesThrownCount > 0\r\n\r\n const description = ([\r\n plural(abortedFiles.length, 'test file', 'failed to load or errored'),\r\n plural(describesThrownCount, 'describe', 'errored'),\r\n plural(failedTestsCount, 'test', 'failed')\r\n ].filter(part => part !== '').join(', ') || 'test run failed')\r\n + ((stop.stopped) ? ', stopped at the first failure' : '')\r\n\r\n const code = (aborted) ? statusCodes.aborted : statusCodes.failed\r\n const failures = failureEntries(Object.values(runTestResults), erroringTests)\r\n\r\n writeStatusFile(\r\n config,\r\n code,\r\n description,\r\n [...summaryLines, ...failureLines(Object.values(runTestResults), erroringTests)],\r\n durationMs\r\n )\r\n\r\n // failures first, so the done line is a complete end of run marker\r\n for (const failure of failures) agentFailure(config, runNumber, failure)\r\n agentDone(\r\n config, runNumber, code, description, testsResultsSummary, durationMs,\r\n state.failedTestFiles.size\r\n )\r\n }\r\n\r\n // full success?\r\n // true/false gets returned to the caller of runTests()\r\n return allPassed\r\n })\r\n}\r\n"]}
1
+ {"version":3,"file":"showTestResultsSummary.js","sourceRoot":"","sources":["../../../src/cli/lib/showTestResultsSummary.ts"],"names":[],"mappings":"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","sourcesContent":["\r\nimport { count } from 'sxy-lib/objects.js'\r\n\r\nimport type { FinalConfig, OutFn } from '../../types.js'\r\nimport type { TestExecutionFilters } from '../cliTypes.js'\r\nimport type { TestFile } from './loadTestFile.js'\r\nimport type { ReRunManageState } from './makeWatchRunState.js'\r\nimport type { TestResult } from './runTest.js'\r\nimport type { TestsResultsSummary } from './runTests.js'\r\nimport type { StopSignal } from './stopSignal.js'\r\nimport chalk from '../../packages/chalk.js'\r\nimport figures from '../../packages/figures.js'\r\nimport { agentDone, agentFailure } from './agentReport.js'\r\nimport { failureEntries } from './failureEntries.js'\r\nimport { failureLines } from './failureLines.js'\r\n//import { showFailures } from './showFailures.js'\r\nimport { showTestFileResult } from './showTestFileResult.js'\r\nimport { showTestLoadingError } from './showTestLoadingError.js'\r\nimport { writeStatusFile, statusCodes } from './statusFile.js'\r\nimport { out as mainOut } from '../../output.js'\r\nimport { timeProfile } from './timeProfiler.js'\r\n\r\n\r\n// the summary lines, minus the colouring, for the status file\r\nfunction joinPlain(...parts: string[]): string {\r\n return parts.filter(part => part !== '').join(' ')\r\n}\r\n\r\nfunction plural(count: number, noun: string, verb: string): string {\r\n if (count < 1) return ''\r\n return `${count} ${noun}${count === 1 ? '' : 's'} ${verb}`\r\n}\r\n\r\nexport function showTestResultsSummary(\r\n runTestResults: Record<string, TestResult>,\r\n erroringTests: Record<string, TestFile>,\r\n runStartTime: number,\r\n config: FinalConfig,\r\n runNumber: number,\r\n state: ReRunManageState,\r\n stop: StopSignal,\r\n filters: TestExecutionFilters,\r\n customOut?: OutFn,\r\n) {\r\n return timeProfile('show test run result summary', () => {\r\n \r\n const out = customOut ?? mainOut\r\n\r\n const testsResultsSummary: TestsResultsSummary = {\r\n total: 0,\r\n passes: 0,\r\n invalid: 0,\r\n describesTotal: 0,\r\n describesPasses: 0,\r\n describesInvalid: 0,\r\n itsTotal: 0,\r\n itsPasses: 0\r\n // itsInvalid: 0 // we don't check whether tests run any asserts (we don't control the assertion lib)\r\n }\r\n let describesThrownCount = 0\r\n\r\n for (const testFile in runTestResults) {\r\n const runTestResult = runTestResults[testFile]\r\n if (!runTestResult) continue\r\n\r\n testsResultsSummary.total += +(runTestResult.success !== null)\r\n testsResultsSummary.passes += +(runTestResult.success ?? false)\r\n testsResultsSummary.invalid += +(runTestResult.success === null)\r\n testsResultsSummary.describesTotal += runTestResult.describeResultsSummary.total\r\n testsResultsSummary.describesPasses += runTestResult.describeResultsSummary.passes\r\n testsResultsSummary.describesInvalid += runTestResult.describeResultsSummary.invalid\r\n testsResultsSummary.itsTotal += runTestResult.describeResultsSummary.itsTotal\r\n testsResultsSummary.itsPasses += runTestResult.describeResultsSummary.itsPasses\r\n describesThrownCount += runTestResult.describeResults\r\n .filter(describeResult => describeResult.error !== undefined)\r\n .length\r\n }\r\n\r\n const failedToLoadCount = count(erroringTests)\r\n testsResultsSummary.total += failedToLoadCount\r\n\r\n if (\r\n (filters.describe !== undefined || filters.it !== undefined)\r\n && testsResultsSummary.itsTotal === 0\r\n && failedToLoadCount === 0\r\n && describesThrownCount === 0\r\n ) {\r\n out(chalk.orange('No tests matched the describe/test filters.'))\r\n const durationMs = new Date().getTime() - runStartTime\r\n writeStatusFile(\r\n config,\r\n statusCodes.couldNotRun,\r\n 'no tests matched the describe/test filters',\r\n [],\r\n durationMs\r\n )\r\n agentDone(\r\n config, runNumber, statusCodes.couldNotRun,\r\n 'no tests matched the describe/test filters', testsResultsSummary, durationMs,\r\n state.failedTestFiles.size\r\n )\r\n return null\r\n }\r\n\r\n const allPassed = (\r\n testsResultsSummary.passes === testsResultsSummary.total\r\n && testsResultsSummary.describesPasses === testsResultsSummary.describesTotal\r\n && testsResultsSummary.itsPasses === testsResultsSummary.itsTotal\r\n )\r\n\r\n const failedTestsCount = testsResultsSummary.itsTotal - testsResultsSummary.itsPasses\r\n\r\n // a file that would not load, or a describe that threw, has no tests in itsTotal -\r\n // each counts as one unit on both sides\r\n const failuresN = failedTestsCount + describesThrownCount + failedToLoadCount\r\n const unitsN = testsResultsSummary.itsTotal + describesThrownCount + failedToLoadCount\r\n\r\n // the originals may have scrolled away on a long run, but past a point repeating\r\n // them buries the tallies - and when everything failed, they are the whole output already\r\n const showFailuresSection = config.restateFailures && failuresN > 0 && failuresN < unitsN\r\n && (failuresN <= 10 || failuresN <= 1.7 * unitsN ** 0.58)\r\n\r\n // the rule is separation enough, without the tallies' wider gap\r\n out((config.compact || showFailuresSection) ? '' : '\\n')\r\n\r\n if (allPassed) {\r\n out(chalk.mediumgreen(`${figures.tick}`))\r\n } else {\r\n //showFailures(out, Object.values(runTestResults), erroringTests)\r\n if (showFailuresSection) {\r\n \r\n const hr = '='.repeat((process.stdout.columns ?? 41) - 1)\r\n out(hr)\r\n out('Failures:')\r\n out(hr)\r\n\r\n for (const test of Object.values(erroringTests)) showTestLoadingError(config, test, out)\r\n for (const testResult of Object.values(runTestResults)) {\r\n if (testResult.success !== false) continue\r\n showTestFileResult(config, testResult, out, { failuresOnly: true })\r\n }\r\n out(config.compact ? '' : '\\n')\r\n }\r\n out(chalk.mediumred(`${figures.cross}`))\r\n }\r\n\r\n // number of tests successful\r\n const testsText = `Tests: ${testsResultsSummary.itsPasses}/${testsResultsSummary.itsTotal}`\r\n if (testsResultsSummary.itsPasses === testsResultsSummary.itsTotal) {\r\n if (testsResultsSummary.itsTotal === 0) {\r\n out(chalk.grey(`${testsText}`))\r\n } else {\r\n out(chalk.mediumgreen(`${testsText}`))\r\n }\r\n } else {\r\n out(chalk.mediumred(`${testsText}`))\r\n }\r\n\r\n // number of items successful\r\n const describesText = `Items: ${testsResultsSummary.describesPasses}/${testsResultsSummary.describesTotal}`\r\n const invalidDescribesPlain = (testsResultsSummary.describesInvalid >= 1)\r\n ? (testsResultsSummary.describesInvalid === 1)\r\n ? '(+1 describe without tests)'\r\n : `(+${testsResultsSummary.describesInvalid} describes without tests)`\r\n : ''\r\n const describesThrownPlain = (describesThrownCount >= 1)\r\n ? (describesThrownCount === 1)\r\n ? '(1 describe errored)'\r\n : `(${describesThrownCount} describes errored)`\r\n : ''\r\n const describesDetailsText = [\r\n chalk.mediumred(describesThrownPlain), chalk.grey(invalidDescribesPlain)\r\n ]\r\n .filter(text => text !== '')\r\n .join(' ')\r\n const describesDetailsSuffix = describesDetailsText === '' ? '' : ` ${describesDetailsText}`\r\n if (testsResultsSummary.describesPasses === testsResultsSummary.describesTotal) {\r\n if (testsResultsSummary.describesTotal === 0) {\r\n out(chalk.grey(`${describesText}`) + describesDetailsSuffix)\r\n } else {\r\n out(chalk.mediumgreen(`${describesText}`) + describesDetailsSuffix)\r\n }\r\n } else {\r\n out(chalk.mediumred(`${describesText}`) + describesDetailsSuffix)\r\n }\r\n\r\n // number of test files successful\r\n const testFilesText = `Test Files: ${testsResultsSummary.passes}/${testsResultsSummary.total}`\r\n const invalidTestFilesPlain = (testsResultsSummary.invalid >= 1)\r\n ? (testsResultsSummary.invalid === 1)\r\n ? '(+1 file without tests)'\r\n : `(+${testsResultsSummary.invalid} files without tests)`\r\n : ''\r\n const failedToLoadPlain = (failedToLoadCount >= 1)\r\n ? (failedToLoadCount === 1)\r\n ? '(1 file failed to load, or errored)'\r\n : `(${failedToLoadCount} files failed to load, or errored)`\r\n : ''\r\n const testFilesDetailsText = [\r\n chalk.mediumred(failedToLoadPlain), chalk.grey(invalidTestFilesPlain)\r\n ]\r\n .filter(text => text !== '')\r\n .join(' ')\r\n const testFilesDetailsSuffix = testFilesDetailsText === '' ? '' : ` ${testFilesDetailsText}`\r\n if (testsResultsSummary.passes === testsResultsSummary.total) {\r\n if (testsResultsSummary.describesTotal === 0) {\r\n out(chalk.grey(`${testFilesText}`) + testFilesDetailsSuffix)\r\n } else {\r\n out(chalk.mediumgreen(`${testFilesText}`) + testFilesDetailsSuffix)\r\n }\r\n } else {\r\n out(chalk.mediumred(`${testFilesText}`) + testFilesDetailsSuffix)\r\n }\r\n\r\n // the tallies only cover what ran, so say the run was cut short - otherwise\r\n // \"Tests: 0/1\" reads as a one test suite\r\n const stoppedPlain = (stop.stopped)\r\n ? 'stopped at the first failure (failFast)'\r\n : ''\r\n if (stoppedPlain !== '') out(chalk.orange(stoppedPlain))\r\n\r\n const summaryLines = [\r\n testsText,\r\n joinPlain(describesText, describesThrownPlain, invalidDescribesPlain),\r\n joinPlain(testFilesText, failedToLoadPlain, invalidTestFilesPlain),\r\n ...(stoppedPlain === '') ? [] : [stoppedPlain]\r\n ]\r\n\r\n const durationMs = new Date().getTime() - runStartTime\r\n\r\n if (allPassed) {\r\n writeStatusFile(\r\n config, statusCodes.passed, 'all tests passed', summaryLines, durationMs\r\n )\r\n agentDone(\r\n config, runNumber, statusCodes.passed, 'all tests passed',\r\n testsResultsSummary, durationMs, state.failedTestFiles.size\r\n )\r\n } else {\r\n const abortedFiles = Object.keys(erroringTests)\r\n\r\n // a file that would not load, or a describe that threw, means the run died\r\n // partway - a different problem from tests that ran and failed\r\n const aborted = abortedFiles.length > 0 || describesThrownCount > 0\r\n\r\n const description = ([\r\n plural(abortedFiles.length, 'test file', 'failed to load or errored'),\r\n plural(describesThrownCount, 'describe', 'errored'),\r\n plural(failedTestsCount, 'test', 'failed')\r\n ].filter(part => part !== '').join(', ') || 'test run failed')\r\n + ((stop.stopped) ? ', stopped at the first failure' : '')\r\n\r\n const code = (aborted) ? statusCodes.aborted : statusCodes.failed\r\n const failures = failureEntries(\r\n Object.values(runTestResults), erroringTests, config.agentLineLengthLimit\r\n )\r\n\r\n writeStatusFile(\r\n config,\r\n code,\r\n description,\r\n [...summaryLines, ...failureLines(Object.values(runTestResults), erroringTests)],\r\n durationMs\r\n )\r\n\r\n // failures first, so the done line is a complete end of run marker\r\n for (const failure of failures) agentFailure(config, runNumber, failure)\r\n agentDone(\r\n config, runNumber, code, description, testsResultsSummary, durationMs,\r\n state.failedTestFiles.size\r\n )\r\n }\r\n\r\n // full success?\r\n // true/false gets returned to the caller of runTests()\r\n return allPassed\r\n })\r\n}\r\n"]}
@@ -14,6 +14,10 @@ export function validateConfig(config, customOut) {
14
14
  if (typeof config.agent !== 'boolean') {
15
15
  doError('Config error, config.agent should be a boolean');
16
16
  }
17
+ const limit = config.agentLineLengthLimit;
18
+ if (typeof limit !== 'number' || !(limit > 0) || !(Number.isInteger(limit) || limit === Infinity)) {
19
+ doError('Config error, config.agentLineLengthLimit should be a positive whole number or Infinity');
20
+ }
17
21
  if (config.execution === undefined) {
18
22
  doError('Config error, config.execution is not defined');
19
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"validateConfig.js","sourceRoot":"","sources":["../../../src/cli/lib/validateConfig.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,IAAI,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAGhD,MAAM,UAAU,cAAc,CAAC,MAAmB,EAAE,SAAiB;IACjE,MAAM,GAAG,GAAG,SAAS,IAAI,OAAO,CAAA;IAEhC,SAAS,OAAO,CAAC,OAAe;QAC5B,GAAG,CAAC,OAAO,CAAC,CAAA;QACZ,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAA;IAC5B,CAAC;IAED,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QACtC,OAAO,CAAC,kDAAkD,CAAC,CAAA;IAC/D,CAAC;IAED,IAAI,OAAO,MAAM,CAAC,eAAe,KAAK,SAAS,EAAE,CAAC;QAC9C,OAAO,CAAC,0DAA0D,CAAC,CAAA;IACvE,CAAC;IAED,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QACpC,OAAO,CAAC,gDAAgD,CAAC,CAAA;IAC7D,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACjC,OAAO,CAAC,+CAA+C,CAAC,CAAA;IAC5D,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,KAAK,UAAU,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,KAAK,YAAY,EAAE,CAAC;QACnF,OAAO,CAAC,+EAA+E,CAAC,CAAA;IAC5F,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,CAAC,SAAS,KAAK,UAAU,IAAI,MAAM,CAAC,SAAS,CAAC,SAAS,KAAK,YAAY,EAAE,CAAC;QAC3F,OAAO,CAAC,mFAAmF,CAAC,CAAA;IAChG,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,KAAK,UAAU,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,KAAK,YAAY,EAAE,CAAC;QACnF,OAAO,CAAC,+EAA+E,CAAC,CAAA;IAC5F,CAAC;IAED,IAAI,OAAO,MAAM,CAAC,KAAK,CAAC,oBAAoB,KAAK,SAAS,EAAE,CAAC;QACzD,OAAO,CAAC,qEAAqE,CAAC,CAAA;IAClF,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,CAAA;IAC1C,IAAI,UAAU,KAAK,KAAK,IAAI,CAAC,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,EAAE,CAAC,EAAE,CAAC;QAChF,OAAO,CAAC,sEAAsE,CAAC,CAAA;IACnF,CAAC;IAED,IAAI,OAAO,MAAM,CAAC,KAAK,CAAC,oBAAoB,KAAK,SAAS,EAAE,CAAC;QACzD,OAAO,CAAC,qEAAqE,CAAC,CAAA;IAClF,CAAC;AACL,CAAC","sourcesContent":["\nimport type { FinalConfig, OutFn } from '../../types.js'\nimport { out as mainOut } from '../../output.js'\n\n\nexport function validateConfig(config: FinalConfig, customOut?: OutFn): void {\n const out = customOut ?? mainOut\n\n function doError(message: string): never {\n out(message)\n throw new Error(message)\n }\n\n if (typeof config.compact !== 'boolean') {\n doError('Config error, config.compact should be a boolean')\n }\n\n if (typeof config.restateFailures !== 'boolean') {\n doError('Config error, config.restateFailures should be a boolean')\n }\n\n if (typeof config.agent !== 'boolean') {\n doError('Config error, config.agent should be a boolean')\n }\n\n if (config.execution === undefined) {\n doError('Config error, config.execution is not defined')\n }\n\n if (config.execution.files !== 'parallel' && config.execution.files !== 'sequential') {\n doError('Config error, config.execution.files should be \\'parallel\\' or \\'sequential\\'')\n }\n\n if (config.execution.describes !== 'parallel' && config.execution.describes !== 'sequential') {\n doError('Config error, config.execution.describes should be \\'parallel\\' or \\'sequential\\'')\n }\n\n if (config.execution.tests !== 'parallel' && config.execution.tests !== 'sequential') {\n doError('Config error, config.execution.tests should be \\'parallel\\' or \\'sequential\\'')\n }\n\n if (typeof config.watch.ttyActionsOnKeypress !== 'boolean') {\n doError('Config error, config.watch.ttyActionsOnKeypress should be a boolean')\n }\n\n const statusFile = config.watch.statusFile\n if (statusFile !== false && (typeof statusFile !== 'string' || statusFile === '')) {\n doError('Config error, config.watch.statusFile should be false or a file path')\n }\n\n if (typeof config.watch.dependencyEvaluation !== 'boolean') {\n doError('Config error, config.watch.dependencyEvaluation should be a boolean')\n }\n}\n"]}
1
+ {"version":3,"file":"validateConfig.js","sourceRoot":"","sources":["../../../src/cli/lib/validateConfig.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,IAAI,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAGhD,MAAM,UAAU,cAAc,CAAC,MAAmB,EAAE,SAAiB;IACjE,MAAM,GAAG,GAAG,SAAS,IAAI,OAAO,CAAA;IAEhC,SAAS,OAAO,CAAC,OAAe;QAC5B,GAAG,CAAC,OAAO,CAAC,CAAA;QACZ,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAA;IAC5B,CAAC;IAED,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QACtC,OAAO,CAAC,kDAAkD,CAAC,CAAA;IAC/D,CAAC;IAED,IAAI,OAAO,MAAM,CAAC,eAAe,KAAK,SAAS,EAAE,CAAC;QAC9C,OAAO,CAAC,0DAA0D,CAAC,CAAA;IACvE,CAAC;IAED,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QACpC,OAAO,CAAC,gDAAgD,CAAC,CAAA;IAC7D,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,oBAAoB,CAAA;IACzC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,QAAQ,CAAC,EAAE,CAAC;QAChG,OAAO,CAAC,yFAAyF,CAAC,CAAA;IACtG,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACjC,OAAO,CAAC,+CAA+C,CAAC,CAAA;IAC5D,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,KAAK,UAAU,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,KAAK,YAAY,EAAE,CAAC;QACnF,OAAO,CAAC,+EAA+E,CAAC,CAAA;IAC5F,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,CAAC,SAAS,KAAK,UAAU,IAAI,MAAM,CAAC,SAAS,CAAC,SAAS,KAAK,YAAY,EAAE,CAAC;QAC3F,OAAO,CAAC,mFAAmF,CAAC,CAAA;IAChG,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,KAAK,UAAU,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,KAAK,YAAY,EAAE,CAAC;QACnF,OAAO,CAAC,+EAA+E,CAAC,CAAA;IAC5F,CAAC;IAED,IAAI,OAAO,MAAM,CAAC,KAAK,CAAC,oBAAoB,KAAK,SAAS,EAAE,CAAC;QACzD,OAAO,CAAC,qEAAqE,CAAC,CAAA;IAClF,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,CAAA;IAC1C,IAAI,UAAU,KAAK,KAAK,IAAI,CAAC,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,EAAE,CAAC,EAAE,CAAC;QAChF,OAAO,CAAC,sEAAsE,CAAC,CAAA;IACnF,CAAC;IAED,IAAI,OAAO,MAAM,CAAC,KAAK,CAAC,oBAAoB,KAAK,SAAS,EAAE,CAAC;QACzD,OAAO,CAAC,qEAAqE,CAAC,CAAA;IAClF,CAAC;AACL,CAAC","sourcesContent":["\nimport type { FinalConfig, OutFn } from '../../types.js'\nimport { out as mainOut } from '../../output.js'\n\n\nexport function validateConfig(config: FinalConfig, customOut?: OutFn): void {\n const out = customOut ?? mainOut\n\n function doError(message: string): never {\n out(message)\n throw new Error(message)\n }\n\n if (typeof config.compact !== 'boolean') {\n doError('Config error, config.compact should be a boolean')\n }\n\n if (typeof config.restateFailures !== 'boolean') {\n doError('Config error, config.restateFailures should be a boolean')\n }\n\n if (typeof config.agent !== 'boolean') {\n doError('Config error, config.agent should be a boolean')\n }\n\n const limit = config.agentLineLengthLimit\n if (typeof limit !== 'number' || !(limit > 0) || !(Number.isInteger(limit) || limit === Infinity)) {\n doError('Config error, config.agentLineLengthLimit should be a positive whole number or Infinity')\n }\n\n if (config.execution === undefined) {\n doError('Config error, config.execution is not defined')\n }\n\n if (config.execution.files !== 'parallel' && config.execution.files !== 'sequential') {\n doError('Config error, config.execution.files should be \\'parallel\\' or \\'sequential\\'')\n }\n\n if (config.execution.describes !== 'parallel' && config.execution.describes !== 'sequential') {\n doError('Config error, config.execution.describes should be \\'parallel\\' or \\'sequential\\'')\n }\n\n if (config.execution.tests !== 'parallel' && config.execution.tests !== 'sequential') {\n doError('Config error, config.execution.tests should be \\'parallel\\' or \\'sequential\\'')\n }\n\n if (typeof config.watch.ttyActionsOnKeypress !== 'boolean') {\n doError('Config error, config.watch.ttyActionsOnKeypress should be a boolean')\n }\n\n const statusFile = config.watch.statusFile\n if (statusFile !== false && (typeof statusFile !== 'string' || statusFile === '')) {\n doError('Config error, config.watch.statusFile should be false or a file path')\n }\n\n if (typeof config.watch.dependencyEvaluation !== 'boolean') {\n doError('Config error, config.watch.dependencyEvaluation should be a boolean')\n }\n}\n"]}
package/dist/cli/once.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import chalk from '../packages/chalk.js';
2
2
  import { packageName, configFileNames } from '../config.js';
3
3
  import { out, log } from '../output.js';
4
- import { setEnv } from './lib/setEnv.js';
4
+ import { setEnv, setAgentEnv } 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'
@@ -93,6 +93,7 @@ export async function once() {
93
93
  else if (config.agent)
94
94
  agentInit(true); // set by the config: announced once it has loaded
95
95
  agentMode = config.agent;
96
+ setAgentEnv(agentMode);
96
97
  agentSetRunReason('once');
97
98
  const runsOut = (agentMode) ? agentSilentOut : undefined;
98
99
  agentOut(chalk.brightblue `[${packageName}]...`);
@@ -1 +1 @@
1
- {"version":3,"file":"once.js","sourceRoot":"","sources":["../../src/cli/once.ts"],"names":[],"mappings":"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","sourcesContent":["\nimport type { OutFn } from '../types.js'\nimport type { AllowedArguments } from './cliTypes.js'\nimport type { Concurrency } from './lib/runTests.js'\nimport chalk from '../packages/chalk.js'\nimport { packageName, configFileNames } from '../config.js'\nimport { out, log } from '../output.js'\nimport { setEnv } from './lib/setEnv.js'\nimport { findingTestsMessage } from './lib/findingTestsMessage.js'\nimport { foundTestsMessage } from './lib/foundTestsMessage.js'\n//import { isTest } from './lib/isTest.js'\nimport { exitCodes } from './lib/exitCodes.js'\nimport { alwaysCacheBust } from './lib/alwaysCacheBust.js'\n\n\nexport async function once(): Promise<void> {\n const startTime = new Date().getTime()\n\n const { parseCommandLineArguments } = await import('./lib/parseCommandLineArguments.js')\n const allowedClArguments: AllowedArguments = {\n config: {\n flag: 'c',\n hasValue: true\n },\n 'test-files': {\n flag: 't',\n hasValue: true,\n isGlob: true\n },\n filter: {\n flag: 'f',\n hasValue: true,\n isGlob: true\n },\n 'filter-it': {\n flag: 'i',\n hasValue: true\n },\n 'filter-describe': {\n flag: 'd',\n hasValue: true\n },\n 'fail-fast': {\n flag: 'x',\n hasValue: false\n },\n 'agent': {\n hasValue: false\n },\n 'compact': {\n hasValue: false\n }\n }\n const clArguments = parseCommandLineArguments(allowedClArguments)\n //debug('clArguments', clArguments)\n\n // agent mode owns stdout: the usual per-test output is routed into a sink, leaving the\n // failures and the summary. Under the flag, announced before the config loads, as in watch mode.\n const agentFlag = clArguments.agent === true\n const {\n agentInit, agentFound, agentRunStart, agentDone, agentSetRunReason, agentSilentOut\n } = await import('./lib/agentReport.js')\n agentInit(agentFlag)\n // the config can still turn agent mode on, so this is settled once it has loaded\n let agentMode = agentFlag\n const agentOut: OutFn = (...texts) => { if (!agentMode) out(...texts) }\n\n setEnv()\n\n const { loadConfig } = await import('./lib/loadConfig.js')\n const userConfig = (typeof clArguments.config === 'string')\n ? await loadConfig(clArguments.config)\n : await loadConfig()\n\n if ('test-files' in clArguments) {\n const testFilesPattern = clArguments['test-files']\n if (typeof testFilesPattern !== 'string' || testFilesPattern === '') {\n throw new Error('No pattern specified for --test-files or -t argument')\n }\n //console.log('Looking for tests using pattern: ' + testFilesPattern) // eslint-disable-line no-console\n userConfig.tests = testFilesPattern\n }\n\n if ('filter' in clArguments) {\n const filter = clArguments.filter\n if (typeof filter !== 'string' || filter === '') {\n throw new Error('No pattern specified for --filter or -f argument')\n }\n //console.log('Filtering tests using pattern: ' + filter) // eslint-disable-line no-console\n userConfig.testsFilter = filter\n }\n\n const filterIt = clArguments['filter-it']\n const filterDescribe = clArguments['filter-describe']\n if (filterIt === true || filterIt === '') throw new Error('No substring specified for --filter-it')\n if (filterDescribe === true || filterDescribe === '') {\n throw new Error('No substring specified for --filter-describe')\n }\n\n const { applyConfigDefaults } = await import('./lib/applyConfigDefaults.js')\n const config = applyConfigDefaults(userConfig)\n // the flag is the only source: assigned rather than or'd, so a config file cannot\n // silently truncate every run\n config.failFast = clArguments['fail-fast'] === true\n if (agentFlag) config.agent = true\n else if (config.agent) agentInit(true) // set by the config: announced once it has loaded\n agentMode = config.agent\n agentSetRunReason('once')\n const runsOut = (agentMode) ? agentSilentOut : undefined\n agentOut(chalk.brightblue`[${packageName}]...`)\n if (clArguments.compact === true) config.compact = true\n\n const { validateConfig } = await import('./lib/validateConfig.js')\n validateConfig(config)\n\n //console.log('run setup')\n //console.log(util.inspect(config))\n const { doUserSetup } = await import('./lib/doUserSetup.js')\n await doUserSetup(config, agentOut)\n //console.log('ran setup')\n \n agentOut(chalk.brightblue(findingTestsMessage(config)))\n const { findTestFiles } = await import('./lib/findTestFiles.js')\n const testFiles = await findTestFiles(config)\n agentFound(config, testFiles.size)\n\n if (testFiles.size === 0) {\n agentOut(chalk.mediumred(`[${packageName}] Found no tests.`\n + '\\nCreate tests matching the patterns, '\n + `\\nor set new patterns in ${configFileNames.map(x => `${x}.js/cjs/mjs`).join(' or ')}`))\n\n const endTime = new Date().getTime()\n const time = endTime - startTime\n agentOut(chalk.brightblue(`[${packageName}] time: ${time.toLocaleString()}ms`))\n\n // reported as a run, so a reader waiting on a done line always gets one\n const { statusCodes } = await import('./lib/statusFile.js')\n const run = agentRunStart(config, 0)\n agentDone(config, run, statusCodes.couldNotRun, 'no test files found', null, time, 0)\n\n // setup has already run by this point, so teardown must run too, or its side\n // effects are left behind\n const { doUserTeardown } = await import('./lib/doUserTeardown.js')\n await doUserTeardown(config)\n\n process.exit(exitCodes.noTestFiles)\n }\n\n agentOut(chalk.brightblue(foundTestsMessage(testFiles.size)))\n\n const concurrency: Concurrency = { limit: -1 }\n\n process.setSourceMapsEnabled(true) // enable source mapping\n \n // testFiles.size is guaranteed non-zero here - the no-tests case exited above\n const { runTests } = await import('./lib/runTests.js')\n if (!agentMode) log(chalk.brightblue`running tests...`)\n const testsResult = await runTests(\n config, testFiles,\n undefined,\n concurrency,\n (alwaysCacheBust) ? 'refresh' : 'cached',\n runsOut,\n {\n it: filterIt,\n describe: filterDescribe\n }\n )\n // a distinct code from noTestFiles, so callers can tell \"no test file matched the\n // pattern\" from \"the files matched but the filters selected nothing in them\"\n const exitCode = (testsResult === null)\n ? exitCodes.noMatchingTests\n : (testsResult) ? exitCodes.passed : exitCodes.testErrors\n\n const time = new Date().getTime() - startTime\n agentOut(chalk.grey`\\n${time.toLocaleString()}ms\\n`)\n\n const { doUserTeardown } = await import('./lib/doUserTeardown.js')\n await doUserTeardown(config)\n\n process.exit(exitCode)\n}\n"]}
1
+ {"version":3,"file":"once.js","sourceRoot":"","sources":["../../src/cli/once.ts"],"names":[],"mappings":"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","sourcesContent":["\nimport type { OutFn } from '../types.js'\nimport type { AllowedArguments } from './cliTypes.js'\nimport type { Concurrency } from './lib/runTests.js'\nimport chalk from '../packages/chalk.js'\nimport { packageName, configFileNames } from '../config.js'\nimport { out, log } from '../output.js'\nimport { setEnv, setAgentEnv } from './lib/setEnv.js'\nimport { findingTestsMessage } from './lib/findingTestsMessage.js'\nimport { foundTestsMessage } from './lib/foundTestsMessage.js'\n//import { isTest } from './lib/isTest.js'\nimport { exitCodes } from './lib/exitCodes.js'\nimport { alwaysCacheBust } from './lib/alwaysCacheBust.js'\n\n\nexport async function once(): Promise<void> {\n const startTime = new Date().getTime()\n\n const { parseCommandLineArguments } = await import('./lib/parseCommandLineArguments.js')\n const allowedClArguments: AllowedArguments = {\n config: {\n flag: 'c',\n hasValue: true\n },\n 'test-files': {\n flag: 't',\n hasValue: true,\n isGlob: true\n },\n filter: {\n flag: 'f',\n hasValue: true,\n isGlob: true\n },\n 'filter-it': {\n flag: 'i',\n hasValue: true\n },\n 'filter-describe': {\n flag: 'd',\n hasValue: true\n },\n 'fail-fast': {\n flag: 'x',\n hasValue: false\n },\n 'agent': {\n hasValue: false\n },\n 'compact': {\n hasValue: false\n }\n }\n const clArguments = parseCommandLineArguments(allowedClArguments)\n //debug('clArguments', clArguments)\n\n // agent mode owns stdout: the usual per-test output is routed into a sink, leaving the\n // failures and the summary. Under the flag, announced before the config loads, as in watch mode.\n const agentFlag = clArguments.agent === true\n const {\n agentInit, agentFound, agentRunStart, agentDone, agentSetRunReason, agentSilentOut\n } = await import('./lib/agentReport.js')\n agentInit(agentFlag)\n // the config can still turn agent mode on, so this is settled once it has loaded\n let agentMode = agentFlag\n const agentOut: OutFn = (...texts) => { if (!agentMode) out(...texts) }\n\n setEnv()\n\n const { loadConfig } = await import('./lib/loadConfig.js')\n const userConfig = (typeof clArguments.config === 'string')\n ? await loadConfig(clArguments.config)\n : await loadConfig()\n\n if ('test-files' in clArguments) {\n const testFilesPattern = clArguments['test-files']\n if (typeof testFilesPattern !== 'string' || testFilesPattern === '') {\n throw new Error('No pattern specified for --test-files or -t argument')\n }\n //console.log('Looking for tests using pattern: ' + testFilesPattern) // eslint-disable-line no-console\n userConfig.tests = testFilesPattern\n }\n\n if ('filter' in clArguments) {\n const filter = clArguments.filter\n if (typeof filter !== 'string' || filter === '') {\n throw new Error('No pattern specified for --filter or -f argument')\n }\n //console.log('Filtering tests using pattern: ' + filter) // eslint-disable-line no-console\n userConfig.testsFilter = filter\n }\n\n const filterIt = clArguments['filter-it']\n const filterDescribe = clArguments['filter-describe']\n if (filterIt === true || filterIt === '') throw new Error('No substring specified for --filter-it')\n if (filterDescribe === true || filterDescribe === '') {\n throw new Error('No substring specified for --filter-describe')\n }\n\n const { applyConfigDefaults } = await import('./lib/applyConfigDefaults.js')\n const config = applyConfigDefaults(userConfig)\n // the flag is the only source: assigned rather than or'd, so a config file cannot\n // silently truncate every run\n config.failFast = clArguments['fail-fast'] === true\n if (agentFlag) config.agent = true\n else if (config.agent) agentInit(true) // set by the config: announced once it has loaded\n agentMode = config.agent\n setAgentEnv(agentMode)\n agentSetRunReason('once')\n const runsOut = (agentMode) ? agentSilentOut : undefined\n agentOut(chalk.brightblue`[${packageName}]...`)\n if (clArguments.compact === true) config.compact = true\n\n const { validateConfig } = await import('./lib/validateConfig.js')\n validateConfig(config)\n\n //console.log('run setup')\n //console.log(util.inspect(config))\n const { doUserSetup } = await import('./lib/doUserSetup.js')\n await doUserSetup(config, agentOut)\n //console.log('ran setup')\n \n agentOut(chalk.brightblue(findingTestsMessage(config)))\n const { findTestFiles } = await import('./lib/findTestFiles.js')\n const testFiles = await findTestFiles(config)\n agentFound(config, testFiles.size)\n\n if (testFiles.size === 0) {\n agentOut(chalk.mediumred(`[${packageName}] Found no tests.`\n + '\\nCreate tests matching the patterns, '\n + `\\nor set new patterns in ${configFileNames.map(x => `${x}.js/cjs/mjs`).join(' or ')}`))\n\n const endTime = new Date().getTime()\n const time = endTime - startTime\n agentOut(chalk.brightblue(`[${packageName}] time: ${time.toLocaleString()}ms`))\n\n // reported as a run, so a reader waiting on a done line always gets one\n const { statusCodes } = await import('./lib/statusFile.js')\n const run = agentRunStart(config, 0)\n agentDone(config, run, statusCodes.couldNotRun, 'no test files found', null, time, 0)\n\n // setup has already run by this point, so teardown must run too, or its side\n // effects are left behind\n const { doUserTeardown } = await import('./lib/doUserTeardown.js')\n await doUserTeardown(config)\n\n process.exit(exitCodes.noTestFiles)\n }\n\n agentOut(chalk.brightblue(foundTestsMessage(testFiles.size)))\n\n const concurrency: Concurrency = { limit: -1 }\n\n process.setSourceMapsEnabled(true) // enable source mapping\n \n // testFiles.size is guaranteed non-zero here - the no-tests case exited above\n const { runTests } = await import('./lib/runTests.js')\n if (!agentMode) log(chalk.brightblue`running tests...`)\n const testsResult = await runTests(\n config, testFiles,\n undefined,\n concurrency,\n (alwaysCacheBust) ? 'refresh' : 'cached',\n runsOut,\n {\n it: filterIt,\n describe: filterDescribe\n }\n )\n // a distinct code from noTestFiles, so callers can tell \"no test file matched the\n // pattern\" from \"the files matched but the filters selected nothing in them\"\n const exitCode = (testsResult === null)\n ? exitCodes.noMatchingTests\n : (testsResult) ? exitCodes.passed : exitCodes.testErrors\n\n const time = new Date().getTime() - startTime\n agentOut(chalk.grey`\\n${time.toLocaleString()}ms\\n`)\n\n const { doUserTeardown } = await import('./lib/doUserTeardown.js')\n await doUserTeardown(config)\n\n process.exit(exitCode)\n}\n"]}
package/dist/cli/watch.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import chalk from '../packages/chalk.js';
2
2
  import { packageName } from '../config.js';
3
3
  import { out, debug } from '../output.js';
4
- import { setEnv } from './lib/setEnv.js';
4
+ import { setEnv, setAgentEnv } 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'
@@ -104,6 +104,7 @@ export async function doWatch(input = process.stdin) {
104
104
  else if (config.agent)
105
105
  agentInit(true); // set by the config: announced once it has loaded
106
106
  agentMode = config.agent;
107
+ setAgentEnv(agentMode);
107
108
  const runsOut = (agentMode) ? agentSilentOut : undefined;
108
109
  agentOut(chalk.brightblue `[${packageName}]...`);
109
110
  if (clArguments.compact === true)
@@ -1 +1 @@
1
- {"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/cli/watch.ts"],"names":[],"mappings":"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","sourcesContent":["\nimport type { DependencyTrees, OutFn } from '../types.js'\nimport type { AllowedArguments } from './cliTypes.js'\nimport type { Concurrency } from './lib/runTests.js'\nimport chalk from '../packages/chalk.js'\nimport { packageName } from '../config.js'\nimport { out, debug } from '../output.js'\nimport { setEnv } from './lib/setEnv.js'\nimport { findingTestsMessage } from './lib/findingTestsMessage.js'\nimport { foundTestsMessage } from './lib/foundTestsMessage.js'\n//import { isTest } from './lib/isTest.js'\nimport { makeRunManagerState } from './lib/makeWatchRunState.js'\nimport { makeReRunManager } from './lib/reRunManager.js'\nimport { alwaysCacheBust } from './lib/alwaysCacheBust.js'\n\n\nexport type StopFn = () => void\n\nexport async function watch(): Promise<void> {\n await doWatch()\n await new Promise<void>(() => {})\n}\n\n// input is injectable so tests never read the terminal their runner is also reading\nexport async function doWatch(input: NodeJS.ReadStream = process.stdin): Promise<StopFn> {\n const startTime = new Date().getTime()\n\n const { parseCommandLineArguments } = await import('./lib/parseCommandLineArguments.js')\n const allowedClArguments: AllowedArguments = {\n 'config': {\n flag: 'c',\n hasValue: true\n },\n 'test-files': {\n flag: 't',\n hasValue: true,\n isGlob: true\n },\n 'filter': {\n flag: 'f',\n hasValue: true,\n isGlob: true\n },\n 'filter-it': {\n flag: 'i',\n hasValue: true\n },\n 'filter-describe': {\n flag: 'd',\n hasValue: true\n },\n 'status-file': {\n flag: 's',\n hasValue: true\n },\n 'agent': {\n hasValue: false\n },\n 'compact': {\n hasValue: false\n }\n }\n const clArguments = parseCommandLineArguments(allowedClArguments)\n //debug('clArguments', clArguments)\n\n // agent mode owns stdout, so the banner and every later message below is routed through\n // agentOut - a sink in agent mode. Under the flag, init is announced before the config\n // loads, so a reader sees the process is alive even if startup is slow.\n const agentFlag = clArguments.agent === true\n const {\n agentInit, agentFound, agentRunStart, agentDone, agentWatching, agentSilentOut\n } = await import('./lib/agentReport.js')\n agentInit(agentFlag)\n // the config can still turn agent mode on, so this is settled once it has loaded\n let agentMode = agentFlag\n const agentOut: OutFn = (...texts) => { if (!agentMode) out(...texts) }\n\n setEnv()\n\n const stopFns: StopFn[] = []\n\n const { loadConfig } = await import('./lib/loadConfig.js')\n const userConfig = (typeof clArguments.config === 'string')\n ? await loadConfig(clArguments.config)\n : await loadConfig()\n\n if ('test-files' in clArguments) {\n const testFilesPattern = clArguments['test-files']\n if (typeof testFilesPattern !== 'string' || testFilesPattern === '') {\n throw new Error('No pattern specified for --test-files or -t argument')\n }\n userConfig.tests = testFilesPattern\n }\n\n if ('filter' in clArguments) {\n const filter = clArguments.filter\n if (typeof filter !== 'string' || filter === '') {\n throw new Error('No pattern specified for --filter or -f argument')\n }\n userConfig.testsFilter = filter\n }\n\n if ('status-file' in clArguments) {\n const statusFile = clArguments['status-file']\n if (typeof statusFile !== 'string' || statusFile === '') {\n throw new Error('No file path specified for --status-file or -s argument')\n }\n userConfig.watch = { ...userConfig.watch, statusFile }\n }\n\n const filterIt = clArguments['filter-it']\n const filterDescribe = clArguments['filter-describe']\n if (filterIt === true || filterIt === '') throw new Error('No substring specified for --filter-it')\n if (filterDescribe === true || filterDescribe === '') {\n throw new Error('No substring specified for --filter-describe')\n }\n const executionFilters = { it: filterIt, describe: filterDescribe }\n\n const { applyConfigDefaults } = await import('./lib/applyConfigDefaults.js')\n const config = applyConfigDefaults(userConfig)\n if (agentFlag) config.agent = true\n else if (config.agent) agentInit(true) // set by the config: announced once it has loaded\n agentMode = config.agent\n const runsOut = (agentMode) ? agentSilentOut : undefined\n agentOut(chalk.brightblue`[${packageName}]...`)\n if (clArguments.compact === true) config.compact = true\n // there is no watch flag for it, and a config file must not enable it here: a truncated\n // run would still report covers=all, and failing files would drop out of `failing`\n config.failFast = false\n\n // not silenced in agent mode - a config error is fatal, so losing the message is worse\n // than breaking the one-line-per-event contract\n const { validateConfig } = await import('./lib/validateConfig.js')\n validateConfig(config)\n\n // no run has finished yet, so the status file starts at -1 rather than stale\n const { resetStatusFile, statusCodes, writeStatusFile } = await import('./lib/statusFile.js')\n resetStatusFile(config)\n\n const { doUserSetup } = await import('./lib/doUserSetup.js')\n await doUserSetup(config, agentOut)\n\n // watch mode never reaches an end of its own, so teardown only gets a chance on the way\n // out. Registered here so it pairs with the setup above and covers the initial run too.\n const { doUserTeardown } = await import('./lib/doUserTeardown.js')\n const { registerShutdownHandlers } = await import('./lib/shutdown.js')\n \n const unregisterShutdownHandlers = registerShutdownHandlers(config, {\n teardown: doUserTeardown,\n exit: code => process.exit(code)\n })\n stopFns.push(unregisterShutdownHandlers)\n\n agentOut(chalk.brightblue(findingTestsMessage(config)))\n const { findTestFiles } = await import('./lib/findTestFiles.js')\n const testFiles = await findTestFiles(config)\n debug(testFiles)\n agentFound(config, testFiles.size)\n\n // global store of the dependencies of tests\n let dependencyTrees: DependencyTrees = {}\n // store failing tests so we can re-run them.\n const failingTests: string[] = []\n \n const concurrency: Concurrency = { limit: -1 }\n\n const reRunManager = makeReRunManager(\n null,\n makeRunManagerState({\n allTestFiles: testFiles,\n lastTestFiles: testFiles\n }),\n runsOut\n )\n\n process.setSourceMapsEnabled(true) // enable source mapping\n\n if (testFiles.size > 0) {\n agentOut(chalk.brightblue(foundTestsMessage(testFiles.size)))\n\n // the trees are only consulted to narrow a run, so with evaluation off building them\n // is pure cost - and it is the slowest part of startup on a large suite\n if (config.watch.dependencyEvaluation) {\n const { buildDependencyTrees } = await import('./lib/buildDependencyTrees.js')\n agentOut(chalk.brightblue`finding initial dependency trees...`)\n dependencyTrees = buildDependencyTrees(config, testFiles)\n }\n }\n\n // live before the first test runs, for two reasons. A change landing during the initial\n // run (a compiler emit, typically) is seen rather than lost. And the watcher starts on a\n // quiet loop: node-watch probes for native recursive support with a 200ms timeout, and a\n // loop busy running tests fails the probe, so it falls back to a sync walk of every\n // directory - which then starved the tests' own timers (a 10ms interval fired once in 45ms)\n const { watchFilesAndRunTests } = await import('./lib/watchFilesAndRunTests.js')\n const stopWatcher = await watchFilesAndRunTests(\n config,\n //testFiles,\n dependencyTrees,\n failingTests, // CHECK this should also be in state\n reRunManager,\n //watchRunState,\n runsOut,\n executionFilters\n )\n stopFns.push(stopWatcher)\n\n const { runTests } = await import('./lib/runTests.js')\n let initialTestRun: Promise<boolean | null> | null = null\n if (testFiles.size > 0) {\n if (config.watch.runAllOnStartup) {\n agentOut(chalk.brightblue`running initial tests...`)\n initialTestRun = runTests(\n config, testFiles,\n reRunManager,\n concurrency,\n (alwaysCacheBust) ? 'refresh' : 'cached',\n runsOut, executionFilters\n ).then(testsResult => {\n const time = new Date().getTime() - startTime\n //await new Promise((resolve) => setTimeout(resolve, 100))\n agentOut(chalk.grey`\\n${time.toLocaleString()}ms`)\n return testsResult\n })\n reRunManager.state.currentRun = initialTestRun\n }\n } else {\n agentOut(chalk.orange`no test files found`)\n writeStatusFile(config, statusCodes.couldNotRun, 'no test files found')\n // still reported as a run, so a reader waiting on a done line always gets one\n const run = agentRunStart(config, 0)\n agentDone(\n config, run, statusCodes.couldNotRun, 'no test files found',\n null, new Date().getTime() - startTime, 0\n )\n }\n\n // announced once the initial run is over, so `watching` marks a real milestone: startup is\n // complete and the watcher is live. A failed run is reported by listenToUser below.\n if (initialTestRun !== null) await initialTestRun.catch(() => null)\n\n agentOut(chalk.brightblue`watching...`)\n agentWatching(config, testFiles.size)\n\n const { listenToUser } = await import('./lib/listenToUser.js')\n const disposeTty = listenToUser(\n reRunManager,\n files => () => {\n return runTests(config, files, reRunManager, concurrency, 'refresh', runsOut, executionFilters)\n },\n config.watch.ttyActionsOnKeypress,\n initialTestRun,\n input,\n runsOut\n )\n stopFns.push(disposeTty)\n\n const dispose = () => {\n for (const stop of stopFns) {\n stop()\n }\n stopFns.length = 0 // Idempotencize\n }\n return dispose\n\n\n // (async () => {\n // await new Promise<void>(() => {})\n // })()\n //await new Promise<void>(() => {})\n}\n"]}
1
+ {"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/cli/watch.ts"],"names":[],"mappings":"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","sourcesContent":["\nimport type { DependencyTrees, OutFn } from '../types.js'\nimport type { AllowedArguments } from './cliTypes.js'\nimport type { Concurrency } from './lib/runTests.js'\nimport chalk from '../packages/chalk.js'\nimport { packageName } from '../config.js'\nimport { out, debug } from '../output.js'\nimport { setEnv, setAgentEnv } from './lib/setEnv.js'\nimport { findingTestsMessage } from './lib/findingTestsMessage.js'\nimport { foundTestsMessage } from './lib/foundTestsMessage.js'\n//import { isTest } from './lib/isTest.js'\nimport { makeRunManagerState } from './lib/makeWatchRunState.js'\nimport { makeReRunManager } from './lib/reRunManager.js'\nimport { alwaysCacheBust } from './lib/alwaysCacheBust.js'\n\n\nexport type StopFn = () => void\n\nexport async function watch(): Promise<void> {\n await doWatch()\n await new Promise<void>(() => {})\n}\n\n// input is injectable so tests never read the terminal their runner is also reading\nexport async function doWatch(input: NodeJS.ReadStream = process.stdin): Promise<StopFn> {\n const startTime = new Date().getTime()\n\n const { parseCommandLineArguments } = await import('./lib/parseCommandLineArguments.js')\n const allowedClArguments: AllowedArguments = {\n 'config': {\n flag: 'c',\n hasValue: true\n },\n 'test-files': {\n flag: 't',\n hasValue: true,\n isGlob: true\n },\n 'filter': {\n flag: 'f',\n hasValue: true,\n isGlob: true\n },\n 'filter-it': {\n flag: 'i',\n hasValue: true\n },\n 'filter-describe': {\n flag: 'd',\n hasValue: true\n },\n 'status-file': {\n flag: 's',\n hasValue: true\n },\n 'agent': {\n hasValue: false\n },\n 'compact': {\n hasValue: false\n }\n }\n const clArguments = parseCommandLineArguments(allowedClArguments)\n //debug('clArguments', clArguments)\n\n // agent mode owns stdout, so the banner and every later message below is routed through\n // agentOut - a sink in agent mode. Under the flag, init is announced before the config\n // loads, so a reader sees the process is alive even if startup is slow.\n const agentFlag = clArguments.agent === true\n const {\n agentInit, agentFound, agentRunStart, agentDone, agentWatching, agentSilentOut\n } = await import('./lib/agentReport.js')\n agentInit(agentFlag)\n // the config can still turn agent mode on, so this is settled once it has loaded\n let agentMode = agentFlag\n const agentOut: OutFn = (...texts) => { if (!agentMode) out(...texts) }\n\n setEnv()\n\n const stopFns: StopFn[] = []\n\n const { loadConfig } = await import('./lib/loadConfig.js')\n const userConfig = (typeof clArguments.config === 'string')\n ? await loadConfig(clArguments.config)\n : await loadConfig()\n\n if ('test-files' in clArguments) {\n const testFilesPattern = clArguments['test-files']\n if (typeof testFilesPattern !== 'string' || testFilesPattern === '') {\n throw new Error('No pattern specified for --test-files or -t argument')\n }\n userConfig.tests = testFilesPattern\n }\n\n if ('filter' in clArguments) {\n const filter = clArguments.filter\n if (typeof filter !== 'string' || filter === '') {\n throw new Error('No pattern specified for --filter or -f argument')\n }\n userConfig.testsFilter = filter\n }\n\n if ('status-file' in clArguments) {\n const statusFile = clArguments['status-file']\n if (typeof statusFile !== 'string' || statusFile === '') {\n throw new Error('No file path specified for --status-file or -s argument')\n }\n userConfig.watch = { ...userConfig.watch, statusFile }\n }\n\n const filterIt = clArguments['filter-it']\n const filterDescribe = clArguments['filter-describe']\n if (filterIt === true || filterIt === '') throw new Error('No substring specified for --filter-it')\n if (filterDescribe === true || filterDescribe === '') {\n throw new Error('No substring specified for --filter-describe')\n }\n const executionFilters = { it: filterIt, describe: filterDescribe }\n\n const { applyConfigDefaults } = await import('./lib/applyConfigDefaults.js')\n const config = applyConfigDefaults(userConfig)\n if (agentFlag) config.agent = true\n else if (config.agent) agentInit(true) // set by the config: announced once it has loaded\n agentMode = config.agent\n setAgentEnv(agentMode)\n const runsOut = (agentMode) ? agentSilentOut : undefined\n agentOut(chalk.brightblue`[${packageName}]...`)\n if (clArguments.compact === true) config.compact = true\n // there is no watch flag for it, and a config file must not enable it here: a truncated\n // run would still report covers=all, and failing files would drop out of `failing`\n config.failFast = false\n\n // not silenced in agent mode - a config error is fatal, so losing the message is worse\n // than breaking the one-line-per-event contract\n const { validateConfig } = await import('./lib/validateConfig.js')\n validateConfig(config)\n\n // no run has finished yet, so the status file starts at -1 rather than stale\n const { resetStatusFile, statusCodes, writeStatusFile } = await import('./lib/statusFile.js')\n resetStatusFile(config)\n\n const { doUserSetup } = await import('./lib/doUserSetup.js')\n await doUserSetup(config, agentOut)\n\n // watch mode never reaches an end of its own, so teardown only gets a chance on the way\n // out. Registered here so it pairs with the setup above and covers the initial run too.\n const { doUserTeardown } = await import('./lib/doUserTeardown.js')\n const { registerShutdownHandlers } = await import('./lib/shutdown.js')\n \n const unregisterShutdownHandlers = registerShutdownHandlers(config, {\n teardown: doUserTeardown,\n exit: code => process.exit(code)\n })\n stopFns.push(unregisterShutdownHandlers)\n\n agentOut(chalk.brightblue(findingTestsMessage(config)))\n const { findTestFiles } = await import('./lib/findTestFiles.js')\n const testFiles = await findTestFiles(config)\n debug(testFiles)\n agentFound(config, testFiles.size)\n\n // global store of the dependencies of tests\n let dependencyTrees: DependencyTrees = {}\n // store failing tests so we can re-run them.\n const failingTests: string[] = []\n \n const concurrency: Concurrency = { limit: -1 }\n\n const reRunManager = makeReRunManager(\n null,\n makeRunManagerState({\n allTestFiles: testFiles,\n lastTestFiles: testFiles\n }),\n runsOut\n )\n\n process.setSourceMapsEnabled(true) // enable source mapping\n\n if (testFiles.size > 0) {\n agentOut(chalk.brightblue(foundTestsMessage(testFiles.size)))\n\n // the trees are only consulted to narrow a run, so with evaluation off building them\n // is pure cost - and it is the slowest part of startup on a large suite\n if (config.watch.dependencyEvaluation) {\n const { buildDependencyTrees } = await import('./lib/buildDependencyTrees.js')\n agentOut(chalk.brightblue`finding initial dependency trees...`)\n dependencyTrees = buildDependencyTrees(config, testFiles)\n }\n }\n\n // live before the first test runs, for two reasons. A change landing during the initial\n // run (a compiler emit, typically) is seen rather than lost. And the watcher starts on a\n // quiet loop: node-watch probes for native recursive support with a 200ms timeout, and a\n // loop busy running tests fails the probe, so it falls back to a sync walk of every\n // directory - which then starved the tests' own timers (a 10ms interval fired once in 45ms)\n const { watchFilesAndRunTests } = await import('./lib/watchFilesAndRunTests.js')\n const stopWatcher = await watchFilesAndRunTests(\n config,\n //testFiles,\n dependencyTrees,\n failingTests, // CHECK this should also be in state\n reRunManager,\n //watchRunState,\n runsOut,\n executionFilters\n )\n stopFns.push(stopWatcher)\n\n const { runTests } = await import('./lib/runTests.js')\n let initialTestRun: Promise<boolean | null> | null = null\n if (testFiles.size > 0) {\n if (config.watch.runAllOnStartup) {\n agentOut(chalk.brightblue`running initial tests...`)\n initialTestRun = runTests(\n config, testFiles,\n reRunManager,\n concurrency,\n (alwaysCacheBust) ? 'refresh' : 'cached',\n runsOut, executionFilters\n ).then(testsResult => {\n const time = new Date().getTime() - startTime\n //await new Promise((resolve) => setTimeout(resolve, 100))\n agentOut(chalk.grey`\\n${time.toLocaleString()}ms`)\n return testsResult\n })\n reRunManager.state.currentRun = initialTestRun\n }\n } else {\n agentOut(chalk.orange`no test files found`)\n writeStatusFile(config, statusCodes.couldNotRun, 'no test files found')\n // still reported as a run, so a reader waiting on a done line always gets one\n const run = agentRunStart(config, 0)\n agentDone(\n config, run, statusCodes.couldNotRun, 'no test files found',\n null, new Date().getTime() - startTime, 0\n )\n }\n\n // announced once the initial run is over, so `watching` marks a real milestone: startup is\n // complete and the watcher is live. A failed run is reported by listenToUser below.\n if (initialTestRun !== null) await initialTestRun.catch(() => null)\n\n agentOut(chalk.brightblue`watching...`)\n agentWatching(config, testFiles.size)\n\n const { listenToUser } = await import('./lib/listenToUser.js')\n const disposeTty = listenToUser(\n reRunManager,\n files => () => {\n return runTests(config, files, reRunManager, concurrency, 'refresh', runsOut, executionFilters)\n },\n config.watch.ttyActionsOnKeypress,\n initialTestRun,\n input,\n runsOut\n )\n stopFns.push(disposeTty)\n\n const dispose = () => {\n for (const stop of stopFns) {\n stop()\n }\n stopFns.length = 0 // Idempotencize\n }\n return dispose\n\n\n // (async () => {\n // await new Promise<void>(() => {})\n // })()\n //await new Promise<void>(() => {})\n}\n"]}
package/dist/types.d.ts CHANGED
@@ -39,6 +39,7 @@ export interface FinalConfig {
39
39
  compact: boolean;
40
40
  restateFailures: boolean;
41
41
  agent: boolean;
42
+ agentLineLengthLimit: number;
42
43
  failFast: boolean;
43
44
  execution: ExecutionConfig;
44
45
  watch: WatchConfig;
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AACA,2EAA2E;AAC3E,2EAA2E;AAC3E,2EAA2E;AAC3E,+EAA+E","sourcesContent":["\n// Shared types for the test-run data model, user config, and CLI plumbing.\n// The config/result shapes are inferred from usage across the old awaitful\n// source (defaultConfig.js, validateConfig.js, init.js's template, and the\n// run*/parseDescribe/showTestResult modules) - there was no prior type source.\n\nimport type { FileMeta } from './meta.js'\nimport type { DescribeMeta } from './describe.js'\n\n\nexport type ExecutionMode = 'parallel' | 'sequential'\nexport type GlobPattern = string | string[]\n\nexport interface ExecutionConfig {\n files: ExecutionMode\n describes: ExecutionMode\n tests: ExecutionMode\n}\n\n// path to write the latest watch run status to, or false to write none\nexport type StatusFileConfig = string | false\n\nexport interface WatchConfig {\n watchFilesBase: string\n watchFiles: GlobPattern\n watchFilesIgnore: GlobPattern\n runAllOnStartup: boolean\n reRunFailingTests: boolean\n // map a changed file to the tests that import it. Off, any watched change runs everything\n dependencyEvaluation: boolean\n ttyActionsOnKeypress: boolean\n statusFile: StatusFileConfig\n}\n\nexport type TaskExports = Record<string, unknown>\nexport type ConfigTaskFn = (parcel?: TaskExports) => TaskExports | void | Promise<TaskExports | void>\n// a task may also be a file path (relative to the project root) to dynamically import\nexport type ConfigTask = ConfigTaskFn | string\nexport type ConfigTasks = ConfigTask | ConfigTask[]\n\nexport interface FinalConfig {\n testsBase: string\n tests: GlobPattern\n testsFilter?: string\n testsIgnore: GlobPattern\n setup?: ConfigTasks\n beforeEachFile?: ConfigTasks\n afterEachFile?: ConfigTasks\n beforeEachDescribe?: ConfigTasks\n afterEachDescribe?: ConfigTasks\n beforeEachTest?: ConfigTasks\n afterEachTest?: ConfigTasks\n teardown?: ConfigTasks\n showErrorTrace: boolean\n compact: boolean\n // repeat a failed run's failures above the tallies, where scrolling has not buried them\n restateFailures: boolean\n // report the run as single agent readable lines instead of the usual output\n agent: boolean\n // stop the run at the first failing test, erroring describe or unloadable test file.\n // Set by `once --fail-fast` only: it describes one invocation, not a project, and in\n // watch mode it would silently truncate runs that report themselves as covering\n // everything\n failFast: boolean\n execution: ExecutionConfig\n watch: WatchConfig\n}\n\nexport type UserConfig = Partial<\n Omit<FinalConfig, 'testsFilter' | 'failFast' | 'execution' | 'watch'>\n> & {\n execution?: Partial<ExecutionConfig>\n watch?: Partial<WatchConfig>\n}\n\nexport type UserConfigInternal = UserConfig\n & Partial<Pick<FinalConfig, 'testsFilter' | 'failFast'>>\n\n\n// -- test-run data model --------------------------------------------------\n\nexport type TestParcel = TaskExports\n\nexport interface DescribeParcel extends TaskExports {\n it: (should: string, test: (parcel: TestParcel) => void | Promise<void>) => void\n test: (should: string, test: (parcel: TestParcel) => void | Promise<void>) => void\n afterDescribe: (func: () => void | Promise<void>) => void\n beforeEachTest: (func: () => TaskExports | void | Promise<TaskExports | void>) => void\n afterEachTest: (func: () => void | Promise<void>) => void\n}\n\nexport type DescribeCallback = (parcel: DescribeParcel) => void | Promise<void>\n\n\n\nexport interface ParsedDescribe {\n its: It[]\n beforeDescribeExports: TaskExports\n afterDescribeFunc?: () => void | Promise<void>\n beforeEachTestFunc?: () => TaskExports | void | Promise<TaskExports | void>\n afterEachTestFunc?: () => void | Promise<void>\n error?: unknown\n}\n\n// export interface TestError extends Error {\n// actual?: unknown\n// expected?: unknown\n// }\n\n\n\n\n\n\n\n\n\n\nexport type DependencyTrees = Record<string, string[]>\n\nexport type OutFn = (...texts: unknown[]) => void\n\n\n\n// -- globals ----------------------------------------------------------------\n\nexport type Describe = {\n counter: number\n thing: string\n meta?: DescribeMeta\n tests: DescribeCallback\n}\n\nexport type It = {\n counter: number\n should: string\n test: (parcel: TestParcel) => void | Promise<void>\n}\n\nexport interface SxyTestRunnerGlobal {\n describes: Describe[]\n describeCounter: number\n fileMeta?: FileMeta\n}\ndeclare global {\n var __sxy_test_runner__: SxyTestRunnerGlobal | undefined\n var __sxyt_commandLineArguments: string[]\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AACA,2EAA2E;AAC3E,2EAA2E;AAC3E,2EAA2E;AAC3E,+EAA+E","sourcesContent":["\n// Shared types for the test-run data model, user config, and CLI plumbing.\n// The config/result shapes are inferred from usage across the old awaitful\n// source (defaultConfig.js, validateConfig.js, init.js's template, and the\n// run*/parseDescribe/showTestResult modules) - there was no prior type source.\n\nimport type { FileMeta } from './meta.js'\nimport type { DescribeMeta } from './describe.js'\n\n\nexport type ExecutionMode = 'parallel' | 'sequential'\nexport type GlobPattern = string | string[]\n\nexport interface ExecutionConfig {\n files: ExecutionMode\n describes: ExecutionMode\n tests: ExecutionMode\n}\n\n// path to write the latest watch run status to, or false to write none\nexport type StatusFileConfig = string | false\n\nexport interface WatchConfig {\n watchFilesBase: string\n watchFiles: GlobPattern\n watchFilesIgnore: GlobPattern\n runAllOnStartup: boolean\n reRunFailingTests: boolean\n // map a changed file to the tests that import it. Off, any watched change runs everything\n dependencyEvaluation: boolean\n ttyActionsOnKeypress: boolean\n statusFile: StatusFileConfig\n}\n\nexport type TaskExports = Record<string, unknown>\nexport type ConfigTaskFn = (parcel?: TaskExports) => TaskExports | void | Promise<TaskExports | void>\n// a task may also be a file path (relative to the project root) to dynamically import\nexport type ConfigTask = ConfigTaskFn | string\nexport type ConfigTasks = ConfigTask | ConfigTask[]\n\nexport interface FinalConfig {\n testsBase: string\n tests: GlobPattern\n testsFilter?: string\n testsIgnore: GlobPattern\n setup?: ConfigTasks\n beforeEachFile?: ConfigTasks\n afterEachFile?: ConfigTasks\n beforeEachDescribe?: ConfigTasks\n afterEachDescribe?: ConfigTasks\n beforeEachTest?: ConfigTasks\n afterEachTest?: ConfigTasks\n teardown?: ConfigTasks\n showErrorTrace: boolean\n compact: boolean\n // repeat a failed run's failures above the tallies, where scrolling has not buried them\n restateFailures: boolean\n // report the run as single agent readable lines instead of the usual output\n agent: boolean\n // the most characters of error text on each agent fail line; Infinity for no limit\n agentLineLengthLimit: number\n // stop the run at the first failing test, erroring describe or unloadable test file.\n // Set by `once --fail-fast` only: it describes one invocation, not a project, and in\n // watch mode it would silently truncate runs that report themselves as covering\n // everything\n failFast: boolean\n execution: ExecutionConfig\n watch: WatchConfig\n}\n\nexport type UserConfig = Partial<\n Omit<FinalConfig, 'testsFilter' | 'failFast' | 'execution' | 'watch'>\n> & {\n execution?: Partial<ExecutionConfig>\n watch?: Partial<WatchConfig>\n}\n\nexport type UserConfigInternal = UserConfig\n & Partial<Pick<FinalConfig, 'testsFilter' | 'failFast'>>\n\n\n// -- test-run data model --------------------------------------------------\n\nexport type TestParcel = TaskExports\n\nexport interface DescribeParcel extends TaskExports {\n it: (should: string, test: (parcel: TestParcel) => void | Promise<void>) => void\n test: (should: string, test: (parcel: TestParcel) => void | Promise<void>) => void\n afterDescribe: (func: () => void | Promise<void>) => void\n beforeEachTest: (func: () => TaskExports | void | Promise<TaskExports | void>) => void\n afterEachTest: (func: () => void | Promise<void>) => void\n}\n\nexport type DescribeCallback = (parcel: DescribeParcel) => void | Promise<void>\n\n\n\nexport interface ParsedDescribe {\n its: It[]\n beforeDescribeExports: TaskExports\n afterDescribeFunc?: () => void | Promise<void>\n beforeEachTestFunc?: () => TaskExports | void | Promise<TaskExports | void>\n afterEachTestFunc?: () => void | Promise<void>\n error?: unknown\n}\n\n// export interface TestError extends Error {\n// actual?: unknown\n// expected?: unknown\n// }\n\n\n\n\n\n\n\n\n\n\nexport type DependencyTrees = Record<string, string[]>\n\nexport type OutFn = (...texts: unknown[]) => void\n\n\n\n// -- globals ----------------------------------------------------------------\n\nexport type Describe = {\n counter: number\n thing: string\n meta?: DescribeMeta\n tests: DescribeCallback\n}\n\nexport type It = {\n counter: number\n should: string\n test: (parcel: TestParcel) => void | Promise<void>\n}\n\nexport interface SxyTestRunnerGlobal {\n describes: Describe[]\n describeCounter: number\n fileMeta?: FileMeta\n}\ndeclare global {\n var __sxy_test_runner__: SxyTestRunnerGlobal | undefined\n var __sxyt_commandLineArguments: string[]\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sxy-test-runner",
3
- "version": "2.5.2",
3
+ "version": "2.5.3",
4
4
  "license": "MIT",
5
5
  "homepage": "https://github.com/RobertSandiford/sxy-test-runner",
6
6
  "repository": {
package/readme.md CHANGED
@@ -203,6 +203,12 @@ clean suite. `status` is one of `passed`, `failed`, `aborted` (a test file would
203
203
  a describe threw) or `could-not-run` - the same states as the status file table above, named
204
204
  rather than numbered. It is not the process exit code: read that from the process.
205
205
 
206
+ Each failure's error message is cut at 500 characters. Set `agentLineLengthLimit` in the
207
+ config to change that, or to `Infinity` to keep messages whole.
208
+
209
+ Agent mode also sets the environment variables `SXYT_AGENT` and `SXY_TEST_RUNNER_AGENT` to
210
+ `true`, so setup code and tests can tell they are running under it.
211
+
206
212
  ## Stopping at the first failure
207
213
 
208
214
  `-x` or `--fail-fast` stops a `once` run at the first failing test, erroring describe, or
@@ -236,7 +242,8 @@ Because of this, be careful with globals, which will be shared.
236
242
 
237
243
  While tests are running, `NODE_ENV` defaults to `test` when it was not already set.
238
244
  `SXYT` and `SXY_TEST_RUNNER` are both set to `true`, allowing configuration and application
239
- code to detect sxy-test-runner specifically.
245
+ code to detect sxy-test-runner specifically. In agent mode, `SXYT_AGENT` and
246
+ `SXY_TEST_RUNNER_AGENT` are also set to `true`.
240
247
 
241
248
  ### Sharing a module between test files
242
249