sxy-test-runner 2.5.3 → 2.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/AGENTS.md +47 -21
  2. package/dist/cli/lib/agentReport.d.ts +1 -0
  3. package/dist/cli/lib/agentReport.js +3 -0
  4. package/dist/cli/lib/agentReport.js.map +1 -1
  5. package/dist/cli/lib/buildDependencyTree.d.ts +1 -2
  6. package/dist/cli/lib/buildDependencyTree.js +25 -23
  7. package/dist/cli/lib/buildDependencyTree.js.map +1 -1
  8. package/dist/cli/lib/buildDependencyTrees.d.ts +1 -2
  9. package/dist/cli/lib/buildDependencyTrees.js +18 -16
  10. package/dist/cli/lib/buildDependencyTrees.js.map +1 -1
  11. package/dist/cli/lib/esmGraphReload.d.ts +5 -0
  12. package/dist/cli/lib/esmGraphReload.js +24 -0
  13. package/dist/cli/lib/esmGraphReload.js.map +1 -0
  14. package/dist/cli/lib/esmTreeReload.d.ts +4 -0
  15. package/dist/cli/lib/esmTreeReload.js +62 -0
  16. package/dist/cli/lib/esmTreeReload.js.map +1 -0
  17. package/dist/cli/lib/handleUserInput.d.ts +2 -2
  18. package/dist/cli/lib/handleUserInput.js +13 -6
  19. package/dist/cli/lib/handleUserInput.js.map +1 -1
  20. package/dist/cli/lib/listenToUser.d.ts +2 -2
  21. package/dist/cli/lib/listenToUser.js.map +1 -1
  22. package/dist/cli/lib/loadTestFile.d.ts +0 -1
  23. package/dist/cli/lib/loadTestFile.js +23 -8
  24. package/dist/cli/lib/loadTestFile.js.map +1 -1
  25. package/dist/cli/lib/makeDependencyGraph.d.ts +10 -0
  26. package/dist/cli/lib/makeDependencyGraph.js +210 -0
  27. package/dist/cli/lib/makeDependencyGraph.js.map +1 -0
  28. package/dist/cli/lib/reRunManager.js +4 -6
  29. package/dist/cli/lib/reRunManager.js.map +1 -1
  30. package/dist/cli/lib/runTests.js +7 -2
  31. package/dist/cli/lib/runTests.js.map +1 -1
  32. package/dist/cli/lib/showTestResultsSummary.d.ts +1 -1
  33. package/dist/cli/lib/showTestResultsSummary.js +5 -1
  34. package/dist/cli/lib/showTestResultsSummary.js.map +1 -1
  35. package/dist/cli/lib/statusFile.js +20 -1
  36. package/dist/cli/lib/statusFile.js.map +1 -1
  37. package/dist/cli/lib/watchFilesAndRunTestsNodeWatch.d.ts +3 -2
  38. package/dist/cli/lib/watchFilesAndRunTestsNodeWatch.js +24 -48
  39. package/dist/cli/lib/watchFilesAndRunTestsNodeWatch.js.map +1 -1
  40. package/dist/cli/watch.js +25 -12
  41. package/dist/cli/watch.js.map +1 -1
  42. package/dist/describe.js +5 -3
  43. package/dist/describe.js.map +1 -1
  44. package/dist/meta.js +2 -1
  45. package/dist/meta.js.map +1 -1
  46. package/dist/registration.d.ts +4 -0
  47. package/dist/registration.js +34 -0
  48. package/dist/registration.js.map +1 -0
  49. package/dist/types.d.ts +8 -0
  50. package/dist/types.js.map +1 -1
  51. package/package.json +11 -6
  52. package/readme.md +16 -123
  53. package/dist/packages/esmReload.d.ts +0 -11
  54. package/dist/packages/esmReload.js +0 -43
  55. package/dist/packages/esmReload.js.map +0 -1
