@fluid-internal/mocha-test-setup 2.11.0 → 2.13.0
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/CHANGELOG.md +8 -0
- package/dist/mochaHooks.d.ts.map +1 -1
- package/dist/mochaHooks.js +61 -49
- package/dist/mochaHooks.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/lib/mochaHooks.d.ts.map +1 -1
- package/lib/mochaHooks.js +61 -49
- package/lib/mochaHooks.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/mocharc-common.cjs +9 -5
- package/package.json +5 -5
- package/src/mochaHooks.ts +72 -53
- package/src/packageVersion.ts +1 -1
package/CHANGELOG.md
CHANGED
package/dist/mochaHooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mochaHooks.d.ts","sourceRoot":"","sources":["../src/mochaHooks.ts"],"names":[],"mappings":"AAAA;;;GAGG;;
|
|
1
|
+
{"version":3,"file":"mochaHooks.d.ts","sourceRoot":"","sources":["../src/mochaHooks.ts"],"names":[],"mappings":"AAAA;;;GAGG;;AAoFH;;GAEG;AACH,eAAO,MAAM,UAAU;;qBAiBL,MAAM,OAAO;oBAed,MAAM,OAAO;CAqB7B,CAAC"}
|
package/dist/mochaHooks.js
CHANGED
|
@@ -30,11 +30,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
30
30
|
exports.mochaHooks = void 0;
|
|
31
31
|
const mochaModule = __importStar(require("mocha"));
|
|
32
32
|
const packageVersion_js_1 = require("./packageVersion.js");
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
// thrown and will take more storage in any logging sink
|
|
33
|
+
// This will enable capturing the full stack for errors.
|
|
34
|
+
// Since this package is only used when we run tests, capturing the full stack is worth it.
|
|
35
|
+
// In non-test environments we need to be more cautious as this will incur a perf impact when errors are
|
|
36
|
+
// thrown and will take more storage in any logging sink.
|
|
38
37
|
// https://v8.dev/docs/stack-trace-api
|
|
39
38
|
Error.stackTraceLimit = Number.POSITIVE_INFINITY;
|
|
40
39
|
const testVariant = process.env.FLUID_TEST_VARIANT;
|
|
@@ -42,22 +41,25 @@ const propsDict = process.env.FLUID_LOGGER_PROPS != null
|
|
|
42
41
|
? JSON.parse(process.env.FLUID_LOGGER_PROPS)
|
|
43
42
|
: undefined;
|
|
44
43
|
const _global = global;
|
|
45
|
-
|
|
44
|
+
/**
|
|
45
|
+
* A logger that adds context about the current test run to all events logged through it, like the test variant being
|
|
46
|
+
* run (odsp, r11s, etc) and the name of the current test (while in the context of a particular test running).
|
|
47
|
+
*/
|
|
48
|
+
class FluidTestRunLogger {
|
|
46
49
|
send(event) {
|
|
47
50
|
// TODO: Remove when issue #7061 is resolved.
|
|
48
51
|
// Don't log this event as we generate too much.
|
|
49
52
|
if (event.eventName === "fluid:telemetry:RouterliciousDriver:readBlob_end") {
|
|
50
53
|
return;
|
|
51
54
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
if (this.currentTestName !== undefined) {
|
|
56
|
+
event.testName = this.currentTestName;
|
|
57
|
+
}
|
|
55
58
|
event.testVariant = testVariant;
|
|
56
|
-
event.hostName = packageVersion_js_1.pkgName;
|
|
57
59
|
this.parentLogger.send({
|
|
58
60
|
...event,
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
+
// Setting hostname to pkgName is the behavior we had for a long time, so keeping it just in case.
|
|
62
|
+
// But prefer a value set through FLUID_LOGGER_PROPS if it exists.
|
|
61
63
|
hostName: propsDict?.hostName ?? packageVersion_js_1.pkgName,
|
|
62
64
|
details: JSON.stringify(propsDict),
|
|
63
65
|
});
|
|
@@ -65,84 +67,94 @@ class TestLogger {
|
|
|
65
67
|
async flush() {
|
|
66
68
|
return this.parentLogger.flush();
|
|
67
69
|
}
|
|
68
|
-
constructor(parentLogger
|
|
70
|
+
constructor(parentLogger) {
|
|
69
71
|
this.parentLogger = parentLogger;
|
|
70
|
-
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Sets the test that is currently running.
|
|
75
|
+
* The test name will be included in all events logged through the logger until {@link clearCurrentTest} is called.
|
|
76
|
+
* @param testName - The name of the test that is currently running.
|
|
77
|
+
*/
|
|
78
|
+
setCurrentTest(testName) {
|
|
79
|
+
this.currentTestName = testName;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Clears the test that is currently running.
|
|
83
|
+
* Must be called after a given test has completed so that events logged outside the context of a test
|
|
84
|
+
* don't include the name of the last test that ran.
|
|
85
|
+
*/
|
|
86
|
+
clearCurrentTest() {
|
|
87
|
+
this.currentTestName = undefined;
|
|
71
88
|
}
|
|
72
89
|
}
|
|
73
90
|
const nullLogger = {
|
|
74
91
|
send: () => { },
|
|
75
92
|
flush: async () => { },
|
|
76
93
|
};
|
|
94
|
+
// Keep references to the original console functions so we can restore them after each test.
|
|
77
95
|
const log = console.log;
|
|
78
96
|
const error = console.log;
|
|
79
97
|
const warn = console.warn;
|
|
80
|
-
let
|
|
81
|
-
let currentTestName;
|
|
82
|
-
let originalLogger;
|
|
98
|
+
let testLogger;
|
|
83
99
|
/**
|
|
84
100
|
* @internal
|
|
85
101
|
*/
|
|
86
102
|
exports.mochaHooks = {
|
|
87
103
|
beforeAll() {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
return testLogger;
|
|
102
|
-
};
|
|
104
|
+
// Code in our tests will call the global `getTestLogger` function to get a logger to use.
|
|
105
|
+
// First we call the version of that function that was (potentially) injected dynamicaly to get the logger that it
|
|
106
|
+
// provides and wrap it with a more intelligent logger which adds test-run-related context to all events logged
|
|
107
|
+
// through it. See the documentation on `FluidTestRunLogger` for details.
|
|
108
|
+
const originalLogger = _global.getTestLogger?.() ?? nullLogger;
|
|
109
|
+
testLogger = new FluidTestRunLogger(originalLogger);
|
|
110
|
+
// Then we redefine `getTestLogger` so it returns the wrapper logger.
|
|
111
|
+
// NOTE: if we have other global mocha hooks defined somewhere, they include a `beforeEach` hook, and the module in
|
|
112
|
+
// which they are defined gets loaded before this one, then if that `beforeEach` hook calls `getTestLogger` the logger
|
|
113
|
+
// it will get will still have a lot of the test-run-related context, but not the name of the current test, because
|
|
114
|
+
// it will run before the `beforeEach` hook in this file which sets that.
|
|
115
|
+
_global.getTestLogger = () => testLogger;
|
|
103
116
|
},
|
|
104
117
|
beforeEach() {
|
|
105
|
-
//
|
|
118
|
+
// If not in verbose mode, suppress console output while the current test runs.
|
|
106
119
|
if (process.env.FLUID_TEST_VERBOSE === undefined) {
|
|
107
120
|
console.log = () => { };
|
|
108
121
|
console.error = () => { };
|
|
109
122
|
console.warn = () => { };
|
|
110
123
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
// send event on test start
|
|
115
|
-
originalLogger.send({
|
|
124
|
+
ensureTestRunLoggerIsInitialized(testLogger);
|
|
125
|
+
testLogger.setCurrentTest(this.currentTest?.fullTitle() ?? "");
|
|
126
|
+
testLogger.send({
|
|
116
127
|
category: "generic",
|
|
117
128
|
eventName: "fluid:telemetry:Test_start",
|
|
118
|
-
testName: currentTestName,
|
|
119
|
-
testVariant,
|
|
120
|
-
hostName: packageVersion_js_1.pkgName,
|
|
121
129
|
});
|
|
122
130
|
},
|
|
123
131
|
afterEach() {
|
|
124
|
-
|
|
125
|
-
|
|
132
|
+
ensureTestRunLoggerIsInitialized(testLogger);
|
|
133
|
+
testLogger.send({
|
|
126
134
|
category: "generic",
|
|
127
135
|
eventName: "fluid:telemetry:Test_end",
|
|
128
|
-
testName: currentTestName,
|
|
129
136
|
state: this.currentTest?.state,
|
|
130
137
|
duration: this.currentTest?.duration,
|
|
131
138
|
timedOut: this.currentTest?.timedOut,
|
|
132
|
-
testVariant,
|
|
133
|
-
hostName: packageVersion_js_1.pkgName,
|
|
134
139
|
error: this.currentTest?.err?.message,
|
|
135
140
|
stack: this.currentTest?.err?.stack,
|
|
136
141
|
});
|
|
142
|
+
// Restore console output now that the current test is done running.
|
|
137
143
|
console.log = log;
|
|
138
144
|
console.error = error;
|
|
139
145
|
console.warn = warn;
|
|
140
|
-
//
|
|
141
|
-
|
|
142
|
-
|
|
146
|
+
// Clear the current test from the logger. Important so if anything calls `getTestLogger` outside the context of a
|
|
147
|
+
// test (e.g. during a `before` or `after` hook), it doesn't log events with the name of the last test that ran.
|
|
148
|
+
testLogger.clearCurrentTest();
|
|
143
149
|
},
|
|
144
150
|
};
|
|
145
151
|
globalThis.getMochaModule = () => {
|
|
146
152
|
return mochaModule;
|
|
147
153
|
};
|
|
154
|
+
function ensureTestRunLoggerIsInitialized(loggerToTest) {
|
|
155
|
+
if (loggerToTest instanceof FluidTestRunLogger) {
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
throw new Error("Test run logger is not initialized");
|
|
159
|
+
}
|
|
148
160
|
//# sourceMappingURL=mochaHooks.js.map
|
package/dist/mochaHooks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mochaHooks.js","sourceRoot":"","sources":["../src/mochaHooks.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;AAIH,mDAAqC;AAErC,2DAA8C;AAE9C,
|
|
1
|
+
{"version":3,"file":"mochaHooks.js","sourceRoot":"","sources":["../src/mochaHooks.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { ITelemetryBufferedLogger } from \"@fluid-internal/test-driver-definitions\";\nimport type { ITelemetryBaseEvent } from \"@fluidframework/core-interfaces\";\nimport * as mochaModule from \"mocha\";\n\nimport { pkgName } from \"./packageVersion.js\";\n\n// This will enable capturing the full stack for errors.\n// Since this package is only used when we run tests, capturing the full stack is worth it.\n// In non-test environments we need to be more cautious as this will incur a perf impact when errors are\n// thrown and will take more storage in any logging sink.\n// https://v8.dev/docs/stack-trace-api\nError.stackTraceLimit = Number.POSITIVE_INFINITY;\n\nconst testVariant = process.env.FLUID_TEST_VARIANT;\nconst propsDict =\n\tprocess.env.FLUID_LOGGER_PROPS != null\n\t\t? JSON.parse(process.env.FLUID_LOGGER_PROPS)\n\t\t: undefined;\n\nconst _global: any = global;\n\n/**\n * A logger that adds context about the current test run to all events logged through it, like the test variant being\n * run (odsp, r11s, etc) and the name of the current test (while in the context of a particular test running).\n */\nclass FluidTestRunLogger implements ITelemetryBufferedLogger {\n\tprivate currentTestName: string | undefined;\n\n\tsend(event: ITelemetryBaseEvent) {\n\t\t// TODO: Remove when issue #7061 is resolved.\n\t\t// Don't log this event as we generate too much.\n\t\tif (event.eventName === \"fluid:telemetry:RouterliciousDriver:readBlob_end\") {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.currentTestName !== undefined) {\n\t\t\tevent.testName = this.currentTestName;\n\t\t}\n\t\tevent.testVariant = testVariant;\n\t\tthis.parentLogger.send({\n\t\t\t...event,\n\t\t\t// Setting hostname to pkgName is the behavior we had for a long time, so keeping it just in case.\n\t\t\t// But prefer a value set through FLUID_LOGGER_PROPS if it exists.\n\t\t\thostName: propsDict?.hostName ?? pkgName,\n\t\t\tdetails: JSON.stringify(propsDict),\n\t\t});\n\t}\n\tasync flush() {\n\t\treturn this.parentLogger.flush();\n\t}\n\tconstructor(private readonly parentLogger: ITelemetryBufferedLogger) {}\n\n\t/**\n\t * Sets the test that is currently running.\n\t * The test name will be included in all events logged through the logger until {@link clearCurrentTest} is called.\n\t * @param testName - The name of the test that is currently running.\n\t */\n\tpublic setCurrentTest(testName: string) {\n\t\tthis.currentTestName = testName;\n\t}\n\n\t/**\n\t * Clears the test that is currently running.\n\t * Must be called after a given test has completed so that events logged outside the context of a test\n\t * don't include the name of the last test that ran.\n\t */\n\tpublic clearCurrentTest() {\n\t\tthis.currentTestName = undefined;\n\t}\n}\nconst nullLogger: ITelemetryBufferedLogger = {\n\tsend: () => {},\n\tflush: async () => {},\n};\n\n// Keep references to the original console functions so we can restore them after each test.\nconst log = console.log;\nconst error = console.log;\nconst warn = console.warn;\n\nlet testLogger: FluidTestRunLogger;\n\n/**\n * @internal\n */\nexport const mochaHooks = {\n\tbeforeAll() {\n\t\t// Code in our tests will call the global `getTestLogger` function to get a logger to use.\n\n\t\t// First we call the version of that function that was (potentially) injected dynamicaly to get the logger that it\n\t\t// provides and wrap it with a more intelligent logger which adds test-run-related context to all events logged\n\t\t// through it. See the documentation on `FluidTestRunLogger` for details.\n\t\tconst originalLogger = _global.getTestLogger?.() ?? nullLogger;\n\t\ttestLogger = new FluidTestRunLogger(originalLogger);\n\n\t\t// Then we redefine `getTestLogger` so it returns the wrapper logger.\n\t\t// NOTE: if we have other global mocha hooks defined somewhere, they include a `beforeEach` hook, and the module in\n\t\t// which they are defined gets loaded before this one, then if that `beforeEach` hook calls `getTestLogger` the logger\n\t\t// it will get will still have a lot of the test-run-related context, but not the name of the current test, because\n\t\t// it will run before the `beforeEach` hook in this file which sets that.\n\t\t_global.getTestLogger = () => testLogger;\n\t},\n\tbeforeEach(this: Mocha.Context) {\n\t\t// If not in verbose mode, suppress console output while the current test runs.\n\t\tif (process.env.FLUID_TEST_VERBOSE === undefined) {\n\t\t\tconsole.log = () => {};\n\t\t\tconsole.error = () => {};\n\t\t\tconsole.warn = () => {};\n\t\t}\n\n\t\tensureTestRunLoggerIsInitialized(testLogger);\n\t\ttestLogger.setCurrentTest(this.currentTest?.fullTitle() ?? \"\");\n\t\ttestLogger.send({\n\t\t\tcategory: \"generic\",\n\t\t\teventName: \"fluid:telemetry:Test_start\",\n\t\t});\n\t},\n\tafterEach(this: Mocha.Context) {\n\t\tensureTestRunLoggerIsInitialized(testLogger);\n\t\ttestLogger.send({\n\t\t\tcategory: \"generic\",\n\t\t\teventName: \"fluid:telemetry:Test_end\",\n\t\t\tstate: this.currentTest?.state,\n\t\t\tduration: this.currentTest?.duration,\n\t\t\ttimedOut: this.currentTest?.timedOut,\n\t\t\terror: this.currentTest?.err?.message,\n\t\t\tstack: this.currentTest?.err?.stack,\n\t\t});\n\n\t\t// Restore console output now that the current test is done running.\n\t\tconsole.log = log;\n\t\tconsole.error = error;\n\t\tconsole.warn = warn;\n\n\t\t// Clear the current test from the logger. Important so if anything calls `getTestLogger` outside the context of a\n\t\t// test (e.g. during a `before` or `after` hook), it doesn't log events with the name of the last test that ran.\n\t\ttestLogger.clearCurrentTest();\n\t},\n};\n\nglobalThis.getMochaModule = () => {\n\treturn mochaModule;\n};\n\nfunction ensureTestRunLoggerIsInitialized(\n\tloggerToTest: FluidTestRunLogger | undefined,\n): loggerToTest is FluidTestRunLogger {\n\tif (loggerToTest instanceof FluidTestRunLogger) {\n\t\treturn true;\n\t}\n\tthrow new Error(\"Test run logger is not initialized\");\n}\n"]}
|
package/dist/packageVersion.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export declare const pkgName = "@fluid-internal/mocha-test-setup";
|
|
8
|
-
export declare const pkgVersion = "2.
|
|
8
|
+
export declare const pkgVersion = "2.13.0";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
package/dist/packageVersion.js
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.pkgVersion = exports.pkgName = void 0;
|
|
10
10
|
exports.pkgName = "@fluid-internal/mocha-test-setup";
|
|
11
|
-
exports.pkgVersion = "2.
|
|
11
|
+
exports.pkgVersion = "2.13.0";
|
|
12
12
|
//# sourceMappingURL=packageVersion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,kCAAkC,CAAC;AAC7C,QAAA,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluid-internal/mocha-test-setup\";\nexport const pkgVersion = \"2.
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,kCAAkC,CAAC;AAC7C,QAAA,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluid-internal/mocha-test-setup\";\nexport const pkgVersion = \"2.13.0\";\n"]}
|
package/lib/mochaHooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mochaHooks.d.ts","sourceRoot":"","sources":["../src/mochaHooks.ts"],"names":[],"mappings":"AAAA;;;GAGG;;
|
|
1
|
+
{"version":3,"file":"mochaHooks.d.ts","sourceRoot":"","sources":["../src/mochaHooks.ts"],"names":[],"mappings":"AAAA;;;GAGG;;AAoFH;;GAEG;AACH,eAAO,MAAM,UAAU;;qBAiBL,MAAM,OAAO;oBAed,MAAM,OAAO;CAqB7B,CAAC"}
|
package/lib/mochaHooks.js
CHANGED
|
@@ -4,11 +4,10 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import * as mochaModule from "mocha";
|
|
6
6
|
import { pkgName } from "./packageVersion.js";
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// thrown and will take more storage in any logging sink
|
|
7
|
+
// This will enable capturing the full stack for errors.
|
|
8
|
+
// Since this package is only used when we run tests, capturing the full stack is worth it.
|
|
9
|
+
// In non-test environments we need to be more cautious as this will incur a perf impact when errors are
|
|
10
|
+
// thrown and will take more storage in any logging sink.
|
|
12
11
|
// https://v8.dev/docs/stack-trace-api
|
|
13
12
|
Error.stackTraceLimit = Number.POSITIVE_INFINITY;
|
|
14
13
|
const testVariant = process.env.FLUID_TEST_VARIANT;
|
|
@@ -16,22 +15,25 @@ const propsDict = process.env.FLUID_LOGGER_PROPS != null
|
|
|
16
15
|
? JSON.parse(process.env.FLUID_LOGGER_PROPS)
|
|
17
16
|
: undefined;
|
|
18
17
|
const _global = global;
|
|
19
|
-
|
|
18
|
+
/**
|
|
19
|
+
* A logger that adds context about the current test run to all events logged through it, like the test variant being
|
|
20
|
+
* run (odsp, r11s, etc) and the name of the current test (while in the context of a particular test running).
|
|
21
|
+
*/
|
|
22
|
+
class FluidTestRunLogger {
|
|
20
23
|
send(event) {
|
|
21
24
|
// TODO: Remove when issue #7061 is resolved.
|
|
22
25
|
// Don't log this event as we generate too much.
|
|
23
26
|
if (event.eventName === "fluid:telemetry:RouterliciousDriver:readBlob_end") {
|
|
24
27
|
return;
|
|
25
28
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
if (this.currentTestName !== undefined) {
|
|
30
|
+
event.testName = this.currentTestName;
|
|
31
|
+
}
|
|
29
32
|
event.testVariant = testVariant;
|
|
30
|
-
event.hostName = pkgName;
|
|
31
33
|
this.parentLogger.send({
|
|
32
34
|
...event,
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
+
// Setting hostname to pkgName is the behavior we had for a long time, so keeping it just in case.
|
|
36
|
+
// But prefer a value set through FLUID_LOGGER_PROPS if it exists.
|
|
35
37
|
hostName: propsDict?.hostName ?? pkgName,
|
|
36
38
|
details: JSON.stringify(propsDict),
|
|
37
39
|
});
|
|
@@ -39,84 +41,94 @@ class TestLogger {
|
|
|
39
41
|
async flush() {
|
|
40
42
|
return this.parentLogger.flush();
|
|
41
43
|
}
|
|
42
|
-
constructor(parentLogger
|
|
44
|
+
constructor(parentLogger) {
|
|
43
45
|
this.parentLogger = parentLogger;
|
|
44
|
-
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Sets the test that is currently running.
|
|
49
|
+
* The test name will be included in all events logged through the logger until {@link clearCurrentTest} is called.
|
|
50
|
+
* @param testName - The name of the test that is currently running.
|
|
51
|
+
*/
|
|
52
|
+
setCurrentTest(testName) {
|
|
53
|
+
this.currentTestName = testName;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Clears the test that is currently running.
|
|
57
|
+
* Must be called after a given test has completed so that events logged outside the context of a test
|
|
58
|
+
* don't include the name of the last test that ran.
|
|
59
|
+
*/
|
|
60
|
+
clearCurrentTest() {
|
|
61
|
+
this.currentTestName = undefined;
|
|
45
62
|
}
|
|
46
63
|
}
|
|
47
64
|
const nullLogger = {
|
|
48
65
|
send: () => { },
|
|
49
66
|
flush: async () => { },
|
|
50
67
|
};
|
|
68
|
+
// Keep references to the original console functions so we can restore them after each test.
|
|
51
69
|
const log = console.log;
|
|
52
70
|
const error = console.log;
|
|
53
71
|
const warn = console.warn;
|
|
54
|
-
let
|
|
55
|
-
let currentTestName;
|
|
56
|
-
let originalLogger;
|
|
72
|
+
let testLogger;
|
|
57
73
|
/**
|
|
58
74
|
* @internal
|
|
59
75
|
*/
|
|
60
76
|
export const mochaHooks = {
|
|
61
77
|
beforeAll() {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
return testLogger;
|
|
76
|
-
};
|
|
78
|
+
// Code in our tests will call the global `getTestLogger` function to get a logger to use.
|
|
79
|
+
// First we call the version of that function that was (potentially) injected dynamicaly to get the logger that it
|
|
80
|
+
// provides and wrap it with a more intelligent logger which adds test-run-related context to all events logged
|
|
81
|
+
// through it. See the documentation on `FluidTestRunLogger` for details.
|
|
82
|
+
const originalLogger = _global.getTestLogger?.() ?? nullLogger;
|
|
83
|
+
testLogger = new FluidTestRunLogger(originalLogger);
|
|
84
|
+
// Then we redefine `getTestLogger` so it returns the wrapper logger.
|
|
85
|
+
// NOTE: if we have other global mocha hooks defined somewhere, they include a `beforeEach` hook, and the module in
|
|
86
|
+
// which they are defined gets loaded before this one, then if that `beforeEach` hook calls `getTestLogger` the logger
|
|
87
|
+
// it will get will still have a lot of the test-run-related context, but not the name of the current test, because
|
|
88
|
+
// it will run before the `beforeEach` hook in this file which sets that.
|
|
89
|
+
_global.getTestLogger = () => testLogger;
|
|
77
90
|
},
|
|
78
91
|
beforeEach() {
|
|
79
|
-
//
|
|
92
|
+
// If not in verbose mode, suppress console output while the current test runs.
|
|
80
93
|
if (process.env.FLUID_TEST_VERBOSE === undefined) {
|
|
81
94
|
console.log = () => { };
|
|
82
95
|
console.error = () => { };
|
|
83
96
|
console.warn = () => { };
|
|
84
97
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
// send event on test start
|
|
89
|
-
originalLogger.send({
|
|
98
|
+
ensureTestRunLoggerIsInitialized(testLogger);
|
|
99
|
+
testLogger.setCurrentTest(this.currentTest?.fullTitle() ?? "");
|
|
100
|
+
testLogger.send({
|
|
90
101
|
category: "generic",
|
|
91
102
|
eventName: "fluid:telemetry:Test_start",
|
|
92
|
-
testName: currentTestName,
|
|
93
|
-
testVariant,
|
|
94
|
-
hostName: pkgName,
|
|
95
103
|
});
|
|
96
104
|
},
|
|
97
105
|
afterEach() {
|
|
98
|
-
|
|
99
|
-
|
|
106
|
+
ensureTestRunLoggerIsInitialized(testLogger);
|
|
107
|
+
testLogger.send({
|
|
100
108
|
category: "generic",
|
|
101
109
|
eventName: "fluid:telemetry:Test_end",
|
|
102
|
-
testName: currentTestName,
|
|
103
110
|
state: this.currentTest?.state,
|
|
104
111
|
duration: this.currentTest?.duration,
|
|
105
112
|
timedOut: this.currentTest?.timedOut,
|
|
106
|
-
testVariant,
|
|
107
|
-
hostName: pkgName,
|
|
108
113
|
error: this.currentTest?.err?.message,
|
|
109
114
|
stack: this.currentTest?.err?.stack,
|
|
110
115
|
});
|
|
116
|
+
// Restore console output now that the current test is done running.
|
|
111
117
|
console.log = log;
|
|
112
118
|
console.error = error;
|
|
113
119
|
console.warn = warn;
|
|
114
|
-
//
|
|
115
|
-
|
|
116
|
-
|
|
120
|
+
// Clear the current test from the logger. Important so if anything calls `getTestLogger` outside the context of a
|
|
121
|
+
// test (e.g. during a `before` or `after` hook), it doesn't log events with the name of the last test that ran.
|
|
122
|
+
testLogger.clearCurrentTest();
|
|
117
123
|
},
|
|
118
124
|
};
|
|
119
125
|
globalThis.getMochaModule = () => {
|
|
120
126
|
return mochaModule;
|
|
121
127
|
};
|
|
128
|
+
function ensureTestRunLoggerIsInitialized(loggerToTest) {
|
|
129
|
+
if (loggerToTest instanceof FluidTestRunLogger) {
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
throw new Error("Test run logger is not initialized");
|
|
133
|
+
}
|
|
122
134
|
//# sourceMappingURL=mochaHooks.js.map
|
package/lib/mochaHooks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mochaHooks.js","sourceRoot":"","sources":["../src/mochaHooks.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,WAAW,MAAM,OAAO,CAAC;AAErC,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE9C,
|
|
1
|
+
{"version":3,"file":"mochaHooks.js","sourceRoot":"","sources":["../src/mochaHooks.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { ITelemetryBufferedLogger } from \"@fluid-internal/test-driver-definitions\";\nimport type { ITelemetryBaseEvent } from \"@fluidframework/core-interfaces\";\nimport * as mochaModule from \"mocha\";\n\nimport { pkgName } from \"./packageVersion.js\";\n\n// This will enable capturing the full stack for errors.\n// Since this package is only used when we run tests, capturing the full stack is worth it.\n// In non-test environments we need to be more cautious as this will incur a perf impact when errors are\n// thrown and will take more storage in any logging sink.\n// https://v8.dev/docs/stack-trace-api\nError.stackTraceLimit = Number.POSITIVE_INFINITY;\n\nconst testVariant = process.env.FLUID_TEST_VARIANT;\nconst propsDict =\n\tprocess.env.FLUID_LOGGER_PROPS != null\n\t\t? JSON.parse(process.env.FLUID_LOGGER_PROPS)\n\t\t: undefined;\n\nconst _global: any = global;\n\n/**\n * A logger that adds context about the current test run to all events logged through it, like the test variant being\n * run (odsp, r11s, etc) and the name of the current test (while in the context of a particular test running).\n */\nclass FluidTestRunLogger implements ITelemetryBufferedLogger {\n\tprivate currentTestName: string | undefined;\n\n\tsend(event: ITelemetryBaseEvent) {\n\t\t// TODO: Remove when issue #7061 is resolved.\n\t\t// Don't log this event as we generate too much.\n\t\tif (event.eventName === \"fluid:telemetry:RouterliciousDriver:readBlob_end\") {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.currentTestName !== undefined) {\n\t\t\tevent.testName = this.currentTestName;\n\t\t}\n\t\tevent.testVariant = testVariant;\n\t\tthis.parentLogger.send({\n\t\t\t...event,\n\t\t\t// Setting hostname to pkgName is the behavior we had for a long time, so keeping it just in case.\n\t\t\t// But prefer a value set through FLUID_LOGGER_PROPS if it exists.\n\t\t\thostName: propsDict?.hostName ?? pkgName,\n\t\t\tdetails: JSON.stringify(propsDict),\n\t\t});\n\t}\n\tasync flush() {\n\t\treturn this.parentLogger.flush();\n\t}\n\tconstructor(private readonly parentLogger: ITelemetryBufferedLogger) {}\n\n\t/**\n\t * Sets the test that is currently running.\n\t * The test name will be included in all events logged through the logger until {@link clearCurrentTest} is called.\n\t * @param testName - The name of the test that is currently running.\n\t */\n\tpublic setCurrentTest(testName: string) {\n\t\tthis.currentTestName = testName;\n\t}\n\n\t/**\n\t * Clears the test that is currently running.\n\t * Must be called after a given test has completed so that events logged outside the context of a test\n\t * don't include the name of the last test that ran.\n\t */\n\tpublic clearCurrentTest() {\n\t\tthis.currentTestName = undefined;\n\t}\n}\nconst nullLogger: ITelemetryBufferedLogger = {\n\tsend: () => {},\n\tflush: async () => {},\n};\n\n// Keep references to the original console functions so we can restore them after each test.\nconst log = console.log;\nconst error = console.log;\nconst warn = console.warn;\n\nlet testLogger: FluidTestRunLogger;\n\n/**\n * @internal\n */\nexport const mochaHooks = {\n\tbeforeAll() {\n\t\t// Code in our tests will call the global `getTestLogger` function to get a logger to use.\n\n\t\t// First we call the version of that function that was (potentially) injected dynamicaly to get the logger that it\n\t\t// provides and wrap it with a more intelligent logger which adds test-run-related context to all events logged\n\t\t// through it. See the documentation on `FluidTestRunLogger` for details.\n\t\tconst originalLogger = _global.getTestLogger?.() ?? nullLogger;\n\t\ttestLogger = new FluidTestRunLogger(originalLogger);\n\n\t\t// Then we redefine `getTestLogger` so it returns the wrapper logger.\n\t\t// NOTE: if we have other global mocha hooks defined somewhere, they include a `beforeEach` hook, and the module in\n\t\t// which they are defined gets loaded before this one, then if that `beforeEach` hook calls `getTestLogger` the logger\n\t\t// it will get will still have a lot of the test-run-related context, but not the name of the current test, because\n\t\t// it will run before the `beforeEach` hook in this file which sets that.\n\t\t_global.getTestLogger = () => testLogger;\n\t},\n\tbeforeEach(this: Mocha.Context) {\n\t\t// If not in verbose mode, suppress console output while the current test runs.\n\t\tif (process.env.FLUID_TEST_VERBOSE === undefined) {\n\t\t\tconsole.log = () => {};\n\t\t\tconsole.error = () => {};\n\t\t\tconsole.warn = () => {};\n\t\t}\n\n\t\tensureTestRunLoggerIsInitialized(testLogger);\n\t\ttestLogger.setCurrentTest(this.currentTest?.fullTitle() ?? \"\");\n\t\ttestLogger.send({\n\t\t\tcategory: \"generic\",\n\t\t\teventName: \"fluid:telemetry:Test_start\",\n\t\t});\n\t},\n\tafterEach(this: Mocha.Context) {\n\t\tensureTestRunLoggerIsInitialized(testLogger);\n\t\ttestLogger.send({\n\t\t\tcategory: \"generic\",\n\t\t\teventName: \"fluid:telemetry:Test_end\",\n\t\t\tstate: this.currentTest?.state,\n\t\t\tduration: this.currentTest?.duration,\n\t\t\ttimedOut: this.currentTest?.timedOut,\n\t\t\terror: this.currentTest?.err?.message,\n\t\t\tstack: this.currentTest?.err?.stack,\n\t\t});\n\n\t\t// Restore console output now that the current test is done running.\n\t\tconsole.log = log;\n\t\tconsole.error = error;\n\t\tconsole.warn = warn;\n\n\t\t// Clear the current test from the logger. Important so if anything calls `getTestLogger` outside the context of a\n\t\t// test (e.g. during a `before` or `after` hook), it doesn't log events with the name of the last test that ran.\n\t\ttestLogger.clearCurrentTest();\n\t},\n};\n\nglobalThis.getMochaModule = () => {\n\treturn mochaModule;\n};\n\nfunction ensureTestRunLoggerIsInitialized(\n\tloggerToTest: FluidTestRunLogger | undefined,\n): loggerToTest is FluidTestRunLogger {\n\tif (loggerToTest instanceof FluidTestRunLogger) {\n\t\treturn true;\n\t}\n\tthrow new Error(\"Test run logger is not initialized\");\n}\n"]}
|
package/lib/packageVersion.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export declare const pkgName = "@fluid-internal/mocha-test-setup";
|
|
8
|
-
export declare const pkgVersion = "2.
|
|
8
|
+
export declare const pkgVersion = "2.13.0";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
package/lib/packageVersion.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,kCAAkC,CAAC;AAC1D,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluid-internal/mocha-test-setup\";\nexport const pkgVersion = \"2.
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,kCAAkC,CAAC;AAC1D,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluid-internal/mocha-test-setup\";\nexport const pkgVersion = \"2.13.0\";\n"]}
|
package/mocharc-common.cjs
CHANGED
|
@@ -50,11 +50,15 @@ function getFluidTestMochaConfig(packageDir, additionalRequiredModules, testRepo
|
|
|
50
50
|
"recursive": true,
|
|
51
51
|
"require": requiredModulePaths,
|
|
52
52
|
"unhandled-rejections": "strict",
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
"node-option": [
|
|
54
|
+
// Allow test-only indexes to be imported. Search the FF repo for package.json files with this condition to see example usage.
|
|
55
|
+
"conditions=allow-ff-test-exports",
|
|
56
|
+
// Performance tests benefit from having access to GC, and memory tests require it.
|
|
57
|
+
// Exposing it here avoids all packages which do perf testing from having to expose it.
|
|
58
|
+
// Note that since "node-option" is explicitly set,
|
|
59
|
+
// these must be provided here and not via mocha's --v8-expose-gc.
|
|
60
|
+
"expose-gc",
|
|
61
|
+
],
|
|
58
62
|
};
|
|
59
63
|
|
|
60
64
|
if (process.env.FLUID_TEST_TIMEOUT !== undefined) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluid-internal/mocha-test-setup",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.13.0",
|
|
4
4
|
"description": "Utilities for Fluid tests",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -30,20 +30,20 @@
|
|
|
30
30
|
"main": "dist/index.js",
|
|
31
31
|
"types": "dist/index.d.ts",
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@fluid-internal/test-driver-definitions": "~2.
|
|
34
|
-
"@fluidframework/core-interfaces": "~2.
|
|
33
|
+
"@fluid-internal/test-driver-definitions": "~2.13.0",
|
|
34
|
+
"@fluidframework/core-interfaces": "~2.13.0",
|
|
35
35
|
"mocha": "^10.2.0",
|
|
36
36
|
"source-map-support": "^0.5.21"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@arethetypeswrong/cli": "^0.
|
|
39
|
+
"@arethetypeswrong/cli": "^0.17.1",
|
|
40
40
|
"@biomejs/biome": "~1.9.3",
|
|
41
41
|
"@fluid-tools/build-cli": "^0.51.0",
|
|
42
42
|
"@fluidframework/build-common": "^2.0.3",
|
|
43
43
|
"@fluidframework/build-tools": "^0.51.0",
|
|
44
44
|
"@fluidframework/eslint-config-fluid": "^5.6.0",
|
|
45
45
|
"@microsoft/api-extractor": "7.47.8",
|
|
46
|
-
"@types/mocha": "^
|
|
46
|
+
"@types/mocha": "^10.0.10",
|
|
47
47
|
"@types/node": "^18.19.0",
|
|
48
48
|
"concurrently": "^8.2.1",
|
|
49
49
|
"copyfiles": "^2.4.1",
|
package/src/mochaHooks.ts
CHANGED
|
@@ -9,11 +9,10 @@ import * as mochaModule from "mocha";
|
|
|
9
9
|
|
|
10
10
|
import { pkgName } from "./packageVersion.js";
|
|
11
11
|
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
// thrown and will take more storage in any logging sink
|
|
12
|
+
// This will enable capturing the full stack for errors.
|
|
13
|
+
// Since this package is only used when we run tests, capturing the full stack is worth it.
|
|
14
|
+
// In non-test environments we need to be more cautious as this will incur a perf impact when errors are
|
|
15
|
+
// thrown and will take more storage in any logging sink.
|
|
17
16
|
// https://v8.dev/docs/stack-trace-api
|
|
18
17
|
Error.stackTraceLimit = Number.POSITIVE_INFINITY;
|
|
19
18
|
|
|
@@ -24,7 +23,14 @@ const propsDict =
|
|
|
24
23
|
: undefined;
|
|
25
24
|
|
|
26
25
|
const _global: any = global;
|
|
27
|
-
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* A logger that adds context about the current test run to all events logged through it, like the test variant being
|
|
29
|
+
* run (odsp, r11s, etc) and the name of the current test (while in the context of a particular test running).
|
|
30
|
+
*/
|
|
31
|
+
class FluidTestRunLogger implements ITelemetryBufferedLogger {
|
|
32
|
+
private currentTestName: string | undefined;
|
|
33
|
+
|
|
28
34
|
send(event: ITelemetryBaseEvent) {
|
|
29
35
|
// TODO: Remove when issue #7061 is resolved.
|
|
30
36
|
// Don't log this event as we generate too much.
|
|
@@ -32,15 +38,14 @@ class TestLogger implements ITelemetryBufferedLogger {
|
|
|
32
38
|
return;
|
|
33
39
|
}
|
|
34
40
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
41
|
+
if (this.currentTestName !== undefined) {
|
|
42
|
+
event.testName = this.currentTestName;
|
|
43
|
+
}
|
|
38
44
|
event.testVariant = testVariant;
|
|
39
|
-
event.hostName = pkgName;
|
|
40
45
|
this.parentLogger.send({
|
|
41
46
|
...event,
|
|
42
|
-
//
|
|
43
|
-
//
|
|
47
|
+
// Setting hostname to pkgName is the behavior we had for a long time, so keeping it just in case.
|
|
48
|
+
// But prefer a value set through FLUID_LOGGER_PROPS if it exists.
|
|
44
49
|
hostName: propsDict?.hostName ?? pkgName,
|
|
45
50
|
details: JSON.stringify(propsDict),
|
|
46
51
|
});
|
|
@@ -48,91 +53,105 @@ class TestLogger implements ITelemetryBufferedLogger {
|
|
|
48
53
|
async flush() {
|
|
49
54
|
return this.parentLogger.flush();
|
|
50
55
|
}
|
|
51
|
-
constructor(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
56
|
+
constructor(private readonly parentLogger: ITelemetryBufferedLogger) {}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Sets the test that is currently running.
|
|
60
|
+
* The test name will be included in all events logged through the logger until {@link clearCurrentTest} is called.
|
|
61
|
+
* @param testName - The name of the test that is currently running.
|
|
62
|
+
*/
|
|
63
|
+
public setCurrentTest(testName: string) {
|
|
64
|
+
this.currentTestName = testName;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Clears the test that is currently running.
|
|
69
|
+
* Must be called after a given test has completed so that events logged outside the context of a test
|
|
70
|
+
* don't include the name of the last test that ran.
|
|
71
|
+
*/
|
|
72
|
+
public clearCurrentTest() {
|
|
73
|
+
this.currentTestName = undefined;
|
|
74
|
+
}
|
|
55
75
|
}
|
|
56
76
|
const nullLogger: ITelemetryBufferedLogger = {
|
|
57
77
|
send: () => {},
|
|
58
78
|
flush: async () => {},
|
|
59
79
|
};
|
|
60
80
|
|
|
81
|
+
// Keep references to the original console functions so we can restore them after each test.
|
|
61
82
|
const log = console.log;
|
|
62
83
|
const error = console.log;
|
|
63
84
|
const warn = console.warn;
|
|
64
|
-
|
|
65
|
-
let
|
|
66
|
-
let originalLogger: ITelemetryBufferedLogger;
|
|
85
|
+
|
|
86
|
+
let testLogger: FluidTestRunLogger;
|
|
67
87
|
|
|
68
88
|
/**
|
|
69
89
|
* @internal
|
|
70
90
|
*/
|
|
71
91
|
export const mochaHooks = {
|
|
72
92
|
beforeAll() {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
return testLogger;
|
|
89
|
-
};
|
|
93
|
+
// Code in our tests will call the global `getTestLogger` function to get a logger to use.
|
|
94
|
+
|
|
95
|
+
// First we call the version of that function that was (potentially) injected dynamicaly to get the logger that it
|
|
96
|
+
// provides and wrap it with a more intelligent logger which adds test-run-related context to all events logged
|
|
97
|
+
// through it. See the documentation on `FluidTestRunLogger` for details.
|
|
98
|
+
const originalLogger = _global.getTestLogger?.() ?? nullLogger;
|
|
99
|
+
testLogger = new FluidTestRunLogger(originalLogger);
|
|
100
|
+
|
|
101
|
+
// Then we redefine `getTestLogger` so it returns the wrapper logger.
|
|
102
|
+
// NOTE: if we have other global mocha hooks defined somewhere, they include a `beforeEach` hook, and the module in
|
|
103
|
+
// which they are defined gets loaded before this one, then if that `beforeEach` hook calls `getTestLogger` the logger
|
|
104
|
+
// it will get will still have a lot of the test-run-related context, but not the name of the current test, because
|
|
105
|
+
// it will run before the `beforeEach` hook in this file which sets that.
|
|
106
|
+
_global.getTestLogger = () => testLogger;
|
|
90
107
|
},
|
|
91
108
|
beforeEach(this: Mocha.Context) {
|
|
92
|
-
//
|
|
109
|
+
// If not in verbose mode, suppress console output while the current test runs.
|
|
93
110
|
if (process.env.FLUID_TEST_VERBOSE === undefined) {
|
|
94
111
|
console.log = () => {};
|
|
95
112
|
console.error = () => {};
|
|
96
113
|
console.warn = () => {};
|
|
97
114
|
}
|
|
98
|
-
// save the test name can and clear the previous logger (if afterEach didn't get ran and it got left behind)
|
|
99
|
-
currentTestName = this.currentTest?.fullTitle();
|
|
100
|
-
currentTestLogger = undefined;
|
|
101
115
|
|
|
102
|
-
|
|
103
|
-
|
|
116
|
+
ensureTestRunLoggerIsInitialized(testLogger);
|
|
117
|
+
testLogger.setCurrentTest(this.currentTest?.fullTitle() ?? "");
|
|
118
|
+
testLogger.send({
|
|
104
119
|
category: "generic",
|
|
105
120
|
eventName: "fluid:telemetry:Test_start",
|
|
106
|
-
testName: currentTestName,
|
|
107
|
-
testVariant,
|
|
108
|
-
hostName: pkgName,
|
|
109
121
|
});
|
|
110
122
|
},
|
|
111
123
|
afterEach(this: Mocha.Context) {
|
|
112
|
-
|
|
113
|
-
|
|
124
|
+
ensureTestRunLoggerIsInitialized(testLogger);
|
|
125
|
+
testLogger.send({
|
|
114
126
|
category: "generic",
|
|
115
127
|
eventName: "fluid:telemetry:Test_end",
|
|
116
|
-
testName: currentTestName,
|
|
117
128
|
state: this.currentTest?.state,
|
|
118
129
|
duration: this.currentTest?.duration,
|
|
119
130
|
timedOut: this.currentTest?.timedOut,
|
|
120
|
-
testVariant,
|
|
121
|
-
hostName: pkgName,
|
|
122
131
|
error: this.currentTest?.err?.message,
|
|
123
132
|
stack: this.currentTest?.err?.stack,
|
|
124
133
|
});
|
|
125
134
|
|
|
135
|
+
// Restore console output now that the current test is done running.
|
|
126
136
|
console.log = log;
|
|
127
137
|
console.error = error;
|
|
128
138
|
console.warn = warn;
|
|
129
139
|
|
|
130
|
-
//
|
|
131
|
-
|
|
132
|
-
|
|
140
|
+
// Clear the current test from the logger. Important so if anything calls `getTestLogger` outside the context of a
|
|
141
|
+
// test (e.g. during a `before` or `after` hook), it doesn't log events with the name of the last test that ran.
|
|
142
|
+
testLogger.clearCurrentTest();
|
|
133
143
|
},
|
|
134
144
|
};
|
|
135
145
|
|
|
136
146
|
globalThis.getMochaModule = () => {
|
|
137
147
|
return mochaModule;
|
|
138
148
|
};
|
|
149
|
+
|
|
150
|
+
function ensureTestRunLoggerIsInitialized(
|
|
151
|
+
loggerToTest: FluidTestRunLogger | undefined,
|
|
152
|
+
): loggerToTest is FluidTestRunLogger {
|
|
153
|
+
if (loggerToTest instanceof FluidTestRunLogger) {
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
throw new Error("Test run logger is not initialized");
|
|
157
|
+
}
|
package/src/packageVersion.ts
CHANGED