sxy-test-runner 2.5.0 → 2.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/AGENTS.md +9 -1
  2. package/dist/cli/cliTypes.d.ts +1 -0
  3. package/dist/cli/cliTypes.js.map +1 -1
  4. package/dist/cli/init.js +3 -0
  5. package/dist/cli/init.js.map +1 -1
  6. package/dist/cli/lib/addBasePath.js +1 -1
  7. package/dist/cli/lib/addBasePath.js.map +1 -1
  8. package/dist/cli/lib/buildDependencyTrees.d.ts +1 -1
  9. package/dist/cli/lib/buildDependencyTrees.js +2 -2
  10. package/dist/cli/lib/buildDependencyTrees.js.map +1 -1
  11. package/dist/cli/lib/defaultConfig.js +1 -0
  12. package/dist/cli/lib/defaultConfig.js.map +1 -1
  13. package/dist/cli/lib/failureEntries.js +6 -3
  14. package/dist/cli/lib/failureEntries.js.map +1 -1
  15. package/dist/cli/lib/filter.js +2 -2
  16. package/dist/cli/lib/filter.js.map +1 -1
  17. package/dist/cli/lib/findTestFiles.js +1 -1
  18. package/dist/cli/lib/findTestFiles.js.map +1 -1
  19. package/dist/cli/lib/parseCommandLineArguments.js +20 -8
  20. package/dist/cli/lib/parseCommandLineArguments.js.map +1 -1
  21. package/dist/cli/lib/parseDescribe.js +1 -1
  22. package/dist/cli/lib/parseDescribe.js.map +1 -1
  23. package/dist/cli/lib/runDescribe.js +1 -1
  24. package/dist/cli/lib/runDescribe.js.map +1 -1
  25. package/dist/cli/lib/runDescribeRun.js +1 -1
  26. package/dist/cli/lib/runDescribeRun.js.map +1 -1
  27. package/dist/cli/lib/runIt.js +1 -1
  28. package/dist/cli/lib/runIt.js.map +1 -1
  29. package/dist/cli/lib/runTests.js +9 -188
  30. package/dist/cli/lib/runTests.js.map +1 -1
  31. package/dist/cli/lib/showFailuresColorized.d.ts +2 -0
  32. package/dist/cli/lib/showFailuresColorized.js +52 -0
  33. package/dist/cli/lib/showFailuresColorized.js.map +1 -0
  34. package/dist/cli/lib/showTestFileResult.d.ts +7 -0
  35. package/dist/cli/lib/{showTestResult.js → showTestFileResult.js} +15 -9
  36. package/dist/cli/lib/showTestFileResult.js.map +1 -0
  37. package/dist/cli/lib/showTestResultsSummary.d.ts +8 -0
  38. package/dist/cli/lib/showTestResultsSummary.js +213 -0
  39. package/dist/cli/lib/showTestResultsSummary.js.map +1 -0
  40. package/dist/cli/lib/timeProfiler.d.ts +3 -0
  41. package/dist/cli/lib/{timeProfier.js → timeProfiler.js} +1 -1
  42. package/dist/cli/lib/timeProfiler.js.map +1 -0
  43. package/dist/cli/lib/validateConfig.js +3 -0
  44. package/dist/cli/lib/validateConfig.js.map +1 -1
  45. package/dist/cli/lib/watchFilesAndRunTestsNodeWatch.js +3 -3
  46. package/dist/cli/lib/watchFilesAndRunTestsNodeWatch.js.map +1 -1
  47. package/dist/cli/lib/watchFilesNodeWatch.js +3 -3
  48. package/dist/cli/lib/watchFilesNodeWatch.js.map +1 -1
  49. package/dist/cli/once.js +4 -2
  50. package/dist/cli/once.js.map +1 -1
  51. package/dist/cli/watch.d.ts +1 -1
  52. package/dist/cli/watch.js +8 -5
  53. package/dist/cli/watch.js.map +1 -1
  54. package/dist/packages/timeProfiler.d.ts +1 -1
  55. package/dist/packages/timeProfiler.js.map +1 -1
  56. package/dist/types.d.ts +1 -0
  57. package/dist/types.js.map +1 -1
  58. package/package.json +2 -3
  59. package/dist/cli/lib/showTestResult.d.ts +0 -4
  60. package/dist/cli/lib/showTestResult.js.map +0 -1
  61. package/dist/cli/lib/timeProfier.d.ts +0 -3
  62. package/dist/cli/lib/timeProfier.js.map +0 -1
@@ -1,31 +1,16 @@
1
- import { count } from 'sxy-lib/objects.js';
2
1
  import { allObj as promiseAllObj } from 'sxy-lib/promises.js';
3
2
  import { createTimeProfiler } from '../../packages/timeProfiler.js';
4
- import figures from '../../packages/figures.js';
5
- import chalk from '../../packages/chalk.js';
6
3
  import { showTimeProfiling } from '../../config.js';
7
- import { out as mainOut } from '../../output.js';
8
4
  import { loadTestFile } from './loadTestFile.js';
9
5
  import { runTest } from './runTest.js';
10
6
  import { showTestLoadingError } from './showTestLoadingError.js';
11
- import { showTestResult } from './showTestResult.js';
12
- import { failureLines } from './failureLines.js';
13
- import { failureEntries } from './failureEntries.js';
14
- import { agentDone, agentFailure, agentRunStart } from './agentReport.js';
7
+ import { showTestFileResult } from './showTestFileResult.js';
8
+ import { agentRunStart } from './agentReport.js';
15
9
  import { makeStopSignal, stopIfFailFast } from './stopSignal.js';
16
- import { statusCodes, writeStatusFile } from './statusFile.js';
17
10
  import { makeRunManagerState } from './makeWatchRunState.js';
11
+ import { showTestResultsSummary } from './showTestResultsSummary.js';
18
12
  const { timeProfileAsync } = createTimeProfiler(showTimeProfiling);
