@fluidframework/merge-tree 2.41.0 → 2.43.0-343119
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/dist/client.d.ts +9 -6
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +79 -36
- package/dist/client.js.map +1 -1
- package/dist/collections/list.d.ts +95 -5
- package/dist/collections/list.d.ts.map +1 -1
- package/dist/collections/list.js +67 -5
- package/dist/collections/list.js.map +1 -1
- package/dist/constants.d.ts +5 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +6 -1
- package/dist/constants.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/mergeTree.d.ts +9 -9
- package/dist/mergeTree.d.ts.map +1 -1
- package/dist/mergeTree.js +15 -7
- package/dist/mergeTree.js.map +1 -1
- package/dist/perspective.d.ts +15 -0
- package/dist/perspective.d.ts.map +1 -1
- package/dist/perspective.js +25 -1
- package/dist/perspective.js.map +1 -1
- package/dist/revertibles.js +1 -1
- package/dist/revertibles.js.map +1 -1
- package/dist/stamps.d.ts +1 -0
- package/dist/stamps.d.ts.map +1 -1
- package/dist/stamps.js +5 -1
- package/dist/stamps.js.map +1 -1
- package/dist/test/beastTest.spec.js +1 -1
- package/dist/test/beastTest.spec.js.map +1 -1
- package/dist/test/client.annotateMarker.spec.js +1 -1
- package/dist/test/client.annotateMarker.spec.js.map +1 -1
- package/dist/test/client.applyMsg.spec.js +25 -25
- package/dist/test/client.applyMsg.spec.js.map +1 -1
- package/dist/test/client.applyStashedOpFarm.spec.d.ts.map +1 -1
- package/dist/test/client.applyStashedOpFarm.spec.js +3 -3
- package/dist/test/client.applyStashedOpFarm.spec.js.map +1 -1
- package/dist/test/client.attributionFarm.spec.js +1 -1
- package/dist/test/client.attributionFarm.spec.js.map +1 -1
- package/dist/test/client.getPosition.spec.js +1 -0
- package/dist/test/client.getPosition.spec.js.map +1 -1
- package/dist/test/client.localReference.spec.js +62 -48
- package/dist/test/client.localReference.spec.js.map +1 -1
- package/dist/test/client.localReferenceFarm.spec.js +1 -0
- package/dist/test/client.localReferenceFarm.spec.js.map +1 -1
- package/dist/test/client.reconnectFarm.spec.js +1 -1
- package/dist/test/client.reconnectFarm.spec.js.map +1 -1
- package/dist/test/client.rollback.spec.js +8 -6
- package/dist/test/client.rollback.spec.js.map +1 -1
- package/dist/test/client.searchForMarker.spec.js +2 -2
- package/dist/test/client.searchForMarker.spec.js.map +1 -1
- package/dist/test/clientTestHelper.js +1 -1
- package/dist/test/clientTestHelper.js.map +1 -1
- package/dist/test/mergeTree.annotate.spec.js +25 -25
- package/dist/test/mergeTree.annotate.spec.js.map +1 -1
- package/dist/test/mergeTree.markRangeRemoved.spec.js +1 -1
- package/dist/test/mergeTree.markRangeRemoved.spec.js.map +1 -1
- package/dist/test/obliterate.spec.js +4 -4
- package/dist/test/obliterate.spec.js.map +1 -1
- package/dist/test/resetPendingSegmentsToOp.spec.js +14 -14
- package/dist/test/resetPendingSegmentsToOp.spec.js.map +1 -1
- package/dist/test/snapshot.utils.js +1 -1
- package/dist/test/snapshot.utils.js.map +1 -1
- package/dist/test/sortedSegmentSet.spec.js +3 -3
- package/dist/test/sortedSegmentSet.spec.js.map +1 -1
- package/dist/test/testClient.js +3 -3
- package/dist/test/testClient.js.map +1 -1
- package/dist/test/tracking.spec.js +7 -7
- package/dist/test/tracking.spec.js.map +1 -1
- package/dist/test/wordUnitTests.spec.js.map +1 -1
- package/lib/client.d.ts +9 -6
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +81 -38
- package/lib/client.js.map +1 -1
- package/lib/collections/list.d.ts +95 -5
- package/lib/collections/list.d.ts.map +1 -1
- package/lib/collections/list.js +67 -5
- package/lib/collections/list.js.map +1 -1
- package/lib/constants.d.ts +5 -0
- package/lib/constants.d.ts.map +1 -1
- package/lib/constants.js +5 -0
- package/lib/constants.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/mergeTree.d.ts +9 -9
- package/lib/mergeTree.d.ts.map +1 -1
- package/lib/mergeTree.js +15 -7
- package/lib/mergeTree.js.map +1 -1
- package/lib/perspective.d.ts +15 -0
- package/lib/perspective.d.ts.map +1 -1
- package/lib/perspective.js +23 -0
- package/lib/perspective.js.map +1 -1
- package/lib/revertibles.js +1 -1
- package/lib/revertibles.js.map +1 -1
- package/lib/stamps.d.ts +1 -0
- package/lib/stamps.d.ts.map +1 -1
- package/lib/stamps.js +4 -1
- package/lib/stamps.js.map +1 -1
- package/lib/test/beastTest.spec.js +1 -1
- package/lib/test/beastTest.spec.js.map +1 -1
- package/lib/test/client.annotateMarker.spec.js +1 -1
- package/lib/test/client.annotateMarker.spec.js.map +1 -1
- package/lib/test/client.applyMsg.spec.js +25 -25
- package/lib/test/client.applyMsg.spec.js.map +1 -1
- package/lib/test/client.applyStashedOpFarm.spec.d.ts.map +1 -1
- package/lib/test/client.applyStashedOpFarm.spec.js +3 -3
- package/lib/test/client.applyStashedOpFarm.spec.js.map +1 -1
- package/lib/test/client.attributionFarm.spec.js +1 -1
- package/lib/test/client.attributionFarm.spec.js.map +1 -1
- package/lib/test/client.getPosition.spec.js +1 -0
- package/lib/test/client.getPosition.spec.js.map +1 -1
- package/lib/test/client.localReference.spec.js +62 -48
- package/lib/test/client.localReference.spec.js.map +1 -1
- package/lib/test/client.localReferenceFarm.spec.js +1 -0
- package/lib/test/client.localReferenceFarm.spec.js.map +1 -1
- package/lib/test/client.reconnectFarm.spec.js +1 -1
- package/lib/test/client.reconnectFarm.spec.js.map +1 -1
- package/lib/test/client.rollback.spec.js +8 -6
- package/lib/test/client.rollback.spec.js.map +1 -1
- package/lib/test/client.searchForMarker.spec.js +2 -2
- package/lib/test/client.searchForMarker.spec.js.map +1 -1
- package/lib/test/clientTestHelper.js +1 -1
- package/lib/test/clientTestHelper.js.map +1 -1
- package/lib/test/mergeTree.annotate.spec.js +25 -25
- package/lib/test/mergeTree.annotate.spec.js.map +1 -1
- package/lib/test/mergeTree.markRangeRemoved.spec.js +1 -1
- package/lib/test/mergeTree.markRangeRemoved.spec.js.map +1 -1
- package/lib/test/obliterate.spec.js +4 -4
- package/lib/test/obliterate.spec.js.map +1 -1
- package/lib/test/resetPendingSegmentsToOp.spec.js +14 -14
- package/lib/test/resetPendingSegmentsToOp.spec.js.map +1 -1
- package/lib/test/snapshot.utils.js +1 -1
- package/lib/test/snapshot.utils.js.map +1 -1
- package/lib/test/sortedSegmentSet.spec.js +3 -3
- package/lib/test/sortedSegmentSet.spec.js.map +1 -1
- package/lib/test/testClient.js +3 -3
- package/lib/test/testClient.js.map +1 -1
- package/lib/test/tracking.spec.js +7 -7
- package/lib/test/tracking.spec.js.map +1 -1
- package/lib/test/wordUnitTests.spec.js.map +1 -1
- package/package.json +16 -16
- package/src/client.ts +117 -50
- package/src/collections/list.ts +101 -5
- package/src/constants.ts +6 -0
- package/src/index.ts +3 -0
- package/src/mergeTree.ts +30 -24
- package/src/perspective.ts +26 -0
- package/src/revertibles.ts +1 -1
- package/src/stamps.ts +9 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clientTestHelper.js","sourceRoot":"","sources":["../../src/test/clientTestHelper.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 \"node:assert\";\n\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport type { IMergeTreeOp, IMergeTreeOptions, InteriorSequencePlace } from \"../index.js\";\nimport type { SegmentGroup } from \"../mergeTreeNodes.js\";\n\nimport type { TestClient } from \"./testClient.js\";\nimport { TestClientLogger, createClientsAtInitialState } from \"./testClientLogger.js\";\n\nconst ClientIds = [\"A\", \"B\", \"C\", \"D\"] as const;\ntype ClientName = (typeof ClientIds)[number];\n\nfunction isClientId(s: unknown): s is ClientName {\n\treturn ClientIds.includes(s as ClientName);\n}\n\nfunction clientNameOf(client: TestClient): ClientName {\n\tconst { longClientId } = client;\n\tassert(isClientId(longClientId), \"Client ID is not a valid client name\");\n\treturn longClientId;\n}\n\n/**\n * Helper for authoring tests which perform operations on a number of clients.\n * This class essentially serves the role of the server in that it maintains a sequencing order of ops as well as information\n * about the latest op that each client has applied.\n *\n * When using this class, *do not* perform operations which may submit ops on clients directly: it does not currently wire up client events\n * to the server. Instead, use methods on the helper and pass the client name they should apply to as the first argument.\n *\n * It is analogous to MockContainerRuntimeFactory in the test-runtime-utils package, though the APIs are not completely equivalent\n * (see for example differences noted on disconnect and reconnect).\n *\n * This helper is also designed to support advancing only some clients to a given sequence number\n * (not all clients must be synchronized at the same time).\n *\n * This allows testing sequences of operations where clients have varying refSeqs, rather than having all clients advance refSeq\n * in lockstep.\n *\n * @remarks\n * If we wired the server up to \"delta\" events on the client, it would be reasonable to rename this to `MockServer` and the API for tests\n * would be a bit cleaner.\n */\nexport class ClientTestHelper {\n\tclients: Record<ClientName, TestClient> & { all: TestClient[] };\n\n\tidxFromName(name: ClientName): number {\n\t\treturn (name.codePointAt(0) ?? 0) - (\"A\".codePointAt(0) ?? 0);\n\t}\n\n\tlogger: TestClientLogger;\n\n\tops: ISequencedDocumentMessage[] = [];\n\tclientToLastAppliedSeq = new Map<ClientName, number>();\n\n\tperClientOps: ISequencedDocumentMessage[][];\n\tprivate readonly disconnectedClientOps = new Map<\n\t\tClientName,\n\t\t{ op: IMergeTreeOp; segmentGroup: SegmentGroup }[]\n\t>();\n\n\tprivate seq: number = 0;\n\n\tpublic constructor(options: IMergeTreeOptions = {}) {\n\t\tthis.clients = createClientsAtInitialState(\n\t\t\t{\n\t\t\t\tinitialState: \"\",\n\t\t\t\toptions: {\n\t\t\t\t\tmergeTreeEnableObliterate: true,\n\t\t\t\t\tmergeTreeEnableObliterateReconnect: true,\n\t\t\t\t\t...options,\n\t\t\t\t},\n\t\t\t},\n\t\t\t...ClientIds,\n\t\t);\n\t\tthis.logger = new TestClientLogger(this.clients.all);\n\t\tthis.perClientOps = this.clients.all.map(() => []);\n\t}\n\n\tprivate addMessage(client: TestClient, op: IMergeTreeOp): void {\n\t\tconst disconnectedQueue = this.disconnectedClientOps.get(clientNameOf(client));\n\t\tif (disconnectedQueue === undefined) {\n\t\t\tconst message = client.makeOpMessage(op, ++this.seq);\n\t\t\tthis.ops.push(message);\n\t\t\t// This implementation (specifically, that of applying ops / synchronizing clients) assumes messages\n\t\t\t// are pushed sequentially starting with seq 1.\n\t\t\tassert(\n\t\t\t\tmessage.sequenceNumber === this.ops.length,\n\t\t\t\t\"Partial sync test helper invariant violated\",\n\t\t\t);\n\t\t} else {\n\t\t\t// Client is not currently connected.\n\t\t\tconst segmentGroup = client.peekPendingSegmentGroups();\n\t\t\tassert(segmentGroup !== undefined, \"Client should have a pending segment group\");\n\t\t\tdisconnectedQueue.push({ op, segmentGroup });\n\t\t}\n\t}\n\n\tpublic insertText(clientName: ClientName, pos: number, text: string): void {\n\t\tconst client = this.clients[clientName];\n\t\tconst insertOp = client.insertTextLocal(pos, text);\n\t\tif (insertOp) {\n\t\t\tthis.addMessage(client, insertOp);\n\t\t}\n\t}\n\n\tpublic removeRange(clientName: ClientName, start: number, end: number): void {\n\t\tconst client = this.clients[clientName];\n\t\tthis.addMessage(client, client.removeRangeLocal(start, end));\n\t}\n\n\tpublic obliterateRange(\n\t\tclientName: ClientName,\n\t\tstart: number | InteriorSequencePlace,\n\t\tend: number | InteriorSequencePlace,\n\t): void {\n\t\tconst client = this.clients[clientName];\n\t\tthis.addMessage(client, client.obliterateRangeLocal(start, end));\n\t}\n\n\tpublic advanceClientToSeq(clientName: ClientName, seq: number): void {\n\t\tconst client = this.clients[clientName];\n\t\tconst lastApplied = this.clientToLastAppliedSeq.get(clientName);\n\t\tassert(seq > 0, \"Can only advance clients to sequence numbers that exist\");\n\t\tassert(\n\t\t\tthis.ops.length >= seq,\n\t\t\t\"Cannot attempt to advance clients to sequence numbers that don't yet exist\",\n\t\t);\n\t\tlet startIndex: number;\n\t\tif (lastApplied === undefined) {\n\t\t\tstartIndex = 0;\n\t\t} else {\n\t\t\tif (lastApplied >= seq) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tstartIndex = lastApplied;\n\t\t}\n\t\tfor (let i = startIndex; i < seq; i++) {\n\t\t\tconst nextMessage = this.ops[i];\n\t\t\tclient.applyMsg(nextMessage);\n\t\t\tthis.clientToLastAppliedSeq.set(clientName, nextMessage.sequenceNumber);\n\t\t}\n\t}\n\n\t/**\n\t * Sends all known ops to the procieded client ids.\n\t */\n\tpublic advanceClients(...clientNames: ClientName[]): void {\n\t\tconst latestSeq = this.ops[this.ops.length - 1].sequenceNumber;\n\t\tfor (const name of clientNames) {\n\t\t\tthis.advanceClientToSeq(name, latestSeq);\n\t\t}\n\t}\n\n\tpublic processAllOps(): void {\n\t\tconst latestSeq = this.ops[this.ops.length - 1].sequenceNumber;\n\t\tfor (const name of ClientIds) {\n\t\t\tthis.advanceClientToSeq(name, latestSeq);\n\t\t}\n\t}\n\n\t/**\n\t * Causes the provided clients to \"disconnect\" by isolating their outbound queue from the op stream.\n\t * These clients will still receive ops from this helper just like all other clients.\n\t * When a client reconnects (see {@link reconnect}), the helper will rebase all of the client's pending ops (that they submitted since\n\t * `disconnect` was called) and re-add them to the op stream.\n\t *\n\t * BEWARE: This is slightly different from what the mocks in test-runtime-utils do in two ways:\n\t *\n\t * 1. Those mocks actually wipe outstanding ops submitted by the disconnected clients from the op stream and rebases those as well.\n\t * 2. Those mocks freeze the inbound queue of the disconnected clients as well as the outbound queue.\n\t *\n\t * E.g. (pseudocode; syntax is different for those mocks and these):\n\t *\n\t * ```typescript\n\t * B.submitLocalOp1()\n\t * B.submitLocalOp2()\n\t * disconnect(B)\n\t * A.submitLocalOp1()\n\t * B.submitLocalOp3()\n\t * processAllOps()\n\t * ```\n\t *\n\t * the test-runtime-mocks will...\n\t *\n\t * - have none of B's local ops be receieved by A in the processAllOps() line\n\t * - have B not receive A's local op 1\n\t *\n\t * whereas this helper will...\n\t *\n\t * - have B's local ops 1 and 2 be received by A, but not its third local op\n\t * - have B receive acks for its first two local ops as well as A's op in the processAllOps() line\n\t *\n\t * This operation is a no-op if called multiple times on the same client with no intervening reconnects.\n\t */\n\tpublic disconnect(...clientNames: ClientName[]): void {\n\t\tfor (const clientName of clientNames) {\n\t\t\tconst client = this.clients[clientName];\n\t\t\tif (this.isDisconnected(client)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.disconnectedClientOps.set(clientName, []);\n\t\t}\n\t}\n\n\t/**\n\t * Reconnects clients which have been disconnected. No-ops on any client which is already connected.\n\t * For disconnected clients, any pending ops they have will be resubmitted using the resubmit flow, see {@link disconnect} for details and an example.\n\t *\n\t * @remarks\n\t * If reconnecting multiple clients, the order that their ops will be resubmitted in will match the order in the array\n\t */\n\tpublic reconnect(...clientNames: ClientName[]): void {\n\t\tfor (const clientName of clientNames) {\n\t\t\tconst submittedOps = this.disconnectedClientOps.get(clientName);\n\t\t\tif (submittedOps === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.disconnectedClientOps.delete(clientName);\n\t\t\tconst client = this.clients[clientName];\n\t\t\tfor (const { op, segmentGroup } of submittedOps) {\n\t\t\t\tconst rebasedOp = client.regeneratePendingOp(op, segmentGroup);\n\t\t\t\tthis.addMessage(client, rebasedOp);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate isDisconnected(client: TestClient): boolean {\n\t\treturn this.disconnectedClientOps.has(clientNameOf(client));\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"clientTestHelper.js","sourceRoot":"","sources":["../../src/test/clientTestHelper.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 \"node:assert\";\n\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport type { IMergeTreeOp, IMergeTreeOptions, InteriorSequencePlace } from \"../index.js\";\nimport type { SegmentGroup } from \"../mergeTreeNodes.js\";\n\nimport type { TestClient } from \"./testClient.js\";\nimport { TestClientLogger, createClientsAtInitialState } from \"./testClientLogger.js\";\n\nconst ClientIds = [\"A\", \"B\", \"C\", \"D\"] as const;\ntype ClientName = (typeof ClientIds)[number];\n\nfunction isClientId(s: unknown): s is ClientName {\n\treturn ClientIds.includes(s as ClientName);\n}\n\nfunction clientNameOf(client: TestClient): ClientName {\n\tconst { longClientId } = client;\n\tassert(isClientId(longClientId), \"Client ID is not a valid client name\");\n\treturn longClientId;\n}\n\n/**\n * Helper for authoring tests which perform operations on a number of clients.\n * This class essentially serves the role of the server in that it maintains a sequencing order of ops as well as information\n * about the latest op that each client has applied.\n *\n * When using this class, *do not* perform operations which may submit ops on clients directly: it does not currently wire up client events\n * to the server. Instead, use methods on the helper and pass the client name they should apply to as the first argument.\n *\n * It is analogous to MockContainerRuntimeFactory in the test-runtime-utils package, though the APIs are not completely equivalent\n * (see for example differences noted on disconnect and reconnect).\n *\n * This helper is also designed to support advancing only some clients to a given sequence number\n * (not all clients must be synchronized at the same time).\n *\n * This allows testing sequences of operations where clients have varying refSeqs, rather than having all clients advance refSeq\n * in lockstep.\n *\n * @remarks\n * If we wired the server up to \"delta\" events on the client, it would be reasonable to rename this to `MockServer` and the API for tests\n * would be a bit cleaner.\n */\nexport class ClientTestHelper {\n\tclients: Record<ClientName, TestClient> & { all: TestClient[] };\n\n\tidxFromName(name: ClientName): number {\n\t\treturn (name.codePointAt(0) ?? 0) - (\"A\".codePointAt(0) ?? 0);\n\t}\n\n\tlogger: TestClientLogger;\n\n\tops: ISequencedDocumentMessage[] = [];\n\tclientToLastAppliedSeq = new Map<ClientName, number>();\n\n\tperClientOps: ISequencedDocumentMessage[][];\n\tprivate readonly disconnectedClientOps = new Map<\n\t\tClientName,\n\t\t{ op: IMergeTreeOp; segmentGroup: SegmentGroup }[]\n\t>();\n\n\tprivate seq: number = 0;\n\n\tpublic constructor(options: IMergeTreeOptions = {}) {\n\t\tthis.clients = createClientsAtInitialState(\n\t\t\t{\n\t\t\t\tinitialState: \"\",\n\t\t\t\toptions: {\n\t\t\t\t\tmergeTreeEnableObliterate: true,\n\t\t\t\t\tmergeTreeEnableObliterateReconnect: true,\n\t\t\t\t\t...options,\n\t\t\t\t},\n\t\t\t},\n\t\t\t...ClientIds,\n\t\t);\n\t\tthis.logger = new TestClientLogger(this.clients.all);\n\t\tthis.perClientOps = this.clients.all.map(() => []);\n\t}\n\n\tprivate addMessage(client: TestClient, op: IMergeTreeOp): void {\n\t\tconst disconnectedQueue = this.disconnectedClientOps.get(clientNameOf(client));\n\t\tif (disconnectedQueue === undefined) {\n\t\t\tconst message = client.makeOpMessage(op, ++this.seq);\n\t\t\tthis.ops.push(message);\n\t\t\t// This implementation (specifically, that of applying ops / synchronizing clients) assumes messages\n\t\t\t// are pushed sequentially starting with seq 1.\n\t\t\tassert(\n\t\t\t\tmessage.sequenceNumber === this.ops.length,\n\t\t\t\t\"Partial sync test helper invariant violated\",\n\t\t\t);\n\t\t} else {\n\t\t\t// Client is not currently connected.\n\t\t\tconst segmentGroup = client.peekPendingSegmentGroups();\n\t\t\tassert(segmentGroup !== undefined, \"Client should have a pending segment group\");\n\t\t\tdisconnectedQueue.push({ op, segmentGroup });\n\t\t}\n\t}\n\n\tpublic insertText(clientName: ClientName, pos: number, text: string): void {\n\t\tconst client = this.clients[clientName];\n\t\tconst insertOp = client.insertTextLocal(pos, text);\n\t\tif (insertOp) {\n\t\t\tthis.addMessage(client, insertOp);\n\t\t}\n\t}\n\n\tpublic removeRange(clientName: ClientName, start: number, end: number): void {\n\t\tconst client = this.clients[clientName];\n\t\tthis.addMessage(client, client.removeRangeLocal(start, end));\n\t}\n\n\tpublic obliterateRange(\n\t\tclientName: ClientName,\n\t\tstart: number | InteriorSequencePlace,\n\t\tend: number | InteriorSequencePlace,\n\t): void {\n\t\tconst client = this.clients[clientName];\n\t\tthis.addMessage(client, client.obliterateRangeLocal(start, end));\n\t}\n\n\tpublic advanceClientToSeq(clientName: ClientName, seq: number): void {\n\t\tconst client = this.clients[clientName];\n\t\tconst lastApplied = this.clientToLastAppliedSeq.get(clientName);\n\t\tassert(seq > 0, \"Can only advance clients to sequence numbers that exist\");\n\t\tassert(\n\t\t\tthis.ops.length >= seq,\n\t\t\t\"Cannot attempt to advance clients to sequence numbers that don't yet exist\",\n\t\t);\n\t\tlet startIndex: number;\n\t\tif (lastApplied === undefined) {\n\t\t\tstartIndex = 0;\n\t\t} else {\n\t\t\tif (lastApplied >= seq) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tstartIndex = lastApplied;\n\t\t}\n\t\tfor (let i = startIndex; i < seq; i++) {\n\t\t\tconst nextMessage = this.ops[i];\n\t\t\tclient.applyMsg(nextMessage);\n\t\t\tthis.clientToLastAppliedSeq.set(clientName, nextMessage.sequenceNumber);\n\t\t}\n\t}\n\n\t/**\n\t * Sends all known ops to the procieded client ids.\n\t */\n\tpublic advanceClients(...clientNames: ClientName[]): void {\n\t\tconst latestSeq = this.ops[this.ops.length - 1].sequenceNumber;\n\t\tfor (const name of clientNames) {\n\t\t\tthis.advanceClientToSeq(name, latestSeq);\n\t\t}\n\t}\n\n\tpublic processAllOps(): void {\n\t\tconst latestSeq = this.ops[this.ops.length - 1].sequenceNumber;\n\t\tfor (const name of ClientIds) {\n\t\t\tthis.advanceClientToSeq(name, latestSeq);\n\t\t}\n\t}\n\n\t/**\n\t * Causes the provided clients to \"disconnect\" by isolating their outbound queue from the op stream.\n\t * These clients will still receive ops from this helper just like all other clients.\n\t * When a client reconnects (see {@link reconnect}), the helper will rebase all of the client's pending ops (that they submitted since\n\t * `disconnect` was called) and re-add them to the op stream.\n\t *\n\t * BEWARE: This is slightly different from what the mocks in test-runtime-utils do in two ways:\n\t *\n\t * 1. Those mocks actually wipe outstanding ops submitted by the disconnected clients from the op stream and rebases those as well.\n\t * 2. Those mocks freeze the inbound queue of the disconnected clients as well as the outbound queue.\n\t *\n\t * E.g. (pseudocode; syntax is different for those mocks and these):\n\t *\n\t * ```typescript\n\t * B.submitLocalOp1()\n\t * B.submitLocalOp2()\n\t * disconnect(B)\n\t * A.submitLocalOp1()\n\t * B.submitLocalOp3()\n\t * processAllOps()\n\t * ```\n\t *\n\t * the test-runtime-mocks will...\n\t *\n\t * - have none of B's local ops be receieved by A in the processAllOps() line\n\t * - have B not receive A's local op 1\n\t *\n\t * whereas this helper will...\n\t *\n\t * - have B's local ops 1 and 2 be received by A, but not its third local op\n\t * - have B receive acks for its first two local ops as well as A's op in the processAllOps() line\n\t *\n\t * This operation is a no-op if called multiple times on the same client with no intervening reconnects.\n\t */\n\tpublic disconnect(...clientNames: ClientName[]): void {\n\t\tfor (const clientName of clientNames) {\n\t\t\tconst client = this.clients[clientName];\n\t\t\tif (this.isDisconnected(client)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.disconnectedClientOps.set(clientName, []);\n\t\t}\n\t}\n\n\t/**\n\t * Reconnects clients which have been disconnected. No-ops on any client which is already connected.\n\t * For disconnected clients, any pending ops they have will be resubmitted using the resubmit flow, see {@link disconnect} for details and an example.\n\t *\n\t * @remarks\n\t * If reconnecting multiple clients, the order that their ops will be resubmitted in will match the order in the array\n\t */\n\tpublic reconnect(...clientNames: ClientName[]): void {\n\t\tfor (const clientName of clientNames) {\n\t\t\tconst submittedOps = this.disconnectedClientOps.get(clientName);\n\t\t\tif (submittedOps === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.disconnectedClientOps.delete(clientName);\n\t\t\tconst client = this.clients[clientName];\n\t\t\tfor (const { op, segmentGroup } of submittedOps) {\n\t\t\t\tconst rebasedOp = client.regeneratePendingOp(op, segmentGroup, false);\n\t\t\t\tthis.addMessage(client, rebasedOp);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate isDisconnected(client: TestClient): boolean {\n\t\treturn this.disconnectedClientOps.has(clientNameOf(client));\n\t}\n}\n"]}
|
|
@@ -42,7 +42,7 @@ describe("MergeTree", () => {
|
|
|
42
42
|
props: { propertySource: "remote" },
|
|
43
43
|
}, remoteClient.perspectiveAt({ refSeq: currentSequenceNumber }), remoteClient.stampAt({ seq: currentSequenceNumber + 1 }), undefined);
|
|
44
44
|
const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
|
|
45
|
-
const segment = segmentInfo
|
|
45
|
+
const segment = segmentInfo?.segment;
|
|
46
46
|
node_assert_1.strict.equal(segment?.properties?.propertySource, "remote");
|
|
47
47
|
});
|
|
48
48
|
it("local", () => {
|
|
@@ -50,7 +50,7 @@ describe("MergeTree", () => {
|
|
|
50
50
|
props: { propertySource: "local" },
|
|
51
51
|
}, mergeTree.localPerspective, mergeTree.collabWindow.mintNextLocalOperationStamp(), undefined);
|
|
52
52
|
const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
|
|
53
|
-
const segment = segmentInfo
|
|
53
|
+
const segment = segmentInfo?.segment;
|
|
54
54
|
node_assert_1.strict.equal(segment.properties?.propertySource, "local");
|
|
55
55
|
});
|
|
56
56
|
});
|
|
@@ -69,7 +69,7 @@ describe("MergeTree", () => {
|
|
|
69
69
|
});
|
|
70
70
|
it("unsequenced local", () => {
|
|
71
71
|
const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
|
|
72
|
-
const segment = segmentInfo
|
|
72
|
+
const segment = segmentInfo?.segment;
|
|
73
73
|
node_assert_1.strict.equal(segment.properties?.propertySource, "local");
|
|
74
74
|
});
|
|
75
75
|
it("unsequenced local after unsequenced local", () => {
|
|
@@ -77,7 +77,7 @@ describe("MergeTree", () => {
|
|
|
77
77
|
props: { secondProperty: "local" },
|
|
78
78
|
}, mergeTree.localPerspective, mergeTree.collabWindow.mintNextLocalOperationStamp(), undefined);
|
|
79
79
|
const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
|
|
80
|
-
const segment = segmentInfo
|
|
80
|
+
const segment = segmentInfo?.segment;
|
|
81
81
|
node_assert_1.strict.equal(segment.properties?.secondProperty, "local");
|
|
82
82
|
});
|
|
83
83
|
it("unsequenced local split", () => {
|
|
@@ -85,7 +85,7 @@ describe("MergeTree", () => {
|
|
|
85
85
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
86
86
|
const splitSegment = splitAt(mergeTree, splitPos);
|
|
87
87
|
(0, segmentInfos_js_1.assertMergeNode)(splitSegment);
|
|
88
|
-
node_assert_1.strict.notEqual(segmentInfo
|
|
88
|
+
node_assert_1.strict.notEqual(segmentInfo?.segment?.ordinal, splitSegment.ordinal);
|
|
89
89
|
node_assert_1.strict.equal(splitSegment.properties?.propertySource, "local");
|
|
90
90
|
});
|
|
91
91
|
it("unsequenced local after unsequenced local split", () => {
|
|
@@ -102,9 +102,9 @@ describe("MergeTree", () => {
|
|
|
102
102
|
};
|
|
103
103
|
mergeTree.annotateRange(splitPos, annotateEnd, splitOnlyProps, mergeTree.localPerspective, mergeTree.collabWindow.mintNextLocalOperationStamp(), undefined);
|
|
104
104
|
const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
|
|
105
|
-
const segment = segmentInfo
|
|
105
|
+
const segment = segmentInfo?.segment;
|
|
106
106
|
const splitSegmentInfo = mergeTree.getContainingSegment(splitPos, mergeTree.localPerspective);
|
|
107
|
-
const splitSegment = splitSegmentInfo
|
|
107
|
+
const splitSegment = splitSegmentInfo?.segment;
|
|
108
108
|
node_assert_1.strict.equal(segment.segmentGroups?.size, 2);
|
|
109
109
|
node_assert_1.strict.equal(segment.properties?.propertySource, "local");
|
|
110
110
|
node_assert_1.strict.equal(segment.properties?.secondChange, 1);
|
|
@@ -176,7 +176,7 @@ describe("MergeTree", () => {
|
|
|
176
176
|
props: { propertySource: "remote", remoteProperty: 1 },
|
|
177
177
|
}, remoteClient.perspectiveAt({ refSeq: currentSequenceNumber }), remoteClient.stampAt({ seq: ++currentSequenceNumber }), undefined);
|
|
178
178
|
const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
|
|
179
|
-
const segment = segmentInfo
|
|
179
|
+
const segment = segmentInfo?.segment;
|
|
180
180
|
node_assert_1.strict.equal(segment.segmentGroups?.size, 1);
|
|
181
181
|
node_assert_1.strict.equal(segment.properties?.propertySource, "local");
|
|
182
182
|
node_assert_1.strict.equal(segment.properties?.remoteProperty, 1);
|
|
@@ -194,7 +194,7 @@ describe("MergeTree", () => {
|
|
|
194
194
|
},
|
|
195
195
|
});
|
|
196
196
|
const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
|
|
197
|
-
const segment = segmentInfo
|
|
197
|
+
const segment = segmentInfo?.segment;
|
|
198
198
|
node_assert_1.strict.equal(segment.segmentGroups?.size, 0);
|
|
199
199
|
node_assert_1.strict.equal(segment.properties?.propertySource, "local");
|
|
200
200
|
});
|
|
@@ -214,14 +214,14 @@ describe("MergeTree", () => {
|
|
|
214
214
|
props: { propertySource: "remote", remoteProperty: 1 },
|
|
215
215
|
}, remoteClient.perspectiveAt({ refSeq: currentSequenceNumber }), remoteClient.stampAt({ seq: ++currentSequenceNumber }), undefined);
|
|
216
216
|
const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
|
|
217
|
-
const segment = segmentInfo
|
|
217
|
+
const segment = segmentInfo?.segment;
|
|
218
218
|
node_assert_1.strict.equal(segment.segmentGroups?.size, 0);
|
|
219
219
|
node_assert_1.strict.equal(segment.properties?.propertySource, "remote");
|
|
220
220
|
node_assert_1.strict.equal(segment.properties?.remoteProperty, 1);
|
|
221
221
|
});
|
|
222
222
|
it("three local changes", () => {
|
|
223
223
|
const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
|
|
224
|
-
const segment = segmentInfo
|
|
224
|
+
const segment = segmentInfo?.segment;
|
|
225
225
|
node_assert_1.strict.equal(segment.properties?.propertySource, "local");
|
|
226
226
|
const props2 = {
|
|
227
227
|
props: { propertySource: "local2", secondSource: 1 },
|
|
@@ -300,7 +300,7 @@ describe("MergeTree", () => {
|
|
|
300
300
|
props: { propertySource: "remote", remoteOnly: 1, secondSource: "remote" },
|
|
301
301
|
}, remoteClient.perspectiveAt({ refSeq: currentSequenceNumber }), remoteClient.stampAt({ seq: ++currentSequenceNumber }), undefined);
|
|
302
302
|
const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
|
|
303
|
-
const segment = segmentInfo
|
|
303
|
+
const segment = segmentInfo?.segment;
|
|
304
304
|
node_assert_1.strict.equal(segment.properties?.remoteOnly, 1);
|
|
305
305
|
node_assert_1.strict.equal(segment.properties?.propertySource, "remote");
|
|
306
306
|
node_assert_1.strict.equal(segment.properties?.secondSource, "local2");
|
|
@@ -312,11 +312,11 @@ describe("MergeTree", () => {
|
|
|
312
312
|
props: { propertySource: "remote", remoteProperty: 1 },
|
|
313
313
|
}, remoteClient.perspectiveAt({ refSeq: currentSequenceNumber }), remoteClient.stampAt({ seq: ++currentSequenceNumber }), undefined);
|
|
314
314
|
const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
|
|
315
|
-
(0, node_assert_1.strict)(segmentInfo
|
|
315
|
+
(0, node_assert_1.strict)(segmentInfo?.segment?.segmentGroups?.size !== 0);
|
|
316
316
|
});
|
|
317
317
|
it("remote only", () => {
|
|
318
318
|
const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
|
|
319
|
-
const segment = segmentInfo
|
|
319
|
+
const segment = segmentInfo?.segment;
|
|
320
320
|
node_assert_1.strict.equal(segment.properties?.propertySource, "remote");
|
|
321
321
|
node_assert_1.strict.equal(segment.properties?.remoteProperty, 1);
|
|
322
322
|
});
|
|
@@ -325,7 +325,7 @@ describe("MergeTree", () => {
|
|
|
325
325
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
326
326
|
const splitSegment = splitAt(mergeTree, annotateStart + 1);
|
|
327
327
|
(0, segmentInfos_js_1.assertMergeNode)(splitSegment);
|
|
328
|
-
node_assert_1.strict.notEqual(segmentInfo
|
|
328
|
+
node_assert_1.strict.notEqual(segmentInfo?.segment?.ordinal, splitSegment.ordinal);
|
|
329
329
|
node_assert_1.strict.equal(splitSegment.properties?.propertySource, "remote");
|
|
330
330
|
node_assert_1.strict.equal(splitSegment.properties?.remoteProperty, 1);
|
|
331
331
|
});
|
|
@@ -334,7 +334,7 @@ describe("MergeTree", () => {
|
|
|
334
334
|
props: { propertySource: "local" },
|
|
335
335
|
}, mergeTree.localPerspective, mergeTree.collabWindow.mintNextLocalOperationStamp(), undefined);
|
|
336
336
|
const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
|
|
337
|
-
const segment = segmentInfo
|
|
337
|
+
const segment = segmentInfo?.segment;
|
|
338
338
|
node_assert_1.strict.equal(segment.properties?.propertySource, "local");
|
|
339
339
|
node_assert_1.strict.equal(segment.properties?.remoteProperty, 1);
|
|
340
340
|
});
|
|
@@ -343,9 +343,9 @@ describe("MergeTree", () => {
|
|
|
343
343
|
props: { propertySource: "local" },
|
|
344
344
|
};
|
|
345
345
|
const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
|
|
346
|
-
(0, node_assert_1.strict)(segmentInfo
|
|
346
|
+
(0, node_assert_1.strict)(segmentInfo?.segment?.segmentGroups?.empty !== false);
|
|
347
347
|
mergeTree.annotateRange(annotateStart, annotateEnd, props, mergeTree.localPerspective, mergeTree.collabWindow.mintNextLocalOperationStamp(), undefined);
|
|
348
|
-
node_assert_1.strict.equal(segmentInfo
|
|
348
|
+
node_assert_1.strict.equal(segmentInfo?.segment?.segmentGroups?.size, 1);
|
|
349
349
|
mergeTree.ackOp({
|
|
350
350
|
op: {
|
|
351
351
|
pos1: annotateStart,
|
|
@@ -357,9 +357,9 @@ describe("MergeTree", () => {
|
|
|
357
357
|
sequenceNumber: ++currentSequenceNumber,
|
|
358
358
|
},
|
|
359
359
|
});
|
|
360
|
-
(0, node_assert_1.strict)(segmentInfo
|
|
361
|
-
node_assert_1.strict.equal(segmentInfo
|
|
362
|
-
node_assert_1.strict.equal(segmentInfo
|
|
360
|
+
(0, node_assert_1.strict)(segmentInfo?.segment?.segmentGroups?.empty);
|
|
361
|
+
node_assert_1.strict.equal(segmentInfo?.segment?.properties?.propertySource, "local");
|
|
362
|
+
node_assert_1.strict.equal(segmentInfo?.segment?.properties?.remoteProperty, 1);
|
|
363
363
|
});
|
|
364
364
|
});
|
|
365
365
|
describe("local with rewrite first", () => {
|
|
@@ -374,7 +374,7 @@ describe("MergeTree", () => {
|
|
|
374
374
|
props: { propertySource: "local2", secondProperty: "local" },
|
|
375
375
|
}, mergeTree.localPerspective, mergeTree.collabWindow.mintNextLocalOperationStamp(), undefined);
|
|
376
376
|
const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
|
|
377
|
-
const segment = segmentInfo
|
|
377
|
+
const segment = segmentInfo?.segment;
|
|
378
378
|
node_assert_1.strict.equal(segment.properties?.propertySource, "local2");
|
|
379
379
|
node_assert_1.strict.equal(segment.properties?.secondProperty, "local");
|
|
380
380
|
});
|
|
@@ -383,7 +383,7 @@ describe("MergeTree", () => {
|
|
|
383
383
|
props: { propertySource: "remote", remoteProperty: 1 },
|
|
384
384
|
}, remoteClient.perspectiveAt({ refSeq: currentSequenceNumber }), remoteClient.stampAt({ seq: ++currentSequenceNumber }), undefined);
|
|
385
385
|
const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
|
|
386
|
-
const segment = segmentInfo
|
|
386
|
+
const segment = segmentInfo?.segment;
|
|
387
387
|
node_assert_1.strict.equal(segment.segmentGroups?.size, 1);
|
|
388
388
|
node_assert_1.strict.equal(segment.properties?.propertySource, "local");
|
|
389
389
|
node_assert_1.strict.equal(segment.properties?.remoteProperty, 1);
|
|
@@ -404,7 +404,7 @@ describe("MergeTree", () => {
|
|
|
404
404
|
props: { propertySource: "remote", remoteProperty: 1 },
|
|
405
405
|
}, remoteClient.perspectiveAt({ refSeq: currentSequenceNumber }), remoteClient.stampAt({ seq: ++currentSequenceNumber }), undefined);
|
|
406
406
|
const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
|
|
407
|
-
const segment = segmentInfo
|
|
407
|
+
const segment = segmentInfo?.segment;
|
|
408
408
|
node_assert_1.strict.equal(segment.segmentGroups?.size, 0);
|
|
409
409
|
node_assert_1.strict.equal(segment.properties?.propertySource, "remote");
|
|
410
410
|
node_assert_1.strict.equal(segment.properties?.remoteProperty, 1);
|
|
@@ -428,7 +428,7 @@ describe("MergeTree", () => {
|
|
|
428
428
|
props: { propertySource: "remote", remoteOnly: 1, secondSource: "remote" },
|
|
429
429
|
}, remoteClient.perspectiveAt({ refSeq: currentSequenceNumber }), remoteClient.stampAt({ seq: ++currentSequenceNumber }), undefined);
|
|
430
430
|
const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
|
|
431
|
-
const segment = segmentInfo
|
|
431
|
+
const segment = segmentInfo?.segment;
|
|
432
432
|
node_assert_1.strict.equal(segment.properties?.remoteOnly, 1);
|
|
433
433
|
node_assert_1.strict.equal(segment.properties?.propertySource, "remote");
|
|
434
434
|
node_assert_1.strict.equal(segment.properties?.secondSource, "local2");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mergeTree.annotate.spec.js","sourceRoot":"","sources":["../../src/test/mergeTree.annotate.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 \"node:assert\";\n\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport { MergeTree } from \"../mergeTree.js\";\nimport { Marker, type ISegmentPrivate } from \"../mergeTreeNodes.js\";\nimport { MergeTreeDeltaType, ReferenceType } from \"../ops.js\";\nimport { LocalDefaultPerspective } from \"../perspective.js\";\nimport { assertMergeNode } from \"../segmentInfos.js\";\nimport type { PropsOrAdjust } from \"../segmentPropertiesManager.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { makeRemoteClient } from \"./testUtils.js\";\n\nfunction splitAt(mergeTree: MergeTree, pos: number): ISegmentPrivate | undefined {\n\tlet segment: ISegmentPrivate | undefined;\n\tmergeTree.mapRange(\n\t\t(seg) => {\n\t\t\tsegment = seg;\n\t\t\treturn false;\n\t\t},\n\t\tnew LocalDefaultPerspective(mergeTree.collabWindow.clientId),\n\t\tundefined,\n\t\tpos,\n\t\tpos + 1,\n\t\ttrue,\n\t);\n\treturn segment;\n}\n\ndescribe(\"MergeTree\", () => {\n\tlet mergeTree: MergeTree;\n\tconst remoteClient = makeRemoteClient({ clientId: 35 });\n\tconst localClientId = 17;\n\tlet currentSequenceNumber: number;\n\n\tconst annotateStart = 1;\n\tconst markerPosition = annotateStart + 2;\n\tconst annotateEnd = markerPosition + 2;\n\tconst splitPos = Math.floor((annotateEnd - annotateStart) / 2) + annotateStart;\n\n\tbeforeEach(() => {\n\t\tmergeTree = new MergeTree();\n\t\tmergeTree.insertSegments(\n\t\t\t0,\n\t\t\t[TextSegment.make(\"hello world!\")],\n\t\t\tmergeTree.localPerspective,\n\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\tundefined,\n\t\t);\n\n\t\tcurrentSequenceNumber = 0;\n\t\tmergeTree.insertSegments(\n\t\t\tmarkerPosition,\n\t\t\t[Marker.make(ReferenceType.Tile)],\n\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\tundefined,\n\t\t);\n\t});\n\n\tdescribe(\"annotateRange\", () => {\n\t\tdescribe(\"not collaborating\", () => {\n\t\t\tit(\"remote\", () => {\n\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\tannotateStart,\n\t\t\t\t\tannotateEnd,\n\t\t\t\t\t{\n\t\t\t\t\t\tprops: { propertySource: \"remote\" },\n\t\t\t\t\t},\n\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\tremoteClient.stampAt({ seq: currentSequenceNumber + 1 }),\n\t\t\t\t\tundefined as never,\n\t\t\t\t);\n\n\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\tannotateStart,\n\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t);\n\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\t\t\t\tassert.equal(segment?.properties?.propertySource, \"remote\");\n\t\t\t});\n\n\t\t\tit(\"local\", () => {\n\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\tannotateStart,\n\t\t\t\t\tannotateEnd,\n\t\t\t\t\t{\n\t\t\t\t\t\tprops: { propertySource: \"local\" },\n\t\t\t\t\t},\n\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\tundefined as never,\n\t\t\t\t);\n\n\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\tannotateStart,\n\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t);\n\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t});\n\t\t});\n\t\tdescribe(\"collaborating\", () => {\n\t\t\tbeforeEach(() => {\n\t\t\t\tmergeTree.startCollaboration(\n\t\t\t\t\tlocalClientId,\n\t\t\t\t\t/* minSeq: */ currentSequenceNumber,\n\t\t\t\t\t/* currentSeq: */ currentSequenceNumber,\n\t\t\t\t);\n\t\t\t});\n\t\t\tdescribe(\"local first\", () => {\n\t\t\t\tconst props: PropsOrAdjust = {\n\t\t\t\t\tprops: { propertySource: \"local\" },\n\t\t\t\t};\n\t\t\t\tbeforeEach(() => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tprops,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local\", () => {\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local after unsequenced local\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { secondProperty: \"local\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.properties?.secondProperty, \"local\");\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local split\", () => {\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\tconst splitSegment = splitAt(mergeTree, splitPos)!;\n\t\t\t\t\tassertMergeNode(splitSegment);\n\t\t\t\t\tassert.notEqual(segmentInfo.segment?.ordinal, splitSegment.ordinal);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"local\");\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local after unsequenced local split\", () => {\n\t\t\t\t\tconst secondChangeProps: PropsOrAdjust = {\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tsecondChange: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tsecondChangeProps,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst splitOnlyProps: PropsOrAdjust = {\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tsplitOnly: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tsplitPos,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tsplitOnlyProps,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\n\t\t\t\t\tconst splitSegmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tsplitPos,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst splitSegment = splitSegmentInfo.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 2);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.secondChange, 1);\n\t\t\t\t\tassert(!segment.properties?.splitOnly);\n\n\t\t\t\t\tassert.equal(splitSegment.segmentGroups?.size, 3);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(splitSegment.properties?.secondChange, 1);\n\t\t\t\t\tassert.equal(splitSegment.properties?.splitOnly, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 1);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.secondChange, 1);\n\t\t\t\t\tassert(!segment.properties?.splitOnly);\n\n\t\t\t\t\tassert.equal(splitSegment?.segmentGroups?.size, 2);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(splitSegment.properties?.secondChange, 1);\n\t\t\t\t\tassert.equal(splitSegment.properties?.splitOnly, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...secondChangeProps,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.secondChange, 1);\n\t\t\t\t\tassert(!segment.properties?.splitOnly);\n\n\t\t\t\t\tassert.equal(splitSegment.segmentGroups?.size, 1);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(splitSegment.properties?.secondChange, 1);\n\t\t\t\t\tassert.equal(splitSegment.properties?.splitOnly, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: splitPos,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...splitOnlyProps,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.secondChange, 1);\n\t\t\t\t\tassert(!segment.properties?.splitOnly);\n\n\t\t\t\t\tassert.equal(splitSegment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(splitSegment.properties?.secondChange, 1);\n\t\t\t\t\tassert.equal(splitSegment.properties?.splitOnly, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local before remote\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteProperty: 1 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 1);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"sequenced local\", () => {\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t});\n\n\t\t\t\tit(\"sequenced local before remote\", () => {\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteProperty: 1 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"three local changes\", () => {\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\n\t\t\t\t\tconst props2: PropsOrAdjust = {\n\t\t\t\t\t\tprops: { propertySource: \"local2\", secondSource: 1 },\n\t\t\t\t\t};\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tprops2,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, 1);\n\n\t\t\t\t\tconst props3: PropsOrAdjust = {\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tthirdSource: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tprops3,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, 1);\n\t\t\t\t\tassert.equal(segment.properties?.thirdSource, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, 1);\n\t\t\t\t\tassert.equal(segment.properties?.thirdSource, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props2,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, 1);\n\t\t\t\t\tassert.equal(segment.properties?.thirdSource, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props3,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, 1);\n\t\t\t\t\tassert.equal(segment.properties?.thirdSource, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"two local changes with interleaved remote\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { secondSource: \"local2\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteOnly: 1, secondSource: \"remote\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.properties?.remoteOnly, 1);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, \"local2\");\n\t\t\t\t});\n\t\t\t});\n\t\t\tdescribe(\"remote first\", () => {\n\t\t\t\tbeforeEach(() => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteProperty: 1 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tassert(segmentInfo.segment?.segmentGroups?.size !== 0);\n\t\t\t\t});\n\t\t\t\tit(\"remote only\", () => {\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"split remote\", () => {\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\tconst splitSegment = splitAt(mergeTree, annotateStart + 1)!;\n\t\t\t\t\tassertMergeNode(splitSegment);\n\t\t\t\t\tassert.notEqual(segmentInfo.segment?.ordinal, splitSegment.ordinal);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(splitSegment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"remote before unsequenced local\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"local\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"remote before sequenced local\", () => {\n\t\t\t\t\tconst props: PropsOrAdjust = {\n\t\t\t\t\t\tprops: { propertySource: \"local\" },\n\t\t\t\t\t};\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tassert(segmentInfo.segment?.segmentGroups?.empty !== false);\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tprops,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tassert.equal(segmentInfo.segment?.segmentGroups?.size, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert(segmentInfo.segment?.segmentGroups?.empty);\n\t\t\t\t\tassert.equal(segmentInfo.segment?.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segmentInfo.segment?.properties?.remoteProperty, 1);\n\t\t\t\t});\n\t\t\t});\n\t\t\tdescribe(\"local with rewrite first\", () => {\n\t\t\t\tconst props: PropsOrAdjust = {\n\t\t\t\t\tprops: { propertySource: \"local\" },\n\t\t\t\t};\n\t\t\t\tbeforeEach(() => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tprops,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local after unsequenced local\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"local2\", secondProperty: \"local\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondProperty, \"local\");\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local before remote\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteProperty: 1 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 1);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"sequenced local before remote\", () => {\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteProperty: 1 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"two local changes with interleaved remote\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { secondSource: \"local2\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteOnly: 1, secondSource: \"remote\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.properties?.remoteOnly, 1);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, \"local2\");\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t});\n});\n"]}
|
|
1
|
+
{"version":3,"file":"mergeTree.annotate.spec.js","sourceRoot":"","sources":["../../src/test/mergeTree.annotate.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 \"node:assert\";\n\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport { MergeTree } from \"../mergeTree.js\";\nimport { Marker, type ISegmentPrivate } from \"../mergeTreeNodes.js\";\nimport { MergeTreeDeltaType, ReferenceType } from \"../ops.js\";\nimport { LocalDefaultPerspective } from \"../perspective.js\";\nimport { assertMergeNode } from \"../segmentInfos.js\";\nimport type { PropsOrAdjust } from \"../segmentPropertiesManager.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { makeRemoteClient } from \"./testUtils.js\";\n\nfunction splitAt(mergeTree: MergeTree, pos: number): ISegmentPrivate | undefined {\n\tlet segment: ISegmentPrivate | undefined;\n\tmergeTree.mapRange(\n\t\t(seg) => {\n\t\t\tsegment = seg;\n\t\t\treturn false;\n\t\t},\n\t\tnew LocalDefaultPerspective(mergeTree.collabWindow.clientId),\n\t\tundefined,\n\t\tpos,\n\t\tpos + 1,\n\t\ttrue,\n\t);\n\treturn segment;\n}\n\ndescribe(\"MergeTree\", () => {\n\tlet mergeTree: MergeTree;\n\tconst remoteClient = makeRemoteClient({ clientId: 35 });\n\tconst localClientId = 17;\n\tlet currentSequenceNumber: number;\n\n\tconst annotateStart = 1;\n\tconst markerPosition = annotateStart + 2;\n\tconst annotateEnd = markerPosition + 2;\n\tconst splitPos = Math.floor((annotateEnd - annotateStart) / 2) + annotateStart;\n\n\tbeforeEach(() => {\n\t\tmergeTree = new MergeTree();\n\t\tmergeTree.insertSegments(\n\t\t\t0,\n\t\t\t[TextSegment.make(\"hello world!\")],\n\t\t\tmergeTree.localPerspective,\n\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\tundefined,\n\t\t);\n\n\t\tcurrentSequenceNumber = 0;\n\t\tmergeTree.insertSegments(\n\t\t\tmarkerPosition,\n\t\t\t[Marker.make(ReferenceType.Tile)],\n\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\tundefined,\n\t\t);\n\t});\n\n\tdescribe(\"annotateRange\", () => {\n\t\tdescribe(\"not collaborating\", () => {\n\t\t\tit(\"remote\", () => {\n\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\tannotateStart,\n\t\t\t\t\tannotateEnd,\n\t\t\t\t\t{\n\t\t\t\t\t\tprops: { propertySource: \"remote\" },\n\t\t\t\t\t},\n\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\tremoteClient.stampAt({ seq: currentSequenceNumber + 1 }),\n\t\t\t\t\tundefined as never,\n\t\t\t\t);\n\n\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\tannotateStart,\n\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t);\n\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\t\t\t\tassert.equal(segment?.properties?.propertySource, \"remote\");\n\t\t\t});\n\n\t\t\tit(\"local\", () => {\n\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\tannotateStart,\n\t\t\t\t\tannotateEnd,\n\t\t\t\t\t{\n\t\t\t\t\t\tprops: { propertySource: \"local\" },\n\t\t\t\t\t},\n\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\tundefined as never,\n\t\t\t\t);\n\n\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\tannotateStart,\n\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t);\n\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t});\n\t\t});\n\t\tdescribe(\"collaborating\", () => {\n\t\t\tbeforeEach(() => {\n\t\t\t\tmergeTree.startCollaboration(\n\t\t\t\t\tlocalClientId,\n\t\t\t\t\t/* minSeq: */ currentSequenceNumber,\n\t\t\t\t\t/* currentSeq: */ currentSequenceNumber,\n\t\t\t\t);\n\t\t\t});\n\t\t\tdescribe(\"local first\", () => {\n\t\t\t\tconst props: PropsOrAdjust = {\n\t\t\t\t\tprops: { propertySource: \"local\" },\n\t\t\t\t};\n\t\t\t\tbeforeEach(() => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tprops,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local\", () => {\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local after unsequenced local\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { secondProperty: \"local\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.properties?.secondProperty, \"local\");\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local split\", () => {\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\tconst splitSegment = splitAt(mergeTree, splitPos)!;\n\t\t\t\t\tassertMergeNode(splitSegment);\n\t\t\t\t\tassert.notEqual(segmentInfo?.segment?.ordinal, splitSegment.ordinal);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"local\");\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local after unsequenced local split\", () => {\n\t\t\t\t\tconst secondChangeProps: PropsOrAdjust = {\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tsecondChange: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tsecondChangeProps,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst splitOnlyProps: PropsOrAdjust = {\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tsplitOnly: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tsplitPos,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tsplitOnlyProps,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\n\t\t\t\t\tconst splitSegmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tsplitPos,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst splitSegment = splitSegmentInfo?.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 2);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.secondChange, 1);\n\t\t\t\t\tassert(!segment.properties?.splitOnly);\n\n\t\t\t\t\tassert.equal(splitSegment.segmentGroups?.size, 3);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(splitSegment.properties?.secondChange, 1);\n\t\t\t\t\tassert.equal(splitSegment.properties?.splitOnly, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 1);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.secondChange, 1);\n\t\t\t\t\tassert(!segment.properties?.splitOnly);\n\n\t\t\t\t\tassert.equal(splitSegment?.segmentGroups?.size, 2);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(splitSegment.properties?.secondChange, 1);\n\t\t\t\t\tassert.equal(splitSegment.properties?.splitOnly, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...secondChangeProps,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.secondChange, 1);\n\t\t\t\t\tassert(!segment.properties?.splitOnly);\n\n\t\t\t\t\tassert.equal(splitSegment.segmentGroups?.size, 1);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(splitSegment.properties?.secondChange, 1);\n\t\t\t\t\tassert.equal(splitSegment.properties?.splitOnly, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: splitPos,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...splitOnlyProps,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.secondChange, 1);\n\t\t\t\t\tassert(!segment.properties?.splitOnly);\n\n\t\t\t\t\tassert.equal(splitSegment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(splitSegment.properties?.secondChange, 1);\n\t\t\t\t\tassert.equal(splitSegment.properties?.splitOnly, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local before remote\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteProperty: 1 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 1);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"sequenced local\", () => {\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t});\n\n\t\t\t\tit(\"sequenced local before remote\", () => {\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteProperty: 1 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"three local changes\", () => {\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\n\t\t\t\t\tconst props2: PropsOrAdjust = {\n\t\t\t\t\t\tprops: { propertySource: \"local2\", secondSource: 1 },\n\t\t\t\t\t};\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tprops2,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, 1);\n\n\t\t\t\t\tconst props3: PropsOrAdjust = {\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tthirdSource: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tprops3,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, 1);\n\t\t\t\t\tassert.equal(segment.properties?.thirdSource, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, 1);\n\t\t\t\t\tassert.equal(segment.properties?.thirdSource, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props2,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, 1);\n\t\t\t\t\tassert.equal(segment.properties?.thirdSource, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props3,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, 1);\n\t\t\t\t\tassert.equal(segment.properties?.thirdSource, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"two local changes with interleaved remote\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { secondSource: \"local2\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteOnly: 1, secondSource: \"remote\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.properties?.remoteOnly, 1);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, \"local2\");\n\t\t\t\t});\n\t\t\t});\n\t\t\tdescribe(\"remote first\", () => {\n\t\t\t\tbeforeEach(() => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteProperty: 1 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tassert(segmentInfo?.segment?.segmentGroups?.size !== 0);\n\t\t\t\t});\n\t\t\t\tit(\"remote only\", () => {\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"split remote\", () => {\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\tconst splitSegment = splitAt(mergeTree, annotateStart + 1)!;\n\t\t\t\t\tassertMergeNode(splitSegment);\n\t\t\t\t\tassert.notEqual(segmentInfo?.segment?.ordinal, splitSegment.ordinal);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(splitSegment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"remote before unsequenced local\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"local\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"remote before sequenced local\", () => {\n\t\t\t\t\tconst props: PropsOrAdjust = {\n\t\t\t\t\t\tprops: { propertySource: \"local\" },\n\t\t\t\t\t};\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tassert(segmentInfo?.segment?.segmentGroups?.empty !== false);\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tprops,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tassert.equal(segmentInfo?.segment?.segmentGroups?.size, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert(segmentInfo?.segment?.segmentGroups?.empty);\n\t\t\t\t\tassert.equal(segmentInfo?.segment?.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segmentInfo?.segment?.properties?.remoteProperty, 1);\n\t\t\t\t});\n\t\t\t});\n\t\t\tdescribe(\"local with rewrite first\", () => {\n\t\t\t\tconst props: PropsOrAdjust = {\n\t\t\t\t\tprops: { propertySource: \"local\" },\n\t\t\t\t};\n\t\t\t\tbeforeEach(() => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tprops,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local after unsequenced local\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"local2\", secondProperty: \"local\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondProperty, \"local\");\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local before remote\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteProperty: 1 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 1);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"sequenced local before remote\", () => {\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteProperty: 1 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"two local changes with interleaved remote\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { secondSource: \"local2\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteOnly: 1, secondSource: \"remote\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.properties?.remoteOnly, 1);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, \"local2\");\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t});\n});\n"]}
|
|
@@ -50,7 +50,7 @@ describe("MergeTree.markRangeRemoved", () => {
|
|
|
50
50
|
let seq = originalSeq;
|
|
51
51
|
const remoteDeleteMessage = client.makeOpMessage((0, opBuilder_js_1.createRemoveRangeOp)(0, client.getLength()), ++seq, undefined, "remote");
|
|
52
52
|
const segmentExpectedRemovedSeq = seq;
|
|
53
|
-
const { segment } = client.getContainingSegment(0);
|
|
53
|
+
const { segment } = client.getContainingSegment(0) ?? {};
|
|
54
54
|
(0, node_assert_1.strict)(segment !== undefined, "expected to find segment");
|
|
55
55
|
const localDeleteMessage = client.makeOpMessage(client.removeRangeLocal(0, client.getLength()), ++seq, originalSeq /* refSeq */);
|
|
56
56
|
node_assert_1.strict.equal(client.getText(), "");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mergeTree.markRangeRemoved.spec.js","sourceRoot":"","sources":["../../src/test/mergeTree.markRangeRemoved.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\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\nimport { strict as assert } from \"node:assert\";\n\nimport { UnassignedSequenceNumber } from \"../constants.js\";\nimport type { ISegmentPrivate } from \"../mergeTreeNodes.js\";\nimport { createInsertSegmentOp, createRemoveRangeOp } from \"../opBuilder.js\";\nimport { assertRemoved } from \"../segmentInfos.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { TestClient } from \"./testClient.js\";\n\ndescribe(\"MergeTree.markRangeRemoved\", () => {\n\tlet client: TestClient;\n\tbeforeEach(() => {\n\t\tclient = new TestClient();\n\t\tclient.startOrUpdateCollaboration(\"local\");\n\t\tfor (const char of \"hello world\") {\n\t\t\tclient.applyMsg(\n\t\t\t\tclient.makeOpMessage(\n\t\t\t\t\tclient.insertTextLocal(client.getLength(), char),\n\t\t\t\t\tclient.getCurrentSeq() + 1,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tassert.equal(client.getText(), \"hello world\");\n\t});\n\n\tit(\"local remove followed by local insert\", () => {\n\t\tclient.removeRangeLocal(0, client.getLength());\n\t\tassert.equal(client.getText(), \"\");\n\n\t\tclient.insertTextLocal(0, \"text\");\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local insert followed by local remove\", () => {\n\t\tclient.insertTextLocal(0, \"text\");\n\t\tassert.equal(client.getText(), \"texthello world\");\n\n\t\tclient.removeRangeLocal(0, client.getLength());\n\t\tassert.equal(client.getText(), \"\");\n\t});\n\n\tit(\"remote remove followed by local insert\", () => {\n\t\tclient.applyMsg(\n\t\t\tclient.makeOpMessage(\n\t\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\t\"remote\",\n\t\t\t),\n\t\t);\n\n\t\tassert.equal(client.getText(), \"\");\n\n\t\tclient.insertTextLocal(0, \"text\");\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local remove followed by remote insert\", () => {\n\t\tclient.removeRangeLocal(0, client.getLength());\n\t\tassert.equal(client.getText(), \"\");\n\n\t\tclient.applyMsg(\n\t\t\tclient.makeOpMessage(\n\t\t\t\tcreateInsertSegmentOp(0, TextSegment.make(\"text\")),\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\t\"remote\",\n\t\t\t),\n\t\t);\n\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local remove followed by remote overlapping remove\", () => {\n\t\tconst originalSeq = client.getCurrentSeq();\n\t\tlet seq = originalSeq;\n\t\tconst remoteDeleteMessage = client.makeOpMessage(\n\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\t++seq,\n\t\t\tundefined,\n\t\t\t\"remote\",\n\t\t);\n\t\tconst segmentExpectedRemovedSeq = seq;\n\t\tconst { segment } = client.getContainingSegment<ISegmentPrivate>(0);\n\t\tassert(segment !== undefined, \"expected to find segment\");\n\t\tconst localDeleteMessage = client.makeOpMessage(\n\t\t\tclient.removeRangeLocal(0, client.getLength()),\n\t\t\t++seq,\n\t\t\toriginalSeq /* refSeq */,\n\t\t);\n\n\t\tassert.equal(client.getText(), \"\");\n\t\tassertRemoved(segment);\n\t\tconst localRemoveInfo = segment.removes[0];\n\t\tassert.equal(localRemoveInfo.seq, UnassignedSequenceNumber);\n\t\tassert(localRemoveInfo.localSeq !== undefined);\n\n\t\tclient.applyMsg(remoteDeleteMessage);\n\t\tconst remoteRemoveInfo = segment.removes[0];\n\t\tassert.deepEqual(segment.removes[1], localRemoveInfo);\n\t\tassert.equal(remoteRemoveInfo.seq, segmentExpectedRemovedSeq);\n\t\tassert.equal(client.getText(), \"\");\n\n\t\t// localRemovedSeq should remain on the segment until the local removal has been acked.\n\t\t// This ensures there's enough information to determine segment length in the case of\n\t\t// reconnect.\n\t\tclient.applyMsg(localDeleteMessage);\n\t\tconst finalRemoveInfo = segment.removes[0];\n\t\tassert.equal(segment.removes.length, 2);\n\t\tassert.equal(finalRemoveInfo.seq, segmentExpectedRemovedSeq);\n\t\tassert.equal(finalRemoveInfo.localSeq, undefined);\n\t\tassert.equal(client.getText(), \"\");\n\t});\n\n\tit(\"remote remove followed by remote insert\", () => {\n\t\tconst removeMsg = client.makeOpMessage(\n\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote2\",\n\t\t);\n\n\t\tconst insertMsg = client.makeOpMessage(\n\t\t\tcreateInsertSegmentOp(0, TextSegment.make(\"text\")),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 2,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote\",\n\t\t);\n\n\t\tclient.applyMsg(removeMsg);\n\t\tclient.applyMsg(insertMsg);\n\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"remote insert followed by remote remove\", () => {\n\t\tconst insertMsg = client.makeOpMessage(\n\t\t\tcreateInsertSegmentOp(0, TextSegment.make(\"text\")),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote\",\n\t\t);\n\n\t\tconst removeMsg = client.makeOpMessage(\n\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 2,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote2\",\n\t\t);\n\n\t\tclient.applyMsg(insertMsg);\n\t\tclient.applyMsg(removeMsg);\n\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local and remote clients race to insert at position of removed segment\", () => {\n\t\t// Note: This test constructs its own TestClients to avoid being initialized with \"hello world\".\n\n\t\t// First we run through the ops from the perspective of a passive observer (i.e., all operations are remote).\n\t\tconst expected = new TestClient();\n\t\texpected.startOrUpdateCollaboration(\"3\");\n\n\t\t{\n\t\t\tlet seq = 0;\n\n\t\t\t// Client 1 locally inserts and removes the letter \"a\".\n\t\t\texpected.insertTextRemote(\n\t\t\t\t0,\n\t\t\t\t\"a\",\n\t\t\t\tundefined,\n\t\t\t\t++seq,\n\t\t\t\t/* refSeq: */ 0,\n\t\t\t\t/* longClientId: */ \"1\",\n\t\t\t);\n\t\t\texpected.removeRangeRemote(0, 1, ++seq, /* refSeq: */ 0, /* longClientId: */ \"1\");\n\t\t\tconst refSeqAt2 = expected.getCurrentSeq();\n\n\t\t\t// In parallel, Client 2 inserted \"x\" without knowledge of Client 1's insertion/removal.\n\t\t\texpected.insertTextRemote(\n\t\t\t\t0,\n\t\t\t\t\"X\",\n\t\t\t\tundefined,\n\t\t\t\t++seq,\n\t\t\t\t/* refSeq: */ 0,\n\t\t\t\t/* longClientId: */ \"2\",\n\t\t\t);\n\n\t\t\t// Client 1 inserts \"c\" having received acks for its own edits, but has not yet having\n\t\t\t// observed the insertion of \"X\" from client 2.\n\t\t\texpected.insertTextRemote(0, \"c\", undefined, ++seq, refSeqAt2, /* longClientId: */ \"1\");\n\t\t}\n\n\t\t// Next, we run through the same sequence from the perspective of client 1:\n\t\tconst actual = new TestClient();\n\t\tactual.startOrUpdateCollaboration(\"1\");\n\n\t\t{\n\t\t\tlet seq = 0;\n\n\t\t\t// Client 1 locally inserts and removes the letter \"a\".\n\t\t\tconst op1 = actual.insertTextLocal(0, \"a\")!;\n\t\t\tconst op2 = actual.removeRangeLocal(0, 1);\n\n\t\t\t// Client 1 receives ACKs for op1 and op2.\n\t\t\tactual.applyMsg(actual.makeOpMessage(op1, ++seq, /* refSeq: */ 0));\n\t\t\tactual.applyMsg(actual.makeOpMessage(op2, ++seq, /* refSeq: */ 0));\n\t\t\tconst refSeqAt2 = actual.getCurrentSeq();\n\n\t\t\t// Client 1 locally inserts \"c\".\n\t\t\tconst op4 = actual.insertTextLocal(0, \"c\");\n\n\t\t\t// Client 1 then processes the parallel insertion of \"X\" from Client 2 at refSeq=0\n\t\t\tactual.insertTextRemote(\n\t\t\t\t0,\n\t\t\t\t\"X\",\n\t\t\t\tundefined,\n\t\t\t\t++seq,\n\t\t\t\t/* refSeq: */ 0,\n\t\t\t\t/* longClientId: */ \"2\",\n\t\t\t);\n\n\t\t\t// Finally, client 1 receives the ack for its insertion of \"c\".\n\t\t\tactual.applyMsg(actual.makeOpMessage(op4, ++seq, refSeqAt2));\n\t\t}\n\n\t\tassert.equal(actual.getText(), expected.getText());\n\t});\n});\n"]}
|
|
1
|
+
{"version":3,"file":"mergeTree.markRangeRemoved.spec.js","sourceRoot":"","sources":["../../src/test/mergeTree.markRangeRemoved.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\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\nimport { strict as assert } from \"node:assert\";\n\nimport { UnassignedSequenceNumber } from \"../constants.js\";\nimport type { ISegmentPrivate } from \"../mergeTreeNodes.js\";\nimport { createInsertSegmentOp, createRemoveRangeOp } from \"../opBuilder.js\";\nimport { assertRemoved } from \"../segmentInfos.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { TestClient } from \"./testClient.js\";\n\ndescribe(\"MergeTree.markRangeRemoved\", () => {\n\tlet client: TestClient;\n\tbeforeEach(() => {\n\t\tclient = new TestClient();\n\t\tclient.startOrUpdateCollaboration(\"local\");\n\t\tfor (const char of \"hello world\") {\n\t\t\tclient.applyMsg(\n\t\t\t\tclient.makeOpMessage(\n\t\t\t\t\tclient.insertTextLocal(client.getLength(), char),\n\t\t\t\t\tclient.getCurrentSeq() + 1,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tassert.equal(client.getText(), \"hello world\");\n\t});\n\n\tit(\"local remove followed by local insert\", () => {\n\t\tclient.removeRangeLocal(0, client.getLength());\n\t\tassert.equal(client.getText(), \"\");\n\n\t\tclient.insertTextLocal(0, \"text\");\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local insert followed by local remove\", () => {\n\t\tclient.insertTextLocal(0, \"text\");\n\t\tassert.equal(client.getText(), \"texthello world\");\n\n\t\tclient.removeRangeLocal(0, client.getLength());\n\t\tassert.equal(client.getText(), \"\");\n\t});\n\n\tit(\"remote remove followed by local insert\", () => {\n\t\tclient.applyMsg(\n\t\t\tclient.makeOpMessage(\n\t\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\t\"remote\",\n\t\t\t),\n\t\t);\n\n\t\tassert.equal(client.getText(), \"\");\n\n\t\tclient.insertTextLocal(0, \"text\");\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local remove followed by remote insert\", () => {\n\t\tclient.removeRangeLocal(0, client.getLength());\n\t\tassert.equal(client.getText(), \"\");\n\n\t\tclient.applyMsg(\n\t\t\tclient.makeOpMessage(\n\t\t\t\tcreateInsertSegmentOp(0, TextSegment.make(\"text\")),\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\t\"remote\",\n\t\t\t),\n\t\t);\n\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local remove followed by remote overlapping remove\", () => {\n\t\tconst originalSeq = client.getCurrentSeq();\n\t\tlet seq = originalSeq;\n\t\tconst remoteDeleteMessage = client.makeOpMessage(\n\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\t++seq,\n\t\t\tundefined,\n\t\t\t\"remote\",\n\t\t);\n\t\tconst segmentExpectedRemovedSeq = seq;\n\t\tconst { segment } = client.getContainingSegment<ISegmentPrivate>(0) ?? {};\n\t\tassert(segment !== undefined, \"expected to find segment\");\n\t\tconst localDeleteMessage = client.makeOpMessage(\n\t\t\tclient.removeRangeLocal(0, client.getLength()),\n\t\t\t++seq,\n\t\t\toriginalSeq /* refSeq */,\n\t\t);\n\n\t\tassert.equal(client.getText(), \"\");\n\t\tassertRemoved(segment);\n\t\tconst localRemoveInfo = segment.removes[0];\n\t\tassert.equal(localRemoveInfo.seq, UnassignedSequenceNumber);\n\t\tassert(localRemoveInfo.localSeq !== undefined);\n\n\t\tclient.applyMsg(remoteDeleteMessage);\n\t\tconst remoteRemoveInfo = segment.removes[0];\n\t\tassert.deepEqual(segment.removes[1], localRemoveInfo);\n\t\tassert.equal(remoteRemoveInfo.seq, segmentExpectedRemovedSeq);\n\t\tassert.equal(client.getText(), \"\");\n\n\t\t// localRemovedSeq should remain on the segment until the local removal has been acked.\n\t\t// This ensures there's enough information to determine segment length in the case of\n\t\t// reconnect.\n\t\tclient.applyMsg(localDeleteMessage);\n\t\tconst finalRemoveInfo = segment.removes[0];\n\t\tassert.equal(segment.removes.length, 2);\n\t\tassert.equal(finalRemoveInfo.seq, segmentExpectedRemovedSeq);\n\t\tassert.equal(finalRemoveInfo.localSeq, undefined);\n\t\tassert.equal(client.getText(), \"\");\n\t});\n\n\tit(\"remote remove followed by remote insert\", () => {\n\t\tconst removeMsg = client.makeOpMessage(\n\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote2\",\n\t\t);\n\n\t\tconst insertMsg = client.makeOpMessage(\n\t\t\tcreateInsertSegmentOp(0, TextSegment.make(\"text\")),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 2,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote\",\n\t\t);\n\n\t\tclient.applyMsg(removeMsg);\n\t\tclient.applyMsg(insertMsg);\n\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"remote insert followed by remote remove\", () => {\n\t\tconst insertMsg = client.makeOpMessage(\n\t\t\tcreateInsertSegmentOp(0, TextSegment.make(\"text\")),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote\",\n\t\t);\n\n\t\tconst removeMsg = client.makeOpMessage(\n\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 2,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote2\",\n\t\t);\n\n\t\tclient.applyMsg(insertMsg);\n\t\tclient.applyMsg(removeMsg);\n\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local and remote clients race to insert at position of removed segment\", () => {\n\t\t// Note: This test constructs its own TestClients to avoid being initialized with \"hello world\".\n\n\t\t// First we run through the ops from the perspective of a passive observer (i.e., all operations are remote).\n\t\tconst expected = new TestClient();\n\t\texpected.startOrUpdateCollaboration(\"3\");\n\n\t\t{\n\t\t\tlet seq = 0;\n\n\t\t\t// Client 1 locally inserts and removes the letter \"a\".\n\t\t\texpected.insertTextRemote(\n\t\t\t\t0,\n\t\t\t\t\"a\",\n\t\t\t\tundefined,\n\t\t\t\t++seq,\n\t\t\t\t/* refSeq: */ 0,\n\t\t\t\t/* longClientId: */ \"1\",\n\t\t\t);\n\t\t\texpected.removeRangeRemote(0, 1, ++seq, /* refSeq: */ 0, /* longClientId: */ \"1\");\n\t\t\tconst refSeqAt2 = expected.getCurrentSeq();\n\n\t\t\t// In parallel, Client 2 inserted \"x\" without knowledge of Client 1's insertion/removal.\n\t\t\texpected.insertTextRemote(\n\t\t\t\t0,\n\t\t\t\t\"X\",\n\t\t\t\tundefined,\n\t\t\t\t++seq,\n\t\t\t\t/* refSeq: */ 0,\n\t\t\t\t/* longClientId: */ \"2\",\n\t\t\t);\n\n\t\t\t// Client 1 inserts \"c\" having received acks for its own edits, but has not yet having\n\t\t\t// observed the insertion of \"X\" from client 2.\n\t\t\texpected.insertTextRemote(0, \"c\", undefined, ++seq, refSeqAt2, /* longClientId: */ \"1\");\n\t\t}\n\n\t\t// Next, we run through the same sequence from the perspective of client 1:\n\t\tconst actual = new TestClient();\n\t\tactual.startOrUpdateCollaboration(\"1\");\n\n\t\t{\n\t\t\tlet seq = 0;\n\n\t\t\t// Client 1 locally inserts and removes the letter \"a\".\n\t\t\tconst op1 = actual.insertTextLocal(0, \"a\")!;\n\t\t\tconst op2 = actual.removeRangeLocal(0, 1);\n\n\t\t\t// Client 1 receives ACKs for op1 and op2.\n\t\t\tactual.applyMsg(actual.makeOpMessage(op1, ++seq, /* refSeq: */ 0));\n\t\t\tactual.applyMsg(actual.makeOpMessage(op2, ++seq, /* refSeq: */ 0));\n\t\t\tconst refSeqAt2 = actual.getCurrentSeq();\n\n\t\t\t// Client 1 locally inserts \"c\".\n\t\t\tconst op4 = actual.insertTextLocal(0, \"c\");\n\n\t\t\t// Client 1 then processes the parallel insertion of \"X\" from Client 2 at refSeq=0\n\t\t\tactual.insertTextRemote(\n\t\t\t\t0,\n\t\t\t\t\"X\",\n\t\t\t\tundefined,\n\t\t\t\t++seq,\n\t\t\t\t/* refSeq: */ 0,\n\t\t\t\t/* longClientId: */ \"2\",\n\t\t\t);\n\n\t\t\t// Finally, client 1 receives the ack for its insertion of \"c\".\n\t\t\tactual.applyMsg(actual.makeOpMessage(op4, ++seq, refSeqAt2));\n\t\t}\n\n\t\tassert.equal(actual.getText(), expected.getText());\n\t});\n});\n"]}
|
|
@@ -77,11 +77,11 @@ describe("obliterate", () => {
|
|
|
77
77
|
client.mergeTree.obliterateRange(obliterateStart, obliterateEnd, remoteClient1.perspectiveAt({ refSeq }), remoteClient1.stampAt({ seq: ++seq }), undefined);
|
|
78
78
|
client.mergeTree.insertSegments(1, [textSegment_js_1.TextSegment.make("more ")], remoteClient2.perspectiveAt({ refSeq }), remoteClient2.stampAt({ seq: ++seq }), { op: { type: ops_js_1.MergeTreeDeltaType.INSERT } });
|
|
79
79
|
node_assert_1.strict.equal(client.getText(), "");
|
|
80
|
-
startSeg.
|
|
80
|
+
startSeg?.segment.localRefs?.walkReferences((ref) => {
|
|
81
81
|
const oblProps = ref.properties?.obliterate;
|
|
82
82
|
(0, node_assert_1.strict)(oblProps?.start !== undefined, "start ref should NOT be removed");
|
|
83
83
|
});
|
|
84
|
-
endSeg.
|
|
84
|
+
endSeg?.segment.localRefs?.walkReferences((ref) => {
|
|
85
85
|
const oblProps = ref.properties?.obliterate;
|
|
86
86
|
(0, node_assert_1.strict)(oblProps?.end !== undefined, "end ref should NOT be removed");
|
|
87
87
|
});
|
|
@@ -93,11 +93,11 @@ describe("obliterate", () => {
|
|
|
93
93
|
client2.applyMsg(insert);
|
|
94
94
|
}
|
|
95
95
|
// want to check that the start and end segment don't have the obliterate refs on them
|
|
96
|
-
startSeg.
|
|
96
|
+
startSeg?.segment.localRefs?.walkReferences((ref) => {
|
|
97
97
|
const oblProps = ref.properties?.obliterate;
|
|
98
98
|
(0, node_assert_1.strict)(oblProps.start === undefined, "start ref should be removed");
|
|
99
99
|
});
|
|
100
|
-
endSeg.
|
|
100
|
+
endSeg?.segment.localRefs?.walkReferences((ref) => {
|
|
101
101
|
const oblProps = ref.properties?.obliterate;
|
|
102
102
|
(0, node_assert_1.strict)(oblProps.end === undefined, "end ref should be removed");
|
|
103
103
|
});
|