@matter/testing 0.15.1 → 0.15.2-alpha.0-20250703-2e16aba2b
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/chai.d.ts +9 -0
- package/dist/cjs/chai.d.ts.map +1 -0
- package/dist/cjs/chai.js +66 -0
- package/dist/cjs/chai.js.map +6 -0
- package/dist/cjs/failure-detail.d.ts +1 -0
- package/dist/cjs/failure-detail.d.ts.map +1 -1
- package/dist/cjs/failure-detail.js +12 -4
- package/dist/cjs/failure-detail.js.map +1 -1
- package/dist/cjs/failure-reporter.js +5 -1
- package/dist/cjs/failure-reporter.js.map +1 -1
- package/dist/cjs/global-declarations.d.ts +8 -1
- package/dist/cjs/global-declarations.d.ts.map +1 -1
- package/dist/cjs/global-definitions.js +0 -1
- package/dist/cjs/global-definitions.js.map +1 -1
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +2 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/mocha.d.ts.map +1 -1
- package/dist/cjs/mocha.js +1 -0
- package/dist/cjs/mocha.js.map +1 -1
- package/dist/cjs/mocks/time.d.ts +7 -0
- package/dist/cjs/mocks/time.d.ts.map +1 -1
- package/dist/cjs/mocks/time.js +13 -1
- package/dist/cjs/mocks/time.js.map +1 -1
- package/dist/cjs/runner.d.ts +5 -1
- package/dist/cjs/runner.d.ts.map +1 -1
- package/dist/cjs/runner.js +24 -6
- package/dist/cjs/runner.js.map +1 -1
- package/dist/cjs/util/files.d.ts.map +1 -1
- package/dist/cjs/util/files.js +1 -0
- package/dist/cjs/util/files.js.map +1 -1
- package/dist/cjs/web.d.ts +3 -0
- package/dist/cjs/web.d.ts.map +1 -1
- package/dist/cjs/web.js +7 -4
- package/dist/cjs/web.js.map +1 -1
- package/dist/esm/chai.d.ts +9 -0
- package/dist/esm/chai.d.ts.map +1 -0
- package/dist/esm/chai.js +40 -0
- package/dist/esm/chai.js.map +6 -0
- package/dist/esm/failure-detail.d.ts +1 -0
- package/dist/esm/failure-detail.d.ts.map +1 -1
- package/dist/esm/failure-detail.js +12 -4
- package/dist/esm/failure-detail.js.map +1 -1
- package/dist/esm/failure-reporter.js +5 -1
- package/dist/esm/failure-reporter.js.map +1 -1
- package/dist/esm/global-declarations.d.ts +8 -1
- package/dist/esm/global-declarations.d.ts.map +1 -1
- package/dist/esm/global-definitions.js +0 -1
- package/dist/esm/global-definitions.js.map +1 -1
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/mocha.d.ts.map +1 -1
- package/dist/esm/mocha.js +1 -0
- package/dist/esm/mocha.js.map +1 -1
- package/dist/esm/mocks/time.d.ts +7 -0
- package/dist/esm/mocks/time.d.ts.map +1 -1
- package/dist/esm/mocks/time.js +13 -1
- package/dist/esm/mocks/time.js.map +1 -1
- package/dist/esm/runner.d.ts +5 -1
- package/dist/esm/runner.d.ts.map +1 -1
- package/dist/esm/runner.js +24 -6
- package/dist/esm/runner.js.map +1 -1
- package/dist/esm/util/files.d.ts.map +1 -1
- package/dist/esm/util/files.js +1 -0
- package/dist/esm/util/files.js.map +1 -1
- package/dist/esm/web.d.ts +3 -0
- package/dist/esm/web.d.ts.map +1 -1
- package/dist/esm/web.js +7 -4
- package/dist/esm/web.js.map +1 -1
- package/package.json +2 -2
- package/src/chai.ts +50 -0
- package/src/failure-detail.ts +14 -4
- package/src/failure-reporter.ts +9 -1
- package/src/global-declarations.ts +17 -1
- package/src/global-definitions.ts +2 -1
- package/src/index.ts +2 -0
- package/src/mocha.ts +2 -0
- package/src/mocks/time.ts +15 -1
- package/src/runner.ts +31 -6
- package/src/util/files.ts +1 -0
- package/src/web.ts +20 -12
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/util/files.ts"],
|
|
4
|
-
"mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,SAAS,eAAe;AACxB,SAAS,kBAAkB;AAEpB,SAAS,iBAAiB,SAAS,OAAO;AAC7C,QAAM,QAAQ,MAAc;AAG5B,QAAM,UAAU,QAAQ,MAAM,YAAY,iBAAiB;AAC3D,QAAM,KAAK,QAAQ,QAAQ,gCAAgC,CAAC;AAC5D,QAAM,KAAK,QAAQ,QAAQ,yBAAyB,CAAC;AAGrD,QAAM,SAAS,IAAI,QAAQ,EAAE,QAAQ,SAAS,MAAM,sBAAsB;AAC1E,MAAI,WAAW,MAAM,GAAG;AACpB,UAAM,KAAK,MAAM;AAAA,EACrB;AAEA,SAAO;AACX;",
|
|
4
|
+
"mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,SAAS,eAAe;AACxB,SAAS,kBAAkB;AAEpB,SAAS,iBAAiB,SAAS,OAAO;AAC7C,QAAM,QAAQ,MAAc;AAG5B,QAAM,UAAU,QAAQ,MAAM,YAAY,iBAAiB;AAC3D,QAAM,KAAK,QAAQ,QAAQ,gCAAgC,CAAC;AAC5D,QAAM,KAAK,QAAQ,QAAQ,kBAAkB,CAAC;AAC9C,QAAM,KAAK,QAAQ,QAAQ,yBAAyB,CAAC;AAGrD,QAAM,SAAS,IAAI,QAAQ,EAAE,QAAQ,SAAS,MAAM,sBAAsB;AAC1E,MAAI,WAAW,MAAM,GAAG;AACpB,UAAM,KAAK,MAAM;AAAA,EACrB;AAEA,SAAO;AACX;",
|
|
5
5
|
"names": []
|
|
6
6
|
}
|
package/dist/esm/web.d.ts
CHANGED
|
@@ -5,4 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { TestRunner } from "./runner.js";
|
|
7
7
|
export declare function testWeb(runner: TestRunner, manual: boolean): Promise<void>;
|
|
8
|
+
export declare namespace testWeb {
|
|
9
|
+
var entrypointPreprocessor: ((lines: string[]) => void) | undefined;
|
|
10
|
+
}
|
|
8
11
|
//# sourceMappingURL=web.d.ts.map
|
package/dist/esm/web.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C,wBAAsB,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,iBA4ChE"}
|
|
1
|
+
{"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C,wBAAsB,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,iBA4ChE;yBA5CqB,OAAO;yCAmDsC,MAAM,EAAE,KAAK,IAAI"}
|
package/dist/esm/web.js
CHANGED
|
@@ -12,7 +12,7 @@ import { chromium } from "playwright";
|
|
|
12
12
|
import { WebReporter } from "./web-reporter.js";
|
|
13
13
|
async function testWeb(runner, manual) {
|
|
14
14
|
const files = await runner.loadFiles("esm");
|
|
15
|
-
const bundlePath = await bundle(files, runner
|
|
15
|
+
const bundlePath = await bundle(files, runner);
|
|
16
16
|
const server = await new Promise((resolve, reject) => {
|
|
17
17
|
try {
|
|
18
18
|
const server2 = express().use(express.static(Package.workspace.resolve("node_modules"))).use(express.static(Package.workspace.path)).get("/", (_, res) => {
|
|
@@ -44,6 +44,7 @@ async function testWeb(runner, manual) {
|
|
|
44
44
|
}
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
|
+
testWeb.entrypointPreprocessor = void 0;
|
|
47
48
|
async function testInBrowser(url, reporter, options) {
|
|
48
49
|
async function setup() {
|
|
49
50
|
const browser = await chromium.launch();
|
|
@@ -104,7 +105,7 @@ function buildIndex(bundlePath) {
|
|
|
104
105
|
</body>
|
|
105
106
|
</html>`;
|
|
106
107
|
}
|
|
107
|
-
async function bundle(files, pkg) {
|
|
108
|
+
async function bundle(files, { pkg, entrypointPreprocessor }) {
|
|
108
109
|
const entrypointPath = pkg.resolve("build/esm/test-entrypoint.js");
|
|
109
110
|
const bundlePath = pkg.resolve("build/cjs/test-bundle.js");
|
|
110
111
|
const entrypoint = files.map((path) => {
|
|
@@ -113,8 +114,9 @@ async function bundle(files, pkg) {
|
|
|
113
114
|
path = `./${path}`;
|
|
114
115
|
}
|
|
115
116
|
return `import ${JSON.stringify(path)}`;
|
|
116
|
-
})
|
|
117
|
-
|
|
117
|
+
});
|
|
118
|
+
entrypointPreprocessor?.(entrypoint);
|
|
119
|
+
await writeFile(pkg.resolve("build/esm/test-entrypoint.js"), entrypoint.join("\n"));
|
|
118
120
|
await build({
|
|
119
121
|
entryPoints: [entrypointPath],
|
|
120
122
|
bundle: true,
|
|
@@ -122,6 +124,7 @@ async function bundle(files, pkg) {
|
|
|
122
124
|
outfile: bundlePath,
|
|
123
125
|
external: ["wtfnode"],
|
|
124
126
|
keepNames: true,
|
|
127
|
+
conditions: ["static-load"],
|
|
125
128
|
// This doesn't work...
|
|
126
129
|
// logOverride: {
|
|
127
130
|
// "direct-eval": "silent",
|
package/dist/esm/web.js.map
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/web.ts"],
|
|
4
|
-
"mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,SAAS,eAAe;AACxB,SAAS,aAAa;AACtB,OAAO,aAAa;AACpB,SAAS,iBAAiB;AAG1B,SAAS,gBAAgB;AACzB,SAAkB,gBAAsC;AAIxD,SAAS,mBAAmB;AAE5B,eAAsB,QAAQ,QAAoB,QAAiB;AAC/D,QAAM,QAAQ,MAAM,OAAO,UAAU,KAAK;AAC1C,QAAM,aAAa,MAAM,OAAO,OAAO,
|
|
4
|
+
"mappings": "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",
|
|
5
5
|
"names": ["server", "options"]
|
|
6
6
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@matter/testing",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.2-alpha.0-20250703-2e16aba2b",
|
|
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.15.
|
|
48
|
+
"@matter/tools": "0.15.2-alpha.0-20250703-2e16aba2b",
|
|
49
49
|
"@types/express": "^5.0.3",
|
|
50
50
|
"ansi-colors": "^4.1.3",
|
|
51
51
|
"chai": "^4.5.0",
|
package/src/chai.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Matter.js Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import Chai from "chai";
|
|
8
|
+
import "./global-definitions.js";
|
|
9
|
+
|
|
10
|
+
export interface DiffMarker {}
|
|
11
|
+
|
|
12
|
+
Chai.config.truncateThreshold = 200;
|
|
13
|
+
|
|
14
|
+
function createDiffMarker(title: string) {
|
|
15
|
+
return {
|
|
16
|
+
toString() {
|
|
17
|
+
return `<<${title}>>`;
|
|
18
|
+
},
|
|
19
|
+
} as DiffMarker;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
expect.IGNORE = createDiffMarker("ignore");
|
|
23
|
+
expect.BIGINT = createDiffMarker("bigint");
|
|
24
|
+
expect.BYTES = createDiffMarker("bytes");
|
|
25
|
+
expect.NUMBER = createDiffMarker("number");
|
|
26
|
+
expect.STRING = createDiffMarker("string");
|
|
27
|
+
|
|
28
|
+
(Chai.config as any).deepEqual = (expected: unknown, actual: unknown) => {
|
|
29
|
+
return (Chai.util as any).eql(expected, actual, {
|
|
30
|
+
comparator(expected: unknown, actual: unknown) {
|
|
31
|
+
switch (expected) {
|
|
32
|
+
case expect.IGNORE:
|
|
33
|
+
return true;
|
|
34
|
+
|
|
35
|
+
case expect.BIGINT:
|
|
36
|
+
return typeof actual === "bigint";
|
|
37
|
+
|
|
38
|
+
case expect.NUMBER:
|
|
39
|
+
return typeof actual === "number";
|
|
40
|
+
|
|
41
|
+
case expect.STRING:
|
|
42
|
+
return typeof actual === "string";
|
|
43
|
+
|
|
44
|
+
case expect.BYTES:
|
|
45
|
+
return actual instanceof Uint8Array;
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
};
|
package/src/failure-detail.ts
CHANGED
|
@@ -13,6 +13,7 @@ export interface FailureDetail {
|
|
|
13
13
|
expected?: string;
|
|
14
14
|
logs?: string;
|
|
15
15
|
cause?: FailureDetail;
|
|
16
|
+
secondary?: FailureDetail;
|
|
16
17
|
errors?: FailureDetail[];
|
|
17
18
|
}
|
|
18
19
|
|
|
@@ -20,7 +21,7 @@ export interface FailureDetail {
|
|
|
20
21
|
* Captures all pertinent information about a failed test.
|
|
21
22
|
*/
|
|
22
23
|
export function FailureDetail(error: any, id?: string, logs?: string[], parentStack?: string[]) {
|
|
23
|
-
const { message, stack, stackLines, cause, errors } = parseError(error, parentStack);
|
|
24
|
+
const { message, stack, stackLines, cause, errors, secondary } = parseError(error, parentStack);
|
|
24
25
|
const result = { message } as FailureDetail;
|
|
25
26
|
|
|
26
27
|
if (stack) {
|
|
@@ -35,6 +36,9 @@ export function FailureDetail(error: any, id?: string, logs?: string[], parentSt
|
|
|
35
36
|
if (cause) {
|
|
36
37
|
result.cause = cause;
|
|
37
38
|
}
|
|
39
|
+
if (secondary) {
|
|
40
|
+
result.secondary = secondary;
|
|
41
|
+
}
|
|
38
42
|
if (errors) {
|
|
39
43
|
result.errors = errors;
|
|
40
44
|
}
|
|
@@ -89,19 +93,25 @@ function messageAndStackFor(
|
|
|
89
93
|
}
|
|
90
94
|
|
|
91
95
|
function parseError(error: Error, parentStack?: string[]) {
|
|
96
|
+
let secondary: FailureDetail | undefined;
|
|
97
|
+
if ("error" in error && "suppressed" in error) {
|
|
98
|
+
secondary = FailureDetail(error.error);
|
|
99
|
+
error = error.suppressed as Error;
|
|
100
|
+
}
|
|
101
|
+
|
|
92
102
|
const { message, id, stack, stackLines } = messageAndStackFor(error, parentStack);
|
|
93
103
|
|
|
94
104
|
let cause: FailureDetail | undefined, errors: FailureDetail[] | undefined;
|
|
95
105
|
|
|
96
106
|
const errorCause = error.cause;
|
|
97
107
|
if (errorCause) {
|
|
98
|
-
cause = FailureDetail(errorCause, undefined, stackLines);
|
|
108
|
+
cause = FailureDetail(errorCause, id, undefined, stackLines);
|
|
99
109
|
}
|
|
100
110
|
|
|
101
111
|
const errorErrors = (error as AggregateError).errors;
|
|
102
112
|
if (Array.isArray(errorErrors)) {
|
|
103
|
-
errors = errorErrors.map(e => FailureDetail(e, undefined, stackLines));
|
|
113
|
+
errors = errorErrors.map(e => FailureDetail(e, id, undefined, stackLines));
|
|
104
114
|
}
|
|
105
115
|
|
|
106
|
-
return { message, id, stack, stackLines, cause, errors };
|
|
116
|
+
return { message, id, stack, stackLines, cause, errors, secondary };
|
|
107
117
|
}
|
package/src/failure-reporter.ts
CHANGED
|
@@ -32,7 +32,10 @@ function dumpCause(out: Printer, failure: FailureDetail) {
|
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
function dumpDetails(
|
|
35
|
+
function dumpDetails(
|
|
36
|
+
out: Printer,
|
|
37
|
+
{ message, id, actual, expected, stack, cause, errors, secondary, logs }: FailureDetail,
|
|
38
|
+
) {
|
|
36
39
|
out("\n", ansi.bright.red(id ? `[${ansi.bold(id)}] ${message}` : message), "\n");
|
|
37
40
|
|
|
38
41
|
if (actual !== undefined && expected !== undefined) {
|
|
@@ -60,6 +63,11 @@ function dumpDetails(out: Printer, { message, id, actual, expected, stack, cause
|
|
|
60
63
|
}
|
|
61
64
|
}
|
|
62
65
|
|
|
66
|
+
if (secondary) {
|
|
67
|
+
out("\n", ansi.bold("Secondary error during disposal:"), "\n");
|
|
68
|
+
dumpCause(out, secondary);
|
|
69
|
+
}
|
|
70
|
+
|
|
63
71
|
if (logs) {
|
|
64
72
|
out("\n", logs, "\n");
|
|
65
73
|
}
|
|
@@ -6,13 +6,29 @@
|
|
|
6
6
|
|
|
7
7
|
import type Chai from "chai";
|
|
8
8
|
import "chai-as-promised";
|
|
9
|
+
import type { DiffMarker } from "./chai.js";
|
|
9
10
|
import type { DiagnosticMessageLike, MockLogger } from "./mocks/logging.js";
|
|
10
11
|
import type { MockTime } from "./mocks/time.js";
|
|
11
12
|
import type { TestDescriptor, TestSuiteDescriptor } from "./test-descriptor.js";
|
|
12
13
|
|
|
13
14
|
declare global {
|
|
14
15
|
// Expose Chai globally
|
|
15
|
-
const expect: typeof Chai.expect
|
|
16
|
+
const expect: typeof Chai.expect & {
|
|
17
|
+
// Ignores for purposes of deep comparison
|
|
18
|
+
IGNORE: DiffMarker;
|
|
19
|
+
|
|
20
|
+
// Matches any bigint for purposes of deep comparison
|
|
21
|
+
BIGINT: DiffMarker;
|
|
22
|
+
|
|
23
|
+
// Matches any byte array for purposes of deep comparison
|
|
24
|
+
BYTES: DiffMarker;
|
|
25
|
+
|
|
26
|
+
// Matches any number for purposes of deep comparison
|
|
27
|
+
NUMBER: DiffMarker;
|
|
28
|
+
|
|
29
|
+
// Matches any string for purposes of deep comparison
|
|
30
|
+
STRING: DiffMarker;
|
|
31
|
+
};
|
|
16
32
|
|
|
17
33
|
// Expose API for controlling time
|
|
18
34
|
let MockTime: MockTime;
|
|
@@ -9,12 +9,13 @@
|
|
|
9
9
|
|
|
10
10
|
import Chai from "chai";
|
|
11
11
|
import ChaiAsPromised from "chai-as-promised";
|
|
12
|
+
|
|
12
13
|
import { browserSetup, extendApi, generalSetup } from "./mocha.js";
|
|
13
14
|
import { bootSetup } from "./mocks/boot.js";
|
|
14
15
|
import { MockLogger, loggerSetup } from "./mocks/logging.js";
|
|
15
16
|
import { timeSetup } from "./mocks/time.js";
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
// This must go here so it initializes early
|
|
18
19
|
Chai.use(ChaiAsPromised);
|
|
19
20
|
|
|
20
21
|
Object.assign(globalThis, {
|
package/src/index.ts
CHANGED
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import "./chai.js";
|
|
7
8
|
import "./global-declarations.js";
|
|
8
9
|
export * from "./chip/index.js";
|
|
9
10
|
export * from "./device/index.js";
|
|
10
11
|
export * from "./docker/index.js";
|
|
11
12
|
export { afterRun } from "./mocha.js";
|
|
12
13
|
export * from "./mocharc.cjs";
|
|
14
|
+
export * from "./runner.js";
|
|
13
15
|
export * from "./util/heap.js";
|
|
14
16
|
export * from "./util/wtf.js";
|
package/src/mocha.ts
CHANGED
|
@@ -89,6 +89,8 @@ export function generalSetup(mocha: Mocha) {
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
export function extendApi(Mocha: typeof MochaType) {
|
|
92
|
+
(Mocha.reporters.Base as any).maxDiffSize = 0xffff;
|
|
93
|
+
|
|
92
94
|
const descriptors = new WeakMap<Mocha.Suite | Mocha.Test, TestDescriptor>();
|
|
93
95
|
|
|
94
96
|
Object.defineProperty(Mocha.Suite.prototype, "descriptor", {
|
package/src/mocks/time.ts
CHANGED
|
@@ -84,6 +84,7 @@ let callbacks = new Array<{ atMs: number; callback: TimerCallback }>();
|
|
|
84
84
|
let nowMs = 0;
|
|
85
85
|
let real = undefined as unknown;
|
|
86
86
|
let enabled = false;
|
|
87
|
+
let defaultToMacrotasks = false;
|
|
87
88
|
|
|
88
89
|
/**
|
|
89
90
|
* An arbitrary start for our mock timeline. Starting at zero causes problems with Matter dates that cannot encode back
|
|
@@ -121,6 +122,7 @@ export const MockTime = {
|
|
|
121
122
|
reset(time: ConstructorParameters<typeof Date>[0] = epoch) {
|
|
122
123
|
callbacks = [];
|
|
123
124
|
nowMs = new Date(time).getTime();
|
|
125
|
+
defaultToMacrotasks = false;
|
|
124
126
|
MockTime.enable();
|
|
125
127
|
},
|
|
126
128
|
|
|
@@ -133,6 +135,16 @@ export const MockTime = {
|
|
|
133
135
|
}
|
|
134
136
|
},
|
|
135
137
|
|
|
138
|
+
/**
|
|
139
|
+
* Enable macrotasks (true) or microtasks (false) for mock time incrementation.
|
|
140
|
+
*
|
|
141
|
+
* Microtasks are the default and are more efficient. Macrotasks are required for e.g. most of node's crypto.subtle
|
|
142
|
+
* methods to resolve.
|
|
143
|
+
*/
|
|
144
|
+
set macrotasks(value: boolean) {
|
|
145
|
+
defaultToMacrotasks = value;
|
|
146
|
+
},
|
|
147
|
+
|
|
136
148
|
atTime<T>(time: number | Date, actor: () => T): T {
|
|
137
149
|
const revertTo = nowMs;
|
|
138
150
|
let isAsync = false;
|
|
@@ -196,7 +208,7 @@ export const MockTime = {
|
|
|
196
208
|
// if you only yield via microtask. It seems to require yielding via macrotask. So we optionally use
|
|
197
209
|
// setTimeout here. Probably related to entropy collection but I think it's safe to classify as a Node bug.
|
|
198
210
|
// Tested on version 20.11.0
|
|
199
|
-
if (macrotasks) {
|
|
211
|
+
if (macrotasks ?? defaultToMacrotasks) {
|
|
200
212
|
await new Promise<void>(resolve => setTimeout(() => resolve(), 0));
|
|
201
213
|
} else {
|
|
202
214
|
await MockTime.yield();
|
|
@@ -215,11 +227,13 @@ export const MockTime = {
|
|
|
215
227
|
|
|
216
228
|
if (stepMs) {
|
|
217
229
|
await this.advance(stepMs);
|
|
230
|
+
timeAdvanced += stepMs;
|
|
218
231
|
} else {
|
|
219
232
|
// Advance time exponentially, trying for granularity but also OK performance. Note that we are not only
|
|
220
233
|
// advancing time but also yielding event loop. So it's possible if we run out of time it's just because
|
|
221
234
|
// there were too few yields in one virtual hour. As designed currently it's 360 macrotasks and 360
|
|
222
235
|
// microtasks (360 loops w/ 1 macro- and 1 micro-yield)
|
|
236
|
+
// TODO - this isn't exponential, fix comment or fix code
|
|
223
237
|
await this.advance(1000);
|
|
224
238
|
timeAdvanced += 1000;
|
|
225
239
|
}
|
package/src/runner.ts
CHANGED
|
@@ -17,6 +17,8 @@ import { Reporter } from "./reporter.js";
|
|
|
17
17
|
import { listSupportFiles } from "./util/files.js";
|
|
18
18
|
import { testWeb } from "./web.js";
|
|
19
19
|
|
|
20
|
+
const HARNESS_CONFIG_FILE = "build/esm/test/test.harness.js";
|
|
21
|
+
|
|
20
22
|
export class TestRunner {
|
|
21
23
|
static #current?: TestRunner;
|
|
22
24
|
|
|
@@ -29,7 +31,14 @@ export class TestRunner {
|
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
readonly reporter: Reporter;
|
|
32
|
-
|
|
34
|
+
#spec = Array<string>();
|
|
35
|
+
#configured = false;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* If present the web runner will run this preprocessor on its entrypoint file. You can modify {@link lines} to
|
|
39
|
+
* add or change entrypoint logic.
|
|
40
|
+
*/
|
|
41
|
+
entrypointPreprocessor?: (this: unknown, lines: string[]) => void;
|
|
33
42
|
|
|
34
43
|
constructor(
|
|
35
44
|
readonly pkg: Package,
|
|
@@ -52,11 +61,11 @@ export class TestRunner {
|
|
|
52
61
|
})();
|
|
53
62
|
|
|
54
63
|
if (options.spec === undefined) {
|
|
55
|
-
this
|
|
64
|
+
this.#spec = ["test/**/*Test.ts"];
|
|
56
65
|
} else if (Array.isArray(options.spec)) {
|
|
57
|
-
this
|
|
66
|
+
this.#spec = options.spec;
|
|
58
67
|
} else {
|
|
59
|
-
this
|
|
68
|
+
this.#spec = [options.spec];
|
|
60
69
|
}
|
|
61
70
|
|
|
62
71
|
if (options.debug) {
|
|
@@ -65,16 +74,32 @@ export class TestRunner {
|
|
|
65
74
|
}
|
|
66
75
|
|
|
67
76
|
async runNode(format: "esm" | "cjs" = "esm") {
|
|
77
|
+
await this.#configure();
|
|
78
|
+
|
|
68
79
|
return await this.#run(this.progress, () => testNodejs(this, format));
|
|
69
80
|
}
|
|
70
81
|
|
|
71
82
|
async runWeb(manual = false) {
|
|
83
|
+
await this.#configure();
|
|
84
|
+
|
|
72
85
|
await this.#run(this.progress, () => testWeb(this, manual));
|
|
73
86
|
}
|
|
74
87
|
|
|
88
|
+
async #configure() {
|
|
89
|
+
if (this.#configured) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (this.pkg.hasFile(HARNESS_CONFIG_FILE)) {
|
|
94
|
+
await import(this.pkg.resolve(HARNESS_CONFIG_FILE));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
this.#configured = true;
|
|
98
|
+
}
|
|
99
|
+
|
|
75
100
|
async loadFiles(format: "esm" | "cjs") {
|
|
76
101
|
const tests = Array<string>();
|
|
77
|
-
for (let spec of this
|
|
102
|
+
for (let spec of this.#spec) {
|
|
78
103
|
spec = spec.replace(/\.ts$/, ".js");
|
|
79
104
|
spec = relative(this.pkg.path, spec);
|
|
80
105
|
if (!spec.startsWith(".") && !spec.startsWith("build/") && !spec.startsWith("dist/")) {
|
|
@@ -94,7 +119,7 @@ export class TestRunner {
|
|
|
94
119
|
}
|
|
95
120
|
|
|
96
121
|
if (!tests.length) {
|
|
97
|
-
fatal(`No files match ${this
|
|
122
|
+
fatal(`No files match ${this.#spec.join(", ")}`);
|
|
98
123
|
}
|
|
99
124
|
|
|
100
125
|
return [...listSupportFiles(format), ...tests];
|
package/src/util/files.ts
CHANGED
|
@@ -13,6 +13,7 @@ export function listSupportFiles(format = "cjs") {
|
|
|
13
13
|
// Always load tooling code in ESM format as tooling globals load as ESM
|
|
14
14
|
const testing = Package.tools.findPackage("@matter/testing");
|
|
15
15
|
files.push(testing.resolve("dist/esm/global-definitions.js"));
|
|
16
|
+
files.push(testing.resolve("dist/esm/chai.js"));
|
|
16
17
|
files.push(testing.resolve("dist/esm/mocks/index.js"));
|
|
17
18
|
|
|
18
19
|
// Package code should load in the format being tested
|
package/src/web.ts
CHANGED
|
@@ -19,7 +19,7 @@ import { WebReporter } from "./web-reporter.js";
|
|
|
19
19
|
|
|
20
20
|
export async function testWeb(runner: TestRunner, manual: boolean) {
|
|
21
21
|
const files = await runner.loadFiles("esm");
|
|
22
|
-
const bundlePath = await bundle(files, runner
|
|
22
|
+
const bundlePath = await bundle(files, runner);
|
|
23
23
|
|
|
24
24
|
const server = await new Promise<http.Server>((resolve, reject) => {
|
|
25
25
|
try {
|
|
@@ -63,6 +63,13 @@ export async function testWeb(runner: TestRunner, manual: boolean) {
|
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
/**
|
|
67
|
+
* You can set this to modify the web entrypoint in your testing configuration.
|
|
68
|
+
*
|
|
69
|
+
* Input is the lines of the entrypoint file. You can modify these lines to add or modify generated code.
|
|
70
|
+
*/
|
|
71
|
+
testWeb.entrypointPreprocessor = undefined as undefined | ((lines: string[]) => void);
|
|
72
|
+
|
|
66
73
|
async function testInBrowser(url: string, reporter: Reporter, options: TestOptions) {
|
|
67
74
|
async function setup() {
|
|
68
75
|
const browser = await chromium.launch();
|
|
@@ -138,23 +145,23 @@ function buildIndex(bundlePath: string) {
|
|
|
138
145
|
</html>`;
|
|
139
146
|
}
|
|
140
147
|
|
|
141
|
-
async function bundle(files: string[], pkg:
|
|
148
|
+
async function bundle(files: string[], { pkg, entrypointPreprocessor }: TestRunner) {
|
|
142
149
|
const entrypointPath = pkg.resolve("build/esm/test-entrypoint.js");
|
|
143
150
|
const bundlePath = pkg.resolve("build/cjs/test-bundle.js");
|
|
144
151
|
|
|
145
|
-
const entrypoint = files
|
|
146
|
-
.
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
152
|
+
const entrypoint = files.map(path => {
|
|
153
|
+
path = relative(pkg.resolve("build/esm"), path).replace(/\\/g, "/");
|
|
154
|
+
if (!path.startsWith(".")) {
|
|
155
|
+
path = `./${path}`;
|
|
156
|
+
}
|
|
157
|
+
return `import ${JSON.stringify(path)}`;
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
entrypointPreprocessor?.(entrypoint);
|
|
154
161
|
|
|
155
162
|
// I was unable to get esbuild to resolve the entrypoint using the "stdin" and "absWorkingDir" options. So we just
|
|
156
163
|
// write to disk
|
|
157
|
-
await writeFile(pkg.resolve("build/esm/test-entrypoint.js"), entrypoint);
|
|
164
|
+
await writeFile(pkg.resolve("build/esm/test-entrypoint.js"), entrypoint.join("\n"));
|
|
158
165
|
|
|
159
166
|
await build({
|
|
160
167
|
entryPoints: [entrypointPath],
|
|
@@ -163,6 +170,7 @@ async function bundle(files: string[], pkg: Package) {
|
|
|
163
170
|
outfile: bundlePath,
|
|
164
171
|
external: ["wtfnode"],
|
|
165
172
|
keepNames: true,
|
|
173
|
+
conditions: ["static-load"],
|
|
166
174
|
|
|
167
175
|
// This doesn't work...
|
|
168
176
|
// logOverride: {
|