@fluidframework/container-loader 2.0.0-dev-rc.2.0.0.245554 → 2.0.0-dev-rc.3.0.0.250606

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 (181) hide show
  1. package/dist/attachment.d.ts +5 -8
  2. package/dist/attachment.d.ts.map +1 -1
  3. package/dist/attachment.js +2 -2
  4. package/dist/attachment.js.map +1 -1
  5. package/dist/audience.d.ts.map +1 -1
  6. package/dist/audience.js +2 -2
  7. package/dist/audience.js.map +1 -1
  8. package/dist/catchUpMonitor.d.ts +1 -1
  9. package/dist/catchUpMonitor.d.ts.map +1 -1
  10. package/dist/catchUpMonitor.js.map +1 -1
  11. package/dist/connectionManager.d.ts +3 -3
  12. package/dist/connectionManager.d.ts.map +1 -1
  13. package/dist/connectionManager.js +1 -1
  14. package/dist/connectionManager.js.map +1 -1
  15. package/dist/connectionStateHandler.d.ts +3 -3
  16. package/dist/connectionStateHandler.d.ts.map +1 -1
  17. package/dist/connectionStateHandler.js.map +1 -1
  18. package/dist/container.d.ts +4 -43
  19. package/dist/container.d.ts.map +1 -1
  20. package/dist/container.js +24 -37
  21. package/dist/container.js.map +1 -1
  22. package/dist/containerContext.d.ts +17 -7
  23. package/dist/containerContext.d.ts.map +1 -1
  24. package/dist/containerContext.js +7 -2
  25. package/dist/containerContext.js.map +1 -1
  26. package/dist/containerStorageAdapter.d.ts +2 -2
  27. package/dist/containerStorageAdapter.d.ts.map +1 -1
  28. package/dist/containerStorageAdapter.js.map +1 -1
  29. package/dist/contracts.d.ts +3 -3
  30. package/dist/contracts.d.ts.map +1 -1
  31. package/dist/contracts.js.map +1 -1
  32. package/dist/debugLogger.d.ts.map +1 -1
  33. package/dist/debugLogger.js.map +1 -1
  34. package/dist/deltaManager.d.ts +5 -5
  35. package/dist/deltaManager.d.ts.map +1 -1
  36. package/dist/deltaManager.js +3 -3
  37. package/dist/deltaManager.js.map +1 -1
  38. package/dist/deltaQueue.d.ts +1 -1
  39. package/dist/deltaQueue.d.ts.map +1 -1
  40. package/dist/deltaQueue.js +1 -1
  41. package/dist/deltaQueue.js.map +1 -1
  42. package/dist/error.d.ts.map +1 -1
  43. package/dist/error.js.map +1 -1
  44. package/dist/loader.d.ts +3 -3
  45. package/dist/loader.d.ts.map +1 -1
  46. package/dist/loader.js +4 -4
  47. package/dist/loader.js.map +1 -1
  48. package/dist/location-redirection-utilities/resolveWithLocationRedirection.d.ts +1 -1
  49. package/dist/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -1
  50. package/dist/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -1
  51. package/dist/noopHeuristic.d.ts +1 -1
  52. package/dist/noopHeuristic.d.ts.map +1 -1
  53. package/dist/noopHeuristic.js.map +1 -1
  54. package/dist/packageVersion.d.ts +1 -1
  55. package/dist/packageVersion.js +1 -1
  56. package/dist/packageVersion.js.map +1 -1
  57. package/dist/quorum.d.ts +1 -1
  58. package/dist/quorum.d.ts.map +1 -1
  59. package/dist/quorum.js +4 -0
  60. package/dist/quorum.js.map +1 -1
  61. package/dist/retriableDocumentStorageService.d.ts +1 -1
  62. package/dist/retriableDocumentStorageService.d.ts.map +1 -1
  63. package/dist/retriableDocumentStorageService.js +1 -1
  64. package/dist/retriableDocumentStorageService.js.map +1 -1
  65. package/dist/serializedStateManager.d.ts +57 -18
  66. package/dist/serializedStateManager.d.ts.map +1 -1
  67. package/dist/serializedStateManager.js +71 -80
  68. package/dist/serializedStateManager.js.map +1 -1
  69. package/dist/utils.d.ts +5 -6
  70. package/dist/utils.d.ts.map +1 -1
  71. package/dist/utils.js +27 -11
  72. package/dist/utils.js.map +1 -1
  73. package/lib/attachment.d.ts +5 -8
  74. package/lib/attachment.d.ts.map +1 -1
  75. package/lib/attachment.js.map +1 -1
  76. package/lib/audience.d.ts.map +1 -1
  77. package/lib/audience.js.map +1 -1
  78. package/lib/catchUpMonitor.d.ts +1 -1
  79. package/lib/catchUpMonitor.d.ts.map +1 -1
  80. package/lib/catchUpMonitor.js.map +1 -1
  81. package/lib/connectionManager.d.ts +3 -3
  82. package/lib/connectionManager.d.ts.map +1 -1
  83. package/lib/connectionManager.js +3 -3
  84. package/lib/connectionManager.js.map +1 -1
  85. package/lib/connectionStateHandler.d.ts +3 -3
  86. package/lib/connectionStateHandler.d.ts.map +1 -1
  87. package/lib/connectionStateHandler.js.map +1 -1
  88. package/lib/container.d.ts +4 -43
  89. package/lib/container.d.ts.map +1 -1
  90. package/lib/container.js +27 -40
  91. package/lib/container.js.map +1 -1
  92. package/lib/containerContext.d.ts +17 -7
  93. package/lib/containerContext.d.ts.map +1 -1
  94. package/lib/containerContext.js +7 -2
  95. package/lib/containerContext.js.map +1 -1
  96. package/lib/containerStorageAdapter.d.ts +2 -2
  97. package/lib/containerStorageAdapter.d.ts.map +1 -1
  98. package/lib/containerStorageAdapter.js.map +1 -1
  99. package/lib/contracts.d.ts +3 -3
  100. package/lib/contracts.d.ts.map +1 -1
  101. package/lib/contracts.js.map +1 -1
  102. package/lib/debugLogger.d.ts.map +1 -1
  103. package/lib/debugLogger.js.map +1 -1
  104. package/lib/deltaManager.d.ts +5 -5
  105. package/lib/deltaManager.d.ts.map +1 -1
  106. package/lib/deltaManager.js +3 -3
  107. package/lib/deltaManager.js.map +1 -1
  108. package/lib/deltaQueue.d.ts +1 -1
  109. package/lib/deltaQueue.d.ts.map +1 -1
  110. package/lib/deltaQueue.js +1 -1
  111. package/lib/deltaQueue.js.map +1 -1
  112. package/lib/error.d.ts.map +1 -1
  113. package/lib/error.js.map +1 -1
  114. package/lib/loader.d.ts +3 -3
  115. package/lib/loader.d.ts.map +1 -1
  116. package/lib/loader.js +4 -4
  117. package/lib/loader.js.map +1 -1
  118. package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.ts +1 -1
  119. package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -1
  120. package/lib/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -1
  121. package/lib/noopHeuristic.d.ts +1 -1
  122. package/lib/noopHeuristic.d.ts.map +1 -1
  123. package/lib/noopHeuristic.js.map +1 -1
  124. package/lib/packageVersion.d.ts +1 -1
  125. package/lib/packageVersion.js +1 -1
  126. package/lib/packageVersion.js.map +1 -1
  127. package/lib/quorum.d.ts +1 -1
  128. package/lib/quorum.d.ts.map +1 -1
  129. package/lib/quorum.js +4 -0
  130. package/lib/quorum.js.map +1 -1
  131. package/lib/retriableDocumentStorageService.d.ts +1 -1
  132. package/lib/retriableDocumentStorageService.d.ts.map +1 -1
  133. package/lib/retriableDocumentStorageService.js +1 -1
  134. package/lib/retriableDocumentStorageService.js.map +1 -1
  135. package/lib/serializedStateManager.d.ts +57 -18
  136. package/lib/serializedStateManager.d.ts.map +1 -1
  137. package/lib/serializedStateManager.js +68 -79
  138. package/lib/serializedStateManager.js.map +1 -1
  139. package/lib/test/attachment.spec.js +2 -2
  140. package/lib/test/attachment.spec.js.map +1 -1
  141. package/lib/test/catchUpMonitor.spec.js.map +1 -1
  142. package/lib/test/connectionStateHandler.spec.js +1 -1
  143. package/lib/test/connectionStateHandler.spec.js.map +1 -1
  144. package/lib/test/container.spec.js +1 -1
  145. package/lib/test/container.spec.js.map +1 -1
  146. package/lib/test/deltaManager.spec.js +2 -2
  147. package/lib/test/deltaManager.spec.js.map +1 -1
  148. package/lib/test/loader.spec.js +4 -4
  149. package/lib/test/loader.spec.js.map +1 -1
  150. package/lib/test/serializedStateManager.spec.js +10 -7
  151. package/lib/test/serializedStateManager.spec.js.map +1 -1
  152. package/lib/test/snapshotConversionTest.spec.js +12 -12
  153. package/lib/test/snapshotConversionTest.spec.js.map +1 -1
  154. package/lib/test/utils.spec.js +66 -1
  155. package/lib/test/utils.spec.js.map +1 -1
  156. package/lib/utils.d.ts +5 -6
  157. package/lib/utils.d.ts.map +1 -1
  158. package/lib/utils.js +26 -11
  159. package/lib/utils.js.map +1 -1
  160. package/package.json +18 -15
  161. package/src/attachment.ts +7 -6
  162. package/src/audience.ts +2 -1
  163. package/src/catchUpMonitor.ts +1 -1
  164. package/src/connectionManager.ts +15 -15
  165. package/src/connectionStateHandler.ts +4 -4
  166. package/src/container.ts +68 -125
  167. package/src/containerContext.ts +16 -9
  168. package/src/containerStorageAdapter.ts +3 -3
  169. package/src/contracts.ts +4 -4
  170. package/src/debugLogger.ts +1 -1
  171. package/src/deltaManager.ts +24 -24
  172. package/src/deltaQueue.ts +1 -1
  173. package/src/error.ts +1 -1
  174. package/src/loader.ts +22 -21
  175. package/src/location-redirection-utilities/resolveWithLocationRedirection.ts +1 -1
  176. package/src/noopHeuristic.ts +2 -2
  177. package/src/packageVersion.ts +1 -1
  178. package/src/quorum.ts +2 -1
  179. package/src/retriableDocumentStorageService.ts +2 -2
  180. package/src/serializedStateManager.ts +133 -116
  181. package/src/utils.ts +47 -18
