@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.
Files changed (98) hide show
  1. package/.eslintrc.js +8 -7
  2. package/.mocharc.js +12 -0
  3. package/CHANGELOG.md +177 -0
  4. package/README.md +44 -14
  5. package/api-extractor-lint.json +4 -0
  6. package/api-extractor.json +2 -2
  7. package/api-report/test-utils.api.md +395 -0
  8. package/dist/DriverWrappers.d.ts +32 -0
  9. package/dist/DriverWrappers.d.ts.map +1 -0
  10. package/dist/DriverWrappers.js +57 -0
  11. package/dist/DriverWrappers.js.map +1 -0
  12. package/dist/TestConfigs.d.ts +10 -0
  13. package/dist/TestConfigs.d.ts.map +1 -0
  14. package/dist/TestConfigs.js +17 -0
  15. package/dist/TestConfigs.js.map +1 -0
  16. package/dist/TestSummaryUtils.d.ts +61 -0
  17. package/dist/TestSummaryUtils.d.ts.map +1 -0
  18. package/dist/TestSummaryUtils.js +135 -0
  19. package/dist/TestSummaryUtils.js.map +1 -0
  20. package/dist/containerUtils.d.ts +46 -0
  21. package/dist/containerUtils.d.ts.map +1 -0
  22. package/dist/containerUtils.js +85 -0
  23. package/dist/containerUtils.js.map +1 -0
  24. package/dist/index.d.ts +14 -9
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +43 -19
  27. package/dist/index.js.map +1 -1
  28. package/dist/interfaces.d.ts +6 -0
  29. package/dist/interfaces.d.ts.map +1 -1
  30. package/dist/interfaces.js.map +1 -1
  31. package/dist/loaderContainerTracker.d.ts +39 -15
  32. package/dist/loaderContainerTracker.d.ts.map +1 -1
  33. package/dist/loaderContainerTracker.js +214 -86
  34. package/dist/loaderContainerTracker.js.map +1 -1
  35. package/dist/localCodeLoader.d.ts +9 -2
  36. package/dist/localCodeLoader.d.ts.map +1 -1
  37. package/dist/localCodeLoader.js +18 -17
  38. package/dist/localCodeLoader.js.map +1 -1
  39. package/dist/localLoader.d.ts +3 -2
  40. package/dist/localLoader.d.ts.map +1 -1
  41. package/dist/localLoader.js +2 -0
  42. package/dist/localLoader.js.map +1 -1
  43. package/dist/packageVersion.d.ts +1 -1
  44. package/dist/packageVersion.d.ts.map +1 -1
  45. package/dist/packageVersion.js +1 -1
  46. package/dist/packageVersion.js.map +1 -1
  47. package/dist/retry.d.ts +1 -0
  48. package/dist/retry.d.ts.map +1 -1
  49. package/dist/retry.js +3 -2
  50. package/dist/retry.js.map +1 -1
  51. package/dist/test-utils-alpha.d.ts +305 -0
  52. package/dist/test-utils-beta.d.ts +202 -0
  53. package/dist/test-utils-public.d.ts +202 -0
  54. package/dist/test-utils-untrimmed.d.ts +1001 -0
  55. package/dist/testContainerRuntimeFactory.d.ts +4 -2
  56. package/dist/testContainerRuntimeFactory.d.ts.map +1 -1
  57. package/dist/testContainerRuntimeFactory.js +67 -12
  58. package/dist/testContainerRuntimeFactory.js.map +1 -1
  59. package/dist/testContainerRuntimeFactoryWithDefaultDataStore.d.ts +23 -0
  60. package/dist/testContainerRuntimeFactoryWithDefaultDataStore.d.ts.map +1 -0
  61. package/dist/testContainerRuntimeFactoryWithDefaultDataStore.js +32 -0
  62. package/dist/testContainerRuntimeFactoryWithDefaultDataStore.js.map +1 -0
  63. package/dist/testFluidObject.d.ts +30 -12
  64. package/dist/testFluidObject.d.ts.map +1 -1
  65. package/dist/testFluidObject.js +74 -43
  66. package/dist/testFluidObject.js.map +1 -1
  67. package/dist/testObjectProvider.d.ts +298 -41
  68. package/dist/testObjectProvider.d.ts.map +1 -1
  69. package/dist/testObjectProvider.js +377 -61
  70. package/dist/testObjectProvider.js.map +1 -1
  71. package/dist/timeoutUtils.d.ts +42 -0
  72. package/dist/timeoutUtils.d.ts.map +1 -1
  73. package/dist/timeoutUtils.js +142 -9
  74. package/dist/timeoutUtils.js.map +1 -1
  75. package/dist/tsdoc-metadata.json +11 -0
  76. package/lib/test-utils-alpha.d.ts +305 -0
  77. package/lib/test-utils-beta.d.ts +202 -0
  78. package/lib/test-utils-public.d.ts +202 -0
  79. package/lib/test-utils-untrimmed.d.ts +1001 -0
  80. package/package.json +106 -72
  81. package/prettier.config.cjs +8 -0
  82. package/src/DriverWrappers.ts +83 -0
  83. package/src/TestConfigs.ts +17 -0
  84. package/src/TestSummaryUtils.ts +210 -0
  85. package/src/containerUtils.ts +90 -0
  86. package/src/index.ts +47 -9
  87. package/src/interfaces.ts +16 -7
  88. package/src/loaderContainerTracker.ts +754 -534
  89. package/src/localCodeLoader.ts +87 -86
  90. package/src/localLoader.ts +27 -26
  91. package/src/packageVersion.ts +1 -1
  92. package/src/retry.ts +33 -26
  93. package/src/testContainerRuntimeFactory.ts +152 -59
  94. package/src/testContainerRuntimeFactoryWithDefaultDataStore.ts +61 -0
  95. package/src/testFluidObject.ts +190 -147
  96. package/src/testObjectProvider.ts +931 -372
  97. package/src/timeoutUtils.ts +226 -37
  98. package/tsconfig.json +9 -12
