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.
- package/AGENTS.md +47 -21
- package/dist/cli/lib/agentReport.d.ts +1 -0
- package/dist/cli/lib/agentReport.js +3 -0
- package/dist/cli/lib/agentReport.js.map +1 -1
- package/dist/cli/lib/buildDependencyTree.d.ts +1 -2
- package/dist/cli/lib/buildDependencyTree.js +25 -23
- package/dist/cli/lib/buildDependencyTree.js.map +1 -1
- package/dist/cli/lib/buildDependencyTrees.d.ts +1 -2
- package/dist/cli/lib/buildDependencyTrees.js +18 -16
- package/dist/cli/lib/buildDependencyTrees.js.map +1 -1
- package/dist/cli/lib/esmGraphReload.d.ts +5 -0
- package/dist/cli/lib/esmGraphReload.js +24 -0
- package/dist/cli/lib/esmGraphReload.js.map +1 -0
- package/dist/cli/lib/esmTreeReload.d.ts +4 -0
- package/dist/cli/lib/esmTreeReload.js +62 -0
- package/dist/cli/lib/esmTreeReload.js.map +1 -0
- package/dist/cli/lib/handleUserInput.d.ts +2 -2
- package/dist/cli/lib/handleUserInput.js +13 -6
- package/dist/cli/lib/handleUserInput.js.map +1 -1
- package/dist/cli/lib/listenToUser.d.ts +2 -2
- package/dist/cli/lib/listenToUser.js.map +1 -1
- package/dist/cli/lib/loadTestFile.d.ts +0 -1
- package/dist/cli/lib/loadTestFile.js +23 -8
- package/dist/cli/lib/loadTestFile.js.map +1 -1
- package/dist/cli/lib/makeDependencyGraph.d.ts +10 -0
- package/dist/cli/lib/makeDependencyGraph.js +210 -0
- package/dist/cli/lib/makeDependencyGraph.js.map +1 -0
- package/dist/cli/lib/reRunManager.js +4 -6
- package/dist/cli/lib/reRunManager.js.map +1 -1
- package/dist/cli/lib/runTests.js +7 -2
- package/dist/cli/lib/runTests.js.map +1 -1
- package/dist/cli/lib/showTestResultsSummary.d.ts +1 -1
- package/dist/cli/lib/showTestResultsSummary.js +5 -1
- package/dist/cli/lib/showTestResultsSummary.js.map +1 -1
- package/dist/cli/lib/statusFile.js +20 -1
- package/dist/cli/lib/statusFile.js.map +1 -1
- package/dist/cli/lib/watchFilesAndRunTestsNodeWatch.d.ts +3 -2
- package/dist/cli/lib/watchFilesAndRunTestsNodeWatch.js +24 -48
- package/dist/cli/lib/watchFilesAndRunTestsNodeWatch.js.map +1 -1
- package/dist/cli/watch.js +25 -12
- package/dist/cli/watch.js.map +1 -1
- package/dist/describe.js +5 -3
- package/dist/describe.js.map +1 -1
- package/dist/meta.js +2 -1
- package/dist/meta.js.map +1 -1
- package/dist/registration.d.ts +4 -0
- package/dist/registration.js +34 -0
- package/dist/registration.js.map +1 -0
- package/dist/types.d.ts +8 -0
- package/dist/types.js.map +1 -1
- package/package.json +11 -6
- package/readme.md +16 -123
- package/dist/packages/esmReload.d.ts +0 -11
- package/dist/packages/esmReload.js +0 -43
- package/dist/packages/esmReload.js.map +0 -1
package/AGENTS.md
CHANGED
|
@@ -138,12 +138,11 @@ filters select no runnable tests, `once` exits `22` - `21` means no test file ma
|
|
|
138
138
|
stdout - nothing else is printed, setup progress included. `--status-file` is watch-only,
|
|
139
139
|
writing the latest run's result to a file. Both are covered under "Watch mode" below.
|
|
140
140
|
|
|
141
|
-
Describe and test filters run after the selected test files have loaded
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
`--filter`
|
|
146
|
-
`--filter-it` only for further narrowing inside those files.
|
|
141
|
+
Describe and test filters run after the selected test files have loaded, so every selected
|
|
142
|
+
file and its module graph is still imported and evaluated. Loading many files and filtering
|
|
143
|
+
their registered describes or tests afterward can therefore be much slower than file
|
|
144
|
+
filtering. Prefer `--filter` when a file glob can narrow the run, then use
|
|
145
|
+
`--filter-describe` or `--filter-it` only for further narrowing inside those files.
|
|
147
146
|
|
|
148
147
|
`--fail-fast` (`-x`) stops the run at the first failure - whether that is a failing test, a
|
|
149
148
|
describe that threw, or a test file that would not load. It is a `once` flag with no config
|
|
@@ -179,14 +178,23 @@ forms exclude exactly the same files, so it costs nothing to prefer the shorter
|
|
|
179
178
|
|
|
180
179
|
## Test lifecycle and data flow
|
|
181
180
|
|
|
182
|
-
All test files run in one Node.js process.
|
|
183
|
-
|
|
184
|
-
static dependency graph. Importing the file registers its describe blocks in
|
|
185
|
-
`global.__sxy_test_runner__`; execution happens afterward.
|
|
181
|
+
All test files run in one Node.js process. Importing a test file registers its describe
|
|
182
|
+
blocks; execution happens afterward.
|
|
186
183
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
184
|
+
Modules are shared between test files, through Node's ordinary module cache: a module
|
|
185
|
+
imported by several test files is evaluated once, and its state carries from one file to the
|
|
186
|
+
next. Tests should set up any shared state they depend on rather than assume a fresh module.
|
|
187
|
+
How modules are reloaded in watch mode is covered under "Watch mode" below.
|
|
188
|
+
|
|
189
|
+
A describe belongs to the test file whose top level made it, directly or through a function
|
|
190
|
+
it calls - a shared suite in a helper module registers in whichever test file calls it. A
|
|
191
|
+
test file imported by another test file still runs its own describes when it is loaded
|
|
192
|
+
itself, but they are not run again as part of the file importing it, and a module that calls
|
|
193
|
+
`describe` as soon as it is imported registers nothing.
|
|
194
|
+
|
|
195
|
+
A module whose filename contains the explicit `._cached_.js` marker is never reloaded, in
|
|
196
|
+
any mode. Its static dependencies are cached with it, allowing explicitly shared state that
|
|
197
|
+
lasts for the whole process:
|
|
190
198
|
|
|
191
199
|
```js
|
|
192
200
|
import { database } from './fixtures/database._cached_.js'
|
|
@@ -333,13 +341,31 @@ for two things: startup stops paying for dependency analysis, which is the slowe
|
|
|
333
341
|
it on a large suite, and the blind spots below stop mattering, because nothing is being
|
|
334
342
|
predicted. On a small or fast suite it is often the better setting.
|
|
335
343
|
|
|
344
|
+
The same setting decides how a rerun reloads modules. Every test file in a rerun is
|
|
345
|
+
evaluated again, so its describes register afresh. Beyond that:
|
|
346
|
+
|
|
347
|
+
- With dependency evaluation on, only a changed file and the files that import it, directly
|
|
348
|
+
or not, are loaded again; everything else stays shared from earlier runs. A rerun with
|
|
349
|
+
nothing changed reloads only the test files themselves.
|
|
350
|
+
- With it off, each test file in a rerun gets a fresh copy of its whole static module graph.
|
|
351
|
+
|
|
352
|
+
In both, packages under `node_modules` are loaded once and never reloaded. A linked package
|
|
353
|
+
(a workspace or `npm link` dependency) resolves to its real path outside `node_modules`, so
|
|
354
|
+
it reloads like the project's own files.
|
|
355
|
+
|
|
336
356
|
Important limitations:
|
|
337
357
|
|
|
338
|
-
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
358
|
+
- Dependency analysis finds `import()` only when its path is a plain string literal. A path
|
|
359
|
+
computed at runtime (`import(name)`, `import('./' + name)`), or written as a template
|
|
360
|
+
literal, is not found, so a test reached only that way is not rerun when its dependency
|
|
361
|
+
changes. `watch.dependencyEvaluation: false` avoids this.
|
|
362
|
+
- With dependency evaluation on, a module is only reloaded when the watcher sees it change
|
|
363
|
+
or sees a change to something it imports. One it cannot connect - a file outside
|
|
364
|
+
`watch.watchFiles` such as a `.json` fixture, or one reached only through a computed
|
|
365
|
+
`import()` - keeps its first loaded copy for the rest of the session. Restart watch mode,
|
|
366
|
+
or set `watch.dependencyEvaluation: false`, to pick up such a change.
|
|
367
|
+
- All reruns still share one long-lived process. Global state and external resources are
|
|
368
|
+
never reset between runs and remain the test author's responsibility.
|
|
343
369
|
- Modules imported through a `._cached_.*` boundary also remain loaded for the life of the
|
|
344
370
|
process. Keep mutable access sequential or provide application-level synchronization,
|
|
345
371
|
and arrange explicit cleanup for resources such as servers and database connections.
|
|
@@ -469,9 +495,9 @@ maps it to a test. Either half can miss:
|
|
|
469
495
|
all**. The stream simply stays quiet, and the previous `done` remains the last word while
|
|
470
496
|
silently going stale.
|
|
471
497
|
- Even for a watched file, the changed-to-test mapping is the static import graph, so it
|
|
472
|
-
misses
|
|
473
|
-
that was neither changed nor already failing is not
|
|
474
|
-
`failing`. Setting `watch.dependencyEvaluation: false` removes this gap - every watched
|
|
498
|
+
misses imports whose path is computed at runtime and anything reached through a
|
|
499
|
+
`._cached_.*` boundary. A test file that was neither changed nor already failing is not
|
|
500
|
+
re-run, so a break in it never reaches `failing`. Setting `watch.dependencyEvaluation: false` removes this gap - every watched
|
|
475
501
|
change then reruns everything, and those runs report `covers=all`.
|
|
476
502
|
|
|
477
503
|
So `failing=0` means "nothing is known to be broken", not "everything passes", and silence
|
|
@@ -8,6 +8,7 @@ export declare function agentEnabled(config: FinalConfig): boolean;
|
|
|
8
8
|
export declare function agentInit(enabled: boolean): void;
|
|
9
9
|
export declare function agentFound(config: FinalConfig, files: number): void;
|
|
10
10
|
export declare function agentSetRunReason(reason: RunReason): void;
|
|
11
|
+
export declare function currentRunReason(): RunReason;
|
|
11
12
|
export declare function agentRunStart(config: FinalConfig, files: number): number;
|
|
12
13
|
export declare function agentFailure(config: FinalConfig, run: number, entry: FailureEntry): void;
|
|
13
14
|
export declare function agentDone(config: FinalConfig, run: number, code: StatusCode, description: string, summary: TestsResultsSummary | null, durationMs: number, failingFiles: number): void;
|
|
@@ -40,6 +40,9 @@ export function agentFound(config, files) {
|
|
|
40
40
|
export function agentSetRunReason(reason) {
|
|
41
41
|
nextRunReason = reason;
|
|
42
42
|
}
|
|
43
|
+
export function currentRunReason() {
|
|
44
|
+
return nextRunReason;
|
|
45
|
+
}
|
|
43
46
|
// claims the next run number and announces the run, so a reader knows work is in flight
|
|
44
47
|
// before any result arrives
|
|
45
48
|
export function agentRunStart(config, files) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agentReport.js","sourceRoot":"","sources":["../../../src/cli/lib/agentReport.ts"],"names":[],"mappings":"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","sourcesContent":["\nimport type { FinalConfig } from '../../types.js'\nimport type { FailureEntry } from './failureEntries.js'\nimport type { RunType } from './reRunManager.js'\nimport type { TestsResultsSummary } from './runTests.js'\nimport { out as mainOut } from '../../output.js'\nimport { statusNames, type StatusCode } from './statusFile.js'\n\n\n// Agent mode reports a watch session as a stream of single lines, for a reader tailing the\n// process rather than watching the terminal. Every line is one complete event:\n//\n// [sxyt] <event> | <key>=<value> | <key>=<value>\n//\n// Values are never quoted, so free text is flattened to keep the grammar intact - one event\n// can never span two lines, and a stray `|` can never look like a field boundary.\n\nconst prefix = '[sxyt]'\n\nexport type RunReason = RunType | 'startup' | 'once'\n\nlet runCounter = 0\n// requestRun sets this before handing a run to runTests; the initial run never goes through\n// the queue, so 'startup' is the right default\nlet nextRunReason: RunReason = 'startup'\n\ntype Field = [string, string | number]\n\nfunction emit(event: string, fields: Field[] = []): void {\n mainOut(prefix + ` ${event}` + fields.map(([key, value]) => ` | ${key}=${value}`).join(''))\n}\n\n// newlines would split one event across two lines, and a `|` would read as a field boundary\nfunction flatten(text: string): string {\n return text.replace(/\\s*[\\r\\n]+\\s*/g, ' ').replace(/\\|/g, '/').trim()\n}\n\nexport function agentEnabled(config: FinalConfig): boolean {\n return config.agent\n}\n\n// the process is up, before the config is even loaded - so a slow startup is\n// distinguishable from one that never began. Takes the flag rather than the config for that\n// reason, and resets the counters so repeated in process sessions start from 1.\nexport function agentInit(enabled: boolean): void {\n runCounter = 0\n nextRunReason = 'startup'\n if (!enabled) return\n emit('init', [['pid', process.pid]])\n}\n\nexport function agentFound(config: FinalConfig, files: number): void {\n if (!agentEnabled(config)) return\n emit('found', [['files', files]])\n}\n\nexport function agentSetRunReason(reason: RunReason): void {\n nextRunReason = reason\n}\n\n// claims the next run number and announces the run, so a reader knows work is in flight\n// before any result arrives\nexport function agentRunStart(config: FinalConfig, files: number): number {\n if (!agentEnabled(config)) return 0\n runCounter++\n emit('running', [\n ['n', runCounter],\n ['files', files],\n ['why', nextRunReason],\n ['covers', runScope(config)]\n ])\n return runCounter\n}\n\n// what the run was built from. A reader needs this to know how far the run's own `status`\n// generalises - only a run covering everything can speak for the whole suite.\nfunction runScope(config: FinalConfig): string {\n // known before the run starts: fail fast means it is built to stop early, so it cannot\n // promise to have covered anything beyond the first failure\n if (config.failFast) return 'until-first-failure'\n\n switch (nextRunReason) {\n case 'startup':\n case 'once':\n case 'all': return 'all'\n case 'last': return 'last'\n case 'failed': return 'failing'\n case 'auto': {\n // with dependency evaluation off a change runs the whole suite, so an auto run\n // carries the same weight as a startup one\n if (!config.watch.dependencyEvaluation) return 'all'\n // the reRunFailingTests case is the one worth spelling out: without it a run says\n // nothing about files that were already failing\n return (config.watch.reRunFailingTests) ? 'changed+failing' : 'changed'\n }\n default: return 'changed'\n }\n}\n\n// failures are emitted before the run's done line, so done is a complete end of run marker\nexport function agentFailure(config: FinalConfig, run: number, entry: FailureEntry): void {\n if (!agentEnabled(config)) return\n emit('fail', [\n ['n', run],\n ['file', flatten(entry.file)],\n ...(entry.describe === undefined)\n ? []\n : [['describe', flatten(entry.describe)] as Field],\n ...(entry.test === undefined) ? [] : [['test', flatten(entry.test)] as Field],\n ['error', flatten(entry.error)]\n ])\n}\n\n// `failing` counts the test files still failing across the whole session, not just this\n// run. A watch re-run usually covers only the changed files, so its own tallies can read as\n// a clean pass while the suite is still broken elsewhere.\nexport function agentDone(\n config: FinalConfig,\n run: number,\n code: StatusCode,\n description: string,\n summary: TestsResultsSummary | null,\n durationMs: number,\n failingFiles: number\n): void {\n if (!agentEnabled(config)) return\n emit('done', [\n ['n', run],\n // named, not numbered: `status=failed` needs no lookup table, and cannot be misread\n // as the process exit code the way a bare `code=1` could\n ['status', statusNames[code]],\n ['desc', flatten(description)],\n ...(summary === null) ? [] : [\n ['tests', `${summary.itsPasses}/${summary.itsTotal}`] as Field,\n ['items', `${summary.describesPasses}/${summary.describesTotal}`] as Field,\n ['files', `${summary.passes}/${summary.total}`] as Field\n ],\n ['failing', failingFiles],\n ['ms', durationMs]\n ])\n}\n\nexport function agentWatching(config: FinalConfig, files: number): void {\n if (!agentEnabled(config)) return\n emit('watching', [['files', files]])\n}\n\nexport function agentChange(config: FinalConfig, file: string, event: string): void {\n if (!agentEnabled(config)) return\n emit('change', [['file', flatten(file)], ['event', flatten(event)]])\n}\n\n// agent mode owns stdout, so the ordinary coloured output is routed into a sink\nexport function agentSilentOut(): void {\n // deliberately nothing - the agent lines are the whole stream\n}\n"]}
|
|
1
|
+
{"version":3,"file":"agentReport.js","sourceRoot":"","sources":["../../../src/cli/lib/agentReport.ts"],"names":[],"mappings":"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","sourcesContent":["\nimport type { FinalConfig } from '../../types.js'\nimport type { FailureEntry } from './failureEntries.js'\nimport type { RunType } from './reRunManager.js'\nimport type { TestsResultsSummary } from './runTests.js'\nimport { out as mainOut } from '../../output.js'\nimport { statusNames, type StatusCode } from './statusFile.js'\n\n\n// Agent mode reports a watch session as a stream of single lines, for a reader tailing the\n// process rather than watching the terminal. Every line is one complete event:\n//\n// [sxyt] <event> | <key>=<value> | <key>=<value>\n//\n// Values are never quoted, so free text is flattened to keep the grammar intact - one event\n// can never span two lines, and a stray `|` can never look like a field boundary.\n\nconst prefix = '[sxyt]'\n\nexport type RunReason = RunType | 'startup' | 'once'\n\nlet runCounter = 0\n// requestRun sets this before handing a run to runTests; the initial run never goes through\n// the queue, so 'startup' is the right default\nlet nextRunReason: RunReason = 'startup'\n\ntype Field = [string, string | number]\n\nfunction emit(event: string, fields: Field[] = []): void {\n mainOut(prefix + ` ${event}` + fields.map(([key, value]) => ` | ${key}=${value}`).join(''))\n}\n\n// newlines would split one event across two lines, and a `|` would read as a field boundary\nfunction flatten(text: string): string {\n return text.replace(/\\s*[\\r\\n]+\\s*/g, ' ').replace(/\\|/g, '/').trim()\n}\n\nexport function agentEnabled(config: FinalConfig): boolean {\n return config.agent\n}\n\n// the process is up, before the config is even loaded - so a slow startup is\n// distinguishable from one that never began. Takes the flag rather than the config for that\n// reason, and resets the counters so repeated in process sessions start from 1.\nexport function agentInit(enabled: boolean): void {\n runCounter = 0\n nextRunReason = 'startup'\n if (!enabled) return\n emit('init', [['pid', process.pid]])\n}\n\nexport function agentFound(config: FinalConfig, files: number): void {\n if (!agentEnabled(config)) return\n emit('found', [['files', files]])\n}\n\nexport function agentSetRunReason(reason: RunReason): void {\n nextRunReason = reason\n}\n\nexport function currentRunReason(): RunReason {\n return nextRunReason\n}\n\n// claims the next run number and announces the run, so a reader knows work is in flight\n// before any result arrives\nexport function agentRunStart(config: FinalConfig, files: number): number {\n if (!agentEnabled(config)) return 0\n runCounter++\n emit('running', [\n ['n', runCounter],\n ['files', files],\n ['why', nextRunReason],\n ['covers', runScope(config)]\n ])\n return runCounter\n}\n\n// what the run was built from. A reader needs this to know how far the run's own `status`\n// generalises - only a run covering everything can speak for the whole suite.\nfunction runScope(config: FinalConfig): string {\n // known before the run starts: fail fast means it is built to stop early, so it cannot\n // promise to have covered anything beyond the first failure\n if (config.failFast) return 'until-first-failure'\n\n switch (nextRunReason) {\n case 'startup':\n case 'once':\n case 'all': return 'all'\n case 'last': return 'last'\n case 'failed': return 'failing'\n case 'auto': {\n // with dependency evaluation off a change runs the whole suite, so an auto run\n // carries the same weight as a startup one\n if (!config.watch.dependencyEvaluation) return 'all'\n // the reRunFailingTests case is the one worth spelling out: without it a run says\n // nothing about files that were already failing\n return (config.watch.reRunFailingTests) ? 'changed+failing' : 'changed'\n }\n default: return 'changed'\n }\n}\n\n// failures are emitted before the run's done line, so done is a complete end of run marker\nexport function agentFailure(config: FinalConfig, run: number, entry: FailureEntry): void {\n if (!agentEnabled(config)) return\n emit('fail', [\n ['n', run],\n ['file', flatten(entry.file)],\n ...(entry.describe === undefined)\n ? []\n : [['describe', flatten(entry.describe)] as Field],\n ...(entry.test === undefined) ? [] : [['test', flatten(entry.test)] as Field],\n ['error', flatten(entry.error)]\n ])\n}\n\n// `failing` counts the test files still failing across the whole session, not just this\n// run. A watch re-run usually covers only the changed files, so its own tallies can read as\n// a clean pass while the suite is still broken elsewhere.\nexport function agentDone(\n config: FinalConfig,\n run: number,\n code: StatusCode,\n description: string,\n summary: TestsResultsSummary | null,\n durationMs: number,\n failingFiles: number\n): void {\n if (!agentEnabled(config)) return\n emit('done', [\n ['n', run],\n // named, not numbered: `status=failed` needs no lookup table, and cannot be misread\n // as the process exit code the way a bare `code=1` could\n ['status', statusNames[code]],\n ['desc', flatten(description)],\n ...(summary === null) ? [] : [\n ['tests', `${summary.itsPasses}/${summary.itsTotal}`] as Field,\n ['items', `${summary.describesPasses}/${summary.describesTotal}`] as Field,\n ['files', `${summary.passes}/${summary.total}`] as Field\n ],\n ['failing', failingFiles],\n ['ms', durationMs]\n ])\n}\n\nexport function agentWatching(config: FinalConfig, files: number): void {\n if (!agentEnabled(config)) return\n emit('watching', [['files', files]])\n}\n\nexport function agentChange(config: FinalConfig, file: string, event: string): void {\n if (!agentEnabled(config)) return\n emit('change', [['file', flatten(file)], ['event', flatten(event)]])\n}\n\n// agent mode owns stdout, so the ordinary coloured output is routed into a sink\nexport function agentSilentOut(): void {\n // deliberately nothing - the agent lines are the whole stream\n}\n"]}
|
|
@@ -1,24 +1,26 @@
|
|
|
1
|
-
import dependencyTree from 'dependency-tree'
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
1
|
+
// import dependencyTree from 'dependency-tree'
|
|
2
|
+
export {};
|
|
3
|
+
// import type { FinalConfig } from '../../types.js'
|
|
4
|
+
// import { debug } from '../../output.js'
|
|
5
|
+
// import slash from '../../packages/slash.js'
|
|
6
|
+
// export function buildDependencyTree(config: FinalConfig, filename: string): string[] {
|
|
7
|
+
// filename = slash(filename)
|
|
8
|
+
// const dependencyTreeConfig = {
|
|
9
|
+
// filename,
|
|
10
|
+
// isListForm: true,
|
|
11
|
+
// directory: config.watch.watchFilesBase,
|
|
12
|
+
// filter: (path: string) => path.indexOf('node_modules') === -1
|
|
13
|
+
// }
|
|
14
|
+
// // isListForm:true makes dependency-tree return a flat string[] at runtime,
|
|
15
|
+
// // which its shipped types don't model (they only type the tree-object form).
|
|
16
|
+
// const dt = dependencyTree(dependencyTreeConfig) as unknown as string[]
|
|
17
|
+
// // process the results into final format
|
|
18
|
+
// // (forward slashes and convert full path to rel path)
|
|
19
|
+
// const cwd = process.cwd()
|
|
20
|
+
// const processed = dt
|
|
21
|
+
// .map(file => slash(file).slice(cwd.length + 1))
|
|
22
|
+
// .filter(file => file !== filename) // remove the current file
|
|
23
|
+
// debug('found dep tree', processed)
|
|
24
|
+
// return processed
|
|
25
|
+
// }
|
|
24
26
|
//# sourceMappingURL=buildDependencyTree.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildDependencyTree.js","sourceRoot":"","sources":["../../../src/cli/lib/buildDependencyTree.ts"],"names":[],"mappings":"AACA,
|
|
1
|
+
{"version":3,"file":"buildDependencyTree.js","sourceRoot":"","sources":["../../../src/cli/lib/buildDependencyTree.ts"],"names":[],"mappings":"AACA,+CAA+C;;AAE/C,oDAAoD;AACpD,0CAA0C;AAC1C,8CAA8C;AAG9C,yFAAyF;AACzF,iCAAiC;AAEjC,qCAAqC;AACrC,oBAAoB;AACpB,4BAA4B;AAC5B,kDAAkD;AAClD,wEAAwE;AACxE,QAAQ;AAER,kFAAkF;AAClF,oFAAoF;AACpF,6EAA6E;AAE7E,+CAA+C;AAC/C,6DAA6D;AAC7D,gCAAgC;AAChC,2BAA2B;AAC3B,0DAA0D;AAC1D,wEAAwE;AAExE,yCAAyC;AAEzC,uBAAuB;AACvB,IAAI","sourcesContent":["\n// import dependencyTree from 'dependency-tree'\n\n// import type { FinalConfig } from '../../types.js'\n// import { debug } from '../../output.js'\n// import slash from '../../packages/slash.js'\n\n\n// export function buildDependencyTree(config: FinalConfig, filename: string): string[] {\n// filename = slash(filename)\n\n// const dependencyTreeConfig = {\n// filename,\n// isListForm: true,\n// directory: config.watch.watchFilesBase,\n// filter: (path: string) => path.indexOf('node_modules') === -1\n// }\n\n// // isListForm:true makes dependency-tree return a flat string[] at runtime,\n// // which its shipped types don't model (they only type the tree-object form).\n// const dt = dependencyTree(dependencyTreeConfig) as unknown as string[]\n\n// // process the results into final format\n// // (forward slashes and convert full path to rel path)\n// const cwd = process.cwd()\n// const processed = dt\n// .map(file => slash(file).slice(cwd.length + 1))\n// .filter(file => file !== filename) // remove the current file\n\n// debug('found dep tree', processed)\n\n// return processed\n// }\n"]}
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
// import type { FinalConfig, DependencyTrees } from '../../types.js'
|
|
2
|
+
// import { createTimeProfiler } from '../../packages/timeProfiler.js'
|
|
3
|
+
// import { showTimeProfiling } from '../../config.js'
|
|
4
|
+
// import { debug } from '../../output.js'
|
|
5
|
+
// import { buildDependencyTree } from './buildDependencyTree.js'
|
|
6
|
+
export {};
|
|
7
|
+
// const { timeProfile } = createTimeProfiler(showTimeProfiling)
|
|
8
|
+
// export function buildDependencyTrees(config: FinalConfig, testFiles: Set<string>): DependencyTrees {
|
|
9
|
+
// return timeProfile('build dependency trees', () => {
|
|
10
|
+
// const dependencyTrees: DependencyTrees = {}
|
|
11
|
+
// for (const testFile of testFiles) {
|
|
12
|
+
// const dependencyTree = buildDependencyTree(config, testFile)
|
|
13
|
+
// dependencyTrees[testFile] = dependencyTree
|
|
14
|
+
// debug('final dep tree', dependencyTrees[testFile])
|
|
15
|
+
// }
|
|
16
|
+
// return dependencyTrees
|
|
17
|
+
// })
|
|
18
|
+
// }
|
|
17
19
|
//# sourceMappingURL=buildDependencyTrees.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildDependencyTrees.js","sourceRoot":"","sources":["../../../src/cli/lib/buildDependencyTrees.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"buildDependencyTrees.js","sourceRoot":"","sources":["../../../src/cli/lib/buildDependencyTrees.ts"],"names":[],"mappings":"AACA,qEAAqE;AACrE,sEAAsE;AACtE,sDAAsD;AACtD,0CAA0C;AAC1C,iEAAiE;;AAGjE,gEAAgE;AAEhE,uGAAuG;AACvG,2DAA2D;AAC3D,sDAAsD;AAEtD,8CAA8C;AAC9C,2EAA2E;AAC3E,yDAAyD;AACzD,iEAAiE;AACjE,YAAY;AAEZ,iCAAiC;AACjC,SAAS;AACT,IAAI","sourcesContent":["\n// import type { FinalConfig, DependencyTrees } from '../../types.js'\n// import { createTimeProfiler } from '../../packages/timeProfiler.js'\n// import { showTimeProfiling } from '../../config.js'\n// import { debug } from '../../output.js'\n// import { buildDependencyTree } from './buildDependencyTree.js'\n\n\n// const { timeProfile } = createTimeProfiler(showTimeProfiling)\n\n// export function buildDependencyTrees(config: FinalConfig, testFiles: Set<string>): DependencyTrees {\n// return timeProfile('build dependency trees', () => {\n// const dependencyTrees: DependencyTrees = {}\n\n// for (const testFile of testFiles) {\n// const dependencyTree = buildDependencyTree(config, testFile)\n// dependencyTrees[testFile] = dependencyTree\n// debug('final dep tree', dependencyTrees[testFile])\n// }\n\n// return dependencyTrees\n// })\n// }\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { registerHooks } from 'node:module';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
const cachedModulePattern = /\._cached_\.(?:[cm]?js|[cm]?ts|jsx|tsx)$/i;
|
|
4
|
+
export function registerGraphReload(getVersion) {
|
|
5
|
+
const resolve = (specifier, context, nextResolve) => {
|
|
6
|
+
const result = nextResolve(specifier, context);
|
|
7
|
+
if (!result.url.startsWith('file:'))
|
|
8
|
+
return result;
|
|
9
|
+
const url = new URL(result.url);
|
|
10
|
+
if (cachedModulePattern.test(url.pathname))
|
|
11
|
+
return result;
|
|
12
|
+
// packages load once; a linked one resolves to its real path outside node_modules, so still reloads
|
|
13
|
+
if (url.pathname.includes('/node_modules/'))
|
|
14
|
+
return result;
|
|
15
|
+
const version = getVersion(fileURLToPath(url));
|
|
16
|
+
if (version === undefined)
|
|
17
|
+
return result;
|
|
18
|
+
url.searchParams.set('sxyt-v', String(version));
|
|
19
|
+
return { ...result, url: url.href };
|
|
20
|
+
};
|
|
21
|
+
const handle = registerHooks({ resolve });
|
|
22
|
+
return { handle };
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=esmGraphReload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"esmGraphReload.js","sourceRoot":"","sources":["../../../src/cli/lib/esmGraphReload.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAwB,MAAM,aAAa,CAAA;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAMxC,MAAM,mBAAmB,GAAG,2CAA2C,CAAA;AAEvE,MAAM,UAAU,mBAAmB,CAAC,UAAyB;IACzD,MAAM,OAAO,GAAoB,CAAC,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE;QACjE,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;QAC9C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC;YAAE,OAAO,MAAM,CAAA;QAElD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAC/B,IAAI,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,OAAO,MAAM,CAAA;QACzD,oGAAoG;QACpG,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC;YAAE,OAAO,MAAM,CAAA;QAE1D,MAAM,OAAO,GAAG,UAAU,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAA;QAC9C,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,MAAM,CAAA;QAExC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAA;QAC/C,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,CAAA;IACvC,CAAC,CAAA;IAED,MAAM,MAAM,GAAG,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC,CAAA;IACzC,OAAO,EAAE,MAAM,EAAE,CAAA;AACrB,CAAC","sourcesContent":["\nimport { registerHooks, type ResolveHookSync } from 'node:module'\nimport { fileURLToPath } from 'node:url'\n\n\n// a module's current version, or undefined to leave it on Node's ordinary module cache\nexport type VersionLookup = (file: string) => number | undefined\n\nconst cachedModulePattern = /\\._cached_\\.(?:[cm]?js|[cm]?ts|jsx|tsx)$/i\n\nexport function registerGraphReload(getVersion: VersionLookup) {\n const resolve: ResolveHookSync = (specifier, context, nextResolve) => {\n const result = nextResolve(specifier, context)\n if (!result.url.startsWith('file:')) return result\n\n const url = new URL(result.url)\n if (cachedModulePattern.test(url.pathname)) return result\n // packages load once; a linked one resolves to its real path outside node_modules, so still reloads\n if (url.pathname.includes('/node_modules/')) return result\n\n const version = getVersion(fileURLToPath(url))\n if (version === undefined) return result\n\n url.searchParams.set('sxyt-v', String(version))\n return { ...result, url: url.href }\n }\n \n const handle = registerHooks({ resolve })\n return { handle }\n}\n"]}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { isBuiltin, registerHooks } from 'node:module';
|
|
2
|
+
/*
|
|
3
|
+
* Based on esm-reload by Marcel Laverdet and Pierre-Yves Gérardy.
|
|
4
|
+
*
|
|
5
|
+
* ISC License
|
|
6
|
+
*
|
|
7
|
+
* Copyright 2024 Marcel Laverdet & Pierre-Yves Gérardy
|
|
8
|
+
*
|
|
9
|
+
* Permission to use, copy, modify, and/or distribute this software for any
|
|
10
|
+
* purpose with or without fee is hereby granted, provided that the above
|
|
11
|
+
* copyright notice and this permission notice appear in all copies.
|
|
12
|
+
*
|
|
13
|
+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
14
|
+
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
15
|
+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
16
|
+
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
17
|
+
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
18
|
+
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
19
|
+
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
20
|
+
*/
|
|
21
|
+
const cachedModulePattern = /\._cached_\.(?:[cm]?js|[cm]?ts|jsx|tsx)$/i;
|
|
22
|
+
let reloadId = 0;
|
|
23
|
+
function isThisModule(url) {
|
|
24
|
+
const candidate = new URL(url);
|
|
25
|
+
const current = new URL(import.meta.url);
|
|
26
|
+
candidate.search = '';
|
|
27
|
+
current.search = '';
|
|
28
|
+
return candidate.href === current.href;
|
|
29
|
+
}
|
|
30
|
+
function isCachedModule(url) {
|
|
31
|
+
return cachedModulePattern.test(url.pathname);
|
|
32
|
+
}
|
|
33
|
+
export const resolve = (specifier, context, nextResolve) => {
|
|
34
|
+
const result = nextResolve(specifier, context);
|
|
35
|
+
if (isThisModule(result.url) || isBuiltin(result.url) || context.parentURL === undefined) {
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
const url = new URL(result.url);
|
|
39
|
+
// A *._cached_.js/ts module and its dependency graph use Node's ordinary
|
|
40
|
+
// process-wide module cache instead of inheriting the test file instance.
|
|
41
|
+
if (isCachedModule(url))
|
|
42
|
+
return result;
|
|
43
|
+
// packages load once; a linked one resolves to its real path outside node_modules, so still reloads
|
|
44
|
+
if (url.pathname.includes('/node_modules/'))
|
|
45
|
+
return result;
|
|
46
|
+
const parentUrl = new URL(context.parentURL);
|
|
47
|
+
const instance = url.searchParams.get('reload') === ''
|
|
48
|
+
? `sxy-test-runner-reload-${reloadId++}`
|
|
49
|
+
: parentUrl.searchParams.get('sxyt-instance');
|
|
50
|
+
if (instance === null)
|
|
51
|
+
return result;
|
|
52
|
+
url.searchParams.delete('reload');
|
|
53
|
+
url.searchParams.set('sxyt-instance', instance);
|
|
54
|
+
return {
|
|
55
|
+
...result,
|
|
56
|
+
url: url.href
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
export function registerTreeReload() {
|
|
60
|
+
return registerHooks({ resolve });
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=esmTreeReload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"esmTreeReload.js","sourceRoot":"","sources":["../../../src/cli/lib/esmTreeReload.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,aAAa,EAA0C,MAAM,aAAa,CAAA;AAG9F;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,mBAAmB,GAAG,2CAA2C,CAAA;AAEvE,IAAI,QAAQ,GAAG,CAAC,CAAA;AAEhB,SAAS,YAAY,CAAC,GAAW;IAC7B,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;IAC9B,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACxC,SAAS,CAAC,MAAM,GAAG,EAAE,CAAA;IACrB,OAAO,CAAC,MAAM,GAAG,EAAE,CAAA;IACnB,OAAO,SAAS,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,CAAA;AAC1C,CAAC;AAED,SAAS,cAAc,CAAC,GAAQ;IAC5B,OAAO,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;AACjD,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAoB,CAAC,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE;IACxE,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;IAE9C,IAAI,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACvF,OAAO,MAAM,CAAA;IACjB,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IAE/B,yEAAyE;IACzE,0EAA0E;IAC1E,IAAI,cAAc,CAAC,GAAG,CAAC;QAAE,OAAO,MAAM,CAAA;IACtC,oGAAoG;IACpG,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QAAE,OAAO,MAAM,CAAA;IAE1D,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IAC5C,MAAM,QAAQ,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE;QAClD,CAAC,CAAC,0BAA0B,QAAQ,EAAE,EAAE;QACxC,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;IAEjD,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,MAAM,CAAA;IAEpC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IACjC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAA;IAE/C,OAAO;QACH,GAAG,MAAM;QACT,GAAG,EAAE,GAAG,CAAC,IAAI;KAChB,CAAA;AACL,CAAC,CAAA;AAED,MAAM,UAAU,kBAAkB;IAC9B,OAAO,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC,CAAA;AACrC,CAAC","sourcesContent":["\nimport { isBuiltin, registerHooks, type ModuleHooks, type ResolveHookSync } from 'node:module'\n\n\n/*\n * Based on esm-reload by Marcel Laverdet and Pierre-Yves Gérardy.\n *\n * ISC License\n *\n * Copyright 2024 Marcel Laverdet & Pierre-Yves Gérardy\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\nconst cachedModulePattern = /\\._cached_\\.(?:[cm]?js|[cm]?ts|jsx|tsx)$/i\n\nlet reloadId = 0\n\nfunction isThisModule(url: string): boolean {\n const candidate = new URL(url)\n const current = new URL(import.meta.url)\n candidate.search = ''\n current.search = ''\n return candidate.href === current.href\n}\n\nfunction isCachedModule(url: URL): boolean {\n return cachedModulePattern.test(url.pathname)\n}\n\nexport const resolve: ResolveHookSync = (specifier, context, nextResolve) => {\n const result = nextResolve(specifier, context)\n\n if (isThisModule(result.url) || isBuiltin(result.url) || context.parentURL === undefined) {\n return result\n }\n\n const url = new URL(result.url)\n\n // A *._cached_.js/ts module and its dependency graph use Node's ordinary\n // process-wide module cache instead of inheriting the test file instance.\n if (isCachedModule(url)) return result\n // packages load once; a linked one resolves to its real path outside node_modules, so still reloads\n if (url.pathname.includes('/node_modules/')) return result\n\n const parentUrl = new URL(context.parentURL)\n const instance = url.searchParams.get('reload') === ''\n ? `sxy-test-runner-reload-${reloadId++}`\n : parentUrl.searchParams.get('sxyt-instance')\n\n if (instance === null) return result\n\n url.searchParams.delete('reload')\n url.searchParams.set('sxyt-instance', instance)\n\n return {\n ...result,\n url: url.href\n }\n}\n\nexport function registerTreeReload(): ModuleHooks {\n return registerHooks({ resolve })\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ReRunManager } from './reRunManager.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { RerunTestsFunction } from './listenToUser.js';
|
|
3
3
|
import type { OutFn } from '../../types.js';
|
|
4
|
-
export declare function handleUserInput(input: string, reRunManager: ReRunManager, rerunTestsCallback:
|
|
4
|
+
export declare function handleUserInput(input: string, reRunManager: ReRunManager, rerunTestsCallback: RerunTestsFunction, customOut?: OutFn): void;
|
|
5
5
|
//# sourceMappingURL=handleUserInput.d.ts.map
|
|
@@ -25,28 +25,35 @@ export function handleUserInput(input, reRunManager, rerunTestsCallback, customO
|
|
|
25
25
|
//console.log('watchRunState.activeRuns', watchRunState.activeRuns)
|
|
26
26
|
// if (rerunManager.watchRunState.activeRuns > 0) return
|
|
27
27
|
let type;
|
|
28
|
-
let
|
|
28
|
+
let testFilesSet;
|
|
29
29
|
if (command === 'r' || command === 'l') {
|
|
30
30
|
type = 'last';
|
|
31
|
-
|
|
31
|
+
testFilesSet = reRunManager.state.lastTestFiles;
|
|
32
32
|
}
|
|
33
33
|
else if (command === 'a') {
|
|
34
34
|
type = 'all';
|
|
35
|
-
|
|
35
|
+
testFilesSet = reRunManager.state.allTestFiles;
|
|
36
36
|
}
|
|
37
37
|
else if (command === 'f') {
|
|
38
38
|
type = 'failed';
|
|
39
|
-
|
|
39
|
+
testFilesSet = reRunManager.state.failedTestFiles;
|
|
40
40
|
}
|
|
41
41
|
else {
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
44
|
//console.log('type', type)
|
|
45
45
|
//console.log('testFiles', testFiles)
|
|
46
|
-
if (
|
|
46
|
+
if (testFilesSet.size === 0) {
|
|
47
47
|
out('No suitable test files to run');
|
|
48
48
|
return;
|
|
49
49
|
}
|
|
50
|
-
void reRunManager.requestRun(type,
|
|
50
|
+
void reRunManager.requestRun(type, () => {
|
|
51
|
+
if (testFilesSet.size === 0) {
|
|
52
|
+
out(type + ': No suitable test files to run');
|
|
53
|
+
return Promise.resolve(null);
|
|
54
|
+
}
|
|
55
|
+
return rerunTestsCallback(new Set(testFilesSet));
|
|
56
|
+
});
|
|
57
|
+
//rerunTestsCallback(new Set(testFilesSet))) /// CHECK is it appropriate to copy here?
|
|
51
58
|
}
|
|
52
59
|
//# sourceMappingURL=handleUserInput.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handleUserInput.js","sourceRoot":"","sources":["../../../src/cli/lib/handleUserInput.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,MAAM,yBAAyB,CAAA;AAC3C,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AAGrC,SAAS,gBAAgB,CAAC,KAAuB,EAAE,SAAgB;IAC/D,MAAM,OAAO,GAAG,CAAC,GAAG,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAA;IAChD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,SAAS,CAAC,qCAAqC,CAAC,CAAA;QAChD,OAAM;IACV,CAAC;IAED,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC,CAAA;IACvD,MAAM,MAAM,GAAG,IAAI,CAAA;IACnB,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,KAAK,CAAC,gBAAgB;YAAE,SAAS,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA;QACxE,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,SAAS;YAAE,SAAS,CAAC,GAAG,MAAM,GAAG,KAAK,CAAC,IAAI,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC/G,CAAC;AACL,CAAC;AAGD,MAAM,UAAU,eAAe,CAC3B,KAAa,EACb,YAA0B,EAC1B,
|
|
1
|
+
{"version":3,"file":"handleUserInput.js","sourceRoot":"","sources":["../../../src/cli/lib/handleUserInput.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,MAAM,yBAAyB,CAAA;AAC3C,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AAGrC,SAAS,gBAAgB,CAAC,KAAuB,EAAE,SAAgB;IAC/D,MAAM,OAAO,GAAG,CAAC,GAAG,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAA;IAChD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,SAAS,CAAC,qCAAqC,CAAC,CAAA;QAChD,OAAM;IACV,CAAC;IAED,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC,CAAA;IACvD,MAAM,MAAM,GAAG,IAAI,CAAA;IACnB,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,KAAK,CAAC,gBAAgB;YAAE,SAAS,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA;QACxE,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,SAAS;YAAE,SAAS,CAAC,GAAG,MAAM,GAAG,KAAK,CAAC,IAAI,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC/G,CAAC;AACL,CAAC;AAGD,MAAM,UAAU,eAAe,CAC3B,KAAa,EACb,YAA0B,EAC1B,kBAAsC,EACtC,YAAmB,GAAG;IAEtB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IAE1C,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;QAClB,gBAAgB,CAAC,YAAY,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;QAC/C,OAAM;IACV,CAAC;IAED,iCAAiC;IAEjC,mEAAmE;IACnE,wDAAwD;IAExD,IAAI,IAAa,CAAA;IACjB,IAAI,YAAyB,CAAA;IAC7B,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;QACrC,IAAI,GAAG,MAAM,CAAA;QACb,YAAY,GAAG,YAAY,CAAC,KAAK,CAAC,aAAa,CAAA;IACnD,CAAC;SAAM,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;QACzB,IAAI,GAAG,KAAK,CAAA;QACZ,YAAY,GAAG,YAAY,CAAC,KAAK,CAAC,YAAY,CAAA;IAClD,CAAC;SAAM,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;QACzB,IAAI,GAAG,QAAQ,CAAA;QACf,YAAY,GAAG,YAAY,CAAC,KAAK,CAAC,eAAe,CAAA;IACrD,CAAC;SAAM,CAAC;QACJ,OAAM;IACV,CAAC;IAED,2BAA2B;IAC3B,qCAAqC;IAErC,IAAI,YAAY,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QAC1B,GAAG,CAAC,+BAA+B,CAAC,CAAA;QACpC,OAAM;IACV,CAAC;IACD,KAAK,YAAY,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE;QACpC,IAAI,YAAY,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC1B,GAAG,CAAC,IAAI,GAAG,iCAAiC,CAAC,CAAA;YAC7C,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAChC,CAAC;QACD,OAAO,kBAAkB,CAAC,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;IACF,sFAAsF;AAE1F,CAAC","sourcesContent":["\r\nimport type { ReRunManager, RunType } from './reRunManager.js'\r\nimport type { RerunTestsFunction } from './listenToUser.js'\r\nimport type { ReRunManageState } from './makeWatchRunState.js'\r\nimport type { OutFn } from '../../types.js'\r\nimport chalk from '../../packages/chalk.js'\r\nimport { out } from '../../output.js'\r\n\r\n\r\nfunction showWithoutTests(state: ReRunManageState, customOut: OutFn): void {\r\n const entries = [...state.withoutTests.values()]\r\n if (entries.length === 0) {\r\n customOut('No files or describes without tests')\r\n return\r\n }\r\n\r\n customOut(chalk.grey('Files/describes without tests:'))\r\n const indent = ' '\r\n for (const entry of entries) {\r\n if (entry.fileWithoutTests) customOut(indent + chalk.yellow(entry.file))\r\n for (const describe of entry.describes) customOut(`${indent}${entry.file} > ` + chalk.brightblue(describe))\r\n }\r\n}\r\n\r\n\r\nexport function handleUserInput(\r\n input: string,\r\n reRunManager: ReRunManager,\r\n rerunTestsCallback: RerunTestsFunction,\r\n customOut: OutFn = out\r\n): void {\r\n const command = input.trim().toLowerCase()\r\n\r\n if (command === 'n') {\r\n showWithoutTests(reRunManager.state, customOut)\r\n return\r\n }\r\n\r\n //console.log('command', command)\r\n\r\n //console.log('watchRunState.activeRuns', watchRunState.activeRuns)\r\n // if (rerunManager.watchRunState.activeRuns > 0) return\r\n\r\n let type: RunType\r\n let testFilesSet: Set<string>\r\n if (command === 'r' || command === 'l') {\r\n type = 'last'\r\n testFilesSet = reRunManager.state.lastTestFiles\r\n } else if (command === 'a') {\r\n type = 'all'\r\n testFilesSet = reRunManager.state.allTestFiles\r\n } else if (command === 'f') {\r\n type = 'failed'\r\n testFilesSet = reRunManager.state.failedTestFiles\r\n } else {\r\n return\r\n }\r\n\r\n //console.log('type', type)\r\n //console.log('testFiles', testFiles)\r\n\r\n if (testFilesSet.size === 0) {\r\n out('No suitable test files to run')\r\n return\r\n }\r\n void reRunManager.requestRun(type, () => {\r\n if (testFilesSet.size === 0) {\r\n out(type + ': No suitable test files to run')\r\n return Promise.resolve(null)\r\n }\r\n return rerunTestsCallback(new Set(testFilesSet))\r\n })\r\n //rerunTestsCallback(new Set(testFilesSet))) /// CHECK is it appropriate to copy here?\r\n \r\n}\r\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { OutFn } from '../../types.js';
|
|
2
2
|
import { type ReRunManager } from './reRunManager.js';
|
|
3
3
|
import type { RunTestsPromise } from './runTests.js';
|
|
4
|
-
export type
|
|
5
|
-
export declare function listenToUser(rerunManager: ReRunManager, rerunTestsCallback:
|
|
4
|
+
export type RerunTestsFunction = (testFiles: Set<string>) => RunTestsPromise;
|
|
5
|
+
export declare function listenToUser(rerunManager: ReRunManager, rerunTestsCallback: RerunTestsFunction, ttyActionsOnKeypress: boolean | undefined, initialTestRun: Promise<boolean | null> | null, input?: NodeJS.ReadStream, customOut?: OutFn): () => void;
|
|
6
6
|
//# sourceMappingURL=listenToUser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listenToUser.js","sourceRoot":"","sources":["../../../src/cli/lib/listenToUser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAY,MAAM,eAAe,CAAA;AAK7E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,GAAG,IAAI,OAAO,EAAE,KAAK,IAAI,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAKrE,MAAM,UAAU,YAAY;AACxB,4BAA4B;AAC5B,4BAA4B;AAC5B,YAA0B,EAC1B,
|
|
1
|
+
{"version":3,"file":"listenToUser.js","sourceRoot":"","sources":["../../../src/cli/lib/listenToUser.ts"],"names":[],"mappings":"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","sourcesContent":["\nimport { createInterface, emitKeypressEvents, type Key } from 'node:readline'\n\nimport type { OutFn } from '../../types.js'\nimport { type ReRunManager } from './reRunManager.js'\nimport type { RunTestsPromise } from './runTests.js'\nimport { showTtyHelp } from './showTtyHelp.js'\nimport { handleUserInput } from './handleUserInput.js'\nimport { out as mainOut, error as printError } from '../../output.js'\n\n\nexport type RerunTestsFunction = (testFiles: Set<string>) => RunTestsPromise\n\nexport function listenToUser(\n //allTestFiles: Set<string>,\n //failingTests: Set<string>,\n rerunManager: ReRunManager,\n rerunTestsCallback: RerunTestsFunction,\n ttyActionsOnKeypress = false,\n initialTestRun: Promise<boolean | null> | null,\n input: NodeJS.ReadStream = process.stdin,\n customOut?: OutFn\n): () => void {\n // an agent spawned session has no TTY, so these notices would otherwise be the only\n // lines in agent mode that are not agent events\n const out = customOut ?? mainOut\n\n //console.log('initia test run', initialTestRun)\n //console.log('listen to user')\n\n //setInterval(() => console.log('active runs: ', rerunManager.state.activeRuns), 10_000)\n\n // set by whichever branch attaches listeners below\n let disposeInput = (): void => {}\n\n if (!input.isTTY) {\n out('No TTY available, not receiving cli input')\n return () => {}\n }\n\n if (ttyActionsOnKeypress) {\n \n //console.log('ttyActionsOnKeypress')\n\n emitKeypressEvents(input)\n\n const wasRaw = input.isRaw\n const restoreRawMode = (): void => {\n //console.log('restoreRawMode')\n if (input.isRaw === wasRaw) return\n try {\n input.setRawMode(wasRaw)\n } catch {\n // The terminal stream may already be closed during process shutdown.\n }\n }\n\n input.setRawMode(true)\n input.resume()\n input.once('close', restoreRawMode)\n if (input === process.stdin) process.once('exit', restoreRawMode)\n\n const onKeypress = (keypressInput: string, key: Key): void => {\n //console.log('keypress', keypressInput)\n if (key.ctrl === true && key.name === 'c') {\n restoreRawMode()\n // process.kill(process.pid, 'SIGINT') terminates unconditionally on Windows\n // rather than raising the event, which skips the shutdown handlers and so\n // skips the user's teardown. Emitting reaches them on every platform.\n // Nothing listening means nobody will exit for us, so do it here.\n if (!process.emit('SIGINT', 'SIGINT')) process.exit(130)\n return\n }\n\n handleUserInput(keypressInput, rerunManager, rerunTestsCallback, out)\n }\n input.on('keypress', onKeypress)\n\n disposeInput = () => {\n input.off('keypress', onKeypress)\n // a `once` listener that never fired is still attached\n input.off('close', restoreRawMode)\n process.off('exit', restoreRawMode)\n restoreRawMode()\n // undoes the resume above, so stdin stops holding the event loop open\n input.pause()\n }\n } else {\n //console.log('no ttyActionsOnKeypress')\n\n const userInput = createInterface({ input })\n\n userInput.on('line', input => {\n //console.log('line input', input)\n handleUserInput(input, rerunManager, rerunTestsCallback, out)\n })\n\n disposeInput = () => {\n // close() takes readline's own data/end/error listeners off the stream\n userInput.close()\n input.pause()\n }\n }\n\n let stopped = false\n\n //console.log('initialTestRun 2', initialTestRun)\n initialTestRun\n ?.then(\n () => { if (!stopped) showTtyHelp(input.isTTY, out, rerunManager.state.withoutTests.size > 0) },\n e => printError('Error in initial test run', e)\n )\n .catch(e => { printError('Error showing TTY help', e) })\n\n return () => {\n if (!stopped) {\n stopped = true\n disposeInput()\n }\n }\n}\n"]}
|