19
- // the summary lines, minus the colouring, for the status file
20
- function joinPlain(...parts) {
21
- return parts.filter(part => part !== '').join(' ');
22
- }
23
- function plural(count, noun, verb) {
24
- if (count < 1)
25
- return '';
26
- return `${count} ${noun}${count === 1 ? '' : 's'} ${verb}`;
27
- }
28
- function recordWithoutTests(state, testFile, testResult) {
13
+ function recordEntitiesWithoutTests(state, testFile, testResult) {
29
14
  const describes = testResult.describeResults
30
15
  .filter(describeResult => describeResult.success === null)
31
16
  .map(describeResult => describeResult.thing);
@@ -48,7 +33,7 @@ refresh = 'refresh', customOut, filters = {}) {
48
33
  }
49
34
  const state = reRunManager?.state || makeRunManagerState();
50
35
  const runStartTime = new Date().getTime();
51
- const agentRun = agentRunStart(config, testFiles.size);
36
+ const runNumber = agentRunStart(config, testFiles.size);
52
37
  const stop = makeStopSignal();
53
38
  //console.log('new runTests:', watchRunState?.activeRuns)
54
39
  //console.log(inspect(testFiles))
@@ -74,7 +59,7 @@ refresh = 'refresh', customOut, filters = {}) {
74
59
  else {
75
60
  const testRunPromise = runTest(config, test, filters, stop);
76
61
  testRunPromises[testFile] = testRunPromise;
77
- testRunOutPromises[testFile] = testRunPromise.then(async (testResult) => {
62
+ testRunOutPromises[testFile] = testRunPromise.then(testResult => {
78
63
  if (testResult.success === true || testResult.success === null) {
79
64
  state.failedTestFiles.delete(testResult.file);
80
65
  }
@@ -84,9 +69,9 @@ refresh = 'refresh', customOut, filters = {}) {
84
69
  const executionFilterActive = filters.describe !== undefined || filters.it !== undefined;
85
70
  // a filter makes files and describes look empty when they are not
86
71
  if (!executionFilterActive)
87
- recordWithoutTests(state, testFile, testResult);
72
+ recordEntitiesWithoutTests(state, testFile, testResult);
88
73
  if (!executionFilterActive || testResult.describeResultsSummary.itsTotal > 0) {
89
- await showTestResult(config, testResult, customOut);
74
+ showTestFileResult(config, testResult, customOut);
90
75
  }
91
76
  });
92
77
  // wait for the test to complete before proceeding if we are in 'sequential' mode
@@ -102,171 +87,7 @@ refresh = 'refresh', customOut, filters = {}) {
102
87
  // wait for the output to complete
103
88
  await promiseAllObj(testRunOutPromises);
104
89
  });
105
- return await timeProfileAsync('show initial test run results', () => {
106
- const out = customOut ?? mainOut;
107
- const testsResultsSummary = {
108
- total: 0,
109
- passes: 0,
110
- invalid: 0,
111
- describesTotal: 0,
112
- describesPasses: 0,
113
- describesInvalid: 0,
114
- itsTotal: 0,
115
- itsPasses: 0
116
- // itsInvalid: 0 // we don't check whether tests run any asserts (we don't control the assertion lib)
117
- };
118
- let describesThrownCount = 0;
119
- for (const testFile in runTestResults) {
120
- const runTestResult = runTestResults[testFile];
121
- if (!runTestResult)
122
- continue;
123
- testsResultsSummary.total += +(runTestResult.success !== null);
124
- testsResultsSummary.passes += +(runTestResult.success ?? false);
125
- testsResultsSummary.invalid += +(runTestResult.success === null);
126
- testsResultsSummary.describesTotal += runTestResult.describeResultsSummary.total;
127
- testsResultsSummary.describesPasses += runTestResult.describeResultsSummary.passes;
128
- testsResultsSummary.describesInvalid += runTestResult.describeResultsSummary.invalid;
129
- testsResultsSummary.itsTotal += runTestResult.describeResultsSummary.itsTotal;
130
- testsResultsSummary.itsPasses += runTestResult.describeResultsSummary.itsPasses;
131
- describesThrownCount += runTestResult.describeResults
132
- .filter(describeResult => describeResult.error !== undefined)
133
- .length;
134
- }
135
- const failedToLoadCount = count(erroringTests);
136
- testsResultsSummary.total += failedToLoadCount;
137
- if ((filters.describe !== undefined || filters.it !== undefined)
138
- && testsResultsSummary.itsTotal === 0
139
- && failedToLoadCount === 0
140
- && describesThrownCount === 0) {
141
- out(chalk.orange('No tests matched the describe/test filters.'));
142
- const durationMs = new Date().getTime() - runStartTime;
143
- writeStatusFile(config, statusCodes.couldNotRun, 'no tests matched the describe/test filters', [], durationMs);
144
- agentDone(config, agentRun, statusCodes.couldNotRun, 'no tests matched the describe/test filters', testsResultsSummary, durationMs, state.failedTestFiles.size);
145
- return null;
146
- }
147
- out(config.compact ? '' : '\n');
148
- const allPassed = (testsResultsSummary.passes === testsResultsSummary.total
149
- && testsResultsSummary.describesPasses === testsResultsSummary.describesTotal
150
- && testsResultsSummary.itsPasses === testsResultsSummary.itsTotal);
151
- if (allPassed) {
152
- out(chalk.mediumgreen(`${figures.tick}`));
153
- }
154
- else {
155
- out(chalk.mediumred(`${figures.cross}`));
156
- }
157
- // number of tests successful
158
- const testsText = `Tests: ${testsResultsSummary.itsPasses}/${testsResultsSummary.itsTotal}`;
159
- if (testsResultsSummary.itsPasses === testsResultsSummary.itsTotal) {
160
- if (testsResultsSummary.itsTotal === 0) {
161
- out(chalk.grey(`${testsText}`));
162
- }
163
- else {
164
- out(chalk.mediumgreen(`${testsText}`));
165
- }
166
- }
167
- else {
168
- out(chalk.mediumred(`${testsText}`));
169
- }
170
- // number of items successful
171
- const describesText = `Items: ${testsResultsSummary.describesPasses}/${testsResultsSummary.describesTotal}`;
172
- const invalidDescribesPlain = (testsResultsSummary.describesInvalid >= 1)
173
- ? (testsResultsSummary.describesInvalid === 1)
174
- ? '(+1 describe without tests)'
175
- : `(+${testsResultsSummary.describesInvalid} describes without tests)`
176
- : '';
177
- const describesThrownPlain = (describesThrownCount >= 1)
178
- ? (describesThrownCount === 1)
179
- ? '(1 describe errored)'
180
- : `(${describesThrownCount} describes errored)`
181
- : '';
182
- const describesDetailsText = [
183
- chalk.mediumred(describesThrownPlain), chalk.grey(invalidDescribesPlain)
184
- ]
185
- .filter(text => text !== '')
186
- .join(' ');
187
- const describesDetailsSuffix = describesDetailsText === '' ? '' : ` ${describesDetailsText}`;
188
- if (testsResultsSummary.describesPasses === testsResultsSummary.describesTotal) {
189
- if (testsResultsSummary.describesTotal === 0) {
190
- out(chalk.grey(`${describesText}`) + describesDetailsSuffix);
191
- }
192
- else {
193
- out(chalk.mediumgreen(`${describesText}`) + describesDetailsSuffix);
194
- }
195
- }
196
- else {
197
- out(chalk.mediumred(`${describesText}`) + describesDetailsSuffix);
198
- }
199
- // number of test files successful
200
- const testFilesText = `Test Files: ${testsResultsSummary.passes}/${testsResultsSummary.total}`;
201
- const invalidTestFilesPlain = (testsResultsSummary.invalid >= 1)
202
- ? (testsResultsSummary.invalid === 1)
203
- ? '(+1 file without tests)'
204
- : `(+${testsResultsSummary.invalid} files without tests)`
205
- : '';
206
- const failedToLoadPlain = (failedToLoadCount >= 1)
207
- ? (failedToLoadCount === 1)
208
- ? '(1 file failed to load, or errored)'
209
- : `(${failedToLoadCount} files failed to load, or errored)`
210
- : '';
211
- const testFilesDetailsText = [
212
- chalk.mediumred(failedToLoadPlain), chalk.grey(invalidTestFilesPlain)
213
- ]
214
- .filter(text => text !== '')
215
- .join(' ');
216
- const testFilesDetailsSuffix = testFilesDetailsText === '' ? '' : ` ${testFilesDetailsText}`;
217
- if (testsResultsSummary.passes === testsResultsSummary.total) {
218
- if (testsResultsSummary.describesTotal === 0) {
219
- out(chalk.grey(`${testFilesText}`) + testFilesDetailsSuffix);
220
- }
221
- else {
222
- out(chalk.mediumgreen(`${testFilesText}`) + testFilesDetailsSuffix);
223
- }
224
- }
225
- else {
226
- out(chalk.mediumred(`${testFilesText}`) + testFilesDetailsSuffix);
227
- }
228
- // the tallies only cover what ran, so say the run was cut short - otherwise
229
- // "Tests: 0/1" reads as a one test suite
230
- const stoppedPlain = (stop.stopped)
231
- ? 'stopped at the first failure (failFast)'
232
- : '';
233
- if (stoppedPlain !== '')
234
- out(chalk.orange(stoppedPlain));
235
- const summaryLines = [
236
- testsText,
237
- joinPlain(describesText, describesThrownPlain, invalidDescribesPlain),
238
- joinPlain(testFilesText, failedToLoadPlain, invalidTestFilesPlain),
239
- ...(stoppedPlain === '') ? [] : [stoppedPlain]
240
- ];
241
- const durationMs = new Date().getTime() - runStartTime;
242
- if (allPassed) {
243
- writeStatusFile(config, statusCodes.passed, 'all tests passed', summaryLines, durationMs);
244
- agentDone(config, agentRun, statusCodes.passed, 'all tests passed', testsResultsSummary, durationMs, state.failedTestFiles.size);
245
- }
246
- else {
247
- const abortedFiles = Object.keys(erroringTests);
248
- // a file that would not load, or a describe that threw, means the run died
249
- // partway - a different problem from tests that ran and failed
250
- const aborted = abortedFiles.length > 0 || describesThrownCount > 0;
251
- const failedTestsCount = testsResultsSummary.itsTotal - testsResultsSummary.itsPasses;
252
- const description = ([
253
- plural(abortedFiles.length, 'test file', 'failed to load or errored'),
254
- plural(describesThrownCount, 'describe', 'errored'),
255
- plural(failedTestsCount, 'test', 'failed')
256
- ].filter(part => part !== '').join(', ') || 'test run failed')
257
- + ((stop.stopped) ? ', stopped at the first failure' : '');
258
- const code = (aborted) ? statusCodes.aborted : statusCodes.failed;
259
- const failures = failureEntries(Object.values(runTestResults), erroringTests);
260
- writeStatusFile(config, code, description, [...summaryLines, ...failureLines(Object.values(runTestResults), erroringTests)], durationMs);
261
- // failures first, so the done line is a complete end of run marker
262
- for (const failure of failures)
263
- agentFailure(config, agentRun, failure);
264
- agentDone(config, agentRun, code, description, testsResultsSummary, durationMs, state.failedTestFiles.size);
265
- }
266
- // full success?
267
- // true/false gets returned to the caller of runTests()
268
- return allPassed;
269
- });
90
+ return showTestResultsSummary(runTestResults, erroringTests, runStartTime, config, runNumber, state, stop, filters, customOut);
270
91
  }
271
92
  finally {
272
93
  if (reRunManager !== undefined)
@@ -1 +1 @@
1
- {"version":3,"file":"runTests.js","sourceRoot":"","sources":["../../../src/cli/lib/runTests.ts"],"names":[],"mappings":"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","sourcesContent":["\nimport { count } from 'sxy-lib/objects.js'\nimport { allObj as promiseAllObj } from 'sxy-lib/promises.js'\n\nimport type { FinalConfig, OutFn } from '../../types.js'\nimport type { TestExecutionFilters } from '../cliTypes.js'\nimport type { ReRunManager } from './reRunManager.js'\nimport { createTimeProfiler } from '../../packages/timeProfiler.js'\nimport figures from '../../packages/figures.js'\nimport chalk from '../../packages/chalk.js'\nimport { showTimeProfiling } from '../../config.js'\nimport { out as mainOut } from '../../output.js'\nimport { loadTestFile, type TestFile } from './loadTestFile.js'\nimport { runTest, type TestResult } from './runTest.js'\nimport { showTestLoadingError } from './showTestLoadingError.js'\nimport { showTestResult } from './showTestResult.js'\nimport { failureLines } from './failureLines.js'\nimport { failureEntries } from './failureEntries.js'\nimport { agentDone, agentFailure, agentRunStart } from './agentReport.js'\nimport { makeStopSignal, stopIfFailFast } from './stopSignal.js'\nimport { statusCodes, writeStatusFile } from './statusFile.js'\nimport { makeRunManagerState, type ReRunManageState } from './makeWatchRunState.js'\n\n\nconst { timeProfileAsync } = createTimeProfiler(showTimeProfiling)\n\nexport interface TestsResultsSummary {\n total: number\n passes: number\n invalid: number\n describesTotal: number\n describesPasses: number\n describesInvalid: number\n itsTotal: number\n itsPasses: number\n}\n\nexport type RunTestsPromise = Promise<boolean | null>\n\n// the summary lines, minus the colouring, for the status file\nfunction joinPlain(...parts: string[]): string {\n return parts.filter(part => part !== '').join(' ')\n}\n\nfunction plural(count: number, noun: string, verb: string): string {\n if (count < 1) return ''\n return `${count} ${noun}${count === 1 ? '' : 's'} ${verb}`\n}\n\nexport type Concurrency = {\n limit: number\n}\n\nfunction recordWithoutTests(state: ReRunManageState, testFile: string, testResult: TestResult): void {\n const describes = testResult.describeResults\n .filter(describeResult => describeResult.success === null)\n .map(describeResult => describeResult.thing)\n const fileWithoutTests = testResult.success === null\n if (fileWithoutTests || describes.length > 0) {\n state.withoutTests.set(testFile, {\n file: testResult.sourceFile ?? testResult.file, fileWithoutTests, describes\n })\n } else {\n state.withoutTests.delete(testFile)\n }\n}\n\nexport async function runTests(\n config: FinalConfig,\n testFiles: Set<string>,\n reRunManager: ReRunManager | undefined,\n concurrency: Concurrency = { limit: -1 }, // eslint-disable-line @typescript-eslint/no-unused-vars\n // -- WIP\n refresh: 'refresh' | 'cached' = 'refresh',\n customOut?: OutFn,\n filters: TestExecutionFilters = {}\n): RunTestsPromise {\n if (reRunManager !== undefined) {\n reRunManager.state.lastTestFiles = new Set(testFiles)\n reRunManager.state.activeRuns++ // whatever, obsolete. Can use it to check on things\n }\n\n const state = reRunManager?.state || makeRunManagerState()\n const runStartTime = new Date().getTime()\n const agentRun = agentRunStart(config, testFiles.size)\n const stop = makeStopSignal()\n //console.log('new runTests:', watchRunState?.activeRuns)\n //console.log(inspect(testFiles))\n\n try {\n const testRunPromises: Record<string, Promise<TestResult>> = {}\n const erroringTests: Record<string, TestFile> = {}\n const testRunOutPromises: Record<string, Promise<void>> = {}\n\n await timeProfileAsync('run tests', async () => {\n if (Array.isArray(testFiles) ? testFiles.length > 0 : testFiles.size > 0) {\n for (const testFile of testFiles) {\n //console.log('testFiles', testFiles)\n //console.log('testFile', testFile)\n\n // an earlier file failed under failFast - leave the rest unloaded\n if (stop.stopped) break\n\n const test = await loadTestFile(config, testFile, refresh)\n\n if (test.error !== undefined && test.error !== false) {\n erroringTests[testFile] = test\n state.failedTestFiles.add(testFile)\n showTestLoadingError(config, test, customOut)\n stopIfFailFast(config, stop, true)\n } else {\n const testRunPromise = runTest(config, test, filters, stop)\n testRunPromises[testFile] = testRunPromise\n\n testRunOutPromises[testFile] = testRunPromise.then(async testResult => {\n if (testResult.success === true || testResult.success === null) {\n state.failedTestFiles.delete(testResult.file)\n } else {\n state.failedTestFiles.add(testFile)\n }\n const executionFilterActive = filters.describe !== undefined || filters.it !== undefined\n // a filter makes files and describes look empty when they are not\n if (!executionFilterActive) recordWithoutTests(state, testFile, testResult)\n if (!executionFilterActive || testResult.describeResultsSummary.itsTotal > 0) {\n await showTestResult(config, testResult, customOut)\n }\n })\n\n // wait for the test to complete before proceeding if we are in 'sequential' mode\n if (config.execution.files === 'sequential') await testRunOutPromises[testFile]\n }\n }\n }\n })\n\n let runTestResults: Record<string, TestResult> = {}\n\n await timeProfileAsync('wait for tests to finish', async () => {\n runTestResults = await promiseAllObj(testRunPromises)\n\n // wait for the output to complete\n await promiseAllObj(testRunOutPromises)\n })\n\n return await timeProfileAsync('show initial test run results', () => {\n \n const out = customOut ?? mainOut\n\n const testsResultsSummary: TestsResultsSummary = {\n total: 0,\n passes: 0,\n invalid: 0,\n describesTotal: 0,\n describesPasses: 0,\n describesInvalid: 0,\n itsTotal: 0,\n itsPasses: 0\n // itsInvalid: 0 // we don't check whether tests run any asserts (we don't control the assertion lib)\n }\n let describesThrownCount = 0\n\n for (const testFile in runTestResults) {\n const runTestResult = runTestResults[testFile]\n if (!runTestResult) continue\n\n testsResultsSummary.total += +(runTestResult.success !== null)\n testsResultsSummary.passes += +(runTestResult.success ?? false)\n testsResultsSummary.invalid += +(runTestResult.success === null)\n testsResultsSummary.describesTotal += runTestResult.describeResultsSummary.total\n testsResultsSummary.describesPasses += runTestResult.describeResultsSummary.passes\n testsResultsSummary.describesInvalid += runTestResult.describeResultsSummary.invalid\n testsResultsSummary.itsTotal += runTestResult.describeResultsSummary.itsTotal\n testsResultsSummary.itsPasses += runTestResult.describeResultsSummary.itsPasses\n describesThrownCount += runTestResult.describeResults\n .filter(describeResult => describeResult.error !== undefined)\n .length\n }\n\n const failedToLoadCount = count(erroringTests)\n testsResultsSummary.total += failedToLoadCount\n\n if (\n (filters.describe !== undefined || filters.it !== undefined)\n && testsResultsSummary.itsTotal === 0\n && failedToLoadCount === 0\n && describesThrownCount === 0\n ) {\n out(chalk.orange('No tests matched the describe/test filters.'))\n const durationMs = new Date().getTime() - runStartTime\n writeStatusFile(\n config,\n statusCodes.couldNotRun,\n 'no tests matched the describe/test filters',\n [],\n durationMs\n )\n agentDone(\n config, agentRun, statusCodes.couldNotRun,\n 'no tests matched the describe/test filters', testsResultsSummary, durationMs,\n state.failedTestFiles.size\n )\n return null\n }\n\n out(config.compact ? '' : '\\n')\n\n const allPassed = (\n testsResultsSummary.passes === testsResultsSummary.total\n && testsResultsSummary.describesPasses === testsResultsSummary.describesTotal\n && testsResultsSummary.itsPasses === testsResultsSummary.itsTotal\n )\n\n if (allPassed) {\n out(chalk.mediumgreen(`${figures.tick}`))\n } else {\n out(chalk.mediumred(`${figures.cross}`))\n }\n\n // number of tests successful\n const testsText = `Tests: ${testsResultsSummary.itsPasses}/${testsResultsSummary.itsTotal}`\n if (testsResultsSummary.itsPasses === testsResultsSummary.itsTotal) {\n if (testsResultsSummary.itsTotal === 0) {\n out(chalk.grey(`${testsText}`))\n } else {\n out(chalk.mediumgreen(`${testsText}`))\n }\n } else {\n out(chalk.mediumred(`${testsText}`))\n }\n\n // number of items successful\n const describesText = `Items: ${testsResultsSummary.describesPasses}/${testsResultsSummary.describesTotal}`\n const invalidDescribesPlain = (testsResultsSummary.describesInvalid >= 1)\n ? (testsResultsSummary.describesInvalid === 1)\n ? '(+1 describe without tests)'\n : `(+${testsResultsSummary.describesInvalid} describes without tests)`\n : ''\n const describesThrownPlain = (describesThrownCount >= 1)\n ? (describesThrownCount === 1)\n ? '(1 describe errored)'\n : `(${describesThrownCount} describes errored)`\n : ''\n const describesDetailsText = [\n chalk.mediumred(describesThrownPlain), chalk.grey(invalidDescribesPlain)\n ]\n .filter(text => text !== '')\n .join(' ')\n const describesDetailsSuffix = describesDetailsText === '' ? '' : ` ${describesDetailsText}`\n if (testsResultsSummary.describesPasses === testsResultsSummary.describesTotal) {\n if (testsResultsSummary.describesTotal === 0) {\n out(chalk.grey(`${describesText}`) + describesDetailsSuffix)\n } else {\n out(chalk.mediumgreen(`${describesText}`) + describesDetailsSuffix)\n }\n } else {\n out(chalk.mediumred(`${describesText}`) + describesDetailsSuffix)\n }\n\n // number of test files successful\n const testFilesText = `Test Files: ${testsResultsSummary.passes}/${testsResultsSummary.total}`\n const invalidTestFilesPlain = (testsResultsSummary.invalid >= 1)\n ? (testsResultsSummary.invalid === 1)\n ? '(+1 file without tests)'\n : `(+${testsResultsSummary.invalid} files without tests)`\n : ''\n const failedToLoadPlain = (failedToLoadCount >= 1)\n ? (failedToLoadCount === 1)\n ? '(1 file failed to load, or errored)'\n : `(${failedToLoadCount} files failed to load, or errored)`\n : ''\n const testFilesDetailsText = [\n chalk.mediumred(failedToLoadPlain), chalk.grey(invalidTestFilesPlain)\n ]\n .filter(text => text !== '')\n .join(' ')\n const testFilesDetailsSuffix = testFilesDetailsText === '' ? '' : ` ${testFilesDetailsText}`\n if (testsResultsSummary.passes === testsResultsSummary.total) {\n if (testsResultsSummary.describesTotal === 0) {\n out(chalk.grey(`${testFilesText}`) + testFilesDetailsSuffix)\n } else {\n out(chalk.mediumgreen(`${testFilesText}`) + testFilesDetailsSuffix)\n }\n } else {\n out(chalk.mediumred(`${testFilesText}`) + testFilesDetailsSuffix)\n }\n\n // the tallies only cover what ran, so say the run was cut short - otherwise\n // \"Tests: 0/1\" reads as a one test suite\n const stoppedPlain = (stop.stopped)\n ? 'stopped at the first failure (failFast)'\n : ''\n if (stoppedPlain !== '') out(chalk.orange(stoppedPlain))\n\n const summaryLines = [\n testsText,\n joinPlain(describesText, describesThrownPlain, invalidDescribesPlain),\n joinPlain(testFilesText, failedToLoadPlain, invalidTestFilesPlain),\n ...(stoppedPlain === '') ? [] : [stoppedPlain]\n ]\n\n const durationMs = new Date().getTime() - runStartTime\n\n if (allPassed) {\n writeStatusFile(\n config, statusCodes.passed, 'all tests passed', summaryLines, durationMs\n )\n agentDone(\n config, agentRun, statusCodes.passed, 'all tests passed',\n testsResultsSummary, durationMs, state.failedTestFiles.size\n )\n } else {\n const abortedFiles = Object.keys(erroringTests)\n\n // a file that would not load, or a describe that threw, means the run died\n // partway - a different problem from tests that ran and failed\n const aborted = abortedFiles.length > 0 || describesThrownCount > 0\n const failedTestsCount = testsResultsSummary.itsTotal - testsResultsSummary.itsPasses\n\n const description = ([\n plural(abortedFiles.length, 'test file', 'failed to load or errored'),\n plural(describesThrownCount, 'describe', 'errored'),\n plural(failedTestsCount, 'test', 'failed')\n ].filter(part => part !== '').join(', ') || 'test run failed')\n + ((stop.stopped) ? ', stopped at the first failure' : '')\n\n const code = (aborted) ? statusCodes.aborted : statusCodes.failed\n const failures = failureEntries(Object.values(runTestResults), erroringTests)\n\n writeStatusFile(\n config,\n code,\n description,\n [...summaryLines, ...failureLines(Object.values(runTestResults), erroringTests)],\n durationMs\n )\n\n // failures first, so the done line is a complete end of run marker\n for (const failure of failures) agentFailure(config, agentRun, failure)\n agentDone(\n config, agentRun, code, description, testsResultsSummary, durationMs,\n state.failedTestFiles.size\n )\n }\n\n // full success?\n // true/false gets returned to the caller of runTests()\n return allPassed\n })\n } finally {\n if (reRunManager !== undefined) reRunManager.state.activeRuns--\n }\n}\n"]}
1
+ {"version":3,"file":"runTests.js","sourceRoot":"","sources":["../../../src/cli/lib/runTests.ts"],"names":[],"mappings":"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","sourcesContent":["\nimport { allObj as promiseAllObj } from 'sxy-lib/promises.js'\n\nimport type { FinalConfig, OutFn } from '../../types.js'\nimport type { TestExecutionFilters } from '../cliTypes.js'\nimport type { ReRunManager } from './reRunManager.js'\nimport { createTimeProfiler } from '../../packages/timeProfiler.js'\nimport { showTimeProfiling } from '../../config.js'\nimport { loadTestFile, type TestFile } from './loadTestFile.js'\nimport { runTest, type TestResult } from './runTest.js'\nimport { showTestLoadingError } from './showTestLoadingError.js'\nimport { showTestFileResult } from './showTestFileResult.js'\nimport { agentRunStart } from './agentReport.js'\nimport { makeStopSignal, stopIfFailFast } from './stopSignal.js'\nimport { makeRunManagerState, type ReRunManageState } from './makeWatchRunState.js'\nimport { showTestResultsSummary } from './showTestResultsSummary.js'\n\n\nconst { timeProfileAsync } = createTimeProfiler(showTimeProfiling)\n\nexport interface TestsResultsSummary {\n total: number\n passes: number\n invalid: number\n describesTotal: number\n describesPasses: number\n describesInvalid: number\n itsTotal: number\n itsPasses: number\n}\n\nexport type RunTestsPromise = Promise<boolean | null>\n\n\nexport type Concurrency = {\n limit: number\n}\n\nfunction recordEntitiesWithoutTests(state: ReRunManageState, testFile: string, testResult: TestResult): void {\n const describes = testResult.describeResults\n .filter(describeResult => describeResult.success === null)\n .map(describeResult => describeResult.thing)\n const fileWithoutTests = testResult.success === null\n if (fileWithoutTests || describes.length > 0) {\n state.withoutTests.set(testFile, {\n file: testResult.sourceFile ?? testResult.file, fileWithoutTests, describes\n })\n } else {\n state.withoutTests.delete(testFile)\n }\n}\n\nexport async function runTests(\n config: FinalConfig,\n testFiles: Set<string>,\n reRunManager: ReRunManager | undefined,\n concurrency: Concurrency = { limit: -1 }, // eslint-disable-line @typescript-eslint/no-unused-vars\n // -- WIP\n refresh: 'refresh' | 'cached' = 'refresh',\n customOut?: OutFn,\n filters: TestExecutionFilters = {}\n): RunTestsPromise {\n if (reRunManager !== undefined) {\n reRunManager.state.lastTestFiles = new Set(testFiles)\n reRunManager.state.activeRuns++ // whatever, obsolete. Can use it to check on things\n }\n\n const state = reRunManager?.state || makeRunManagerState()\n const runStartTime = new Date().getTime()\n const runNumber = agentRunStart(config, testFiles.size)\n const stop = makeStopSignal()\n //console.log('new runTests:', watchRunState?.activeRuns)\n //console.log(inspect(testFiles))\n\n try {\n const testRunPromises: Record<string, Promise<TestResult>> = {}\n const erroringTests: Record<string, TestFile> = {}\n const testRunOutPromises: Record<string, Promise<void>> = {}\n\n await timeProfileAsync('run tests', async () => {\n if (Array.isArray(testFiles) ? testFiles.length > 0 : testFiles.size > 0) {\n for (const testFile of testFiles) {\n //console.log('testFiles', testFiles)\n //console.log('testFile', testFile)\n\n // an earlier file failed under failFast - leave the rest unloaded\n if (stop.stopped) break\n\n const test = await loadTestFile(config, testFile, refresh)\n\n if (test.error !== undefined && test.error !== false) {\n erroringTests[testFile] = test\n state.failedTestFiles.add(testFile)\n showTestLoadingError(config, test, customOut)\n stopIfFailFast(config, stop, true)\n } else {\n const testRunPromise = runTest(config, test, filters, stop)\n testRunPromises[testFile] = testRunPromise\n\n testRunOutPromises[testFile] = testRunPromise.then(testResult => {\n if (testResult.success === true || testResult.success === null) {\n state.failedTestFiles.delete(testResult.file)\n } else {\n state.failedTestFiles.add(testFile)\n }\n const executionFilterActive = filters.describe !== undefined || filters.it !== undefined\n // a filter makes files and describes look empty when they are not\n if (!executionFilterActive) recordEntitiesWithoutTests(state, testFile, testResult)\n if (!executionFilterActive || testResult.describeResultsSummary.itsTotal > 0) {\n showTestFileResult(config, testResult, customOut)\n }\n })\n\n // wait for the test to complete before proceeding if we are in 'sequential' mode\n if (config.execution.files === 'sequential') await testRunOutPromises[testFile]\n }\n }\n }\n })\n\n let runTestResults: Record<string, TestResult> = {}\n\n await timeProfileAsync('wait for tests to finish', async () => {\n runTestResults = await promiseAllObj(testRunPromises)\n\n // wait for the output to complete\n await promiseAllObj(testRunOutPromises)\n })\n\n return showTestResultsSummary(\n runTestResults, erroringTests, runStartTime,\n config, runNumber, state, stop, filters, customOut\n )\n \n } finally {\n if (reRunManager !== undefined) reRunManager.state.activeRuns--\n }\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=showFailuresColorized.d.ts.map
@@ -0,0 +1,52 @@
1
+ // import type { OutFn } from '../../types.js'
2
+ // import type { TestFile } from './loadTestFile.js'
3
+ // import type { TestResult } from './runTest.js'
4
+ // import chalk from '../../packages/chalk.js'
5
+ // import figures from '../../packages/figures.js'
6
+ // import { failureEntries } from './failureEntries.js'
7
+ export {};
8
+ // // The run's failures gathered in one place ahead of the tallies, one line per error. The full
9
+ // // diff, logs and trace stay in each file's own output above.
10
+ // export function showFailuresColorized(
11
+ // out: OutFn,
12
+ // testResults: TestResult[],
13
+ // erroringTests: Record<string, TestFile>
14
+ // ): void {
15
+ // const entries = failureEntries(testResults, erroringTests)
16
+ // if (entries.length === 0) return
17
+ // const displayNames = new Map<string, string>()
18
+ // for (const testResult of testResults) {
19
+ // displayNames.set(testResult.file, testResult.sourceFile ?? testResult.file)
20
+ // }
21
+ // for (const [file, test] of Object.entries(erroringTests)) {
22
+ // displayNames.set(file, test.sourceFile ?? file)
23
+ // }
24
+ // out(chalk.mediumred('Failures:'))
25
+ // let currentFile: string | undefined
26
+ // let currentDescribe: string | undefined
27
+ // // entries arrive in tree order, so a heading is needed only when its value changes
28
+ // for (const entry of entries) {
29
+ // if (entry.file !== currentFile) {
30
+ // out(chalk.grey(` ${displayNames.get(entry.file) ?? entry.file}`))
31
+ // currentFile = entry.file
32
+ // currentDescribe = undefined
33
+ // }
34
+ // if (entry.describe === undefined) {
35
+ // out(chalk.mediumred(` ${entry.error}`))
36
+ // continue
37
+ // }
38
+ // if (entry.describe !== currentDescribe) {
39
+ // const number = (entry.describeNumber === undefined) ? '' : `${entry.describeNumber}) `
40
+ // out(chalk.lightgrey(` ${number}`) + chalk.brightblue(entry.describe))
41
+ // currentDescribe = entry.describe
42
+ // }
43
+ // if (entry.test === undefined) {
44
+ // out(chalk.mediumred(` ${entry.error}`))
45
+ // } else {
46
+ // const letter = (entry.testLetter === undefined) ? '' : `${entry.testLetter}) `
47
+ // out(chalk.lightgrey(` ${letter}`) + chalk.mediumred(`${figures.cross} ${entry.test}`))
48
+ // out(chalk.mediumred(` ${entry.error}`))
49
+ // }
50
+ // }
51
+ // }
52
+ //# sourceMappingURL=showFailuresColorized.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"showFailuresColorized.js","sourceRoot":"","sources":["../../../src/cli/lib/showFailuresColorized.ts"],"names":[],"mappings":"AACA,8CAA8C;AAC9C,oDAAoD;AACpD,iDAAiD;AACjD,8CAA8C;AAC9C,kDAAkD;AAClD,uDAAuD;;AAGvD,iGAAiG;AACjG,gEAAgE;AAChE,yCAAyC;AACzC,kBAAkB;AAClB,iCAAiC;AACjC,8CAA8C;AAC9C,YAAY;AACZ,iEAAiE;AACjE,uCAAuC;AAEvC,qDAAqD;AACrD,8CAA8C;AAC9C,sFAAsF;AACtF,QAAQ;AACR,kEAAkE;AAClE,0DAA0D;AAC1D,QAAQ;AAER,wCAAwC;AAExC,0CAA0C;AAC1C,8CAA8C;AAE9C,0FAA0F;AAC1F,qCAAqC;AACrC,4CAA4C;AAC5C,iFAAiF;AACjF,uCAAuC;AACvC,0CAA0C;AAC1C,YAAY;AAEZ,8CAA8C;AAC9C,yDAAyD;AACzD,uBAAuB;AACvB,YAAY;AAEZ,oDAAoD;AACpD,qGAAqG;AACrG,uFAAuF;AACvF,+CAA+C;AAC/C,YAAY;AAEZ,0CAA0C;AAC1C,2DAA2D;AAC3D,mBAAmB;AACnB,6FAA6F;AAC7F,0GAA0G;AAC1G,6DAA6D;AAC7D,YAAY;AACZ,QAAQ;AACR,IAAI","sourcesContent":["\n// import type { OutFn } from '../../types.js'\n// import type { TestFile } from './loadTestFile.js'\n// import type { TestResult } from './runTest.js'\n// import chalk from '../../packages/chalk.js'\n// import figures from '../../packages/figures.js'\n// import { failureEntries } from './failureEntries.js'\n\n\n// // The run's failures gathered in one place ahead of the tallies, one line per error. The full\n// // diff, logs and trace stay in each file's own output above.\n// export function showFailuresColorized(\n// out: OutFn,\n// testResults: TestResult[],\n// erroringTests: Record<string, TestFile>\n// ): void {\n// const entries = failureEntries(testResults, erroringTests)\n// if (entries.length === 0) return\n\n// const displayNames = new Map<string, string>()\n// for (const testResult of testResults) {\n// displayNames.set(testResult.file, testResult.sourceFile ?? testResult.file)\n// }\n// for (const [file, test] of Object.entries(erroringTests)) {\n// displayNames.set(file, test.sourceFile ?? file)\n// }\n\n// out(chalk.mediumred('Failures:'))\n\n// let currentFile: string | undefined\n// let currentDescribe: string | undefined\n\n// // entries arrive in tree order, so a heading is needed only when its value changes\n// for (const entry of entries) {\n// if (entry.file !== currentFile) {\n// out(chalk.grey(` ${displayNames.get(entry.file) ?? entry.file}`))\n// currentFile = entry.file\n// currentDescribe = undefined\n// }\n\n// if (entry.describe === undefined) {\n// out(chalk.mediumred(` ${entry.error}`))\n// continue\n// }\n\n// if (entry.describe !== currentDescribe) {\n// const number = (entry.describeNumber === undefined) ? '' : `${entry.describeNumber}) `\n// out(chalk.lightgrey(` ${number}`) + chalk.brightblue(entry.describe))\n// currentDescribe = entry.describe\n// }\n\n// if (entry.test === undefined) {\n// out(chalk.mediumred(` ${entry.error}`))\n// } else {\n// const letter = (entry.testLetter === undefined) ? '' : `${entry.testLetter}) `\n// out(chalk.lightgrey(` ${letter}`) + chalk.mediumred(`${figures.cross} ${entry.test}`))\n// out(chalk.mediumred(` ${entry.error}`))\n// }\n// }\n// }\n"]}
@@ -0,0 +1,7 @@
1
+ import type { FinalConfig, OutFn } from '../../types.js';
2
+ import type { TestResult } from './runTest.js';
3
+ export interface ShowTestFileResultOptions {
4
+ failuresOnly?: boolean;
5
+ }
6
+ export declare function showTestFileResult(config: FinalConfig, testResult: TestResult, customOut?: OutFn, { failuresOnly }?: ShowTestFileResultOptions): void;
7
+ //# sourceMappingURL=showTestFileResult.d.ts.map
@@ -1,11 +1,9 @@
1
1
  import { inspect } from 'node:util';
2
2
  import chalk from '../../packages/chalk.js';
3
3
  import figures from '../../packages/figures.js';
4
- import { createTimeProfiler } from '../../packages/timeProfiler.js';
5
- import { showTimeProfiling } from '../../config.js';
6
4
  import { out as mainOut } from '../../output.js';
7
5
  import { indexNumberToLetters } from '../../indexNumberToLetters.js';
8
- const { timeProfileAsync } = createTimeProfiler(showTimeProfiling);
6
+ import { timeProfile } from './timeProfiler.js';
9
7
  function IsErrorLike(v) {
10
8
  return typeof v === 'object' && v !== null
11
9
  && 'name' in v && typeof v.name === 'string'
@@ -38,16 +36,20 @@ function showExpected(err, column) {
38
36
  }
39
37
  return showValue(err.expected, column);
40
38
  }
39
+ function describeFailed(describeResult) {
40
+ return describeResult.error !== undefined
41
+ || describeResult.itResults.some(itResult => itResult.success === false);
42
+ }
41
43
  function display(u) {
42
44
  if (typeof u === 'string')
43
45
  return u;
44
46
  return inspect(u);
45
47
  }
46
- export async function showTestResult(config, testResult, customOut) {
48
+ export function showTestFileResult(config, testResult, customOut, { failuresOnly = false } = {}) {
47
49
  const out = customOut ?? mainOut;
48
50
  // compact keeps only the blank line that separates files
49
51
  const gap = config.compact ? () => { } : () => { out(); };
50
- await timeProfileAsync('show test result', () => {
52
+ timeProfile('show test result', () => {
51
53
  out();
52
54
  const fileTime = (testResult.time === undefined) ? '' : ` ${testResult.time.toLocaleString()}ms`
53
55
  + ((testResult.loadTime === undefined)
@@ -55,7 +57,7 @@ export async function showTestResult(config, testResult, customOut) {
55
57
  : ` (${testResult.loadTime.toLocaleString()}ms module re-loading)`);
56
58
  out(chalk.grey `File ${testResult.sourceFile ?? testResult.file}${fileTime}`);
57
59
  const indent = ' ';
58
- if (testResult.logs.length > 0) {
60
+ if (!failuresOnly && testResult.logs.length > 0) {
59
61
  gap();
60
62
  out(chalk.grey `console.logs:`);
61
63
  testResult.logs.forEach(log => {
@@ -63,12 +65,14 @@ export async function showTestResult(config, testResult, customOut) {
63
65
  });
64
66
  gap();
65
67
  }
66
- if (testResult.describeResults.length === 0) {
68
+ if (!failuresOnly && testResult.describeResults.length === 0) {
67
69
  out('No describes');
68
70
  gap();
69
71
  }
70
72
  let first = true;
71
73
  for (const describeResult of testResult.describeResults) {
74
+ if (failuresOnly && !describeFailed(describeResult))
75
+ continue;
72
76
  if (!first)
73
77
  gap();
74
78
  first = false;
@@ -77,7 +81,7 @@ export async function showTestResult(config, testResult, customOut) {
77
81
  if (describeResult.itResults.length === 0 && !('error' in describeResult))
78
82
  out(`${indent}No tests`);
79
83
  gap();
80
- if (describeResult.logs && describeResult.logs.length > 0) {
84
+ if (!failuresOnly && describeResult.logs && describeResult.logs.length > 0) {
81
85
  out(chalk.grey `console.logs:`);
82
86
  describeResult.logs.forEach(log => {
83
87
  out(...log);
@@ -100,6 +104,8 @@ export async function showTestResult(config, testResult, customOut) {
100
104
  gap();
101
105
  }
102
106
  for (const itResult of describeResult.itResults) {
107
+ if (failuresOnly && itResult.success !== false)
108
+ continue;
103
109
  const letters = indexNumberToLetters(itResult.counter) ?? '';
104
110
  const itTime = chalk.grey ` ${itResult.time.toLocaleString()}ms`;
105
111
  if (itResult.success === true) {
@@ -150,4 +156,4 @@ export async function showTestResult(config, testResult, customOut) {
150
156
  }
151
157
  });
152
158
  }
153
- //# sourceMappingURL=showTestResult.js.map
159
+ //# sourceMappingURL=showTestFileResult.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"showTestFileResult.js","sourceRoot":"","sources":["../../../src/cli/lib/showTestFileResult.ts"],"names":[],"mappings":"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","sourcesContent":["\nimport type { Expand } from 'sxy-lib/types/Expand.js'\nimport { inspect } from 'node:util'\n\nimport type { FinalConfig, OutFn } from '../../types.js'\nimport type { DescribeResult } from './runDescribe.js'\nimport type { TestResult } from './runTest.js'\nimport chalk from '../../packages/chalk.js'\nimport figures from '../../packages/figures.js'\nimport { out as mainOut } from '../../output.js'\nimport { indexNumberToLetters } from '../../indexNumberToLetters.js'\nimport { timeProfile } from './timeProfiler.js'\n\n\n// Assertion failures are recognised by shape, not by where they came from. Importing an\n// assertion library to test `instanceof` against cannot work here: the runner would need it\n// as a dependency, and the copy a test file throws from is a separate ESM instance anyway,\n// so the check fails for the very errors it is meant to catch.\n\n\ninterface ErrorLike {\n name: string\n message: string\n stack?: unknown\n cause?: unknown\n}\ninterface AssertionLike extends ErrorLike {\n actual?: unknown\n expected?: unknown\n}\nfunction IsErrorLike(v: unknown): v is Expand<ErrorLike> {\n return typeof v === 'object' && v !== null\n && 'name' in v && typeof v.name === 'string'\n && 'message' in v && typeof v.message === 'string'\n}\nfunction ErrorLikeIsAssertionLike(v: ErrorLike): v is Expand<AssertionLike> {\n return ('actual' in v || 'expected' in v)\n}\n\n\n// Node's assertion messages run to several lines. Later lines are indented to the message\n// column and blank ones dropped; a single line message passes through untouched.\nfunction alignMessage(message: string, spacer: string): string {\n return message.split('\\n').reduce<string[]>(\n (previous, line) => (previous.length === 0)\n ? [line]\n : (line.trim()) ? [...previous, spacer + line] : previous,\n []\n ).join('\\n')\n}\n\n// A multi line string is shown as text, indented under its label. inspect() would render it\n// as one quoted chunk per line joined with `+`, which buries the content it is there to\n// show. Everything else - objects, and single line strings, whose quotes reveal padding and\n// emptiness - still goes through inspect.\nfunction showValue(value: unknown, column: string): string {\n if (typeof value !== 'string' || !value.includes('\\n')) {\n return inspect(value, { depth: 5 })\n }\n return value.split('\\n').join(`\\n${column}`)\n}\n\n// sxy-assert describes an expected that is no single value (not null, instanceof) rather than carrying one\nfunction showExpected(err: AssertionLike, column: string): string {\n if (!('expected' in err) && 'expectedDescription' in err && typeof err.expectedDescription === 'string') {\n return err.expectedDescription\n }\n return showValue(err.expected, column)\n}\n\nfunction describeFailed(describeResult: DescribeResult): boolean {\n return describeResult.error !== undefined\n || describeResult.itResults.some(itResult => itResult.success === false)\n}\n\nfunction display(u: unknown): string {\n if (typeof u === 'string') return u\n return inspect(u)\n}\n\nexport interface ShowTestFileResultOptions {\n // for the summary: only what failed, and only the failing tests' own logs\n failuresOnly?: boolean\n}\n\nexport function showTestFileResult(\n config: FinalConfig,\n testResult: TestResult,\n customOut?: OutFn,\n { failuresOnly = false }: ShowTestFileResultOptions = {}\n): void {\n const out = customOut ?? mainOut\n // compact keeps only the blank line that separates files\n const gap = config.compact ? () => {} : () => { out() }\n\n timeProfile('show test result', () => {\n out()\n const fileTime = (testResult.time === undefined) ? '' : ` ${testResult.time.toLocaleString()}ms`\n + ((testResult.loadTime === undefined)\n ? ''\n : ` (${testResult.loadTime.toLocaleString()}ms module re-loading)`)\n out(chalk.grey`File ${testResult.sourceFile ?? testResult.file}${fileTime}`)\n\n const indent = ' '\n\n if (!failuresOnly && testResult.logs.length > 0) {\n gap()\n out(chalk.grey`console.logs:`)\n testResult.logs.forEach(log => {\n out(...log)\n })\n gap()\n }\n\n if (!failuresOnly && testResult.describeResults.length === 0) {\n out('No describes')\n gap()\n }\n\n let first = true\n\n for (const describeResult of testResult.describeResults) {\n if (failuresOnly && !describeFailed(describeResult)) continue\n\n if (!first) gap()\n first = false\n\n out(chalk.lightgrey`${describeResult.counter}) describing ` + chalk.brightblue(describeResult.thing)\n + chalk.grey` ${describeResult.time.toLocaleString()}ms`)\n if (describeResult.itResults.length === 0 && !('error' in describeResult)) out(`${indent}No tests`)\n gap()\n\n if (!failuresOnly && describeResult.logs && describeResult.logs.length > 0) {\n out(chalk.grey`console.logs:`)\n describeResult.logs.forEach(log => {\n out(...log)\n })\n gap()\n }\n\n if ('error' in describeResult) {\n const describeError = describeResult.error\n\n out(chalk.mediumred(`${indent}Threw:`))\n if (IsErrorLike(describeError)) {\n out(chalk.mediumred(`${indent}${describeError.name}: ${describeError.message}`))\n if (config.showErrorTrace && 'stack' in describeError) {\n gap()\n out(chalk.grey(display(describeError.stack)))\n }\n } else {\n out(chalk.mediumred(`${indent}${display(describeError)}`))\n }\n gap()\n }\n\n for (const itResult of describeResult.itResults) {\n if (failuresOnly && itResult.success !== false) continue\n\n const letters = indexNumberToLetters(itResult.counter) ?? ''\n const itTime = chalk.grey` ${itResult.time.toLocaleString()}ms`\n if (itResult.success === true) {\n out(chalk.lightgrey`${indent}${letters})`\n + chalk.mediumgreen` ${figures.tick} ${itResult.should}` + itTime)\n } else {\n out(chalk.lightgrey`${indent}${letters})`\n + chalk.mediumred` ${figures.cross} ${itResult.should}` + itTime)\n gap()\n const spacer = `${indent}${' '.repeat(letters.length)} `\n if ('error' in itResult) {\n const err = itResult.error\n if (IsErrorLike(err)) {\n if (ErrorLikeIsAssertionLike(err)) {\n out(chalk.mediumred(\n //`${spacer}Assertion Failed: ${alignMessage(err.message, spacer)}`\n `${spacer}${err.name}: ${alignMessage(err.message, spacer)}`\n ))\n // shown whenever the error carries them, so a falsy actual or\n // expected - 0, '', false, null - still gets its diff\n const valueColumn = `${spacer} `\n out(\n chalk.yellow`${spacer}Actual ${showValue(err.actual, valueColumn)}\\n`\n + chalk.brightblue`${spacer}Expected ${showExpected(err, valueColumn)}`\n )\n } else {\n out(chalk.mediumred(\n `${spacer}${err.name}: ${alignMessage(err.message, spacer)}`\n ))\n }\n // stack trace\n if (config.showErrorTrace && 'stack' in err) {\n gap()\n out(chalk.grey(display(err.stack)))\n }\n } else {\n out(chalk.mediumred(\n `${spacer}${display(err)}`\n ))\n }\n }\n }\n\n gap()\n if (itResult.logs.length > 0) {\n out(chalk.grey`console.logs:`)\n itResult.logs.forEach(log => {\n out(...log)\n })\n gap()\n }\n }\n }\n })\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import type { FinalConfig, OutFn } from '../../types.js';
2
+ import type { TestExecutionFilters } from '../cliTypes.js';
3
+ import type { TestFile } from './loadTestFile.js';
4
+ import type { ReRunManageState } from './makeWatchRunState.js';
5
+ import type { TestResult } from './runTest.js';
6
+ import type { StopSignal } from './stopSignal.js';
7
+ export declare function showTestResultsSummary(runTestResults: Record<string, TestResult>, erroringTests: Record<string, TestFile>, runStartTime: number, config: FinalConfig, runNumber: number, state: ReRunManageState, stop: StopSignal, filters: TestExecutionFilters, customOut?: OutFn): boolean | null;
8
+ //# sourceMappingURL=showTestResultsSummary.d.ts.map