@@ -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(\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"]}
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 // what the run covered, e.g. 'all' or 'failures', shown uncoloured after the tallies\r\n runLabel?: string\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 if (runLabel !== undefined) out(`(${runLabel})`)\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"]}
@@ -46,6 +46,25 @@ function localTime(date) {
46
46
  + ` ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`
47
47
  + ` ${offset}`;
48
48
  }
49
+ const renameAttempts = 10;
50
+ const renameRetryMs = 10;
51
+ const transientRenameCodes = new Set(['EPERM', 'EBUSY', 'EACCES']);
52
+ // Windows refuses a rename over a file something else briefly holds open - antivirus or the
53
+ // indexer, typically just after it was written - so a refusal is waited out for a moment
54
+ function renameRetrying(from, to) {
55
+ for (let attempt = 1;; attempt++) {
56
+ try {
57
+ fs.renameSync(from, to);
58
+ return;
59
+ }
60
+ catch (error) {
61
+ const code = (error instanceof Error && 'code' in error) ? String(error.code) : '';
62
+ if (attempt >= renameAttempts || !transientRenameCodes.has(code))
63
+ throw error;
64
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, renameRetryMs);
65
+ }
66
+ }
67
+ }
49
68
  function write(config, contents) {
50
69
  const statusFile = config.watch.statusFile;
51
70
  if (typeof statusFile !== 'string' || statusFile === '')
@@ -56,7 +75,7 @@ function write(config, contents) {
56
75
  try {
57
76
  fs.mkdirSync(path.dirname(location), { recursive: true });
58
77
  fs.writeFileSync(tempLocation, contents);
59
- fs.renameSync(tempLocation, location);
78
+ renameRetrying(tempLocation, location);
60
79
  }
61
80
  catch (error) {
62
81
  // never let the status file take the run down with it
@@ -1 +1 @@
1
- {"version":3,"file":"statusFile.js","sourceRoot":"","sources":["../../../src/cli/lib/statusFile.ts"],"names":[],"mappings":"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","sourcesContent":["\nimport fs from 'fs'\nimport path from 'path'\n\nimport type { FinalConfig } from '../../types.js'\nimport chalk from '../../packages/chalk.js'\nimport { packageName } from '../../config.js'\nimport { log } from '../../output.js'\n\n\n// The status file holds the result of the latest run: `<code> - <description>` on the first\n// line, then any detail. Watch mode resets it to -1 on startup so a stale result is never\n// mistaken for the current one.\nexport const statusCodes = {\n notRunYet: -1, // watch mode has started, but no run has finished\n passed: 0,\n failed: 1, // tests ran and failed\n aborted: 2, // the run died partway - a test file failed to load, or a describe threw\n couldNotRun: 3 // nothing ran at all - no test files, or no match for the filters\n} as const\n\nexport type StatusCode = typeof statusCodes[keyof typeof statusCodes]\n\n// The same states as words, for the agent stream. A number needs the table above to mean\n// anything; a reader of one line should not have to go and find it. Defined here so the two\n// cannot drift apart.\nexport const statusNames: Record<StatusCode, string> = {\n [statusCodes.notRunYet]: 'not-run',\n [statusCodes.passed]: 'passed',\n [statusCodes.failed]: 'failed',\n [statusCodes.aborted]: 'aborted',\n [statusCodes.couldNotRun]: 'could-not-run'\n}\n\nexport function resetStatusFile(config: FinalConfig): void {\n writeStatusFile(config, statusCodes.notRunYet, 'no run has finished yet')\n}\n\nexport function writeStatusFile(\n config: FinalConfig,\n code: StatusCode,\n description: string,\n details: string[] = [],\n durationMs?: number\n): void {\n write(config, [\n `${code} - ${description}`,\n localTime(new Date()),\n ...details,\n ...(durationMs === undefined) ? [] : [`${durationMs.toLocaleString()}ms`]\n ].join('\\n') + '\\n')\n}\n\n// local time, so the file reads the way the terminal beside it does, with the offset so a\n// reader elsewhere can still place it\nfunction localTime(date: Date): string {\n const pad = (value: number): string => String(value).padStart(2, '0')\n // getTimezoneOffset() counts minutes behind UTC, so the sign is the other way round\n const offsetMinutes = -date.getTimezoneOffset()\n const offset = `${(offsetMinutes < 0) ? '-' : '+'}`\n + `${pad(Math.floor(Math.abs(offsetMinutes) / 60))}:${pad(Math.abs(offsetMinutes) % 60)}`\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`\n + ` ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`\n + ` ${offset}`\n}\n\nfunction write(config: FinalConfig, contents: string): void {\n const statusFile = config.watch.statusFile\n if (typeof statusFile !== 'string' || statusFile === '') return\n\n const location = path.resolve(process.cwd(), statusFile)\n // written via a temp file and renamed, so a poller never reads a half written status\n const tempLocation = `${location}.${process.pid}.tmp`\n try {\n fs.mkdirSync(path.dirname(location), { recursive: true })\n fs.writeFileSync(tempLocation, contents)\n fs.renameSync(tempLocation, location)\n } catch (error) {\n // never let the status file take the run down with it\n log(chalk.mediumred(\n `[${packageName}] Could not write status file ${location}: ${String(error)}`\n ))\n try { fs.rmSync(tempLocation, { force: true }) } catch { /* nothing more to do */ }\n }\n}\n"]}
1
+ {"version":3,"file":"statusFile.js","sourceRoot":"","sources":["../../../src/cli/lib/statusFile.ts"],"names":[],"mappings":"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","sourcesContent":["\nimport fs from 'fs'\nimport path from 'path'\n\nimport type { FinalConfig } from '../../types.js'\nimport chalk from '../../packages/chalk.js'\nimport { packageName } from '../../config.js'\nimport { log } from '../../output.js'\n\n\n// The status file holds the result of the latest run: `<code> - <description>` on the first\n// line, then any detail. Watch mode resets it to -1 on startup so a stale result is never\n// mistaken for the current one.\nexport const statusCodes = {\n notRunYet: -1, // watch mode has started, but no run has finished\n passed: 0,\n failed: 1, // tests ran and failed\n aborted: 2, // the run died partway - a test file failed to load, or a describe threw\n couldNotRun: 3 // nothing ran at all - no test files, or no match for the filters\n} as const\n\nexport type StatusCode = typeof statusCodes[keyof typeof statusCodes]\n\n// The same states as words, for the agent stream. A number needs the table above to mean\n// anything; a reader of one line should not have to go and find it. Defined here so the two\n// cannot drift apart.\nexport const statusNames: Record<StatusCode, string> = {\n [statusCodes.notRunYet]: 'not-run',\n [statusCodes.passed]: 'passed',\n [statusCodes.failed]: 'failed',\n [statusCodes.aborted]: 'aborted',\n [statusCodes.couldNotRun]: 'could-not-run'\n}\n\nexport function resetStatusFile(config: FinalConfig): void {\n writeStatusFile(config, statusCodes.notRunYet, 'no run has finished yet')\n}\n\nexport function writeStatusFile(\n config: FinalConfig,\n code: StatusCode,\n description: string,\n details: string[] = [],\n durationMs?: number\n): void {\n write(config, [\n `${code} - ${description}`,\n localTime(new Date()),\n ...details,\n ...(durationMs === undefined) ? [] : [`${durationMs.toLocaleString()}ms`]\n ].join('\\n') + '\\n')\n}\n\n// local time, so the file reads the way the terminal beside it does, with the offset so a\n// reader elsewhere can still place it\nfunction localTime(date: Date): string {\n const pad = (value: number): string => String(value).padStart(2, '0')\n // getTimezoneOffset() counts minutes behind UTC, so the sign is the other way round\n const offsetMinutes = -date.getTimezoneOffset()\n const offset = `${(offsetMinutes < 0) ? '-' : '+'}`\n + `${pad(Math.floor(Math.abs(offsetMinutes) / 60))}:${pad(Math.abs(offsetMinutes) % 60)}`\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`\n + ` ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`\n + ` ${offset}`\n}\n\nconst renameAttempts = 10\nconst renameRetryMs = 10\nconst transientRenameCodes = new Set(['EPERM', 'EBUSY', 'EACCES'])\n\n// Windows refuses a rename over a file something else briefly holds open - antivirus or the\n// indexer, typically just after it was written - so a refusal is waited out for a moment\nfunction renameRetrying(from: string, to: string): void {\n for (let attempt = 1; ; attempt++) {\n try {\n fs.renameSync(from, to)\n return\n } catch (error) {\n const code = (error instanceof Error && 'code' in error) ? String(error.code) : ''\n if (attempt >= renameAttempts || !transientRenameCodes.has(code)) throw error\n Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, renameRetryMs)\n }\n }\n}\n\nfunction write(config: FinalConfig, contents: string): void {\n const statusFile = config.watch.statusFile\n if (typeof statusFile !== 'string' || statusFile === '') return\n\n const location = path.resolve(process.cwd(), statusFile)\n // written via a temp file and renamed, so a poller never reads a half written status\n const tempLocation = `${location}.${process.pid}.tmp`\n try {\n fs.mkdirSync(path.dirname(location), { recursive: true })\n fs.writeFileSync(tempLocation, contents)\n renameRetrying(tempLocation, location)\n } catch (error) {\n // never let the status file take the run down with it\n log(chalk.mediumred(\n `[${packageName}] Could not write status file ${location}: ${String(error)}`\n ))\n try { fs.rmSync(tempLocation, { force: true }) } catch { /* nothing more to do */ }\n }\n}\n"]}
@@ -1,6 +1,7 @@
1
- import type { FinalConfig, DependencyTrees, OutFn } from '../../types.js';
1
+ import type { FinalConfig, OutFn } from '../../types.js';
2
2
  import type { TestExecutionFilters } from '../cliTypes.js';
3
3
  import type { ReRunManager } from './reRunManager.js';
4
+ import type { DependencyGraph } from './makeDependencyGraph.js';
4
5
  import type { StopFn } from '../watch.js';
5
- export declare function watchFilesAndRunTestsNodeWatch(config: FinalConfig, dependencyTrees: DependencyTrees, failingTests: string[], reRunManager: ReRunManager, customOut?: OutFn, executionFilters?: TestExecutionFilters): Promise<StopFn>;
6
+ export declare function watchFilesAndRunTestsNodeWatch(config: FinalConfig, dependencyGraph: DependencyGraph | null, failingTests: string[], reRunManager: ReRunManager, customOut?: OutFn, executionFilters?: TestExecutionFilters): Promise<StopFn>;
6
7
  //# sourceMappingURL=watchFilesAndRunTestsNodeWatch.d.ts.map
@@ -6,7 +6,6 @@ import { showTimeProfiling } from '../../config.js';
6
6
  import { out as mainOut, log, debug } from '../../output.js';
7
7
  import { agentChange } from './agentReport.js';
8
8
  import { runTests } from './runTests.js';
9
- import { buildDependencyTree } from './buildDependencyTree.js';
10
9
  import { globArgCombine } from './globArgCombine.js';
11
10
  import { addBasePath } from './addBasePath.js';
12
11
  import { watchFilesNodeWatch } from './watchFilesNodeWatch.js';
@@ -14,10 +13,10 @@ import { filter } from './filter.js';
14
13
  const { timeProfile, timeProfileAsync } = createTimeProfiler(showTimeProfiling);
15
14
  export async function watchFilesAndRunTestsNodeWatch(config,
16
15
  //testFiles: Set<string>,
17
- dependencyTrees, failingTests, reRunManager,
16
+ // null when watch.dependencyEvaluation is off
17
+ dependencyGraph, failingTests, reRunManager,
18
18
  //watchRunState: WatchRunState,
19
19
  customOut, executionFilters = {}) {
20
- const projectDir = process.cwd();
21
20
  // agent mode passes a sink here, so its own change lines are the only ones printed
22
21
  const out = customOut ?? mainOut;
23
22
  return timeProfileAsync('init watching', async () => {
@@ -48,18 +47,11 @@ customOut, executionFilters = {}) {
48
47
  function watchEvent(filename, event) {
49
48
  debug('handle watch event ', filename, event);
50
49
  filename = slash(filename);
51
- // remove dep tree for any tests that are deleted, avoiding trying to run it later
50
+ // forget a deleted test, avoiding trying to run it later
52
51
  if (event === 'remove') {
53
52
  debug('removing test', filename);
54
53
  reRunManager.state.withoutTests.delete(filename);
55
- if (filename in dependencyTrees) {
56
- reRunManager.state.allTestFiles.delete(filename);
57
- delete dependencyTrees[filename];
58
- }
59
- else if (!config.watch.dependencyEvaluation) {
60
- // without trees there is nothing to look the file up in
61
- reRunManager.state.allTestFiles.delete(filename);
62
- }
54
+ reRunManager.state.allTestFiles.delete(filename);
63
55
  }
64
56
  // info on the event found
65
57
  out(chalk.grey `change: ${filename} (${event})`);
@@ -75,47 +67,39 @@ customOut, executionFilters = {}) {
75
67
  timeProfile('handle changed files', () => {
76
68
  debug('changedFiles', changedFiles);
77
69
  try {
70
+ // the whole batch is applied before any lookup, so an import added in one
71
+ // file can reach a file created in the same batch
72
+ if (dependencyGraph !== null) {
73
+ for (const [file, fileEvent] of changedFiles) {
74
+ if (fileEvent === 'remove')
75
+ dependencyGraph.remove(file);
76
+ else if (testFilter(file))
77
+ dependencyGraph.addTest(file);
78
+ else
79
+ dependencyGraph.update(file);
80
+ }
81
+ }
78
82
  // build related test list
79
- //const tests: string[] = []
80
83
  const tests = new Set;
81
84
  for (const [file, fileEvent] of changedFiles) {
82
85
  debug('check', file);
83
- debug('1 tests', tests);
84
86
  if (fileEvent !== 'remove') { // only check if it's a test if it exists (has not just been removed)
85
87
  if (testFilter(file)) { // it is a test file itself, add to run list
86
88
  debug('its a test', file);
87
- //tests.push(file)
88
89
  tests.add(file);
89
- if (config.watch.dependencyEvaluation) {
90
- if (!(file in dependencyTrees)) { // if its a new test
91
- debug('try to add a new test', file);
92
- addNewTest(file);
93
- }
94
- }
95
- else {
96
- // no trees to record it in, so this is what makes a
97
- // newly created test part of the run set
98
- reRunManager.state.allTestFiles.add(file);
99
- }
90
+ // makes a newly created test part of what `a` runs
91
+ reRunManager.state.allTestFiles.add(file);
100
92
  }
101
93
  }
102
94
  // with evaluation off there is nothing to map the change through:
103
95
  // any watched file could affect any test, so run the lot
104
- if (!config.watch.dependencyEvaluation) {
96
+ if (dependencyGraph === null) {
105
97
  for (const f of reRunManager.state.allTestFiles)
106
98
  tests.add(f);
107
99
  continue;
108
100
  }
109
- debug('dtrees', dependencyTrees);
110
- debug('2 tests', tests);
111
- for (const f of Object.getOwnPropertyNames(dependencyTrees)) {
112
- debug('dep tree', f, dependencyTrees[f]);
113
- if (dependencyTrees[f]?.some(dep => dep === file) === true) { // a test depends on this file
114
- debug('its a dependency', file);
115
- //tests.push(f)
116
- tests.add(f);
117
- }
118
- }
101
+ for (const f of dependencyGraph.testsAffectedBy(file))
102
+ tests.add(f);
119
103
  }
120
104
  changedFiles = [];
121
105
  debug('tests', tests);
@@ -126,14 +110,13 @@ customOut, executionFilters = {}) {
126
110
  // changes accumulate here because an 'auto' request made while a
127
111
  // run is in flight is coalesced into the queued one - everything
128
112
  // edited in the meantime still has to be covered
129
- reRunManager.state.untestedFiles
130
- = reRunManager.state.untestedFiles.union(tests);
113
+ for (const test of tests)
114
+ reRunManager.state.untestedFiles.add(test);
131
115
  void reRunManager.requestRun('auto', () => {
132
116
  // resolved when the run actually starts, not when it is
133
117
  // queued, so a coalesced request picks up the later edits
134
118
  const toTest = (config.watch.reRunFailingTests)
135
- ? reRunManager.state.untestedFiles
136
- .union(reRunManager.state.failedTestFiles)
119
+ ? reRunManager.state.untestedFiles.union(reRunManager.state.failedTestFiles)
137
120
  : new Set(reRunManager.state.untestedFiles);
138
121
  // consumed by this run - without this they are retested
139
122
  // on every later run for the rest of the session
@@ -151,13 +134,6 @@ customOut, executionFilters = {}) {
151
134
  });
152
135
  }, debounceMs);
153
136
  } // end of watch event
154
- function addNewTest(testFile) {
155
- debug('new test', testFile);
156
- const dependencyTree = buildDependencyTree(config, testFile);
157
- dependencyTrees[testFile] = dependencyTree
158
- .map(file => slash(file).slice(projectDir.length + 1))
159
- .filter(f => f !== testFile);
160
- }
161
137
  });
162
138
  // NOTE: "watching..." is intentionally NOT printed here. watch() already emits it,
163
139
  // tied to a real milestone (the initial test run finishing, or no tests found).
@@ -1 +1 @@
1
- {"version":3,"file":"watchFilesAndRunTestsNodeWatch.js","sourceRoot":"","sources":["../../../src/cli/lib/watchFilesAndRunTestsNodeWatch.ts"],"names":[],"mappings":"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","sourcesContent":["\nimport { matchesGlob } from 'node:path'\n\nimport type { FinalConfig, DependencyTrees, OutFn } from '../../types.js'\nimport type { TestExecutionFilters } from '../cliTypes.js'\nimport type { ReRunManager } from './reRunManager.js'\nimport type { StopFn } from '../watch.js'\nimport chalk from '../../packages/chalk.js'\nimport slash from '../../packages/slash.js'\nimport { createTimeProfiler } from '../../packages/timeProfiler.js'\nimport { showTimeProfiling } from '../../config.js'\nimport { out as mainOut, log, debug } from '../../output.js'\nimport { agentChange } from './agentReport.js'\nimport { runTests } from './runTests.js'\nimport { buildDependencyTree } from './buildDependencyTree.js'\nimport { globArgCombine } from './globArgCombine.js'\nimport { addBasePath } from './addBasePath.js'\nimport { watchFilesNodeWatch } from './watchFilesNodeWatch.js'\nimport { filter } from './filter.js'\n\n\nconst { timeProfile, timeProfileAsync } = createTimeProfiler(showTimeProfiling)\n\nexport async function watchFilesAndRunTestsNodeWatch(\n config: FinalConfig,\n //testFiles: Set<string>,\n dependencyTrees: DependencyTrees,\n failingTests: string[],\n reRunManager: ReRunManager,\n //watchRunState: WatchRunState,\n customOut?: OutFn,\n executionFilters: TestExecutionFilters = {}\n): Promise<StopFn> {\n const projectDir = process.cwd()\n // agent mode passes a sink here, so its own change lines are the only ones printed\n const out = customOut ?? mainOut\n\n return timeProfileAsync('init watching', async () => {\n debug('failingTests', failingTests)\n\n const testsGlobs = addBasePath(config.testsBase, config.tests)\n const testsIgnoreGlobs = addBasePath(config.testsBase, config.testsIgnore)\n\n // indentify a test file\n const testFilter = (file: string): boolean => {\n return matchesGlob(file, globArgCombine(testsGlobs))\n && !matchesGlob(file, globArgCombine(testsIgnoreGlobs))\n && (\n config.testsFilter === undefined\n || config.testsFilter === ''\n || filter(config.testsBase, config.testsFilter, file)\n )\n }\n\n let changedFiles: Array<[string, string]> = []\n let timeout: ReturnType<typeof setTimeout> | null = null\n\n if (config.watch.watchFilesBase === '') {\n out('No config.watch.watchFilesBase provided, defaulting to \\'.\\'')\n config.watch.watchFilesBase = '.'\n }\n\n const watcher = await watchFilesNodeWatch(config, watchEvent)\n return () => {\n watcher.close()\n // a change seen just before stopping would otherwise still run its tests\n if (timeout) clearTimeout(timeout)\n }\n\n function watchEvent(filename: string, event: string): void {\n debug('handle watch event ', filename, event)\n\n filename = slash(filename)\n\n // remove dep tree for any tests that are deleted, avoiding trying to run it later\n if (event === 'remove') {\n debug('removing test', filename)\n reRunManager.state.withoutTests.delete(filename)\n if (filename in dependencyTrees) {\n reRunManager.state.allTestFiles.delete(filename)\n delete dependencyTrees[filename]\n } else if (!config.watch.dependencyEvaluation) {\n // without trees there is nothing to look the file up in\n reRunManager.state.allTestFiles.delete(filename)\n }\n }\n\n // info on the event found\n out(chalk.grey`change: ${filename} (${event})`)\n agentChange(config, filename, event)\n\n // add the file to changed files\n changedFiles.push([filename, event])\n\n // 33ms debounce\n const debounceMs = 33\n if (timeout) {\n clearTimeout(timeout)\n }\n timeout = setTimeout(() => {\n timeProfile('handle changed files', () => {\n debug('changedFiles', changedFiles)\n try {\n // build related test list\n //const tests: string[] = []\n const tests = new Set<string>\n for (const [file, fileEvent] of changedFiles) {\n debug('check', file)\n debug('1 tests', tests)\n if (fileEvent !== 'remove') { // only check if it's a test if it exists (has not just been removed)\n if (testFilter(file)) { // it is a test file itself, add to run list\n debug('its a test', file)\n //tests.push(file)\n tests.add(file)\n if (config.watch.dependencyEvaluation) {\n if (!(file in dependencyTrees)) { // if its a new test\n debug('try to add a new test', file)\n addNewTest(file)\n }\n } else {\n // no trees to record it in, so this is what makes a\n // newly created test part of the run set\n reRunManager.state.allTestFiles.add(file)\n }\n }\n }\n\n // with evaluation off there is nothing to map the change through:\n // any watched file could affect any test, so run the lot\n if (!config.watch.dependencyEvaluation) {\n for (const f of reRunManager.state.allTestFiles) tests.add(f)\n continue\n }\n\n debug('dtrees', dependencyTrees)\n debug('2 tests', tests)\n for (const f of Object.getOwnPropertyNames(dependencyTrees)) {\n debug('dep tree', f, dependencyTrees[f])\n if (dependencyTrees[f]?.some(dep => dep === file) === true) { // a test depends on this file\n debug('its a dependency', file)\n //tests.push(f)\n tests.add(f)\n }\n }\n }\n\n changedFiles = []\n\n debug('tests', tests)\n\n if (tests.size > 0) {\n timeProfile('build list of files to test and request a run',\n () => {\n debug('tests', tests)\n debug('reRunFailingTests', config.watch.reRunFailingTests)\n\n // changes accumulate here because an 'auto' request made while a\n // run is in flight is coalesced into the queued one - everything\n // edited in the meantime still has to be covered\n reRunManager.state.untestedFiles\n = reRunManager.state.untestedFiles.union(tests)\n\n void reRunManager.requestRun(\n 'auto',\n () => {\n // resolved when the run actually starts, not when it is\n // queued, so a coalesced request picks up the later edits\n const toTest = (config.watch.reRunFailingTests)\n ? reRunManager.state.untestedFiles\n .union(reRunManager.state.failedTestFiles)\n : new Set(reRunManager.state.untestedFiles)\n\n // consumed by this run - without this they are retested\n // on every later run for the rest of the session\n reRunManager.state.untestedFiles = new Set()\n\n debug('run tests on change')\n debug('toTest', toTest)\n\n return runTests(\n config,\n toTest,\n reRunManager,\n { limit: -1 },\n 'refresh',\n customOut,\n executionFilters\n )\n }\n )\n }\n )\n }\n } catch (e) {\n log('watch handler error', e)\n }\n })\n }, debounceMs)\n } // end of watch event\n\n function addNewTest(testFile: string): void {\n debug('new test', testFile)\n const dependencyTree = buildDependencyTree(config, testFile)\n dependencyTrees[testFile] = dependencyTree\n .map(file => slash(file).slice(projectDir.length + 1))\n .filter(f => f !== testFile)\n }\n })\n\n // NOTE: \"watching...\" is intentionally NOT printed here. watch() already emits it,\n // tied to a real milestone (the initial test run finishing, or no tests found).\n // Printing it again here produced a duplicate \"watching...\" on every startup.\n // out(chalk.brightblue`watching...`)\n}\n"]}
1
+ {"version":3,"file":"watchFilesAndRunTestsNodeWatch.js","sourceRoot":"","sources":["../../../src/cli/lib/watchFilesAndRunTestsNodeWatch.ts"],"names":[],"mappings":"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","sourcesContent":["\nimport { matchesGlob } from 'node:path'\n\nimport type { FinalConfig, OutFn } from '../../types.js'\nimport type { TestExecutionFilters } from '../cliTypes.js'\nimport type { ReRunManager } from './reRunManager.js'\nimport type { DependencyGraph } from './makeDependencyGraph.js'\nimport type { StopFn } from '../watch.js'\nimport chalk from '../../packages/chalk.js'\nimport slash from '../../packages/slash.js'\nimport { createTimeProfiler } from '../../packages/timeProfiler.js'\nimport { showTimeProfiling } from '../../config.js'\nimport { out as mainOut, log, debug } from '../../output.js'\nimport { agentChange } from './agentReport.js'\nimport { runTests } from './runTests.js'\nimport { globArgCombine } from './globArgCombine.js'\nimport { addBasePath } from './addBasePath.js'\nimport { watchFilesNodeWatch } from './watchFilesNodeWatch.js'\nimport { filter } from './filter.js'\n\n\nconst { timeProfile, timeProfileAsync } = createTimeProfiler(showTimeProfiling)\n\nexport async function watchFilesAndRunTestsNodeWatch(\n config: FinalConfig,\n //testFiles: Set<string>,\n // null when watch.dependencyEvaluation is off\n dependencyGraph: DependencyGraph | null,\n failingTests: string[],\n reRunManager: ReRunManager,\n //watchRunState: WatchRunState,\n customOut?: OutFn,\n executionFilters: TestExecutionFilters = {}\n): Promise<StopFn> {\n // agent mode passes a sink here, so its own change lines are the only ones printed\n const out = customOut ?? mainOut\n\n return timeProfileAsync('init watching', async () => {\n debug('failingTests', failingTests)\n\n const testsGlobs = addBasePath(config.testsBase, config.tests)\n const testsIgnoreGlobs = addBasePath(config.testsBase, config.testsIgnore)\n\n // indentify a test file\n const testFilter = (file: string): boolean => {\n return matchesGlob(file, globArgCombine(testsGlobs))\n && !matchesGlob(file, globArgCombine(testsIgnoreGlobs))\n && (\n config.testsFilter === undefined\n || config.testsFilter === ''\n || filter(config.testsBase, config.testsFilter, file)\n )\n }\n\n let changedFiles: Array<[string, string]> = []\n let timeout: ReturnType<typeof setTimeout> | null = null\n\n if (config.watch.watchFilesBase === '') {\n out('No config.watch.watchFilesBase provided, defaulting to \\'.\\'')\n config.watch.watchFilesBase = '.'\n }\n\n const watcher = await watchFilesNodeWatch(config, watchEvent)\n return () => {\n watcher.close()\n // a change seen just before stopping would otherwise still run its tests\n if (timeout) clearTimeout(timeout)\n }\n\n function watchEvent(filename: string, event: string): void {\n debug('handle watch event ', filename, event)\n\n filename = slash(filename)\n\n // forget a deleted test, avoiding trying to run it later\n if (event === 'remove') {\n debug('removing test', filename)\n reRunManager.state.withoutTests.delete(filename)\n reRunManager.state.allTestFiles.delete(filename)\n }\n\n // info on the event found\n out(chalk.grey`change: ${filename} (${event})`)\n agentChange(config, filename, event)\n\n // add the file to changed files\n changedFiles.push([filename, event])\n\n // 33ms debounce\n const debounceMs = 33\n if (timeout) {\n clearTimeout(timeout)\n }\n timeout = setTimeout(() => {\n timeProfile('handle changed files', () => {\n debug('changedFiles', changedFiles)\n try {\n // the whole batch is applied before any lookup, so an import added in one\n // file can reach a file created in the same batch\n if (dependencyGraph !== null) {\n for (const [file, fileEvent] of changedFiles) {\n if (fileEvent === 'remove') dependencyGraph.remove(file)\n else if (testFilter(file)) dependencyGraph.addTest(file)\n else dependencyGraph.update(file)\n }\n }\n\n // build related test list\n const tests = new Set<string>\n for (const [file, fileEvent] of changedFiles) {\n debug('check', file)\n if (fileEvent !== 'remove') { // only check if it's a test if it exists (has not just been removed)\n if (testFilter(file)) { // it is a test file itself, add to run list\n debug('its a test', file)\n tests.add(file)\n // makes a newly created test part of what `a` runs\n reRunManager.state.allTestFiles.add(file)\n }\n }\n\n // with evaluation off there is nothing to map the change through:\n // any watched file could affect any test, so run the lot\n if (dependencyGraph === null) {\n for (const f of reRunManager.state.allTestFiles) tests.add(f)\n continue\n }\n\n for (const f of dependencyGraph.testsAffectedBy(file)) tests.add(f)\n }\n\n changedFiles = []\n\n debug('tests', tests)\n\n if (tests.size > 0) {\n timeProfile('build list of files to test and request a run', () => {\n debug('tests', tests)\n debug('reRunFailingTests', config.watch.reRunFailingTests)\n\n // changes accumulate here because an 'auto' request made while a\n // run is in flight is coalesced into the queued one - everything\n // edited in the meantime still has to be covered\n for (const test of tests) reRunManager.state.untestedFiles.add(test)\n\n void reRunManager.requestRun('auto', () => {\n // resolved when the run actually starts, not when it is\n // queued, so a coalesced request picks up the later edits\n const toTest = (config.watch.reRunFailingTests)\n ? reRunManager.state.untestedFiles.union(reRunManager.state.failedTestFiles)\n : new Set(reRunManager.state.untestedFiles)\n\n // consumed by this run - without this they are retested\n // on every later run for the rest of the session\n reRunManager.state.untestedFiles = new Set()\n\n debug('run tests on change')\n debug('toTest', toTest)\n\n return runTests(\n config,\n toTest,\n reRunManager,\n { limit: -1 },\n 'refresh',\n customOut,\n executionFilters\n )\n })\n })\n }\n } catch (e) {\n log('watch handler error', e)\n }\n })\n }, debounceMs)\n } // end of watch event\n })\n\n // NOTE: \"watching...\" is intentionally NOT printed here. watch() already emits it,\n // tied to a real milestone (the initial test run finishing, or no tests found).\n // Printing it again here produced a duplicate \"watching...\" on every startup.\n // out(chalk.brightblue`watching...`)\n}\n"]}
package/dist/cli/watch.js CHANGED
@@ -135,8 +135,6 @@ export async function doWatch(input = process.stdin) {
135
135
  const testFiles = await findTestFiles(config);
136
136
  debug(testFiles);
137
137
  agentFound(config, testFiles.size);
138
- // global store of the dependencies of tests
139
- let dependencyTrees = {};
140
138
  // store failing tests so we can re-run them.
141
139
  const failingTests = [];
142
140
  const concurrency = { limit: -1 };
@@ -145,15 +143,30 @@ export async function doWatch(input = process.stdin) {
145
143
  lastTestFiles: testFiles
146
144
  }), runsOut);
147
145
  process.setSourceMapsEnabled(true); // enable source mapping
148
- if (testFiles.size > 0) {
146
+ if (testFiles.size > 0)
149
147
  agentOut(chalk.brightblue(foundTestsMessage(testFiles.size)));
150
- // the trees are only consulted to narrow a run, so with evaluation off building them
151
- // is pure cost - and it is the slowest part of startup on a large suite
152
- if (config.watch.dependencyEvaluation) {
153
- const { buildDependencyTrees } = await import('./lib/buildDependencyTrees.js');
154
- agentOut(chalk.brightblue `finding initial dependency trees...`);
155
- dependencyTrees = buildDependencyTrees(config, testFiles);
156
- }
148
+ // the graph is only consulted to narrow a run, so with evaluation off building it is pure
149
+ // cost - and it is the slowest part of startup on a large suite. Built even with no tests,
150
+ // so tests created later are recorded in it.
151
+ let dependencyGraph = null;
152
+ if (config.watch.dependencyEvaluation) {
153
+ const { makeDependencyGraph } = await import('./lib/makeDependencyGraph.js');
154
+ if (testFiles.size > 0)
155
+ agentOut(chalk.brightblue `finding initial dependencies...`);
156
+ dependencyGraph = makeDependencyGraph(config, testFiles);
157
+ }
158
+ // registered before anything loads, so a rerun reloads only what the graph says changed
159
+ if (dependencyGraph !== null) {
160
+ const graph = dependencyGraph;
161
+ const { registerGraphReload } = await import('./lib/esmGraphReload.js');
162
+ const { handle } = registerGraphReload(file => graph.versionOf(file));
163
+ stopFns.push(() => handle.deregister());
164
+ }
165
+ else {
166
+ // todo: one instance per run; until then each test file reloads its whole graph
167
+ const { registerTreeReload } = await import('./lib/esmTreeReload.js');
168
+ const handle = registerTreeReload();
169
+ stopFns.push(() => handle.deregister());
157
170
  }
158
171
  // live before the first test runs, for two reasons. A change landing during the initial
159
172
  // run (a compiler emit, typically) is seen rather than lost. And the watcher starts on a
@@ -163,7 +176,7 @@ export async function doWatch(input = process.stdin) {
163
176
  const { watchFilesAndRunTests } = await import('./lib/watchFilesAndRunTests.js');
164
177
  const stopWatcher = await watchFilesAndRunTests(config,
165
178
  //testFiles,
166
- dependencyTrees, failingTests, // CHECK this should also be in state
179
+ dependencyGraph, failingTests, // CHECK this should also be in state
167
180
  reRunManager,
168
181
  //watchRunState,
169
182
  runsOut, executionFilters);
@@ -196,7 +209,7 @@ export async function doWatch(input = process.stdin) {
196
209
  agentOut(chalk.brightblue `watching...`);
197
210
  agentWatching(config, testFiles.size);
198
211
  const { listenToUser } = await import('./lib/listenToUser.js');
199
- const disposeTty = listenToUser(reRunManager, files => () => {
212
+ const disposeTty = listenToUser(reRunManager, files => {
200
213
  return runTests(config, files, reRunManager, concurrency, 'refresh', runsOut, executionFilters);
201
214
  }, config.watch.ttyActionsOnKeypress, initialTestRun, input, runsOut);
202
215
  stopFns.push(disposeTty);
@@ -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, 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"]}
1
+ {"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/cli/watch.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 type { DependencyGraph } from './lib/makeDependencyGraph.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 // 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) agentOut(chalk.brightblue(foundTestsMessage(testFiles.size)))\n\n // the graph is only consulted to narrow a run, so with evaluation off building it is pure\n // cost - and it is the slowest part of startup on a large suite. Built even with no tests,\n // so tests created later are recorded in it.\n let dependencyGraph: DependencyGraph | null = null\n if (config.watch.dependencyEvaluation) {\n const { makeDependencyGraph } = await import('./lib/makeDependencyGraph.js')\n if (testFiles.size > 0) agentOut(chalk.brightblue`finding initial dependencies...`)\n dependencyGraph = makeDependencyGraph(config, testFiles)\n }\n\n // registered before anything loads, so a rerun reloads only what the graph says changed\n if (dependencyGraph !== null) {\n const graph = dependencyGraph\n const { registerGraphReload } = await import('./lib/esmGraphReload.js')\n const { handle } = registerGraphReload(file => graph.versionOf(file))\n stopFns.push(() => handle.deregister())\n } else {\n // todo: one instance per run; until then each test file reloads its whole graph\n const { registerTreeReload } = await import('./lib/esmTreeReload.js')\n const handle = registerTreeReload()\n stopFns.push(() => handle.deregister())\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 dependencyGraph,\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/describe.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import chalk from './packages/chalk.js';
2
2
  import { checkMeta } from './checkMeta.js';
3
3
  import { debug } from './output.js';
4
+ import { registrationFor } from './registration.js';
4
5
  export function describe(theThing, testsOrMeta, possiblyTests) {
5
6
  if (!global.__sxy_test_runner__) {
6
7
  throw new Error('sxy-test-runner describe() was called, but the test framework has not initialized.'
@@ -8,8 +9,9 @@ export function describe(theThing, testsOrMeta, possiblyTests) {
8
9
  + ', instead of running \'pnpm sxy-test-runner\'');
9
10
  // todo - maybe we can initialise the framework and just run only this test file
10
11
  }
11
- const thisDescribeCounter = global.__sxy_test_runner__.describeCounter;
12
- global.__sxy_test_runner__.describeCounter++;
12
+ const registration = registrationFor(global.__sxy_test_runner__);
13
+ const thisDescribeCounter = registration.describeCounter;
14
+ registration.describeCounter++;
13
15
  let meta = undefined;
14
16
  let tests;
15
17
  if (testsOrMeta === undefined) {
@@ -23,7 +25,7 @@ export function describe(theThing, testsOrMeta, possiblyTests) {
23
25
  meta = testsOrMeta;
24
26
  tests = possiblyTests; // eslint-disable-line @typescript-eslint/no-unsafe-type-assertion
25
27
  }
26
- global.__sxy_test_runner__.describes.push({
28
+ registration.describes.push({
27
29
  counter: thisDescribeCounter,
28
30
  thing: theThing,
29
31
  meta,