@@ -3,105 +3,119 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { defaultFluidObjectRequestHandler } from "@fluidframework/aqueduct";
7
6
  import { IRequest, IResponse, IFluidHandle } from "@fluidframework/core-interfaces";
8
- import { FluidObjectHandle, FluidDataStoreRuntime, mixinRequestHandler } from "@fluidframework/datastore";
7
+ import {
8
+ FluidObjectHandle,
9
+ FluidDataStoreRuntime,
10
+ mixinRequestHandler,
11
+ } from "@fluidframework/datastore";
9
12
  import { SharedMap, ISharedMap } from "@fluidframework/map";
10
13
  import {
11
- IFluidDataStoreContext,
12
- IFluidDataStoreFactory,
13
- IFluidDataStoreChannel,
14
+ IFluidDataStoreContext,
15
+ IFluidDataStoreFactory,
16
+ IFluidDataStoreChannel,
14
17
  } from "@fluidframework/runtime-definitions";
15
18
  import { IFluidDataStoreRuntime, IChannelFactory } from "@fluidframework/datastore-definitions";
19
+ import { assert } from "@fluidframework/core-utils";
20
+ import { create404Response } from "@fluidframework/runtime-utils";
16
21
  import { ITestFluidObject } from "./interfaces";
17
22
 
18
23
  /**
19
24
  * A test Fluid object that will create a shared object for each key-value pair in the factoryEntries passed to load.
20
25
  * The shared objects can be retrieved by passing the key of the entry to getSharedObject.
21
26
  * It exposes the IFluidDataStoreContext and IFluidDataStoreRuntime.
27
+ * @internal
22
28
  */
