@matter/testing 0.12.2 → 0.12.3-alpha.0-20250205-ad3416ca3

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 (94) hide show
  1. package/dist/cjs/cli.js +1 -1
  2. package/dist/cjs/cli.js.map +1 -1
  3. package/dist/cjs/failure-detail.d.ts +7 -6
  4. package/dist/cjs/failure-detail.d.ts.map +1 -1
  5. package/dist/cjs/failure-detail.js +26 -75
  6. package/dist/cjs/failure-detail.js.map +2 -2
  7. package/dist/cjs/failure-reporter.d.ts +11 -0
  8. package/dist/cjs/failure-reporter.d.ts.map +1 -0
  9. package/dist/cjs/failure-reporter.js +78 -0
  10. package/dist/cjs/failure-reporter.js.map +6 -0
  11. package/dist/cjs/global-declarations.d.ts +8 -0
  12. package/dist/cjs/global-declarations.d.ts.map +1 -1
  13. package/dist/cjs/mocha.d.ts.map +1 -1
  14. package/dist/cjs/mocha.js +4 -3
  15. package/dist/cjs/mocha.js.map +1 -1
  16. package/dist/cjs/mocks/logging.js +2 -12
  17. package/dist/cjs/mocks/logging.js.map +2 -2
  18. package/dist/cjs/nodejs-reporter.d.ts +24 -0
  19. package/dist/cjs/nodejs-reporter.d.ts.map +1 -0
  20. package/dist/cjs/nodejs-reporter.js +123 -0
  21. package/dist/cjs/nodejs-reporter.js.map +6 -0
  22. package/dist/cjs/package.json +2 -1
  23. package/dist/cjs/reporter.d.ts +0 -23
  24. package/dist/cjs/reporter.d.ts.map +1 -1
  25. package/dist/cjs/reporter.js +0 -141
  26. package/dist/cjs/reporter.js.map +2 -2
  27. package/dist/cjs/runner.d.ts.map +1 -1
  28. package/dist/cjs/runner.js +7 -7
  29. package/dist/cjs/runner.js.map +2 -2
  30. package/dist/cjs/text-diff.d.ts +10 -0
  31. package/dist/cjs/text-diff.d.ts.map +1 -0
  32. package/dist/cjs/text-diff.js +37 -0
  33. package/dist/cjs/text-diff.js.map +6 -0
  34. package/dist/cjs/web-reporter.d.ts +22 -0
  35. package/dist/cjs/web-reporter.d.ts.map +1 -0
  36. package/dist/cjs/web-reporter.js +58 -0
  37. package/dist/cjs/web-reporter.js.map +6 -0
  38. package/dist/cjs/web.d.ts.map +1 -1
  39. package/dist/cjs/web.js +3 -3
  40. package/dist/cjs/web.js.map +1 -1
  41. package/dist/esm/cli.js +2 -2
  42. package/dist/esm/cli.js.map +1 -1
  43. package/dist/esm/failure-detail.d.ts +7 -6
  44. package/dist/esm/failure-detail.d.ts.map +1 -1
  45. package/dist/esm/failure-detail.js +26 -65
  46. package/dist/esm/failure-detail.js.map +2 -2
  47. package/dist/esm/failure-reporter.d.ts +11 -0
  48. package/dist/esm/failure-reporter.d.ts.map +1 -0
  49. package/dist/esm/failure-reporter.js +58 -0
  50. package/dist/esm/failure-reporter.js.map +6 -0
  51. package/dist/esm/global-declarations.d.ts +8 -0
  52. package/dist/esm/global-declarations.d.ts.map +1 -1
  53. package/dist/esm/mocha.d.ts.map +1 -1
  54. package/dist/esm/mocha.js +4 -3
  55. package/dist/esm/mocha.js.map +1 -1
  56. package/dist/esm/mocks/logging.js +2 -2
  57. package/dist/esm/mocks/logging.js.map +1 -1
  58. package/dist/esm/nodejs-reporter.d.ts +24 -0
  59. package/dist/esm/nodejs-reporter.d.ts.map +1 -0
  60. package/dist/esm/nodejs-reporter.js +103 -0
  61. package/dist/esm/nodejs-reporter.js.map +6 -0
  62. package/dist/esm/package.json +2 -1
  63. package/dist/esm/reporter.d.ts +0 -23
  64. package/dist/esm/reporter.d.ts.map +1 -1
  65. package/dist/esm/reporter.js +0 -127
  66. package/dist/esm/reporter.js.map +1 -1
  67. package/dist/esm/runner.d.ts.map +1 -1
  68. package/dist/esm/runner.js +8 -8
  69. package/dist/esm/runner.js.map +1 -1
  70. package/dist/esm/text-diff.d.ts +10 -0
  71. package/dist/esm/text-diff.d.ts.map +1 -0
  72. package/dist/esm/text-diff.js +17 -0
  73. package/dist/esm/text-diff.js.map +6 -0
  74. package/dist/esm/web-reporter.d.ts +22 -0
  75. package/dist/esm/web-reporter.d.ts.map +1 -0
  76. package/dist/esm/web-reporter.js +38 -0
  77. package/dist/esm/web-reporter.js.map +6 -0
  78. package/dist/esm/web.d.ts.map +1 -1
  79. package/dist/esm/web.js +3 -3
  80. package/dist/esm/web.js.map +1 -1
  81. package/package.json +4 -3
  82. package/src/cli.ts +2 -2
  83. package/src/failure-detail.ts +41 -64
  84. package/src/failure-reporter.ts +65 -0
  85. package/src/global-declarations.ts +8 -0
  86. package/src/mocha.ts +5 -3
  87. package/src/mocks/logging.ts +2 -2
  88. package/src/nodejs-reporter.ts +123 -0
  89. package/src/reporter.ts +0 -147
  90. package/src/runner.ts +10 -7
  91. package/src/text-diff.ts +16 -0
  92. package/src/tsconfig.json +5 -1
  93. package/src/web-reporter.ts +51 -0
  94. package/src/web.ts +4 -3
