@matter/testing 0.13.0-alpha.0-20250318-c1aa38b08 → 0.13.0-alpha.0-20250322-f085fa576

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.
@@ -4,10 +4,26 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import { Boot } from "./boot.js";
7
+ const registry = {
8
+ timers: /* @__PURE__ */ new Set(),
9
+ register(_timer) {
10
+ },
11
+ unregister(_timer) {
12
+ }
13
+ };
7
14
  class MockTimer {
8
- constructor(mockTime, durationMs, callback) {
9
- this.mockTime = mockTime;
10
- this.durationMs = durationMs;
15
+ name = "Test";
16
+ systemId = 0;
17
+ intervalMs = 0;
18
+ isPeriodic = false;
19
+ #mockTime;
20
+ #durationMs;
21
+ isRunning = false;
22
+ callback;
23
+ constructor(mockTime, name, durationMs, callback) {
24
+ this.name = name;
25
+ this.#mockTime = mockTime;
26
+ this.#durationMs = durationMs;
11
27
  if (this instanceof MockInterval) {
12
28
  this.callback = callback;
13
29
  } else {
@@ -17,30 +33,26 @@ class MockTimer {
17
33
  };
18
34
  }
19
35
  }
20
- name = "Test";
21
- systemId = 0;
22
- intervalMs = 0;
23
- isPeriodic = false;
24
- isRunning = false;
25
- callback;
26
36
  start() {
27
- this.mockTime.callbackAtTime(this.mockTime.nowMs() + this.durationMs, this.callback);
37
+ registry.register(this);
38
+ this.#mockTime.callbackAtTime(this.#mockTime.nowMs() + this.#durationMs, this.callback);
28
39
  this.isRunning = true;
29
40
  return this;
30
41
  }
31
42
  stop() {
32
- this.mockTime.removeCallback(this.callback);
43
+ registry.unregister(this);
44
+ this.#mockTime.removeCallback(this.callback);
33
45
  this.isRunning = false;
34
46
  return this;
35
47
  }
36
48
  }
37
49
  class MockInterval extends MockTimer {
38
- constructor(mockTime, durationMs, callback) {
50
+ constructor(mockTime, name, durationMs, callback) {
39
51
  const intervalCallback = async () => {
40
52
  mockTime.callbackAtTime(mockTime.nowMs() + durationMs, intervalCallback);
41
53
  await callback();
42
54
  };
43
- super(mockTime, durationMs, intervalCallback);
55
+ super(mockTime, name, durationMs, intervalCallback);
44
56
  }
45
57
  }
46
58
  function isAsync(fn) {
@@ -73,18 +85,18 @@ const MockTime = {
73
85
  nowMs() {
74
86
  return nowMs;
75
87
  },
76
- getTimer(_name, durationMs, callback) {
77
- return new MockTimer(this, durationMs, callback);
88
+ getTimer(name, durationMs, callback) {
89
+ return new MockTimer(this, name, durationMs, callback);
78
90
  },
79
- getPeriodicTimer(_name, intervalMs, callback) {
80
- return new MockInterval(this, intervalMs, callback);
91
+ getPeriodicTimer(name, intervalMs, callback) {
92
+ return new MockInterval(this, name, intervalMs, callback);
81
93
  },
82
94
  /**
83
95
  * Resolve a promise with time dependency.
84
96
  *
85
97
  * Moves time forward until the promise resolves.
86
98
  */
87
- async resolve(promise) {
99
+ async resolve(promise, { stepMs, macrotasks } = {}) {
88
100
  let resolved = false;
89
101
  let result;
90
102
  let error;
@@ -100,7 +112,11 @@ const MockTime = {
100
112
  );
101
113
  let timeAdvanced = 0;
102
114
  while (!resolved) {
103
- await new Promise((resolve) => setTimeout(() => resolve(), 0));
115
+ if (macrotasks) {
116
+ await new Promise((resolve) => setTimeout(() => resolve(), 0));
117
+ } else {
118
+ await MockTime.yield();
119
+ }
104
120
  if (resolved) {
105
121
  break;
106
122
  }
@@ -109,8 +125,12 @@ const MockTime = {
109
125
  "Mock timeout: Promise did not resolve within one (virtual) hour, probably not going to happen"
110
126
  );
111
127
  }
112
- await this.advance(1e3);
113
- timeAdvanced += 1e3;
128
+ if (stepMs) {
129
+ await this.advance(stepMs);
130
+ } else {
131
+ await this.advance(1e3);
132
+ timeAdvanced += 1e3;
133
+ }
114
134
  if (resolved) {
115
135
  break;
116
136
  }
@@ -126,8 +146,7 @@ const MockTime = {
126
146
  */
127
147
  async advance(ms) {
128
148
  const newTimeMs = nowMs + ms;
129
- while (true) {
130
- if (callbacks.length === 0) break;
149
+ while (callbacks.length) {
131
150
  const { atMs, callback } = callbacks[0];
132
151
  if (atMs > newTimeMs) break;
133
152
  callbacks.shift();
@@ -137,20 +156,17 @@ const MockTime = {
137
156
  nowMs = newTimeMs;
138
157
  },
139
158
  /**
140
- * Yield to scheduled microtasks. This means that all code paths waiting
141
- * on resolved promises (including await) will proceed before this method
142
- * returns.
159
+ * Yield to scheduled microtasks. This means that all code paths waiting on resolved promises (including await)
160
+ * will proceed before this method returns.
143
161
  */
144
162
  async yield() {
145
163
  await Promise.resolve();
146
164
  },
147
165
  /**
148
- * Due to its implementation, an older version of yield() would actually
149
- * yield to microtasks three times. Our tests then depended on this
150
- * functionality -- one yield could trigger up to three nested awaits.
166
+ * Due to its implementation, an older version of yield() would actually yield to microtasks three times. Our tests
167
+ * then depended on this functionality -- one yield could trigger up to three nested awaits.
151
168
  *
152
- * To make this clear, the version of yield() that emulates old behavior
153
- * is called "yield3".
169
+ * To make this clear, the version of yield() that emulates old behavior is called "yield3".
154
170
  */
155
171
  async yield3() {
156
172
  await Promise.resolve();
@@ -158,14 +174,12 @@ const MockTime = {
158
174
  await Promise.resolve();
159
175
  },
160
176
  /**
161
- * Hook a method and invoke a callback just before the method completes.
162
- * Unhooks after completion.
177
+ * Hook a method and invoke a callback just before the method completes. Unhooks after completion.
163
178
  *
164
- * Handles both synchronous and asynchronous methods. The interceptor
165
- * should match the async-ness of the intercepted method.
179
+ * Handles both synchronous and asynchronous methods. The interceptor should match the async-ness of the
180
+ * intercepted method.
166
181
  *
167
- * The interceptor can optionally access and/or replace the resolve/reject
168
- * value.
182
+ * The interceptor can optionally access and/or replace the resolve/reject value.
169
183
  */
170
184
  interceptOnce(obj, method, interceptor) {
171
185
  const original = obj[method];
@@ -207,6 +221,12 @@ const MockTime = {
207
221
  };
208
222
  }
209
223
  },
224
+ /**
225
+ * Count the number of registered timers with a specific name.
226
+ */
227
+ timerCountFor(name) {
228
+ return [...registry.timers].filter((timer) => timer.name === name).length;
229
+ },
210
230
  callbackAtTime(atMs, callback) {
211
231
  callbacks.push({ atMs, callback });
212
232
  callbacks.sort(({ atMs: atMsA }, { atMs: atMsB }) => atMsA - atMsB);
@@ -219,6 +239,9 @@ const MockTime = {
219
239
  };
220
240
  let reinstallTime;
221
241
  function timeSetup(Time) {
242
+ registry.register = Time.register;
243
+ registry.unregister = Time.unregister;
244
+ registry.timers = Time.timers;
222
245
  Time.startup.systemMs = Time.startup.processMs = 0;
223
246
  real = Time.get();
224
247
  MockTime.sleep = real.sleep;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/mocks/time.ts"],
4
- "mappings": "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",
4
+ "mappings": "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",
5
5
  "names": []
6
6
  }
@@ -83,7 +83,7 @@ class NodejsReporter {
83
83
  std.out("\n");
84
84
  }
85
85
  const failure = this.#failures[i];
86
- const index = `Failure ${ansi.bold((i + 1).toString())} of ${this.#failures.length}`;
86
+ const index = `\u26A0 Failure ${ansi.bold((i + 1).toString())} of ${this.#failures.length}`;
87
87
  const title = `${index} ${this.#formatName(failure.suite, failure.test, failure.step)}`;
88
88
  FailureReporter.report(std.out, failure.detail, title);
89
89
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/nodejs-reporter.ts"],
4
- "mappings": "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",
4
+ "mappings": "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",
5
5
  "names": []
6
6
  }
@@ -7,6 +7,7 @@ import { Package, Progress } from "#tools";
7
7
  import { TestOptions } from "./options.js";
8
8
  import { Reporter } from "./reporter.js";
9
9
  export declare class TestRunner {
10
+ #private;
10
11
  readonly pkg: Package;
11
12
  readonly progress: Progress;
12
13
  readonly options: TestOptions;
@@ -16,6 +17,5 @@ export declare class TestRunner {
16
17
  runNode(format?: "esm" | "cjs"): Promise<void>;
17
18
  runWeb(manual?: boolean): Promise<void>;
18
19
  loadFiles(format: "esm" | "cjs"): Promise<string[]>;
19
- private run;
20
20
  }
21
21
  //# sourceMappingURL=runner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/runner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAQ,OAAO,EAAE,QAAQ,EAAO,MAAM,QAAQ,CAAC;AAQtD,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAIzC,qBAAa,UAAU;IAKf,QAAQ,CAAC,GAAG,EAAE,OAAO;IACrB,QAAQ,CAAC,QAAQ,EAAE,QAAQ;IAC3B,QAAQ,CAAC,OAAO,EAAE,WAAW;IANjC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,OAAO,CAAC,IAAI,CAAmB;gBAGlB,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,WAAW;IA8B3B,OAAO,CAAC,MAAM,GAAE,KAAK,GAAG,KAAa;IAIrC,MAAM,CAAC,MAAM,UAAQ;IAIrB,SAAS,CAAC,MAAM,EAAE,KAAK,GAAG,KAAK;YAmBvB,GAAG;CAMpB"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/runner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAQ,OAAO,EAAE,QAAQ,EAAO,MAAM,QAAQ,CAAC;AAStD,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAIzC,qBAAa,UAAU;;IAKf,QAAQ,CAAC,GAAG,EAAE,OAAO;IACrB,QAAQ,CAAC,QAAQ,EAAE,QAAQ;IAC3B,QAAQ,CAAC,OAAO,EAAE,WAAW;IANjC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,OAAO,CAAC,IAAI,CAAmB;gBAGlB,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,WAAW;IA8B3B,OAAO,CAAC,MAAM,GAAE,KAAK,GAAG,KAAa;IAIrC,MAAM,CAAC,MAAM,UAAQ;IAIrB,SAAS,CAAC,MAAM,EAAE,KAAK,GAAG,KAAK;CA0GxC"}
@@ -5,7 +5,8 @@
5
5
  */
6
6
  import { ansi, Progress, std } from "#tools";
7
7
  import debug from "debug";
8
- import { relative } from "node:path";
8
+ import { readFile } from "node:fs/promises";
9
+ import { dirname, relative, resolve } from "node:path";
9
10
  import { chip } from "./chip/chip.js";
10
11
  import { FailureReporter } from "./failure-reporter.js";
11
12
  import { NodejsReporter } from "./nodejs-reporter.js";
@@ -43,13 +44,13 @@ class TestRunner {
43
44
  reporter;
44
45
  spec = Array();
45
46
  async runNode(format = "esm") {
46
- await this.run(this.progress, () => testNodejs(this, format));
47
+ await this.#run(this.progress, () => testNodejs(this, format));
47
48
  }
48
49
  async runWeb(manual = false) {
49
- await this.run(this.progress, () => testWeb(this, manual));
50
+ await this.#run(this.progress, () => testWeb(this, manual));
50
51
  }
51
52
  async loadFiles(format) {
52
- const tests = [];
53
+ const tests = Array();
53
54
  for (let spec of this.spec) {
54
55
  spec = spec.replace(/\.ts$/, ".js");
55
56
  spec = relative(this.pkg.path, spec);
@@ -58,17 +59,76 @@ class TestRunner {
58
59
  }
59
60
  tests.push(...await this.pkg.glob(spec));
60
61
  }
62
+ for (let i = 0; i < tests.length; i++) {
63
+ if (tests[i].indexOf("/src/") === -1) {
64
+ continue;
65
+ }
66
+ tests[i] = await this.#mapSourceToTest(tests[i]);
67
+ }
61
68
  if (!tests.length) {
62
69
  fatal(`No files match ${this.spec.join(", ")}`);
63
70
  }
64
71
  return [...listSupportFiles(format), ...tests];
65
72
  }
66
- async run(progress, runner) {
73
+ async #run(progress, runner) {
67
74
  await runner();
68
75
  if (progress.status !== Progress.Status.Success) {
69
76
  fatal(`Test ${progress.status.toLowerCase()}, aborting`);
70
77
  }
71
78
  }
79
+ async #mapSourceToTest(filename) {
80
+ try {
81
+ const src = await readFile(filename, "utf-8");
82
+ const [, args] = src.match(/\/\/ matter-test (.*)/) ?? [];
83
+ if (args) {
84
+ return this.#parseMarkerArgs(args, filename);
85
+ }
86
+ } catch (e) {
87
+ }
88
+ return filename.replace("/src/", "/test/");
89
+ }
90
+ #parseMarkerArgs(args, filename) {
91
+ const parts = args.match(/[a-z]+=(?:"(?:[^"\\]|\\.)+"|[^"]\S+)/g);
92
+ if (!parts) {
93
+ throw new Error("No matter-test parameters detected");
94
+ }
95
+ let file;
96
+ let module;
97
+ for (const part of parts) {
98
+ const equalPos = part.indexOf("=");
99
+ const name = part.substring(0, equalPos);
100
+ let value = part.substring(equalPos + 1);
101
+ if (value[0] === '"') {
102
+ value = value.substring(1, value.length - 2).replace(/\\"/g, '"').replace(/\\\\/g, '"');
103
+ }
104
+ switch (name) {
105
+ case "file":
106
+ file = value;
107
+ break;
108
+ case "module":
109
+ module = value;
110
+ break;
111
+ default:
112
+ throw new Error(`Unrecognized matter-test parameter "${name}"`);
113
+ }
114
+ }
115
+ if (file === void 0) {
116
+ throw new Error(`matter-test parameter "file" is required`);
117
+ }
118
+ if (file.startsWith("./") || file.startsWith("../")) {
119
+ file = resolve(dirname(filename), file);
120
+ }
121
+ let testPkg;
122
+ if (module === void 0) {
123
+ testPkg = this.pkg;
124
+ } else {
125
+ testPkg = this.pkg.findPackage(module);
126
+ if (testPkg === void 0) {
127
+ throw new Error(`Unknown matter-test module "${module}"`);
128
+ }
129
+ }
130
+ return testPkg.resolve("test", file);
131
+ }
72
132
  }
73
133
  function fatal(message) {
74
134
  std.err.write(ansi.bright.red(`
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/runner.ts"],
4
- "mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,SAAS,MAAe,UAAU,WAAW;AAC7C,OAAO,WAAW;AAClB,SAAS,gBAAgB;AACzB,SAAS,YAAY;AAErB,SAAS,uBAAuB;AAChC,SAAS,sBAAsB;AAC/B,SAAS,kBAAkB;AAG3B,SAAS,wBAAwB;AACjC,SAAS,eAAe;AAEjB,MAAM,WAAW;AAAA,EAIpB,YACa,KACA,UACA,SACX;AAHW;AACA;AACA;AAET,SAAK,SAAS;AAEd,SAAK,WAAW,IAAK,cAAc,eAAe;AAAA,MAC9C,cAAc;AACV,cAAM,QAAQ;AAAA,MAClB;AAAA,MAES,QAAQ,QAAuB;AACpC,YAAI,IAAI,MAAM,IAAI;AAClB,wBAAgB,OAAO,IAAI,KAAK,QAAQ,kBAAkB;AAC1D,YAAI,IAAI,MAAM,IAAI;AAClB,gBAAQ,KAAK,CAAC;AAAA,MAClB;AAAA,IACJ,EAAG;AAEH,QAAI,QAAQ,SAAS,QAAW;AAC5B,WAAK,OAAO,CAAC,kBAAkB;AAAA,IACnC,WAAW,MAAM,QAAQ,QAAQ,IAAI,GAAG;AACpC,WAAK,OAAO,QAAQ;AAAA,IACxB,OAAO;AACH,WAAK,OAAO,CAAC,QAAQ,IAAI;AAAA,IAC7B;AAEA,QAAI,QAAQ,OAAO;AACf,YAAM,OAAO,SAAS;AAAA,IAC1B;AAAA,EACJ;AAAA,EAlCS;AAAA,EACD,OAAO,MAAc;AAAA,EAmC7B,MAAM,QAAQ,SAAwB,OAAO;AACzC,UAAM,KAAK,IAAI,KAAK,UAAU,MAAM,WAAW,MAAM,MAAM,CAAC;AAAA,EAChE;AAAA,EAEA,MAAM,OAAO,SAAS,OAAO;AACzB,UAAM,KAAK,IAAI,KAAK,UAAU,MAAM,QAAQ,MAAM,MAAM,CAAC;AAAA,EAC7D;AAAA,EAEA,MAAM,UAAU,QAAuB;AACnC,UAAM,QAAQ,CAAC;AACf,aAAS,QAAQ,KAAK,MAAM;AACxB,aAAO,KAAK,QAAQ,SAAS,KAAK;AAClC,aAAO,SAAS,KAAK,IAAI,MAAM,IAAI;AACnC,UAAI,CAAC,KAAK,WAAW,GAAG,KAAK,CAAC,KAAK,WAAW,QAAQ,KAAK,CAAC,KAAK,WAAW,OAAO,GAAG;AAClF,eAAO,SAAS,MAAM,IAAI,IAAI;AAAA,MAClC;AAEA,YAAM,KAAK,GAAI,MAAM,KAAK,IAAI,KAAK,IAAI,CAAE;AAAA,IAC7C;AAEA,QAAI,CAAC,MAAM,QAAQ;AACf,YAAM,kBAAkB,KAAK,KAAK,KAAK,IAAI,CAAC,EAAE;AAAA,IAClD;AAEA,WAAO,CAAC,GAAG,iBAAiB,MAAM,GAAG,GAAG,KAAK;AAAA,EACjD;AAAA,EAEA,MAAc,IAAI,UAAoB,QAA6B;AAC/D,UAAM,OAAO;AACb,QAAI,SAAS,WAAW,SAAS,OAAO,SAAS;AAC7C,YAAM,QAAQ,SAAS,OAAO,YAAY,CAAC,YAAY;AAAA,IAC3D;AAAA,EACJ;AACJ;AAEA,SAAS,MAAM,SAAiB;AAC5B,MAAI,IAAI,MAAM,KAAK,OAAO,IAAI;AAAA,EAAK,OAAO;AAAA;AAAA,CAAM,CAAC;AACjD,UAAQ,KAAK,CAAC;AAClB;",
4
+ "mappings": "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",
5
5
  "names": []
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matter/testing",
3
- "version": "0.13.0-alpha.0-20250318-c1aa38b08",
3
+ "version": "0.13.0-alpha.0-20250322-f085fa576",
4
4
  "description": "Test harness for running JavaScript and Matter certification tests",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -45,7 +45,7 @@
45
45
  "#tools/ansi-text": "@matter/tools/ansi-text"
46
46
  },
47
47
  "dependencies": {
48
- "@matter/tools": "0.13.0-alpha.0-20250318-c1aa38b08",
48
+ "@matter/tools": "0.13.0-alpha.0-20250322-f085fa576",
49
49
  "@types/express": "^5.0.0",
50
50
  "ansi-colors": "^4.1.3",
51
51
  "chai": "^4.5.0",
package/src/mocks/time.ts CHANGED
@@ -11,6 +11,12 @@ type TimerCallback = () => any;
11
11
  type MockTimeLike = typeof MockTime;
12
12
  export interface MockTime extends MockTimeLike {}
13
13
 
14
+ const registry = {
15
+ timers: new Set<MockTimer>(),
16
+ register(_timer: MockTimer) {},
17
+ unregister(_timer: MockTimer) {},
18
+ };
19
+
14
20
  // Must match matter.js Timer interface
15
21
  class MockTimer {
16
22
  name = "Test";
@@ -18,14 +24,18 @@ class MockTimer {
18
24
  intervalMs = 0;
19
25
  isPeriodic = false;
20
26
 
27
+ #mockTime: MockTime;
28
+ #durationMs: number;
29
+
21
30
  isRunning = false;
22
31
  private readonly callback: TimerCallback;
23
32
 
24
- constructor(
25
- private readonly mockTime: MockTime,
26
- private readonly durationMs: number,
27
- callback: TimerCallback,
28
- ) {
33
+ constructor(mockTime: MockTime, name: string, durationMs: number, callback: TimerCallback) {
34
+ this.name = name;
35
+
36
+ this.#mockTime = mockTime;
37
+ this.#durationMs = durationMs;
38
+
29
39
  if (this instanceof MockInterval) {
30
40
  this.callback = callback;
31
41
  } else {
@@ -37,25 +47,27 @@ class MockTimer {
37
47
  }
38
48
 
39
49
  start() {
40
- this.mockTime.callbackAtTime(this.mockTime.nowMs() + this.durationMs, this.callback);
50
+ registry.register(this);
51
+ this.#mockTime.callbackAtTime(this.#mockTime.nowMs() + this.#durationMs, this.callback);
41
52
  this.isRunning = true;
42
53
  return this;
43
54
  }
44
55
 
45
56
  stop() {
46
- this.mockTime.removeCallback(this.callback);
57
+ registry.unregister(this);
58
+ this.#mockTime.removeCallback(this.callback);
47
59
  this.isRunning = false;
48
60
  return this;
49
61
  }
50
62
  }
51
63
 
52
64
  class MockInterval extends MockTimer {
53
- constructor(mockTime: MockTime, durationMs: number, callback: TimerCallback) {
65
+ constructor(mockTime: MockTime, name: string, durationMs: number, callback: TimerCallback) {
54
66
  const intervalCallback = async () => {
55
67
  mockTime.callbackAtTime(mockTime.nowMs() + durationMs, intervalCallback);
56
68
  await callback();
57
69
  };
58
- super(mockTime, durationMs, intervalCallback);
70
+ super(mockTime, name, durationMs, intervalCallback);
59
71
  }
60
72
  }
61
73
 
@@ -105,12 +117,12 @@ export const MockTime = {
105
117
  return nowMs;
106
118
  },
107
119
 
108
- getTimer(_name: string, durationMs: number, callback: TimerCallback): MockTimer {
109
- return new MockTimer(this, durationMs, callback);
120
+ getTimer(name: string, durationMs: number, callback: TimerCallback): MockTimer {
121
+ return new MockTimer(this, name, durationMs, callback);
110
122
  },
111
123
 
112
- getPeriodicTimer(_name: string, intervalMs: number, callback: TimerCallback): MockTimer {
113
- return new MockInterval(this, intervalMs, callback);
124
+ getPeriodicTimer(name: string, intervalMs: number, callback: TimerCallback): MockTimer {
125
+ return new MockInterval(this, name, intervalMs, callback);
114
126
  },
115
127
 
116
128
  /**
@@ -118,7 +130,7 @@ export const MockTime = {
118
130
  *
119
131
  * Moves time forward until the promise resolves.
120
132
  */
121
- async resolve<T>(promise: PromiseLike<T>) {
133
+ async resolve<T>(promise: PromiseLike<T>, { stepMs, macrotasks }: { stepMs?: number; macrotasks?: boolean } = {}) {
122
134
  let resolved = false;
123
135
  let result: T | undefined;
124
136
  let error: any;
@@ -137,10 +149,14 @@ export const MockTime = {
137
149
  let timeAdvanced = 0;
138
150
  while (!resolved) {
139
151
  // Interestingly, a Time.yield() works in almost every case. However, on Node SubtleCrypto.deriveBits hangs
140
- // if you only yield via microtask. It seems to require yielding via macrotask. So we use setTimeout here.
141
- // Probably related to entropy collection but I think it's safe to classify as a Node bug. Tested on
142
- // version 20.11.0
143
- await new Promise<void>(resolve => setTimeout(() => resolve(), 0));
152
+ // if you only yield via microtask. It seems to require yielding via macrotask. So we optionally use
153
+ // setTimeout here. Probably related to entropy collection but I think it's safe to classify as a Node bug.
154
+ // Tested on version 20.11.0
155
+ if (macrotasks) {
156
+ await new Promise<void>(resolve => setTimeout(() => resolve(), 0));
157
+ } else {
158
+ await MockTime.yield();
159
+ }
144
160
 
145
161
  if (resolved) {
146
162
  break;
@@ -153,12 +169,16 @@ export const MockTime = {
153
169
  );
154
170
  }
155
171
 
156
- // Advance time exponentially, trying for granularity but also OK performance. Note that we are not only
157
- // advancing time but also yielding event loop. So it's possible if we run out of time it's just because
158
- // there were too few yields in one virtual hour. As designed currently it's 360 macrotasks and 360
159
- // microtasks (360 loops w/ 1 macro- and 1 micro-yield)
160
- await this.advance(1000);
161
- timeAdvanced += 1000;
172
+ if (stepMs) {
173
+ await this.advance(stepMs);
174
+ } else {
175
+ // Advance time exponentially, trying for granularity but also OK performance. Note that we are not only
176
+ // advancing time but also yielding event loop. So it's possible if we run out of time it's just because
177
+ // there were too few yields in one virtual hour. As designed currently it's 360 macrotasks and 360
178
+ // microtasks (360 loops w/ 1 macro- and 1 micro-yield)
179
+ await this.advance(1000);
180
+ timeAdvanced += 1000;
181
+ }
162
182
 
163
183
  if (resolved) {
164
184
  break;
@@ -180,8 +200,7 @@ export const MockTime = {
180
200
  async advance(ms: number) {
181
201
  const newTimeMs = nowMs + ms;
182
202
 
183
- while (true) {
184
- if (callbacks.length === 0) break;
203
+ while (callbacks.length) {
185
204
  const { atMs, callback } = callbacks[0];
186
205
  if (atMs > newTimeMs) break;
187
206
  callbacks.shift();
@@ -193,21 +212,18 @@ export const MockTime = {
193
212
  },
194
213
 
195
214
  /**
196
- * Yield to scheduled microtasks. This means that all code paths waiting
197
- * on resolved promises (including await) will proceed before this method
198
- * returns.
215
+ * Yield to scheduled microtasks. This means that all code paths waiting on resolved promises (including await)
216
+ * will proceed before this method returns.
199
217
  */
200
218
  async yield() {
201
219
  await Promise.resolve();
202
220
  },
203
221
 
204
222
  /**
205
- * Due to its implementation, an older version of yield() would actually
206
- * yield to microtasks three times. Our tests then depended on this
207
- * functionality -- one yield could trigger up to three nested awaits.
223
+ * Due to its implementation, an older version of yield() would actually yield to microtasks three times. Our tests
224
+ * then depended on this functionality -- one yield could trigger up to three nested awaits.
208
225
  *
209
- * To make this clear, the version of yield() that emulates old behavior
210
- * is called "yield3".
226
+ * To make this clear, the version of yield() that emulates old behavior is called "yield3".
211
227
  */
212
228
  async yield3() {
213
229
  await Promise.resolve();
@@ -216,14 +232,12 @@ export const MockTime = {
216
232
  },
217
233
 
218
234
  /**
219
- * Hook a method and invoke a callback just before the method completes.
220
- * Unhooks after completion.
235
+ * Hook a method and invoke a callback just before the method completes. Unhooks after completion.
221
236
  *
222
- * Handles both synchronous and asynchronous methods. The interceptor
223
- * should match the async-ness of the intercepted method.
237
+ * Handles both synchronous and asynchronous methods. The interceptor should match the async-ness of the
238
+ * intercepted method.
224
239
  *
225
- * The interceptor can optionally access and/or replace the resolve/reject
226
- * value.
240
+ * The interceptor can optionally access and/or replace the resolve/reject value.
227
241
  */
228
242
  interceptOnce<NameT extends string, ReturnT, ObjT extends { [N in NameT]: (...args: any) => ReturnT }>(
229
243
  obj: ObjT,
@@ -272,6 +286,13 @@ export const MockTime = {
272
286
  }
273
287
  },
274
288
 
289
+ /**
290
+ * Count the number of registered timers with a specific name.
291
+ */
292
+ timerCountFor(name: string) {
293
+ return [...registry.timers].filter(timer => timer.name === name).length;
294
+ },
295
+
275
296
  callbackAtTime(atMs: number, callback: TimerCallback) {
276
297
  callbacks.push({ atMs, callback });
277
298
  callbacks.sort(({ atMs: atMsA }, { atMs: atMsB }) => atMsA - atMsB);
@@ -286,7 +307,16 @@ export const MockTime = {
286
307
 
287
308
  let reinstallTime: undefined | (() => void);
288
309
 
289
- export function timeSetup(Time: { startup: { systemMs: number; processMs: number }; get(): unknown }) {
310
+ export function timeSetup(Time: {
311
+ startup: { systemMs: number; processMs: number };
312
+ get(): unknown;
313
+ register(timer: MockTimer): void;
314
+ unregister(timer: MockTimer): void;
315
+ timers: Set<MockTimer>;
316
+ }) {
317
+ registry.register = Time.register;
318
+ registry.unregister = Time.unregister;
319
+ registry.timers = Time.timers;
290
320
  Time.startup.systemMs = Time.startup.processMs = 0;
291
321
  real = Time.get();
292
322
  (MockTime as any).sleep = (real as any).sleep;
@@ -105,7 +105,7 @@ export abstract class NodejsReporter implements Reporter {
105
105
  }
106
106
 
107
107
  const failure = this.#failures[i];
108
- const index = `Failure ${ansi.bold((i + 1).toString())} of ${this.#failures.length}`;
108
+ const index = `⚠ Failure ${ansi.bold((i + 1).toString())} of ${this.#failures.length}`;
109
109
  const title = `${index} ${this.#formatName(failure.suite, failure.test, failure.step)}`;
110
110
 
111
111
  FailureReporter.report(std.out, failure.detail, title);