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