package/src/mocha.ts CHANGED
@@ -11,9 +11,11 @@ import { FailureDetail } from "./failure-detail.js";
11
11
  import { Boot } from "./mocks/boot.js";
12
12
  import { LoggerHooks } from "./mocks/logging.js";
13
13
  import { TestOptions } from "./options.js";
14
- import { ConsoleProxyReporter, Reporter } from "./reporter.js";
14
+ import { Reporter } from "./reporter.js";
15
15
  import type { TestDescriptor } from "./test-descriptor.js";
16
+ import { TextDiff } from "./text-diff.js";
16
17
  import { wtf } from "./util/wtf.js";
18
+ import { WebReporter } from "./web-reporter.js";
17
19
 
18
20
  // We allow fixed 60s. timeout for our extended "before/after each test" hooks. To make this configurable we'd need
19
21
  // to perform timeout handling ourselves so avoiding for now
@@ -92,7 +94,7 @@ export function generalSetup(mocha: Mocha) {
92
94
  return (this.currentTest as HookableTest)[afterOneHook]?.call(this, done);
93
95
  });
94
96
 
95
- FailureDetail.diff = Base.generateDiff.bind(Base);
97
+ TextDiff.generator = Base.generateDiff.bind(Base);
96
98
  }
97
99
 
98
100
  export function extendApi(Mocha: typeof MochaType) {
@@ -262,7 +264,7 @@ export function browserSetup(mocha: BrowserMocha) {
262
264
  // Start Mocha, proxying reporting through console to Playwright and completing once Mocha has finished
263
265
  auto: async function (options: TestOptions) {
264
266
  TestOptions.apply(mocha, options);
265
- mocha.reporter(adaptReporter(Mocha, "Web", new ConsoleProxyReporter()));
267
+ mocha.reporter(adaptReporter(Mocha, "Web", new WebReporter()));
266
268
  return new Promise<void>(accept => {
267
269
  const runner = this.start();
268
270
  runner.on("end", accept);
@@ -4,7 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
- import colors from "ansi-colors";
7
+ import { ansi, Wrapper } from "#tools/ansi-text";
8
8
 
9
9
  interface LoggerLike {
10
10
  format: string;
@@ -22,7 +22,7 @@ export const TheMockLogger: MockLogger = {
22
22
  };
23
23
 
24
24
  function formatExternalMessage(source: string, text: string) {
25
- return `${colors.bgCyan.black.bold(` ${source} `)} ${colors.dim(text)}`;
25
+ return `${Wrapper.prefixStart}${ansi.black.bg.cyan.bold(` ${source} `)} ${Wrapper.prefixStop}${ansi.dim(text)}`;
26
26
  }
27
27
 
28
28
  /**
@@ -0,0 +1,123 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2024 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { Progress, ansi, std } from "#tools";
8
+ import { FailureDetail } from "./failure-detail.js";
9
+ import { FailureReporter } from "./failure-reporter.js";
10
+ import { Failure, Reporter, Stats } from "./reporter.js";
11
+
12
+ /**
13
+ * Test UI for Node.js.
14
+ */
15
+ export abstract class NodejsReporter implements Reporter {
16
+ #run = "";
17
+ #suite = Array<string>();
18
+ #test?: string;
19
+ #step?: string;
20
+ #stats?: Stats;
21
+ #failures = Array<Failure>();
22
+ #lastTitle?: string;
23
+
24
+ constructor(private progress: Progress) {}
25
+
26
+ beginRun(name: string, stats: Stats | undefined, supportsSuites = true): void {
27
+ this.#run = name;
28
+ this.#suite = [];
29
+ this.#failures = [];
30
+ if (!supportsSuites) {
31
+ this.progress.update(this.#summarize(stats));
32
+ }
33
+ }
34
+
35
+ beginSuite(name: string[]): void {
36
+ this.#suite = name;
37
+ }
38
+
39
+ beginTest(name: string, stats?: Stats): void {
40
+ this.#test = name;
41
+ this.#stats = stats;
42
+ this.#step = undefined;
43
+
44
+ // If not a TTY, only update once per suite to keep the line count down for e.g. GH action logs
45
+ const title = process.stdout.isTTY ? this.#formatName(this.#suite, name) : this.#suite[0];
46
+ this.#updateTitle(title);
47
+ }
48
+
49
+ beginStep(name: string): void {
50
+ this.#step = name;
51
+
52
+ if (process.stdout.isTTY && this.#test) {
53
+ const title = this.#formatName(this.#suite, this.#test, name);
54
+ this.#updateTitle(title);
55
+ }
56
+ }
57
+
58
+ #updateTitle(title: string) {
59
+ if (title === this.#lastTitle) {
60
+ return;
61
+ }
62
+ this.#lastTitle = title;
63
+ this.progress.update(this.#summarize(this.#stats), title);
64
+ }
65
+
66
+ failTest(name: string, detail: FailureDetail) {
67
+ this.#failures.push({
68
+ suite: this.#suite,
69
+ test: name,
70
+ step: this.#step,
71
+ detail,
72
+ });
73
+ }
74
+
75
+ abstract failRun(detail: FailureDetail): void;
76
+
77
+ endRun(stats?: Stats): void {
78
+ if (this.#failures.length) {
79
+ this.progress.failure(this.#summarize(stats));
80
+ this.#dumpFailures();
81
+ } else if (stats && !stats.complete) {
82
+ this.progress.failure("No tests found");
83
+ } else {
84
+ this.progress.success(this.#summarize(stats));
85
+ }
86
+ }
87
+
88
+ #summarize(stats?: Stats) {
89
+ let statStr;
90
+ if (stats) {
91
+ const complete = ansi.dim(`${stats.complete}/${stats.total}`);
92
+ const failures = stats.failures ? ansi.bright.red(` ${stats.failures.toString()} failed`) : "";
93
+ statStr = ` ${complete}${failures}`;
94
+ } else {
95
+ statStr = "";
96
+ }
97
+
98
+ return `${ansi.bold(this.#run)}${statStr}`;
99
+ }
100
+
101
+ #dumpFailures() {
102
+ for (let i = 0; i < this.#failures.length; i++) {
103
+ if (i !== 0) {
104
+ std.out("\n");
105
+ }
106
+
107
+ const failure = this.#failures[i];
108
+ const index = `Failure ${ansi.bold((i + 1).toString())} of ${this.#failures.length}`;
109
+ const title = `${index} ${this.#formatName(failure.suite, failure.test, failure.step)}`;
110
+
111
+ FailureReporter.report(std.out, failure.detail, title);
112
+ }
113
+ }
114
+
115
+ #formatName(suite: string[], test: string, step?: string) {
116
+ const breadcrumb = [...suite, test];
117
+ if (step) {
118
+ breadcrumb.push(step);
119
+ }
120
+ breadcrumb[breadcrumb.length - 1] = ansi.bold(breadcrumb[breadcrumb.length - 1]).toString();
121
+ return breadcrumb.join(" ➡ ");
122
+ }
123
+ }
package/src/reporter.ts CHANGED
@@ -4,8 +4,6 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
- import { Progress } from "#tools";
8
- import colors from "ansi-colors";
9
7
  import { FailureDetail } from "./failure-detail.js";
10
8
 
11
9
  export type Stats = {
@@ -30,148 +28,3 @@ export interface Failure {
30
28
  step?: string;
31
29
  detail: FailureDetail;
32
30
  }
33
-
34
- export abstract class ProgressReporter implements Reporter {
35
- #run = "";
36
- #suite = Array<string>();
37
- #test?: string;
38
- #step?: string;
39
- #stats?: Stats;
40
- #failures = Array<Failure>();
41
- #lastTitle?: string;
42
-
43
- constructor(private progress: Progress) {}
44
-
45
- beginRun(name: string, stats: Stats | undefined, supportsSuites = true): void {
46
- this.#run = name;
47
- this.#suite = [];
48
- this.#failures = [];
49
- if (!supportsSuites) {
50
- this.progress.update(this.#summarize(stats));
51
- }
52
- }
53
-
54
- beginSuite(name: string[]): void {
55
- this.#suite = name;
56
- }
57
-
58
- beginTest(name: string, stats?: Stats): void {
59
- this.#test = name;
60
- this.#stats = stats;
61
- this.#step = undefined;
62
-
63
- // If not a TTY, only update once per suite to keep the line count down for e.g. GH action logs
64
- const title = process.stdout.isTTY ? this.#formatName(this.#suite, name) : this.#suite[0];
65
- this.#updateTitle(title);
66
- }
67
-
68
- beginStep(name: string): void {
69
- this.#step = name;
70
-
71
- if (process.stdout.isTTY && this.#test) {
72
- const title = this.#formatName(this.#suite, this.#test, name);
73
- this.#updateTitle(title);
74
- }
75
- }
76
-
77
- #updateTitle(title: string) {
78
- if (title === this.#lastTitle) {
79
- return;
80
- }
81
- this.#lastTitle = title;
82
- this.progress.update(this.#summarize(this.#stats), title);
83
- }
84
-
85
- failTest(name: string, detail: FailureDetail) {
86
- this.#failures.push({
87
- suite: this.#suite,
88
- test: name,
89
- step: this.#step,
90
- detail,
91
- });
92
- }
93
-
94
- abstract failRun(detail: FailureDetail): void;
95
-
96
- endRun(stats?: Stats): void {
97
- if (this.#failures.length) {
98
- this.progress.failure(this.#summarize(stats));
99
- this.#dumpFailures();
100
- } else if (stats && !stats.complete) {
101
- this.progress.failure("No tests found");
102
- } else {
103
- this.progress.success(this.#summarize(stats));
104
- }
105
- }
106
-
107
- #summarize(stats?: Stats) {
108
- let statStr;
109
- if (stats) {
110
- const complete = colors.dim(`${stats.complete}/${stats.total}`);
111
- const failures = stats.failures ? colors.redBright(` ${stats.failures.toString()} failed`) : "";
112
- statStr = ` ${complete}${failures}`;
113
- } else {
114
- statStr = "";
115
- }
116
-
117
- return `${colors.bold(this.#run)}${statStr}`;
118
- }
119
-
120
- #dumpFailures() {
121
- for (let i = 0; i < this.#failures.length; i++) {
122
- const failure = this.#failures[i];
123
- const index = `Failure ${colors.bold((i + 1).toString())} of ${this.#failures.length}`;
124
- process.stdout.write(`\n${index} ${this.#formatName(failure.suite, failure.test, failure.step)}\n\n`);
125
-
126
- FailureDetail.dump(failure.detail, " ");
127
- }
128
- }
129
-
130
- #formatName(suite: string[], test: string, step?: string) {
131
- const breadcrumb = [...suite, test];
132
- if (step) {
133
- breadcrumb.push(step);
134
- }
135
- breadcrumb[breadcrumb.length - 1] = colors.bold(breadcrumb[breadcrumb.length - 1]);
136
- return breadcrumb.join(" ➡ ");
137
- }
138
- }
139
-
140
- const actualConsole = console;
141
- const actualLog = actualConsole.log;
142
-
143
- function proxy(...args: any[]) {
144
- actualLog.call(actualConsole, `${ConsoleProxyReporter.FLAG}${JSON.stringify(args)}`);
145
- }
146
-
147
- export class ConsoleProxyReporter implements Reporter {
148
- static FLAG = "<<REPORT>> ";
149
-
150
- beginRun(name: string, stats?: Stats) {
151
- proxy("beginRun", name, stats);
152
- }
153
-
154
- beginSuite(name: string[], stats?: Stats) {
155
- proxy("beginSuite", name, stats);
156
- }
157
-
158
- beginTest(name: string, stats?: Stats) {
159
- proxy("beginTest", name, stats);
160
- }
161
-
162
- beginStep(name: string) {
163
- proxy("beginStep", name);
164
- }
165
-
166
- endRun(stats?: Stats) {
167
- proxy("endRun", stats);
168
- }
169
-
170
- failTest(name: string, detail: FailureDetail) {
171
- proxy("failTest", name, detail);
172
- }
173
-
174
- failRun(detail: FailureDetail) {
175
- proxy("failRun", detail);
176
- }
177
- }
package/src/runner.ts CHANGED
@@ -4,15 +4,16 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
- import { Package, Progress } from "#tools";
8
- import colors from "ansi-colors";
7
+ import { ansi, Package, Progress, std } from "#tools";
9
8
  import debug from "debug";
10
9
  import { relative } from "path";
11
10
  import { chip } from "./chip/chip.js";
12
11
  import { FailureDetail } from "./failure-detail.js";
12
+ import { FailureReporter } from "./failure-reporter.js";
13
+ import { NodejsReporter } from "./nodejs-reporter.js";
13
14
  import { testNodejs } from "./nodejs.js";
14
15
  import { TestOptions } from "./options.js";
15
- import { ProgressReporter, Reporter } from "./reporter.js";
16
+ import { Reporter } from "./reporter.js";
16
17
  import { listSupportFiles } from "./util/files.js";
17
18
  import { testWeb } from "./web.js";
18
19
 
@@ -27,13 +28,15 @@ export class TestRunner {
27
28
  ) {
28
29
  chip.runner = this;
29
30
 
30
- this.reporter = new (class extends ProgressReporter {
31
+ this.reporter = new (class extends NodejsReporter {
31
32
  constructor() {
32
33
  super(progress);
33
34
  }
35
+
34
36
  override failRun(detail: FailureDetail) {
35
- process.stdout.write("\n");
36
- FailureDetail.dump(detail);
37
+ std.err.write("\n");
38
+ FailureReporter.report(std.err, detail, "Test suite crash");
39
+ std.err.write("\n");
37
40
  process.exit(1);
38
41
  }
39
42
  })();
@@ -87,6 +90,6 @@ export class TestRunner {
87
90
  }
88
91
 
89
92
  function fatal(message: string) {
90
- process.stderr.write(colors.redBright(`\n${message}\n\n`));
93
+ std.err.write(ansi.bright.red(`\n${message}\n\n`));
91
94
  process.exit(1);
92
95
  }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2024 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ export function TextDiff(actual: string, expected: string) {
8
+ if (TextDiff.generator) {
9
+ return TextDiff.generator(actual, expected);
10
+ }
11
+ return "(no diff generator installed)";
12
+ }
13
+
14
+ export namespace TextDiff {
15
+ export let generator: undefined | ((actual: string, expected: string) => string);
16
+ }
package/src/tsconfig.json CHANGED
@@ -8,5 +8,9 @@
8
8
  "include": [
9
9
  "**/*.ts"
10
10
  ],
11
- "references": []
11
+ "references": [
12
+ {
13
+ "path": "../../tools/src"
14
+ }
15
+ ]
12
16
  }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2024 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { FailureDetail } from "./failure-detail.js";
8
+ import { Reporter, Stats } from "./reporter.js";
9
+
10
+ // Save these so we can avoid any trapping logic and write directly to the console
11
+ const actualConsole = console;
12
+ const actualLog = actualConsole.log;
13
+ function proxy(...args: any[]) {
14
+ actualLog.call(actualConsole, `${WebReporter.FLAG}${JSON.stringify(args)}`);
15
+ }
16
+
17
+ /**
18
+ * Test UI for web browsers. Encodes each reporting method to the console. This is a simple way to convey messages
19
+ * from the browser to the test harness.
20
+ */
21
+ export class WebReporter implements Reporter {
22
+ static FLAG = "<<REPORT>> ";
23
+
24
+ beginRun(name: string, stats?: Stats) {
25
+ proxy("beginRun", name, stats);
26
+ }
27
+
28
+ beginSuite(name: string[], stats?: Stats) {
29
+ proxy("beginSuite", name, stats);
30
+ }
31
+
32
+ beginTest(name: string, stats?: Stats) {
33
+ proxy("beginTest", name, stats);
34
+ }
35
+
36
+ beginStep(name: string) {
37
+ proxy("beginStep", name);
38
+ }
39
+
40
+ endRun(stats?: Stats) {
41
+ proxy("endRun", stats);
42
+ }
43
+
44
+ failTest(name: string, detail: FailureDetail) {
45
+ proxy("failTest", name, detail);
46
+ }
47
+
48
+ failRun(detail: FailureDetail) {
49
+ proxy("failRun", detail);
50
+ }
51
+ }
package/src/web.ts CHANGED
@@ -13,8 +13,9 @@ import { AddressInfo } from "net";
13
13
  import { relative } from "path";
14
14
  import { Browser, chromium, ConsoleMessage, Page } from "playwright";
15
15
  import { TestOptions } from "./options.js";
16
- import { ConsoleProxyReporter, Reporter } from "./reporter.js";
16
+ import { Reporter } from "./reporter.js";
17
17
  import type { TestRunner } from "./runner.js";
18
+ import { WebReporter } from "./web-reporter.js";
18
19
 
19
20
  export async function testWeb(runner: TestRunner, manual: boolean) {
20
21
  const files = await runner.loadFiles("esm");
@@ -105,13 +106,13 @@ function consoleHandler(reporter: Reporter) {
105
106
  const text = message.text();
106
107
 
107
108
  // If it's not an encoded reporter update, write to normal console
108
- if (type !== "log" || !text.startsWith(ConsoleProxyReporter.FLAG)) {
109
+ if (type !== "log" || !text.startsWith(WebReporter.FLAG)) {
109
110
  console[type](text);
110
111
  return;
111
112
  }
112
113
 
113
114
  // Invoke reporter
114
- const args: string[] = JSON.parse(text.slice(ConsoleProxyReporter.FLAG.length));
115
+ const args: string[] = JSON.parse(text.slice(WebReporter.FLAG.length));
115
116
  const method = (reporter as any)[args[0]];
116
117
  if (typeof method !== "function") {
117
118
  throw new Error(`Invalid encoded reporter update method ${args[0]}`);