@@ -1 +1 @@
1
- {"version":3,"file":"attachment.spec.js","sourceRoot":"","sources":["../../src/test/attachment.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"assert\";\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport { v4 as uuid } from \"uuid\";\nimport { SummaryType } from \"@fluidframework/protocol-definitions\";\nimport { stringToBuffer } from \"@fluid-internal/client-utils\";\nimport { IDocumentStorageService } from \"@fluidframework/driver-definitions\";\nimport {\n\tAttachProcessProps,\n\tAttachingDataWithBlobs,\n\tDetachedDataWithOutstandingBlobs,\n\trunRetriableAttachProcess,\n\tDetachedDefaultData,\n\tAttachmentData,\n\tAttachingDataWithoutBlobs,\n} from \"../attachment.js\";\nimport { combineAppAndProtocolSummary } from \"../utils.js\";\n\nconst emptySummary = combineAppAndProtocolSummary(\n\t{ tree: {}, type: SummaryType.Tree },\n\t{ tree: {}, type: SummaryType.Tree },\n);\n\ntype ObjectWithCallCounts<T extends Record<string, any>> = T &\n\tRecord<\"calls\", Record<keyof T, number>>;\n\nconst addCallCounts = <T extends Record<string, any>>(obj: T): ObjectWithCallCounts<T> => {\n\tconst calls = Object.keys(obj).reduce((pv, cv) => {\n\t\tpv[cv] = 0;\n\t\treturn pv;\n\t}, {}) as Record<keyof T, number>;\n\n\treturn new Proxy<ObjectWithCallCounts<T>>(obj as ObjectWithCallCounts<T>, {\n\t\tget: (t, p, r): any => {\n\t\t\tif (p === \"calls\") {\n\t\t\t\treturn calls;\n\t\t\t} else {\n\t\t\t\tcalls[p as keyof T]++;\n\t\t\t\treturn Reflect.get(t, p, r);\n\t\t\t}\n\t\t},\n\t});\n};\n\nconst createDetachStorage = (\n\tblobCount: number,\n): ObjectWithCallCounts<Exclude<AttachProcessProps[\"detachedBlobStorage\"], undefined>> => {\n\tconst blobs = new Map<string, ArrayBufferLike>(\n\t\tArray.from({ length: blobCount }).map((_, i) => [\n\t\t\ti.toString(),\n\t\t\tstringToBuffer(`${i}-content`, \"utf-8\"),\n\t\t]),\n\t);\n\n\treturn addCallCounts({\n\t\tget size() {\n\t\t\treturn blobs.size;\n\t\t},\n\t\tgetBlobIds() {\n\t\t\treturn [...blobs.keys()];\n\t\t},\n\t\tasync readBlob(id) {\n\t\t\tconst content = blobs.get(id);\n\t\t\tassert(content !== undefined, `no blob content for [${id}]`);\n\t\t\treturn content;\n\t\t},\n\t});\n};\n\nconst createProxyWithFailDefault = <T extends Record<string, any> | undefined>(\n\tpartial: Partial<T> = {},\n): T => {\n\treturn new Proxy(partial, {\n\t\tget: (t, p, r): any => {\n\t\t\tif (p in t) {\n\t\t\t\treturn Reflect.get(t, p, r);\n\t\t\t}\n\n\t\t\treturn new Proxy(\n\t\t\t\t{},\n\t\t\t\t{\n\t\t\t\t\tget: () => assert.fail(`unexpected call too ${p.toString()}`),\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t}) as T;\n};\n\ndescribe(\"runRetriableAttachProcess\", () => {\n\tdescribe(\"end to end process\", () => {\n\t\tit(\"From DetachedDefaultData without blobs or offline\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tawait runRetriableAttachProcess({\n\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\tofflineLoadEnabled: false,\n\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\tcreateAttachmentSummary: (redirectTable) => {\n\t\t\t\t\tassert.strictEqual(redirectTable, undefined, \"redirectTable\");\n\t\t\t\t\treturn emptySummary;\n\t\t\t\t},\n\t\t\t\tcreateOrGetStorageService: async () =>\n\t\t\t\t\tcreateProxyWithFailDefault<IDocumentStorageService>(),\n\t\t\t});\n\n\t\t\tassert.strictEqual(attachmentData?.state, AttachState.Attached, \"should be attached\");\n\t\t});\n\n\t\tit(\"From DetachedDefaultData with offline and without blobs\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst snapshot = await runRetriableAttachProcess({\n\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\tofflineLoadEnabled: true,\n\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\tcreateAttachmentSummary: (redirectTable) => {\n\t\t\t\t\tassert.strictEqual(redirectTable, undefined, \"redirectTable\");\n\t\t\t\t\treturn emptySummary;\n\t\t\t\t},\n\t\t\t\tcreateOrGetStorageService: async () => ({\n\t\t\t\t\tcreateBlob: async () => assert.fail(\"no blobs should be created\"),\n\t\t\t\t\tuploadSummaryWithContext: async () =>\n\t\t\t\t\t\tassert.fail(\"no summary should be uploaded outside of create\"),\n\t\t\t\t}),\n\t\t\t});\n\n\t\t\tassert.strictEqual(attachmentData?.state, AttachState.Attached, \"should be attached\");\n\t\t\tassert.notStrictEqual(snapshot, undefined, \"should have snapshot\");\n\t\t});\n\n\t\tit(\"From DetachedDefaultData with blobs and without offline\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst blobCount = 10;\n\t\t\tconst detachedBlobStorage = createDetachStorage(blobCount);\n\t\t\tconst storageAdapter = addCallCounts({\n\t\t\t\tcreateBlob: async () => Promise.resolve({ id: uuid() }),\n\t\t\t\tuploadSummaryWithContext: async () => Promise.resolve(uuid()),\n\t\t\t});\n\t\t\tawait runRetriableAttachProcess({\n\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\tofflineLoadEnabled: false,\n\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\tcreateAttachmentSummary: (redirectTable) => {\n\t\t\t\t\tassert.strictEqual(redirectTable?.size, blobCount, \"redirectTable?.size\");\n\t\t\t\t\treturn emptySummary;\n\t\t\t\t},\n\t\t\t\tcreateOrGetStorageService: async () => storageAdapter,\n\t\t\t\tdetachedBlobStorage,\n\t\t\t});\n\n\t\t\t// expect every blob to read, and uploaded\n\t\t\tassert.strictEqual(\n\t\t\t\tdetachedBlobStorage.calls.readBlob,\n\t\t\t\tblobCount,\n\t\t\t\t\"detachedBlobStorage.calls.readBlob\",\n\t\t\t);\n\t\t\tassert.strictEqual(\n\t\t\t\tstorageAdapter.calls.createBlob,\n\t\t\t\tblobCount,\n\t\t\t\t\"storageAdapter.calls.createBlob\",\n\t\t\t);\n\n\t\t\t// after blobs are uploaded summary should be\n\t\t\tassert.strictEqual(\n\t\t\t\tstorageAdapter.calls.uploadSummaryWithContext,\n\t\t\t\t1,\n\t\t\t\t\"storageAdapter.calls.uploadSummaryWithContext\",\n\t\t\t);\n\n\t\t\tassert.strictEqual(attachmentData?.state, AttachState.Attached, \"should be attached\");\n\t\t});\n\n\t\tit(\"From DetachedDefaultData with zero blobs and without offline\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tawait runRetriableAttachProcess({\n\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\tofflineLoadEnabled: false,\n\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\tcreateAttachmentSummary: (redirectTable) => {\n\t\t\t\t\tassert.strictEqual(redirectTable, undefined, \"redirectTable\");\n\t\t\t\t\treturn emptySummary;\n\t\t\t\t},\n\t\t\t\tcreateOrGetStorageService: async () => createProxyWithFailDefault(),\n\t\t\t\t// we have blobs storage, but it is empty,\n\t\t\t\t// so it should be treat like there are no blobs\n\t\t\t\tdetachedBlobStorage: createProxyWithFailDefault<\n\t\t\t\t\tAttachProcessProps[\"detachedBlobStorage\"]\n\t\t\t\t>({ size: 0 }),\n\t\t\t});\n\n\t\t\tassert.strictEqual(attachmentData?.state, AttachState.Attached, \"should be attached\");\n\t\t});\n\t});\n\n\tdescribe(\"ends in intermediate state due to failure\", () => {\n\t\tit(\"From DetachedDefaultData without blobs with createAttachmentSummary failure\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst error = new Error(\"createAttachmentSummary failure\");\n\t\t\ttry {\n\t\t\t\tawait runRetriableAttachProcess(\n\t\t\t\t\tcreateProxyWithFailDefault<AttachProcessProps>({\n\t\t\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\t\t\tdetachedBlobStorage: undefined,\n\t\t\t\t\t\tcreateAttachmentSummary: () => {\n\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tassert.fail(\"failure expected\");\n\t\t\t} catch (e) {\n\t\t\t\tassert.deepStrictEqual(e, error);\n\t\t\t}\n\n\t\t\tassert.deepStrictEqual(\n\t\t\t\tattachmentData,\n\t\t\t\tundefined,\n\t\t\t\t\"attachment data shouldn't have been set\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"From DetachedDefaultData without blobs getStorageService failure\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst error = new Error(\"getStorageService failure\");\n\t\t\ttry {\n\t\t\t\tawait runRetriableAttachProcess(\n\t\t\t\t\tcreateProxyWithFailDefault<AttachProcessProps>({\n\t\t\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\t\t\tcreateAttachmentSummary: () => emptySummary,\n\t\t\t\t\t\tdetachedBlobStorage: undefined,\n\t\t\t\t\t\tcreateOrGetStorageService: () => {\n\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tassert.fail(\"failure expected\");\n\t\t\t} catch (e) {\n\t\t\t\tassert.deepStrictEqual(e, error);\n\t\t\t}\n\n\t\t\tassert.deepStrictEqual<AttachingDataWithoutBlobs>(\n\t\t\t\tattachmentData,\n\t\t\t\t{\n\t\t\t\t\tstate: AttachState.Attaching,\n\t\t\t\t\tblobs: \"none\",\n\t\t\t\t\tsummary: emptySummary,\n\t\t\t\t},\n\t\t\t\t\"should have made it to attaching state\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"From DetachedDefaultData with blobs with createBlob failure\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst blobCount = 10;\n\t\t\tconst detachedBlobStorage = createDetachStorage(blobCount);\n\t\t\tconst error = new Error(\"createBlob failure\");\n\t\t\ttry {\n\t\t\t\tawait runRetriableAttachProcess({\n\t\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\t\tofflineLoadEnabled: false,\n\t\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\t\tcreateAttachmentSummary: () => emptySummary,\n\t\t\t\t\tcreateOrGetStorageService: async () =>\n\t\t\t\t\t\tcreateProxyWithFailDefault<IDocumentStorageService>({\n\t\t\t\t\t\t\tcreateBlob: () => {\n\t\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\tdetachedBlobStorage,\n\t\t\t\t});\n\t\t\t\tassert.fail(\"failure expected\");\n\t\t\t} catch (e) {\n\t\t\t\tassert.deepStrictEqual(e, error);\n\t\t\t}\n\n\t\t\tassert.deepStrictEqual<DetachedDataWithOutstandingBlobs>(\n\t\t\t\tattachmentData,\n\t\t\t\t{\n\t\t\t\t\tstate: AttachState.Detached,\n\t\t\t\t\tblobs: \"outstanding\",\n\t\t\t\t\tredirectTable: new Map(),\n\t\t\t\t},\n\t\t\t\t\"should have made it to attaching state\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"From DetachedDefaultData with blobs with createAttachmentSummary failure\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst blobCount = 10;\n\t\t\tconst detachedBlobStorage = createDetachStorage(blobCount);\n\t\t\tconst error = new Error(\"createAttachmentSummary failure\");\n\t\t\ttry {\n\t\t\t\tawait runRetriableAttachProcess({\n\t\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\t\tofflineLoadEnabled: false,\n\t\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\t\tcreateAttachmentSummary: () => {\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t},\n\t\t\t\t\tcreateOrGetStorageService: async () =>\n\t\t\t\t\t\tcreateProxyWithFailDefault<IDocumentStorageService>({\n\t\t\t\t\t\t\tcreateBlob: async () => Promise.resolve({ id: uuid() }),\n\t\t\t\t\t\t}),\n\t\t\t\t\tdetachedBlobStorage,\n\t\t\t\t});\n\t\t\t\tassert.fail(\"failure expected\");\n\t\t\t} catch (e) {\n\t\t\t\tassert.deepStrictEqual(e, error);\n\t\t\t}\n\n\t\t\tassert.deepStrictEqual<DetachedDataWithOutstandingBlobs>(\n\t\t\t\t// override redirectTable as it makes validation pain, and we have good coverage in other tests\n\t\t\t\t{\n\t\t\t\t\t...attachmentData,\n\t\t\t\t\tredirectTable:\n\t\t\t\t\t\tattachmentData && \"redirectTable\" in attachmentData ? new Map() : undefined,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tstate: AttachState.Detached,\n\t\t\t\t\tblobs: \"outstanding\",\n\t\t\t\t\tredirectTable: new Map(),\n\t\t\t\t},\n\t\t\t\t\"should have made it to attaching state\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"From DetachedDefaultData with blobs with uploadSummaryWithContext failure\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst blobCount = 10;\n\t\t\tconst detachedBlobStorage = createDetachStorage(blobCount);\n\t\t\tconst error = new Error(\"uploadSummaryWithContext failure\");\n\t\t\ttry {\n\t\t\t\tawait runRetriableAttachProcess({\n\t\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\t\tofflineLoadEnabled: false,\n\t\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\t\tcreateAttachmentSummary: (redirectTable) => {\n\t\t\t\t\t\tassert.strictEqual(redirectTable?.size, 10, \"redirectTable?.size\");\n\t\t\t\t\t\treturn emptySummary;\n\t\t\t\t\t},\n\t\t\t\t\tcreateOrGetStorageService: async () => ({\n\t\t\t\t\t\tcreateBlob: async () => Promise.resolve({ id: uuid() }),\n\t\t\t\t\t\tuploadSummaryWithContext: () => {\n\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t\tdetachedBlobStorage,\n\t\t\t\t});\n\t\t\t\tassert.fail(\"failure expected\");\n\t\t\t} catch (e) {\n\t\t\t\tassert.deepStrictEqual(e, error);\n\t\t\t}\n\n\t\t\tassert.deepStrictEqual<AttachingDataWithBlobs>(\n\t\t\t\tattachmentData,\n\t\t\t\t{\n\t\t\t\t\tstate: AttachState.Attaching,\n\t\t\t\t\tblobs: \"done\",\n\t\t\t\t\tsummary: emptySummary,\n\t\t\t\t},\n\t\t\t\t\"should have made it to attaching state\",\n\t\t\t);\n\t\t});\n\t});\n\n\tdescribe(\"from intermediate state\", () => {\n\t\tit(\"From DetachedDataWithOutstandingBlobs\", async () => {\n\t\t\tconst initial: DetachedDataWithOutstandingBlobs = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t\tblobs: \"outstanding\",\n\t\t\t\tredirectTable: new Map(),\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst blobCount = 10;\n\t\t\tconst detachedBlobStorage = createDetachStorage(blobCount);\n\t\t\tconst storageAdapter = addCallCounts({\n\t\t\t\tcreateBlob: async () => Promise.resolve({ id: uuid() }),\n\t\t\t\tuploadSummaryWithContext: async () => Promise.resolve(uuid()),\n\t\t\t});\n\t\t\tawait runRetriableAttachProcess({\n\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\tofflineLoadEnabled: false,\n\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\tcreateAttachmentSummary: (redirectTable) => {\n\t\t\t\t\tassert.strictEqual(redirectTable?.size, blobCount, \"redirectTable?.size\");\n\t\t\t\t\treturn emptySummary;\n\t\t\t\t},\n\t\t\t\tcreateOrGetStorageService: async () => storageAdapter,\n\t\t\t\tdetachedBlobStorage,\n\t\t\t});\n\n\t\t\t// expect every blob to read, and uploaded\n\t\t\tassert.strictEqual(initial.redirectTable.size, blobCount, \"initial.redirectTable.size\");\n\n\t\t\tassert.strictEqual(\n\t\t\t\tdetachedBlobStorage.calls.readBlob,\n\t\t\t\tblobCount,\n\t\t\t\t\"detachedBlobStorage.calls.readBlob\",\n\t\t\t);\n\t\t\tassert.strictEqual(\n\t\t\t\tstorageAdapter.calls.createBlob,\n\t\t\t\tblobCount,\n\t\t\t\t\"storageAdapter.calls.createBlob\",\n\t\t\t);\n\n\t\t\t// after blobs are uploaded summary should be\n\t\t\tassert.strictEqual(\n\t\t\t\tstorageAdapter.calls.uploadSummaryWithContext,\n\t\t\t\t1,\n\t\t\t\t\"storageAdapter.calls.uploadSummaryWithContext\",\n\t\t\t);\n\n\t\t\tassert.strictEqual(attachmentData?.state, AttachState.Attached, \"should be attached\");\n\t\t});\n\n\t\tit(\"From AttachingDataWithBlobs\", async () => {\n\t\t\tconst initial: AttachingDataWithBlobs = {\n\t\t\t\tstate: AttachState.Attaching,\n\t\t\t\tblobs: \"done\",\n\t\t\t\tsummary: emptySummary,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst snapshot = await runRetriableAttachProcess(\n\t\t\t\tcreateProxyWithFailDefault<AttachProcessProps>({\n\t\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\t\tofflineLoadEnabled: true,\n\t\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\t\tcreateOrGetStorageService: async () =>\n\t\t\t\t\t\t// only the summary should be left to upload\n\t\t\t\t\t\tcreateProxyWithFailDefault<IDocumentStorageService>({\n\t\t\t\t\t\t\tuploadSummaryWithContext: async () => Promise.resolve(uuid()),\n\t\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\tassert.strictEqual(attachmentData?.state, AttachState.Attached, \"should be attached\");\n\t\t\tassert.notStrictEqual(snapshot, undefined, \"should have snapshot\");\n\t\t});\n\n\t\tit(\"From AttachingDataWithoutBlobs\", async () => {\n\t\t\tconst initial: AttachingDataWithoutBlobs = {\n\t\t\t\tstate: AttachState.Attaching,\n\t\t\t\tblobs: \"none\",\n\t\t\t\tsummary: emptySummary,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst snapshot = await runRetriableAttachProcess(\n\t\t\t\tcreateProxyWithFailDefault<AttachProcessProps>({\n\t\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\t\tofflineLoadEnabled: true,\n\t\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\t\tcreateOrGetStorageService: async (summary) => {\n\t\t\t\t\t\tassert.notStrictEqual(summary, undefined, \"data.summary\");\n\t\t\t\t\t\treturn createProxyWithFailDefault();\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\tassert.strictEqual(attachmentData?.state, AttachState.Attached, \"should be attached\");\n\t\t\tassert.notStrictEqual(snapshot, undefined, \"should have snapshot\");\n\t\t});\n\t});\n});\n"]}
1
+ {"version":3,"file":"attachment.spec.js","sourceRoot":"","sources":["../../src/test/attachment.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"assert\";\nimport { stringToBuffer } from \"@fluid-internal/client-utils\";\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport { IDocumentStorageService } from \"@fluidframework/driver-definitions\";\nimport { SummaryType } from \"@fluidframework/protocol-definitions\";\nimport { v4 as uuid } from \"uuid\";\nimport {\n\tAttachProcessProps,\n\tAttachingDataWithBlobs,\n\tAttachingDataWithoutBlobs,\n\tAttachmentData,\n\tDetachedDataWithOutstandingBlobs,\n\tDetachedDefaultData,\n\trunRetriableAttachProcess,\n} from \"../attachment.js\";\nimport { combineAppAndProtocolSummary } from \"../utils.js\";\n\nconst emptySummary = combineAppAndProtocolSummary(\n\t{ tree: {}, type: SummaryType.Tree },\n\t{ tree: {}, type: SummaryType.Tree },\n);\n\ntype ObjectWithCallCounts<T extends Record<string, any>> = T &\n\tRecord<\"calls\", Record<keyof T, number>>;\n\nconst addCallCounts = <T extends Record<string, any>>(obj: T): ObjectWithCallCounts<T> => {\n\tconst calls = Object.keys(obj).reduce((pv, cv) => {\n\t\tpv[cv] = 0;\n\t\treturn pv;\n\t}, {}) as Record<keyof T, number>;\n\n\treturn new Proxy<ObjectWithCallCounts<T>>(obj as ObjectWithCallCounts<T>, {\n\t\tget: (t, p, r): any => {\n\t\t\tif (p === \"calls\") {\n\t\t\t\treturn calls;\n\t\t\t} else {\n\t\t\t\tcalls[p as keyof T]++;\n\t\t\t\treturn Reflect.get(t, p, r);\n\t\t\t}\n\t\t},\n\t});\n};\n\nconst createDetachStorage = (\n\tblobCount: number,\n): ObjectWithCallCounts<Exclude<AttachProcessProps[\"detachedBlobStorage\"], undefined>> => {\n\tconst blobs = new Map<string, ArrayBufferLike>(\n\t\tArray.from({ length: blobCount }).map((_, i) => [\n\t\t\ti.toString(),\n\t\t\tstringToBuffer(`${i}-content`, \"utf-8\"),\n\t\t]),\n\t);\n\n\treturn addCallCounts({\n\t\tget size() {\n\t\t\treturn blobs.size;\n\t\t},\n\t\tgetBlobIds() {\n\t\t\treturn [...blobs.keys()];\n\t\t},\n\t\tasync readBlob(id) {\n\t\t\tconst content = blobs.get(id);\n\t\t\tassert(content !== undefined, `no blob content for [${id}]`);\n\t\t\treturn content;\n\t\t},\n\t});\n};\n\nconst createProxyWithFailDefault = <T extends Record<string, any> | undefined>(\n\tpartial: Partial<T> = {},\n): T => {\n\treturn new Proxy(partial, {\n\t\tget: (t, p, r): any => {\n\t\t\tif (p in t) {\n\t\t\t\treturn Reflect.get(t, p, r);\n\t\t\t}\n\n\t\t\treturn new Proxy(\n\t\t\t\t{},\n\t\t\t\t{\n\t\t\t\t\tget: () => assert.fail(`unexpected call too ${p.toString()}`),\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t}) as T;\n};\n\ndescribe(\"runRetriableAttachProcess\", () => {\n\tdescribe(\"end to end process\", () => {\n\t\tit(\"From DetachedDefaultData without blobs or offline\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tawait runRetriableAttachProcess({\n\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\tofflineLoadEnabled: false,\n\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\tcreateAttachmentSummary: (redirectTable) => {\n\t\t\t\t\tassert.strictEqual(redirectTable, undefined, \"redirectTable\");\n\t\t\t\t\treturn emptySummary;\n\t\t\t\t},\n\t\t\t\tcreateOrGetStorageService: async () =>\n\t\t\t\t\tcreateProxyWithFailDefault<IDocumentStorageService>(),\n\t\t\t});\n\n\t\t\tassert.strictEqual(attachmentData?.state, AttachState.Attached, \"should be attached\");\n\t\t});\n\n\t\tit(\"From DetachedDefaultData with offline and without blobs\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst snapshot = await runRetriableAttachProcess({\n\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\tofflineLoadEnabled: true,\n\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\tcreateAttachmentSummary: (redirectTable) => {\n\t\t\t\t\tassert.strictEqual(redirectTable, undefined, \"redirectTable\");\n\t\t\t\t\treturn emptySummary;\n\t\t\t\t},\n\t\t\t\tcreateOrGetStorageService: async () => ({\n\t\t\t\t\tcreateBlob: async () => assert.fail(\"no blobs should be created\"),\n\t\t\t\t\tuploadSummaryWithContext: async () =>\n\t\t\t\t\t\tassert.fail(\"no summary should be uploaded outside of create\"),\n\t\t\t\t}),\n\t\t\t});\n\n\t\t\tassert.strictEqual(attachmentData?.state, AttachState.Attached, \"should be attached\");\n\t\t\tassert.notStrictEqual(snapshot, undefined, \"should have snapshot\");\n\t\t});\n\n\t\tit(\"From DetachedDefaultData with blobs and without offline\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst blobCount = 10;\n\t\t\tconst detachedBlobStorage = createDetachStorage(blobCount);\n\t\t\tconst storageAdapter = addCallCounts({\n\t\t\t\tcreateBlob: async () => Promise.resolve({ id: uuid() }),\n\t\t\t\tuploadSummaryWithContext: async () => Promise.resolve(uuid()),\n\t\t\t});\n\t\t\tawait runRetriableAttachProcess({\n\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\tofflineLoadEnabled: false,\n\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\tcreateAttachmentSummary: (redirectTable) => {\n\t\t\t\t\tassert.strictEqual(redirectTable?.size, blobCount, \"redirectTable?.size\");\n\t\t\t\t\treturn emptySummary;\n\t\t\t\t},\n\t\t\t\tcreateOrGetStorageService: async () => storageAdapter,\n\t\t\t\tdetachedBlobStorage,\n\t\t\t});\n\n\t\t\t// expect every blob to read, and uploaded\n\t\t\tassert.strictEqual(\n\t\t\t\tdetachedBlobStorage.calls.readBlob,\n\t\t\t\tblobCount,\n\t\t\t\t\"detachedBlobStorage.calls.readBlob\",\n\t\t\t);\n\t\t\tassert.strictEqual(\n\t\t\t\tstorageAdapter.calls.createBlob,\n\t\t\t\tblobCount,\n\t\t\t\t\"storageAdapter.calls.createBlob\",\n\t\t\t);\n\n\t\t\t// after blobs are uploaded summary should be\n\t\t\tassert.strictEqual(\n\t\t\t\tstorageAdapter.calls.uploadSummaryWithContext,\n\t\t\t\t1,\n\t\t\t\t\"storageAdapter.calls.uploadSummaryWithContext\",\n\t\t\t);\n\n\t\t\tassert.strictEqual(attachmentData?.state, AttachState.Attached, \"should be attached\");\n\t\t});\n\n\t\tit(\"From DetachedDefaultData with zero blobs and without offline\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tawait runRetriableAttachProcess({\n\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\tofflineLoadEnabled: false,\n\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\tcreateAttachmentSummary: (redirectTable) => {\n\t\t\t\t\tassert.strictEqual(redirectTable, undefined, \"redirectTable\");\n\t\t\t\t\treturn emptySummary;\n\t\t\t\t},\n\t\t\t\tcreateOrGetStorageService: async () => createProxyWithFailDefault(),\n\t\t\t\t// we have blobs storage, but it is empty,\n\t\t\t\t// so it should be treat like there are no blobs\n\t\t\t\tdetachedBlobStorage: createProxyWithFailDefault<\n\t\t\t\t\tAttachProcessProps[\"detachedBlobStorage\"]\n\t\t\t\t>({ size: 0 }),\n\t\t\t});\n\n\t\t\tassert.strictEqual(attachmentData?.state, AttachState.Attached, \"should be attached\");\n\t\t});\n\t});\n\n\tdescribe(\"ends in intermediate state due to failure\", () => {\n\t\tit(\"From DetachedDefaultData without blobs with createAttachmentSummary failure\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst error = new Error(\"createAttachmentSummary failure\");\n\t\t\ttry {\n\t\t\t\tawait runRetriableAttachProcess(\n\t\t\t\t\tcreateProxyWithFailDefault<AttachProcessProps>({\n\t\t\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\t\t\tdetachedBlobStorage: undefined,\n\t\t\t\t\t\tcreateAttachmentSummary: () => {\n\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tassert.fail(\"failure expected\");\n\t\t\t} catch (e) {\n\t\t\t\tassert.deepStrictEqual(e, error);\n\t\t\t}\n\n\t\t\tassert.deepStrictEqual(\n\t\t\t\tattachmentData,\n\t\t\t\tundefined,\n\t\t\t\t\"attachment data shouldn't have been set\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"From DetachedDefaultData without blobs getStorageService failure\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst error = new Error(\"getStorageService failure\");\n\t\t\ttry {\n\t\t\t\tawait runRetriableAttachProcess(\n\t\t\t\t\tcreateProxyWithFailDefault<AttachProcessProps>({\n\t\t\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\t\t\tcreateAttachmentSummary: () => emptySummary,\n\t\t\t\t\t\tdetachedBlobStorage: undefined,\n\t\t\t\t\t\tcreateOrGetStorageService: () => {\n\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tassert.fail(\"failure expected\");\n\t\t\t} catch (e) {\n\t\t\t\tassert.deepStrictEqual(e, error);\n\t\t\t}\n\n\t\t\tassert.deepStrictEqual<AttachingDataWithoutBlobs>(\n\t\t\t\tattachmentData,\n\t\t\t\t{\n\t\t\t\t\tstate: AttachState.Attaching,\n\t\t\t\t\tblobs: \"none\",\n\t\t\t\t\tsummary: emptySummary,\n\t\t\t\t},\n\t\t\t\t\"should have made it to attaching state\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"From DetachedDefaultData with blobs with createBlob failure\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst blobCount = 10;\n\t\t\tconst detachedBlobStorage = createDetachStorage(blobCount);\n\t\t\tconst error = new Error(\"createBlob failure\");\n\t\t\ttry {\n\t\t\t\tawait runRetriableAttachProcess({\n\t\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\t\tofflineLoadEnabled: false,\n\t\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\t\tcreateAttachmentSummary: () => emptySummary,\n\t\t\t\t\tcreateOrGetStorageService: async () =>\n\t\t\t\t\t\tcreateProxyWithFailDefault<IDocumentStorageService>({\n\t\t\t\t\t\t\tcreateBlob: () => {\n\t\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\tdetachedBlobStorage,\n\t\t\t\t});\n\t\t\t\tassert.fail(\"failure expected\");\n\t\t\t} catch (e) {\n\t\t\t\tassert.deepStrictEqual(e, error);\n\t\t\t}\n\n\t\t\tassert.deepStrictEqual<DetachedDataWithOutstandingBlobs>(\n\t\t\t\tattachmentData,\n\t\t\t\t{\n\t\t\t\t\tstate: AttachState.Detached,\n\t\t\t\t\tblobs: \"outstanding\",\n\t\t\t\t\tredirectTable: new Map(),\n\t\t\t\t},\n\t\t\t\t\"should have made it to attaching state\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"From DetachedDefaultData with blobs with createAttachmentSummary failure\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst blobCount = 10;\n\t\t\tconst detachedBlobStorage = createDetachStorage(blobCount);\n\t\t\tconst error = new Error(\"createAttachmentSummary failure\");\n\t\t\ttry {\n\t\t\t\tawait runRetriableAttachProcess({\n\t\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\t\tofflineLoadEnabled: false,\n\t\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\t\tcreateAttachmentSummary: () => {\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t},\n\t\t\t\t\tcreateOrGetStorageService: async () =>\n\t\t\t\t\t\tcreateProxyWithFailDefault<IDocumentStorageService>({\n\t\t\t\t\t\t\tcreateBlob: async () => Promise.resolve({ id: uuid() }),\n\t\t\t\t\t\t}),\n\t\t\t\t\tdetachedBlobStorage,\n\t\t\t\t});\n\t\t\t\tassert.fail(\"failure expected\");\n\t\t\t} catch (e) {\n\t\t\t\tassert.deepStrictEqual(e, error);\n\t\t\t}\n\n\t\t\tassert.deepStrictEqual<DetachedDataWithOutstandingBlobs>(\n\t\t\t\t// override redirectTable as it makes validation pain, and we have good coverage in other tests\n\t\t\t\t{\n\t\t\t\t\t...attachmentData,\n\t\t\t\t\tredirectTable:\n\t\t\t\t\t\tattachmentData && \"redirectTable\" in attachmentData ? new Map() : undefined,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tstate: AttachState.Detached,\n\t\t\t\t\tblobs: \"outstanding\",\n\t\t\t\t\tredirectTable: new Map(),\n\t\t\t\t},\n\t\t\t\t\"should have made it to attaching state\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"From DetachedDefaultData with blobs with uploadSummaryWithContext failure\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst blobCount = 10;\n\t\t\tconst detachedBlobStorage = createDetachStorage(blobCount);\n\t\t\tconst error = new Error(\"uploadSummaryWithContext failure\");\n\t\t\ttry {\n\t\t\t\tawait runRetriableAttachProcess({\n\t\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\t\tofflineLoadEnabled: false,\n\t\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\t\tcreateAttachmentSummary: (redirectTable) => {\n\t\t\t\t\t\tassert.strictEqual(redirectTable?.size, 10, \"redirectTable?.size\");\n\t\t\t\t\t\treturn emptySummary;\n\t\t\t\t\t},\n\t\t\t\t\tcreateOrGetStorageService: async () => ({\n\t\t\t\t\t\tcreateBlob: async () => Promise.resolve({ id: uuid() }),\n\t\t\t\t\t\tuploadSummaryWithContext: () => {\n\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t\tdetachedBlobStorage,\n\t\t\t\t});\n\t\t\t\tassert.fail(\"failure expected\");\n\t\t\t} catch (e) {\n\t\t\t\tassert.deepStrictEqual(e, error);\n\t\t\t}\n\n\t\t\tassert.deepStrictEqual<AttachingDataWithBlobs>(\n\t\t\t\tattachmentData,\n\t\t\t\t{\n\t\t\t\t\tstate: AttachState.Attaching,\n\t\t\t\t\tblobs: \"done\",\n\t\t\t\t\tsummary: emptySummary,\n\t\t\t\t},\n\t\t\t\t\"should have made it to attaching state\",\n\t\t\t);\n\t\t});\n\t});\n\n\tdescribe(\"from intermediate state\", () => {\n\t\tit(\"From DetachedDataWithOutstandingBlobs\", async () => {\n\t\t\tconst initial: DetachedDataWithOutstandingBlobs = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t\tblobs: \"outstanding\",\n\t\t\t\tredirectTable: new Map(),\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst blobCount = 10;\n\t\t\tconst detachedBlobStorage = createDetachStorage(blobCount);\n\t\t\tconst storageAdapter = addCallCounts({\n\t\t\t\tcreateBlob: async () => Promise.resolve({ id: uuid() }),\n\t\t\t\tuploadSummaryWithContext: async () => Promise.resolve(uuid()),\n\t\t\t});\n\t\t\tawait runRetriableAttachProcess({\n\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\tofflineLoadEnabled: false,\n\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\tcreateAttachmentSummary: (redirectTable) => {\n\t\t\t\t\tassert.strictEqual(redirectTable?.size, blobCount, \"redirectTable?.size\");\n\t\t\t\t\treturn emptySummary;\n\t\t\t\t},\n\t\t\t\tcreateOrGetStorageService: async () => storageAdapter,\n\t\t\t\tdetachedBlobStorage,\n\t\t\t});\n\n\t\t\t// expect every blob to read, and uploaded\n\t\t\tassert.strictEqual(initial.redirectTable.size, blobCount, \"initial.redirectTable.size\");\n\n\t\t\tassert.strictEqual(\n\t\t\t\tdetachedBlobStorage.calls.readBlob,\n\t\t\t\tblobCount,\n\t\t\t\t\"detachedBlobStorage.calls.readBlob\",\n\t\t\t);\n\t\t\tassert.strictEqual(\n\t\t\t\tstorageAdapter.calls.createBlob,\n\t\t\t\tblobCount,\n\t\t\t\t\"storageAdapter.calls.createBlob\",\n\t\t\t);\n\n\t\t\t// after blobs are uploaded summary should be\n\t\t\tassert.strictEqual(\n\t\t\t\tstorageAdapter.calls.uploadSummaryWithContext,\n\t\t\t\t1,\n\t\t\t\t\"storageAdapter.calls.uploadSummaryWithContext\",\n\t\t\t);\n\n\t\t\tassert.strictEqual(attachmentData?.state, AttachState.Attached, \"should be attached\");\n\t\t});\n\n\t\tit(\"From AttachingDataWithBlobs\", async () => {\n\t\t\tconst initial: AttachingDataWithBlobs = {\n\t\t\t\tstate: AttachState.Attaching,\n\t\t\t\tblobs: \"done\",\n\t\t\t\tsummary: emptySummary,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst snapshot = await runRetriableAttachProcess(\n\t\t\t\tcreateProxyWithFailDefault<AttachProcessProps>({\n\t\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\t\tofflineLoadEnabled: true,\n\t\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\t\tcreateOrGetStorageService: async () =>\n\t\t\t\t\t\t// only the summary should be left to upload\n\t\t\t\t\t\tcreateProxyWithFailDefault<IDocumentStorageService>({\n\t\t\t\t\t\t\tuploadSummaryWithContext: async () => Promise.resolve(uuid()),\n\t\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\tassert.strictEqual(attachmentData?.state, AttachState.Attached, \"should be attached\");\n\t\t\tassert.notStrictEqual(snapshot, undefined, \"should have snapshot\");\n\t\t});\n\n\t\tit(\"From AttachingDataWithoutBlobs\", async () => {\n\t\t\tconst initial: AttachingDataWithoutBlobs = {\n\t\t\t\tstate: AttachState.Attaching,\n\t\t\t\tblobs: \"none\",\n\t\t\t\tsummary: emptySummary,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst snapshot = await runRetriableAttachProcess(\n\t\t\t\tcreateProxyWithFailDefault<AttachProcessProps>({\n\t\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\t\tofflineLoadEnabled: true,\n\t\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\t\tcreateOrGetStorageService: async (summary) => {\n\t\t\t\t\t\tassert.notStrictEqual(summary, undefined, \"data.summary\");\n\t\t\t\t\t\treturn createProxyWithFailDefault();\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\tassert.strictEqual(attachmentData?.state, AttachState.Attached, \"should be attached\");\n\t\t\tassert.notStrictEqual(snapshot, undefined, \"should have snapshot\");\n\t\t});\n\t});\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"catchUpMonitor.spec.js","sourceRoot":"","sources":["../../src/test/catchUpMonitor.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"assert\";\nimport { IDeltaManager, IDeltaManagerEvents } from \"@fluidframework/container-definitions\";\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport { CatchUpMonitor } from \"../catchUpMonitor.js\";\n\nclass MockDeltaManagerForCatchingUp\n\textends TypedEventEmitter<IDeltaManagerEvents>\n\timplements Pick<IDeltaManager<any, any>, \"lastSequenceNumber\" | \"lastKnownSeqNumber\">\n{\n\tconstructor(\n\t\tpublic lastSequenceNumber: number = 5,\n\t\tpublic lastKnownSeqNumber: number = 10,\n\t) {\n\t\tsuper();\n\t}\n\n\t/** Simulate processing op with the given sequence number, to trigger CatchUpMonitor */\n\temitOpWithSequenceNumber(sequenceNumber: number) {\n\t\tthis.emit(\"op\", { sequenceNumber });\n\t}\n\n\t/** Trigger the CatchUpMonitor by emitting op with the target sequence number */\n\temitOpToCatchUp() {\n\t\tthis.emitOpWithSequenceNumber(this.lastKnownSeqNumber);\n\t}\n\n\tstatic create(\n\t\tsequenceNumbers: {\n\t\t\tlastSequenceNumber?: number;\n\t\t\tlastKnownSeqNumber?: number;\n\t\t} = {},\n\t): MockDeltaManagerForCatchingUp & IDeltaManager<any, any> {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-return\n\t\treturn new MockDeltaManagerForCatchingUp(\n\t\t\tsequenceNumbers.lastSequenceNumber,\n\t\t\tsequenceNumbers.lastKnownSeqNumber,\n\t\t) as any;\n\t}\n}\n\ndescribe(\"CatchUpMonitor\", () => {\n\tlet monitor: CatchUpMonitor;\n\n\tafterEach(() => {\n\t\tmonitor?.dispose();\n\t});\n\n\tit(\"constructor validates DeltaManager sequence number coherency\", async () => {\n\t\tconst mockDeltaManager = MockDeltaManagerForCatchingUp.create({\n\t\t\tlastSequenceNumber: 20,\n\t\t\tlastKnownSeqNumber: 15, // Should be impossible in real world\n\t\t});\n\n\t\tassert.throws(\n\t\t\t() => new CatchUpMonitor(mockDeltaManager, () => {}),\n\t\t\t\"Expect assert when DeltaManager in invalid state\",\n\t\t);\n\t});\n\n\tit(\"Emits caughtUp event when caught up to the point it was created\", () => {\n\t\tconst mockDeltaManager = MockDeltaManagerForCatchingUp.create({\n\t\t\tlastSequenceNumber: 10,\n\t\t\tlastKnownSeqNumber: 15,\n\t\t});\n\t\tlet caughtUp = false;\n\n\t\tmockDeltaManager.lastKnownSeqNumber = 20;\n\t\tmonitor = new CatchUpMonitor(mockDeltaManager, () => {\n\t\t\tcaughtUp = true;\n\t\t});\n\t\tmockDeltaManager.lastKnownSeqNumber = 25; // Shouldn't change anything about the monitor\n\n\t\tmockDeltaManager.emitOpWithSequenceNumber(19); // Less than 20\n\t\tassert(!caughtUp, \"Shouldn't be considered caught up yet\");\n\t\tmockDeltaManager.emitOpWithSequenceNumber(21); // Greater than 20\n\t\tassert(caughtUp, \"Should be considered caught up now\");\n\t});\n\n\tit(\"Emits caught up immediately if last known/processed sequence numbers match\", () => {\n\t\tconst mockDeltaManager = MockDeltaManagerForCatchingUp.create({\n\t\t\tlastSequenceNumber: 10,\n\t\t\tlastKnownSeqNumber: 10,\n\t\t});\n\t\tlet caughtUp = false;\n\n\t\tmonitor = new CatchUpMonitor(mockDeltaManager, () => {\n\t\t\tcaughtUp = true;\n\t\t});\n\n\t\tassert(caughtUp, \"caughtUp should have fired immediately\");\n\t});\n\n\tit(\"Only emits caughtUp once\", () => {\n\t\tconst mockDeltaManager = MockDeltaManagerForCatchingUp.create({\n\t\t\tlastSequenceNumber: 10,\n\t\t\tlastKnownSeqNumber: 15,\n\t\t});\n\t\tlet caughtUpCount = 0;\n\n\t\tmonitor = new CatchUpMonitor(mockDeltaManager, () => {\n\t\t\t++caughtUpCount;\n\t\t});\n\n\t\tmockDeltaManager.emitOpWithSequenceNumber(15);\n\t\tassert.equal(caughtUpCount, 1, \"caughtUp should have fired once\");\n\t\tmockDeltaManager.emitOpWithSequenceNumber(16);\n\t\tassert.equal(caughtUpCount, 1, \"caughtUp should have fired only once\");\n\t});\n\n\tit(\"Dispose removes all listeners\", () => {\n\t\tconst mockDeltaManager = MockDeltaManagerForCatchingUp.create();\n\t\tmonitor = new CatchUpMonitor(mockDeltaManager, () => {});\n\n\t\tmonitor.dispose();\n\n\t\tassert(monitor.disposed, \"dispose() should set disposed\");\n\t\tassert.equal(\n\t\t\tmockDeltaManager.listenerCount(\"op\"),\n\t\t\t0,\n\t\t\t\"CatchUpMonitor.dispose should remove listener on DeltaManager\",\n\t\t);\n\t});\n});\n"]}
1
+ {"version":3,"file":"catchUpMonitor.spec.js","sourceRoot":"","sources":["../../src/test/catchUpMonitor.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"assert\";\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport { IDeltaManager, IDeltaManagerEvents } from \"@fluidframework/container-definitions\";\nimport { CatchUpMonitor } from \"../catchUpMonitor.js\";\n\nclass MockDeltaManagerForCatchingUp\n\textends TypedEventEmitter<IDeltaManagerEvents>\n\timplements Pick<IDeltaManager<any, any>, \"lastSequenceNumber\" | \"lastKnownSeqNumber\">\n{\n\tconstructor(\n\t\tpublic lastSequenceNumber: number = 5,\n\t\tpublic lastKnownSeqNumber: number = 10,\n\t) {\n\t\tsuper();\n\t}\n\n\t/** Simulate processing op with the given sequence number, to trigger CatchUpMonitor */\n\temitOpWithSequenceNumber(sequenceNumber: number) {\n\t\tthis.emit(\"op\", { sequenceNumber });\n\t}\n\n\t/** Trigger the CatchUpMonitor by emitting op with the target sequence number */\n\temitOpToCatchUp() {\n\t\tthis.emitOpWithSequenceNumber(this.lastKnownSeqNumber);\n\t}\n\n\tstatic create(\n\t\tsequenceNumbers: {\n\t\t\tlastSequenceNumber?: number;\n\t\t\tlastKnownSeqNumber?: number;\n\t\t} = {},\n\t): MockDeltaManagerForCatchingUp & IDeltaManager<any, any> {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-return\n\t\treturn new MockDeltaManagerForCatchingUp(\n\t\t\tsequenceNumbers.lastSequenceNumber,\n\t\t\tsequenceNumbers.lastKnownSeqNumber,\n\t\t) as any;\n\t}\n}\n\ndescribe(\"CatchUpMonitor\", () => {\n\tlet monitor: CatchUpMonitor;\n\n\tafterEach(() => {\n\t\tmonitor?.dispose();\n\t});\n\n\tit(\"constructor validates DeltaManager sequence number coherency\", async () => {\n\t\tconst mockDeltaManager = MockDeltaManagerForCatchingUp.create({\n\t\t\tlastSequenceNumber: 20,\n\t\t\tlastKnownSeqNumber: 15, // Should be impossible in real world\n\t\t});\n\n\t\tassert.throws(\n\t\t\t() => new CatchUpMonitor(mockDeltaManager, () => {}),\n\t\t\t\"Expect assert when DeltaManager in invalid state\",\n\t\t);\n\t});\n\n\tit(\"Emits caughtUp event when caught up to the point it was created\", () => {\n\t\tconst mockDeltaManager = MockDeltaManagerForCatchingUp.create({\n\t\t\tlastSequenceNumber: 10,\n\t\t\tlastKnownSeqNumber: 15,\n\t\t});\n\t\tlet caughtUp = false;\n\n\t\tmockDeltaManager.lastKnownSeqNumber = 20;\n\t\tmonitor = new CatchUpMonitor(mockDeltaManager, () => {\n\t\t\tcaughtUp = true;\n\t\t});\n\t\tmockDeltaManager.lastKnownSeqNumber = 25; // Shouldn't change anything about the monitor\n\n\t\tmockDeltaManager.emitOpWithSequenceNumber(19); // Less than 20\n\t\tassert(!caughtUp, \"Shouldn't be considered caught up yet\");\n\t\tmockDeltaManager.emitOpWithSequenceNumber(21); // Greater than 20\n\t\tassert(caughtUp, \"Should be considered caught up now\");\n\t});\n\n\tit(\"Emits caught up immediately if last known/processed sequence numbers match\", () => {\n\t\tconst mockDeltaManager = MockDeltaManagerForCatchingUp.create({\n\t\t\tlastSequenceNumber: 10,\n\t\t\tlastKnownSeqNumber: 10,\n\t\t});\n\t\tlet caughtUp = false;\n\n\t\tmonitor = new CatchUpMonitor(mockDeltaManager, () => {\n\t\t\tcaughtUp = true;\n\t\t});\n\n\t\tassert(caughtUp, \"caughtUp should have fired immediately\");\n\t});\n\n\tit(\"Only emits caughtUp once\", () => {\n\t\tconst mockDeltaManager = MockDeltaManagerForCatchingUp.create({\n\t\t\tlastSequenceNumber: 10,\n\t\t\tlastKnownSeqNumber: 15,\n\t\t});\n\t\tlet caughtUpCount = 0;\n\n\t\tmonitor = new CatchUpMonitor(mockDeltaManager, () => {\n\t\t\t++caughtUpCount;\n\t\t});\n\n\t\tmockDeltaManager.emitOpWithSequenceNumber(15);\n\t\tassert.equal(caughtUpCount, 1, \"caughtUp should have fired once\");\n\t\tmockDeltaManager.emitOpWithSequenceNumber(16);\n\t\tassert.equal(caughtUpCount, 1, \"caughtUp should have fired only once\");\n\t});\n\n\tit(\"Dispose removes all listeners\", () => {\n\t\tconst mockDeltaManager = MockDeltaManagerForCatchingUp.create();\n\t\tmonitor = new CatchUpMonitor(mockDeltaManager, () => {});\n\n\t\tmonitor.dispose();\n\n\t\tassert(monitor.disposed, \"dispose() should set disposed\");\n\t\tassert.equal(\n\t\t\tmockDeltaManager.listenerCount(\"op\"),\n\t\t\t0,\n\t\t\t\"CatchUpMonitor.dispose should remove listener on DeltaManager\",\n\t\t);\n\t});\n});\n"]}
@@ -4,8 +4,8 @@
4
4
  */
5
5
  import { strict as assert } from "assert";
6
6
  import { TypedEventEmitter } from "@fluid-internal/client-utils";
7
- import { useFakeTimers } from "sinon";
8
7
  import { createChildLogger } from "@fluidframework/telemetry-utils";
8
+ import { useFakeTimers } from "sinon";
9
9
  import { Audience } from "../audience.js";
10
10
  import { ConnectionState } from "../connectionState.js";
11
11
  import { createConnectionStateHandlerCore, } from "../connectionStateHandler.js";
@@ -1 +1 @@
1
- {"version":3,"file":"connectionStateHandler.spec.js","sourceRoot":"","sources":["../../src/test/connectionStateHandler.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"assert\";\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport {\n\tIClient,\n\tIClientConfiguration,\n\tConnectionMode,\n\tITokenClaims,\n\tISequencedClient,\n} from \"@fluidframework/protocol-definitions\";\nimport { IDeltaManager, IDeltaManagerEvents } from \"@fluidframework/container-definitions\";\nimport { SinonFakeTimers, useFakeTimers } from \"sinon\";\nimport { ITelemetryBaseProperties } from \"@fluidframework/core-interfaces\";\nimport { createChildLogger, TelemetryEventCategory } from \"@fluidframework/telemetry-utils\";\nimport { Audience } from \"../audience.js\";\nimport { ConnectionState } from \"../connectionState.js\";\nimport {\n\tIConnectionStateHandlerInputs,\n\tIConnectionStateHandler,\n\tcreateConnectionStateHandlerCore,\n} from \"../connectionStateHandler.js\";\nimport { IConnectionDetailsInternal } from \"../contracts.js\";\nimport { ProtocolHandler } from \"../protocol.js\";\n\nclass MockDeltaManagerForCatchingUp\n\textends TypedEventEmitter<IDeltaManagerEvents>\n\timplements Pick<IDeltaManager<any, any>, \"lastSequenceNumber\" | \"lastKnownSeqNumber\">\n{\n\tlastSequenceNumber: number = 5;\n\tlastKnownSeqNumber: number = 10;\n\tcatchUp(seq = 10) {\n\t\tthis.lastKnownSeqNumber = seq;\n\t\tthis.lastSequenceNumber = seq;\n\t\tthis.emit(\"op\", { sequenceNumber: this.lastKnownSeqNumber });\n\t}\n}\n\ndescribe(\"ConnectionStateHandler Tests\", () => {\n\tlet clock: SinonFakeTimers;\n\tlet handlerInputs: IConnectionStateHandlerInputs;\n\tlet connectionStateHandler: IConnectionStateHandler;\n\tlet protocolHandler: ProtocolHandler;\n\tlet shouldClientJoinWrite: boolean;\n\tlet connectionDetails: IConnectionDetailsInternal;\n\tlet connectionDetails2: IConnectionDetailsInternal;\n\tlet connectionDetails3: IConnectionDetailsInternal;\n\tconst expectedTimeout = 90000;\n\tconst pendingClientId = \"pendingClientId\";\n\tconst pendingClientId2 = \"pendingClientId2\";\n\tconst pendingClientId3 = \"pendingClientId3\";\n\tlet deltaManagerForCatchingUp: MockDeltaManagerForCatchingUp;\n\tlet connectionStateHandler_receivedAddMemberEvent: (id: string) => void;\n\tlet connectionStateHandler_receivedJoinSignalEvent: (\n\t\tdetails: IConnectionDetailsInternal,\n\t) => void;\n\tlet connectionStateHandler_receivedRemoveMemberEvent: (id: string) => void;\n\n\t// Stash the real setTimeout because sinon fake timers will hijack it.\n\tconst realSetTimeout = setTimeout;\n\n\t// function to yield control in the Javascript event loop.\n\tasync function yieldEventLoop(): Promise<void> {\n\t\tawait new Promise<void>((resolve) => {\n\t\t\trealSetTimeout(resolve, 0);\n\t\t});\n\t}\n\n\tasync function tickClock(tickValue: number) {\n\t\tclock.tick(tickValue);\n\n\t\t// Yield the event loop because the outbound op will be processed asynchronously.\n\t\tawait yieldEventLoop();\n\t}\n\n\tfunction createHandler(\n\t\tconnectedRaisedWhenCaughtUp: boolean,\n\t\treadClientsWaitForJoinSignal: boolean,\n\t) {\n\t\tconst handler = createConnectionStateHandlerCore(\n\t\t\tconnectedRaisedWhenCaughtUp,\n\t\t\treadClientsWaitForJoinSignal,\n\t\t\thandlerInputs,\n\t\t\tdeltaManagerForCatchingUp as any,\n\t\t\tundefined,\n\t\t);\n\t\thandler.initProtocol(protocolHandler);\n\t\treturn handler;\n\t}\n\n\tbefore(() => {\n\t\tclock = useFakeTimers();\n\t});\n\n\tbeforeEach(() => {\n\t\tconnectionDetails = {\n\t\t\tclientId: pendingClientId,\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tclaims: {} as ITokenClaims,\n\t\t\tmode: \"read\",\n\t\t\tversion: \"0.1\",\n\t\t\tinitialClients: [],\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tserviceConfiguration: {} as IClientConfiguration,\n\t\t\tcheckpointSequenceNumber: undefined,\n\t\t\treason: { text: \"test\" },\n\t\t};\n\t\tconnectionDetails2 = {\n\t\t\tclientId: pendingClientId2,\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tclaims: {} as ITokenClaims,\n\t\t\tmode: \"write\",\n\t\t\tversion: \"0.1\",\n\t\t\tinitialClients: [],\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tserviceConfiguration: {} as IClientConfiguration,\n\t\t\tcheckpointSequenceNumber: undefined,\n\t\t\treason: { text: \"test\" },\n\t\t};\n\t\tconnectionDetails3 = {\n\t\t\tclientId: pendingClientId3,\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tclaims: {} as ITokenClaims,\n\t\t\tmode: \"write\",\n\t\t\tversion: \"0.1\",\n\t\t\tinitialClients: [],\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tserviceConfiguration: {} as IClientConfiguration,\n\t\t\tcheckpointSequenceNumber: undefined,\n\t\t\treason: { text: \"test\" },\n\t\t};\n\n\t\tprotocolHandler = new ProtocolHandler(\n\t\t\t{ minimumSequenceNumber: 0, sequenceNumber: 0 }, // attributes\n\t\t\t{ members: [], proposals: [], values: [] }, // quorumSnapshot\n\t\t\t(key, value) => 0, // sendProposal\n\t\t\tnew Audience(),\n\t\t\t(clientId: string) => false, // shouldClientHaveLeft\n\t\t);\n\t\tshouldClientJoinWrite = false;\n\t\thandlerInputs = {\n\t\t\tmaxClientLeaveWaitTime: expectedTimeout,\n\t\t\tshouldClientJoinWrite: () => shouldClientJoinWrite,\n\t\t\tlogConnectionIssue: (\n\t\t\t\teventName: string,\n\t\t\t\tcategory: TelemetryEventCategory,\n\t\t\t\tdetails?: ITelemetryBaseProperties,\n\t\t\t) => {\n\t\t\t\tthrow new Error(`logConnectionIssue: ${eventName} ${JSON.stringify(details)}`);\n\t\t\t},\n\t\t\tconnectionStateChanged: () => {},\n\t\t\tlogger: createChildLogger(),\n\t\t\tclientShouldHaveLeft: (clientId: string) => {},\n\t\t};\n\n\t\tdeltaManagerForCatchingUp = new MockDeltaManagerForCatchingUp();\n\n\t\tconnectionStateHandler = createHandler(\n\t\t\tfalse, // connectedRaisedWhenCaughtUp,\n\t\t\tfalse,\n\t\t); // readClientsWaitForJoinSignal\n\n\t\tconnectionStateHandler_receivedAddMemberEvent = (id: string) => {\n\t\t\tprotocolHandler.quorum.addMember(id, { client: {} } as any as ISequencedClient);\n\t\t};\n\t\tconnectionStateHandler_receivedRemoveMemberEvent = (id: string) => {\n\t\t\tprotocolHandler.quorum.removeMember(id);\n\t\t};\n\t\tconnectionStateHandler_receivedJoinSignalEvent = (details: IConnectionDetailsInternal) => {\n\t\t\tprotocolHandler.audience.addMember(details.clientId, {\n\t\t\t\tmode: details.mode,\n\t\t\t} as any as IClient);\n\t\t};\n\t});\n\n\tafterEach(() => {\n\t\t// Get rid of timers\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"the end of test\" });\n\t\tconnectionStateHandler.dispose();\n\t});\n\n\tit(\"Should move to connected state on normal flow for read client\", async () => {\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in disconnected state\",\n\t\t);\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Read Client should be in connected state\",\n\t\t);\n\t});\n\n\tit(\"Should move to connected after catching up for read client #1\", async () => {\n\t\tconnectionStateHandler = createHandler(\n\t\t\ttrue, // connectedRaisedWhenCaughtUp\n\t\t\tfalse,\n\t\t); // readClientsWaitForJoinSignal\n\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in Disconnected state\",\n\t\t);\n\t\tconnectionStateHandler.establishingConnection({ text: \"read\" });\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in CatchingUp state\",\n\t\t);\n\n\t\tdeltaManagerForCatchingUp.catchUp();\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Read Client should be in Connected state\",\n\t\t);\n\t});\n\n\tit(\"Should move to connected after catching up for read client #2\", async () => {\n\t\tconnectionStateHandler = createHandler(\n\t\t\ttrue, // connectedRaisedWhenCaughtUp\n\t\t\ttrue,\n\t\t); // readClientsWaitForJoinSignal\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in Disconnected state\",\n\t\t);\n\n\t\tconnectionStateHandler.establishingConnection({ text: \"read\" });\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in CatchingUp state\",\n\t\t);\n\n\t\tdeltaManagerForCatchingUp.catchUp();\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in CatchingUp state\",\n\t\t);\n\n\t\tconnectionStateHandler_receivedJoinSignalEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Read Client should be in Connected state\",\n\t\t);\n\t});\n\n\tit(\"Should move to connected after catching up for read client #3\", async () => {\n\t\tconnectionStateHandler = createHandler(\n\t\t\ttrue, // connectedRaisedWhenCaughtUp\n\t\t\ttrue,\n\t\t); // readClientsWaitForJoinSignal\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in Disconnected state\",\n\t\t);\n\n\t\tconnectionStateHandler.establishingConnection({ text: \"read\" });\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in CatchingUp state\",\n\t\t);\n\n\t\tconnectionStateHandler_receivedJoinSignalEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in CatchingUp state\",\n\t\t);\n\n\t\tdeltaManagerForCatchingUp.catchUp();\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Read Client should be in Connected state\",\n\t\t);\n\t});\n\n\tit(\"Should move to connected after receiving join op for read client\", async () => {\n\t\tconnectionStateHandler = createHandler(\n\t\t\tfalse, // connectedRaisedWhenCaughtUp\n\t\t\ttrue,\n\t\t); // readClientsWaitForJoinSignal\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in Disconnected state\",\n\t\t);\n\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in CatchingUp state\",\n\t\t);\n\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Read Client should be in Connected state\",\n\t\t);\n\t});\n\n\tit(\"Changes in lastKnownSeqNumber by join signal should be picked up\", async () => {\n\t\tconnectionStateHandler = createHandler(\n\t\t\ttrue, // connectedRaisedWhenCaughtUp\n\t\t\ttrue,\n\t\t); // readClientsWaitForJoinSignal\n\n\t\tconnectionStateHandler.establishingConnection({ text: \"write\" });\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in CatchingUp state\",\n\t\t);\n\n\t\tconst lastKnown = deltaManagerForCatchingUp.lastKnownSeqNumber;\n\t\tconst signalRef = lastKnown + 10;\n\n\t\tdeltaManagerForCatchingUp.catchUp(lastKnown);\n\t\tdeltaManagerForCatchingUp.lastKnownSeqNumber = signalRef;\n\t\tconnectionStateHandler_receivedJoinSignalEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in CatchingUp state\",\n\t\t);\n\n\t\tdeltaManagerForCatchingUp.catchUp(signalRef);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Read Client should be in Connected state\",\n\t\t);\n\t});\n\n\tit(\"Should move to connected state on normal flow for write client\", async () => {\n\t\tconnectionDetails.mode = \"write\";\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in disconnected state\",\n\t\t);\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in connecting state\",\n\t\t);\n\t\tconnectionStateHandler_receivedAddMemberEvent(\"anotherClientId\");\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Some other client joined.\",\n\t\t);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client should be in connected state\",\n\t\t);\n\t});\n\n\tit(\"Should move to connected state after catching up for write client\", async () => {\n\t\tconnectionDetails.mode = \"write\";\n\t\tconnectionStateHandler = createHandler(\n\t\t\ttrue, // connectedRaisedWhenCaughtUp\n\t\t\tfalse,\n\t\t); // readClientsWaitForJoinSignal\n\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in Disconnected state\",\n\t\t);\n\n\t\tconnectionStateHandler.establishingConnection({ text: \"write\" });\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in CatchingUp state\",\n\t\t);\n\t\tconnectionStateHandler_receivedAddMemberEvent(\"anotherClientId\");\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Some other client joined.\",\n\t\t);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in CatchingUp state until caught up\",\n\t\t);\n\t\tdeltaManagerForCatchingUp.catchUp();\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client should be in Connected state\",\n\t\t);\n\t});\n\n\tit(\"Connect write first, init protocol later #1\", async () => {\n\t\t// ConnectionStateManager without initialized protocol\n\t\tconnectionStateHandler = createConnectionStateHandlerCore(\n\t\t\tfalse, // connectedRaisedWhenCaughtUp,\n\t\t\tfalse, // readClientsWaitForJoinSignal\n\t\t\thandlerInputs,\n\t\t\tdeltaManagerForCatchingUp as any,\n\t\t\tundefined,\n\t\t);\n\n\t\tconnectionDetails.mode = \"write\";\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in disconnected state\",\n\t\t);\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in connecting state\",\n\t\t);\n\n\t\t// init protocol\n\t\tconnectionStateHandler.initProtocol(protocolHandler);\n\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client should be in connected state\",\n\t\t);\n\t});\n\n\tit(\"Connect write first, init protocol later #2\", async () => {\n\t\t// ConnectionStateManager without initialized protocol\n\t\tconnectionStateHandler = createConnectionStateHandlerCore(\n\t\t\tfalse, // connectedRaisedWhenCaughtUp,\n\t\t\tfalse, // readClientsWaitForJoinSignal\n\t\t\thandlerInputs,\n\t\t\tdeltaManagerForCatchingUp as any,\n\t\t\tundefined,\n\t\t);\n\n\t\tconnectionDetails.mode = \"write\";\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in disconnected state\",\n\t\t);\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in connecting state\",\n\t\t);\n\n\t\t/*\n There is a tiny tiny race possible, where these events happen in this order:\n 1. A connection is established (no \"cached\" mode is used, so it happens in parallel / faster than other steps)\n 2. Some other client produces a summary\n 3. We get \"lucky\" and load from that summary as our initial snapshot\n 4. ConnectionStateHandler.initProtocol is called, \"self\" is already in the quorum.\n We could avoid this sequence (and delete this test case and handling in initProtocol()) if\n we move connection lower in Container.load().\n */\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\n\t\t// init protocol\n\t\tconnectionStateHandler.initProtocol(protocolHandler);\n\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client should be in connected state\",\n\t\t);\n\t});\n\n\tit(\"Should wait for previous client to leave before moving to connected state\", async () => {\n\t\tconnectionDetails.mode = \"write\";\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client should be in connected state\",\n\t\t);\n\n\t\tshouldClientJoinWrite = true;\n\t\t// Disconnect the client\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in disconnected state\",\n\t\t);\n\n\t\t// Make new client join so that it waits for previous client to leave\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails2);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId2);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 2 should be in connecting state as we are waiting for leave\",\n\t\t);\n\n\t\t// Send leave\n\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 2 should be in connected state\",\n\t\t);\n\t});\n\n\tit(\"Should wait for previous client to leave before moving to connected state, even if already in quorum\", async () => {\n\t\tconnectionDetails.mode = \"write\";\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client should be in connected state\",\n\t\t);\n\n\t\tshouldClientJoinWrite = true;\n\t\t// Disconnect the client\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in disconnected state\",\n\t\t);\n\n\t\t// Make new client join so that it waits for previous client to leave\n\t\t// Put Client 2 in quorum before receiving connect event\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId2);\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails2);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 2 should be in connecting state as we are waiting for leave\",\n\t\t);\n\n\t\t// Send leave\n\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 2 should be in connected state\",\n\t\t);\n\t});\n\n\tit(\"read connection following write connection won't have leave timer\", async () => {\n\t\t// Connect a write client, to be Disconnected\n\t\tconnectionDetails.mode = \"write\";\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client should be in connected state\",\n\t\t);\n\n\t\t// Disconnect the first client, indicating all pending ops were ack'd\n\t\tshouldClientJoinWrite = false;\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in disconnected state\",\n\t\t);\n\n\t\t// Make new client join as read - no waiting for leave since shouldClientJoinWrite is false\n\t\tconnectionDetails3.mode = \"read\";\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails3);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 2 should be in connected state\",\n\t\t);\n\t});\n\n\tit(\"Should wait for timeout before moving to connected state if no leave received\", async () => {\n\t\tconnectionDetails.mode = \"write\";\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client should be in connected state\",\n\t\t);\n\n\t\tshouldClientJoinWrite = true;\n\t\t// Disconnect the client\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in disconnected state\",\n\t\t);\n\n\t\t// Make new client join so that it waits for previous client to leave\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails2);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId2);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 2 should be in connecting state as we are waiting for timeout\",\n\t\t);\n\n\t\t// Check state before timeout\n\t\tawait tickClock(expectedTimeout - 1);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 2 should still be in connecting state as we are waiting for timeout\",\n\t\t);\n\n\t\tawait tickClock(1);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 2 should now be in connected state\",\n\t\t);\n\t});\n\n\tit(\"Should wait for Saved event before moving to connected state if no leave received\", async () => {\n\t\tconnectionDetails.mode = \"write\";\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client should be in connected state\",\n\t\t);\n\n\t\tshouldClientJoinWrite = true;\n\t\t// Disconnect the client\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in disconnected state\",\n\t\t);\n\n\t\t// Make new client join so that it waits for previous client to leave\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails2);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId2);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 2 should be in connecting state as we are waiting for timeout\",\n\t\t);\n\n\t\t// Check state before timeout\n\t\tawait tickClock(expectedTimeout - 1);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 2 should still be in connecting state as we are waiting for timeout\",\n\t\t);\n\n\t\t// Fire the container saved event.\n\t\tconnectionStateHandler.containerSaved();\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 2 should now be in connected state\",\n\t\t);\n\t});\n\n\tit(\"All pending state should be cleared after disconnect\", async () => {\n\t\tconnectionDetails.mode = \"write\";\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tassert(\n\t\t\tconnectionStateHandler.pendingClientId !== undefined,\n\t\t\t\"pendingClientId should be set after receiving 'connect' event\",\n\t\t);\n\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"test\" });\n\t\tassert(\n\t\t\tconnectionStateHandler.pendingClientId === undefined,\n\t\t\t\"pendingClientId should not be set after receiving 'disconnect' event\",\n\t\t);\n\t});\n\n\tasync function testComplex(client3mode: ConnectionMode) {\n\t\tconnectionDetails.mode = \"write\";\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 1 should be in connected state\",\n\t\t);\n\n\t\tshouldClientJoinWrite = true;\n\t\t// Disconnect the client\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client 1 should be in disconnected state\",\n\t\t);\n\n\t\t// Make new client join but disconnect it from connecting state\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails2);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 2 should be in connecting state\",\n\t\t);\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client 2 should be in disconnected state\",\n\t\t);\n\n\t\t// Make new client 3 join so that it waits for client 1 to leave\n\t\t// This is rather tricky case when client3mode === \"read\", as we are testing adding \"read\" client when\n\t\t// shouldClientJoinWrite() reports true.\n\t\tconnectionDetails3.mode = client3mode;\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails3);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId3);\n\n\t\t// Send leave for client 2 and check that client 3 should not move to connected state as we were waiting\n\t\t// on client 1 leave\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId2);\n\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId2);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 3 should still be in connecting state\",\n\t\t);\n\n\t\t// Client 1 leaves.\n\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 3 should move to connected state\",\n\t\t);\n\t\t// Timeout should not raise any error as timer should be cleared\n\t\tawait tickClock(expectedTimeout);\n\t}\n\n\tit(\"Should wait for client 1 to leave before moving to connected state(Client 3) when client 2 got disconnected from connecting state #1\", async () => {\n\t\treturn testComplex(\"read\");\n\t});\n\n\tit(\"Should wait for client 1 to leave before moving to connected state(Client 3) when client 2 got disconnected from connecting state #2\", async () => {\n\t\treturn testComplex(\"write\");\n\t});\n\n\tit(\"Should wait for client 1 timeout before moving to connected state(Client 3) when client 2 got disconnected from connecting state #3\", async () => {\n\t\tconnectionDetails.mode = \"write\";\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 1 should be in connected state\",\n\t\t);\n\n\t\tshouldClientJoinWrite = true;\n\t\t// Disconnect the client\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client 1 should be in disconnected state\",\n\t\t);\n\n\t\t// Make new client join but disconnect it from connecting state\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails2);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 2 should be in connecting state\",\n\t\t);\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client 2 should be in disconnected state\",\n\t\t);\n\n\t\t// Make new client 3 join so that it waits for client 1 to leave\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails3);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId3);\n\n\t\t// Send leave for client 2 and check that client 3 should not move to connected state as we were waiting\n\t\t// on client 1 leave.\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId2);\n\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId2);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 3 should still be in connecting state\",\n\t\t);\n\n\t\t// Pass some time.\n\t\tawait tickClock(expectedTimeout - 1);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 3 should still be in connecting state as timeout has not occured\",\n\t\t);\n\n\t\tawait tickClock(1);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 3 should move to connected state\",\n\t\t);\n\t\t// Sending client 1 leave now should not cause any error\n\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 3 should move to connected state\",\n\t\t);\n\t});\n\n\tit(\"Should wait for savedEvent before moving to connected state(Client 3) when client 2 got disconnected from connecting state\", async () => {\n\t\tconnectionDetails.mode = \"write\";\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 1 should be in connected state\",\n\t\t);\n\n\t\tshouldClientJoinWrite = true;\n\t\t// Disconnect the client\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client 1 should be in disconnected state\",\n\t\t);\n\n\t\t// Make new client join but disconnect it from connecting state\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails2);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 2 should be in connecting state\",\n\t\t);\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client 2 should be in disconnected state\",\n\t\t);\n\n\t\t// Make new client 3 join so that it waits for client 1 to leave\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails3);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId3);\n\n\t\t// Send leave for client 2 and check that client 3 should not move to connected state as we were waiting\n\t\t// on client 1 leave.\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId2);\n\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId2);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 3 should still be in connecting state\",\n\t\t);\n\n\t\t// Pass some time.\n\t\tawait tickClock(expectedTimeout - 1);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 3 should still be in connecting state as timeout has not occured\",\n\t\t);\n\n\t\tconnectionStateHandler.containerSaved();\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 3 should move to connected state\",\n\t\t);\n\t\t// Sending client 1 leave now should not cause any error\n\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 3 should move to connected state\",\n\t\t);\n\t});\n\n\tit(\n\t\t\"Should wait for client 1 to leave before moving to connected state(Client 3) when client 2 \" +\n\t\t\t\"got disconnected from connected state\",\n\t\tasync () => {\n\t\t\tconnectionDetails.mode = \"write\";\n\t\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Connected,\n\t\t\t\t\"Client 1 should be in connected state\",\n\t\t\t);\n\n\t\t\tshouldClientJoinWrite = true;\n\t\t\t// Disconnect the client\n\t\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Disconnected,\n\t\t\t\t\"Client 1 should be in disconnected state\",\n\t\t\t);\n\n\t\t\t// Make new client join but disconnect it from connected state\n\t\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails2);\n\t\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId2);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.CatchingUp,\n\t\t\t\t\"Client 2 should still be in connecting state\",\n\t\t\t);\n\t\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Disconnected,\n\t\t\t\t\"Client 2 should be in disconnected state\",\n\t\t\t);\n\n\t\t\t// Make new client 3 join so that it waits for client 1 to leave\n\t\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails3);\n\t\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId3);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.CatchingUp,\n\t\t\t\t\"Client 3 should still be in connecting state\",\n\t\t\t);\n\n\t\t\t// Send leave for client 2 and check that client 3 should not move to connected state as we were waiting\n\t\t\t// on client 1 leave\n\t\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId2);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.CatchingUp,\n\t\t\t\t\"Client 3 should still be in connecting state\",\n\t\t\t);\n\n\t\t\t// Client 1 leaves.\n\t\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Connected,\n\t\t\t\t\"Client 3 should move to connected state\",\n\t\t\t);\n\t\t\t// Timeout should not raise any error as timer should be cleared\n\t\t\tawait tickClock(expectedTimeout);\n\t\t},\n\t);\n\n\tit(\n\t\t\"Should wait for client 1 timeout before moving to connected state(Client 3) when client 2 \" +\n\t\t\t\"got disconnected from connected state\",\n\t\tasync () => {\n\t\t\tconnectionDetails.mode = \"write\";\n\t\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Connected,\n\t\t\t\t\"Client 1 should be in connected state\",\n\t\t\t);\n\n\t\t\tshouldClientJoinWrite = true;\n\t\t\t// Disconnect the client\n\t\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Disconnected,\n\t\t\t\t\"Client 1 should be in disconnected state\",\n\t\t\t);\n\n\t\t\t// Make new client join but disconnect it from connecting state\n\t\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails2);\n\t\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId2);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.CatchingUp,\n\t\t\t\t\"Client 2 should still be in connecting state\",\n\t\t\t);\n\t\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Disconnected,\n\t\t\t\t\"Client 2 should be in disconnected state\",\n\t\t\t);\n\n\t\t\t// Make new client 3 join so that it waits for client 1 to leave\n\t\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails3);\n\t\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId3);\n\n\t\t\t// Send leave for client 2 and check that client 3 should not move to connected state as we were waiting\n\t\t\t// on client 1 leave.\n\t\t\tconnectionStateHandler_receivedRemoveMemberEvent(\"pendingClientId2\");\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.CatchingUp,\n\t\t\t\t\"Client 3 should still be in connecting state\",\n\t\t\t);\n\n\t\t\t// Pass some time.\n\t\t\tawait tickClock(expectedTimeout - 1);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.CatchingUp,\n\t\t\t\t\"Client 3 should still be in connecting state as timeout has not occured\",\n\t\t\t);\n\n\t\t\tawait tickClock(1);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Connected,\n\t\t\t\t\"Client 3 should move to connected state\",\n\t\t\t);\n\n\t\t\t// Sending client 1 leave now should not cause any error\n\t\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Connected,\n\t\t\t\t\"Client 3 should move to connected state\",\n\t\t\t);\n\t\t},\n\t);\n\n\tit(\n\t\t\"Client 3 should wait for client 2(which got disconnected without sending any ops) to leave \" +\n\t\t\t\"when client 2 already waited on client 1\",\n\t\tasync () => {\n\t\t\tconnectionDetails.mode = \"write\";\n\t\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Connected,\n\t\t\t\t\"Client 1 should be in connected state\",\n\t\t\t);\n\n\t\t\tshouldClientJoinWrite = true;\n\t\t\t// Disconnect the client\n\t\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Disconnected,\n\t\t\t\t\"Client 1 should be in disconnected state\",\n\t\t\t);\n\n\t\t\t// Make new client join but disconnect it from connected state\n\t\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails2);\n\t\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId2);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.CatchingUp,\n\t\t\t\t\"Client 2 should still be in connecting state\",\n\t\t\t);\n\t\t\t// Client 1 leaves.\n\t\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId);\n\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Connected,\n\t\t\t\t\"Client 2 should move to connected state\",\n\t\t\t);\n\n\t\t\t// Client 2 leaves without sending any ops.\n\t\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Disconnected,\n\t\t\t\t\"Client 2 should be in disconnected state\",\n\t\t\t);\n\n\t\t\t// Make new client 3 join. Now it should not wait for previous client as client 2 already waited.\n\t\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails3);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.CatchingUp,\n\t\t\t\t\"Client 3 should still be in connecting state\",\n\t\t\t);\n\t\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId3);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.CatchingUp,\n\t\t\t\t\"Client 3 should still be in connecting state\",\n\t\t\t);\n\n\t\t\t// Client 2 leaves.\n\t\t\tconnectionStateHandler_receivedRemoveMemberEvent(\"pendingClientId2\");\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Connected,\n\t\t\t\t\"Client 3 should move to connected state\",\n\t\t\t);\n\t\t\t// Timeout should not raise any error as timer should be cleared\n\t\t\tawait tickClock(expectedTimeout);\n\t\t},\n\t);\n\n\tafterEach(() => {\n\t\tclock.reset();\n\t});\n\n\tafter(() => {\n\t\tclock.restore();\n\t});\n});\n"]}
1
+ {"version":3,"file":"connectionStateHandler.spec.js","sourceRoot":"","sources":["../../src/test/connectionStateHandler.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"assert\";\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport { IDeltaManager, IDeltaManagerEvents } from \"@fluidframework/container-definitions\";\nimport { ITelemetryBaseProperties } from \"@fluidframework/core-interfaces\";\nimport {\n\tConnectionMode,\n\tIClient,\n\tIClientConfiguration,\n\tISequencedClient,\n\tITokenClaims,\n} from \"@fluidframework/protocol-definitions\";\nimport { TelemetryEventCategory, createChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { SinonFakeTimers, useFakeTimers } from \"sinon\";\nimport { Audience } from \"../audience.js\";\nimport { ConnectionState } from \"../connectionState.js\";\nimport {\n\tIConnectionStateHandler,\n\tIConnectionStateHandlerInputs,\n\tcreateConnectionStateHandlerCore,\n} from \"../connectionStateHandler.js\";\nimport { IConnectionDetailsInternal } from \"../contracts.js\";\nimport { ProtocolHandler } from \"../protocol.js\";\n\nclass MockDeltaManagerForCatchingUp\n\textends TypedEventEmitter<IDeltaManagerEvents>\n\timplements Pick<IDeltaManager<any, any>, \"lastSequenceNumber\" | \"lastKnownSeqNumber\">\n{\n\tlastSequenceNumber: number = 5;\n\tlastKnownSeqNumber: number = 10;\n\tcatchUp(seq = 10) {\n\t\tthis.lastKnownSeqNumber = seq;\n\t\tthis.lastSequenceNumber = seq;\n\t\tthis.emit(\"op\", { sequenceNumber: this.lastKnownSeqNumber });\n\t}\n}\n\ndescribe(\"ConnectionStateHandler Tests\", () => {\n\tlet clock: SinonFakeTimers;\n\tlet handlerInputs: IConnectionStateHandlerInputs;\n\tlet connectionStateHandler: IConnectionStateHandler;\n\tlet protocolHandler: ProtocolHandler;\n\tlet shouldClientJoinWrite: boolean;\n\tlet connectionDetails: IConnectionDetailsInternal;\n\tlet connectionDetails2: IConnectionDetailsInternal;\n\tlet connectionDetails3: IConnectionDetailsInternal;\n\tconst expectedTimeout = 90000;\n\tconst pendingClientId = \"pendingClientId\";\n\tconst pendingClientId2 = \"pendingClientId2\";\n\tconst pendingClientId3 = \"pendingClientId3\";\n\tlet deltaManagerForCatchingUp: MockDeltaManagerForCatchingUp;\n\tlet connectionStateHandler_receivedAddMemberEvent: (id: string) => void;\n\tlet connectionStateHandler_receivedJoinSignalEvent: (\n\t\tdetails: IConnectionDetailsInternal,\n\t) => void;\n\tlet connectionStateHandler_receivedRemoveMemberEvent: (id: string) => void;\n\n\t// Stash the real setTimeout because sinon fake timers will hijack it.\n\tconst realSetTimeout = setTimeout;\n\n\t// function to yield control in the Javascript event loop.\n\tasync function yieldEventLoop(): Promise<void> {\n\t\tawait new Promise<void>((resolve) => {\n\t\t\trealSetTimeout(resolve, 0);\n\t\t});\n\t}\n\n\tasync function tickClock(tickValue: number) {\n\t\tclock.tick(tickValue);\n\n\t\t// Yield the event loop because the outbound op will be processed asynchronously.\n\t\tawait yieldEventLoop();\n\t}\n\n\tfunction createHandler(\n\t\tconnectedRaisedWhenCaughtUp: boolean,\n\t\treadClientsWaitForJoinSignal: boolean,\n\t) {\n\t\tconst handler = createConnectionStateHandlerCore(\n\t\t\tconnectedRaisedWhenCaughtUp,\n\t\t\treadClientsWaitForJoinSignal,\n\t\t\thandlerInputs,\n\t\t\tdeltaManagerForCatchingUp as any,\n\t\t\tundefined,\n\t\t);\n\t\thandler.initProtocol(protocolHandler);\n\t\treturn handler;\n\t}\n\n\tbefore(() => {\n\t\tclock = useFakeTimers();\n\t});\n\n\tbeforeEach(() => {\n\t\tconnectionDetails = {\n\t\t\tclientId: pendingClientId,\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tclaims: {} as ITokenClaims,\n\t\t\tmode: \"read\",\n\t\t\tversion: \"0.1\",\n\t\t\tinitialClients: [],\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tserviceConfiguration: {} as IClientConfiguration,\n\t\t\tcheckpointSequenceNumber: undefined,\n\t\t\treason: { text: \"test\" },\n\t\t};\n\t\tconnectionDetails2 = {\n\t\t\tclientId: pendingClientId2,\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tclaims: {} as ITokenClaims,\n\t\t\tmode: \"write\",\n\t\t\tversion: \"0.1\",\n\t\t\tinitialClients: [],\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tserviceConfiguration: {} as IClientConfiguration,\n\t\t\tcheckpointSequenceNumber: undefined,\n\t\t\treason: { text: \"test\" },\n\t\t};\n\t\tconnectionDetails3 = {\n\t\t\tclientId: pendingClientId3,\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tclaims: {} as ITokenClaims,\n\t\t\tmode: \"write\",\n\t\t\tversion: \"0.1\",\n\t\t\tinitialClients: [],\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tserviceConfiguration: {} as IClientConfiguration,\n\t\t\tcheckpointSequenceNumber: undefined,\n\t\t\treason: { text: \"test\" },\n\t\t};\n\n\t\tprotocolHandler = new ProtocolHandler(\n\t\t\t{ minimumSequenceNumber: 0, sequenceNumber: 0 }, // attributes\n\t\t\t{ members: [], proposals: [], values: [] }, // quorumSnapshot\n\t\t\t(key, value) => 0, // sendProposal\n\t\t\tnew Audience(),\n\t\t\t(clientId: string) => false, // shouldClientHaveLeft\n\t\t);\n\t\tshouldClientJoinWrite = false;\n\t\thandlerInputs = {\n\t\t\tmaxClientLeaveWaitTime: expectedTimeout,\n\t\t\tshouldClientJoinWrite: () => shouldClientJoinWrite,\n\t\t\tlogConnectionIssue: (\n\t\t\t\teventName: string,\n\t\t\t\tcategory: TelemetryEventCategory,\n\t\t\t\tdetails?: ITelemetryBaseProperties,\n\t\t\t) => {\n\t\t\t\tthrow new Error(`logConnectionIssue: ${eventName} ${JSON.stringify(details)}`);\n\t\t\t},\n\t\t\tconnectionStateChanged: () => {},\n\t\t\tlogger: createChildLogger(),\n\t\t\tclientShouldHaveLeft: (clientId: string) => {},\n\t\t};\n\n\t\tdeltaManagerForCatchingUp = new MockDeltaManagerForCatchingUp();\n\n\t\tconnectionStateHandler = createHandler(\n\t\t\tfalse, // connectedRaisedWhenCaughtUp,\n\t\t\tfalse,\n\t\t); // readClientsWaitForJoinSignal\n\n\t\tconnectionStateHandler_receivedAddMemberEvent = (id: string) => {\n\t\t\tprotocolHandler.quorum.addMember(id, { client: {} } as any as ISequencedClient);\n\t\t};\n\t\tconnectionStateHandler_receivedRemoveMemberEvent = (id: string) => {\n\t\t\tprotocolHandler.quorum.removeMember(id);\n\t\t};\n\t\tconnectionStateHandler_receivedJoinSignalEvent = (details: IConnectionDetailsInternal) => {\n\t\t\tprotocolHandler.audience.addMember(details.clientId, {\n\t\t\t\tmode: details.mode,\n\t\t\t} as any as IClient);\n\t\t};\n\t});\n\n\tafterEach(() => {\n\t\t// Get rid of timers\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"the end of test\" });\n\t\tconnectionStateHandler.dispose();\n\t});\n\n\tit(\"Should move to connected state on normal flow for read client\", async () => {\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in disconnected state\",\n\t\t);\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Read Client should be in connected state\",\n\t\t);\n\t});\n\n\tit(\"Should move to connected after catching up for read client #1\", async () => {\n\t\tconnectionStateHandler = createHandler(\n\t\t\ttrue, // connectedRaisedWhenCaughtUp\n\t\t\tfalse,\n\t\t); // readClientsWaitForJoinSignal\n\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in Disconnected state\",\n\t\t);\n\t\tconnectionStateHandler.establishingConnection({ text: \"read\" });\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in CatchingUp state\",\n\t\t);\n\n\t\tdeltaManagerForCatchingUp.catchUp();\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Read Client should be in Connected state\",\n\t\t);\n\t});\n\n\tit(\"Should move to connected after catching up for read client #2\", async () => {\n\t\tconnectionStateHandler = createHandler(\n\t\t\ttrue, // connectedRaisedWhenCaughtUp\n\t\t\ttrue,\n\t\t); // readClientsWaitForJoinSignal\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in Disconnected state\",\n\t\t);\n\n\t\tconnectionStateHandler.establishingConnection({ text: \"read\" });\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in CatchingUp state\",\n\t\t);\n\n\t\tdeltaManagerForCatchingUp.catchUp();\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in CatchingUp state\",\n\t\t);\n\n\t\tconnectionStateHandler_receivedJoinSignalEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Read Client should be in Connected state\",\n\t\t);\n\t});\n\n\tit(\"Should move to connected after catching up for read client #3\", async () => {\n\t\tconnectionStateHandler = createHandler(\n\t\t\ttrue, // connectedRaisedWhenCaughtUp\n\t\t\ttrue,\n\t\t); // readClientsWaitForJoinSignal\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in Disconnected state\",\n\t\t);\n\n\t\tconnectionStateHandler.establishingConnection({ text: \"read\" });\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in CatchingUp state\",\n\t\t);\n\n\t\tconnectionStateHandler_receivedJoinSignalEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in CatchingUp state\",\n\t\t);\n\n\t\tdeltaManagerForCatchingUp.catchUp();\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Read Client should be in Connected state\",\n\t\t);\n\t});\n\n\tit(\"Should move to connected after receiving join op for read client\", async () => {\n\t\tconnectionStateHandler = createHandler(\n\t\t\tfalse, // connectedRaisedWhenCaughtUp\n\t\t\ttrue,\n\t\t); // readClientsWaitForJoinSignal\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in Disconnected state\",\n\t\t);\n\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in CatchingUp state\",\n\t\t);\n\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Read Client should be in Connected state\",\n\t\t);\n\t});\n\n\tit(\"Changes in lastKnownSeqNumber by join signal should be picked up\", async () => {\n\t\tconnectionStateHandler = createHandler(\n\t\t\ttrue, // connectedRaisedWhenCaughtUp\n\t\t\ttrue,\n\t\t); // readClientsWaitForJoinSignal\n\n\t\tconnectionStateHandler.establishingConnection({ text: \"write\" });\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in CatchingUp state\",\n\t\t);\n\n\t\tconst lastKnown = deltaManagerForCatchingUp.lastKnownSeqNumber;\n\t\tconst signalRef = lastKnown + 10;\n\n\t\tdeltaManagerForCatchingUp.catchUp(lastKnown);\n\t\tdeltaManagerForCatchingUp.lastKnownSeqNumber = signalRef;\n\t\tconnectionStateHandler_receivedJoinSignalEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in CatchingUp state\",\n\t\t);\n\n\t\tdeltaManagerForCatchingUp.catchUp(signalRef);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Read Client should be in Connected state\",\n\t\t);\n\t});\n\n\tit(\"Should move to connected state on normal flow for write client\", async () => {\n\t\tconnectionDetails.mode = \"write\";\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in disconnected state\",\n\t\t);\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in connecting state\",\n\t\t);\n\t\tconnectionStateHandler_receivedAddMemberEvent(\"anotherClientId\");\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Some other client joined.\",\n\t\t);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client should be in connected state\",\n\t\t);\n\t});\n\n\tit(\"Should move to connected state after catching up for write client\", async () => {\n\t\tconnectionDetails.mode = \"write\";\n\t\tconnectionStateHandler = createHandler(\n\t\t\ttrue, // connectedRaisedWhenCaughtUp\n\t\t\tfalse,\n\t\t); // readClientsWaitForJoinSignal\n\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in Disconnected state\",\n\t\t);\n\n\t\tconnectionStateHandler.establishingConnection({ text: \"write\" });\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in CatchingUp state\",\n\t\t);\n\t\tconnectionStateHandler_receivedAddMemberEvent(\"anotherClientId\");\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Some other client joined.\",\n\t\t);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in CatchingUp state until caught up\",\n\t\t);\n\t\tdeltaManagerForCatchingUp.catchUp();\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client should be in Connected state\",\n\t\t);\n\t});\n\n\tit(\"Connect write first, init protocol later #1\", async () => {\n\t\t// ConnectionStateManager without initialized protocol\n\t\tconnectionStateHandler = createConnectionStateHandlerCore(\n\t\t\tfalse, // connectedRaisedWhenCaughtUp,\n\t\t\tfalse, // readClientsWaitForJoinSignal\n\t\t\thandlerInputs,\n\t\t\tdeltaManagerForCatchingUp as any,\n\t\t\tundefined,\n\t\t);\n\n\t\tconnectionDetails.mode = \"write\";\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in disconnected state\",\n\t\t);\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in connecting state\",\n\t\t);\n\n\t\t// init protocol\n\t\tconnectionStateHandler.initProtocol(protocolHandler);\n\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client should be in connected state\",\n\t\t);\n\t});\n\n\tit(\"Connect write first, init protocol later #2\", async () => {\n\t\t// ConnectionStateManager without initialized protocol\n\t\tconnectionStateHandler = createConnectionStateHandlerCore(\n\t\t\tfalse, // connectedRaisedWhenCaughtUp,\n\t\t\tfalse, // readClientsWaitForJoinSignal\n\t\t\thandlerInputs,\n\t\t\tdeltaManagerForCatchingUp as any,\n\t\t\tundefined,\n\t\t);\n\n\t\tconnectionDetails.mode = \"write\";\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in disconnected state\",\n\t\t);\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client should be in connecting state\",\n\t\t);\n\n\t\t/*\n There is a tiny tiny race possible, where these events happen in this order:\n 1. A connection is established (no \"cached\" mode is used, so it happens in parallel / faster than other steps)\n 2. Some other client produces a summary\n 3. We get \"lucky\" and load from that summary as our initial snapshot\n 4. ConnectionStateHandler.initProtocol is called, \"self\" is already in the quorum.\n We could avoid this sequence (and delete this test case and handling in initProtocol()) if\n we move connection lower in Container.load().\n */\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\n\t\t// init protocol\n\t\tconnectionStateHandler.initProtocol(protocolHandler);\n\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client should be in connected state\",\n\t\t);\n\t});\n\n\tit(\"Should wait for previous client to leave before moving to connected state\", async () => {\n\t\tconnectionDetails.mode = \"write\";\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client should be in connected state\",\n\t\t);\n\n\t\tshouldClientJoinWrite = true;\n\t\t// Disconnect the client\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in disconnected state\",\n\t\t);\n\n\t\t// Make new client join so that it waits for previous client to leave\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails2);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId2);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 2 should be in connecting state as we are waiting for leave\",\n\t\t);\n\n\t\t// Send leave\n\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 2 should be in connected state\",\n\t\t);\n\t});\n\n\tit(\"Should wait for previous client to leave before moving to connected state, even if already in quorum\", async () => {\n\t\tconnectionDetails.mode = \"write\";\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client should be in connected state\",\n\t\t);\n\n\t\tshouldClientJoinWrite = true;\n\t\t// Disconnect the client\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in disconnected state\",\n\t\t);\n\n\t\t// Make new client join so that it waits for previous client to leave\n\t\t// Put Client 2 in quorum before receiving connect event\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId2);\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails2);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 2 should be in connecting state as we are waiting for leave\",\n\t\t);\n\n\t\t// Send leave\n\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 2 should be in connected state\",\n\t\t);\n\t});\n\n\tit(\"read connection following write connection won't have leave timer\", async () => {\n\t\t// Connect a write client, to be Disconnected\n\t\tconnectionDetails.mode = \"write\";\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client should be in connected state\",\n\t\t);\n\n\t\t// Disconnect the first client, indicating all pending ops were ack'd\n\t\tshouldClientJoinWrite = false;\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in disconnected state\",\n\t\t);\n\n\t\t// Make new client join as read - no waiting for leave since shouldClientJoinWrite is false\n\t\tconnectionDetails3.mode = \"read\";\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails3);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 2 should be in connected state\",\n\t\t);\n\t});\n\n\tit(\"Should wait for timeout before moving to connected state if no leave received\", async () => {\n\t\tconnectionDetails.mode = \"write\";\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client should be in connected state\",\n\t\t);\n\n\t\tshouldClientJoinWrite = true;\n\t\t// Disconnect the client\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in disconnected state\",\n\t\t);\n\n\t\t// Make new client join so that it waits for previous client to leave\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails2);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId2);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 2 should be in connecting state as we are waiting for timeout\",\n\t\t);\n\n\t\t// Check state before timeout\n\t\tawait tickClock(expectedTimeout - 1);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 2 should still be in connecting state as we are waiting for timeout\",\n\t\t);\n\n\t\tawait tickClock(1);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 2 should now be in connected state\",\n\t\t);\n\t});\n\n\tit(\"Should wait for Saved event before moving to connected state if no leave received\", async () => {\n\t\tconnectionDetails.mode = \"write\";\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client should be in connected state\",\n\t\t);\n\n\t\tshouldClientJoinWrite = true;\n\t\t// Disconnect the client\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client should be in disconnected state\",\n\t\t);\n\n\t\t// Make new client join so that it waits for previous client to leave\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails2);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId2);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 2 should be in connecting state as we are waiting for timeout\",\n\t\t);\n\n\t\t// Check state before timeout\n\t\tawait tickClock(expectedTimeout - 1);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 2 should still be in connecting state as we are waiting for timeout\",\n\t\t);\n\n\t\t// Fire the container saved event.\n\t\tconnectionStateHandler.containerSaved();\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 2 should now be in connected state\",\n\t\t);\n\t});\n\n\tit(\"All pending state should be cleared after disconnect\", async () => {\n\t\tconnectionDetails.mode = \"write\";\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tassert(\n\t\t\tconnectionStateHandler.pendingClientId !== undefined,\n\t\t\t\"pendingClientId should be set after receiving 'connect' event\",\n\t\t);\n\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"test\" });\n\t\tassert(\n\t\t\tconnectionStateHandler.pendingClientId === undefined,\n\t\t\t\"pendingClientId should not be set after receiving 'disconnect' event\",\n\t\t);\n\t});\n\n\tasync function testComplex(client3mode: ConnectionMode) {\n\t\tconnectionDetails.mode = \"write\";\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 1 should be in connected state\",\n\t\t);\n\n\t\tshouldClientJoinWrite = true;\n\t\t// Disconnect the client\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client 1 should be in disconnected state\",\n\t\t);\n\n\t\t// Make new client join but disconnect it from connecting state\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails2);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 2 should be in connecting state\",\n\t\t);\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client 2 should be in disconnected state\",\n\t\t);\n\n\t\t// Make new client 3 join so that it waits for client 1 to leave\n\t\t// This is rather tricky case when client3mode === \"read\", as we are testing adding \"read\" client when\n\t\t// shouldClientJoinWrite() reports true.\n\t\tconnectionDetails3.mode = client3mode;\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails3);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId3);\n\n\t\t// Send leave for client 2 and check that client 3 should not move to connected state as we were waiting\n\t\t// on client 1 leave\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId2);\n\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId2);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 3 should still be in connecting state\",\n\t\t);\n\n\t\t// Client 1 leaves.\n\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 3 should move to connected state\",\n\t\t);\n\t\t// Timeout should not raise any error as timer should be cleared\n\t\tawait tickClock(expectedTimeout);\n\t}\n\n\tit(\"Should wait for client 1 to leave before moving to connected state(Client 3) when client 2 got disconnected from connecting state #1\", async () => {\n\t\treturn testComplex(\"read\");\n\t});\n\n\tit(\"Should wait for client 1 to leave before moving to connected state(Client 3) when client 2 got disconnected from connecting state #2\", async () => {\n\t\treturn testComplex(\"write\");\n\t});\n\n\tit(\"Should wait for client 1 timeout before moving to connected state(Client 3) when client 2 got disconnected from connecting state #3\", async () => {\n\t\tconnectionDetails.mode = \"write\";\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 1 should be in connected state\",\n\t\t);\n\n\t\tshouldClientJoinWrite = true;\n\t\t// Disconnect the client\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client 1 should be in disconnected state\",\n\t\t);\n\n\t\t// Make new client join but disconnect it from connecting state\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails2);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 2 should be in connecting state\",\n\t\t);\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client 2 should be in disconnected state\",\n\t\t);\n\n\t\t// Make new client 3 join so that it waits for client 1 to leave\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails3);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId3);\n\n\t\t// Send leave for client 2 and check that client 3 should not move to connected state as we were waiting\n\t\t// on client 1 leave.\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId2);\n\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId2);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 3 should still be in connecting state\",\n\t\t);\n\n\t\t// Pass some time.\n\t\tawait tickClock(expectedTimeout - 1);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 3 should still be in connecting state as timeout has not occured\",\n\t\t);\n\n\t\tawait tickClock(1);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 3 should move to connected state\",\n\t\t);\n\t\t// Sending client 1 leave now should not cause any error\n\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 3 should move to connected state\",\n\t\t);\n\t});\n\n\tit(\"Should wait for savedEvent before moving to connected state(Client 3) when client 2 got disconnected from connecting state\", async () => {\n\t\tconnectionDetails.mode = \"write\";\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 1 should be in connected state\",\n\t\t);\n\n\t\tshouldClientJoinWrite = true;\n\t\t// Disconnect the client\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client 1 should be in disconnected state\",\n\t\t);\n\n\t\t// Make new client join but disconnect it from connecting state\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails2);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 2 should be in connecting state\",\n\t\t);\n\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Disconnected,\n\t\t\t\"Client 2 should be in disconnected state\",\n\t\t);\n\n\t\t// Make new client 3 join so that it waits for client 1 to leave\n\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails3);\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId3);\n\n\t\t// Send leave for client 2 and check that client 3 should not move to connected state as we were waiting\n\t\t// on client 1 leave.\n\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId2);\n\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId2);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 3 should still be in connecting state\",\n\t\t);\n\n\t\t// Pass some time.\n\t\tawait tickClock(expectedTimeout - 1);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.CatchingUp,\n\t\t\t\"Client 3 should still be in connecting state as timeout has not occured\",\n\t\t);\n\n\t\tconnectionStateHandler.containerSaved();\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 3 should move to connected state\",\n\t\t);\n\t\t// Sending client 1 leave now should not cause any error\n\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId);\n\t\tassert.strictEqual(\n\t\t\tconnectionStateHandler.connectionState,\n\t\t\tConnectionState.Connected,\n\t\t\t\"Client 3 should move to connected state\",\n\t\t);\n\t});\n\n\tit(\n\t\t\"Should wait for client 1 to leave before moving to connected state(Client 3) when client 2 \" +\n\t\t\t\"got disconnected from connected state\",\n\t\tasync () => {\n\t\t\tconnectionDetails.mode = \"write\";\n\t\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Connected,\n\t\t\t\t\"Client 1 should be in connected state\",\n\t\t\t);\n\n\t\t\tshouldClientJoinWrite = true;\n\t\t\t// Disconnect the client\n\t\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Disconnected,\n\t\t\t\t\"Client 1 should be in disconnected state\",\n\t\t\t);\n\n\t\t\t// Make new client join but disconnect it from connected state\n\t\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails2);\n\t\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId2);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.CatchingUp,\n\t\t\t\t\"Client 2 should still be in connecting state\",\n\t\t\t);\n\t\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Disconnected,\n\t\t\t\t\"Client 2 should be in disconnected state\",\n\t\t\t);\n\n\t\t\t// Make new client 3 join so that it waits for client 1 to leave\n\t\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails3);\n\t\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId3);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.CatchingUp,\n\t\t\t\t\"Client 3 should still be in connecting state\",\n\t\t\t);\n\n\t\t\t// Send leave for client 2 and check that client 3 should not move to connected state as we were waiting\n\t\t\t// on client 1 leave\n\t\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId2);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.CatchingUp,\n\t\t\t\t\"Client 3 should still be in connecting state\",\n\t\t\t);\n\n\t\t\t// Client 1 leaves.\n\t\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Connected,\n\t\t\t\t\"Client 3 should move to connected state\",\n\t\t\t);\n\t\t\t// Timeout should not raise any error as timer should be cleared\n\t\t\tawait tickClock(expectedTimeout);\n\t\t},\n\t);\n\n\tit(\n\t\t\"Should wait for client 1 timeout before moving to connected state(Client 3) when client 2 \" +\n\t\t\t\"got disconnected from connected state\",\n\t\tasync () => {\n\t\t\tconnectionDetails.mode = \"write\";\n\t\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Connected,\n\t\t\t\t\"Client 1 should be in connected state\",\n\t\t\t);\n\n\t\t\tshouldClientJoinWrite = true;\n\t\t\t// Disconnect the client\n\t\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Disconnected,\n\t\t\t\t\"Client 1 should be in disconnected state\",\n\t\t\t);\n\n\t\t\t// Make new client join but disconnect it from connecting state\n\t\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails2);\n\t\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId2);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.CatchingUp,\n\t\t\t\t\"Client 2 should still be in connecting state\",\n\t\t\t);\n\t\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Disconnected,\n\t\t\t\t\"Client 2 should be in disconnected state\",\n\t\t\t);\n\n\t\t\t// Make new client 3 join so that it waits for client 1 to leave\n\t\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails3);\n\t\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId3);\n\n\t\t\t// Send leave for client 2 and check that client 3 should not move to connected state as we were waiting\n\t\t\t// on client 1 leave.\n\t\t\tconnectionStateHandler_receivedRemoveMemberEvent(\"pendingClientId2\");\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.CatchingUp,\n\t\t\t\t\"Client 3 should still be in connecting state\",\n\t\t\t);\n\n\t\t\t// Pass some time.\n\t\t\tawait tickClock(expectedTimeout - 1);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.CatchingUp,\n\t\t\t\t\"Client 3 should still be in connecting state as timeout has not occured\",\n\t\t\t);\n\n\t\t\tawait tickClock(1);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Connected,\n\t\t\t\t\"Client 3 should move to connected state\",\n\t\t\t);\n\n\t\t\t// Sending client 1 leave now should not cause any error\n\t\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Connected,\n\t\t\t\t\"Client 3 should move to connected state\",\n\t\t\t);\n\t\t},\n\t);\n\n\tit(\n\t\t\"Client 3 should wait for client 2(which got disconnected without sending any ops) to leave \" +\n\t\t\t\"when client 2 already waited on client 1\",\n\t\tasync () => {\n\t\t\tconnectionDetails.mode = \"write\";\n\t\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails);\n\t\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Connected,\n\t\t\t\t\"Client 1 should be in connected state\",\n\t\t\t);\n\n\t\t\tshouldClientJoinWrite = true;\n\t\t\t// Disconnect the client\n\t\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Disconnected,\n\t\t\t\t\"Client 1 should be in disconnected state\",\n\t\t\t);\n\n\t\t\t// Make new client join but disconnect it from connected state\n\t\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails2);\n\t\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId2);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.CatchingUp,\n\t\t\t\t\"Client 2 should still be in connecting state\",\n\t\t\t);\n\t\t\t// Client 1 leaves.\n\t\t\tconnectionStateHandler_receivedRemoveMemberEvent(pendingClientId);\n\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Connected,\n\t\t\t\t\"Client 2 should move to connected state\",\n\t\t\t);\n\n\t\t\t// Client 2 leaves without sending any ops.\n\t\t\tconnectionStateHandler.receivedDisconnectEvent({ text: \"Test\" });\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Disconnected,\n\t\t\t\t\"Client 2 should be in disconnected state\",\n\t\t\t);\n\n\t\t\t// Make new client 3 join. Now it should not wait for previous client as client 2 already waited.\n\t\t\tconnectionStateHandler.receivedConnectEvent(connectionDetails3);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.CatchingUp,\n\t\t\t\t\"Client 3 should still be in connecting state\",\n\t\t\t);\n\t\t\tconnectionStateHandler_receivedAddMemberEvent(pendingClientId3);\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.CatchingUp,\n\t\t\t\t\"Client 3 should still be in connecting state\",\n\t\t\t);\n\n\t\t\t// Client 2 leaves.\n\t\t\tconnectionStateHandler_receivedRemoveMemberEvent(\"pendingClientId2\");\n\t\t\tassert.strictEqual(\n\t\t\t\tconnectionStateHandler.connectionState,\n\t\t\t\tConnectionState.Connected,\n\t\t\t\t\"Client 3 should move to connected state\",\n\t\t\t);\n\t\t\t// Timeout should not raise any error as timer should be cleared\n\t\t\tawait tickClock(expectedTimeout);\n\t\t},\n\t);\n\n\tafterEach(() => {\n\t\tclock.reset();\n\t});\n\n\tafter(() => {\n\t\tclock.restore();\n\t});\n});\n"]}
@@ -4,8 +4,8 @@
4
4
  */
5
5
  import assert from "assert";
6
6
  import { TypedEventEmitter } from "@fluid-internal/client-utils";
7
- import { waitContainerToCatchUp } from "../container.js";
8
7
  import { ConnectionState } from "../connectionState.js";
8
+ import { waitContainerToCatchUp } from "../container.js";
9
9
  class MockDeltaManager extends TypedEventEmitter {
10
10
  constructor() {
11
11
  super(...arguments);
@@ -1 +1 @@
1
- {"version":3,"file":"container.spec.js","sourceRoot":"","sources":["../../src/test/container.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAU5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAGjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,MAAM,gBACL,SAAQ,iBAAsC;IAD/C;;QAOC,gCAA2B,GAAG,IAAI,CAAC;QACnC,uBAAkB,GAAG,CAAC,CAAC;QACvB,uBAAkB,GAAG,CAAC,CAAC;IACxB,CAAC;CAAA;AAED,MAAM,aACL,SAAQ,iBAAmC;IAD5C;;QAIC,iBAAY,GACX,IAAI,gBAAgB,EAAS,CAAC;QAG/B,WAAM,GAAyB,KAAK,CAAC;IAgBtC,CAAC;IARA,IAAI,gBAAgB;QACnB,OAAO,IAAI,CAAC,YAAuC,CAAC;IACrD,CAAC;IAED,OAAO;QACN,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC,SAAS,CAAC;QACjD,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACxB,CAAC;CACD;AAED,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IAC1B,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;QACvC,EAAE,CAAC,wBAAwB,EAAE,KAAK,IAAI,EAAE;YACvC,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;YAC1C,aAAa,CAAC,MAAM,GAAG,IAAI,CAAC;YAE5B,MAAM,MAAM,CAAC,OAAO,CACnB,KAAK,IAAI,EAAE,CAAC,sBAAsB,CAAC,aAAkC,CAAC,EACtE,yCAAyC,CACzC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;YAC1D,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;YAC1C,aAAa,CAAC,eAAe,GAAG,eAAe,CAAC,SAAS,CAAC;YAE1D,MAAM,KAAK,GAAG,sBAAsB,CAAC,aAAkC,CAAC,CAAC;YACzE,aAAa,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC,CAAC;YAEjE,2DAA2D;YAC3D,MAAM,KAAK,CAAC;QACb,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;YACvE,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;YAC1C,aAAa,CAAC,gBAAgB,CAAC,kBAAkB,GAAG,CAAC,CAAC,CAAC,8BAA8B;YACrF,aAAa,CAAC,eAAe,GAAG,eAAe,CAAC,SAAS,CAAC;YAE1D,MAAM,KAAK,GAAG,sBAAsB,CAAC,aAAkC,CAAC,CAAC;YAEzE,2DAA2D;YAC3D,MAAM,KAAK,CAAC;QACb,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;YACjF,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;YAC1C,aAAa,CAAC,eAAe,GAAG,eAAe,CAAC,YAAY,CAAC;YAE7D,MAAM,KAAK,GAAG,sBAAsB,CAAC,aAAkC,CAAC,CAAC;YACzE,aAAa,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC,CAAC;YAEjE,2DAA2D;YAC3D,MAAM,KAAK,CAAC;QACb,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport assert from \"assert\";\nimport {\n\tAttachState,\n\tIAudience,\n\tIContainer,\n\tIContainerEvents,\n\tIDeltaManager,\n\tIDeltaManagerEvents,\n\tReadOnlyInfo,\n} from \"@fluidframework/container-definitions\";\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport { IResolvedUrl } from \"@fluidframework/driver-definitions\";\nimport { ISequencedDocumentMessage, IDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { waitContainerToCatchUp } from \"../container.js\";\nimport { ConnectionState } from \"../connectionState.js\";\n\nclass MockDeltaManager\n\textends TypedEventEmitter<IDeltaManagerEvents>\n\timplements\n\t\tPartial<\n\t\t\tOmit<IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>, \"on\" | \"off\" | \"once\">\n\t\t>\n{\n\thasCheckpointSequenceNumber = true;\n\tlastKnownSeqNumber = 2;\n\tlastSequenceNumber = 1;\n}\n\nclass MockContainer\n\textends TypedEventEmitter<IContainerEvents>\n\timplements Partial<Omit<IContainer, \"on\" | \"off\" | \"once\">>\n{\n\tdeltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage> =\n\t\tnew MockDeltaManager() as any;\n\tresolvedUrl?: IResolvedUrl | undefined;\n\tattachState?: AttachState | undefined;\n\tclosed?: boolean | undefined = false;\n\tisDirty?: boolean | undefined;\n\tconnectionState?: ConnectionState | undefined;\n\tconnected?: boolean | undefined;\n\taudience?: IAudience | undefined;\n\tclientId?: string | undefined;\n\treadOnlyInfo?: ReadOnlyInfo | undefined;\n\n\tget mockDeltaManager() {\n\t\treturn this.deltaManager as any as MockDeltaManager;\n\t}\n\n\tconnect() {\n\t\tthis.connectionState = ConnectionState.Connected;\n\t\tthis.emit(\"connected\");\n\t}\n}\n\ndescribe(\"Container\", () => {\n\tdescribe(\"waitContainerToCatchUp\", () => {\n\t\tit(\"Closed Container fails\", async () => {\n\t\t\tconst mockContainer = new MockContainer();\n\t\t\tmockContainer.closed = true;\n\n\t\t\tawait assert.rejects(\n\t\t\t\tasync () => waitContainerToCatchUp(mockContainer as any as IContainer),\n\t\t\t\t\"Passing a closed container should throw\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"Connected Container waits for catching up\", async () => {\n\t\t\tconst mockContainer = new MockContainer();\n\t\t\tmockContainer.connectionState = ConnectionState.Connected;\n\n\t\t\tconst waitP = waitContainerToCatchUp(mockContainer as any as IContainer);\n\t\t\tmockContainer.mockDeltaManager.emit(\"op\", { sequenceNumber: 2 });\n\n\t\t\t// Should resolve immediately, otherwise test will time out\n\t\t\tawait waitP;\n\t\t});\n\n\t\tit(\"Connected and caught up Container resolves immediately\", async () => {\n\t\t\tconst mockContainer = new MockContainer();\n\t\t\tmockContainer.mockDeltaManager.lastSequenceNumber = 2; // to match lastKnownSeqNumber\n\t\t\tmockContainer.connectionState = ConnectionState.Connected;\n\n\t\t\tconst waitP = waitContainerToCatchUp(mockContainer as any as IContainer);\n\n\t\t\t// Should resolve immediately, otherwise test will time out\n\t\t\tawait waitP;\n\t\t});\n\n\t\tit(\"Disconnected Container gets Connected then waits for catching up\", async () => {\n\t\t\tconst mockContainer = new MockContainer();\n\t\t\tmockContainer.connectionState = ConnectionState.Disconnected;\n\n\t\t\tconst waitP = waitContainerToCatchUp(mockContainer as any as IContainer);\n\t\t\tmockContainer.mockDeltaManager.emit(\"op\", { sequenceNumber: 2 });\n\n\t\t\t// Should resolve immediately, otherwise test will time out\n\t\t\tawait waitP;\n\t\t});\n\t});\n});\n"]}
1
+ {"version":3,"file":"container.spec.js","sourceRoot":"","sources":["../../src/test/container.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAYjE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,MAAM,gBACL,SAAQ,iBAAsC;IAD/C;;QAOC,gCAA2B,GAAG,IAAI,CAAC;QACnC,uBAAkB,GAAG,CAAC,CAAC;QACvB,uBAAkB,GAAG,CAAC,CAAC;IACxB,CAAC;CAAA;AAED,MAAM,aACL,SAAQ,iBAAmC;IAD5C;;QAIC,iBAAY,GACX,IAAI,gBAAgB,EAAS,CAAC;QAG/B,WAAM,GAAyB,KAAK,CAAC;IAgBtC,CAAC;IARA,IAAI,gBAAgB;QACnB,OAAO,IAAI,CAAC,YAAuC,CAAC;IACrD,CAAC;IAED,OAAO;QACN,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC,SAAS,CAAC;QACjD,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACxB,CAAC;CACD;AAED,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IAC1B,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;QACvC,EAAE,CAAC,wBAAwB,EAAE,KAAK,IAAI,EAAE;YACvC,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;YAC1C,aAAa,CAAC,MAAM,GAAG,IAAI,CAAC;YAE5B,MAAM,MAAM,CAAC,OAAO,CACnB,KAAK,IAAI,EAAE,CAAC,sBAAsB,CAAC,aAAkC,CAAC,EACtE,yCAAyC,CACzC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;YAC1D,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;YAC1C,aAAa,CAAC,eAAe,GAAG,eAAe,CAAC,SAAS,CAAC;YAE1D,MAAM,KAAK,GAAG,sBAAsB,CAAC,aAAkC,CAAC,CAAC;YACzE,aAAa,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC,CAAC;YAEjE,2DAA2D;YAC3D,MAAM,KAAK,CAAC;QACb,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;YACvE,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;YAC1C,aAAa,CAAC,gBAAgB,CAAC,kBAAkB,GAAG,CAAC,CAAC,CAAC,8BAA8B;YACrF,aAAa,CAAC,eAAe,GAAG,eAAe,CAAC,SAAS,CAAC;YAE1D,MAAM,KAAK,GAAG,sBAAsB,CAAC,aAAkC,CAAC,CAAC;YAEzE,2DAA2D;YAC3D,MAAM,KAAK,CAAC;QACb,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;YACjF,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;YAC1C,aAAa,CAAC,eAAe,GAAG,eAAe,CAAC,YAAY,CAAC;YAE7D,MAAM,KAAK,GAAG,sBAAsB,CAAC,aAAkC,CAAC,CAAC;YACzE,aAAa,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC,CAAC;YAEjE,2DAA2D;YAC3D,MAAM,KAAK,CAAC;QACb,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport assert from \"assert\";\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport {\n\tAttachState,\n\tIAudience,\n\tIContainer,\n\tIContainerEvents,\n\tIDeltaManager,\n\tIDeltaManagerEvents,\n\tReadOnlyInfo,\n} from \"@fluidframework/container-definitions\";\nimport { IResolvedUrl } from \"@fluidframework/driver-definitions\";\nimport { IDocumentMessage, ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { ConnectionState } from \"../connectionState.js\";\nimport { waitContainerToCatchUp } from \"../container.js\";\n\nclass MockDeltaManager\n\textends TypedEventEmitter<IDeltaManagerEvents>\n\timplements\n\t\tPartial<\n\t\t\tOmit<IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>, \"on\" | \"off\" | \"once\">\n\t\t>\n{\n\thasCheckpointSequenceNumber = true;\n\tlastKnownSeqNumber = 2;\n\tlastSequenceNumber = 1;\n}\n\nclass MockContainer\n\textends TypedEventEmitter<IContainerEvents>\n\timplements Partial<Omit<IContainer, \"on\" | \"off\" | \"once\">>\n{\n\tdeltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage> =\n\t\tnew MockDeltaManager() as any;\n\tresolvedUrl?: IResolvedUrl | undefined;\n\tattachState?: AttachState | undefined;\n\tclosed?: boolean | undefined = false;\n\tisDirty?: boolean | undefined;\n\tconnectionState?: ConnectionState | undefined;\n\tconnected?: boolean | undefined;\n\taudience?: IAudience | undefined;\n\tclientId?: string | undefined;\n\treadOnlyInfo?: ReadOnlyInfo | undefined;\n\n\tget mockDeltaManager() {\n\t\treturn this.deltaManager as any as MockDeltaManager;\n\t}\n\n\tconnect() {\n\t\tthis.connectionState = ConnectionState.Connected;\n\t\tthis.emit(\"connected\");\n\t}\n}\n\ndescribe(\"Container\", () => {\n\tdescribe(\"waitContainerToCatchUp\", () => {\n\t\tit(\"Closed Container fails\", async () => {\n\t\t\tconst mockContainer = new MockContainer();\n\t\t\tmockContainer.closed = true;\n\n\t\t\tawait assert.rejects(\n\t\t\t\tasync () => waitContainerToCatchUp(mockContainer as any as IContainer),\n\t\t\t\t\"Passing a closed container should throw\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"Connected Container waits for catching up\", async () => {\n\t\t\tconst mockContainer = new MockContainer();\n\t\t\tmockContainer.connectionState = ConnectionState.Connected;\n\n\t\t\tconst waitP = waitContainerToCatchUp(mockContainer as any as IContainer);\n\t\t\tmockContainer.mockDeltaManager.emit(\"op\", { sequenceNumber: 2 });\n\n\t\t\t// Should resolve immediately, otherwise test will time out\n\t\t\tawait waitP;\n\t\t});\n\n\t\tit(\"Connected and caught up Container resolves immediately\", async () => {\n\t\t\tconst mockContainer = new MockContainer();\n\t\t\tmockContainer.mockDeltaManager.lastSequenceNumber = 2; // to match lastKnownSeqNumber\n\t\t\tmockContainer.connectionState = ConnectionState.Connected;\n\n\t\t\tconst waitP = waitContainerToCatchUp(mockContainer as any as IContainer);\n\n\t\t\t// Should resolve immediately, otherwise test will time out\n\t\t\tawait waitP;\n\t\t});\n\n\t\tit(\"Disconnected Container gets Connected then waits for catching up\", async () => {\n\t\t\tconst mockContainer = new MockContainer();\n\t\t\tmockContainer.connectionState = ConnectionState.Disconnected;\n\n\t\t\tconst waitP = waitContainerToCatchUp(mockContainer as any as IContainer);\n\t\t\tmockContainer.mockDeltaManager.emit(\"op\", { sequenceNumber: 2 });\n\n\t\t\t// Should resolve immediately, otherwise test will time out\n\t\t\tawait waitP;\n\t\t});\n\t});\n});\n"]}
@@ -5,12 +5,12 @@
5
5
  import { strict as assert } from "assert";
6
6
  import { EventEmitter } from "@fluid-internal/client-utils";
7
7
  import { MockDocumentDeltaConnection, MockDocumentService } from "@fluid-private/test-loader-utils";
8
- import { createChildLogger, MockLogger, } from "@fluidframework/telemetry-utils";
9
8
  import { MessageType, } from "@fluidframework/protocol-definitions";
9
+ import { MockLogger, createChildLogger, } from "@fluidframework/telemetry-utils";
10
10
  import { useFakeTimers } from "sinon";
11
+ import { ConnectionManager } from "../connectionManager.js";
11
12
  import { DeltaManager } from "../deltaManager.js";
12
13
  import { NoopHeuristic } from "../noopHeuristic.js";
13
- import { ConnectionManager } from "../connectionManager.js";
14
14
  describe("Loader", () => {
15
15
  describe("Container Loader", () => {
16
16
  describe("Delta Manager", () => {