@fluidframework/test-utils 2.90.0 → 2.92.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.
Files changed (51) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +2 -0
  3. package/dist/eventAndErrorLogger.d.ts +51 -0
  4. package/dist/eventAndErrorLogger.d.ts.map +1 -0
  5. package/dist/eventAndErrorLogger.js +116 -0
  6. package/dist/eventAndErrorLogger.js.map +1 -0
  7. package/dist/index.d.ts +7 -3
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +14 -5
  10. package/dist/index.js.map +1 -1
  11. package/dist/legacy.d.ts +1 -1
  12. package/dist/packageVersion.d.ts +1 -1
  13. package/dist/packageVersion.js +1 -1
  14. package/dist/packageVersion.js.map +1 -1
  15. package/dist/public.d.ts +1 -1
  16. package/dist/testObjectProvider.d.ts +4 -46
  17. package/dist/testObjectProvider.d.ts.map +1 -1
  18. package/dist/testObjectProvider.js +6 -113
  19. package/dist/testObjectProvider.js.map +1 -1
  20. package/dist/timeoutUtils.d.ts.map +1 -1
  21. package/dist/timeoutUtils.js +2 -0
  22. package/dist/timeoutUtils.js.map +1 -1
  23. package/eslint.config.mts +25 -2
  24. package/internal.d.ts +1 -1
  25. package/legacy.d.ts +1 -1
  26. package/lib/eventAndErrorLogger.d.ts +51 -0
  27. package/lib/eventAndErrorLogger.d.ts.map +1 -0
  28. package/lib/eventAndErrorLogger.js +111 -0
  29. package/lib/eventAndErrorLogger.js.map +1 -0
  30. package/lib/index.d.ts +7 -3
  31. package/lib/index.d.ts.map +1 -1
  32. package/lib/index.js +11 -2
  33. package/lib/index.js.map +1 -1
  34. package/lib/legacy.d.ts +1 -1
  35. package/lib/packageVersion.d.ts +1 -1
  36. package/lib/packageVersion.js +1 -1
  37. package/lib/packageVersion.js.map +1 -1
  38. package/lib/public.d.ts +1 -1
  39. package/lib/testObjectProvider.d.ts +4 -46
  40. package/lib/testObjectProvider.d.ts.map +1 -1
  41. package/lib/testObjectProvider.js +1 -106
  42. package/lib/testObjectProvider.js.map +1 -1
  43. package/lib/timeoutUtils.d.ts.map +1 -1
  44. package/lib/timeoutUtils.js +2 -0
  45. package/lib/timeoutUtils.js.map +1 -1
  46. package/package.json +30 -30
  47. package/src/eventAndErrorLogger.ts +164 -0
  48. package/src/index.ts +22 -8
  49. package/src/packageVersion.ts +1 -1
  50. package/src/testObjectProvider.ts +5 -155
  51. package/src/timeoutUtils.ts +8 -0
package/src/index.ts CHANGED
@@ -3,8 +3,12 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
+ export type { IEventAndErrorTrackingLogger } from "./eventAndErrorLogger.js";
7
+ export {
8
+ EventAndErrorTrackingLogger,
9
+ getUnexpectedLogErrorException,
10
+ } from "./eventAndErrorLogger.js";
6
11
  export { IProvideTestFluidObject, ITestFluidObject } from "./interfaces.js";