23
29
  export class TestFluidObject implements ITestFluidObject {
24
- public static async load(
25
- runtime: IFluidDataStoreRuntime,
26
- channel: IFluidDataStoreChannel,
27
- context: IFluidDataStoreContext,
28
- factoryEntries: Map<string, IChannelFactory>,
29
- existing: boolean,
30
- ) {
31
- const fluidObject = new TestFluidObject(runtime, channel, context, factoryEntries);
32
- await fluidObject.initialize(existing);
33
-
34
- return fluidObject;
35
- }
36
-
37
- public get ITestFluidObject() {
38
- return this;
39
- }
40
-
41
- public get IFluidLoadable() {
42
- return this;
43
- }
44
-
45
- public get handle(): IFluidHandle<this> { return this.innerHandle; }
46
-
47
- public root!: ISharedMap;
48
- private readonly innerHandle: IFluidHandle<this>;
49
-
50
- /**
51
- * Creates a new TestFluidObject.
52
- * @param runtime - The data store runtime.
53
- * @param context - The data store context.
54
- * @param factoryEntries - A list of id to IChannelFactory mapping. For each item in the list,
55
- * a shared object is created which can be retrieved by calling getSharedObject() with the id;
56
- */
57
- constructor(
58
- public readonly runtime: IFluidDataStoreRuntime,
59
- public readonly channel: IFluidDataStoreChannel,
60
- public readonly context: IFluidDataStoreContext,
61
- private readonly factoryEntriesMap: Map<string, IChannelFactory>,
62
- ) {
63
- this.innerHandle = new FluidObjectHandle(this, "", runtime.objectsRoutingContext);
64
- }
65
-
66
- /**
67
- * Retrieves a shared object with the given id.
68
- * @param id - The id of the shared object to retrieve.
69
- */
70
- public async getSharedObject<T = any>(id: string): Promise<T> {
71
- if (this.factoryEntriesMap === undefined) {
72
- throw new Error("Shared objects were not provided during creation.");
73
- }
74
-
75
- for (const key of this.factoryEntriesMap.keys()) {
76
- if (key === id) {
77
- const handle = this.root.get<IFluidHandle>(id);
78
- return handle?.get() as unknown as T;
79
- }
80
- }
81
-
82
- throw new Error(`Shared object with id ${id} not found.`);
83
- }
84
-
85
- public async request(request: IRequest): Promise<IResponse> {
86
- return defaultFluidObjectRequestHandler(this, request);
87
- }
88
-
89
- private async initialize(existing: boolean) {
90
- if (!existing) {
91
- this.root = SharedMap.create(this.runtime, "root");
92
-
93
- this.factoryEntriesMap.forEach((sharedObjectFactory: IChannelFactory, key: string) => {
94
- const sharedObject = this.runtime.createChannel(key, sharedObjectFactory.type);
95
- this.root.set(key, sharedObject.handle);
96
- });
97
-
98
- this.root.bindToContext();
99
- }
100
-
101
- this.root = await this.runtime.getChannel("root") as ISharedMap;
102
- }
30
+ public get ITestFluidObject() {
31
+ return this;
32
+ }
33
+
34
+ public get IFluidLoadable() {
35
+ return this;
36
+ }
37
+
38
+ public get handle(): IFluidHandle<this> {
39
+ return this.innerHandle;
40
+ }
41
+
42
+ public root!: ISharedMap;
43
+ private readonly innerHandle: IFluidHandle<this>;
44
+ private initializeP: Promise<void> | undefined;
45
+
46
+ /**
47
+ * Creates a new TestFluidObject.
48
+ * @param runtime - The data store runtime.
49
+ * @param context - The data store context.
50
+ * @param factoryEntries - A list of id to IChannelFactory mapping. For each item in the list,
51
+ * a shared object is created which can be retrieved by calling getSharedObject() with the id;
52
+ */
53
+ constructor(
54
+ public readonly runtime: IFluidDataStoreRuntime,
55
+ public readonly channel: IFluidDataStoreChannel,
56
+ public readonly context: IFluidDataStoreContext,
57
+ private readonly factoryEntriesMap: Map<string, IChannelFactory>,
58
+ ) {
59
+ this.innerHandle = new FluidObjectHandle(this, "", runtime.objectsRoutingContext);
60
+ }
61
+
62
+ /**
63
+ * Retrieves a shared object with the given id.
64
+ * @param id - The id of the shared object to retrieve.
65
+ */
66
+ public async getSharedObject<T = any>(id: string): Promise<T> {
67
+ if (this.factoryEntriesMap === undefined) {
68
+ throw new Error("Shared objects were not provided during creation.");
69
+ }
70
+
71
+ for (const key of this.factoryEntriesMap.keys()) {
72
+ if (key === id) {
73
+ const handle = this.root.get<IFluidHandle>(id);
74
+ return handle?.get() as unknown as T;
75
+ }
76
+ }
77
+
78
+ throw new Error(`Shared object with id ${id} not found.`);
79
+ }
80
+
81
+ public async request(request: IRequest): Promise<IResponse> {
82
+ return request.url === "" || request.url === "/" || request.url.startsWith("/?")
83
+ ? { mimeType: "fluid/object", status: 200, value: this }
84
+ : create404Response(request);
85
+ }
86
+
87
+ public async initialize(existing: boolean) {
88
+ const doInitialization = async () => {
89
+ if (!existing) {
90
+ this.root = SharedMap.create(this.runtime, "root");
91
+
92
+ this.factoryEntriesMap.forEach(
93
+ (sharedObjectFactory: IChannelFactory, key: string) => {
94
+ const sharedObject = this.runtime.createChannel(
95
+ key,
96
+ sharedObjectFactory.type,
97
+ );
98
+ this.root.set(key, sharedObject.handle);
99
+ },
100
+ );
101
+
102
+ this.root.bindToContext();
103
+ }
104
+
105
+ this.root = (await this.runtime.getChannel("root")) as ISharedMap;
106
+ };
107
+
108
+ if (this.initializeP === undefined) {
109
+ this.initializeP = doInitialization();
110
+ }
111
+
112
+ return this.initializeP;
113
+ }
103
114
  }
