@fluidframework/test-utils 2.90.0-378676 → 2.91.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 (67) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +2 -0
  3. package/dist/TestSummaryUtils.d.ts.map +1 -1
  4. package/dist/TestSummaryUtils.js +0 -1
  5. package/dist/TestSummaryUtils.js.map +1 -1
  6. package/dist/eventAndErrorLogger.d.ts +51 -0
  7. package/dist/eventAndErrorLogger.d.ts.map +1 -0
  8. package/dist/eventAndErrorLogger.js +116 -0
  9. package/dist/eventAndErrorLogger.js.map +1 -0
  10. package/dist/index.d.ts +7 -3
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +14 -5
  13. package/dist/index.js.map +1 -1
  14. package/dist/loaderContainerTracker.d.ts.map +1 -1
  15. package/dist/loaderContainerTracker.js +1 -2
  16. package/dist/loaderContainerTracker.js.map +1 -1
  17. package/dist/localCodeLoader.d.ts.map +1 -1
  18. package/dist/localCodeLoader.js +0 -1
  19. package/dist/localCodeLoader.js.map +1 -1
  20. package/dist/packageVersion.d.ts +1 -1
  21. package/dist/packageVersion.d.ts.map +1 -1
  22. package/dist/packageVersion.js +1 -1
  23. package/dist/packageVersion.js.map +1 -1
  24. package/dist/testObjectProvider.d.ts +4 -46
  25. package/dist/testObjectProvider.d.ts.map +1 -1
  26. package/dist/testObjectProvider.js +10 -117
  27. package/dist/testObjectProvider.js.map +1 -1
  28. package/dist/timeoutUtils.d.ts.map +1 -1
  29. package/dist/timeoutUtils.js +2 -0
  30. package/dist/timeoutUtils.js.map +1 -1
  31. package/lib/TestSummaryUtils.d.ts.map +1 -1
  32. package/lib/TestSummaryUtils.js +0 -1
  33. package/lib/TestSummaryUtils.js.map +1 -1
  34. package/lib/eventAndErrorLogger.d.ts +51 -0
  35. package/lib/eventAndErrorLogger.d.ts.map +1 -0
  36. package/lib/eventAndErrorLogger.js +111 -0
  37. package/lib/eventAndErrorLogger.js.map +1 -0
  38. package/lib/index.d.ts +7 -3
  39. package/lib/index.d.ts.map +1 -1
  40. package/lib/index.js +11 -2
  41. package/lib/index.js.map +1 -1
  42. package/lib/loaderContainerTracker.d.ts.map +1 -1
  43. package/lib/loaderContainerTracker.js +1 -2
  44. package/lib/loaderContainerTracker.js.map +1 -1
  45. package/lib/localCodeLoader.d.ts.map +1 -1
  46. package/lib/localCodeLoader.js +0 -1
  47. package/lib/localCodeLoader.js.map +1 -1
  48. package/lib/packageVersion.d.ts +1 -1
  49. package/lib/packageVersion.d.ts.map +1 -1
  50. package/lib/packageVersion.js +1 -1
  51. package/lib/packageVersion.js.map +1 -1
  52. package/lib/testObjectProvider.d.ts +4 -46
  53. package/lib/testObjectProvider.d.ts.map +1 -1
  54. package/lib/testObjectProvider.js +5 -110
  55. package/lib/testObjectProvider.js.map +1 -1
  56. package/lib/timeoutUtils.d.ts.map +1 -1
  57. package/lib/timeoutUtils.js +2 -0
  58. package/lib/timeoutUtils.js.map +1 -1
  59. package/package.json +27 -27
  60. package/src/TestSummaryUtils.ts +0 -2
  61. package/src/eventAndErrorLogger.ts +164 -0
  62. package/src/index.ts +22 -8
  63. package/src/loaderContainerTracker.ts +2 -3
  64. package/src/localCodeLoader.ts +0 -1
  65. package/src/packageVersion.ts +1 -1
  66. package/src/testObjectProvider.ts +9 -159
  67. 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,