7
- export { LoaderContainerTracker } from "./loaderContainerTracker.js";
8
12
  export {
9
13
  fluidEntryPoint,
10
14
  LocalCodeLoader,
@@ -30,25 +34,33 @@ export {
30
34
  TestFluidObjectFactory,
31
35
  TestDataObjectKind,
32
36
  } from "./testFluidObject.js";
33
- export {
34
- createDocumentId,
35
- DataObjectFactoryType,
36
- EventAndErrorTrackingLogger,
37
- type IEventAndErrorTrackingLogger,
38
- getUnexpectedLogErrorException,
37
+
38
+ // #region Exports with load side-effect
39
+ // The below runtime (not "type") exports transitively or directly import
40
+ // timeoutUtils.ts, which always executes on import and may patch Mocha's timeout
41
+ // handling. That patching only takes effect when consumers use
42
+ // @fluid-internal/mocha-test-setup that sets globalThis.getMochaModule.
43
+ // @fluid-internal/mocha-test-setup is pervasive in our tests and thus patch
44
+ // is usually in effect (when this package is used).
45
+ export { LoaderContainerTracker } from "./loaderContainerTracker.js";
46
+ export type {
39
47
  IDocumentIdStrategy,
40
48
  IOpProcessingController,
41
49
  ITestContainerConfig,
42
50
  ITestObjectProvider,
51
+ } from "./testObjectProvider.js";
52
+ export {
53
+ createDocumentId,
54
+ DataObjectFactoryType,
43
55
  TestObjectProvider,
44
56
  TestObjectProviderWithVersionedLoad,
45
57
  } from "./testObjectProvider.js";
58
+ export type { SummaryInfo } from "./TestSummaryUtils.js";
46
59
  export {
47
60
  createSummarizer,
48
61
  createSummarizerCore,
49
62
  createSummarizerFromFactory,
50
63
  summarizeNow,
51
- SummaryInfo,
52
64
  } from "./TestSummaryUtils.js";
53
65
  export {
54
66
  timeoutAwait,
@@ -63,6 +75,8 @@ export {
63
75
  getContainerEntryPointBackCompat,
64
76
  getDataStoreEntryPointBackCompat,
65
77
  } from "./containerUtils.js";
78
+ // #endregion
79
+
66
80
  export {
67
81
  type ContainerRuntimeFactoryWithDefaultDataStoreConstructor,
68
82
  type ContainerRuntimeFactoryWithDefaultDataStoreProps,
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/test-utils";
9
- export const pkgVersion = "2.90.0";
9
+ export const pkgVersion = "2.92.0";
@@ -18,7 +18,6 @@ import {
18
18
  import type { IContainerRuntimeOptionsInternal } from "@fluidframework/container-runtime/internal";
19
19
  import {
20
20
  IRequestHeader,
21
- ITelemetryBaseEvent,
22
21
  ITelemetryBaseLogger,
23
22
  ITelemetryBaseProperties,
24
23
  TelemetryBaseEventPropertyType,
@@ -32,7 +31,6 @@ import {
32
31
  import { isOdspResolvedUrl } from "@fluidframework/odsp-driver/internal";
33
32
  import type { MinimumVersionForCollab } from "@fluidframework/runtime-definitions/internal";
34
33
  import {
35
- type ITelemetryGenericEventExt,
36
34
  createChildLogger,
37
35
  createMultiSinkLogger,
38
36
  type ITelemetryLoggerPropertyBags,
@@ -41,10 +39,14 @@ import {
41
39
  } from "@fluidframework/telemetry-utils/internal";
42
40
  import { v4 as uuid } from "uuid";
43
41
 
42
+ import type { IEventAndErrorTrackingLogger } from "./eventAndErrorLogger.js";
43
+ import {
44
+ EventAndErrorTrackingLogger,
45
+ getUnexpectedLogErrorException,
46
+ } from "./eventAndErrorLogger.js";
44
47
  import { LoaderContainerTracker } from "./loaderContainerTracker.js";
45
48
  import { LocalCodeLoader, fluidEntryPoint } from "./localCodeLoader.js";
46
49
  import { createAndAttachContainer } from "./localLoader.js";
47
- import { isNonEmptyArray } from "./nonEmptyArrayType.js";
48
50
  import { ChannelFactoryRegistry } from "./testFluidObject.js";
49
51
 
50
52
  const defaultCodeDetails: IFluidCodeDetails = {
@@ -329,111 +331,6 @@ function getDocumentIdStrategy(type?: TestDriverTypes): IDocumentIdStrategy {
329
331
  }
330
332
  }
331
333
 
332
- /** @internal */
333
- export interface IEventAndErrorTrackingLogger {
334
- registerExpectedEvent: (...orderedExpectedEvents: ITelemetryGenericEventExt[]) => void;
335
- reportAndClearTrackedEvents: () => {
336
- expectedNotFound: { index: number; event: ITelemetryGenericEventExt }[];
337
- unexpectedErrors: ITelemetryBaseEvent[];
338
- };
339
- }
340
-
341
- /**
342
- * This class tracks events. It allows specifying expected events, which will be looked for in order.
343
- * It also tracks all unexpected errors.
344
- * At any point you call reportAndClearTrackedEvents which will provide all unexpected errors, and
345
- * any expected events that have not occurred.
346
- * @internal
347
- */
348
- export class EventAndErrorTrackingLogger
349
- implements ITelemetryBaseLogger, IEventAndErrorTrackingLogger
350
- {
351
- /**
352
- * Even if these error events are logged, tests should still be allowed to pass
353
- * Additionally, if downgrade is true, then log as generic (e.g. to avoid polluting the e2e test logs)
354
- */
355
- private readonly allowedErrors: { eventName: string; downgrade?: true }[] = [
356
- // This log was removed in current version as unnecessary, but it's still present in previous versions
357
- {
358
- eventName: "fluid:telemetry:Container:NoRealStorageInDetachedContainer",
359
- downgrade: true,
360
- },
361
- // 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.
362
- { eventName: "fluid:telemetry:OpRoundtripTime" },
363
- ];
364
-
365
- constructor(private readonly baseLogger?: ITelemetryBaseLogger) {}
366
-
367
- private readonly expectedEvents: { index: number; event: ITelemetryGenericEventExt }[] = [];
368
- private readonly unexpectedErrors: ITelemetryBaseEvent[] = [];
369
-
370
- public registerExpectedEvent(...orderedExpectedEvents: ITelemetryGenericEventExt[]): void {
371
- if (this.expectedEvents.length !== 0) {
372
- // we don't have to error here. just no reason not to. given the events must be
373
- // ordered it could be tricky to figure out problems around multiple registrations.
374
- throw new Error(
375
- "Expected events already registered.\n" +
376
- "Call reportAndClearTrackedEvents to clear them before registering more",
377
- );
378
- }
379
- this.expectedEvents.push(
380
- ...orderedExpectedEvents.map((event, index) => ({ index, event })),
381
- );
382
- }
383
-
384
- send(event: ITelemetryBaseEvent): void {
385
- if (isNonEmptyArray(this.expectedEvents)) {
386
- const ee = this.expectedEvents[0].event;
387
- if (ee.eventName === event.eventName) {
388
- let matches = true;
389
- for (const key of Object.keys(ee)) {
390
- if (ee[key] !== event[key]) {
391
- matches = false;
392
- break;
393
- }
394
- }
395
- if (matches) {
396
- // we found an expected event
397
- // so remove it from the list of expected events
398
- // and if it is an error, change it to generic
399
- // this helps keep our telemetry clear of
400
- // expected errors.
401
- this.expectedEvents.shift();
402
- if (event.category === "error") {
403
- event.category = "generic";
404
- }
405
- }
406
- }
407
- }
408
- if (event.category === "error") {
409
- // Check to see if this error is allowed and if its category should be downgraded
410
- const allowedError = this.allowedErrors.find(
411
- ({ eventName }) => eventName === event.eventName,
412
- );
413
-
414
- if (allowedError === undefined) {
415
- this.unexpectedErrors.push(event);
416
- } else if (allowedError.downgrade) {
417
- event.category = "generic";
418
- }
419
- }
420
-
421
- this.baseLogger?.send(event);
422
- }
423
-
424
- public reportAndClearTrackedEvents(): {
425
- expectedNotFound: { index: number; event: ITelemetryGenericEventExt }[];
426
- unexpectedErrors: ITelemetryBaseEvent[];
427
- } {
428
- const expectedNotFound = this.expectedEvents.splice(0, this.expectedEvents.length);
429
- const unexpectedErrors = this.unexpectedErrors.splice(0, this.unexpectedErrors.length);
430
- return {
431
- expectedNotFound,
432
- unexpectedErrors,
433
- };
434
- }
435
- }
436
-
437
334
  /**
438
335
  * Shared base class for test object provider. Contain code for loader and container creation and loading
439
336
  * @internal
@@ -1171,50 +1068,3 @@ function getUrlTelemetryProps(
1171
1068
 
1172
1069
  return tagData(TelemetryDataTag.UserData, props);
1173
1070
  }
1174
-
1175
- /** Summarize the event with just the primary properties, for succinct output in case of test failure */
1176
- const primaryEventProps = ({
1177
- category,
1178
- eventName,
1179
- error,
1180
- errorType,
1181
- }: ITelemetryBaseEvent): Partial<ITelemetryBaseEvent> => ({
1182
- category,
1183
- eventName,
1184
- error,
1185
- errorType,
1186
- ["..."]: "*** Additional properties not shown, see full log for details ***",
1187
- });
1188
-
1189
- /**
1190
- * Retrieves unexpected errors from a logger and returns them as an exception.
1191
- *
1192
- * @internal
1193
- */
1194
- export function getUnexpectedLogErrorException(
1195
- logger: IEventAndErrorTrackingLogger | undefined,
1196
- prefix?: string,
1197
- ): Error | undefined {
1198
- if (logger === undefined) {
1199
- return;
1200
- }
1201
- const results = logger.reportAndClearTrackedEvents();
1202
- if (results.unexpectedErrors.length > 0) {
1203
- return new Error(
1204
- `${prefix ?? ""}Unexpected Errors in Logs:\n${JSON.stringify(
1205
- results.unexpectedErrors.map(primaryEventProps),
1206
- undefined,
1207
- 2,
1208
- )}`,
1209
- );
1210
- }
1211
- if (results.expectedNotFound.length > 0) {
1212
- return new Error(
1213
- `${prefix ?? ""}Expected Events not found:\n${JSON.stringify(
1214
- results.expectedNotFound,
1215
- undefined,
1216
- 2,
1217
- )}`,
1218
- );
1219
- }
1220
- }
@@ -3,7 +3,15 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
+ // Warning: this module has load side effect of patching Mocha's timeout handling.
7
+ // See globalThis.getMochaModule use below.
8
+
6
9
  import { assert, Deferred } from "@fluidframework/core-utils/internal";
10
+ // Note that "@types/mocha" is only a devDependency of this package.
11
+ // None of the mocha types are exposed through exports and thus it's reasonable
12
+ // to leave mocha as a devDependency only. Further, the underlying code is only
13
+ // used when @fluid-internal/mocha-test-setup is used and that package dictates
14
+ // a mocha version.
7
15
  import type * as Mocha from "mocha";
8
16
 
9
17
  const timeBuffer = 15; // leave 15 ms leeway for finish processing