@fluid-experimental/tree 1.2.1 → 2.0.0-internal.1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierignore +6 -0
- package/dist/Checkout.d.ts +9 -4
- package/dist/Checkout.d.ts.map +1 -1
- package/dist/Checkout.js +34 -25
- package/dist/Checkout.js.map +1 -1
- package/dist/Common.d.ts +31 -18
- package/dist/Common.d.ts.map +1 -1
- package/dist/Common.js +32 -22
- package/dist/Common.js.map +1 -1
- package/dist/EditUtilities.d.ts +5 -0
- package/dist/EditUtilities.d.ts.map +1 -1
- package/dist/EditUtilities.js +4 -3
- package/dist/EditUtilities.js.map +1 -1
- package/dist/HistoryEditFactory.d.ts +5 -3
- package/dist/HistoryEditFactory.d.ts.map +1 -1
- package/dist/HistoryEditFactory.js +18 -3
- package/dist/HistoryEditFactory.js.map +1 -1
- package/dist/SharedTree.d.ts +6 -3
- package/dist/SharedTree.d.ts.map +1 -1
- package/dist/SharedTree.js +4 -4
- package/dist/SharedTree.js.map +1 -1
- package/dist/Transaction.d.ts +2 -2
- package/dist/Transaction.d.ts.map +1 -1
- package/dist/Transaction.js +3 -2
- package/dist/Transaction.js.map +1 -1
- package/lib/Checkout.d.ts +9 -4
- package/lib/Checkout.d.ts.map +1 -1
- package/lib/Checkout.js +36 -27
- package/lib/Checkout.js.map +1 -1
- package/lib/Common.d.ts +31 -18
- package/lib/Common.d.ts.map +1 -1
- package/lib/Common.js +30 -21
- package/lib/Common.js.map +1 -1
- package/lib/EditUtilities.d.ts +5 -0
- package/lib/EditUtilities.d.ts.map +1 -1
- package/lib/EditUtilities.js +4 -3
- package/lib/EditUtilities.js.map +1 -1
- package/lib/HistoryEditFactory.d.ts +5 -3
- package/lib/HistoryEditFactory.d.ts.map +1 -1
- package/lib/HistoryEditFactory.js +18 -3
- package/lib/HistoryEditFactory.js.map +1 -1
- package/lib/SharedTree.d.ts +6 -3
- package/lib/SharedTree.d.ts.map +1 -1
- package/lib/SharedTree.js +5 -5
- package/lib/SharedTree.js.map +1 -1
- package/lib/Transaction.d.ts +2 -2
- package/lib/Transaction.d.ts.map +1 -1
- package/lib/Transaction.js +3 -2
- package/lib/Transaction.js.map +1 -1
- package/lib/test/Checkout.tests.d.ts.map +1 -1
- package/lib/test/Checkout.tests.js +39 -10
- package/lib/test/Checkout.tests.js.map +1 -1
- package/lib/test/Common.tests.js +20 -1
- package/lib/test/Common.tests.js.map +1 -1
- package/lib/test/HistoryEditFactory.tests.js +48 -9
- package/lib/test/HistoryEditFactory.tests.js.map +1 -1
- package/lib/test/utilities/SharedTreeTests.d.ts.map +1 -1
- package/lib/test/utilities/SharedTreeTests.js +35 -26
- package/lib/test/utilities/SharedTreeTests.js.map +1 -1
- package/lib/test/utilities/TestUtilities.d.ts +5 -0
- package/lib/test/utilities/TestUtilities.d.ts.map +1 -1
- package/lib/test/utilities/TestUtilities.js +4 -3
- package/lib/test/utilities/TestUtilities.js.map +1 -1
- package/lib/test/utilities/UndoRedoTests.js +3 -2
- package/lib/test/utilities/UndoRedoTests.js.map +1 -1
- package/package.json +22 -20
- package/src/Checkout.ts +56 -14
- package/src/Common.ts +38 -21
- package/src/EditUtilities.ts +3 -3
- package/src/HistoryEditFactory.ts +24 -3
- package/src/SharedTree.ts +19 -8
- package/src/Transaction.ts +5 -4
package/lib/Transaction.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Transaction.js","sourceRoot":"","sources":["../src/Transaction.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAwB,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAChF,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"Transaction.js","sourceRoot":"","sources":["../src/Transaction.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 { IErrorEvent } from '@fluidframework/common-definitions';\nimport { TypedEventEmitter } from '@fluidframework/common-utils';\nimport { ChangeInternal, Edit, EditStatus } from './persisted-types';\nimport { newEditId } from './EditUtilities';\nimport { TreeView } from './TreeView';\nimport { Change } from './ChangeTypes';\nimport { SharedTree } from './SharedTree';\nimport { GenericTransaction, TransactionInternal } from './TransactionInternal';\nimport { CachingLogViewer } from './LogViewer';\nimport { RestOrArray, unwrapRestOrArray } from './Common';\n\n/**\n * An event emitted by a `Transaction` to indicate a state change. See {@link TransactionEvents} for event argument information.\n * @public\n */\nexport enum TransactionEvent {\n\t/**\n\t * `currentView` has changed from `before` to `after`\n\t */\n\tViewChange = 'viewChange',\n}\n\n/**\n * Events which may be emitted by `Transaction`\n * @public\n */\nexport interface TransactionEvents extends IErrorEvent {\n\t(event: TransactionEvent.ViewChange, listener: (before: TreeView, after: TreeView) => void);\n}\n\n/**\n * Buffers changes to be applied to an isolated view of a `SharedTree` over time before applying them directly to the tree itself as a\n * single edit\n */\nexport class Transaction extends TypedEventEmitter<TransactionEvents> {\n\t/** The view of the tree when this transaction was created */\n\tpublic readonly startingView: TreeView;\n\tprivate readonly transaction: GenericTransaction;\n\n\t/**\n\t * Create a new transaction over the given tree. The tree's `currentView` at this time will become the `startingView` for this\n\t * transaction.\n\t * @param tree - the `SharedTree` that this transaction applies changes to\n\t */\n\tpublic constructor(public readonly tree: SharedTree) {\n\t\tsuper();\n\t\tconst { currentView } = tree;\n\t\tthis.transaction = new GenericTransaction(currentView, new TransactionInternal.Policy());\n\t\tthis.startingView = currentView;\n\t}\n\n\t/**\n\t * True if this transaction is open, false if it is closed. A transaction may be closed manually via `closeAndApplyEdit()`, or may\n\t * be automatically closed by a change in this transaction failing to apply (see `applyChange()`).\n\t */\n\tpublic get isOpen(): boolean {\n\t\treturn this.transaction.isOpen && this.status === EditStatus.Applied;\n\t}\n\n\t/**\n\t * The status of the most recently applied change in this transaction\n\t */\n\tpublic get status(): EditStatus {\n\t\treturn this.transaction.status;\n\t}\n\n\t/**\n\t * The state of the tree following the most change that was successfully applied. If no changes have been applied, this is the same as\n\t * `startingView`.\n\t */\n\tpublic get currentView(): TreeView {\n\t\treturn this.transaction.view;\n\t}\n\n\t/**\n\t * Attempt to apply a sequence of changes in this transaction. The `currentView` will be updated to reflect the new tree state after all\n\t * applied changes. If any change fails to apply, the remaining changes will be ignored and this transaction will be automatically\n\t * closed (see `isOpen`). If this transaction is already closed, this method has no effect. This method will emit a\n\t * `TransactionEvent.ViewChange` event at most once per call.\n\t * @param changes - the changes to apply\n\t * @returns either the `EditStatus` of the given changes or the `EditStatus` of the last change before the transaction was closed\n\t */\n\tpublic apply(...changes: readonly Change[]): EditStatus;\n\tpublic apply(changes: readonly Change[]): EditStatus;\n\tpublic apply(...changesOrArray: RestOrArray<Change>): EditStatus {\n\t\tif (this.isOpen) {\n\t\t\tconst changes = unwrapRestOrArray(changesOrArray);\n\t\t\tif (changes.length > 0) {\n\t\t\t\tconst previousView = this.currentView;\n\t\t\t\tthis.transaction.applyChanges(changes.map((c) => this.tree.internalizeChange(c)));\n\t\t\t\tif (\n\t\t\t\t\tthis.listenerCount(TransactionEvent.ViewChange) > 0 &&\n\t\t\t\t\t!previousView.hasEqualForest(this.currentView)\n\t\t\t\t) {\n\t\t\t\t\tthis.emit(TransactionEvent.ViewChange, previousView, this.currentView);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn this.status;\n\t}\n\n\t/**\n\t * Close this transaction and apply its changes to the `SharedTree`. If this transaction is already closed, this method has no effect.\n\t */\n\tpublic closeAndCommit(): void {\n\t\tif (this.isOpen) {\n\t\t\tif (this.transaction.changes.length > 0) {\n\t\t\t\tconst result = this.transaction.close();\n\t\t\t\tconst edit: Edit<ChangeInternal> = { id: newEditId(), changes: result.changes };\n\t\t\t\tif (this.tree.edits instanceof CachingLogViewer) {\n\t\t\t\t\tthis.tree.edits.setKnownEditingResult(edit, result);\n\t\t\t\t}\n\t\t\t\tthis.tree.applyEditInternal(edit);\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Checkout.tests.d.ts","sourceRoot":"","sources":["../../src/test/Checkout.tests.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"Checkout.tests.d.ts","sourceRoot":"","sources":["../../src/test/Checkout.tests.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAMN,UAAU,EAEV,QAAQ,EAKR,MAAM,UAAU,CAAC;AAIlB;;GAEG;AACH,wBAAgB,aAAa,CAC5B,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,QAAQ,CAAC,EACxD,eAAe,CAAC,EAAE,MAAM,IAAI,GAC1B,IAAI,CAwjBN"}
|
|
@@ -9,7 +9,8 @@ import { setUpTestSharedTree, setUpTestTree } from './utilities/TestUtilities';
|
|
|
9
9
|
* Checkout test suite
|
|
10
10
|
*/
|
|
11
11
|
export function checkoutTests(checkoutName, checkoutFactory, additionalTests) {
|
|
12
|
-
async function setUpTestCheckout(
|
|
12
|
+
async function setUpTestCheckout(optionsArg) {
|
|
13
|
+
const options = Object.assign({ localMode: true, noFailOnError: true }, optionsArg);
|
|
13
14
|
const { tree } = setUpTestSharedTree(options);
|
|
14
15
|
return { checkout: await checkoutFactory(tree), tree };
|
|
15
16
|
}
|
|
@@ -40,8 +41,8 @@ export function checkoutTests(checkoutName, checkoutFactory, additionalTests) {
|
|
|
40
41
|
expect(errors).deep.equal([]);
|
|
41
42
|
return data.changeCount;
|
|
42
43
|
}
|
|
43
|
-
async function setUpTestTreeCheckout() {
|
|
44
|
-
const { checkout, tree } = await setUpTestCheckout();
|
|
44
|
+
async function setUpTestTreeCheckout(options) {
|
|
45
|
+
const { checkout, tree } = await setUpTestCheckout(options);
|
|
45
46
|
const testTree = setUpTestTree(tree);
|
|
46
47
|
await checkout.waitForPendingUpdates();
|
|
47
48
|
return { checkout, sharedTree: tree, testTree };
|
|
@@ -80,7 +81,7 @@ export function checkoutTests(checkoutName, checkoutFactory, additionalTests) {
|
|
|
80
81
|
// Starts as valid
|
|
81
82
|
expect(checkout.getEditStatus()).equals(EditStatus.Applied);
|
|
82
83
|
// Is invalid after an invalid edit
|
|
83
|
-
expect(() => checkout.applyChanges(
|
|
84
|
+
expect(() => checkout.applyChanges(Change.insertTree(testTree.left, StablePlace.after(testTree.left)))).throws('Locally constructed edits must be well-formed and valid.');
|
|
84
85
|
expect(checkout.getEditStatus()).equals(EditStatus.Invalid);
|
|
85
86
|
checkout.abortEdit();
|
|
86
87
|
// Next edit is unaffected
|
|
@@ -98,7 +99,7 @@ export function checkoutTests(checkoutName, checkoutFactory, additionalTests) {
|
|
|
98
99
|
start: { side: Side.Before },
|
|
99
100
|
end: { side: Side.After },
|
|
100
101
|
}, { side: Side.After });
|
|
101
|
-
expect(() => checkout.applyChanges(
|
|
102
|
+
expect(() => checkout.applyChanges(malformedMove)).throws('Locally constructed edits must be well-formed and valid.');
|
|
102
103
|
expect(checkout.getEditStatus()).equals(EditStatus.Malformed);
|
|
103
104
|
// Is still malformed after a subsequent valid edit
|
|
104
105
|
expect(() => checkout.applyChanges(Change.delete(StableRange.only(testTree.left)))).throws('Cannot apply change to an edit unless all previous changes have applied');
|
|
@@ -109,11 +110,39 @@ export function checkoutTests(checkoutName, checkoutFactory, additionalTests) {
|
|
|
109
110
|
expect(checkout.getEditStatus()).equals(EditStatus.Applied);
|
|
110
111
|
checkout.closeEdit();
|
|
111
112
|
});
|
|
113
|
+
it.only('emits error telemetry on attempted close of malformed edits', async () => {
|
|
114
|
+
const events = [];
|
|
115
|
+
const { checkout } = await setUpTestTreeCheckout({
|
|
116
|
+
logger: { send: (event) => event.eventName.includes('Checkout') && events.push(event) },
|
|
117
|
+
});
|
|
118
|
+
checkout.openEdit();
|
|
119
|
+
// Starts as valid
|
|
120
|
+
expect(checkout.getEditStatus()).equals(EditStatus.Applied);
|
|
121
|
+
// Is malformed after a malformed edit
|
|
122
|
+
const malformedMove = Change.move({
|
|
123
|
+
start: { side: Side.Before },
|
|
124
|
+
end: { side: Side.After },
|
|
125
|
+
}, { side: Side.After });
|
|
126
|
+
expect(() => checkout.applyChanges(...malformedMove)).throws('Locally constructed edits must be well-formed and valid.');
|
|
127
|
+
expect(events.length).to.equal(0);
|
|
128
|
+
expect(() => checkout.closeEdit()).throws('Locally constructed edits must be well-formed and valid');
|
|
129
|
+
expect(events.length).to.equal(1);
|
|
130
|
+
expect(events[0]).to.deep.equal({
|
|
131
|
+
category: 'error',
|
|
132
|
+
error: 'FailedLocalEdit',
|
|
133
|
+
eventName: 'SharedTree:Checkout:FailedLocalEdit',
|
|
134
|
+
failureKind: 'BadRange',
|
|
135
|
+
isSharedTreeEvent: true,
|
|
136
|
+
rangeFailure: 'BadPlace',
|
|
137
|
+
rangeEndpointFailure: 'Malformed',
|
|
138
|
+
status: 'Malformed',
|
|
139
|
+
});
|
|
140
|
+
});
|
|
112
141
|
it('can try to apply an invalid edit and abort without causing an error', async () => {
|
|
113
142
|
const { checkout, tree } = await setUpTestCheckout();
|
|
114
143
|
const simpleTestTree = setUpTestTree(tree);
|
|
115
144
|
// tryApplyEdit aborts when applying an invalid edit and returns undefined
|
|
116
|
-
expect(checkout.tryApplyEdit(
|
|
145
|
+
expect(checkout.tryApplyEdit(Change.insertTree(simpleTestTree.left, StablePlace.after(simpleTestTree.left)))).to.be.undefined;
|
|
117
146
|
// Next edit is unaffected
|
|
118
147
|
checkout.openEdit();
|
|
119
148
|
expect(checkout.getEditStatus()).equals(EditStatus.Applied);
|
|
@@ -154,7 +183,7 @@ export function checkoutTests(checkoutName, checkoutFactory, additionalTests) {
|
|
|
154
183
|
// Starts as valid
|
|
155
184
|
expect(checkout.getEditStatus()).equals(EditStatus.Applied);
|
|
156
185
|
// Is invalid after an invalid edit
|
|
157
|
-
expect(() => checkout.applyChanges(
|
|
186
|
+
expect(() => checkout.applyChanges(Change.insertTree(testTree.left, StablePlace.after(testTree.left)))).throws('Locally constructed edits must be well-formed and valid.');
|
|
158
187
|
expect(checkout.getEditStatus()).equals(EditStatus.Invalid);
|
|
159
188
|
// Is still invalid after a subsequent valid edit
|
|
160
189
|
expect(() => checkout.applyChanges(Change.delete(StableRange.only(testTree.left)))).throws('Cannot apply change to an edit unless all previous changes have applied');
|
|
@@ -175,7 +204,7 @@ export function checkoutTests(checkoutName, checkoutFactory, additionalTests) {
|
|
|
175
204
|
start: { side: Side.Before },
|
|
176
205
|
end: { side: Side.After },
|
|
177
206
|
}, { side: Side.After });
|
|
178
|
-
expect(() => checkout.applyChanges(
|
|
207
|
+
expect(() => checkout.applyChanges(malformedMove)).throws('Locally constructed edits must be well-formed and valid.');
|
|
179
208
|
expect(checkout.getEditStatus()).equals(EditStatus.Malformed);
|
|
180
209
|
// Is still malformed after a subsequent valid edit
|
|
181
210
|
expect(() => checkout.applyChanges(Change.delete(StableRange.only(testTree.left)))).throws('Cannot apply change to an edit unless all previous changes have applied');
|
|
@@ -350,7 +379,7 @@ export function checkoutTests(checkoutName, checkoutFactory, additionalTests) {
|
|
|
350
379
|
const secondCheckout = await checkoutFactory(secondTree);
|
|
351
380
|
const newLeftNode = simpleTestTree.buildLeaf(simpleTestTree.generateNodeId());
|
|
352
381
|
checkout.openEdit();
|
|
353
|
-
checkout.applyChanges(
|
|
382
|
+
checkout.applyChanges(setTrait(simpleTestTree.left.traitLocation, [newLeftNode]));
|
|
354
383
|
// Concurrently, the second client deletes the right node. This will not conflict with the operation performed
|
|
355
384
|
// on the left trait on the first client.
|
|
356
385
|
secondCheckout.applyEdit(Change.delete(StableRange.only(simpleTestTree.right.translateId(secondTree))));
|
|
@@ -394,7 +423,7 @@ export function checkoutTests(checkoutName, checkoutFactory, additionalTests) {
|
|
|
394
423
|
const secondCheckout = await checkoutFactory(secondTree);
|
|
395
424
|
checkout.openEdit();
|
|
396
425
|
// Move the left node to after the right node
|
|
397
|
-
checkout.applyChanges(
|
|
426
|
+
checkout.applyChanges(Change.move(StableRange.only(simpleTestTree.left), StablePlace.after(simpleTestTree.right)));
|
|
398
427
|
// Concurrently, the second client deletes the right node. This will conflict with the move operation by the first client.
|
|
399
428
|
secondCheckout.applyEdit(Change.delete(StableRange.only(simpleTestTree.right.translateId(secondTree))));
|
|
400
429
|
await secondCheckout.waitForPendingUpdates();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Checkout.tests.js","sourceRoot":"","sources":["../../src/test/Checkout.tests.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 { expect } from 'chai';\nimport {\n\tsetTrait,\n\tEditStatus,\n\tStableRange,\n\tStablePlace,\n\tEditValidationResult,\n\tSharedTree,\n\tSharedTreeEvent,\n\tCheckout,\n\tCheckoutEvent,\n\tChange,\n\tSide,\n\tareRevisionViewsSemanticallyEqual,\n} from '../index';\nimport { TestTree } from './utilities/TestNode';\nimport { setUpTestSharedTree, SharedTreeTestingOptions, setUpTestTree } from './utilities/TestUtilities';\n\n/**\n * Checkout test suite\n */\nexport function checkoutTests(\n\tcheckoutName: string,\n\tcheckoutFactory: (tree: SharedTree) => Promise<Checkout>,\n\tadditionalTests?: () => void\n): void {\n\tasync function setUpTestCheckout(\n\t\toptions: SharedTreeTestingOptions = { localMode: true, noFailOnError: true }\n\t): Promise<{ checkout: Checkout; tree: SharedTree }> {\n\t\tconst { tree } = setUpTestSharedTree(options);\n\t\treturn { checkout: await checkoutFactory(tree), tree };\n\t}\n\n\t/**\n\t * Counts the number of times ViewChange occurs while performing `action`.\n\t * Checks arguments to ViewChange are correct as well.\n\t * @param action - Action to perform\n\t * @param options - Options object used to construct the initial SharedTree\n\t */\n\tasync function countViewChange(\n\t\taction: (checkout: Checkout, simpleTestTree: TestTree, data: { changeCount: number }) => void | Promise<void>,\n\t\toptions: SharedTreeTestingOptions = { localMode: true }\n\t): Promise<number> {\n\t\tconst { checkout, tree } = await setUpTestCheckout(options);\n\t\tconst simpleTestTree = setUpTestTree(tree);\n\t\tawait checkout.waitForPendingUpdates();\n\t\tlet lastView = checkout.currentView;\n\t\tconst data = { changeCount: 0 };\n\t\tcheckout.on(CheckoutEvent.ViewChange, (before, after) => {\n\t\t\texpect(after).equals(checkout.currentView);\n\t\t\texpect(before).equals(lastView);\n\t\t\tlastView = after;\n\t\t\tdata.changeCount++;\n\t\t});\n\t\t// Prevent errors from errors (like failed expects) from being hidden.\n\t\tconst errors: Error[] = [];\n\t\tcheckout.on('error', (error) => {\n\t\t\terrors.push(error);\n\t\t});\n\n\t\tawait action(checkout, simpleTestTree, data);\n\t\texpect(errors).deep.equal([]);\n\t\treturn data.changeCount;\n\t}\n\n\tasync function setUpTestTreeCheckout(): Promise<{\n\t\tcheckout: Checkout;\n\t\tsharedTree: SharedTree;\n\t\ttestTree: TestTree;\n\t}> {\n\t\tconst { checkout, tree } = await setUpTestCheckout();\n\t\tconst testTree = setUpTestTree(tree);\n\t\tawait checkout.waitForPendingUpdates();\n\t\treturn { checkout, sharedTree: tree, testTree };\n\t}\n\n\tdescribe(checkoutName, () => {\n\t\tit('can only have one edit open at a time', async () => {\n\t\t\tconst { checkout } = await setUpTestCheckout();\n\t\t\tcheckout.openEdit();\n\t\t\texpect(() => checkout.openEdit()).throws();\n\t\t});\n\n\t\tit('can only close an edit if one is open', async () => {\n\t\t\tconst { checkout } = await setUpTestCheckout();\n\t\t\texpect(() => checkout.closeEdit()).throws();\n\t\t});\n\n\t\tit('can only apply changes if an edit is open', async () => {\n\t\t\tconst { checkout, testTree } = await setUpTestTreeCheckout();\n\t\t\texpect(() => checkout.applyChanges(Change.delete(StableRange.only(testTree.left)))).throws();\n\t\t});\n\n\t\tit('cannot abort an edit if no edit is open', async () => {\n\t\t\tconst { checkout } = await setUpTestCheckout();\n\t\t\texpect(() => checkout.abortEdit()).throws();\n\t\t});\n\n\t\tit('can abort valid edits', async () => {\n\t\t\tconst { checkout, testTree } = await setUpTestTreeCheckout();\n\t\t\tcheckout.openEdit();\n\t\t\t// Is still valid after a valid edit\n\t\t\tcheckout.applyChanges(Change.delete(StableRange.only(testTree.left.identifier)));\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\t\t\tcheckout.abortEdit();\n\n\t\t\t// The left node should still be there\n\t\t\texpect(checkout.currentView.getViewNode(testTree.left.identifier).identifier).not.undefined;\n\t\t});\n\n\t\tit('can abort invalid edits', async () => {\n\t\t\tconst { checkout, testTree } = await setUpTestTreeCheckout();\n\t\t\tcheckout.openEdit();\n\t\t\t// Starts as valid\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\n\t\t\t// Is invalid after an invalid edit\n\t\t\texpect(() =>\n\t\t\t\tcheckout.applyChanges(...Change.insertTree(testTree.left, StablePlace.after(testTree.left)))\n\t\t\t).throws('Locally constructed edits must be well-formed and valid.');\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Invalid);\n\t\t\tcheckout.abortEdit();\n\n\t\t\t// Next edit is unaffected\n\t\t\tcheckout.openEdit();\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\t\t\tcheckout.closeEdit();\n\t\t});\n\n\t\tit('can abort malformed edits', async () => {\n\t\t\tconst { checkout, testTree } = await setUpTestTreeCheckout();\n\t\t\tcheckout.openEdit();\n\t\t\t// Starts as valid\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\n\t\t\t// Is malformed after a malformed edit\n\t\t\tconst malformedMove = Change.move(\n\t\t\t\t{\n\t\t\t\t\tstart: { side: Side.Before },\n\t\t\t\t\tend: { side: Side.After },\n\t\t\t\t},\n\t\t\t\t{ side: Side.After }\n\t\t\t);\n\t\t\texpect(() => checkout.applyChanges(...malformedMove)).throws(\n\t\t\t\t'Locally constructed edits must be well-formed and valid.'\n\t\t\t);\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Malformed);\n\n\t\t\t// Is still malformed after a subsequent valid edit\n\t\t\texpect(() => checkout.applyChanges(Change.delete(StableRange.only(testTree.left)))).throws(\n\t\t\t\t'Cannot apply change to an edit unless all previous changes have applied'\n\t\t\t);\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Malformed);\n\n\t\t\tcheckout.abortEdit();\n\n\t\t\t// Next edit is unaffected\n\t\t\tcheckout.openEdit();\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\t\t\tcheckout.closeEdit();\n\t\t});\n\n\t\tit('can try to apply an invalid edit and abort without causing an error', async () => {\n\t\t\tconst { checkout, tree } = await setUpTestCheckout();\n\t\t\tconst simpleTestTree = setUpTestTree(tree);\n\n\t\t\t// tryApplyEdit aborts when applying an invalid edit and returns undefined\n\t\t\texpect(\n\t\t\t\tcheckout.tryApplyEdit(...Change.insertTree(simpleTestTree.left, StablePlace.after(simpleTestTree.left)))\n\t\t\t).to.be.undefined;\n\n\t\t\t// Next edit is unaffected\n\t\t\tcheckout.openEdit();\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\t\t\tcheckout.closeEdit();\n\t\t});\n\n\t\tit('cannot get the edit status if no edit is open', async () => {\n\t\t\tconst { checkout } = await setUpTestCheckout();\n\t\t\texpect(() => checkout.getEditStatus()).throws();\n\t\t});\n\n\t\tit('Surfaces error events to SharedTree', async () => {\n\t\t\tconst { checkout, tree } = await setUpTestCheckout();\n\t\t\tconst message = 'Simulated unexpected error in ViewChange event handler';\n\t\t\tcheckout.on(CheckoutEvent.ViewChange, () => {\n\t\t\t\tthrow Error(message);\n\t\t\t});\n\t\t\tlet treeErrorHandlerWasCalled = false;\n\t\t\ttree.on('error', (error) => {\n\t\t\t\ttreeErrorHandlerWasCalled = true;\n\t\t\t\texpect(error).to.have.property('message').that.equals(message);\n\t\t\t});\n\n\t\t\t// This could alternatively actually cause a ViewChange via application of an edit.\n\t\t\tcheckout.emit(CheckoutEvent.ViewChange, checkout.currentView, checkout.currentView);\n\t\t\texpect(treeErrorHandlerWasCalled).equals(true);\n\t\t});\n\n\t\tit('exposes the current edit status in the face of valid edits', async () => {\n\t\t\tconst { checkout, testTree } = await setUpTestTreeCheckout();\n\t\t\tcheckout.openEdit();\n\t\t\t// Starts as valid\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\n\t\t\t// Is still valid after a valid edit\n\t\t\tcheckout.applyChanges(Change.delete(StableRange.only(testTree.left)));\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\n\t\t\tcheckout.closeEdit();\n\t\t});\n\n\t\tit('exposes the current edit status in the face of invalid edits', async () => {\n\t\t\tconst { checkout, testTree } = await setUpTestTreeCheckout();\n\t\t\tcheckout.openEdit();\n\t\t\t// Starts as valid\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\n\t\t\t// Is invalid after an invalid edit\n\t\t\texpect(() =>\n\t\t\t\tcheckout.applyChanges(...Change.insertTree(testTree.left, StablePlace.after(testTree.left)))\n\t\t\t).throws('Locally constructed edits must be well-formed and valid.');\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Invalid);\n\n\t\t\t// Is still invalid after a subsequent valid edit\n\t\t\texpect(() => checkout.applyChanges(Change.delete(StableRange.only(testTree.left)))).throws(\n\t\t\t\t'Cannot apply change to an edit unless all previous changes have applied'\n\t\t\t);\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Invalid);\n\n\t\t\texpect(() => checkout.closeEdit()).throws('Locally constructed edits must be well-formed and valid');\n\n\t\t\t// Next edit is unaffected\n\t\t\tcheckout.openEdit();\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\t\t\tcheckout.closeEdit();\n\t\t});\n\n\t\tit('exposes the current edit status in the face of malformed edits', async () => {\n\t\t\tconst { checkout, testTree } = await setUpTestTreeCheckout();\n\t\t\tcheckout.openEdit();\n\t\t\t// Starts as valid\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\n\t\t\t// Is malformed after a malformed edit\n\t\t\tconst malformedMove = Change.move(\n\t\t\t\t{\n\t\t\t\t\tstart: { side: Side.Before },\n\t\t\t\t\tend: { side: Side.After },\n\t\t\t\t},\n\t\t\t\t{ side: Side.After }\n\t\t\t);\n\t\t\texpect(() => checkout.applyChanges(...malformedMove)).throws(\n\t\t\t\t'Locally constructed edits must be well-formed and valid.'\n\t\t\t);\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Malformed);\n\n\t\t\t// Is still malformed after a subsequent valid edit\n\t\t\texpect(() => checkout.applyChanges(Change.delete(StableRange.only(testTree.left)))).throws(\n\t\t\t\t'Cannot apply change to an edit unless all previous changes have applied'\n\t\t\t);\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Malformed);\n\n\t\t\texpect(() => checkout.closeEdit()).throws('Locally constructed edits must be well-formed and valid');\n\n\t\t\t// Next edit is unaffected\n\t\t\tcheckout.openEdit();\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\t\t\tcheckout.closeEdit();\n\t\t});\n\n\t\tit('does not invalidate in response to an empty edit', async () => {\n\t\t\tconst invalidations = await countViewChange((checkout) => {\n\t\t\t\tcheckout.openEdit();\n\t\t\t\tcheckout.closeEdit();\n\t\t\t});\n\t\t\texpect(invalidations).equals(0);\n\t\t});\n\n\t\tit('records empty edits', async () => {\n\t\t\tconst { checkout, tree } = await setUpTestCheckout();\n\t\t\tcheckout.openEdit();\n\t\t\tconst editId = checkout.closeEdit();\n\t\t\tawait checkout.waitForPendingUpdates();\n\t\t\texpect(tree.edits.length).equals(1);\n\t\t\texpect(tree.edits.tryGetEdit(editId)).is.not.undefined;\n\t\t});\n\n\t\tit('will emit invalidation messages in response to changes', async () => {\n\t\t\tconst invalidations = await countViewChange((checkout, simpleTestTree) => {\n\t\t\t\tcheckout.applyEdit(Change.delete(StableRange.only(simpleTestTree.left)));\n\t\t\t});\n\t\t\texpect(invalidations).equals(1);\n\t\t});\n\n\t\tit('will emit invalidation messages in response to payload change', async () => {\n\t\t\tconst invalidations = await countViewChange((checkout, simpleTestTree) => {\n\t\t\t\tcheckout.applyEdit(Change.setPayload(simpleTestTree.left.identifier, 5));\n\t\t\t});\n\t\t\texpect(invalidations).equals(1);\n\t\t});\n\n\t\tit('emits a change event for each batch of changes in a local edit', async () => {\n\t\t\tconst changes = await countViewChange(async (checkout, simpleTestTree, data) => {\n\t\t\t\tcheckout.on(CheckoutEvent.ViewChange, () => {\n\t\t\t\t\tconst leftTrait = checkout.currentView.getTrait(simpleTestTree.left.traitLocation);\n\t\t\t\t\tconst rightTrait = checkout.currentView.getTrait(simpleTestTree.right.traitLocation);\n\n\t\t\t\t\tif (data.changeCount === 1) {\n\t\t\t\t\t\texpect(leftTrait.length).to.equal(0); // \"left\" child is deleted...\n\t\t\t\t\t\texpect(rightTrait.length).to.equal(1); // ...but \"right\" child is not\n\t\t\t\t\t} else if (data.changeCount === 2) {\n\t\t\t\t\t\texpect(leftTrait.length).to.equal(0); // \"left\" child is deleted...\n\t\t\t\t\t\texpect(rightTrait.length).to.equal(0); // ...and so is \"right\" child\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tcheckout.openEdit();\n\t\t\t\texpect(data.changeCount).equals(0);\n\t\t\t\tcheckout.applyChanges(Change.delete(StableRange.only(simpleTestTree.left)));\n\t\t\t\texpect(data.changeCount).equals(1);\n\t\t\t\tcheckout.applyChanges(Change.delete(StableRange.only(simpleTestTree.right)));\n\t\t\t\texpect(data.changeCount).equals(2);\n\t\t\t\tcheckout.closeEdit();\n\t\t\t\tawait checkout.waitForPendingUpdates();\n\t\t\t});\n\n\t\t\t// Checkout's use of LogViewer.setKnownEditingResult should enable CachingLogViewer\n\t\t\t// to return the exact same revision view object, allowing checkout to skip an extra change event from closeEdit.\n\t\t\texpect(changes).equals(2);\n\t\t});\n\n\t\tit('emits ViewChange events for edits directly on tree', async () => {\n\t\t\tconst { checkout, testTree } = await setUpTestTreeCheckout();\n\t\t\tlet changeCount = 0;\n\t\t\tcheckout.on(CheckoutEvent.ViewChange, () => {\n\t\t\t\tchangeCount += 1;\n\t\t\t});\n\t\t\texpect(changeCount).equals(0);\n\t\t\tcheckout.tree.applyEdit(Change.delete(StableRange.only(testTree.left)));\n\t\t\t// Wait for edit to be included in checkout.\n\t\t\tawait checkout.waitForPendingUpdates();\n\t\t\texpect(changeCount).equals(1);\n\t\t});\n\n\t\tit('automatically loads views from edits committed directly on it', async () => {\n\t\t\tconst { checkout, testTree } = await setUpTestTreeCheckout();\n\t\t\tconst viewBefore = checkout.currentView;\n\t\t\tlet changeCount = 0;\n\t\t\tcheckout.on(CheckoutEvent.ViewChange, () => {\n\t\t\t\tchangeCount += 1;\n\t\t\t});\n\t\t\tcheckout.applyEdit(Change.delete(StableRange.only(testTree.left)));\n\t\t\texpect(changeCount).equals(1);\n\t\t\texpect(viewBefore.equals(checkout.currentView)).to.be.false;\n\t\t});\n\n\t\tconst secondTreeOptions = {\n\t\t\tid: 'secondTestSharedTree',\n\t\t\tlocalMode: false,\n\t\t\tallowInvalid: true,\n\t\t};\n\n\t\tit('can wait on edits to be submitted', async () => {\n\t\t\tconst { checkout, testTree } = await setUpTestTreeCheckout();\n\t\t\tlet committedEditsCount = 0;\n\t\t\tcheckout.tree.on(SharedTreeEvent.EditCommitted, () => {\n\t\t\t\tcommittedEditsCount += 1;\n\t\t\t});\n\t\t\texpect(committedEditsCount).equals(0);\n\t\t\tcheckout.tree.applyEdit(Change.delete(StableRange.only(testTree.left)));\n\t\t\tawait checkout.waitForEditsToSubmit();\n\t\t\texpect(committedEditsCount).equals(1);\n\t\t});\n\n\t\tit('emits ViewChange events for remote edits', async () => {\n\t\t\tconst { containerRuntimeFactory, tree } = setUpTestSharedTree({ localMode: false });\n\t\t\tconst simpleTestTree = setUpTestTree(tree);\n\n\t\t\tconst { tree: secondTree } = setUpTestSharedTree({\n\t\t\t\tcontainerRuntimeFactory,\n\t\t\t\t...secondTreeOptions,\n\t\t\t});\n\n\t\t\tcontainerRuntimeFactory.processAllMessages();\n\t\t\tconst checkout = await checkoutFactory(tree);\n\n\t\t\tlet changeCount = 0;\n\t\t\tcheckout.on(CheckoutEvent.ViewChange, () => {\n\t\t\t\tchangeCount += 1;\n\t\t\t});\n\n\t\t\tsecondTree.applyEdit(Change.delete(StableRange.only(simpleTestTree.left.translateId(secondTree))));\n\t\t\texpect(changeCount).equals(0);\n\t\t\tcontainerRuntimeFactory.processAllMessages();\n\t\t\t// Wait for edit to be included in checkout.\n\t\t\tawait checkout.waitForPendingUpdates();\n\t\t\texpect(changeCount).equals(1);\n\t\t\texpect(secondTree.equals(tree));\n\t\t});\n\n\t\tit('connected state with a remote SharedTree equates correctly during edits', async () => {\n\t\t\t// Invalid edits are allowed here because this test creates edits concurrently in two trees,\n\t\t\t// which after syncing, end up with one being invalid.\n\t\t\tconst { tree, containerRuntimeFactory } = setUpTestSharedTree({ localMode: false, allowInvalid: true });\n\t\t\tconst simpleTestTree = setUpTestTree(tree);\n\t\t\tconst { tree: secondTree } = setUpTestSharedTree({\n\t\t\t\tcontainerRuntimeFactory,\n\t\t\t\t...secondTreeOptions,\n\t\t\t});\n\n\t\t\tcontainerRuntimeFactory.processAllMessages();\n\t\t\tconst checkout = await checkoutFactory(tree);\n\t\t\tconst secondCheckout = await checkoutFactory(tree);\n\n\t\t\texpect(checkout.currentView.equals(secondCheckout.currentView)).to.be.true;\n\t\t\texpect(checkout.currentView.hasEqualForest(secondCheckout.currentView)).to.be.true;\n\t\t\tcheckout.openEdit();\n\t\t\texpect(checkout.currentView.equals(secondCheckout.currentView)).to.be.false;\n\t\t\texpect(checkout.currentView.hasEqualForest(secondCheckout.currentView)).to.be.true;\n\t\t\texpect(tree.equals(secondTree)).to.be.true;\n\t\t\tsecondCheckout.openEdit();\n\t\t\texpect(checkout.currentView.equals(secondCheckout.currentView)).to.be.true;\n\t\t\texpect(checkout.currentView.hasEqualForest(secondCheckout.currentView)).to.be.true;\n\t\t\texpect(tree.equals(secondTree)).to.be.true;\n\t\t\tcheckout.applyChanges(Change.delete(StableRange.only(simpleTestTree.left)));\n\t\t\texpect(checkout.currentView.equals(secondCheckout.currentView)).to.be.false;\n\t\t\texpect(checkout.currentView.hasEqualForest(secondCheckout.currentView)).to.be.false;\n\t\t\tsecondCheckout.applyChanges(Change.delete(StableRange.only(simpleTestTree.left)));\n\t\t\texpect(checkout.currentView.equals(secondCheckout.currentView)).to.be.true;\n\t\t\texpect(checkout.currentView.hasEqualForest(secondCheckout.currentView)).to.be.true;\n\t\t\texpect(tree.equals(secondTree)).to.be.true;\n\t\t\tcheckout.closeEdit();\n\t\t\tawait checkout.waitForPendingUpdates();\n\t\t\texpect(checkout.currentView.equals(secondCheckout.currentView)).to.be.false;\n\t\t\texpect(checkout.currentView.hasEqualForest(secondCheckout.currentView)).to.be.true;\n\t\t\tsecondCheckout.closeEdit();\n\t\t\tawait secondCheckout.waitForPendingUpdates();\n\t\t\texpect(checkout.currentView.equals(secondCheckout.currentView)).to.be.true;\n\t\t\texpect(checkout.currentView.hasEqualForest(secondCheckout.currentView)).to.be.true;\n\t\t\tawait checkout.waitForPendingUpdates();\n\t\t\tawait secondCheckout.waitForPendingUpdates();\n\t\t\tcontainerRuntimeFactory.processAllMessages();\n\t\t\texpect(tree.equals(secondTree)).to.be.true;\n\t\t\tawait checkout.waitForPendingUpdates();\n\t\t\tawait secondCheckout.waitForPendingUpdates();\n\t\t\texpect(checkout.currentView.equals(secondCheckout.currentView)).to.be.true;\n\t\t\texpect(checkout.currentView.hasEqualForest(secondCheckout.currentView)).to.be.true;\n\t\t});\n\n\t\tit('can successfully rebase an ongoing local edit', async () => {\n\t\t\tconst { tree, containerRuntimeFactory } = setUpTestSharedTree({ localMode: false });\n\t\t\tconst simpleTestTree = setUpTestTree(tree);\n\t\t\tconst { tree: secondTree } = setUpTestSharedTree({ containerRuntimeFactory, ...secondTreeOptions });\n\n\t\t\t// Sync initial tree\n\t\t\tcontainerRuntimeFactory.processAllMessages();\n\n\t\t\tconst checkout = await checkoutFactory(tree);\n\t\t\tconst secondCheckout = await checkoutFactory(secondTree);\n\n\t\t\tconst newLeftNode = simpleTestTree.buildLeaf(simpleTestTree.generateNodeId());\n\t\t\tcheckout.openEdit();\n\t\t\tcheckout.applyChanges(...setTrait(simpleTestTree.left.traitLocation, [newLeftNode]));\n\n\t\t\t// Concurrently, the second client deletes the right node. This will not conflict with the operation performed\n\t\t\t// on the left trait on the first client.\n\t\t\tsecondCheckout.applyEdit(Change.delete(StableRange.only(simpleTestTree.right.translateId(secondTree))));\n\t\t\tawait secondCheckout.waitForPendingUpdates();\n\n\t\t\t// Deliver the remote change. Since there will not be any conflicts, the result should merge locally and both trait\n\t\t\t// modifications should be reflected in the current view.\n\t\t\tcontainerRuntimeFactory.processAllMessages();\n\n\t\t\tawait checkout.waitForPendingUpdates();\n\t\t\tawait secondCheckout.waitForPendingUpdates();\n\n\t\t\tlet leftTrait = checkout.currentView.getTrait(simpleTestTree.left.traitLocation);\n\t\t\tlet rightTrait = checkout.currentView.getTrait(simpleTestTree.right.traitLocation);\n\t\t\texpect(leftTrait).deep.equals([newLeftNode.identifier]);\n\t\t\t// The remote deletion of the right node, while delivered, will not be reflected in the view yet.\n\t\t\texpect(rightTrait).deep.equals([simpleTestTree.right.identifier]);\n\n\t\t\tconst secondLeftTrait = secondCheckout.currentView.getTrait(\n\t\t\t\tsimpleTestTree.left.traitLocation.translate(secondTree)\n\t\t\t);\n\t\t\tconst secondRightTrait = secondCheckout.currentView.getTrait(\n\t\t\t\tsimpleTestTree.right.traitLocation.translate(secondTree)\n\t\t\t);\n\t\t\texpect(secondLeftTrait).deep.equals([simpleTestTree.left.translateId(secondTree)]);\n\t\t\texpect(secondRightTrait.length).equals(0);\n\n\t\t\t// Merge in the latest changes.\n\t\t\tawait checkout.waitForPendingUpdates();\n\t\t\tconst rebaseResult = checkout.rebaseCurrentEdit();\n\t\t\texpect(rebaseResult).equals(EditValidationResult.Valid);\n\t\t\tleftTrait = checkout.currentView.getTrait(simpleTestTree.left.traitLocation);\n\t\t\trightTrait = checkout.currentView.getTrait(simpleTestTree.right.traitLocation);\n\t\t\texpect(leftTrait).deep.equals([newLeftNode.identifier]);\n\t\t\texpect(rightTrait.length).equals(0);\n\n\t\t\tcheckout.closeEdit();\n\t\t\t// Again, call this prior to processing ops to accommodate PrefetchingCheckout\n\t\t\tawait checkout.waitForPendingUpdates();\n\t\t\tcontainerRuntimeFactory.processAllMessages();\n\t\t\tawait secondCheckout.waitForPendingUpdates();\n\t\t\texpect(tree.equals(secondTree)).to.be.true;\n\t\t});\n\n\t\tit('can handle a failed rebase of an ongoing local edit', async () => {\n\t\t\tconst { tree, containerRuntimeFactory } = setUpTestSharedTree({ localMode: false });\n\t\t\tconst simpleTestTree = setUpTestTree(tree);\n\t\t\tconst { tree: secondTree } = setUpTestSharedTree({ containerRuntimeFactory, ...secondTreeOptions });\n\n\t\t\t// Sync initial tree\n\t\t\tcontainerRuntimeFactory.processAllMessages();\n\n\t\t\tconst checkout = await checkoutFactory(tree);\n\t\t\tconst secondCheckout = await checkoutFactory(secondTree);\n\n\t\t\tcheckout.openEdit();\n\t\t\t// Move the left node to after the right node\n\t\t\tcheckout.applyChanges(\n\t\t\t\t...Change.move(StableRange.only(simpleTestTree.left), StablePlace.after(simpleTestTree.right))\n\t\t\t);\n\n\t\t\t// Concurrently, the second client deletes the right node. This will conflict with the move operation by the first client.\n\t\t\tsecondCheckout.applyEdit(Change.delete(StableRange.only(simpleTestTree.right.translateId(secondTree))));\n\t\t\tawait secondCheckout.waitForPendingUpdates();\n\n\t\t\tcontainerRuntimeFactory.processAllMessages();\n\t\t\tawait checkout.waitForPendingUpdates();\n\t\t\tawait secondCheckout.waitForPendingUpdates();\n\n\t\t\t// Before rebasing, the first client should still see the right node and will have moved the left node after it.\n\t\t\tconst leftTrait = checkout.currentView.getTrait(simpleTestTree.left.traitLocation);\n\t\t\tconst rightTrait = checkout.currentView.getTrait(simpleTestTree.right.traitLocation);\n\t\t\texpect(leftTrait).deep.equals([]);\n\t\t\texpect(rightTrait).deep.equals([simpleTestTree.right.identifier, simpleTestTree.left.identifier]);\n\n\t\t\t// Merge in the latest changes.\n\t\t\tconst rebaseResult = checkout.rebaseCurrentEdit();\n\t\t\texpect(rebaseResult).equals(EditValidationResult.Invalid);\n\t\t\texpect(\n\t\t\t\tareRevisionViewsSemanticallyEqual(checkout.currentView, tree, secondCheckout.currentView, secondTree)\n\t\t\t).to.be.true;\n\t\t});\n\n\t\tit('can dispose and remove listeners', async () => {\n\t\t\tconst { checkout } = await setUpTestCheckout();\n\t\t\texpect(checkout.tree.listenerCount(SharedTreeEvent.EditCommitted)).to.equal(1);\n\t\t\tcheckout.dispose();\n\t\t\texpect(checkout.tree.listenerCount(SharedTreeEvent.EditCommitted)).to.equal(0);\n\t\t});\n\n\t\tadditionalTests?.();\n\t});\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Checkout.tests.js","sourceRoot":"","sources":["../../src/test/Checkout.tests.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 { ITelemetryBaseEvent } from '@fluidframework/common-definitions';\nimport { expect } from 'chai';\nimport {\n\tsetTrait,\n\tEditStatus,\n\tStableRange,\n\tStablePlace,\n\tEditValidationResult,\n\tSharedTree,\n\tSharedTreeEvent,\n\tCheckout,\n\tCheckoutEvent,\n\tChange,\n\tSide,\n\tareRevisionViewsSemanticallyEqual,\n} from '../index';\nimport { TestTree } from './utilities/TestNode';\nimport { setUpTestSharedTree, SharedTreeTestingOptions, setUpTestTree } from './utilities/TestUtilities';\n\n/**\n * Checkout test suite\n */\nexport function checkoutTests(\n\tcheckoutName: string,\n\tcheckoutFactory: (tree: SharedTree) => Promise<Checkout>,\n\tadditionalTests?: () => void\n): void {\n\tasync function setUpTestCheckout(\n\t\toptionsArg?: SharedTreeTestingOptions\n\t): Promise<{ checkout: Checkout; tree: SharedTree }> {\n\t\tconst options = { localMode: true, noFailOnError: true, ...optionsArg };\n\t\tconst { tree } = setUpTestSharedTree(options);\n\t\treturn { checkout: await checkoutFactory(tree), tree };\n\t}\n\n\t/**\n\t * Counts the number of times ViewChange occurs while performing `action`.\n\t * Checks arguments to ViewChange are correct as well.\n\t * @param action - Action to perform\n\t * @param options - Options object used to construct the initial SharedTree\n\t */\n\tasync function countViewChange(\n\t\taction: (checkout: Checkout, simpleTestTree: TestTree, data: { changeCount: number }) => void | Promise<void>,\n\t\toptions: SharedTreeTestingOptions = { localMode: true }\n\t): Promise<number> {\n\t\tconst { checkout, tree } = await setUpTestCheckout(options);\n\t\tconst simpleTestTree = setUpTestTree(tree);\n\t\tawait checkout.waitForPendingUpdates();\n\t\tlet lastView = checkout.currentView;\n\t\tconst data = { changeCount: 0 };\n\t\tcheckout.on(CheckoutEvent.ViewChange, (before, after) => {\n\t\t\texpect(after).equals(checkout.currentView);\n\t\t\texpect(before).equals(lastView);\n\t\t\tlastView = after;\n\t\t\tdata.changeCount++;\n\t\t});\n\t\t// Prevent errors from errors (like failed expects) from being hidden.\n\t\tconst errors: Error[] = [];\n\t\tcheckout.on('error', (error) => {\n\t\t\terrors.push(error);\n\t\t});\n\n\t\tawait action(checkout, simpleTestTree, data);\n\t\texpect(errors).deep.equal([]);\n\t\treturn data.changeCount;\n\t}\n\n\tasync function setUpTestTreeCheckout(options?: SharedTreeTestingOptions): Promise<{\n\t\tcheckout: Checkout;\n\t\tsharedTree: SharedTree;\n\t\ttestTree: TestTree;\n\t}> {\n\t\tconst { checkout, tree } = await setUpTestCheckout(options);\n\t\tconst testTree = setUpTestTree(tree);\n\t\tawait checkout.waitForPendingUpdates();\n\t\treturn { checkout, sharedTree: tree, testTree };\n\t}\n\n\tdescribe(checkoutName, () => {\n\t\tit('can only have one edit open at a time', async () => {\n\t\t\tconst { checkout } = await setUpTestCheckout();\n\t\t\tcheckout.openEdit();\n\t\t\texpect(() => checkout.openEdit()).throws();\n\t\t});\n\n\t\tit('can only close an edit if one is open', async () => {\n\t\t\tconst { checkout } = await setUpTestCheckout();\n\t\t\texpect(() => checkout.closeEdit()).throws();\n\t\t});\n\n\t\tit('can only apply changes if an edit is open', async () => {\n\t\t\tconst { checkout, testTree } = await setUpTestTreeCheckout();\n\t\t\texpect(() => checkout.applyChanges(Change.delete(StableRange.only(testTree.left)))).throws();\n\t\t});\n\n\t\tit('cannot abort an edit if no edit is open', async () => {\n\t\t\tconst { checkout } = await setUpTestCheckout();\n\t\t\texpect(() => checkout.abortEdit()).throws();\n\t\t});\n\n\t\tit('can abort valid edits', async () => {\n\t\t\tconst { checkout, testTree } = await setUpTestTreeCheckout();\n\t\t\tcheckout.openEdit();\n\t\t\t// Is still valid after a valid edit\n\t\t\tcheckout.applyChanges(Change.delete(StableRange.only(testTree.left.identifier)));\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\t\t\tcheckout.abortEdit();\n\n\t\t\t// The left node should still be there\n\t\t\texpect(checkout.currentView.getViewNode(testTree.left.identifier).identifier).not.undefined;\n\t\t});\n\n\t\tit('can abort invalid edits', async () => {\n\t\t\tconst { checkout, testTree } = await setUpTestTreeCheckout();\n\t\t\tcheckout.openEdit();\n\t\t\t// Starts as valid\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\n\t\t\t// Is invalid after an invalid edit\n\t\t\texpect(() =>\n\t\t\t\tcheckout.applyChanges(Change.insertTree(testTree.left, StablePlace.after(testTree.left)))\n\t\t\t).throws('Locally constructed edits must be well-formed and valid.');\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Invalid);\n\t\t\tcheckout.abortEdit();\n\n\t\t\t// Next edit is unaffected\n\t\t\tcheckout.openEdit();\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\t\t\tcheckout.closeEdit();\n\t\t});\n\n\t\tit('can abort malformed edits', async () => {\n\t\t\tconst { checkout, testTree } = await setUpTestTreeCheckout();\n\t\t\tcheckout.openEdit();\n\t\t\t// Starts as valid\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\n\t\t\t// Is malformed after a malformed edit\n\t\t\tconst malformedMove = Change.move(\n\t\t\t\t{\n\t\t\t\t\tstart: { side: Side.Before },\n\t\t\t\t\tend: { side: Side.After },\n\t\t\t\t},\n\t\t\t\t{ side: Side.After }\n\t\t\t);\n\t\t\texpect(() => checkout.applyChanges(malformedMove)).throws(\n\t\t\t\t'Locally constructed edits must be well-formed and valid.'\n\t\t\t);\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Malformed);\n\n\t\t\t// Is still malformed after a subsequent valid edit\n\t\t\texpect(() => checkout.applyChanges(Change.delete(StableRange.only(testTree.left)))).throws(\n\t\t\t\t'Cannot apply change to an edit unless all previous changes have applied'\n\t\t\t);\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Malformed);\n\n\t\t\tcheckout.abortEdit();\n\n\t\t\t// Next edit is unaffected\n\t\t\tcheckout.openEdit();\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\t\t\tcheckout.closeEdit();\n\t\t});\n\n\t\tit.only('emits error telemetry on attempted close of malformed edits', async () => {\n\t\t\tconst events: ITelemetryBaseEvent[] = [];\n\t\t\tconst { checkout } = await setUpTestTreeCheckout({\n\t\t\t\tlogger: { send: (event) => event.eventName.includes('Checkout') && events.push(event) },\n\t\t\t});\n\t\t\tcheckout.openEdit();\n\t\t\t// Starts as valid\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\n\t\t\t// Is malformed after a malformed edit\n\t\t\tconst malformedMove = Change.move(\n\t\t\t\t{\n\t\t\t\t\tstart: { side: Side.Before },\n\t\t\t\t\tend: { side: Side.After },\n\t\t\t\t},\n\t\t\t\t{ side: Side.After }\n\t\t\t);\n\t\t\texpect(() => checkout.applyChanges(...malformedMove)).throws(\n\t\t\t\t'Locally constructed edits must be well-formed and valid.'\n\t\t\t);\n\t\t\texpect(events.length).to.equal(0);\n\t\t\texpect(() => checkout.closeEdit()).throws('Locally constructed edits must be well-formed and valid');\n\t\t\texpect(events.length).to.equal(1);\n\t\t\texpect(events[0]).to.deep.equal({\n\t\t\t\tcategory: 'error',\n\t\t\t\terror: 'FailedLocalEdit',\n\t\t\t\teventName: 'SharedTree:Checkout:FailedLocalEdit',\n\t\t\t\tfailureKind: 'BadRange',\n\t\t\t\tisSharedTreeEvent: true,\n\t\t\t\trangeFailure: 'BadPlace',\n\t\t\t\trangeEndpointFailure: 'Malformed',\n\t\t\t\tstatus: 'Malformed',\n\t\t\t});\n\t\t});\n\n\t\tit('can try to apply an invalid edit and abort without causing an error', async () => {\n\t\t\tconst { checkout, tree } = await setUpTestCheckout();\n\t\t\tconst simpleTestTree = setUpTestTree(tree);\n\n\t\t\t// tryApplyEdit aborts when applying an invalid edit and returns undefined\n\t\t\texpect(\n\t\t\t\tcheckout.tryApplyEdit(Change.insertTree(simpleTestTree.left, StablePlace.after(simpleTestTree.left)))\n\t\t\t).to.be.undefined;\n\n\t\t\t// Next edit is unaffected\n\t\t\tcheckout.openEdit();\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\t\t\tcheckout.closeEdit();\n\t\t});\n\n\t\tit('cannot get the edit status if no edit is open', async () => {\n\t\t\tconst { checkout } = await setUpTestCheckout();\n\t\t\texpect(() => checkout.getEditStatus()).throws();\n\t\t});\n\n\t\tit('Surfaces error events to SharedTree', async () => {\n\t\t\tconst { checkout, tree } = await setUpTestCheckout();\n\t\t\tconst message = 'Simulated unexpected error in ViewChange event handler';\n\t\t\tcheckout.on(CheckoutEvent.ViewChange, () => {\n\t\t\t\tthrow Error(message);\n\t\t\t});\n\t\t\tlet treeErrorHandlerWasCalled = false;\n\t\t\ttree.on('error', (error) => {\n\t\t\t\ttreeErrorHandlerWasCalled = true;\n\t\t\t\texpect(error).to.have.property('message').that.equals(message);\n\t\t\t});\n\n\t\t\t// This could alternatively actually cause a ViewChange via application of an edit.\n\t\t\tcheckout.emit(CheckoutEvent.ViewChange, checkout.currentView, checkout.currentView);\n\t\t\texpect(treeErrorHandlerWasCalled).equals(true);\n\t\t});\n\n\t\tit('exposes the current edit status in the face of valid edits', async () => {\n\t\t\tconst { checkout, testTree } = await setUpTestTreeCheckout();\n\t\t\tcheckout.openEdit();\n\t\t\t// Starts as valid\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\n\t\t\t// Is still valid after a valid edit\n\t\t\tcheckout.applyChanges(Change.delete(StableRange.only(testTree.left)));\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\n\t\t\tcheckout.closeEdit();\n\t\t});\n\n\t\tit('exposes the current edit status in the face of invalid edits', async () => {\n\t\t\tconst { checkout, testTree } = await setUpTestTreeCheckout();\n\t\t\tcheckout.openEdit();\n\t\t\t// Starts as valid\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\n\t\t\t// Is invalid after an invalid edit\n\t\t\texpect(() =>\n\t\t\t\tcheckout.applyChanges(Change.insertTree(testTree.left, StablePlace.after(testTree.left)))\n\t\t\t).throws('Locally constructed edits must be well-formed and valid.');\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Invalid);\n\n\t\t\t// Is still invalid after a subsequent valid edit\n\t\t\texpect(() => checkout.applyChanges(Change.delete(StableRange.only(testTree.left)))).throws(\n\t\t\t\t'Cannot apply change to an edit unless all previous changes have applied'\n\t\t\t);\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Invalid);\n\n\t\t\texpect(() => checkout.closeEdit()).throws('Locally constructed edits must be well-formed and valid');\n\n\t\t\t// Next edit is unaffected\n\t\t\tcheckout.openEdit();\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\t\t\tcheckout.closeEdit();\n\t\t});\n\n\t\tit('exposes the current edit status in the face of malformed edits', async () => {\n\t\t\tconst { checkout, testTree } = await setUpTestTreeCheckout();\n\t\t\tcheckout.openEdit();\n\t\t\t// Starts as valid\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\n\t\t\t// Is malformed after a malformed edit\n\t\t\tconst malformedMove = Change.move(\n\t\t\t\t{\n\t\t\t\t\tstart: { side: Side.Before },\n\t\t\t\t\tend: { side: Side.After },\n\t\t\t\t},\n\t\t\t\t{ side: Side.After }\n\t\t\t);\n\t\t\texpect(() => checkout.applyChanges(malformedMove)).throws(\n\t\t\t\t'Locally constructed edits must be well-formed and valid.'\n\t\t\t);\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Malformed);\n\n\t\t\t// Is still malformed after a subsequent valid edit\n\t\t\texpect(() => checkout.applyChanges(Change.delete(StableRange.only(testTree.left)))).throws(\n\t\t\t\t'Cannot apply change to an edit unless all previous changes have applied'\n\t\t\t);\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Malformed);\n\n\t\t\texpect(() => checkout.closeEdit()).throws('Locally constructed edits must be well-formed and valid');\n\n\t\t\t// Next edit is unaffected\n\t\t\tcheckout.openEdit();\n\t\t\texpect(checkout.getEditStatus()).equals(EditStatus.Applied);\n\t\t\tcheckout.closeEdit();\n\t\t});\n\n\t\tit('does not invalidate in response to an empty edit', async () => {\n\t\t\tconst invalidations = await countViewChange((checkout) => {\n\t\t\t\tcheckout.openEdit();\n\t\t\t\tcheckout.closeEdit();\n\t\t\t});\n\t\t\texpect(invalidations).equals(0);\n\t\t});\n\n\t\tit('records empty edits', async () => {\n\t\t\tconst { checkout, tree } = await setUpTestCheckout();\n\t\t\tcheckout.openEdit();\n\t\t\tconst editId = checkout.closeEdit();\n\t\t\tawait checkout.waitForPendingUpdates();\n\t\t\texpect(tree.edits.length).equals(1);\n\t\t\texpect(tree.edits.tryGetEdit(editId)).is.not.undefined;\n\t\t});\n\n\t\tit('will emit invalidation messages in response to changes', async () => {\n\t\t\tconst invalidations = await countViewChange((checkout, simpleTestTree) => {\n\t\t\t\tcheckout.applyEdit(Change.delete(StableRange.only(simpleTestTree.left)));\n\t\t\t});\n\t\t\texpect(invalidations).equals(1);\n\t\t});\n\n\t\tit('will emit invalidation messages in response to payload change', async () => {\n\t\t\tconst invalidations = await countViewChange((checkout, simpleTestTree) => {\n\t\t\t\tcheckout.applyEdit(Change.setPayload(simpleTestTree.left.identifier, 5));\n\t\t\t});\n\t\t\texpect(invalidations).equals(1);\n\t\t});\n\n\t\tit('emits a change event for each batch of changes in a local edit', async () => {\n\t\t\tconst changes = await countViewChange(async (checkout, simpleTestTree, data) => {\n\t\t\t\tcheckout.on(CheckoutEvent.ViewChange, () => {\n\t\t\t\t\tconst leftTrait = checkout.currentView.getTrait(simpleTestTree.left.traitLocation);\n\t\t\t\t\tconst rightTrait = checkout.currentView.getTrait(simpleTestTree.right.traitLocation);\n\n\t\t\t\t\tif (data.changeCount === 1) {\n\t\t\t\t\t\texpect(leftTrait.length).to.equal(0); // \"left\" child is deleted...\n\t\t\t\t\t\texpect(rightTrait.length).to.equal(1); // ...but \"right\" child is not\n\t\t\t\t\t} else if (data.changeCount === 2) {\n\t\t\t\t\t\texpect(leftTrait.length).to.equal(0); // \"left\" child is deleted...\n\t\t\t\t\t\texpect(rightTrait.length).to.equal(0); // ...and so is \"right\" child\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tcheckout.openEdit();\n\t\t\t\texpect(data.changeCount).equals(0);\n\t\t\t\tcheckout.applyChanges(Change.delete(StableRange.only(simpleTestTree.left)));\n\t\t\t\texpect(data.changeCount).equals(1);\n\t\t\t\tcheckout.applyChanges(Change.delete(StableRange.only(simpleTestTree.right)));\n\t\t\t\texpect(data.changeCount).equals(2);\n\t\t\t\tcheckout.closeEdit();\n\t\t\t\tawait checkout.waitForPendingUpdates();\n\t\t\t});\n\n\t\t\t// Checkout's use of LogViewer.setKnownEditingResult should enable CachingLogViewer\n\t\t\t// to return the exact same revision view object, allowing checkout to skip an extra change event from closeEdit.\n\t\t\texpect(changes).equals(2);\n\t\t});\n\n\t\tit('emits ViewChange events for edits directly on tree', async () => {\n\t\t\tconst { checkout, testTree } = await setUpTestTreeCheckout();\n\t\t\tlet changeCount = 0;\n\t\t\tcheckout.on(CheckoutEvent.ViewChange, () => {\n\t\t\t\tchangeCount += 1;\n\t\t\t});\n\t\t\texpect(changeCount).equals(0);\n\t\t\tcheckout.tree.applyEdit(Change.delete(StableRange.only(testTree.left)));\n\t\t\t// Wait for edit to be included in checkout.\n\t\t\tawait checkout.waitForPendingUpdates();\n\t\t\texpect(changeCount).equals(1);\n\t\t});\n\n\t\tit('automatically loads views from edits committed directly on it', async () => {\n\t\t\tconst { checkout, testTree } = await setUpTestTreeCheckout();\n\t\t\tconst viewBefore = checkout.currentView;\n\t\t\tlet changeCount = 0;\n\t\t\tcheckout.on(CheckoutEvent.ViewChange, () => {\n\t\t\t\tchangeCount += 1;\n\t\t\t});\n\t\t\tcheckout.applyEdit(Change.delete(StableRange.only(testTree.left)));\n\t\t\texpect(changeCount).equals(1);\n\t\t\texpect(viewBefore.equals(checkout.currentView)).to.be.false;\n\t\t});\n\n\t\tconst secondTreeOptions = {\n\t\t\tid: 'secondTestSharedTree',\n\t\t\tlocalMode: false,\n\t\t\tallowInvalid: true,\n\t\t};\n\n\t\tit('can wait on edits to be submitted', async () => {\n\t\t\tconst { checkout, testTree } = await setUpTestTreeCheckout();\n\t\t\tlet committedEditsCount = 0;\n\t\t\tcheckout.tree.on(SharedTreeEvent.EditCommitted, () => {\n\t\t\t\tcommittedEditsCount += 1;\n\t\t\t});\n\t\t\texpect(committedEditsCount).equals(0);\n\t\t\tcheckout.tree.applyEdit(Change.delete(StableRange.only(testTree.left)));\n\t\t\tawait checkout.waitForEditsToSubmit();\n\t\t\texpect(committedEditsCount).equals(1);\n\t\t});\n\n\t\tit('emits ViewChange events for remote edits', async () => {\n\t\t\tconst { containerRuntimeFactory, tree } = setUpTestSharedTree({ localMode: false });\n\t\t\tconst simpleTestTree = setUpTestTree(tree);\n\n\t\t\tconst { tree: secondTree } = setUpTestSharedTree({\n\t\t\t\tcontainerRuntimeFactory,\n\t\t\t\t...secondTreeOptions,\n\t\t\t});\n\n\t\t\tcontainerRuntimeFactory.processAllMessages();\n\t\t\tconst checkout = await checkoutFactory(tree);\n\n\t\t\tlet changeCount = 0;\n\t\t\tcheckout.on(CheckoutEvent.ViewChange, () => {\n\t\t\t\tchangeCount += 1;\n\t\t\t});\n\n\t\t\tsecondTree.applyEdit(Change.delete(StableRange.only(simpleTestTree.left.translateId(secondTree))));\n\t\t\texpect(changeCount).equals(0);\n\t\t\tcontainerRuntimeFactory.processAllMessages();\n\t\t\t// Wait for edit to be included in checkout.\n\t\t\tawait checkout.waitForPendingUpdates();\n\t\t\texpect(changeCount).equals(1);\n\t\t\texpect(secondTree.equals(tree));\n\t\t});\n\n\t\tit('connected state with a remote SharedTree equates correctly during edits', async () => {\n\t\t\t// Invalid edits are allowed here because this test creates edits concurrently in two trees,\n\t\t\t// which after syncing, end up with one being invalid.\n\t\t\tconst { tree, containerRuntimeFactory } = setUpTestSharedTree({ localMode: false, allowInvalid: true });\n\t\t\tconst simpleTestTree = setUpTestTree(tree);\n\t\t\tconst { tree: secondTree } = setUpTestSharedTree({\n\t\t\t\tcontainerRuntimeFactory,\n\t\t\t\t...secondTreeOptions,\n\t\t\t});\n\n\t\t\tcontainerRuntimeFactory.processAllMessages();\n\t\t\tconst checkout = await checkoutFactory(tree);\n\t\t\tconst secondCheckout = await checkoutFactory(tree);\n\n\t\t\texpect(checkout.currentView.equals(secondCheckout.currentView)).to.be.true;\n\t\t\texpect(checkout.currentView.hasEqualForest(secondCheckout.currentView)).to.be.true;\n\t\t\tcheckout.openEdit();\n\t\t\texpect(checkout.currentView.equals(secondCheckout.currentView)).to.be.false;\n\t\t\texpect(checkout.currentView.hasEqualForest(secondCheckout.currentView)).to.be.true;\n\t\t\texpect(tree.equals(secondTree)).to.be.true;\n\t\t\tsecondCheckout.openEdit();\n\t\t\texpect(checkout.currentView.equals(secondCheckout.currentView)).to.be.true;\n\t\t\texpect(checkout.currentView.hasEqualForest(secondCheckout.currentView)).to.be.true;\n\t\t\texpect(tree.equals(secondTree)).to.be.true;\n\t\t\tcheckout.applyChanges(Change.delete(StableRange.only(simpleTestTree.left)));\n\t\t\texpect(checkout.currentView.equals(secondCheckout.currentView)).to.be.false;\n\t\t\texpect(checkout.currentView.hasEqualForest(secondCheckout.currentView)).to.be.false;\n\t\t\tsecondCheckout.applyChanges(Change.delete(StableRange.only(simpleTestTree.left)));\n\t\t\texpect(checkout.currentView.equals(secondCheckout.currentView)).to.be.true;\n\t\t\texpect(checkout.currentView.hasEqualForest(secondCheckout.currentView)).to.be.true;\n\t\t\texpect(tree.equals(secondTree)).to.be.true;\n\t\t\tcheckout.closeEdit();\n\t\t\tawait checkout.waitForPendingUpdates();\n\t\t\texpect(checkout.currentView.equals(secondCheckout.currentView)).to.be.false;\n\t\t\texpect(checkout.currentView.hasEqualForest(secondCheckout.currentView)).to.be.true;\n\t\t\tsecondCheckout.closeEdit();\n\t\t\tawait secondCheckout.waitForPendingUpdates();\n\t\t\texpect(checkout.currentView.equals(secondCheckout.currentView)).to.be.true;\n\t\t\texpect(checkout.currentView.hasEqualForest(secondCheckout.currentView)).to.be.true;\n\t\t\tawait checkout.waitForPendingUpdates();\n\t\t\tawait secondCheckout.waitForPendingUpdates();\n\t\t\tcontainerRuntimeFactory.processAllMessages();\n\t\t\texpect(tree.equals(secondTree)).to.be.true;\n\t\t\tawait checkout.waitForPendingUpdates();\n\t\t\tawait secondCheckout.waitForPendingUpdates();\n\t\t\texpect(checkout.currentView.equals(secondCheckout.currentView)).to.be.true;\n\t\t\texpect(checkout.currentView.hasEqualForest(secondCheckout.currentView)).to.be.true;\n\t\t});\n\n\t\tit('can successfully rebase an ongoing local edit', async () => {\n\t\t\tconst { tree, containerRuntimeFactory } = setUpTestSharedTree({ localMode: false });\n\t\t\tconst simpleTestTree = setUpTestTree(tree);\n\t\t\tconst { tree: secondTree } = setUpTestSharedTree({ containerRuntimeFactory, ...secondTreeOptions });\n\n\t\t\t// Sync initial tree\n\t\t\tcontainerRuntimeFactory.processAllMessages();\n\n\t\t\tconst checkout = await checkoutFactory(tree);\n\t\t\tconst secondCheckout = await checkoutFactory(secondTree);\n\n\t\t\tconst newLeftNode = simpleTestTree.buildLeaf(simpleTestTree.generateNodeId());\n\t\t\tcheckout.openEdit();\n\t\t\tcheckout.applyChanges(setTrait(simpleTestTree.left.traitLocation, [newLeftNode]));\n\n\t\t\t// Concurrently, the second client deletes the right node. This will not conflict with the operation performed\n\t\t\t// on the left trait on the first client.\n\t\t\tsecondCheckout.applyEdit(Change.delete(StableRange.only(simpleTestTree.right.translateId(secondTree))));\n\t\t\tawait secondCheckout.waitForPendingUpdates();\n\n\t\t\t// Deliver the remote change. Since there will not be any conflicts, the result should merge locally and both trait\n\t\t\t// modifications should be reflected in the current view.\n\t\t\tcontainerRuntimeFactory.processAllMessages();\n\n\t\t\tawait checkout.waitForPendingUpdates();\n\t\t\tawait secondCheckout.waitForPendingUpdates();\n\n\t\t\tlet leftTrait = checkout.currentView.getTrait(simpleTestTree.left.traitLocation);\n\t\t\tlet rightTrait = checkout.currentView.getTrait(simpleTestTree.right.traitLocation);\n\t\t\texpect(leftTrait).deep.equals([newLeftNode.identifier]);\n\t\t\t// The remote deletion of the right node, while delivered, will not be reflected in the view yet.\n\t\t\texpect(rightTrait).deep.equals([simpleTestTree.right.identifier]);\n\n\t\t\tconst secondLeftTrait = secondCheckout.currentView.getTrait(\n\t\t\t\tsimpleTestTree.left.traitLocation.translate(secondTree)\n\t\t\t);\n\t\t\tconst secondRightTrait = secondCheckout.currentView.getTrait(\n\t\t\t\tsimpleTestTree.right.traitLocation.translate(secondTree)\n\t\t\t);\n\t\t\texpect(secondLeftTrait).deep.equals([simpleTestTree.left.translateId(secondTree)]);\n\t\t\texpect(secondRightTrait.length).equals(0);\n\n\t\t\t// Merge in the latest changes.\n\t\t\tawait checkout.waitForPendingUpdates();\n\t\t\tconst rebaseResult = checkout.rebaseCurrentEdit();\n\t\t\texpect(rebaseResult).equals(EditValidationResult.Valid);\n\t\t\tleftTrait = checkout.currentView.getTrait(simpleTestTree.left.traitLocation);\n\t\t\trightTrait = checkout.currentView.getTrait(simpleTestTree.right.traitLocation);\n\t\t\texpect(leftTrait).deep.equals([newLeftNode.identifier]);\n\t\t\texpect(rightTrait.length).equals(0);\n\n\t\t\tcheckout.closeEdit();\n\t\t\t// Again, call this prior to processing ops to accommodate PrefetchingCheckout\n\t\t\tawait checkout.waitForPendingUpdates();\n\t\t\tcontainerRuntimeFactory.processAllMessages();\n\t\t\tawait secondCheckout.waitForPendingUpdates();\n\t\t\texpect(tree.equals(secondTree)).to.be.true;\n\t\t});\n\n\t\tit('can handle a failed rebase of an ongoing local edit', async () => {\n\t\t\tconst { tree, containerRuntimeFactory } = setUpTestSharedTree({ localMode: false });\n\t\t\tconst simpleTestTree = setUpTestTree(tree);\n\t\t\tconst { tree: secondTree } = setUpTestSharedTree({ containerRuntimeFactory, ...secondTreeOptions });\n\n\t\t\t// Sync initial tree\n\t\t\tcontainerRuntimeFactory.processAllMessages();\n\n\t\t\tconst checkout = await checkoutFactory(tree);\n\t\t\tconst secondCheckout = await checkoutFactory(secondTree);\n\n\t\t\tcheckout.openEdit();\n\t\t\t// Move the left node to after the right node\n\t\t\tcheckout.applyChanges(\n\t\t\t\tChange.move(StableRange.only(simpleTestTree.left), StablePlace.after(simpleTestTree.right))\n\t\t\t);\n\n\t\t\t// Concurrently, the second client deletes the right node. This will conflict with the move operation by the first client.\n\t\t\tsecondCheckout.applyEdit(Change.delete(StableRange.only(simpleTestTree.right.translateId(secondTree))));\n\t\t\tawait secondCheckout.waitForPendingUpdates();\n\n\t\t\tcontainerRuntimeFactory.processAllMessages();\n\t\t\tawait checkout.waitForPendingUpdates();\n\t\t\tawait secondCheckout.waitForPendingUpdates();\n\n\t\t\t// Before rebasing, the first client should still see the right node and will have moved the left node after it.\n\t\t\tconst leftTrait = checkout.currentView.getTrait(simpleTestTree.left.traitLocation);\n\t\t\tconst rightTrait = checkout.currentView.getTrait(simpleTestTree.right.traitLocation);\n\t\t\texpect(leftTrait).deep.equals([]);\n\t\t\texpect(rightTrait).deep.equals([simpleTestTree.right.identifier, simpleTestTree.left.identifier]);\n\n\t\t\t// Merge in the latest changes.\n\t\t\tconst rebaseResult = checkout.rebaseCurrentEdit();\n\t\t\texpect(rebaseResult).equals(EditValidationResult.Invalid);\n\t\t\texpect(\n\t\t\t\tareRevisionViewsSemanticallyEqual(checkout.currentView, tree, secondCheckout.currentView, secondTree)\n\t\t\t).to.be.true;\n\t\t});\n\n\t\tit('can dispose and remove listeners', async () => {\n\t\t\tconst { checkout } = await setUpTestCheckout();\n\t\t\texpect(checkout.tree.listenerCount(SharedTreeEvent.EditCommitted)).to.equal(1);\n\t\t\tcheckout.dispose();\n\t\t\texpect(checkout.tree.listenerCount(SharedTreeEvent.EditCommitted)).to.equal(0);\n\t\t});\n\n\t\tadditionalTests?.();\n\t});\n}\n"]}
|
package/lib/test/Common.tests.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
import { expect } from 'chai';
|
|
6
|
-
import { filter, find, getOrCreate, identity, map, memoizeGetter, reduce } from '../Common';
|
|
6
|
+
import { filter, find, getOrCreate, identity, map, memoizeGetter, reduce, unwrapRestOrArray, } from '../Common';
|
|
7
7
|
describe('Common', () => {
|
|
8
8
|
it('function memoizeGetter() correctly memoizes', () => {
|
|
9
9
|
let x = 0;
|
|
@@ -79,5 +79,24 @@ describe('Common', () => {
|
|
|
79
79
|
const predicateNever = (n) => n < 0;
|
|
80
80
|
expect(find(inputs, predicateNever)).to.equal(inputs.find(predicateNever));
|
|
81
81
|
});
|
|
82
|
+
describe('unwrapRestOrArray', () => {
|
|
83
|
+
function testUnwrap(...params) {
|
|
84
|
+
return unwrapRestOrArray(params);
|
|
85
|
+
}
|
|
86
|
+
it('unwraps array arguments', () => {
|
|
87
|
+
const input = [0, 1, 2, 3];
|
|
88
|
+
const result = testUnwrap(input);
|
|
89
|
+
expect(result).to.equal(input);
|
|
90
|
+
});
|
|
91
|
+
it('does not unwrap rest arguments', () => {
|
|
92
|
+
const input = [0, 1, 2, 3];
|
|
93
|
+
const spreadResult = testUnwrap(...input);
|
|
94
|
+
const restResult = testUnwrap(0, 1, 2, 3);
|
|
95
|
+
expect(Array.isArray(spreadResult)).to.equal(true);
|
|
96
|
+
expect(Array.isArray(restResult)).to.equal(true);
|
|
97
|
+
expect(spreadResult.length).to.equal(input.length);
|
|
98
|
+
expect(restResult.length).to.equal(input.length);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
82
101
|
});
|
|
83
102
|
//# sourceMappingURL=Common.tests.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Common.tests.js","sourceRoot":"","sources":["../../src/test/Common.tests.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAC9B,OAAO,
|
|
1
|
+
{"version":3,"file":"Common.tests.js","sourceRoot":"","sources":["../../src/test/Common.tests.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 { expect } from 'chai';\nimport {\n\tfilter,\n\tfind,\n\tgetOrCreate,\n\tidentity,\n\tmap,\n\tmemoizeGetter,\n\treduce,\n\tRestOrArray,\n\tunwrapRestOrArray,\n} from '../Common';\n\ndescribe('Common', () => {\n\tit('function memoizeGetter() correctly memoizes', () => {\n\t\tlet x = 0;\n\t\tconst getAndInc = () => x++;\n\t\tconst obj = {\n\t\t\tget getUncached(): number {\n\t\t\t\treturn getAndInc();\n\t\t\t},\n\t\t\tget getCached(): number {\n\t\t\t\treturn memoizeGetter(this, 'getCached', getAndInc());\n\t\t\t},\n\t\t};\n\n\t\texpect(obj.getUncached).to.equal(0);\n\t\texpect(obj.getUncached).to.equal(1);\n\t\texpect(obj.getCached).to.equal(2);\n\t\texpect(obj.getCached).to.equal(2); // Cached, no increment\n\t});\n\n\tit('identity function returns its input', () => {\n\t\tconst inputs = [42, 'test', true];\n\t\tfor (const input of inputs) {\n\t\t\texpect(identity(input)).to.equal(input);\n\t\t}\n\t});\n\n\tdescribe('getOrCreate', () => {\n\t\tit('returns existing values', () => {\n\t\t\tconst map = new Map<number, string>();\n\t\t\tconst key = 42;\n\t\t\tconst value = 'test';\n\t\t\tmap.set(key, value);\n\t\t\texpect(\n\t\t\t\tgetOrCreate(map, key, () => expect.fail('should not call value creator for existing values'))\n\t\t\t).to.equal(value);\n\t\t});\n\n\t\tit('inserts new values', () => {\n\t\t\tconst map = new Map<number, string>();\n\t\t\tconst key = 42;\n\t\t\tconst value = 'test';\n\t\t\texpect(getOrCreate(map, key, () => value)).to.equal(value);\n\t\t\texpect(map.get(key)).to.equal(value);\n\t\t});\n\t});\n\n\tit('maps iterables correctly', () => {\n\t\tconst inputs = [0, 1, 2, 3];\n\t\tconst mapper = (n: number) => n * 2;\n\t\texpect([...map(inputs, mapper)]).to.deep.equal(inputs.map(mapper));\n\t});\n\n\tit('filters iterables correctly', () => {\n\t\tconst inputs = [0, 1, 2, 3];\n\t\tconst predicate = (n: number) => n < 2;\n\t\texpect([...filter(inputs, predicate)]).to.deep.equal(inputs.filter(predicate));\n\t});\n\n\tdescribe('reduces iterables', () => {\n\t\tconst reducer = (p: number, c: number) => p + c;\n\n\t\tit('that are empty', () => {\n\t\t\tconst inputs: number[] = [];\n\t\t\texpect(reduce(inputs, reducer)).to.be.undefined;\n\t\t});\n\n\t\tit('that have a single element', () => {\n\t\t\tconst inputs = [42];\n\t\t\texpect(reduce(inputs, reducer)).to.equal(inputs.reduce(reducer));\n\t\t});\n\n\t\tit('with no initial value', () => {\n\t\t\tconst inputs = [0, 1, 2, 3];\n\t\t\texpect(reduce(inputs, reducer)).to.equal(inputs.reduce(reducer));\n\t\t});\n\n\t\tit('with an initial value', () => {\n\t\t\tconst inputs = [0, 1, 2, 3];\n\t\t\texpect(reduce(inputs, reducer, 42)).to.equal(inputs.reduce(reducer, 42));\n\t\t});\n\t});\n\n\tit('finds elements in iterables', () => {\n\t\tconst inputs = [0, 1, 2, 3];\n\t\tconst predicateFind = (n: number) => n >= 2;\n\t\texpect(find(inputs, predicateFind)).to.equal(inputs.find(predicateFind));\n\t\tconst predicateNever = (n: number) => n < 0;\n\t\texpect(find(inputs, predicateNever)).to.equal(inputs.find(predicateNever));\n\t});\n\n\tdescribe('unwrapRestOrArray', () => {\n\t\tfunction testUnwrap(...params: RestOrArray<number>): readonly number[] {\n\t\t\treturn unwrapRestOrArray(params);\n\t\t}\n\t\tit('unwraps array arguments', () => {\n\t\t\tconst input = [0, 1, 2, 3];\n\t\t\tconst result = testUnwrap(input);\n\t\t\texpect(result).to.equal(input);\n\t\t});\n\t\tit('does not unwrap rest arguments', () => {\n\t\t\tconst input = [0, 1, 2, 3];\n\t\t\tconst spreadResult = testUnwrap(...input);\n\t\t\tconst restResult = testUnwrap(0, 1, 2, 3);\n\t\t\texpect(Array.isArray(spreadResult)).to.equal(true);\n\t\t\texpect(Array.isArray(restResult)).to.equal(true);\n\t\t\texpect(spreadResult.length).to.equal(input.length);\n\t\t\texpect(restResult.length).to.equal(input.length);\n\t\t});\n\t});\n});\n"]}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { expect } from 'chai';
|
|
6
6
|
import { revert } from '../HistoryEditFactory';
|
|
7
|
-
import { ChangeInternal,
|
|
7
|
+
import { ChangeInternal, StablePlaceInternal, StableRangeInternal } from '../persisted-types';
|
|
8
8
|
import { expectDefined } from './utilities/TestCommon';
|
|
9
9
|
import { refreshTestTree } from './utilities/TestUtilities';
|
|
10
10
|
describe('revert', () => {
|
|
@@ -15,10 +15,7 @@ describe('revert', () => {
|
|
|
15
15
|
const firstBuild = ChangeInternal.build([node], firstDetachedId);
|
|
16
16
|
const insertedNodeId = 1;
|
|
17
17
|
const insertedBuild = ChangeInternal.build([firstDetachedId], insertedNodeId);
|
|
18
|
-
const insertChange = ChangeInternal.insert(insertedNodeId,
|
|
19
|
-
referenceTrait: testTree.left.traitLocation,
|
|
20
|
-
side: Side.After,
|
|
21
|
-
});
|
|
18
|
+
const insertChange = ChangeInternal.insert(insertedNodeId, StablePlaceInternal.atStartOf(testTree.left.traitLocation));
|
|
22
19
|
const result = expectDefined(revert([firstBuild, insertedBuild, insertChange], testTree.view));
|
|
23
20
|
expect(result.length).to.equal(1);
|
|
24
21
|
const revertedChange = result[0];
|
|
@@ -34,16 +31,58 @@ describe('revert', () => {
|
|
|
34
31
|
const secondBuild = ChangeInternal.build([secondNode], secondDetachedId);
|
|
35
32
|
const insertedNodeId = 2;
|
|
36
33
|
const insertedBuild = ChangeInternal.build([firstDetachedId, secondDetachedId], insertedNodeId);
|
|
37
|
-
const insertChange = ChangeInternal.insert(insertedNodeId,
|
|
38
|
-
referenceTrait: testTree.left.traitLocation,
|
|
39
|
-
side: Side.After,
|
|
40
|
-
});
|
|
34
|
+
const insertChange = ChangeInternal.insert(insertedNodeId, StablePlaceInternal.atStartOf(testTree.left.traitLocation));
|
|
41
35
|
const result = expectDefined(revert([firstBuild, secondBuild, insertedBuild, insertChange], testTree.view));
|
|
42
36
|
expect(result.length).to.equal(1);
|
|
43
37
|
const revertedChange = result[0];
|
|
44
38
|
expect(revertedChange.source.start.referenceSibling).to.deep.equal(firstNode.identifier);
|
|
45
39
|
expect(revertedChange.source.end.referenceSibling).to.deep.equal(secondNode.identifier);
|
|
46
40
|
});
|
|
41
|
+
it('handles reverting the insert of empty nodes, with subsequent non-empty nodes', () => {
|
|
42
|
+
// build and insert of empty traits
|
|
43
|
+
const emptyTraitNodeId = 0;
|
|
44
|
+
const emptyTraitBuild = ChangeInternal.build([], emptyTraitNodeId);
|
|
45
|
+
const emptyTraitInsert = ChangeInternal.insert(emptyTraitNodeId, StablePlaceInternal.atStartOf(testTree.left.traitLocation));
|
|
46
|
+
// build and insert of non-empty traits
|
|
47
|
+
const firstDetachedId = 1;
|
|
48
|
+
const firstNode = testTree.buildLeafInternal();
|
|
49
|
+
const firstBuild = ChangeInternal.build([firstNode], firstDetachedId);
|
|
50
|
+
const insertedNodeId = 3;
|
|
51
|
+
const insertedBuild = ChangeInternal.build([firstDetachedId], insertedNodeId);
|
|
52
|
+
const insertChange = ChangeInternal.insert(insertedNodeId, StablePlaceInternal.atStartOf(testTree.left.traitLocation));
|
|
53
|
+
const result = expectDefined(revert([emptyTraitBuild, emptyTraitInsert, firstBuild, insertedBuild, insertChange], testTree.view));
|
|
54
|
+
expect(result.length).to.equal(1);
|
|
55
|
+
const revertedChange = result[0];
|
|
56
|
+
expect(revertedChange.source.start.referenceSibling).to.deep.equal(firstNode.identifier);
|
|
57
|
+
});
|
|
58
|
+
/** This is a regression test for a bug where we make sure that any built/detached nodes are cleared when any
|
|
59
|
+
* empty insert/detach change is skipped once encountered. The expected outcome is undefined, as during the second
|
|
60
|
+
* empty insert (with the same DetachSequenceId), there should be no such node in the builtNodes.
|
|
61
|
+
*/
|
|
62
|
+
it('handles reverting the insert of empty nodes, with subsequent empty nodes of same DetachedSequenceId', () => {
|
|
63
|
+
const emptyTraitNodeId = 0;
|
|
64
|
+
const emptyTraitBuild = ChangeInternal.build([], emptyTraitNodeId);
|
|
65
|
+
const emptyTraitInsert = ChangeInternal.insert(emptyTraitNodeId, StablePlaceInternal.atStartOf(testTree.left.traitLocation));
|
|
66
|
+
const result = revert([emptyTraitBuild, emptyTraitInsert, emptyTraitInsert], testTree.view);
|
|
67
|
+
expect(result).to.be.undefined;
|
|
68
|
+
});
|
|
69
|
+
it('handles reverting the detach of an empty trait', () => {
|
|
70
|
+
const insertedNodeId = 0;
|
|
71
|
+
const result = expectDefined(revert([
|
|
72
|
+
ChangeInternal.detach(StableRangeInternal.all({
|
|
73
|
+
label: 'someNonExistentTraitLabel',
|
|
74
|
+
parent: testTree.identifier,
|
|
75
|
+
}), insertedNodeId),
|
|
76
|
+
], testTree.view));
|
|
77
|
+
expect(result).to.have.lengthOf(0);
|
|
78
|
+
});
|
|
79
|
+
it('handles reverting the insert of an empty trait', () => {
|
|
80
|
+
const emptyTraitNodeId = 0;
|
|
81
|
+
const emptyTraitBuild = ChangeInternal.build([], emptyTraitNodeId);
|
|
82
|
+
const emptyTraitInsert = ChangeInternal.insert(emptyTraitNodeId, StablePlaceInternal.atStartOf(testTree.left.traitLocation));
|
|
83
|
+
const result = expectDefined(revert([emptyTraitBuild, emptyTraitInsert], testTree.view));
|
|
84
|
+
expect(result).to.have.lengthOf(0);
|
|
85
|
+
});
|
|
47
86
|
describe('returns undefined for reverts that require more context than the view directly before the edit', () => {
|
|
48
87
|
describe('because the edit conflicted', () => {
|
|
49
88
|
it('when reverting a detach of a node that is not in the tree', () => {
|