@fluidframework/telemetry-utils 2.0.0-rc.1.0.3 → 2.0.0-rc.2.0.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/{.mocharc.js → .mocharc.cjs} +1 -1
- package/CHANGELOG.md +23 -0
- package/{api-extractor-esm.json → api-extractor-cjs.json} +5 -2
- package/api-extractor-lint.json +1 -1
- package/api-extractor.json +1 -1
- package/api-report/telemetry-utils.api.md +10 -33
- package/dist/config.d.ts +2 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -3
- package/dist/config.js.map +1 -1
- package/dist/error.d.ts +2 -2
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +9 -9
- package/dist/error.js.map +1 -1
- package/dist/errorLogging.d.ts +4 -4
- package/dist/errorLogging.d.ts.map +1 -1
- package/dist/errorLogging.js +19 -60
- package/dist/errorLogging.js.map +1 -1
- package/dist/eventEmitterWithErrorHandling.d.ts +1 -1
- package/dist/eventEmitterWithErrorHandling.js +1 -1
- package/dist/eventEmitterWithErrorHandling.js.map +1 -1
- package/dist/events.d.ts +2 -3
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js.map +1 -1
- package/dist/fluidErrorBase.d.ts +4 -3
- package/dist/fluidErrorBase.d.ts.map +1 -1
- package/dist/fluidErrorBase.js.map +1 -1
- package/dist/index.d.ts +12 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +58 -60
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +7 -23
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +12 -29
- package/dist/logger.js.map +1 -1
- package/dist/mockLogger.d.ts +1 -1
- package/dist/mockLogger.d.ts.map +1 -1
- package/dist/mockLogger.js +2 -2
- package/dist/mockLogger.js.map +1 -1
- package/dist/package.json +3 -0
- package/dist/sampledTelemetryHelper.d.ts +4 -4
- package/dist/sampledTelemetryHelper.d.ts.map +1 -1
- package/dist/sampledTelemetryHelper.js +1 -1
- package/dist/sampledTelemetryHelper.js.map +1 -1
- package/dist/telemetry-utils-alpha.d.ts +4 -15
- package/dist/telemetry-utils-beta.d.ts +4 -32
- package/dist/telemetry-utils-public.d.ts +4 -32
- package/dist/telemetry-utils-untrimmed.d.ts +11 -50
- package/dist/thresholdCounter.d.ts +1 -1
- package/dist/thresholdCounter.d.ts.map +1 -1
- package/dist/thresholdCounter.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/dist/utils.d.ts +1 -20
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +3 -27
- package/dist/utils.js.map +1 -1
- package/lib/config.d.ts +2 -2
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +1 -1
- package/lib/config.js.map +1 -1
- package/lib/error.d.ts +2 -2
- package/lib/error.d.ts.map +1 -1
- package/lib/error.js +1 -1
- package/lib/error.js.map +1 -1
- package/lib/errorLogging.d.ts +4 -4
- package/lib/errorLogging.d.ts.map +1 -1
- package/lib/errorLogging.js +15 -56
- package/lib/errorLogging.js.map +1 -1
- package/lib/eventEmitterWithErrorHandling.d.ts +1 -1
- package/lib/eventEmitterWithErrorHandling.js +1 -1
- package/lib/eventEmitterWithErrorHandling.js.map +1 -1
- package/lib/events.d.ts +2 -3
- package/lib/events.d.ts.map +1 -1
- package/lib/events.js.map +1 -1
- package/lib/fluidErrorBase.d.ts +4 -3
- package/lib/fluidErrorBase.d.ts.map +1 -1
- package/lib/fluidErrorBase.js.map +1 -1
- package/lib/index.d.ts +12 -12
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +11 -11
- package/lib/index.js.map +1 -1
- package/lib/logger.d.ts +7 -23
- package/lib/logger.d.ts.map +1 -1
- package/lib/logger.js +3 -19
- package/lib/logger.js.map +1 -1
- package/lib/mockLogger.d.ts +1 -1
- package/lib/mockLogger.d.ts.map +1 -1
- package/lib/mockLogger.js +1 -1
- package/lib/mockLogger.js.map +1 -1
- package/lib/sampledTelemetryHelper.d.ts +4 -4
- package/lib/sampledTelemetryHelper.d.ts.map +1 -1
- package/lib/sampledTelemetryHelper.js +1 -1
- package/lib/sampledTelemetryHelper.js.map +1 -1
- package/lib/{telemetry-utils-alpha.d.mts → telemetry-utils-alpha.d.ts} +4 -15
- package/lib/{telemetry-utils-beta.d.mts → telemetry-utils-beta.d.ts} +4 -32
- package/lib/{telemetry-utils-public.d.mts → telemetry-utils-public.d.ts} +4 -32
- package/lib/{telemetry-utils-untrimmed.d.mts → telemetry-utils-untrimmed.d.ts} +11 -50
- package/lib/test/EventEmitterWithErrorHandling.spec.js +86 -0
- package/lib/test/EventEmitterWithErrorHandling.spec.js.map +1 -0
- package/lib/test/childLogger.spec.js +233 -0
- package/lib/test/childLogger.spec.js.map +1 -0
- package/lib/test/config.spec.js +229 -0
- package/lib/test/config.spec.js.map +1 -0
- package/lib/test/error.spec.js +161 -0
- package/lib/test/error.spec.js.map +1 -0
- package/lib/test/errorLogging.spec.js +801 -0
- package/lib/test/errorLogging.spec.js.map +1 -0
- package/lib/test/errorTypeLoggingTest.spec.js +107 -0
- package/lib/test/errorTypeLoggingTest.spec.js.map +1 -0
- package/lib/test/mockLogger.spec.js +164 -0
- package/lib/test/mockLogger.spec.js.map +1 -0
- package/lib/test/multiSinkLogger.spec.js +84 -0
- package/lib/test/multiSinkLogger.spec.js.map +1 -0
- package/lib/test/performanceEvent.spec.js +86 -0
- package/lib/test/performanceEvent.spec.js.map +1 -0
- package/lib/test/sampledTelemetryHelper.spec.js +169 -0
- package/lib/test/sampledTelemetryHelper.spec.js.map +1 -0
- package/lib/test/telemetryLogger.spec.js +357 -0
- package/lib/test/telemetryLogger.spec.js.map +1 -0
- package/lib/test/thresholdCounter.spec.js +51 -0
- package/lib/test/thresholdCounter.spec.js.map +1 -0
- package/lib/test/types/validateTelemetryUtilsPrevious.generated.js +132 -0
- package/lib/test/types/validateTelemetryUtilsPrevious.generated.js.map +1 -0
- package/lib/test/utils.spec.js +284 -0
- package/lib/test/utils.spec.js.map +1 -0
- package/lib/thresholdCounter.d.ts +1 -1
- package/lib/thresholdCounter.d.ts.map +1 -1
- package/lib/thresholdCounter.js.map +1 -1
- package/lib/utils.d.ts +1 -20
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +1 -24
- package/lib/utils.js.map +1 -1
- package/package.json +75 -26
- package/src/config.ts +2 -2
- package/src/error.ts +2 -2
- package/src/errorLogging.ts +27 -68
- package/src/eventEmitterWithErrorHandling.ts +1 -1
- package/src/events.ts +2 -4
- package/src/fluidErrorBase.ts +4 -3
- package/src/index.ts +12 -13
- package/src/logger.ts +12 -28
- package/src/mockLogger.ts +2 -2
- package/src/sampledTelemetryHelper.ts +10 -11
- package/src/thresholdCounter.ts +1 -1
- package/src/utils.ts +3 -36
- package/tsconfig.cjs.json +7 -0
- package/tsconfig.json +2 -3
- package/tsconfig.esnext.json +0 -7
- /package/{.eslintrc.js → .eslintrc.cjs} +0 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import { strict as assert } from "node:assert";
|
|
6
|
+
import { LogLevel, } from "@fluidframework/core-interfaces";
|
|
7
|
+
import { ChildLogger, createChildLogger, createMultiSinkLogger } from "../logger.js";
|
|
8
|
+
import { MockLogger } from "../mockLogger.js";
|
|
9
|
+
describe("ChildLogger", () => {
|
|
10
|
+
it("Properties & Getters Propagate", () => {
|
|
11
|
+
let sent = false;
|
|
12
|
+
const logger = {
|
|
13
|
+
send(event) {
|
|
14
|
+
if (event.testProperty !== true || event.testGetter !== true) {
|
|
15
|
+
throw new Error("expected testProperty and testGetter on event");
|
|
16
|
+
}
|
|
17
|
+
sent = true;
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
const childLogger1 = ChildLogger.create(logger, "test1", {
|
|
21
|
+
all: {
|
|
22
|
+
testProperty: true,
|
|
23
|
+
testGetter: () => true,
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
childLogger1.send({ category: "generic", eventName: "test1" });
|
|
27
|
+
assert(sent, "event should be sent");
|
|
28
|
+
sent = false;
|
|
29
|
+
const childLogger2 = createChildLogger({ logger: childLogger1, namespace: "test2" });
|
|
30
|
+
childLogger2.send({ category: "generic", eventName: "test2" });
|
|
31
|
+
assert(sent, "event should be sent");
|
|
32
|
+
});
|
|
33
|
+
it("Undefined initial Properties and Getter", () => {
|
|
34
|
+
let sent = false;
|
|
35
|
+
const logger = {
|
|
36
|
+
send(event) {
|
|
37
|
+
if (event.testProperty !== true || event.testGetter !== true) {
|
|
38
|
+
throw new Error("expected testProperty and testGetter on event");
|
|
39
|
+
}
|
|
40
|
+
if (event.eventName !== "test1:test2:testEvent") {
|
|
41
|
+
throw new Error("expected combined namespace");
|
|
42
|
+
}
|
|
43
|
+
sent = true;
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
const childLogger1 = createChildLogger({ logger, namespace: "test1" });
|
|
47
|
+
sent = false;
|
|
48
|
+
const childLogger2 = ChildLogger.create(childLogger1, "test2", {
|
|
49
|
+
all: {
|
|
50
|
+
testProperty: true,
|
|
51
|
+
testGetter: () => true,
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
childLogger2.send({ category: "generic", eventName: "testEvent" });
|
|
55
|
+
assert(sent, "event should be sent");
|
|
56
|
+
});
|
|
57
|
+
it("Properties Are Combined", () => {
|
|
58
|
+
let sent = false;
|
|
59
|
+
const logger = {
|
|
60
|
+
send(event) {
|
|
61
|
+
if (event.testProperty1 !== true || event.testProperty2 !== true) {
|
|
62
|
+
throw new Error("expected testProperty1 and testProperty2 on event");
|
|
63
|
+
}
|
|
64
|
+
if (event.eventName !== "test1:test2:testEvent") {
|
|
65
|
+
throw new Error("expected combined namespace");
|
|
66
|
+
}
|
|
67
|
+
sent = true;
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
const childLogger1 = ChildLogger.create(logger, "test1", {
|
|
71
|
+
all: {
|
|
72
|
+
testProperty1: true,
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
const childLogger2 = ChildLogger.create(childLogger1, "test2", {
|
|
76
|
+
all: {
|
|
77
|
+
testProperty2: true,
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
childLogger2.send({ category: "generic", eventName: "testEvent" });
|
|
81
|
+
assert(sent, "event should be sent");
|
|
82
|
+
});
|
|
83
|
+
it("Getters Are Combined", () => {
|
|
84
|
+
let sent = false;
|
|
85
|
+
const logger = {
|
|
86
|
+
send(event) {
|
|
87
|
+
if (event.testGetter1 !== true || event.testGetter2 !== true) {
|
|
88
|
+
throw new Error("expected testGetter1 and testGetter2 on event");
|
|
89
|
+
}
|
|
90
|
+
if (event.eventName !== "test1:test2:testEvent") {
|
|
91
|
+
throw new Error("expected combined namespace");
|
|
92
|
+
}
|
|
93
|
+
sent = true;
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
const childLogger1 = ChildLogger.create(logger, "test1", {
|
|
97
|
+
all: {
|
|
98
|
+
testGetter1: () => true,
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
const childLogger2 = ChildLogger.create(childLogger1, "test2", {
|
|
102
|
+
all: {
|
|
103
|
+
testGetter2: () => true,
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
childLogger2.send({ category: "generic", eventName: "testEvent" });
|
|
107
|
+
assert(sent, "event should be sent");
|
|
108
|
+
});
|
|
109
|
+
it("Undefined initial namespace", () => {
|
|
110
|
+
let sent = false;
|
|
111
|
+
const logger = {
|
|
112
|
+
send(event) {
|
|
113
|
+
if (event.eventName !== "test2:testEvent") {
|
|
114
|
+
throw new Error("expected combined namespace");
|
|
115
|
+
}
|
|
116
|
+
sent = true;
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
const childLogger1 = createChildLogger({ logger });
|
|
120
|
+
sent = false;
|
|
121
|
+
const childLogger2 = createChildLogger({ logger: childLogger1, namespace: "test2" });
|
|
122
|
+
childLogger2.send({ category: "generic", eventName: "testEvent" });
|
|
123
|
+
assert(sent, "event should be sent");
|
|
124
|
+
});
|
|
125
|
+
it("Undefined second child namespace", () => {
|
|
126
|
+
let sent = false;
|
|
127
|
+
const logger = {
|
|
128
|
+
send(event) {
|
|
129
|
+
if (event.eventName !== "test1:testEvent") {
|
|
130
|
+
throw new Error("expected combined namespace");
|
|
131
|
+
}
|
|
132
|
+
sent = true;
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
const childLogger1 = createChildLogger({ logger, namespace: "test1" });
|
|
136
|
+
sent = false;
|
|
137
|
+
const childLogger2 = createChildLogger({ logger: childLogger1 });
|
|
138
|
+
childLogger2.send({ category: "generic", eventName: "testEvent" });
|
|
139
|
+
assert(sent, "event should be sent");
|
|
140
|
+
});
|
|
141
|
+
it("Undefined namespace", () => {
|
|
142
|
+
let sent = false;
|
|
143
|
+
const logger = {
|
|
144
|
+
send(event) {
|
|
145
|
+
if (event.eventName !== "testEvent") {
|
|
146
|
+
throw new Error("expected combined namespace");
|
|
147
|
+
}
|
|
148
|
+
sent = true;
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
const childLogger1 = createChildLogger({ logger });
|
|
152
|
+
sent = false;
|
|
153
|
+
const childLogger2 = createChildLogger({ logger: childLogger1 });
|
|
154
|
+
childLogger2.send({ category: "generic", eventName: "testEvent" });
|
|
155
|
+
assert(sent, "event should be sent");
|
|
156
|
+
});
|
|
157
|
+
it("should not send events with log level less than minloglevel", () => {
|
|
158
|
+
let sent = false;
|
|
159
|
+
const logger = {
|
|
160
|
+
send(event) {
|
|
161
|
+
if (event.eventName !== "testEvent") {
|
|
162
|
+
throw new Error("unexpected event");
|
|
163
|
+
}
|
|
164
|
+
sent = true;
|
|
165
|
+
},
|
|
166
|
+
minLogLevel: LogLevel.error,
|
|
167
|
+
};
|
|
168
|
+
const childLogger1 = createChildLogger({ logger });
|
|
169
|
+
childLogger1.send({ category: "error", eventName: "testEvent" }, LogLevel.error);
|
|
170
|
+
assert(sent, "event should be sent");
|
|
171
|
+
sent = false;
|
|
172
|
+
childLogger1.send({ category: "generic", eventName: "testEvent" }, LogLevel.default);
|
|
173
|
+
assert(!sent, "event should not be sent");
|
|
174
|
+
});
|
|
175
|
+
it("should receive verbose events with min loglevel set as verbose", () => {
|
|
176
|
+
let sent = false;
|
|
177
|
+
const logger = {
|
|
178
|
+
send(event) {
|
|
179
|
+
if (event.eventName !== "testEvent") {
|
|
180
|
+
throw new Error("unexpected event");
|
|
181
|
+
}
|
|
182
|
+
sent = true;
|
|
183
|
+
},
|
|
184
|
+
minLogLevel: LogLevel.verbose,
|
|
185
|
+
};
|
|
186
|
+
const childLogger1 = createChildLogger({ logger });
|
|
187
|
+
childLogger1.send({ category: "generic", eventName: "testEvent" }, LogLevel.verbose);
|
|
188
|
+
assert(sent, "event should be sent");
|
|
189
|
+
sent = false;
|
|
190
|
+
childLogger1.send({ category: "error", eventName: "testEvent" });
|
|
191
|
+
assert(sent, "default event should be sent");
|
|
192
|
+
});
|
|
193
|
+
it("should not receive verbose events with no min loglevel", () => {
|
|
194
|
+
let sent = false;
|
|
195
|
+
const logger = {
|
|
196
|
+
send(event) {
|
|
197
|
+
if (event.eventName !== "testEvent") {
|
|
198
|
+
throw new Error("unexpected event");
|
|
199
|
+
}
|
|
200
|
+
sent = true;
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
const childLogger1 = createChildLogger({ logger });
|
|
204
|
+
childLogger1.send({ category: "error", eventName: "testEvent" });
|
|
205
|
+
assert(sent, "default event should be sent");
|
|
206
|
+
sent = false;
|
|
207
|
+
childLogger1.send({ category: "generic", eventName: "testEvent" }, LogLevel.verbose);
|
|
208
|
+
assert(!sent, "event should not be sent");
|
|
209
|
+
});
|
|
210
|
+
it("should be able to send events correctly according to loglevel if multisink logger is used inside childlogger", () => {
|
|
211
|
+
let sent = false;
|
|
212
|
+
const logger1 = {
|
|
213
|
+
send(event) {
|
|
214
|
+
if (event.eventName !== "testEvent") {
|
|
215
|
+
throw new Error("unexpected event");
|
|
216
|
+
}
|
|
217
|
+
sent = true;
|
|
218
|
+
},
|
|
219
|
+
minLogLevel: LogLevel.default,
|
|
220
|
+
};
|
|
221
|
+
const multiSinkLogger = createMultiSinkLogger({
|
|
222
|
+
loggers: [logger1, new MockLogger(LogLevel.error)],
|
|
223
|
+
});
|
|
224
|
+
const childLogger1 = createChildLogger({
|
|
225
|
+
logger: multiSinkLogger,
|
|
226
|
+
});
|
|
227
|
+
childLogger1.send({ category: "generic", eventName: "testEvent" }, LogLevel.verbose);
|
|
228
|
+
assert(!sent, "verbose event should not be sent");
|
|
229
|
+
childLogger1.send({ category: "generic", eventName: "testEvent" }, LogLevel.default);
|
|
230
|
+
assert(sent, "verbose event should be sent");
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
//# sourceMappingURL=childLogger.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"childLogger.spec.js","sourceRoot":"","sources":["../../src/test/childLogger.spec.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 { strict as assert } from \"node:assert\";\nimport {\n\tITelemetryBaseEvent,\n\tITelemetryBaseLogger,\n\tLogLevel,\n} from \"@fluidframework/core-interfaces\";\nimport { ChildLogger, createChildLogger, createMultiSinkLogger } from \"../logger.js\";\nimport { MockLogger } from \"../mockLogger.js\";\n\ndescribe(\"ChildLogger\", () => {\n\tit(\"Properties & Getters Propagate\", () => {\n\t\tlet sent = false;\n\t\tconst logger: ITelemetryBaseLogger = {\n\t\t\tsend(event: ITelemetryBaseEvent): void {\n\t\t\t\tif (event.testProperty !== true || event.testGetter !== true) {\n\t\t\t\t\tthrow new Error(\"expected testProperty and testGetter on event\");\n\t\t\t\t}\n\t\t\t\tsent = true;\n\t\t\t},\n\t\t};\n\t\tconst childLogger1 = ChildLogger.create(logger, \"test1\", {\n\t\t\tall: {\n\t\t\t\ttestProperty: true,\n\t\t\t\ttestGetter: () => true,\n\t\t\t},\n\t\t});\n\n\t\tchildLogger1.send({ category: \"generic\", eventName: \"test1\" });\n\t\tassert(sent, \"event should be sent\");\n\n\t\tsent = false;\n\t\tconst childLogger2 = createChildLogger({ logger: childLogger1, namespace: \"test2\" });\n\n\t\tchildLogger2.send({ category: \"generic\", eventName: \"test2\" });\n\t\tassert(sent, \"event should be sent\");\n\t});\n\n\tit(\"Undefined initial Properties and Getter\", () => {\n\t\tlet sent = false;\n\t\tconst logger: ITelemetryBaseLogger = {\n\t\t\tsend(event: ITelemetryBaseEvent): void {\n\t\t\t\tif (event.testProperty !== true || event.testGetter !== true) {\n\t\t\t\t\tthrow new Error(\"expected testProperty and testGetter on event\");\n\t\t\t\t}\n\t\t\t\tif (event.eventName !== \"test1:test2:testEvent\") {\n\t\t\t\t\tthrow new Error(\"expected combined namespace\");\n\t\t\t\t}\n\t\t\t\tsent = true;\n\t\t\t},\n\t\t};\n\t\tconst childLogger1 = createChildLogger({ logger, namespace: \"test1\" });\n\n\t\tsent = false;\n\t\tconst childLogger2 = ChildLogger.create(childLogger1, \"test2\", {\n\t\t\tall: {\n\t\t\t\ttestProperty: true,\n\t\t\t\ttestGetter: () => true,\n\t\t\t},\n\t\t});\n\n\t\tchildLogger2.send({ category: \"generic\", eventName: \"testEvent\" });\n\t\tassert(sent, \"event should be sent\");\n\t});\n\n\tit(\"Properties Are Combined\", () => {\n\t\tlet sent = false;\n\t\tconst logger: ITelemetryBaseLogger = {\n\t\t\tsend(event: ITelemetryBaseEvent): void {\n\t\t\t\tif (event.testProperty1 !== true || event.testProperty2 !== true) {\n\t\t\t\t\tthrow new Error(\"expected testProperty1 and testProperty2 on event\");\n\t\t\t\t}\n\t\t\t\tif (event.eventName !== \"test1:test2:testEvent\") {\n\t\t\t\t\tthrow new Error(\"expected combined namespace\");\n\t\t\t\t}\n\t\t\t\tsent = true;\n\t\t\t},\n\t\t};\n\t\tconst childLogger1 = ChildLogger.create(logger, \"test1\", {\n\t\t\tall: {\n\t\t\t\ttestProperty1: true,\n\t\t\t},\n\t\t});\n\n\t\tconst childLogger2 = ChildLogger.create(childLogger1, \"test2\", {\n\t\t\tall: {\n\t\t\t\ttestProperty2: true,\n\t\t\t},\n\t\t});\n\n\t\tchildLogger2.send({ category: \"generic\", eventName: \"testEvent\" });\n\t\tassert(sent, \"event should be sent\");\n\t});\n\n\tit(\"Getters Are Combined\", () => {\n\t\tlet sent = false;\n\t\tconst logger: ITelemetryBaseLogger = {\n\t\t\tsend(event: ITelemetryBaseEvent): void {\n\t\t\t\tif (event.testGetter1 !== true || event.testGetter2 !== true) {\n\t\t\t\t\tthrow new Error(\"expected testGetter1 and testGetter2 on event\");\n\t\t\t\t}\n\t\t\t\tif (event.eventName !== \"test1:test2:testEvent\") {\n\t\t\t\t\tthrow new Error(\"expected combined namespace\");\n\t\t\t\t}\n\t\t\t\tsent = true;\n\t\t\t},\n\t\t};\n\t\tconst childLogger1 = ChildLogger.create(logger, \"test1\", {\n\t\t\tall: {\n\t\t\t\ttestGetter1: () => true,\n\t\t\t},\n\t\t});\n\n\t\tconst childLogger2 = ChildLogger.create(childLogger1, \"test2\", {\n\t\t\tall: {\n\t\t\t\ttestGetter2: () => true,\n\t\t\t},\n\t\t});\n\n\t\tchildLogger2.send({ category: \"generic\", eventName: \"testEvent\" });\n\t\tassert(sent, \"event should be sent\");\n\t});\n\n\tit(\"Undefined initial namespace\", () => {\n\t\tlet sent = false;\n\t\tconst logger: ITelemetryBaseLogger = {\n\t\t\tsend(event: ITelemetryBaseEvent): void {\n\t\t\t\tif (event.eventName !== \"test2:testEvent\") {\n\t\t\t\t\tthrow new Error(\"expected combined namespace\");\n\t\t\t\t}\n\t\t\t\tsent = true;\n\t\t\t},\n\t\t};\n\t\tconst childLogger1 = createChildLogger({ logger });\n\n\t\tsent = false;\n\t\tconst childLogger2 = createChildLogger({ logger: childLogger1, namespace: \"test2\" });\n\n\t\tchildLogger2.send({ category: \"generic\", eventName: \"testEvent\" });\n\t\tassert(sent, \"event should be sent\");\n\t});\n\n\tit(\"Undefined second child namespace\", () => {\n\t\tlet sent = false;\n\t\tconst logger: ITelemetryBaseLogger = {\n\t\t\tsend(event: ITelemetryBaseEvent): void {\n\t\t\t\tif (event.eventName !== \"test1:testEvent\") {\n\t\t\t\t\tthrow new Error(\"expected combined namespace\");\n\t\t\t\t}\n\t\t\t\tsent = true;\n\t\t\t},\n\t\t};\n\t\tconst childLogger1 = createChildLogger({ logger, namespace: \"test1\" });\n\n\t\tsent = false;\n\t\tconst childLogger2 = createChildLogger({ logger: childLogger1 });\n\n\t\tchildLogger2.send({ category: \"generic\", eventName: \"testEvent\" });\n\t\tassert(sent, \"event should be sent\");\n\t});\n\n\tit(\"Undefined namespace\", () => {\n\t\tlet sent = false;\n\t\tconst logger: ITelemetryBaseLogger = {\n\t\t\tsend(event: ITelemetryBaseEvent): void {\n\t\t\t\tif (event.eventName !== \"testEvent\") {\n\t\t\t\t\tthrow new Error(\"expected combined namespace\");\n\t\t\t\t}\n\t\t\t\tsent = true;\n\t\t\t},\n\t\t};\n\t\tconst childLogger1 = createChildLogger({ logger });\n\n\t\tsent = false;\n\t\tconst childLogger2 = createChildLogger({ logger: childLogger1 });\n\n\t\tchildLogger2.send({ category: \"generic\", eventName: \"testEvent\" });\n\t\tassert(sent, \"event should be sent\");\n\t});\n\n\tit(\"should not send events with log level less than minloglevel\", () => {\n\t\tlet sent = false;\n\t\tconst logger: ITelemetryBaseLogger = {\n\t\t\tsend(event: ITelemetryBaseEvent): void {\n\t\t\t\tif (event.eventName !== \"testEvent\") {\n\t\t\t\t\tthrow new Error(\"unexpected event\");\n\t\t\t\t}\n\t\t\t\tsent = true;\n\t\t\t},\n\n\t\t\tminLogLevel: LogLevel.error,\n\t\t};\n\t\tconst childLogger1 = createChildLogger({ logger });\n\n\t\tchildLogger1.send({ category: \"error\", eventName: \"testEvent\" }, LogLevel.error);\n\t\tassert(sent, \"event should be sent\");\n\n\t\tsent = false;\n\t\tchildLogger1.send({ category: \"generic\", eventName: \"testEvent\" }, LogLevel.default);\n\t\tassert(!sent, \"event should not be sent\");\n\t});\n\n\tit(\"should receive verbose events with min loglevel set as verbose\", () => {\n\t\tlet sent = false;\n\t\tconst logger: ITelemetryBaseLogger = {\n\t\t\tsend(event: ITelemetryBaseEvent): void {\n\t\t\t\tif (event.eventName !== \"testEvent\") {\n\t\t\t\t\tthrow new Error(\"unexpected event\");\n\t\t\t\t}\n\t\t\t\tsent = true;\n\t\t\t},\n\n\t\t\tminLogLevel: LogLevel.verbose,\n\t\t};\n\t\tconst childLogger1 = createChildLogger({ logger });\n\n\t\tchildLogger1.send({ category: \"generic\", eventName: \"testEvent\" }, LogLevel.verbose);\n\t\tassert(sent, \"event should be sent\");\n\n\t\tsent = false;\n\t\tchildLogger1.send({ category: \"error\", eventName: \"testEvent\" });\n\t\tassert(sent, \"default event should be sent\");\n\t});\n\n\tit(\"should not receive verbose events with no min loglevel\", () => {\n\t\tlet sent = false;\n\t\tconst logger: ITelemetryBaseLogger = {\n\t\t\tsend(event: ITelemetryBaseEvent): void {\n\t\t\t\tif (event.eventName !== \"testEvent\") {\n\t\t\t\t\tthrow new Error(\"unexpected event\");\n\t\t\t\t}\n\t\t\t\tsent = true;\n\t\t\t},\n\t\t};\n\t\tconst childLogger1 = createChildLogger({ logger });\n\n\t\tchildLogger1.send({ category: \"error\", eventName: \"testEvent\" });\n\t\tassert(sent, \"default event should be sent\");\n\n\t\tsent = false;\n\t\tchildLogger1.send({ category: \"generic\", eventName: \"testEvent\" }, LogLevel.verbose);\n\t\tassert(!sent, \"event should not be sent\");\n\t});\n\n\tit(\"should be able to send events correctly according to loglevel if multisink logger is used inside childlogger\", () => {\n\t\tlet sent = false;\n\t\tconst logger1: ITelemetryBaseLogger = {\n\t\t\tsend(event: ITelemetryBaseEvent): void {\n\t\t\t\tif (event.eventName !== \"testEvent\") {\n\t\t\t\t\tthrow new Error(\"unexpected event\");\n\t\t\t\t}\n\t\t\t\tsent = true;\n\t\t\t},\n\t\t\tminLogLevel: LogLevel.default,\n\t\t};\n\t\tconst multiSinkLogger = createMultiSinkLogger({\n\t\t\tloggers: [logger1, new MockLogger(LogLevel.error)],\n\t\t});\n\t\tconst childLogger1 = createChildLogger({\n\t\t\tlogger: multiSinkLogger,\n\t\t});\n\n\t\tchildLogger1.send({ category: \"generic\", eventName: \"testEvent\" }, LogLevel.verbose);\n\t\tassert(!sent, \"verbose event should not be sent\");\n\n\t\tchildLogger1.send({ category: \"generic\", eventName: \"testEvent\" }, LogLevel.default);\n\t\tassert(sent, \"verbose event should be sent\");\n\t});\n});\n"]}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import { strict as assert } from "node:assert";
|
|
6
|
+
import { CachedConfigProvider, inMemoryConfigProvider, wrapConfigProviderWithDefaults, } from "../config.js";
|
|
7
|
+
import { TelemetryDataTag } from "../logger.js";
|
|
8
|
+
import { MockLogger } from "../mockLogger.js";
|
|
9
|
+
const getMockStore = (settings) => {
|
|
10
|
+
const ops = [];
|
|
11
|
+
return {
|
|
12
|
+
getItem: (key) => {
|
|
13
|
+
ops.push(key);
|
|
14
|
+
return settings[key];
|
|
15
|
+
},
|
|
16
|
+
getOps: () => ops,
|
|
17
|
+
length: Object.keys(settings).length,
|
|
18
|
+
clear: () => { },
|
|
19
|
+
// eslint-disable-next-line unicorn/no-null
|
|
20
|
+
key: (_index) => null,
|
|
21
|
+
removeItem: (_key) => { },
|
|
22
|
+
setItem: (_key, _value) => { },
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
const untypedProvider = (settings) => {
|
|
26
|
+
return {
|
|
27
|
+
getRawConfig: (name) => settings[name],
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
describe("Config", () => {
|
|
31
|
+
it("Typing - storage provider", () => {
|
|
32
|
+
const settings = {
|
|
33
|
+
number: "1",
|
|
34
|
+
badNumber: "{1}",
|
|
35
|
+
stringAndNumber: "1",
|
|
36
|
+
stringAndBoolean: "true",
|
|
37
|
+
string: "string",
|
|
38
|
+
boolean: "true",
|
|
39
|
+
badBoolean: "truthy",
|
|
40
|
+
numberArray: `[1, 2, 3]`,
|
|
41
|
+
badNumberArray: `["one", "two", "three"]`,
|
|
42
|
+
stringArray: `["1", "2", "3"]`,
|
|
43
|
+
badStringArray: "1",
|
|
44
|
+
booleanArray: "[true, false, true]",
|
|
45
|
+
BadBooleanArray: "[true, 1, true]",
|
|
46
|
+
};
|
|
47
|
+
const mockStore = getMockStore(settings);
|
|
48
|
+
const logger = new MockLogger();
|
|
49
|
+
const config = new CachedConfigProvider(logger, inMemoryConfigProvider(mockStore));
|
|
50
|
+
assert.equal(config.getNumber("number"), 1);
|
|
51
|
+
logger.assertMatch([
|
|
52
|
+
{
|
|
53
|
+
category: "generic",
|
|
54
|
+
eventName: "ConfigRead",
|
|
55
|
+
configName: { tag: TelemetryDataTag.CodeArtifact, value: "number" },
|
|
56
|
+
configValue: {
|
|
57
|
+
tag: TelemetryDataTag.CodeArtifact,
|
|
58
|
+
value: `{"raw":"1","string":"1","number":1}`,
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
]);
|
|
62
|
+
assert.equal(config.getNumber("badNumber"), undefined);
|
|
63
|
+
assert.equal(config.getNumber("stringAndNumber"), 1);
|
|
64
|
+
assert.equal(config.getString("stringAndNumber"), "1");
|
|
65
|
+
assert.equal(config.getString("stringAndBoolean"), "true");
|
|
66
|
+
assert.equal(config.getString("string"), "string");
|
|
67
|
+
assert.equal(config.getBoolean("boolean"), true);
|
|
68
|
+
assert.equal(config.getBoolean("badBoolean"), undefined);
|
|
69
|
+
assert.equal(config.getBoolean("stringAndBoolean"), true);
|
|
70
|
+
assert.deepEqual(config.getNumberArray("numberArray"), [1, 2, 3]);
|
|
71
|
+
assert.equal(config.getNumberArray("badNumberArray"), undefined);
|
|
72
|
+
assert.deepEqual(config.getStringArray("stringArray"), ["1", "2", "3"]);
|
|
73
|
+
assert.equal(config.getStringArray("badStringArray"), undefined);
|
|
74
|
+
assert.deepEqual(config.getBooleanArray("booleanArray"), [true, false, true]);
|
|
75
|
+
assert.equal(config.getBooleanArray("BadBooleanArray"), undefined);
|
|
76
|
+
});
|
|
77
|
+
it("Typing - custom provider", () => {
|
|
78
|
+
const settings = {
|
|
79
|
+
number: 1,
|
|
80
|
+
badNumber: "{1}",
|
|
81
|
+
stringAndNumber: "1",
|
|
82
|
+
stringAndBoolean: "true",
|
|
83
|
+
string: "string",
|
|
84
|
+
badString: [],
|
|
85
|
+
boolean: "true",
|
|
86
|
+
badBoolean: "truthy",
|
|
87
|
+
numberArray: `[1, 2, 3]`,
|
|
88
|
+
badNumberArray: ["one", "two", "three"],
|
|
89
|
+
stringArray: `["1", "2", "3"]`,
|
|
90
|
+
badStringArray: "1",
|
|
91
|
+
booleanArray: [true, false, true],
|
|
92
|
+
badBooleanArray: [1, 2, 3],
|
|
93
|
+
badBooleanArray2: ["true", "false", "true"],
|
|
94
|
+
};
|
|
95
|
+
const mockStore = untypedProvider(settings);
|
|
96
|
+
const config = new CachedConfigProvider(undefined, mockStore);
|
|
97
|
+
assert.equal(config.getNumber("number"), 1);
|
|
98
|
+
assert.equal(config.getNumber("stringAndNumber"), 1);
|
|
99
|
+
assert.equal(config.getNumber("badNumber"), undefined);
|
|
100
|
+
assert.equal(config.getString("stringAndNumber"), "1");
|
|
101
|
+
assert.equal(config.getString("stringAndBoolean"), "true");
|
|
102
|
+
assert.equal(config.getString("string"), "string");
|
|
103
|
+
assert.equal(config.getString("badString"), undefined);
|
|
104
|
+
assert.equal(config.getBoolean("boolean"), true);
|
|
105
|
+
assert.equal(config.getBoolean("badBoolean"), undefined);
|
|
106
|
+
assert.equal(config.getBoolean("stringAndBoolean"), true);
|
|
107
|
+
assert.deepEqual(config.getNumberArray("numberArray"), [1, 2, 3]);
|
|
108
|
+
assert.equal(config.getNumberArray("badNumberArray"), undefined);
|
|
109
|
+
assert.deepEqual(config.getStringArray("stringArray"), ["1", "2", "3"]);
|
|
110
|
+
assert.equal(config.getStringArray("badStringArray"), undefined);
|
|
111
|
+
assert.deepEqual(config.getBooleanArray("booleanArray"), [true, false, true]);
|
|
112
|
+
assert.equal(config.getBooleanArray("badBooleanArray"), undefined);
|
|
113
|
+
assert.equal(config.getBooleanArray("badBooleanArray2"), undefined);
|
|
114
|
+
});
|
|
115
|
+
it("Void provider", () => {
|
|
116
|
+
const config = new CachedConfigProvider(undefined, inMemoryConfigProvider(undefined));
|
|
117
|
+
assert.equal(config.getNumber("number"), undefined);
|
|
118
|
+
assert.equal(config.getString("does not exist"), undefined);
|
|
119
|
+
assert.equal(config.getBoolean("boolean"), undefined);
|
|
120
|
+
});
|
|
121
|
+
it("Config priority", () => {
|
|
122
|
+
const settings1 = {
|
|
123
|
+
number: "1",
|
|
124
|
+
string: "string1",
|
|
125
|
+
boolean: "true",
|
|
126
|
+
featureEnabled: "false",
|
|
127
|
+
};
|
|
128
|
+
const settings2 = {
|
|
129
|
+
number: "2",
|
|
130
|
+
string: "string2",
|
|
131
|
+
boolean: "false",
|
|
132
|
+
number2: "3",
|
|
133
|
+
featureEnabled: "true",
|
|
134
|
+
};
|
|
135
|
+
const settings3 = {
|
|
136
|
+
number2: "4",
|
|
137
|
+
number3: "4",
|
|
138
|
+
featureEnabled: "true",
|
|
139
|
+
};
|
|
140
|
+
const config1 = new CachedConfigProvider(undefined, inMemoryConfigProvider(getMockStore(settings1)), inMemoryConfigProvider(getMockStore(settings1)), inMemoryConfigProvider(getMockStore(settings2)), inMemoryConfigProvider(getMockStore(settings3)));
|
|
141
|
+
assert.equal(config1.getNumber("number"), 1); // from settings1
|
|
142
|
+
assert.equal(config1.getString("string"), "string1"); // from settings1
|
|
143
|
+
assert.equal(config1.getBoolean("boolean"), true); // from settings1
|
|
144
|
+
assert.equal(config1.getNumber("number2"), 3); // from settings2
|
|
145
|
+
assert.equal(config1.getNumber("number3"), 4); // from settings3
|
|
146
|
+
assert.equal(config1.getBoolean("featureEnabled"), false); // from settings1.BreakGlass
|
|
147
|
+
const config2 = new CachedConfigProvider(undefined, inMemoryConfigProvider(getMockStore(settings3)), inMemoryConfigProvider(getMockStore(settings2)), inMemoryConfigProvider(getMockStore(settings1)), inMemoryConfigProvider(getMockStore(settings1)));
|
|
148
|
+
assert.equal(config2.getNumber("number"), 2); // from settings2
|
|
149
|
+
assert.equal(config2.getString("string"), "string2"); // from settings2
|
|
150
|
+
assert.equal(config2.getBoolean("boolean"), false); // from settings2
|
|
151
|
+
assert.equal(config2.getNumber("number2"), 4); // from settings3
|
|
152
|
+
assert.equal(config2.getNumber("number3"), 4); // from settings3
|
|
153
|
+
assert.equal(config1.getBoolean("featureEnabled"), false); // from settings1.BreakGlass
|
|
154
|
+
});
|
|
155
|
+
class HybridSettingsProvider {
|
|
156
|
+
constructor(store) {
|
|
157
|
+
this.store = store;
|
|
158
|
+
this.SettingsProvider = this;
|
|
159
|
+
}
|
|
160
|
+
getRawConfig(name) {
|
|
161
|
+
// The point here is to use `getSetting`
|
|
162
|
+
// eslint-disable-next-line unicorn/no-null
|
|
163
|
+
const val = this.getSetting(name, null);
|
|
164
|
+
return val ?? undefined;
|
|
165
|
+
}
|
|
166
|
+
getSetting(settingName, defaultValue, namespace) {
|
|
167
|
+
const key = namespace === undefined ? settingName : `${namespace}.${settingName}`;
|
|
168
|
+
return this.store[key] ?? defaultValue;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
it("Typing - SettingsProvider", () => {
|
|
172
|
+
const settings = {
|
|
173
|
+
number: 1,
|
|
174
|
+
sortOfNumber: "1",
|
|
175
|
+
badNumber: "{1}",
|
|
176
|
+
stringAndNumber: "1",
|
|
177
|
+
stringAndBoolean: "true",
|
|
178
|
+
string: "string",
|
|
179
|
+
badString: [],
|
|
180
|
+
boolean: "true",
|
|
181
|
+
badBoolean: "truthy",
|
|
182
|
+
numberArray: `[1, 2, 3]`,
|
|
183
|
+
badNumberArray: ["one", "two", "three"],
|
|
184
|
+
stringArray: `["1", "2", "3"]`,
|
|
185
|
+
badStringArray: "1",
|
|
186
|
+
booleanArray: [true, false, true],
|
|
187
|
+
badBooleanArray: [1, 2, 3],
|
|
188
|
+
badBooleanArray2: ["true", "false", "true"],
|
|
189
|
+
};
|
|
190
|
+
const config = new CachedConfigProvider(undefined, new HybridSettingsProvider(settings));
|
|
191
|
+
assert.equal(config.getNumber("number"), 1);
|
|
192
|
+
assert.equal(config.getNumber("sortOfNumber"), 1);
|
|
193
|
+
assert.equal(config.getNumber("badNumber"), undefined);
|
|
194
|
+
assert.equal(config.getString("stringAndNumber"), "1");
|
|
195
|
+
assert.equal(config.getString("stringAndBoolean"), "true");
|
|
196
|
+
assert.equal(config.getString("string"), "string");
|
|
197
|
+
assert.equal(config.getString("badString"), undefined);
|
|
198
|
+
assert.equal(config.getBoolean("boolean"), true);
|
|
199
|
+
assert.equal(config.getBoolean("badBoolean"), undefined);
|
|
200
|
+
assert.deepEqual(config.getNumberArray("numberArray"), [1, 2, 3]);
|
|
201
|
+
assert.equal(config.getNumberArray("badNumberArray"), undefined);
|
|
202
|
+
assert.deepEqual(config.getStringArray("stringArray"), ["1", "2", "3"]);
|
|
203
|
+
assert.equal(config.getStringArray("badStringArray"), undefined);
|
|
204
|
+
assert.deepEqual(config.getBooleanArray("booleanArray"), [true, false, true]);
|
|
205
|
+
assert.equal(config.getBooleanArray("badBooleanArray"), undefined);
|
|
206
|
+
assert.equal(config.getBooleanArray("badBooleanArray2"), undefined);
|
|
207
|
+
});
|
|
208
|
+
// #endregion SettingsProvider
|
|
209
|
+
});
|
|
210
|
+
describe("wrappedConfigProvider", () => {
|
|
211
|
+
const configProvider = (featureGates) => ({
|
|
212
|
+
getRawConfig: (name) => featureGates[name],
|
|
213
|
+
});
|
|
214
|
+
it("When there is no original config provider", () => {
|
|
215
|
+
const config = wrapConfigProviderWithDefaults(undefined, { "Fluid.Feature.Gate": true });
|
|
216
|
+
assert.strictEqual(config.getRawConfig("Fluid.Feature.Gate"), true);
|
|
217
|
+
});
|
|
218
|
+
it("When the original config provider does not specify the required key", () => {
|
|
219
|
+
const config = wrapConfigProviderWithDefaults(configProvider({}), {
|
|
220
|
+
"Fluid.Feature.Gate": true,
|
|
221
|
+
});
|
|
222
|
+
assert.strictEqual(config.getRawConfig("Fluid.Feature.Gate"), true);
|
|
223
|
+
});
|
|
224
|
+
it("When the original config provider specifies the required key", () => {
|
|
225
|
+
const config = wrapConfigProviderWithDefaults(configProvider({ "Fluid.Feature.Gate": false }), { "Fluid.Feature.Gate": true });
|
|
226
|
+
assert.strictEqual(config.getRawConfig("Fluid.Feature.Gate"), false);
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
//# sourceMappingURL=config.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.spec.js","sourceRoot":"","sources":["../../src/test/config.spec.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 { strict as assert } from \"node:assert\";\nimport { ConfigTypes, IConfigProviderBase } from \"@fluidframework/core-interfaces\";\nimport {\n\tCachedConfigProvider,\n\tinMemoryConfigProvider,\n\twrapConfigProviderWithDefaults,\n} from \"../config.js\";\nimport { TelemetryDataTag } from \"../logger.js\";\nimport { MockLogger } from \"../mockLogger.js\";\n\nconst getMockStore = (settings: Record<string, string>): Storage => {\n\tconst ops: string[] = [];\n\treturn {\n\t\tgetItem: (key: string): string | null => {\n\t\t\tops.push(key);\n\t\t\treturn settings[key];\n\t\t},\n\t\tgetOps: (): Readonly<string[]> => ops,\n\t\tlength: Object.keys(settings).length,\n\t\tclear: (): void => {},\n\t\t// eslint-disable-next-line unicorn/no-null\n\t\tkey: (_index: number): string | null => null,\n\t\tremoveItem: (_key: string): void => {},\n\t\tsetItem: (_key: string, _value: string): void => {},\n\t};\n};\n\nconst untypedProvider = (settings: Record<string, ConfigTypes>): IConfigProviderBase => {\n\treturn {\n\t\tgetRawConfig: (name: string): ConfigTypes => settings[name],\n\t};\n};\n\ndescribe(\"Config\", () => {\n\tit(\"Typing - storage provider\", () => {\n\t\tconst settings = {\n\t\t\tnumber: \"1\",\n\t\t\tbadNumber: \"{1}\",\n\t\t\tstringAndNumber: \"1\",\n\t\t\tstringAndBoolean: \"true\",\n\t\t\tstring: \"string\",\n\t\t\tboolean: \"true\",\n\t\t\tbadBoolean: \"truthy\",\n\t\t\tnumberArray: `[1, 2, 3]`,\n\t\t\tbadNumberArray: `[\"one\", \"two\", \"three\"]`,\n\t\t\tstringArray: `[\"1\", \"2\", \"3\"]`,\n\t\t\tbadStringArray: \"1\",\n\t\t\tbooleanArray: \"[true, false, true]\",\n\t\t\tBadBooleanArray: \"[true, 1, true]\",\n\t\t};\n\n\t\tconst mockStore = getMockStore(settings);\n\t\tconst logger = new MockLogger();\n\t\tconst config = new CachedConfigProvider(logger, inMemoryConfigProvider(mockStore));\n\n\t\tassert.equal(config.getNumber(\"number\"), 1);\n\t\tlogger.assertMatch([\n\t\t\t{\n\t\t\t\tcategory: \"generic\",\n\t\t\t\teventName: \"ConfigRead\",\n\t\t\t\tconfigName: { tag: TelemetryDataTag.CodeArtifact, value: \"number\" },\n\t\t\t\tconfigValue: {\n\t\t\t\t\ttag: TelemetryDataTag.CodeArtifact,\n\t\t\t\t\tvalue: `{\"raw\":\"1\",\"string\":\"1\",\"number\":1}`,\n\t\t\t\t},\n\t\t\t},\n\t\t]);\n\t\tassert.equal(config.getNumber(\"badNumber\"), undefined);\n\t\tassert.equal(config.getNumber(\"stringAndNumber\"), 1);\n\n\t\tassert.equal(config.getString(\"stringAndNumber\"), \"1\");\n\t\tassert.equal(config.getString(\"stringAndBoolean\"), \"true\");\n\t\tassert.equal(config.getString(\"string\"), \"string\");\n\n\t\tassert.equal(config.getBoolean(\"boolean\"), true);\n\t\tassert.equal(config.getBoolean(\"badBoolean\"), undefined);\n\t\tassert.equal(config.getBoolean(\"stringAndBoolean\"), true);\n\n\t\tassert.deepEqual(config.getNumberArray(\"numberArray\"), [1, 2, 3]);\n\t\tassert.equal(config.getNumberArray(\"badNumberArray\"), undefined);\n\n\t\tassert.deepEqual(config.getStringArray(\"stringArray\"), [\"1\", \"2\", \"3\"]);\n\t\tassert.equal(config.getStringArray(\"badStringArray\"), undefined);\n\n\t\tassert.deepEqual(config.getBooleanArray(\"booleanArray\"), [true, false, true]);\n\t\tassert.equal(config.getBooleanArray(\"BadBooleanArray\"), undefined);\n\t});\n\n\tit(\"Typing - custom provider\", () => {\n\t\tconst settings = {\n\t\t\tnumber: 1,\n\t\t\tbadNumber: \"{1}\",\n\t\t\tstringAndNumber: \"1\",\n\t\t\tstringAndBoolean: \"true\",\n\t\t\tstring: \"string\",\n\t\t\tbadString: [],\n\t\t\tboolean: \"true\",\n\t\t\tbadBoolean: \"truthy\",\n\t\t\tnumberArray: `[1, 2, 3]`,\n\t\t\tbadNumberArray: [\"one\", \"two\", \"three\"],\n\t\t\tstringArray: `[\"1\", \"2\", \"3\"]`,\n\t\t\tbadStringArray: \"1\",\n\t\t\tbooleanArray: [true, false, true],\n\t\t\tbadBooleanArray: [1, 2, 3],\n\t\t\tbadBooleanArray2: [\"true\", \"false\", \"true\"],\n\t\t};\n\n\t\tconst mockStore = untypedProvider(settings);\n\t\tconst config = new CachedConfigProvider(undefined, mockStore);\n\n\t\tassert.equal(config.getNumber(\"number\"), 1);\n\t\tassert.equal(config.getNumber(\"stringAndNumber\"), 1);\n\t\tassert.equal(config.getNumber(\"badNumber\"), undefined);\n\n\t\tassert.equal(config.getString(\"stringAndNumber\"), \"1\");\n\t\tassert.equal(config.getString(\"stringAndBoolean\"), \"true\");\n\t\tassert.equal(config.getString(\"string\"), \"string\");\n\t\tassert.equal(config.getString(\"badString\"), undefined);\n\n\t\tassert.equal(config.getBoolean(\"boolean\"), true);\n\t\tassert.equal(config.getBoolean(\"badBoolean\"), undefined);\n\t\tassert.equal(config.getBoolean(\"stringAndBoolean\"), true);\n\n\t\tassert.deepEqual(config.getNumberArray(\"numberArray\"), [1, 2, 3]);\n\t\tassert.equal(config.getNumberArray(\"badNumberArray\"), undefined);\n\n\t\tassert.deepEqual(config.getStringArray(\"stringArray\"), [\"1\", \"2\", \"3\"]);\n\t\tassert.equal(config.getStringArray(\"badStringArray\"), undefined);\n\n\t\tassert.deepEqual(config.getBooleanArray(\"booleanArray\"), [true, false, true]);\n\t\tassert.equal(config.getBooleanArray(\"badBooleanArray\"), undefined);\n\t\tassert.equal(config.getBooleanArray(\"badBooleanArray2\"), undefined);\n\t});\n\n\tit(\"Void provider\", () => {\n\t\tconst config = new CachedConfigProvider(undefined, inMemoryConfigProvider(undefined));\n\t\tassert.equal(config.getNumber(\"number\"), undefined);\n\t\tassert.equal(config.getString(\"does not exist\"), undefined);\n\t\tassert.equal(config.getBoolean(\"boolean\"), undefined);\n\t});\n\n\tit(\"Config priority\", () => {\n\t\tconst settings1 = {\n\t\t\tnumber: \"1\",\n\t\t\tstring: \"string1\",\n\t\t\tboolean: \"true\",\n\t\t\tfeatureEnabled: \"false\",\n\t\t};\n\t\tconst settings2 = {\n\t\t\tnumber: \"2\",\n\t\t\tstring: \"string2\",\n\t\t\tboolean: \"false\",\n\t\t\tnumber2: \"3\",\n\t\t\tfeatureEnabled: \"true\",\n\t\t};\n\t\tconst settings3 = {\n\t\t\tnumber2: \"4\",\n\t\t\tnumber3: \"4\",\n\t\t\tfeatureEnabled: \"true\",\n\t\t};\n\n\t\tconst config1 = new CachedConfigProvider(\n\t\t\tundefined,\n\t\t\tinMemoryConfigProvider(getMockStore(settings1)),\n\t\t\tinMemoryConfigProvider(getMockStore(settings1)),\n\t\t\tinMemoryConfigProvider(getMockStore(settings2)),\n\t\t\tinMemoryConfigProvider(getMockStore(settings3)),\n\t\t);\n\n\t\tassert.equal(config1.getNumber(\"number\"), 1); // from settings1\n\t\tassert.equal(config1.getString(\"string\"), \"string1\"); // from settings1\n\t\tassert.equal(config1.getBoolean(\"boolean\"), true); // from settings1\n\t\tassert.equal(config1.getNumber(\"number2\"), 3); // from settings2\n\t\tassert.equal(config1.getNumber(\"number3\"), 4); // from settings3\n\t\tassert.equal(config1.getBoolean(\"featureEnabled\"), false); // from settings1.BreakGlass\n\n\t\tconst config2 = new CachedConfigProvider(\n\t\t\tundefined,\n\t\t\tinMemoryConfigProvider(getMockStore(settings3)),\n\t\t\tinMemoryConfigProvider(getMockStore(settings2)),\n\t\t\tinMemoryConfigProvider(getMockStore(settings1)),\n\t\t\tinMemoryConfigProvider(getMockStore(settings1)),\n\t\t);\n\n\t\tassert.equal(config2.getNumber(\"number\"), 2); // from settings2\n\t\tassert.equal(config2.getString(\"string\"), \"string2\"); // from settings2\n\t\tassert.equal(config2.getBoolean(\"boolean\"), false); // from settings2\n\t\tassert.equal(config2.getNumber(\"number2\"), 4); // from settings3\n\t\tassert.equal(config2.getNumber(\"number3\"), 4); // from settings3\n\t\tassert.equal(config1.getBoolean(\"featureEnabled\"), false); // from settings1.BreakGlass\n\t});\n\n\t// #region SettingsProvider\n\n\ttype SettingType = string | boolean | number | (string | boolean | number)[] | null;\n\n\tinterface ProvideSettingsProvider {\n\t\treadonly SettingsProvider: SettingsProvider;\n\t}\n\n\tinterface SettingsProvider extends ProvideSettingsProvider {\n\t\t/**\n\t\t * Used to get the setting value for the specified setting.\n\t\t * Providing a default in case setting is not available or not defined.\n\t\t */\n\t\tgetSetting<T extends SettingType>(\n\t\t\tsettingName: string,\n\t\t\tdefaultValue: T,\n\t\t\tnamespace?: string,\n\t\t): T;\n\t}\n\n\tclass HybridSettingsProvider implements SettingsProvider, IConfigProviderBase {\n\t\tconstructor(private readonly store: Record<string, SettingType | ConfigTypes>) {}\n\n\t\tgetRawConfig(name: string): ConfigTypes {\n\t\t\t// The point here is to use `getSetting`\n\t\t\t// eslint-disable-next-line unicorn/no-null\n\t\t\tconst val = this.getSetting(name, null);\n\t\t\treturn val ?? undefined;\n\t\t}\n\n\t\tgetSetting<T extends SettingType>(\n\t\t\tsettingName: string,\n\t\t\tdefaultValue: T,\n\t\t\tnamespace?: string,\n\t\t): T {\n\t\t\tconst key = namespace === undefined ? settingName : `${namespace}.${settingName}`;\n\t\t\treturn (this.store[key] as T) ?? defaultValue;\n\t\t}\n\n\t\tSettingsProvider: SettingsProvider = this;\n\t}\n\n\tit(\"Typing - SettingsProvider\", () => {\n\t\tconst settings = {\n\t\t\tnumber: 1,\n\t\t\tsortOfNumber: \"1\",\n\t\t\tbadNumber: \"{1}\",\n\t\t\tstringAndNumber: \"1\",\n\t\t\tstringAndBoolean: \"true\",\n\t\t\tstring: \"string\",\n\t\t\tbadString: [],\n\t\t\tboolean: \"true\",\n\t\t\tbadBoolean: \"truthy\",\n\t\t\tnumberArray: `[1, 2, 3]`,\n\t\t\tbadNumberArray: [\"one\", \"two\", \"three\"],\n\t\t\tstringArray: `[\"1\", \"2\", \"3\"]`,\n\t\t\tbadStringArray: \"1\",\n\t\t\tbooleanArray: [true, false, true],\n\t\t\tbadBooleanArray: [1, 2, 3],\n\t\t\tbadBooleanArray2: [\"true\", \"false\", \"true\"],\n\t\t};\n\n\t\tconst config = new CachedConfigProvider(undefined, new HybridSettingsProvider(settings));\n\n\t\tassert.equal(config.getNumber(\"number\"), 1);\n\t\tassert.equal(config.getNumber(\"sortOfNumber\"), 1);\n\t\tassert.equal(config.getNumber(\"badNumber\"), undefined);\n\n\t\tassert.equal(config.getString(\"stringAndNumber\"), \"1\");\n\t\tassert.equal(config.getString(\"stringAndBoolean\"), \"true\");\n\t\tassert.equal(config.getString(\"string\"), \"string\");\n\t\tassert.equal(config.getString(\"badString\"), undefined);\n\n\t\tassert.equal(config.getBoolean(\"boolean\"), true);\n\t\tassert.equal(config.getBoolean(\"badBoolean\"), undefined);\n\n\t\tassert.deepEqual(config.getNumberArray(\"numberArray\"), [1, 2, 3]);\n\t\tassert.equal(config.getNumberArray(\"badNumberArray\"), undefined);\n\n\t\tassert.deepEqual(config.getStringArray(\"stringArray\"), [\"1\", \"2\", \"3\"]);\n\t\tassert.equal(config.getStringArray(\"badStringArray\"), undefined);\n\n\t\tassert.deepEqual(config.getBooleanArray(\"booleanArray\"), [true, false, true]);\n\t\tassert.equal(config.getBooleanArray(\"badBooleanArray\"), undefined);\n\t\tassert.equal(config.getBooleanArray(\"badBooleanArray2\"), undefined);\n\t});\n\n\t// #endregion SettingsProvider\n});\n\ndescribe(\"wrappedConfigProvider\", () => {\n\tconst configProvider = (featureGates: Record<string, ConfigTypes>): IConfigProviderBase => ({\n\t\tgetRawConfig: (name: string): ConfigTypes => featureGates[name],\n\t});\n\n\tit(\"When there is no original config provider\", () => {\n\t\tconst config = wrapConfigProviderWithDefaults(undefined, { \"Fluid.Feature.Gate\": true });\n\t\tassert.strictEqual(config.getRawConfig(\"Fluid.Feature.Gate\"), true);\n\t});\n\n\tit(\"When the original config provider does not specify the required key\", () => {\n\t\tconst config = wrapConfigProviderWithDefaults(configProvider({}), {\n\t\t\t\"Fluid.Feature.Gate\": true,\n\t\t});\n\t\tassert.strictEqual(config.getRawConfig(\"Fluid.Feature.Gate\"), true);\n\t});\n\n\tit(\"When the original config provider specifies the required key\", () => {\n\t\tconst config = wrapConfigProviderWithDefaults(\n\t\t\tconfigProvider({ \"Fluid.Feature.Gate\": false }),\n\t\t\t{ \"Fluid.Feature.Gate\": true },\n\t\t);\n\t\tassert.strictEqual(config.getRawConfig(\"Fluid.Feature.Gate\"), false);\n\t});\n});\n"]}
|