@@ -12,7 +12,6 @@ import { ConnectionState } from "@fluidframework/container-loader";
12
12
  import {
13
13
  IContainerCreateProps,
14
14
  IContainerLoadProps,
15
- // eslint-disable-next-line import-x/no-internal-modules
16
15
  } from "@fluidframework/container-loader/internal/test/container";
17
16
  import { assert } from "@fluidframework/core-utils/internal";
18
17
  import {
@@ -228,7 +227,7 @@ export class LoaderContainerTracker implements IOpProcessingController {
228
227
  const resumed = this.resumeProcessing(...containers);
229
228
 
230
229
  let waitingSequenceNumberSynchronized: string | undefined;
231
- // eslint-disable-next-line no-constant-condition
230
+
232
231
  while (true) {
233
232
  // yield a turn to allow side effect of resuming or the ops we just processed execute before we check
234
233
  await new Promise<void>((resolve) => {
@@ -515,7 +514,7 @@ export class LoaderContainerTracker implements IOpProcessingController {
515
514
  for (const container of containersToApply) {
516
515
  const record = this.containers.get(container);
517
516
  if (record !== undefined && !record.paused) {
518
- // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions, @typescript-eslint/prefer-nullish-coalescing -- intentional behavior
517
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- intentional behavior
519
518
  if (record.pauseP === undefined) {
520
519
  record.pauseP = this.pauseContainer(container, record);
521
520
  }
@@ -45,7 +45,6 @@ export type fluidEntryPoint = SupportedExportInterfaces | IFluidModule;
45
45
  */
46
46
  export type Factory = IFluidDataStoreFactory & Partial<IProvideFluidDataStoreRegistry>;
47
47
 
48
- // eslint-disable-next-line jsdoc/require-description -- TODO: add documentation
49
48
  /**
50
49
  * @internal
51
50
  */
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/test-utils";
9
- export const pkgVersion = "2.90.0-378676";
9
+ export const pkgVersion = "2.91.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
@@ -505,7 +402,7 @@ export class TestObjectProvider implements ITestObjectProvider {
505
402
  * {@inheritDoc ITestObjectProvider.documentServiceFactory}
506
403
  */
507
404
  public get documentServiceFactory(): IDocumentServiceFactory {
508
- // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions, @typescript-eslint/prefer-nullish-coalescing -- intentional behavior
405
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- intentional behavior
509
406
  if (!this._documentServiceFactory) {
510
407
  this._documentServiceFactory = this.driver.createDocumentServiceFactory();
511
408
  }
@@ -516,7 +413,7 @@ export class TestObjectProvider implements ITestObjectProvider {
516
413
  * {@inheritDoc ITestObjectProvider.urlResolver}
517
414
  */
518
415
  public get urlResolver(): IUrlResolver {
519
- // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions, @typescript-eslint/prefer-nullish-coalescing -- intentional behavior
416
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- intentional behavior
520
417
  if (!this._urlResolver) {
521
418
  this._urlResolver = this.driver.createUrlResolver();
522
419
  }
@@ -823,7 +720,7 @@ export class TestObjectProviderWithVersionedLoad implements ITestObjectProvider
823
720
  * {@inheritDoc ITestObjectProvider.documentServiceFactory}
824
721
  */
825
722
  public get documentServiceFactory(): IDocumentServiceFactory {
826
- // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions, @typescript-eslint/prefer-nullish-coalescing -- intentional behavior
723
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- intentional behavior
827
724
  if (!this._documentServiceFactory) {
828
725
  this._documentServiceFactory = this.driverForCreating.createDocumentServiceFactory();
829
726
  }
@@ -834,7 +731,7 @@ export class TestObjectProviderWithVersionedLoad implements ITestObjectProvider
834
731
  * {@inheritDoc ITestObjectProvider.urlResolver}
835
732
  */
836
733
  public get urlResolver(): IUrlResolver {
837
- // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions, @typescript-eslint/prefer-nullish-coalescing -- intentional behavior
734
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- intentional behavior
838
735
  if (!this._urlResolver) {
839
736
  this._urlResolver = this.driverForCreating.createUrlResolver();
840
737
  }
@@ -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