@fluidframework/test-utils 1.4.0-115997 → 2.0.0-dev-rc.1.0.0.224419
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/.eslintrc.js +8 -7
- package/.mocharc.js +12 -0
- package/CHANGELOG.md +177 -0
- package/README.md +44 -14
- package/api-extractor-lint.json +4 -0
- package/api-extractor.json +2 -2
- package/api-report/test-utils.api.md +395 -0
- package/dist/DriverWrappers.d.ts +32 -0
- package/dist/DriverWrappers.d.ts.map +1 -0
- package/dist/DriverWrappers.js +57 -0
- package/dist/DriverWrappers.js.map +1 -0
- package/dist/TestConfigs.d.ts +10 -0
- package/dist/TestConfigs.d.ts.map +1 -0
- package/dist/TestConfigs.js +17 -0
- package/dist/TestConfigs.js.map +1 -0
- package/dist/TestSummaryUtils.d.ts +61 -0
- package/dist/TestSummaryUtils.d.ts.map +1 -0
- package/dist/TestSummaryUtils.js +135 -0
- package/dist/TestSummaryUtils.js.map +1 -0
- package/dist/containerUtils.d.ts +46 -0
- package/dist/containerUtils.d.ts.map +1 -0
- package/dist/containerUtils.js +85 -0
- package/dist/containerUtils.js.map +1 -0
- package/dist/index.d.ts +14 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +43 -19
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +6 -0
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js.map +1 -1
- package/dist/loaderContainerTracker.d.ts +39 -15
- package/dist/loaderContainerTracker.d.ts.map +1 -1
- package/dist/loaderContainerTracker.js +214 -86
- package/dist/loaderContainerTracker.js.map +1 -1
- package/dist/localCodeLoader.d.ts +9 -2
- package/dist/localCodeLoader.d.ts.map +1 -1
- package/dist/localCodeLoader.js +18 -17
- package/dist/localCodeLoader.js.map +1 -1
- package/dist/localLoader.d.ts +3 -2
- package/dist/localLoader.d.ts.map +1 -1
- package/dist/localLoader.js +2 -0
- package/dist/localLoader.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/retry.d.ts +1 -0
- package/dist/retry.d.ts.map +1 -1
- package/dist/retry.js +3 -2
- package/dist/retry.js.map +1 -1
- package/dist/test-utils-alpha.d.ts +305 -0
- package/dist/test-utils-beta.d.ts +202 -0
- package/dist/test-utils-public.d.ts +202 -0
- package/dist/test-utils-untrimmed.d.ts +1001 -0
- package/dist/testContainerRuntimeFactory.d.ts +4 -2
- package/dist/testContainerRuntimeFactory.d.ts.map +1 -1
- package/dist/testContainerRuntimeFactory.js +67 -12
- package/dist/testContainerRuntimeFactory.js.map +1 -1
- package/dist/testContainerRuntimeFactoryWithDefaultDataStore.d.ts +23 -0
- package/dist/testContainerRuntimeFactoryWithDefaultDataStore.d.ts.map +1 -0
- package/dist/testContainerRuntimeFactoryWithDefaultDataStore.js +32 -0
- package/dist/testContainerRuntimeFactoryWithDefaultDataStore.js.map +1 -0
- package/dist/testFluidObject.d.ts +30 -12
- package/dist/testFluidObject.d.ts.map +1 -1
- package/dist/testFluidObject.js +74 -43
- package/dist/testFluidObject.js.map +1 -1
- package/dist/testObjectProvider.d.ts +298 -41
- package/dist/testObjectProvider.d.ts.map +1 -1
- package/dist/testObjectProvider.js +377 -61
- package/dist/testObjectProvider.js.map +1 -1
- package/dist/timeoutUtils.d.ts +42 -0
- package/dist/timeoutUtils.d.ts.map +1 -1
- package/dist/timeoutUtils.js +142 -9
- package/dist/timeoutUtils.js.map +1 -1
- package/dist/tsdoc-metadata.json +11 -0
- package/lib/test-utils-alpha.d.ts +305 -0
- package/lib/test-utils-beta.d.ts +202 -0
- package/lib/test-utils-public.d.ts +202 -0
- package/lib/test-utils-untrimmed.d.ts +1001 -0
- package/package.json +106 -72
- package/prettier.config.cjs +8 -0
- package/src/DriverWrappers.ts +83 -0
- package/src/TestConfigs.ts +17 -0
- package/src/TestSummaryUtils.ts +210 -0
- package/src/containerUtils.ts +90 -0
- package/src/index.ts +47 -9
- package/src/interfaces.ts +16 -7
- package/src/loaderContainerTracker.ts +754 -534
- package/src/localCodeLoader.ts +87 -86
- package/src/localLoader.ts +27 -26
- package/src/packageVersion.ts +1 -1
- package/src/retry.ts +33 -26
- package/src/testContainerRuntimeFactory.ts +152 -59
- package/src/testContainerRuntimeFactoryWithDefaultDataStore.ts +61 -0
- package/src/testFluidObject.ts +190 -147
- package/src/testObjectProvider.ts +931 -372
- package/src/timeoutUtils.ts +226 -37
- package/tsconfig.json +9 -12
|
@@ -4,9 +4,8 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.getUnexpectedLogErrorException = exports.TestObjectProvider = exports.EventAndErrorTrackingLogger = exports.createDocumentId = exports.DataObjectFactoryType = void 0;
|
|
7
|
+
exports.getUnexpectedLogErrorException = exports.TestObjectProviderWithVersionedLoad = exports.TestObjectProvider = exports.EventAndErrorTrackingLogger = exports.createDocumentId = exports.DataObjectFactoryType = void 0;
|
|
8
8
|
const container_loader_1 = require("@fluidframework/container-loader");
|
|
9
|
-
const driver_utils_1 = require("@fluidframework/driver-utils");
|
|
10
9
|
const uuid_1 = require("uuid");
|
|
11
10
|
const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
|
|
12
11
|
const loaderContainerTracker_1 = require("./loaderContainerTracker");
|
|
@@ -16,11 +15,17 @@ const defaultCodeDetails = {
|
|
|
16
15
|
package: "defaultTestPackage",
|
|
17
16
|
config: {},
|
|
18
17
|
};
|
|
18
|
+
/**
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
19
21
|
var DataObjectFactoryType;
|
|
20
22
|
(function (DataObjectFactoryType) {
|
|
21
23
|
DataObjectFactoryType[DataObjectFactoryType["Primed"] = 0] = "Primed";
|
|
22
24
|
DataObjectFactoryType[DataObjectFactoryType["Test"] = 1] = "Test";
|
|
23
|
-
})(DataObjectFactoryType
|
|
25
|
+
})(DataObjectFactoryType || (exports.DataObjectFactoryType = DataObjectFactoryType = {}));
|
|
26
|
+
/**
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
24
29
|
const createDocumentId = () => (0, uuid_1.v4)();
|
|
25
30
|
exports.createDocumentId = createDocumentId;
|
|
26
31
|
/**
|
|
@@ -34,18 +39,20 @@ function getDocumentIdStrategy(type) {
|
|
|
34
39
|
return {
|
|
35
40
|
get: () => documentId,
|
|
36
41
|
update: () => { },
|
|
37
|
-
reset: () => {
|
|
42
|
+
reset: () => {
|
|
43
|
+
documentId = (0, exports.createDocumentId)();
|
|
44
|
+
},
|
|
38
45
|
};
|
|
39
46
|
default:
|
|
40
47
|
return {
|
|
41
48
|
get: () => documentId,
|
|
42
49
|
update: (resolvedUrl) => {
|
|
43
|
-
var _a;
|
|
44
50
|
// Extract the document ID from the resolved container's URL and reset the ID property
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
documentId = resolvedUrl?.id ?? documentId;
|
|
52
|
+
},
|
|
53
|
+
reset: () => {
|
|
54
|
+
documentId = (0, exports.createDocumentId)();
|
|
47
55
|
},
|
|
48
|
-
reset: () => { documentId = (0, exports.createDocumentId)(); },
|
|
49
56
|
};
|
|
50
57
|
}
|
|
51
58
|
}
|
|
@@ -54,11 +61,24 @@ function getDocumentIdStrategy(type) {
|
|
|
54
61
|
* It also tracks all unexpected errors.
|
|
55
62
|
* At any point you call reportAndClearTrackedEvents which will provide all unexpected errors, and
|
|
56
63
|
* any expected events that have not occurred.
|
|
64
|
+
* @internal
|
|
57
65
|
*/
|
|
58
|
-
class EventAndErrorTrackingLogger
|
|
66
|
+
class EventAndErrorTrackingLogger {
|
|
59
67
|
constructor(baseLogger) {
|
|
60
|
-
super();
|
|
61
68
|
this.baseLogger = baseLogger;
|
|
69
|
+
/**
|
|
70
|
+
* Even if these error events are logged, tests should still be allowed to pass
|
|
71
|
+
* Additionally, if downgrade is true, then log as generic (e.g. to avoid polluting the e2e test logs)
|
|
72
|
+
*/
|
|
73
|
+
this.allowedErrors = [
|
|
74
|
+
// This log was removed in current version as unnecessary, but it's still present in previous versions
|
|
75
|
+
{
|
|
76
|
+
eventName: "fluid:telemetry:Container:NoRealStorageInDetachedContainer",
|
|
77
|
+
downgrade: true,
|
|
78
|
+
},
|
|
79
|
+
// This log's category changes depending on the op latency. test results shouldn't be affected but if we see lots we'd like an alert from the logs.
|
|
80
|
+
{ eventName: "fluid:telemetry:OpPerf:OpRoundtripTime" },
|
|
81
|
+
];
|
|
62
82
|
this.expectedEvents = [];
|
|
63
83
|
this.unexpectedErrors = [];
|
|
64
84
|
}
|
|
@@ -66,15 +86,14 @@ class EventAndErrorTrackingLogger extends telemetry_utils_1.TelemetryLogger {
|
|
|
66
86
|
if (this.expectedEvents.length !== 0) {
|
|
67
87
|
// we don't have to error here. just no reason not to. given the events must be
|
|
68
88
|
// ordered it could be tricky to figure out problems around multiple registrations.
|
|
69
|
-
throw new Error("Expected events already registered.\n"
|
|
70
|
-
|
|
89
|
+
throw new Error("Expected events already registered.\n" +
|
|
90
|
+
"Call reportAndClearTrackedEvents to clear them before registering more");
|
|
71
91
|
}
|
|
72
92
|
this.expectedEvents.push(...orderedExpectedEvents.map((event, index) => ({ index, event })));
|
|
73
93
|
}
|
|
74
94
|
send(event) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if ((ee === null || ee === void 0 ? void 0 : ee.eventName) === event.eventName) {
|
|
95
|
+
const ee = this.expectedEvents[0]?.event;
|
|
96
|
+
if (ee?.eventName === event.eventName) {
|
|
78
97
|
let matches = true;
|
|
79
98
|
for (const key of Object.keys(ee)) {
|
|
80
99
|
if (ee[key] !== event[key]) {
|
|
@@ -95,7 +114,14 @@ class EventAndErrorTrackingLogger extends telemetry_utils_1.TelemetryLogger {
|
|
|
95
114
|
}
|
|
96
115
|
}
|
|
97
116
|
if (event.category === "error") {
|
|
98
|
-
this
|
|
117
|
+
// Check to see if this error is allowed and if its category should be downgraded
|
|
118
|
+
const allowedError = this.allowedErrors.find(({ eventName }) => eventName === event.eventName);
|
|
119
|
+
if (allowedError === undefined) {
|
|
120
|
+
this.unexpectedErrors.push(event);
|
|
121
|
+
}
|
|
122
|
+
else if (allowedError.downgrade) {
|
|
123
|
+
event.category = "generic";
|
|
124
|
+
}
|
|
99
125
|
}
|
|
100
126
|
this.baseLogger.send(event);
|
|
101
127
|
}
|
|
@@ -111,6 +137,7 @@ class EventAndErrorTrackingLogger extends telemetry_utils_1.TelemetryLogger {
|
|
|
111
137
|
exports.EventAndErrorTrackingLogger = EventAndErrorTrackingLogger;
|
|
112
138
|
/**
|
|
113
139
|
* Shared base class for test object provider. Contain code for loader and container creation and loading
|
|
140
|
+
* @internal
|
|
114
141
|
*/
|
|
115
142
|
class TestObjectProvider {
|
|
116
143
|
/**
|
|
@@ -118,76 +145,104 @@ class TestObjectProvider {
|
|
|
118
145
|
* @param createFluidEntryPoint - callback to create a fluidEntryPoint, with an optional set of channel name
|
|
119
146
|
* and factory for TestFluidObject
|
|
120
147
|
*/
|
|
121
|
-
constructor(LoaderConstructor,
|
|
148
|
+
constructor(LoaderConstructor,
|
|
149
|
+
/**
|
|
150
|
+
* {@inheritDoc ITestObjectProvider.driver}
|
|
151
|
+
*/
|
|
152
|
+
driver,
|
|
153
|
+
/**
|
|
154
|
+
* {@inheritDoc ITestObjectProvider.createFluidEntryPoint}
|
|
155
|
+
*/
|
|
156
|
+
createFluidEntryPoint) {
|
|
122
157
|
this.LoaderConstructor = LoaderConstructor;
|
|
123
158
|
this.driver = driver;
|
|
124
159
|
this.createFluidEntryPoint = createFluidEntryPoint;
|
|
160
|
+
/**
|
|
161
|
+
* {@inheritDoc ITestObjectProvider."type"}
|
|
162
|
+
*/
|
|
163
|
+
this.type = "TestObjectProvider";
|
|
125
164
|
this._loaderContainerTracker = new loaderContainerTracker_1.LoaderContainerTracker();
|
|
126
165
|
// Since documentId doesn't change we can only create/make one container. Call the load functions instead.
|
|
127
166
|
this._documentCreated = false;
|
|
128
167
|
this._documentIdStrategy = getDocumentIdStrategy(driver.type);
|
|
129
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* {@inheritDoc ITestObjectProvider.logger}
|
|
171
|
+
*/
|
|
130
172
|
get logger() {
|
|
131
173
|
if (this._logger === undefined) {
|
|
132
|
-
this._logger = new EventAndErrorTrackingLogger(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
174
|
+
this._logger = new EventAndErrorTrackingLogger((0, telemetry_utils_1.createChildLogger)({
|
|
175
|
+
logger: getTestLogger?.(),
|
|
176
|
+
properties: {
|
|
177
|
+
all: {
|
|
178
|
+
driverType: this.driver.type,
|
|
179
|
+
driverEndpointName: this.driver.endpointName,
|
|
180
|
+
driverTenantName: this.driver.tenantName,
|
|
181
|
+
driverUserIndex: this.driver.userIndex,
|
|
182
|
+
},
|
|
138
183
|
},
|
|
139
184
|
}));
|
|
140
185
|
}
|
|
141
186
|
return this._logger;
|
|
142
187
|
}
|
|
188
|
+
set logger(logger) {
|
|
189
|
+
this._logger = logger;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* {@inheritDoc ITestObjectProvider.documentServiceFactory}
|
|
193
|
+
*/
|
|
143
194
|
get documentServiceFactory() {
|
|
144
195
|
if (!this._documentServiceFactory) {
|
|
145
196
|
this._documentServiceFactory = this.driver.createDocumentServiceFactory();
|
|
146
197
|
}
|
|
147
198
|
return this._documentServiceFactory;
|
|
148
199
|
}
|
|
200
|
+
/**
|
|
201
|
+
* {@inheritDoc ITestObjectProvider.urlResolver}
|
|
202
|
+
*/
|
|
149
203
|
get urlResolver() {
|
|
150
204
|
if (!this._urlResolver) {
|
|
151
205
|
this._urlResolver = this.driver.createUrlResolver();
|
|
152
206
|
}
|
|
153
207
|
return this._urlResolver;
|
|
154
208
|
}
|
|
209
|
+
/**
|
|
210
|
+
* {@inheritDoc ITestObjectProvider.documentId}
|
|
211
|
+
*/
|
|
155
212
|
get documentId() {
|
|
156
213
|
return this._documentIdStrategy.get();
|
|
157
214
|
}
|
|
215
|
+
/**
|
|
216
|
+
* {@inheritDoc ITestObjectProvider.defaultCodeDetails}
|
|
217
|
+
*/
|
|
158
218
|
get defaultCodeDetails() {
|
|
159
219
|
return defaultCodeDetails;
|
|
160
220
|
}
|
|
221
|
+
/**
|
|
222
|
+
* {@inheritDoc ITestObjectProvider.opProcessingController}
|
|
223
|
+
*/
|
|
161
224
|
get opProcessingController() {
|
|
162
225
|
return this._loaderContainerTracker;
|
|
163
226
|
}
|
|
164
227
|
/**
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
* Only the version of the loader will vary based on compat config. The version of
|
|
168
|
-
* containerRuntime/dataRuntime used in fluidEntryPoint will be used as is from what is passed in.
|
|
169
|
-
*
|
|
170
|
-
* @param packageEntries - list of code details and fluidEntryPoint pairs.
|
|
228
|
+
* {@inheritDoc ITestObjectProvider.createLoader}
|
|
171
229
|
*/
|
|
172
230
|
createLoader(packageEntries, loaderProps) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
231
|
+
const logger = (0, telemetry_utils_1.createMultiSinkLogger)({
|
|
232
|
+
loggers: [this.logger, loaderProps?.logger],
|
|
233
|
+
});
|
|
234
|
+
const loader = new this.LoaderConstructor({
|
|
235
|
+
...loaderProps,
|
|
236
|
+
logger,
|
|
237
|
+
codeLoader: loaderProps?.codeLoader ?? new localCodeLoader_1.LocalCodeLoader(packageEntries),
|
|
238
|
+
urlResolver: loaderProps?.urlResolver ?? this.urlResolver,
|
|
239
|
+
documentServiceFactory: loaderProps?.documentServiceFactory ?? this.documentServiceFactory,
|
|
240
|
+
});
|
|
180
241
|
this._loaderContainerTracker.add(loader);
|
|
181
242
|
return loader;
|
|
182
243
|
}
|
|
183
244
|
/**
|
|
184
|
-
*
|
|
185
|
-
* Container created is automatically added to the OpProcessingController to manage op flow
|
|
186
|
-
*
|
|
187
|
-
* Only the version of the loader will vary based on compat config. The version of
|
|
188
|
-
* containerRuntime/dataRuntime used in fluidEntryPoint will be used as is from what is passed in.
|
|
189
|
-
*
|
|
190
|
-
* @param packageEntries - list of code details and fluidEntryPoint pairs.
|
|
245
|
+
* {@inheritDoc ITestObjectProvider.createContainer}
|
|
191
246
|
*/
|
|
192
247
|
async createContainer(entryPoint, loaderProps) {
|
|
193
248
|
if (this._documentCreated) {
|
|
@@ -201,22 +256,27 @@ class TestObjectProvider {
|
|
|
201
256
|
this._documentIdStrategy.update(container.resolvedUrl);
|
|
202
257
|
return container;
|
|
203
258
|
}
|
|
259
|
+
/**
|
|
260
|
+
* {@inheritDoc ITestObjectProvider.loadContainer}
|
|
261
|
+
*/
|
|
204
262
|
async loadContainer(entryPoint, loaderProps, requestHeader) {
|
|
205
263
|
const loader = this.createLoader([[defaultCodeDetails, entryPoint]], loaderProps);
|
|
206
|
-
return
|
|
264
|
+
return this.resolveContainer(loader, requestHeader);
|
|
265
|
+
}
|
|
266
|
+
async resolveContainer(loader, headers) {
|
|
267
|
+
return loader.resolve({
|
|
268
|
+
url: await this.driver.createContainerUrl(this.documentId),
|
|
269
|
+
headers,
|
|
270
|
+
});
|
|
207
271
|
}
|
|
208
272
|
/**
|
|
209
|
-
*
|
|
210
|
-
* The version of the loader/containerRuntime/dataRuntime may vary based on compat config of the current run
|
|
211
|
-
* @param testContainerConfig - optional configuring the test Container
|
|
273
|
+
* {@inheritDoc ITestObjectProvider.makeTestLoader}
|
|
212
274
|
*/
|
|
213
275
|
makeTestLoader(testContainerConfig) {
|
|
214
|
-
return this.createLoader([[defaultCodeDetails, this.createFluidEntryPoint(testContainerConfig)]], testContainerConfig
|
|
276
|
+
return this.createLoader([[defaultCodeDetails, this.createFluidEntryPoint(testContainerConfig)]], testContainerConfig?.loaderProps);
|
|
215
277
|
}
|
|
216
278
|
/**
|
|
217
|
-
*
|
|
218
|
-
* Container loaded is automatically added to the OpProcessingController to manage op flow
|
|
219
|
-
* @param testContainerConfig - optional configuring the test Container
|
|
279
|
+
* {@inheritDoc ITestObjectProvider.makeTestContainer}
|
|
220
280
|
*/
|
|
221
281
|
async makeTestContainer(testContainerConfig) {
|
|
222
282
|
if (this._documentCreated) {
|
|
@@ -231,20 +291,17 @@ class TestObjectProvider {
|
|
|
231
291
|
return container;
|
|
232
292
|
}
|
|
233
293
|
/**
|
|
234
|
-
*
|
|
235
|
-
* IContainer loaded is automatically added to the OpProcessingController to manage op flow
|
|
236
|
-
* @param testContainerConfig - optional configuring the test Container
|
|
237
|
-
* @param requestHeader - optional headers to be supplied to the loader
|
|
294
|
+
* {@inheritDoc ITestObjectProvider.loadTestContainer}
|
|
238
295
|
*/
|
|
239
296
|
async loadTestContainer(testContainerConfig, requestHeader) {
|
|
240
297
|
const loader = this.makeTestLoader(testContainerConfig);
|
|
241
|
-
const container = await
|
|
242
|
-
url: await this.driver.createContainerUrl(this.documentId),
|
|
243
|
-
headers: requestHeader,
|
|
244
|
-
});
|
|
298
|
+
const container = await this.resolveContainer(loader, requestHeader);
|
|
245
299
|
await this.waitContainerToCatchUp(container);
|
|
246
300
|
return container;
|
|
247
301
|
}
|
|
302
|
+
/**
|
|
303
|
+
* {@inheritDoc ITestObjectProvider.reset}
|
|
304
|
+
*/
|
|
248
305
|
reset() {
|
|
249
306
|
this._loaderContainerTracker.reset();
|
|
250
307
|
this._documentServiceFactory = undefined;
|
|
@@ -257,6 +314,9 @@ class TestObjectProvider {
|
|
|
257
314
|
this._logger = undefined;
|
|
258
315
|
this._documentCreated = false;
|
|
259
316
|
}
|
|
317
|
+
/**
|
|
318
|
+
* {@inheritDoc ITestObjectProvider.ensureSynchronized}
|
|
319
|
+
*/
|
|
260
320
|
async ensureSynchronized() {
|
|
261
321
|
return this._loaderContainerTracker.ensureSynchronized();
|
|
262
322
|
}
|
|
@@ -270,25 +330,281 @@ class TestObjectProvider {
|
|
|
270
330
|
}
|
|
271
331
|
return (0, container_loader_1.waitContainerToCatchUp)(container);
|
|
272
332
|
}
|
|
333
|
+
/**
|
|
334
|
+
* {@inheritDoc ITestObjectProvider.updateDocumentId}
|
|
335
|
+
*/
|
|
273
336
|
updateDocumentId(resolvedUrl) {
|
|
274
337
|
this._documentIdStrategy.update(resolvedUrl);
|
|
275
338
|
}
|
|
339
|
+
/**
|
|
340
|
+
* {@inheritDoc ITestObjectProvider.resetLoaderContainerTracker}
|
|
341
|
+
*/
|
|
276
342
|
resetLoaderContainerTracker(syncSummarizerClients = false) {
|
|
277
343
|
this._loaderContainerTracker.reset();
|
|
278
344
|
this._loaderContainerTracker = new loaderContainerTracker_1.LoaderContainerTracker(syncSummarizerClients);
|
|
279
345
|
}
|
|
280
346
|
}
|
|
281
347
|
exports.TestObjectProvider = TestObjectProvider;
|
|
348
|
+
/**
|
|
349
|
+
* Implements {@link ITestObjectProvider}, but uses different versions to create and load containers.
|
|
350
|
+
*
|
|
351
|
+
* @internal
|
|
352
|
+
*/
|
|
353
|
+
class TestObjectProviderWithVersionedLoad {
|
|
354
|
+
constructor(LoaderConstructorForCreating, LoaderConstructorForLoading, driverForCreating, driverForLoading, createFluidEntryPointForCreating, createFluidEntryPointForLoading) {
|
|
355
|
+
this.LoaderConstructorForCreating = LoaderConstructorForCreating;
|
|
356
|
+
this.LoaderConstructorForLoading = LoaderConstructorForLoading;
|
|
357
|
+
this.driverForCreating = driverForCreating;
|
|
358
|
+
this.driverForLoading = driverForLoading;
|
|
359
|
+
this.createFluidEntryPointForCreating = createFluidEntryPointForCreating;
|
|
360
|
+
this.createFluidEntryPointForLoading = createFluidEntryPointForLoading;
|
|
361
|
+
/**
|
|
362
|
+
* {@inheritDoc ITestObjectProvider."type"}
|
|
363
|
+
*/
|
|
364
|
+
this.type = "TestObjectProviderWithVersionedLoad";
|
|
365
|
+
this._loaderContainerTracker = new loaderContainerTracker_1.LoaderContainerTracker();
|
|
366
|
+
// Since documentId doesn't change we can only create/make one container. Call the load functions instead.
|
|
367
|
+
this._documentCreated = false;
|
|
368
|
+
/**
|
|
369
|
+
* `_loadCount` is used to alternate which version we load the next container with.
|
|
370
|
+
* loadCount is even then we will load with the "create" version, and if odd we load with the "load" version.
|
|
371
|
+
* After each test we will reset loadCount to 0 to ensure we always create the first container with the create version.
|
|
372
|
+
*
|
|
373
|
+
* Note: This will only affect tests that load a container more than two times.
|
|
374
|
+
*/
|
|
375
|
+
this._loadCount = 0;
|
|
376
|
+
this._documentIdStrategy = getDocumentIdStrategy(driverForCreating.type);
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* {@inheritDoc ITestObjectProvider.logger}
|
|
380
|
+
*/
|
|
381
|
+
get logger() {
|
|
382
|
+
if (this._logger === undefined) {
|
|
383
|
+
this._logger = new EventAndErrorTrackingLogger((0, telemetry_utils_1.createChildLogger)({
|
|
384
|
+
logger: getTestLogger?.(),
|
|
385
|
+
}));
|
|
386
|
+
}
|
|
387
|
+
return this._logger;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* {@inheritDoc ITestObjectProvider.documentServiceFactory}
|
|
391
|
+
*/
|
|
392
|
+
get documentServiceFactory() {
|
|
393
|
+
if (!this._documentServiceFactory) {
|
|
394
|
+
this._documentServiceFactory = this.driverForCreating.createDocumentServiceFactory();
|
|
395
|
+
}
|
|
396
|
+
return this._documentServiceFactory;
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* {@inheritDoc ITestObjectProvider.urlResolver}
|
|
400
|
+
*/
|
|
401
|
+
get urlResolver() {
|
|
402
|
+
if (!this._urlResolver) {
|
|
403
|
+
this._urlResolver = this.driverForCreating.createUrlResolver();
|
|
404
|
+
}
|
|
405
|
+
return this._urlResolver;
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* {@inheritDoc ITestObjectProvider.documentId}
|
|
409
|
+
*/
|
|
410
|
+
get documentId() {
|
|
411
|
+
return this._documentIdStrategy.get();
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* {@inheritDoc ITestObjectProvider.defaultCodeDetails}
|
|
415
|
+
*/
|
|
416
|
+
get defaultCodeDetails() {
|
|
417
|
+
return defaultCodeDetails;
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* {@inheritDoc ITestObjectProvider.opProcessingController}
|
|
421
|
+
*/
|
|
422
|
+
get opProcessingController() {
|
|
423
|
+
return this._loaderContainerTracker;
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* {@inheritDoc ITestObjectProvider.driver}
|
|
427
|
+
*/
|
|
428
|
+
get driver() {
|
|
429
|
+
return this.nextLoaderShouldCreate() ? this.driverForCreating : this.driverForLoading;
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* {@inheritDoc ITestObjectProvider.createFluidEntryPoint}
|
|
433
|
+
*/
|
|
434
|
+
get createFluidEntryPoint() {
|
|
435
|
+
return this.nextLoaderShouldCreate()
|
|
436
|
+
? this.createFluidEntryPointForCreating
|
|
437
|
+
: this.createFluidEntryPointForLoading;
|
|
438
|
+
}
|
|
439
|
+
createLoaderForCreating(packageEntries, loaderProps) {
|
|
440
|
+
const logger = (0, telemetry_utils_1.createMultiSinkLogger)({
|
|
441
|
+
loggers: [this.logger, loaderProps?.logger],
|
|
442
|
+
});
|
|
443
|
+
const loader = new this.LoaderConstructorForCreating({
|
|
444
|
+
...loaderProps,
|
|
445
|
+
logger,
|
|
446
|
+
codeLoader: loaderProps?.codeLoader ?? new localCodeLoader_1.LocalCodeLoader(packageEntries),
|
|
447
|
+
urlResolver: loaderProps?.urlResolver ?? this.urlResolver,
|
|
448
|
+
documentServiceFactory: loaderProps?.documentServiceFactory ?? this.documentServiceFactory,
|
|
449
|
+
});
|
|
450
|
+
this._loaderContainerTracker.add(loader);
|
|
451
|
+
return loader;
|
|
452
|
+
}
|
|
453
|
+
createLoaderForLoading(packageEntries, loaderProps) {
|
|
454
|
+
const logger = (0, telemetry_utils_1.createMultiSinkLogger)({
|
|
455
|
+
loggers: [this.logger, loaderProps?.logger],
|
|
456
|
+
});
|
|
457
|
+
const loader = new this.LoaderConstructorForLoading({
|
|
458
|
+
...loaderProps,
|
|
459
|
+
logger,
|
|
460
|
+
codeLoader: loaderProps?.codeLoader ?? new localCodeLoader_1.LocalCodeLoader(packageEntries),
|
|
461
|
+
urlResolver: loaderProps?.urlResolver ?? this.urlResolver,
|
|
462
|
+
documentServiceFactory: loaderProps?.documentServiceFactory ?? this.documentServiceFactory,
|
|
463
|
+
});
|
|
464
|
+
this._loaderContainerTracker.add(loader);
|
|
465
|
+
return loader;
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* {@inheritDoc ITestObjectProvider.createLoader}
|
|
469
|
+
*/
|
|
470
|
+
createLoader(packageEntries, loaderProps) {
|
|
471
|
+
return this.nextLoaderShouldCreate(/** increment */ true)
|
|
472
|
+
? this.createLoaderForCreating(packageEntries, loaderProps)
|
|
473
|
+
: this.createLoaderForLoading(packageEntries, loaderProps);
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* {@inheritDoc ITestObjectProvider.createContainer}
|
|
477
|
+
*/
|
|
478
|
+
async createContainer(entryPoint, loaderProps) {
|
|
479
|
+
if (this._documentCreated) {
|
|
480
|
+
throw new Error("Only one container/document can be created. To load the container/document use loadContainer");
|
|
481
|
+
}
|
|
482
|
+
const loader = this.createLoader([[defaultCodeDetails, entryPoint]], loaderProps);
|
|
483
|
+
const container = await (0, localLoader_1.createAndAttachContainer)(defaultCodeDetails, loader, this.driverForCreating.createCreateNewRequest(this.documentId));
|
|
484
|
+
this._documentCreated = true;
|
|
485
|
+
// r11s driver will generate a new ID for the new container.
|
|
486
|
+
// update the document ID with the actual ID of the attached container.
|
|
487
|
+
this._documentIdStrategy.update(container.resolvedUrl);
|
|
488
|
+
return container;
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* {@inheritDoc ITestObjectProvider.loadContainer}
|
|
492
|
+
*/
|
|
493
|
+
async loadContainer(entryPoint, loaderProps, requestHeader) {
|
|
494
|
+
const driver = this.nextLoaderShouldCreate()
|
|
495
|
+
? this.driverForCreating
|
|
496
|
+
: this.driverForLoading;
|
|
497
|
+
const loader = this.createLoader([[defaultCodeDetails, entryPoint]], loaderProps);
|
|
498
|
+
return this.resolveContainer(loader, requestHeader, driver);
|
|
499
|
+
}
|
|
500
|
+
async resolveContainer(loader, headers, driver) {
|
|
501
|
+
return loader.resolve({
|
|
502
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
503
|
+
url: await driver.createContainerUrl(this.documentId),
|
|
504
|
+
headers,
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* {@inheritDoc ITestObjectProvider.makeTestLoader}
|
|
509
|
+
*/
|
|
510
|
+
makeTestLoader(testContainerConfig) {
|
|
511
|
+
return this.createLoader([[defaultCodeDetails, this.createFluidEntryPoint(testContainerConfig)]], testContainerConfig?.loaderProps);
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* {@inheritDoc ITestObjectProvider.makeTestContainer}
|
|
515
|
+
*/
|
|
516
|
+
async makeTestContainer(testContainerConfig) {
|
|
517
|
+
if (this._documentCreated) {
|
|
518
|
+
throw new Error("Only one container/document can be created. To load the container/document use loadTestContainer");
|
|
519
|
+
}
|
|
520
|
+
const loader = this.createLoader([[defaultCodeDetails, this.createFluidEntryPoint(testContainerConfig)]], testContainerConfig?.loaderProps);
|
|
521
|
+
const container = await (0, localLoader_1.createAndAttachContainer)(defaultCodeDetails, loader, this.driverForCreating.createCreateNewRequest(this.documentId));
|
|
522
|
+
this._documentCreated = true;
|
|
523
|
+
// r11s driver will generate a new ID for the new container.
|
|
524
|
+
// update the document ID with the actual ID of the attached container.
|
|
525
|
+
this._documentIdStrategy.update(container.resolvedUrl);
|
|
526
|
+
return container;
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* {@inheritDoc ITestObjectProvider.loadTestContainer}
|
|
530
|
+
*/
|
|
531
|
+
async loadTestContainer(testContainerConfig, requestHeader) {
|
|
532
|
+
// Keep track of which Loader we are about to use so we can pass the correct driver through
|
|
533
|
+
const driver = this.nextLoaderShouldCreate()
|
|
534
|
+
? this.driverForCreating
|
|
535
|
+
: this.driverForLoading;
|
|
536
|
+
const loader = this.makeTestLoader(testContainerConfig);
|
|
537
|
+
const container = await this.resolveContainer(loader, requestHeader, driver);
|
|
538
|
+
await this.waitContainerToCatchUp(container);
|
|
539
|
+
return container;
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* {@inheritDoc ITestObjectProvider.reset}
|
|
543
|
+
*/
|
|
544
|
+
reset() {
|
|
545
|
+
this._loadCount = 0;
|
|
546
|
+
this._loaderContainerTracker.reset();
|
|
547
|
+
this._logger = undefined;
|
|
548
|
+
this._documentServiceFactory = undefined;
|
|
549
|
+
this._urlResolver = undefined;
|
|
550
|
+
this._documentIdStrategy.reset();
|
|
551
|
+
const logError = getUnexpectedLogErrorException(this._logger);
|
|
552
|
+
if (logError) {
|
|
553
|
+
throw logError;
|
|
554
|
+
}
|
|
555
|
+
this._documentCreated = false;
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* {@inheritDoc ITestObjectProvider.ensureSynchronized}
|
|
559
|
+
*/
|
|
560
|
+
async ensureSynchronized() {
|
|
561
|
+
return this._loaderContainerTracker.ensureSynchronized();
|
|
562
|
+
}
|
|
563
|
+
async waitContainerToCatchUp(container) {
|
|
564
|
+
// The original waitContainerToCatchUp() from container loader uses either Container.resume()
|
|
565
|
+
// or Container.connect() as part of its implementation. However, resume() was deprecated
|
|
566
|
+
// and eventually replaced with connect(). To avoid issues during LTS compatibility testing
|
|
567
|
+
// with older container versions issues, we use resume() when connect() is unavailable.
|
|
568
|
+
if (container.connect === undefined) {
|
|
569
|
+
container.connect = container.resume;
|
|
570
|
+
}
|
|
571
|
+
return (0, container_loader_1.waitContainerToCatchUp)(container);
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* {@inheritDoc ITestObjectProvider.updateDocumentId}
|
|
575
|
+
*/
|
|
576
|
+
updateDocumentId(resolvedUrl) {
|
|
577
|
+
this._documentIdStrategy.update(resolvedUrl);
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* {@inheritDoc ITestObjectProvider.resetLoaderContainerTracker}
|
|
581
|
+
*/
|
|
582
|
+
resetLoaderContainerTracker(syncSummarizerClients = false) {
|
|
583
|
+
this._loaderContainerTracker.reset();
|
|
584
|
+
this._loaderContainerTracker = new loaderContainerTracker_1.LoaderContainerTracker(syncSummarizerClients);
|
|
585
|
+
}
|
|
586
|
+
nextLoaderShouldCreate(increment = false) {
|
|
587
|
+
const shouldCreate = this._loadCount % 2 === 0;
|
|
588
|
+
if (increment) {
|
|
589
|
+
this._loadCount++;
|
|
590
|
+
}
|
|
591
|
+
return shouldCreate;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
exports.TestObjectProviderWithVersionedLoad = TestObjectProviderWithVersionedLoad;
|
|
595
|
+
/**
|
|
596
|
+
* @internal
|
|
597
|
+
*/
|
|
282
598
|
function getUnexpectedLogErrorException(logger, prefix) {
|
|
283
599
|
if (logger === undefined) {
|
|
284
600
|
return;
|
|
285
601
|
}
|
|
286
602
|
const results = logger.reportAndClearTrackedEvents();
|
|
287
603
|
if (results.unexpectedErrors.length > 0) {
|
|
288
|
-
return new Error(`${prefix
|
|
604
|
+
return new Error(`${prefix ?? ""}Unexpected Errors in Logs:\n${JSON.stringify(results.unexpectedErrors, undefined, 2)}`);
|
|
289
605
|
}
|
|
290
606
|
if (results.expectedNotFound.length > 0) {
|
|
291
|
-
return new Error(`${prefix
|
|
607
|
+
return new Error(`${prefix ?? ""}Expected Events not found:\n${JSON.stringify(results.expectedNotFound, undefined, 2)}`);
|
|
292
608
|
}
|
|
293
609
|
}
|
|
294
610
|
exports.getUnexpectedLogErrorException = getUnexpectedLogErrorException;
|