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":"describe.js","sourceRoot":"","sources":["../src/describe.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,qBAAqB,CAAA;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAOnC,MAAM,UAAU,QAAQ,CACpB,QAAgB,EAAE,WAA4C,EAAE,aAAgC;IAEhG,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACX,oFAAoF;cAClF,0DAA0D;cAC1D,+CAA+C,CACpD,CAAA;QACD,gFAAgF;IACpF,CAAC;IAED,MAAM,mBAAmB,GAAG,MAAM,CAAC,mBAAmB,CAAC,eAAe,CAAA;IACtE,MAAM,CAAC,mBAAmB,CAAC,eAAe,EAAE,CAAA;IAE5C,IAAI,IAAI,GAAG,SAAS,CAAA;IACpB,IAAI,KAAK,CAAA;IACT,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,2CAA2C,QAAQ,IAAI,CAAC,CAAA;IAC5E,CAAC;SAAM,IAAI,OAAO,WAAW,KAAK,UAAU,EAAE,CAAC;QAC3C,KAAK,GAAG,WAAW,CAAA;IACvB,CAAC;SAAM,CAAC;QACJ,SAAS,CAAC,aAAa,QAAQ,IAAI,EAAE,WAAW,EAAE,CAAC,eAAe,EAAE,iBAAiB,CAAC,CAAC,CAAA;QACvF,IAAI,GAAG,WAAW,CAAA;QAClB,KAAK,GAAG,aAAiC,CAAA,CAAC,kEAAkE;IAChH,CAAC;IACD,MAAM,CAAC,mBAAmB,CAAC,SAAS,CAAC,IAAI,CAAC;QACtC,OAAO,EAAE,mBAAmB;QAC5B,KAAK,EAAE,QAAQ;QACf,IAAI;QACJ,KAAK;KACR,CAAC,CAAA;IAEF,KAAK,CACD,KAAK,CAAC,SAAS,CAAA,GAAG,mBAAmB,GAAG;UAClC,KAAK,CAAC,SAAS,CAAA,aAAa,GAAG,KAAK,CAAC,UAAU,CAAA,GAAG,QAAQ,IAAI,CACvE,CAAA;AACL,CAAC","sourcesContent":["\nimport type { DescribeCallback } from './types.js'\nimport chalk from './packages/chalk.js'\nimport { checkMeta } from './checkMeta.js'\nimport { debug } from './output.js'\n\n\nexport type DescribeMeta = { parallelTests: boolean } | { sequentialTests: boolean }\n\nexport function describe(theThing: string, tests: DescribeCallback): void\nexport function describe(theThing: string, meta: DescribeMeta, tests: DescribeCallback): void\nexport function describe(\n theThing: string, testsOrMeta: DescribeCallback | DescribeMeta, possiblyTests?: DescribeCallback\n): void {\n if (!global.__sxy_test_runner__) {\n throw new Error(\n 'sxy-test-runner describe() was called, but the test framework has not initialized.'\n + ' This might be because you have run a test file directly'\n + ', instead of running \\'pnpm sxy-test-runner\\''\n )\n // todo - maybe we can initialise the framework and just run only this test file\n }\n\n const thisDescribeCounter = global.__sxy_test_runner__.describeCounter\n global.__sxy_test_runner__.describeCounter++\n\n let meta = undefined\n let tests\n if (testsOrMeta === undefined) {\n throw new Error(`callback argument missing for describe('${theThing}')`)\n } else if (typeof testsOrMeta === 'function') {\n tests = testsOrMeta\n } else {\n checkMeta(`describe('${theThing}')`, testsOrMeta, ['parallelTests', 'sequentialTests'])\n meta = testsOrMeta\n tests = possiblyTests as DescribeCallback // eslint-disable-line @typescript-eslint/no-unsafe-type-assertion\n }\n global.__sxy_test_runner__.describes.push({\n counter: thisDescribeCounter,\n thing: theThing,\n meta,\n tests\n })\n\n debug(\n chalk.lightgrey`${thisDescribeCounter})`\n + chalk.lightgrey` Done with ` + chalk.brightblue`${theThing}\\n`\n )\n}\n"]}
1
+ {"version":3,"file":"describe.js","sourceRoot":"","sources":["../src/describe.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,qBAAqB,CAAA;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAOnD,MAAM,UAAU,QAAQ,CACpB,QAAgB,EAAE,WAA4C,EAAE,aAAgC;IAEhG,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACX,oFAAoF;cAClF,0DAA0D;cAC1D,+CAA+C,CACpD,CAAA;QACD,gFAAgF;IACpF,CAAC;IAED,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAA;IAChE,MAAM,mBAAmB,GAAG,YAAY,CAAC,eAAe,CAAA;IACxD,YAAY,CAAC,eAAe,EAAE,CAAA;IAE9B,IAAI,IAAI,GAAG,SAAS,CAAA;IACpB,IAAI,KAAK,CAAA;IACT,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,2CAA2C,QAAQ,IAAI,CAAC,CAAA;IAC5E,CAAC;SAAM,IAAI,OAAO,WAAW,KAAK,UAAU,EAAE,CAAC;QAC3C,KAAK,GAAG,WAAW,CAAA;IACvB,CAAC;SAAM,CAAC;QACJ,SAAS,CAAC,aAAa,QAAQ,IAAI,EAAE,WAAW,EAAE,CAAC,eAAe,EAAE,iBAAiB,CAAC,CAAC,CAAA;QACvF,IAAI,GAAG,WAAW,CAAA;QAClB,KAAK,GAAG,aAAiC,CAAA,CAAC,kEAAkE;IAChH,CAAC;IACD,YAAY,CAAC,SAAS,CAAC,IAAI,CAAC;QACxB,OAAO,EAAE,mBAAmB;QAC5B,KAAK,EAAE,QAAQ;QACf,IAAI;QACJ,KAAK;KACR,CAAC,CAAA;IAEF,KAAK,CACD,KAAK,CAAC,SAAS,CAAA,GAAG,mBAAmB,GAAG;UAClC,KAAK,CAAC,SAAS,CAAA,aAAa,GAAG,KAAK,CAAC,UAAU,CAAA,GAAG,QAAQ,IAAI,CACvE,CAAA;AACL,CAAC","sourcesContent":["\nimport type { DescribeCallback } from './types.js'\nimport chalk from './packages/chalk.js'\nimport { checkMeta } from './checkMeta.js'\nimport { debug } from './output.js'\nimport { registrationFor } from './registration.js'\n\n\nexport type DescribeMeta = { parallelTests: boolean } | { sequentialTests: boolean }\n\nexport function describe(theThing: string, tests: DescribeCallback): void\nexport function describe(theThing: string, meta: DescribeMeta, tests: DescribeCallback): void\nexport function describe(\n theThing: string, testsOrMeta: DescribeCallback | DescribeMeta, possiblyTests?: DescribeCallback\n): void {\n if (!global.__sxy_test_runner__) {\n throw new Error(\n 'sxy-test-runner describe() was called, but the test framework has not initialized.'\n + ' This might be because you have run a test file directly'\n + ', instead of running \\'pnpm sxy-test-runner\\''\n )\n // todo - maybe we can initialise the framework and just run only this test file\n }\n\n const registration = registrationFor(global.__sxy_test_runner__)\n const thisDescribeCounter = registration.describeCounter\n registration.describeCounter++\n\n let meta = undefined\n let tests\n if (testsOrMeta === undefined) {\n throw new Error(`callback argument missing for describe('${theThing}')`)\n } else if (typeof testsOrMeta === 'function') {\n tests = testsOrMeta\n } else {\n checkMeta(`describe('${theThing}')`, testsOrMeta, ['parallelTests', 'sequentialTests'])\n meta = testsOrMeta\n tests = possiblyTests as DescribeCallback // eslint-disable-line @typescript-eslint/no-unsafe-type-assertion\n }\n registration.describes.push({\n counter: thisDescribeCounter,\n thing: theThing,\n meta,\n tests\n })\n\n debug(\n chalk.lightgrey`${thisDescribeCounter})`\n + chalk.lightgrey` Done with ` + chalk.brightblue`${theThing}\\n`\n )\n}\n"]}
package/dist/meta.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { checkMeta } from './checkMeta.js';
2
+ import { registrationFor } from './registration.js';
2
3
  export function meta(theMeta) {
3
4
  if (!global.__sxy_test_runner__) {
4
5
  throw new Error('sxy-test-runner meta() was called, but the test framework has not initialized.'
@@ -6,6 +7,6 @@ export function meta(theMeta) {
6
7
  + ', instead of running \'pnpm sxy-test-runner\'');
7
8
  }
8
9
  checkMeta('meta()', theMeta, ['parallelDescribes', 'sequentialDescribes']);
9
- global.__sxy_test_runner__.fileMeta = theMeta;
10
+ registrationFor(global.__sxy_test_runner__).fileMeta = theMeta;
10
11
  }
11
12
  //# sourceMappingURL=meta.js.map
package/dist/meta.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"meta.js","sourceRoot":"","sources":["../src/meta.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAO1C,MAAM,UAAU,IAAI,CAAC,OAAiB;IAClC,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACX,gFAAgF;cAC9E,0DAA0D;cAC1D,+CAA+C,CACpD,CAAA;IACL,CAAC;IAED,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,mBAAmB,EAAE,qBAAqB,CAAC,CAAC,CAAA;IAE1E,MAAM,CAAC,mBAAmB,CAAC,QAAQ,GAAG,OAAO,CAAA;AACjD,CAAC","sourcesContent":["\nimport { checkMeta } from './checkMeta.js'\n\n\nexport type FileMeta\n = { parallelDescribes: boolean }\n | { sequentialDescribes: boolean }\n\nexport function meta(theMeta: FileMeta): void {\n if (!global.__sxy_test_runner__) {\n throw new Error(\n 'sxy-test-runner meta() was called, but the test framework has not initialized.'\n + ' This might be because you have run a test file directly'\n + ', instead of running \\'pnpm sxy-test-runner\\''\n )\n }\n\n checkMeta('meta()', theMeta, ['parallelDescribes', 'sequentialDescribes'])\n\n global.__sxy_test_runner__.fileMeta = theMeta\n}\n"]}
1
+ {"version":3,"file":"meta.js","sourceRoot":"","sources":["../src/meta.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAOnD,MAAM,UAAU,IAAI,CAAC,OAAiB;IAClC,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACX,gFAAgF;cAC9E,0DAA0D;cAC1D,+CAA+C,CACpD,CAAA;IACL,CAAC;IAED,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,mBAAmB,EAAE,qBAAqB,CAAC,CAAC,CAAA;IAE1E,eAAe,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,QAAQ,GAAG,OAAO,CAAA;AAClE,CAAC","sourcesContent":["\nimport { checkMeta } from './checkMeta.js'\nimport { registrationFor } from './registration.js'\n\n\nexport type FileMeta\n = { parallelDescribes: boolean }\n | { sequentialDescribes: boolean }\n\nexport function meta(theMeta: FileMeta): void {\n if (!global.__sxy_test_runner__) {\n throw new Error(\n 'sxy-test-runner meta() was called, but the test framework has not initialized.'\n + ' This might be because you have run a test file directly'\n + ', instead of running \\'pnpm sxy-test-runner\\''\n )\n }\n\n checkMeta('meta()', theMeta, ['parallelDescribes', 'sequentialDescribes'])\n\n registrationFor(global.__sxy_test_runner__).fileMeta = theMeta\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import type { FileRegistration, SxyTestRunnerGlobal } from './types.js';
2
+ export declare function withoutQuery(url: string): string;
3
+ export declare function registrationFor(registry: SxyTestRunnerGlobal): SxyTestRunnerGlobal | FileRegistration;
4
+ //# sourceMappingURL=registration.d.ts.map
@@ -0,0 +1,34 @@
1
+ import { getCallSites } from 'node:util';
2
+ const maxCallSites = 200;
3
+ export function withoutQuery(url) {
4
+ const parsed = new URL(url);
5
+ parsed.search = '';
6
+ parsed.hash = '';
7
+ return parsed.href;
8
+ }
9
+ // the URL of the module whose top level this call comes from - each module evaluates on a stack
10
+ // of its own, so a module imported by the test file never has the test file beneath it
11
+ function topLevelUrl(fallback) {
12
+ // the module URLs as loaded - with --enable-source-maps they would otherwise name the source
13
+ const sites = getCallSites(maxCallSites, { sourceMap: false });
14
+ // a stack this deep may have lost its outermost frames
15
+ if (sites.length >= maxCallSites)
16
+ return fallback;
17
+ return sites.findLast(site => site.scriptName.startsWith('file:'))?.scriptName ?? fallback;
18
+ }
19
+ // where a describe or meta call registers: the registry itself outside a test file load, as
20
+ // when describe is called directly, otherwise the registration of the module that made it
21
+ export function registrationFor(registry) {
22
+ if (registry.files === undefined || registry.loadingUrl === undefined)
23
+ return registry;
24
+ const url = topLevelUrl(registry.loadingUrl);
25
+ const key = withoutQuery(url);
26
+ let registration = registry.files.get(key);
27
+ // a newer evaluation of the same file replaces what an older one registered
28
+ if (registration?.url !== url) {
29
+ registration = { url, describes: [], describeCounter: 1 };
30
+ registry.files.set(key, registration);
31
+ }
32
+ return registration;
33
+ }
34
+ //# sourceMappingURL=registration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registration.js","sourceRoot":"","sources":["../src/registration.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAKxC,MAAM,YAAY,GAAG,GAAG,CAAA;AAExB,MAAM,UAAU,YAAY,CAAC,GAAW;IACpC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;IAC3B,MAAM,CAAC,MAAM,GAAG,EAAE,CAAA;IAClB,MAAM,CAAC,IAAI,GAAG,EAAE,CAAA;IAChB,OAAO,MAAM,CAAC,IAAI,CAAA;AACtB,CAAC;AAED,gGAAgG;AAChG,uFAAuF;AACvF,SAAS,WAAW,CAAC,QAAgB;IACjC,6FAA6F;IAC7F,MAAM,KAAK,GAAG,YAAY,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAA;IAC9D,uDAAuD;IACvD,IAAI,KAAK,CAAC,MAAM,IAAI,YAAY;QAAE,OAAO,QAAQ,CAAA;IACjD,OAAO,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,EAAE,UAAU,IAAI,QAAQ,CAAA;AAC9F,CAAC;AAED,4FAA4F;AAC5F,0FAA0F;AAC1F,MAAM,UAAU,eAAe,CAAC,QAA6B;IACzD,IAAI,QAAQ,CAAC,KAAK,KAAK,SAAS,IAAI,QAAQ,CAAC,UAAU,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAA;IAEtF,MAAM,GAAG,GAAG,WAAW,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAA;IAC5C,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,CAAA;IAC7B,IAAI,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC1C,4EAA4E;IAC5E,IAAI,YAAY,EAAE,GAAG,KAAK,GAAG,EAAE,CAAC;QAC5B,YAAY,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,eAAe,EAAE,CAAC,EAAE,CAAA;QACzD,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,YAAY,CAAC,CAAA;IACzC,CAAC;IACD,OAAO,YAAY,CAAA;AACvB,CAAC","sourcesContent":["\nimport { getCallSites } from 'node:util'\n\nimport type { FileRegistration, SxyTestRunnerGlobal } from './types.js'\n\n\nconst maxCallSites = 200\n\nexport function withoutQuery(url: string): string {\n const parsed = new URL(url)\n parsed.search = ''\n parsed.hash = ''\n return parsed.href\n}\n\n// the URL of the module whose top level this call comes from - each module evaluates on a stack\n// of its own, so a module imported by the test file never has the test file beneath it\nfunction topLevelUrl(fallback: string): string {\n // the module URLs as loaded - with --enable-source-maps they would otherwise name the source\n const sites = getCallSites(maxCallSites, { sourceMap: false })\n // a stack this deep may have lost its outermost frames\n if (sites.length >= maxCallSites) return fallback\n return sites.findLast(site => site.scriptName.startsWith('file:'))?.scriptName ?? fallback\n}\n\n// where a describe or meta call registers: the registry itself outside a test file load, as\n// when describe is called directly, otherwise the registration of the module that made it\nexport function registrationFor(registry: SxyTestRunnerGlobal): SxyTestRunnerGlobal | FileRegistration {\n if (registry.files === undefined || registry.loadingUrl === undefined) return registry\n\n const url = topLevelUrl(registry.loadingUrl)\n const key = withoutQuery(url)\n let registration = registry.files.get(key)\n // a newer evaluation of the same file replaces what an older one registered\n if (registration?.url !== url) {\n registration = { url, describes: [], describeCounter: 1 }\n registry.files.set(key, registration)\n }\n return registration\n}\n"]}
package/dist/types.d.ts CHANGED
@@ -79,10 +79,18 @@ export type It = {
79
79
  should: string;
80
80
  test: (parcel: TestParcel) => void | Promise<void>;
81
81
  };
82
+ export interface FileRegistration {
83
+ url: string;
84
+ describes: Describe[];
85
+ describeCounter: number;
86
+ fileMeta?: FileMeta;
87
+ }
82
88
  export interface SxyTestRunnerGlobal {
83
89
  describes: Describe[];
84
90
  describeCounter: number;
85
91
  fileMeta?: FileMeta;
92
+ files?: Map<string, FileRegistration>;
93
+ loadingUrl?: string;
86
94
  }
87
95
  declare global {
88
96
  var __sxy_test_runner__: SxyTestRunnerGlobal | undefined;
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AACA,2EAA2E;AAC3E,2EAA2E;AAC3E,2EAA2E;AAC3E,+EAA+E","sourcesContent":["\n// Shared types for the test-run data model, user config, and CLI plumbing.\n// The config/result shapes are inferred from usage across the old awaitful\n// source (defaultConfig.js, validateConfig.js, init.js's template, and the\n// run*/parseDescribe/showTestResult modules) - there was no prior type source.\n\nimport type { FileMeta } from './meta.js'\nimport type { DescribeMeta } from './describe.js'\n\n\nexport type ExecutionMode = 'parallel' | 'sequential'\nexport type GlobPattern = string | string[]\n\nexport interface ExecutionConfig {\n files: ExecutionMode\n describes: ExecutionMode\n tests: ExecutionMode\n}\n\n// path to write the latest watch run status to, or false to write none\nexport type StatusFileConfig = string | false\n\nexport interface WatchConfig {\n watchFilesBase: string\n watchFiles: GlobPattern\n watchFilesIgnore: GlobPattern\n runAllOnStartup: boolean\n reRunFailingTests: boolean\n // map a changed file to the tests that import it. Off, any watched change runs everything\n dependencyEvaluation: boolean\n ttyActionsOnKeypress: boolean\n statusFile: StatusFileConfig\n}\n\nexport type TaskExports = Record<string, unknown>\nexport type ConfigTaskFn = (parcel?: TaskExports) => TaskExports | void | Promise<TaskExports | void>\n// a task may also be a file path (relative to the project root) to dynamically import\nexport type ConfigTask = ConfigTaskFn | string\nexport type ConfigTasks = ConfigTask | ConfigTask[]\n\nexport interface FinalConfig {\n testsBase: string\n tests: GlobPattern\n testsFilter?: string\n testsIgnore: GlobPattern\n setup?: ConfigTasks\n beforeEachFile?: ConfigTasks\n afterEachFile?: ConfigTasks\n beforeEachDescribe?: ConfigTasks\n afterEachDescribe?: ConfigTasks\n beforeEachTest?: ConfigTasks\n afterEachTest?: ConfigTasks\n teardown?: ConfigTasks\n showErrorTrace: boolean\n compact: boolean\n // repeat a failed run's failures above the tallies, where scrolling has not buried them\n restateFailures: boolean\n // report the run as single agent readable lines instead of the usual output\n agent: boolean\n // the most characters of error text on each agent fail line; Infinity for no limit\n agentLineLengthLimit: number\n // stop the run at the first failing test, erroring describe or unloadable test file.\n // Set by `once --fail-fast` only: it describes one invocation, not a project, and in\n // watch mode it would silently truncate runs that report themselves as covering\n // everything\n failFast: boolean\n execution: ExecutionConfig\n watch: WatchConfig\n}\n\nexport type UserConfig = Partial<\n Omit<FinalConfig, 'testsFilter' | 'failFast' | 'execution' | 'watch'>\n> & {\n execution?: Partial<ExecutionConfig>\n watch?: Partial<WatchConfig>\n}\n\nexport type UserConfigInternal = UserConfig\n & Partial<Pick<FinalConfig, 'testsFilter' | 'failFast'>>\n\n\n// -- test-run data model --------------------------------------------------\n\nexport type TestParcel = TaskExports\n\nexport interface DescribeParcel extends TaskExports {\n it: (should: string, test: (parcel: TestParcel) => void | Promise<void>) => void\n test: (should: string, test: (parcel: TestParcel) => void | Promise<void>) => void\n afterDescribe: (func: () => void | Promise<void>) => void\n beforeEachTest: (func: () => TaskExports | void | Promise<TaskExports | void>) => void\n afterEachTest: (func: () => void | Promise<void>) => void\n}\n\nexport type DescribeCallback = (parcel: DescribeParcel) => void | Promise<void>\n\n\n\nexport interface ParsedDescribe {\n its: It[]\n beforeDescribeExports: TaskExports\n afterDescribeFunc?: () => void | Promise<void>\n beforeEachTestFunc?: () => TaskExports | void | Promise<TaskExports | void>\n afterEachTestFunc?: () => void | Promise<void>\n error?: unknown\n}\n\n// export interface TestError extends Error {\n// actual?: unknown\n// expected?: unknown\n// }\n\n\n\n\n\n\n\n\n\n\nexport type DependencyTrees = Record<string, string[]>\n\nexport type OutFn = (...texts: unknown[]) => void\n\n\n\n// -- globals ----------------------------------------------------------------\n\nexport type Describe = {\n counter: number\n thing: string\n meta?: DescribeMeta\n tests: DescribeCallback\n}\n\nexport type It = {\n counter: number\n should: string\n test: (parcel: TestParcel) => void | Promise<void>\n}\n\nexport interface SxyTestRunnerGlobal {\n describes: Describe[]\n describeCounter: number\n fileMeta?: FileMeta\n}\ndeclare global {\n var __sxy_test_runner__: SxyTestRunnerGlobal | undefined\n var __sxyt_commandLineArguments: string[]\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AACA,2EAA2E;AAC3E,2EAA2E;AAC3E,2EAA2E;AAC3E,+EAA+E","sourcesContent":["\n// Shared types for the test-run data model, user config, and CLI plumbing.\n// The config/result shapes are inferred from usage across the old awaitful\n// source (defaultConfig.js, validateConfig.js, init.js's template, and the\n// run*/parseDescribe/showTestResult modules) - there was no prior type source.\n\nimport type { FileMeta } from './meta.js'\nimport type { DescribeMeta } from './describe.js'\n\n\nexport type ExecutionMode = 'parallel' | 'sequential'\nexport type GlobPattern = string | string[]\n\nexport interface ExecutionConfig {\n files: ExecutionMode\n describes: ExecutionMode\n tests: ExecutionMode\n}\n\n// path to write the latest watch run status to, or false to write none\nexport type StatusFileConfig = string | false\n\nexport interface WatchConfig {\n watchFilesBase: string\n watchFiles: GlobPattern\n watchFilesIgnore: GlobPattern\n runAllOnStartup: boolean\n reRunFailingTests: boolean\n // map a changed file to the tests that import it. Off, any watched change runs everything\n dependencyEvaluation: boolean\n ttyActionsOnKeypress: boolean\n statusFile: StatusFileConfig\n}\n\nexport type TaskExports = Record<string, unknown>\nexport type ConfigTaskFn = (parcel?: TaskExports) => TaskExports | void | Promise<TaskExports | void>\n// a task may also be a file path (relative to the project root) to dynamically import\nexport type ConfigTask = ConfigTaskFn | string\nexport type ConfigTasks = ConfigTask | ConfigTask[]\n\nexport interface FinalConfig {\n testsBase: string\n tests: GlobPattern\n testsFilter?: string\n testsIgnore: GlobPattern\n setup?: ConfigTasks\n beforeEachFile?: ConfigTasks\n afterEachFile?: ConfigTasks\n beforeEachDescribe?: ConfigTasks\n afterEachDescribe?: ConfigTasks\n beforeEachTest?: ConfigTasks\n afterEachTest?: ConfigTasks\n teardown?: ConfigTasks\n showErrorTrace: boolean\n compact: boolean\n // repeat a failed run's failures above the tallies, where scrolling has not buried them\n restateFailures: boolean\n // report the run as single agent readable lines instead of the usual output\n agent: boolean\n // the most characters of error text on each agent fail line; Infinity for no limit\n agentLineLengthLimit: number\n // stop the run at the first failing test, erroring describe or unloadable test file.\n // Set by `once --fail-fast` only: it describes one invocation, not a project, and in\n // watch mode it would silently truncate runs that report themselves as covering\n // everything\n failFast: boolean\n execution: ExecutionConfig\n watch: WatchConfig\n}\n\nexport type UserConfig = Partial<\n Omit<FinalConfig, 'testsFilter' | 'failFast' | 'execution' | 'watch'>\n> & {\n execution?: Partial<ExecutionConfig>\n watch?: Partial<WatchConfig>\n}\n\nexport type UserConfigInternal = UserConfig\n & Partial<Pick<FinalConfig, 'testsFilter' | 'failFast'>>\n\n\n// -- test-run data model --------------------------------------------------\n\nexport type TestParcel = TaskExports\n\nexport interface DescribeParcel extends TaskExports {\n it: (should: string, test: (parcel: TestParcel) => void | Promise<void>) => void\n test: (should: string, test: (parcel: TestParcel) => void | Promise<void>) => void\n afterDescribe: (func: () => void | Promise<void>) => void\n beforeEachTest: (func: () => TaskExports | void | Promise<TaskExports | void>) => void\n afterEachTest: (func: () => void | Promise<void>) => void\n}\n\nexport type DescribeCallback = (parcel: DescribeParcel) => void | Promise<void>\n\n\n\nexport interface ParsedDescribe {\n its: It[]\n beforeDescribeExports: TaskExports\n afterDescribeFunc?: () => void | Promise<void>\n beforeEachTestFunc?: () => TaskExports | void | Promise<TaskExports | void>\n afterEachTestFunc?: () => void | Promise<void>\n error?: unknown\n}\n\n// export interface TestError extends Error {\n// actual?: unknown\n// expected?: unknown\n// }\n\n\n\n\n\n\n\n\n\n\nexport type DependencyTrees = Record<string, string[]>\n\nexport type OutFn = (...texts: unknown[]) => void\n\n\n\n// -- globals ----------------------------------------------------------------\n\nexport type Describe = {\n counter: number\n thing: string\n meta?: DescribeMeta\n tests: DescribeCallback\n}\n\nexport type It = {\n counter: number\n should: string\n test: (parcel: TestParcel) => void | Promise<void>\n}\n\n// what one evaluation of a module registered, from the exact URL it was evaluated as\nexport interface FileRegistration {\n url: string\n describes: Describe[]\n describeCounter: number\n fileMeta?: FileMeta\n}\n\nexport interface SxyTestRunnerGlobal {\n describes: Describe[]\n describeCounter: number\n fileMeta?: FileMeta\n // set while loading test files: registrations filed by the module whose top level made them,\n // so a test file imported by another is credited to itself, keyed by URL without its query\n files?: Map<string, FileRegistration>\n // the URL the test file is being imported as, for a call whose top level cannot be found\n loadingUrl?: string\n}\ndeclare global {\n var __sxy_test_runner__: SxyTestRunnerGlobal | undefined\n var __sxyt_commandLineArguments: string[]\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sxy-test-runner",
3
- "version": "2.5.3",
3
+ "version": "2.5.5",
4
4
  "license": "MIT",
5
5
  "homepage": "https://github.com/RobertSandiford/sxy-test-runner",
6
6
  "repository": {
@@ -41,11 +41,12 @@
41
41
  "dependencies": {
42
42
  "chalk": "^4.1.2",
43
43
  "cross-env": "^7.0.3",
44
- "dependency-tree": "^12.0.1",
45
44
  "esm-reload": "^1.0.1",
45
+ "filing-cabinet": "^6.0.0",
46
46
  "node-watch": "^0.7.4",
47
47
  "rimraf": "^6.1.3",
48
- "sxy-lib": "^3.0.7"
48
+ "sxy-lib": "^3.0.7",
49
+ "sxy-precinct": "^13.1.1"
49
50
  },
50
51
  "devDependencies": {
51
52
  "@types/chai": "^5.2.3",
@@ -63,16 +64,20 @@
63
64
  "eslint-config-tungsten-flat": "^0.3.4",
64
65
  "eslint-plugin-imports-regulation": "0.2.4",
65
66
  "eslint-plugin-start-end-lines": "^0.1.0",
67
+ "eslint-plugin-use-disposables": "^0.1.1",
66
68
  "mocha": "^9.2.2",
67
69
  "mocha-steps": "^1.3.0",
68
70
  "nodemon": "^2.0.22",
69
71
  "sinon": "^12.0.1",
70
72
  "sinon-chai": "^3.7.0",
73
+ "sxy-assert": "^0.1.13",
71
74
  "typescript": "^6.0.3"
72
75
  },
73
76
  "scripts": {
74
- "build": "rimraf dist && tsc --watch",
75
- "build-once": "rimraf dist && tsc",
77
+ "build": "tscmon",
78
+ "build-once": "tscmon --once",
79
+ "time-dep-graph": "node bench/depGraph.ts",
80
+ "time-reload": "node bench/reload.ts",
76
81
  "dev-mon": "cross-env NODE_OPTIONS=\"--experimental-specifier-resolution=node\" nodemon --experimental-specifier-resolution=node --watch dist/cli --watch dist/cli/lib --watch sxy-test-runner.config.js --watch sxy-loader.config.js dist/cli/index.js",
77
82
  "dev-mon-input": "cross-env NODE_OPTIONS=\"--experimental-specifier-resolution=node\" nodemon --no-stdin --experimental-specifier-resolution=node --watch dist/cli --watch dist/cli/lib --watch sxy-test-runner.config.js --watch sxy-loader.config.js dist/cli/index.js",
78
83
  "dev": "cross-env NODE_OPTIONS=\"--experimental-specifier-resolution=node\" node --experimental-specifier-resolution=node dist/cli/index.js",
@@ -114,7 +119,7 @@
114
119
  "unit-test-add-exports": "mocha --watch --parallel --config unitTesting/.mocharc.cjs --watch-files dist,unitTesting dist/**/addExports.unitTest.js",
115
120
  "unit-test-describe": "mocha --watch --parallel --config unitTesting/.mocharc.cjs --watch-files dist,unitTesting dist/**/describe.unitTest.js",
116
121
  "unit-test-run-tests": "mocha --watch --parallel --config unitTesting/.mocharc.cjs --watch-files dist,unitTesting dist/**/runTests.unitTest.js",
117
- "unit-test-esm-reload": "mocha --watch --parallel --config unitTesting/.mocharc.cjs --watch-files dist,unitTesting dist/**/esmReload.unitTest.js",
122
+ "unit-test-esm-reload": "mocha --watch --parallel --config unitTesting/.mocharc.cjs --watch-files dist,unitTesting dist/**/esmTreeReload.unitTest.js",
118
123
  "unit-test-user-input": "mocha --watch --parallel --config unitTesting/.mocharc.cjs --watch-files dist,unitTesting dist/**/handleUserInput.unitTest.js dist/**/listenToUser.unitTest.js",
119
124
  "mocha-trial": "mocha --watch --parallel --config unitTesting/.mocharc.cjs --watch-files dist,unitTesting dist/**/runTest.unitTest.js"
120
125
  }
package/readme.md CHANGED
@@ -74,18 +74,18 @@ This will create a config in your project folder. It can be moved to a folder na
74
74
  }
75
75
  ```
76
76
 
77
- The other config options and fairly well explained in the config. More info on them later.
77
+ The other config options are fairly well explained in the config. More info on them later.
78
78
 
79
79
  ### 4. Run
80
80
 
81
81
  ```
82
82
  npx sxy-test-runner
83
83
  ```
84
- *sxyt and sxy-test are aliases for sxy-test-runner and can be used instead*
84
+ *`sxyt` and `sxy-test` are aliases for sxy-test-runner and can be used instead*
85
85
 
86
86
  ("npx" can be omitted in package.json scripts)
87
87
 
88
- sxy-test-runner runs watch mode, re-running only relevant tests, by default.
88
+ `sxy-test-runner` runs watch mode, re-running only relevant tests, by default.
89
89
 
90
90
  While watch mode is idle, enter `r` or `l` to re-run the last set of tests, `a` to run
91
91
  all tests again, or `f` to re-run the currently failing tests.
@@ -115,70 +115,16 @@ npx sxy-test-runner once --filter "**/users/**"
115
115
  `--test-files` and `--filter` can be combined: the former replaces the configured test
116
116
  pattern, then the latter filters the discovered files.
117
117
 
118
- `--filter-describe` and `--filter-it` filter by name, but only after the selected test files
119
- have loaded. sxy-test-runner gives each test file a fresh ESM instance and propagates it
120
- through that file's static dependency graph, bypassing the ordinary ESM cache. Loading a
121
- large set of files and filtering their describes or tests afterward can therefore be much
122
- slower than filtering files first. Prefer `--filter` when a file glob can select the work
123
- you need, and use the name filters for further narrowing within those files.
118
+ `--filter-describe` and `--filter-it` filter describes and tests by name.
124
119
 
125
- To have watch mode record each run's result in a file, use `-s` or `--status-file`, or set
126
- `watch.statusFile` in the config. This is for anything watching the suite from outside - a
127
- script, a notifier, an agent - that would otherwise have to read the terminal:
128
-
129
- ```
130
- npx sxy-test-runner --status-file .sxyt-status
131
- ```
132
-
133
- The first line is a status code, a `-`, and a short description. The second is the time the
134
- run finished, then the summary, then any failures, and the run's duration last:
135
-
136
- ```
137
- 1 - 2 tests failed
138
- 2026-08-03 20:14:52 +01:00
139
- Tests: 8/10
140
- Items: 4/5
141
- Test Files: 1/2
142
- Failures:
143
- f: tests/users.test.js
144
- d: creating a user
145
- t: rejects a duplicate email
146
- e: AssertionError: expected 409 to equal 200
147
- t: sends a welcome email
148
- e: Error: connect ECONNREFUSED 127.0.0.1:2525
149
- 1,204ms
150
- ```
151
-
152
- Failures nest as `f:` file, `d:` describe, `t:` test, `e:` error - one line each. Diffs, logs
153
- and stack traces stay in the terminal.
154
-
155
- | code | meaning |
156
- | --- | --- |
157
- | -1 | watch mode has started, but no run has finished |
158
- | 0 | everything passed |
159
- | 1 | tests ran and failed |
160
- | 2 | the run died partway - a test file would not load, or a describe threw |
161
- | 3 | nothing ran - no test files were found, or the filters matched nothing |
162
-
163
- Watch mode writes the `-1` status on startup, so a status left over from a previous session
164
- is never read as the current one. Each write goes to a temporary file and is renamed into
165
- place, so a poller only ever sees a complete status.
166
-
167
- Name the file `.sxys` and the VS Code extension in
168
- [`vscode-sxyt-status/`](vscode-sxyt-status) will colour it - green when the run passed, red
169
- where it did not.
170
-
171
- To specific an alternate config, use -c or --config
120
+ To specify an alternate config, use -c or --config
172
121
  ```
173
- npx sxy-test-runner --config sxy-test-runner.alternate.config.js
122
+ npx sxy-test-runner --config sxyt.alternate.config.js
174
123
  ```
175
124
 
176
125
  ## Reporting for an agent
177
126
 
178
- `--agent` replaces the usual output with one line per event, for something reading the
179
- process's stdout rather than a terminal. It works in both modes. In `once` it leaves only
180
- the failures and the summary - passing tests are not listed - and the exit code is
181
- unchanged, so the run stays usable in CI:
127
+ `--agent` replaces the usual (verbose) output with lines for key events - e.g. startup, failures, and completion.
182
128
 
183
129
  ```
184
130
  npx sxy-test-runner once --agent
@@ -192,77 +138,28 @@ npx sxy-test-runner once --agent
192
138
  [sxyt] done | n=1 | status=failed | desc=1 test failed | tests=2/3 | items=1/2 | files=1/2 | failing=1 | ms=150
193
139
  ```
194
140
 
195
- Every line is one complete event: `[sxyt] <event>` followed by ` | <key>=<value>` pairs.
196
- Newlines in free text are collapsed and any `|` becomes `/`, so one event never spans two
197
- lines. In watch mode the stream continues with `change`, further `run`/`done` pairs, and a
198
- `watching` line once the watcher is live.
199
-
200
- `failing` counts the test files still known to be failing across the whole session, and
201
- `covers` says what the run was built from, so a partial re-run cannot be mistaken for a
202
- clean suite. `status` is one of `passed`, `failed`, `aborted` (a test file would not load, or
203
- a describe threw) or `could-not-run` - the same states as the status file table above, named
204
- rather than numbered. It is not the process exit code: read that from the process.
205
-
206
- Each failure's error message is cut at 500 characters. Set `agentLineLengthLimit` in the
207
- config to change that, or to `Infinity` to keep messages whole.
208
-
209
141
  Agent mode also sets the environment variables `SXYT_AGENT` and `SXY_TEST_RUNNER_AGENT` to
210
142
  `true`, so setup code and tests can tell they are running under it.
211
143
 
212
- ## Stopping at the first failure
213
-
214
- `-x` or `--fail-fast` stops a `once` run at the first failing test, erroring describe, or
215
- test file that will not load. The failure is reported in full and nothing further starts;
216
- `afterEach*` hooks and `teardown` still run:
217
-
218
- ```
219
- npx sxy-test-runner once --fail-fast
220
- ```
221
-
222
- The tallies then count only what ran, so the summary ends with `stopped at the first
223
- failure (failFast)`. There is no watch equivalent, and no config option - it describes a
224
- single run rather than a project.
225
-
226
- ## Unrecognised options
227
-
228
- `--help` (`-h`) and `--version` (`-v`) work on any command and take over from it, so
229
- `once --help` describes `once` rather than running the suite.
230
-
231
- An option that the command does not accept is an error: the command exits without running
232
- anything, rather than warning and carrying on. A typo like `--fitler-it` would otherwise
233
- quietly run the whole suite and report a pass. Options are per-command, so `--fail-fast`
234
- belongs to `once` and `--status-file` to `watch`. Run `npx sxy-test-runner help`, or add
235
- `--help` to any command, for the current list.
236
-
237
144
  # How it works
238
145
 
239
- sxy-test-runner runs all tests inside one node process, to improve performance (this framework far exceeds mocha in parallel mode, which is needed to test ESM files, due to this).
240
-
241
- Because of this, be careful with globals, which will be shared.
146
+ sxy-test-runner runs all tests inside one node process. Be careful with globals, which will be shared.
242
147
 
243
148
  While tests are running, `NODE_ENV` defaults to `test` when it was not already set.
244
149
  `SXYT` and `SXY_TEST_RUNNER` are both set to `true`, allowing configuration and application
245
150
  code to detect sxy-test-runner specifically. In agent mode, `SXYT_AGENT` and
246
151
  `SXY_TEST_RUNNER_AGENT` are also set to `true`.
247
152
 
248
- ### Sharing a module between test files
153
+ ### Caching modules
249
154
 
250
- Ordinary test dependencies receive a fresh module instance for each test file. To
251
- deliberately share a module and its static dependency graph, give its filename a
252
- `._cached_.` marker:
155
+ In watch mode modules will be reloaded as needed. With `watch.dependencyEvaluation: false` everything will be reloaded on each run.
156
+
157
+ To force a file never to be reloaded, insert `._cached_.` into its filename, like:
253
158
 
254
159
  ```js
255
160
  import { database } from './fixtures/database._cached_.js'
256
161
  ```
257
162
 
258
- The module then uses Node's normal process-wide module cache, so every test file receives
259
- the same exported values. JavaScript and TypeScript module extensions are supported; in
260
- TypeScript `NodeNext` source, import the emitted `._cached_.js` name as usual.
261
-
262
- Cached modules remain loaded for the full one-off run or watch process. Avoid unsynchronised
263
- mutable state when tests run in parallel, and explicitly clean up shared resources such as
264
- servers or database connections.
265
-
266
163
  ## Execution modes
267
164
 
268
165
  **execution** settings let you choose whether to run test files, describe blocks, and individual tests sequentially or in parallel.
@@ -271,17 +168,13 @@ If working with globals you may want to use sequential only, to avoid conflicts
271
168
 
272
169
  Sequential mode also allows console log output to be displayed correctly with each test. Running in parallel mode does not allow log output to be matched up to each test, due to the use of a global override on console.log (other console output methods such as console.trace() are not covered currently)
273
170
 
274
- If your code is isolated, and asyncronous, you can use parallel exeecution modes to radically speed up your tests, as the expense of the points mentioned above.
171
+ If your code is isolated, and asynchronous, you can use parallel execution modes to radically speed up your tests, at the expense of the points mentioned above.
275
172
 
276
173
  ## Dependencies
277
174
 
278
- Module dependencies are identified using dependency-tree. Dynamic imports will not be detected and will not trigger test re-runs.
175
+ Dynamic imports will not be detected and will not trigger test re-runs.
279
176
 
280
- To re-run every test on any watched change instead, set `config.watch.dependencyEvaluation`
281
- to `false`. The dependency analysis is then skipped entirely - no trees are built at startup,
282
- which is the slowest part of it on a large suite - and the blind spot above stops mattering,
283
- because nothing is being predicted. On a small or fast suite this is often the better
284
- setting; on a large one it trades a slower re-run for a complete one.
177
+ To re-run every test on any change in the watched files instead set `watch.dependencyEvaluation: false`
285
178
 
286
179
  ## Failing test re-running
287
180
 
@@ -372,5 +265,5 @@ describe('something', ({it, beforeEachTest, afterEachTest, afterDescribe}) => {
372
265
  These start at 20 to stay clear of Node's reserved codes (1-14) and of signal exits
373
266
  (over 128), so a non-zero code is always sxy-test's own.
374
267
 
375
- It may also crash due to exceptions without giving any of these codes, in which case Node
268
+ It could also crash due to exceptions without giving any of these codes, in which case Node
376
269
  supplies the code - usually `1` for an uncaught exception.
@@ -1,11 +0,0 @@
1
- interface ResolveContext {
2
- parentURL?: string;
3
- }
4
- interface ResolveResult {
5
- url: string;
6
- [key: string]: unknown;
7
- }
8
- type NextResolve = (specifier: string, context: ResolveContext) => ResolveResult | Promise<ResolveResult>;
9
- export declare function resolve(specifier: string, context: ResolveContext, nextResolve: NextResolve): Promise<ResolveResult>;
10
- export {};
11
- //# sourceMappingURL=esmReload.d.ts.map
@@ -1,43 +0,0 @@
1
- import { isBuiltin, register } from 'node:module';
2
- const cachedModulePattern = /\._cached_\.(?:[cm]?js|[cm]?ts|jsx|tsx)$/i;
3
- let reloadId = 0;
4
- function isLoaderInstance() {
5
- return new URL(import.meta.url).searchParams.has('loader');
6
- }
7
- function isThisModule(url) {
8
- const candidate = new URL(url);
9
- const current = new URL(import.meta.url);
10
- candidate.search = '';
11
- current.search = '';
12
- return candidate.href === current.href;
13
- }
14
- function isCachedModule(url) {
15
- return cachedModulePattern.test(url.pathname);
16
- }
17
- export async function resolve(specifier, context, nextResolve) {
18
- const result = await nextResolve(specifier, context);
19
- if (isThisModule(result.url) || isBuiltin(result.url) || context.parentURL === undefined) {
20
- return result;
21
- }
22
- const url = new URL(result.url);
23
- // A *._cached_.js/ts module and its dependency graph use Node's ordinary
24
- // process-wide module cache instead of inheriting the test file instance.
25
- if (isCachedModule(url))
26
- return result;
27
- const parentUrl = new URL(context.parentURL);
28
- const instance = url.searchParams.get('reload') === ''
29
- ? `sxy-test-runner-reload-${reloadId++}`
30
- : parentUrl.searchParams.get('sxyt-instance');
31
- if (instance === null)
32
- return result;
33
- url.searchParams.delete('reload');
34
- url.searchParams.set('sxyt-instance', instance);
35
- return {
36
- ...result,
37
- url: url.href
38
- };
39
- }
40
- if (!isLoaderInstance()) {
41
- register(`${import.meta.url}?loader`);
42
- }
43
- //# sourceMappingURL=esmReload.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"esmReload.js","sourceRoot":"","sources":["../../src/packages/esmReload.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAqCjD,MAAM,mBAAmB,GAAG,2CAA2C,CAAA;AAEvE,IAAI,QAAQ,GAAG,CAAC,CAAA;AAEhB,SAAS,gBAAgB;IACrB,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;AAC9D,CAAC;AAED,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,KAAK,UAAU,OAAO,CACzB,SAAiB,EACjB,OAAuB,EACvB,WAAwB;IAExB,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;IAEpD,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;IAEtC,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;AAED,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC;IACtB,QAAQ,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAA;AACzC,CAAC","sourcesContent":["\nimport { isBuiltin, register } 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\ninterface ResolveContext {\n parentURL?: string\n}\n\ninterface ResolveResult {\n url: string\n [key: string]: unknown\n}\n\ntype NextResolve = (\n specifier: string,\n context: ResolveContext\n) => ResolveResult | Promise<ResolveResult>\n\nconst cachedModulePattern = /\\._cached_\\.(?:[cm]?js|[cm]?ts|jsx|tsx)$/i\n\nlet reloadId = 0\n\nfunction isLoaderInstance(): boolean {\n return new URL(import.meta.url).searchParams.has('loader')\n}\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 async function resolve(\n specifier: string,\n context: ResolveContext,\n nextResolve: NextResolve\n): Promise<ResolveResult> {\n const result = await 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\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\nif (!isLoaderInstance()) {\n register(`${import.meta.url}?loader`)\n}\n"]}