104
115
 
116
+ /**
117
+ * @internal
118
+ */
105
119
  export type ChannelFactoryRegistry = Iterable<[string | undefined, IChannelFactory]>;
106
120
 
107
121
  /**
@@ -109,71 +123,100 @@ export type ChannelFactoryRegistry = Iterable<[string | undefined, IChannelFacto
109
123
  * with the object factories in the entry list. All the entries with an id other than undefined are passed to the
110
124
  * Fluid object so that it can create a shared object for each.
111
125
  *
112
- * For example, the following will create a Fluid object that creates and loads a SharedString and SharedDirectory. It
113
- * will add SparseMatrix to the data store's factory so that it can be created later.
114
- * new TestFluidObjectFactory([
115
- * [ "sharedString", SharedString.getFactory() ],
116
- * [ "sharedDirectory", SharedDirectory.getFactory() ],
117
- * [ undefined, SparseMatrix.getFactory() ],
118
- * ]);
126
+ * @example
127
+ *
128
+ * The following will create a Fluid object that creates and loads a SharedString and SharedDirectory.
129
+ * It will add SparseMatrix to the data store's factory so that it can be created later.
130
+ *
131
+ * ```typescript
132
+ * new TestFluidObjectFactory([
133
+ * [ "sharedString", SharedString.getFactory() ],
134
+ * [ "sharedDirectory", SharedDirectory.getFactory() ],
135
+ * [ undefined, SparseMatrix.getFactory() ],
136
+ * ]);
137
+ * ```
119
138
  *
120
139
  * The SharedString and SharedDirectory can be retrieved via getSharedObject() on the TestFluidObject as follows:
121
- * sharedString = testFluidObject.getSharedObject<SharedString>("sharedString");
122
- * sharedDir = testFluidObject.getSharedObject<SharedDirectory>("sharedDirectory");
140
+ *
141
+ * ```typescript
142
+ * sharedString = testFluidObject.getSharedObject<SharedString>("sharedString");
143
+ * sharedDir = testFluidObject.getSharedObject<SharedDirectory>("sharedDirectory");
144
+ * ```
145
+ *
146
+ * @privateRemarks Beware that using this class generally forfeits some compatibility coverage
147
+ * `describeCompat` aims to provide:
148
+ * `SharedMap`s always reference the current version of SharedMap.
149
+ * AB#4670 tracks improving this situation.
150
+ * @internal
123
151
  */
124
152
  export class TestFluidObjectFactory implements IFluidDataStoreFactory {
125
- public get IFluidDataStoreFactory() { return this; }
126
-
127
- /**
128
- * Creates a new TestFluidObjectFactory.
129
- * @param factoryEntries - A list of id to IChannelFactory mapping. It creates a data store runtime with each
130
- * IChannelFactory. Entries with string ids are passed to the Fluid object so that it can create a shared object
131
- * for it.
132
- */
133
- constructor(private readonly factoryEntries: ChannelFactoryRegistry,
134
- public readonly type = "TestFluidObjectFactory") { }
135
-
136
- public async instantiateDataStore(
137
- context: IFluidDataStoreContext,
138
- existing: boolean,
139
- ): Promise<FluidDataStoreRuntime> {
140
- const dataTypes = new Map<string, IChannelFactory>();
141
-
142
- // Add SharedMap's factory which will be used to create the root map.
143
- const sharedMapFactory = SharedMap.getFactory();
144
- dataTypes.set(sharedMapFactory.type, sharedMapFactory);
145
-
146
- // Add the object factories to the list to be sent to data store runtime.
147
- for (const entry of this.factoryEntries) {
148
- const factory = entry[1];
149
- dataTypes.set(factory.type, factory);
150
- }
151
-
152
- // Create a map from the factory entries with entries that don't have the id as undefined. This will be
153
- // passed to the Fluid object.
154
- const factoryEntriesMapForObject = new Map<string, IChannelFactory>();
155
- for (const entry of this.factoryEntries) {
156
- const id = entry[0];
157
- if (id !== undefined) {
158
- factoryEntriesMapForObject.set(id, entry[1]);
159
- }
160
- }
161
-
162
- const runtimeClass = mixinRequestHandler(
163
- async (request: IRequest) => {
164
- const router = await routerP;
165
- return router.request(request);
166
- });
167
-
168
- const runtime = new runtimeClass(context, dataTypes, existing);
169
- const routerP = TestFluidObject.load(
170
- runtime,
171
- runtime,
172
- context,
173
- factoryEntriesMapForObject,
174
- existing,
175
- );
176
-
177
- return runtime;
178
- }
153
+ public get IFluidDataStoreFactory() {
154
+ return this;
155
+ }
156
+
157
+ /**
158
+ * Creates a new TestFluidObjectFactory.
159
+ * @param factoryEntries - A list of id to IChannelFactory mapping. It creates a data store runtime with each
160
+ * IChannelFactory. Entries with string ids are passed to the Fluid object so that it can create a shared object
161
+ * for it.
162
+ */
163
+ constructor(
164
+ private readonly factoryEntries: ChannelFactoryRegistry,
165
+ public readonly type = "TestFluidObjectFactory",
166
+ ) {}
167
+
168
+ public async instantiateDataStore(
169
+ context: IFluidDataStoreContext,
170
+ existing: boolean,
171
+ ): Promise<FluidDataStoreRuntime> {
172
+ const dataTypes = new Map<string, IChannelFactory>();
173
+
174
+ // Add SharedMap's factory which will be used to create the root map.
175
+ const sharedMapFactory = SharedMap.getFactory();
176
+ dataTypes.set(sharedMapFactory.type, sharedMapFactory);
177
+
178
+ // Add the object factories to the list to be sent to data store runtime.
179
+ for (const [, factory] of this.factoryEntries) {
180
+ dataTypes.set(factory.type, factory);
181
+ }
182
+
183
+ // Create a map from the factory entries with entries that don't have the id as undefined. This will be
184
+ // passed to the Fluid object.
185
+ const factoryEntriesMapForObject = new Map<string, IChannelFactory>();
186
+ for (const [id, factory] of this.factoryEntries) {
187
+ if (id !== undefined) {
188
+ factoryEntriesMapForObject.set(id, factory);
189
+ }
190
+ }
191
+
192
+ const runtimeClass = mixinRequestHandler(
193
+ async (request: IRequest, rt: FluidDataStoreRuntime) => {
194
+ // The provideEntryPoint callback below always returns FluidDataStoreRuntime, so this cast is safe
195
+ const dataObject = (await rt.entryPoint.get()) as FluidDataStoreRuntime;
196
+ assert(
197
+ dataObject.request !== undefined,
198
+ "entryPoint should have been initialized by now",
199
+ );
200
+ return dataObject.request(request);
201
+ },
202
+ );
203
+
204
+ const runtime = new runtimeClass(context, dataTypes, existing, async () => {
205
+ await instance.initialize(true);
206
+ return instance;
207
+ });
208
+
209
+ const instance: TestFluidObject = new TestFluidObject(
210
+ runtime, // runtime
211
+ runtime, // channel
212
+ context,
213
+ factoryEntriesMapForObject,
214
+ );
215
+
216
+ if (!existing) {
217
+ await instance.initialize(false);
218
+ }
219
+
220
+ return runtime;
221
+ }
179
222
  }