cojson 0.17.10 → 0.17.12
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +20 -0
- package/dist/coValueCore/SessionMap.d.ts +3 -2
- package/dist/coValueCore/SessionMap.d.ts.map +1 -1
- package/dist/coValueCore/SessionMap.js.map +1 -1
- package/dist/coValueCore/coValueCore.d.ts +9 -4
- package/dist/coValueCore/coValueCore.d.ts.map +1 -1
- package/dist/coValueCore/coValueCore.js +16 -8
- package/dist/coValueCore/coValueCore.js.map +1 -1
- package/dist/coValueCore/verifiedState.d.ts +2 -2
- package/dist/coValueCore/verifiedState.d.ts.map +1 -1
- package/dist/coValueCore/verifiedState.js +1 -1
- package/dist/coValueCore/verifiedState.js.map +1 -1
- package/dist/coValues/group.d.ts.map +1 -1
- package/dist/coValues/group.js +6 -2
- package/dist/coValues/group.js.map +1 -1
- package/dist/crypto/PureJSCrypto.d.ts +2 -2
- package/dist/crypto/PureJSCrypto.d.ts.map +1 -1
- package/dist/crypto/PureJSCrypto.js +3 -0
- package/dist/crypto/PureJSCrypto.js.map +1 -1
- package/dist/crypto/WasmCrypto.d.ts +1 -1
- package/dist/crypto/WasmCrypto.d.ts.map +1 -1
- package/dist/crypto/WasmCrypto.js.map +1 -1
- package/dist/crypto/crypto.d.ts +1 -1
- package/dist/crypto/crypto.d.ts.map +1 -1
- package/dist/localNode.js +1 -1
- package/dist/localNode.js.map +1 -1
- package/dist/permissions.d.ts +17 -1
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js.map +1 -1
- package/dist/queue/LocalTransactionsSyncQueue.d.ts +15 -0
- package/dist/queue/LocalTransactionsSyncQueue.d.ts.map +1 -1
- package/dist/queue/LocalTransactionsSyncQueue.js +25 -0
- package/dist/queue/LocalTransactionsSyncQueue.js.map +1 -1
- package/dist/sync.d.ts +8 -5
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +78 -66
- package/dist/sync.js.map +1 -1
- package/dist/tests/PureJSCrypto.test.js +15 -1
- package/dist/tests/PureJSCrypto.test.js.map +1 -1
- package/dist/tests/WasmCrypto.test.js +1 -1
- package/dist/tests/WasmCrypto.test.js.map +1 -1
- package/dist/tests/coValueCore.test.js +2 -2
- package/dist/tests/coValueCore.test.js.map +1 -1
- package/dist/tests/group.addMember.test.js +6 -11
- package/dist/tests/group.addMember.test.js.map +1 -1
- package/dist/tests/sync.known.test.d.ts +2 -0
- package/dist/tests/sync.known.test.d.ts.map +1 -0
- package/dist/tests/sync.known.test.js +78 -0
- package/dist/tests/sync.known.test.js.map +1 -0
- package/dist/tests/sync.load.test.js +40 -1
- package/dist/tests/sync.load.test.js.map +1 -1
- package/dist/tests/sync.sharding.test.d.ts +2 -0
- package/dist/tests/sync.sharding.test.d.ts.map +1 -0
- package/dist/tests/sync.sharding.test.js +51 -0
- package/dist/tests/sync.sharding.test.js.map +1 -0
- package/dist/tests/sync.test.js +30 -1
- package/dist/tests/sync.test.js.map +1 -1
- package/package.json +2 -2
- package/src/coValueCore/SessionMap.ts +4 -5
- package/src/coValueCore/coValueCore.ts +42 -32
- package/src/coValueCore/verifiedState.ts +1 -3
- package/src/coValues/group.ts +10 -2
- package/src/crypto/PureJSCrypto.ts +6 -2
- package/src/crypto/WasmCrypto.ts +1 -1
- package/src/crypto/crypto.ts +1 -1
- package/src/localNode.ts +1 -1
- package/src/permissions.ts +17 -1
- package/src/queue/LocalTransactionsSyncQueue.ts +32 -1
- package/src/sync.ts +103 -80
- package/src/tests/PureJSCrypto.test.ts +25 -2
- package/src/tests/WasmCrypto.test.ts +0 -2
- package/src/tests/coValueCore.test.ts +0 -4
- package/src/tests/group.addMember.test.ts +69 -63
- package/src/tests/sync.known.test.ts +109 -0
- package/src/tests/sync.load.test.ts +52 -0
- package/src/tests/sync.sharding.test.ts +76 -0
- package/src/tests/sync.test.ts +43 -2
|
@@ -2,7 +2,6 @@ import { beforeEach, describe, expect, test } from "vitest";
|
|
|
2
2
|
import { expectMap } from "../coValue.js";
|
|
3
3
|
import {
|
|
4
4
|
SyncMessagesLog,
|
|
5
|
-
TEST_NODE_CONFIG,
|
|
6
5
|
loadCoValueOrFail,
|
|
7
6
|
setupTestAccount,
|
|
8
7
|
setupTestNode,
|
|
@@ -220,68 +219,75 @@ describe("Group.addMember", () => {
|
|
|
220
219
|
expect(personOnReaderNode.get("name")).toEqual(undefined);
|
|
221
220
|
});
|
|
222
221
|
|
|
223
|
-
test("
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
)
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
222
|
+
test.each(["writer", "reader", "writeOnly"] as const)(
|
|
223
|
+
"an admin should not be able to downgrade an admin to %s",
|
|
224
|
+
async (targetRole) => {
|
|
225
|
+
const admin = await setupTestAccount({
|
|
226
|
+
connected: true,
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
const otherAdmin = await setupTestAccount({
|
|
230
|
+
connected: true,
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
const group = admin.node.createGroup();
|
|
234
|
+
const person = group.createMap({
|
|
235
|
+
name: "John Doe",
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
const otherAdminOnAdminNode = await loadCoValueOrFail(
|
|
239
|
+
admin.node,
|
|
240
|
+
otherAdmin.accountID,
|
|
241
|
+
);
|
|
242
|
+
group.addMember(otherAdminOnAdminNode, "admin");
|
|
243
|
+
|
|
244
|
+
// Try to downgrade other admin
|
|
245
|
+
expect(() => group.addMember(otherAdminOnAdminNode, targetRole)).toThrow(
|
|
246
|
+
"Administrators cannot demote other administrators in a group",
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
expect(group.roleOf(otherAdmin.accountID)).toEqual("admin");
|
|
250
|
+
|
|
251
|
+
// Verify other admin still has admin access by adding a new member
|
|
252
|
+
const reader = await setupTestAccount({
|
|
253
|
+
connected: true,
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
const readerOnOtherAdminNode = await loadCoValueOrFail(
|
|
257
|
+
otherAdmin.node,
|
|
258
|
+
reader.accountID,
|
|
259
|
+
);
|
|
260
|
+
group.addMember(readerOnOtherAdminNode, "reader");
|
|
261
|
+
|
|
262
|
+
const personOnReaderNode = await loadCoValueOrFail(
|
|
263
|
+
reader.node,
|
|
264
|
+
person.id,
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
await waitFor(() => {
|
|
268
|
+
expect(
|
|
269
|
+
expectMap(personOnReaderNode.core.getCurrentContent()).get("name"),
|
|
270
|
+
).toEqual("John Doe");
|
|
271
|
+
});
|
|
272
|
+
},
|
|
273
|
+
);
|
|
274
|
+
|
|
275
|
+
test.each(["writer", "reader", "writeOnly"] as const)(
|
|
276
|
+
"an admin should be able downgrade themselves to %s",
|
|
277
|
+
async (targetRole) => {
|
|
278
|
+
const admin = await setupTestAccount({
|
|
279
|
+
connected: true,
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
const group = admin.node.createGroup();
|
|
283
|
+
|
|
284
|
+
const account = await loadCoValueOrFail(admin.node, admin.accountID);
|
|
285
|
+
|
|
286
|
+
// Downgrade self to target role
|
|
287
|
+
group.addMember(account, targetRole);
|
|
288
|
+
expect(group.roleOf(admin.accountID)).toEqual(targetRole);
|
|
289
|
+
},
|
|
290
|
+
);
|
|
285
291
|
|
|
286
292
|
test("an admin should be able downgrade a writeOnly to reader", async () => {
|
|
287
293
|
const admin = await setupTestAccount({
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, test } from "vitest";
|
|
2
|
+
import { setCoValueLoadingRetryDelay } from "../config";
|
|
3
|
+
import {
|
|
4
|
+
SyncMessagesLog,
|
|
5
|
+
TEST_NODE_CONFIG,
|
|
6
|
+
blockMessageTypeOnOutgoingPeer,
|
|
7
|
+
getSyncServerConnectedPeer,
|
|
8
|
+
loadCoValueOrFail,
|
|
9
|
+
setupTestAccount,
|
|
10
|
+
setupTestNode,
|
|
11
|
+
} from "./testUtils";
|
|
12
|
+
|
|
13
|
+
let jazzCloud: ReturnType<typeof setupTestNode>;
|
|
14
|
+
|
|
15
|
+
// Set a short timeout to make the tests on unavailable complete faster
|
|
16
|
+
setCoValueLoadingRetryDelay(100);
|
|
17
|
+
|
|
18
|
+
beforeEach(async () => {
|
|
19
|
+
// We want to simulate a real world communication that happens asynchronously
|
|
20
|
+
TEST_NODE_CONFIG.withAsyncPeers = true;
|
|
21
|
+
|
|
22
|
+
SyncMessagesLog.clear();
|
|
23
|
+
jazzCloud = setupTestNode({ isSyncServer: true });
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe("sending known coValues", () => {
|
|
27
|
+
test("dependencies are included when responding to a client", async () => {
|
|
28
|
+
const group = jazzCloud.node.createGroup();
|
|
29
|
+
const map = group.createMap();
|
|
30
|
+
map.set("hello", "world", "trusting");
|
|
31
|
+
|
|
32
|
+
const { node: client } = setupTestNode({
|
|
33
|
+
connected: true,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
map.set("hello2", "world2", "trusting");
|
|
37
|
+
await map.core.waitForSync();
|
|
38
|
+
|
|
39
|
+
const mapOnClient = await loadCoValueOrFail(client, map.id);
|
|
40
|
+
expect(mapOnClient.get("hello")).toEqual("world");
|
|
41
|
+
expect(mapOnClient.get("hello2")).toEqual("world2");
|
|
42
|
+
|
|
43
|
+
expect(
|
|
44
|
+
SyncMessagesLog.getMessages({
|
|
45
|
+
Group: group.core,
|
|
46
|
+
Map: map.core,
|
|
47
|
+
}),
|
|
48
|
+
).toMatchInlineSnapshot(`
|
|
49
|
+
[
|
|
50
|
+
"client -> server | LOAD Map sessions: empty",
|
|
51
|
+
"server -> client | CONTENT Group header: true new: After: 0 New: 3",
|
|
52
|
+
"server -> client | CONTENT Map header: true new: After: 0 New: 2",
|
|
53
|
+
"client -> server | KNOWN Group sessions: header/3",
|
|
54
|
+
"client -> server | KNOWN Map sessions: header/2",
|
|
55
|
+
]
|
|
56
|
+
`);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test("dependencies are excluded when responding to a server", async () => {
|
|
60
|
+
// Create a disconnected client
|
|
61
|
+
const { node: client, accountID } = await setupTestAccount({
|
|
62
|
+
connected: false,
|
|
63
|
+
});
|
|
64
|
+
const account = client.expectCurrentAccount(accountID);
|
|
65
|
+
|
|
66
|
+
// Prepare a group -- this will be a non-account dependency of a forthcoming map.
|
|
67
|
+
const group = client.createGroup();
|
|
68
|
+
group.addMember("everyone", "writer");
|
|
69
|
+
|
|
70
|
+
// Let the queue drain
|
|
71
|
+
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
72
|
+
|
|
73
|
+
// Disable transaction verification on the server so it doesn't ask for dependencies.
|
|
74
|
+
jazzCloud.node.syncManager.disableTransactionVerification();
|
|
75
|
+
|
|
76
|
+
// Connect the client, but don't setup syncing just yet...
|
|
77
|
+
const { peer } = getSyncServerConnectedPeer({
|
|
78
|
+
peerId: client.getCurrentAgent().id,
|
|
79
|
+
syncServer: jazzCloud.node,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Disable reconciliation while we setup syncing because we don't want the
|
|
83
|
+
// server to know about our forthcoming map's dependencies (group + account).
|
|
84
|
+
const blocker = blockMessageTypeOnOutgoingPeer(peer, "load", {});
|
|
85
|
+
client.syncManager.addPeer(peer);
|
|
86
|
+
blocker.unblock();
|
|
87
|
+
|
|
88
|
+
// Create a map and set a value on it, this will trigger:
|
|
89
|
+
// - CONTENT from client to server
|
|
90
|
+
// - KNOWN from server to client
|
|
91
|
+
//
|
|
92
|
+
// We don't expect any more messages to be sent from client to server in this
|
|
93
|
+
// case because clients shouldn't greedily send dependencies to a server.
|
|
94
|
+
const map = group.createMap();
|
|
95
|
+
await map.core.waitForSync();
|
|
96
|
+
|
|
97
|
+
const syncMessages = SyncMessagesLog.getMessages({
|
|
98
|
+
Account: account.core,
|
|
99
|
+
Group: group.core,
|
|
100
|
+
Map: map.core,
|
|
101
|
+
});
|
|
102
|
+
expect(
|
|
103
|
+
syncMessages.some(
|
|
104
|
+
(msg) =>
|
|
105
|
+
msg.includes("CONTENT Account") || msg.includes("CONTENT Group"),
|
|
106
|
+
),
|
|
107
|
+
).toBe(false);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
SyncMessagesLog,
|
|
10
10
|
TEST_NODE_CONFIG,
|
|
11
11
|
blockMessageTypeOnOutgoingPeer,
|
|
12
|
+
getSyncServerConnectedPeer,
|
|
12
13
|
loadCoValueOrFail,
|
|
13
14
|
setupTestAccount,
|
|
14
15
|
setupTestNode,
|
|
@@ -1034,4 +1035,55 @@ describe("loading coValues from server", () => {
|
|
|
1034
1035
|
|
|
1035
1036
|
vi.useRealTimers();
|
|
1036
1037
|
});
|
|
1038
|
+
|
|
1039
|
+
test("should not request dependencies if transaction verification is disabled", async () => {
|
|
1040
|
+
// Create a disconnected client
|
|
1041
|
+
const { node: client, accountID } = await setupTestAccount({
|
|
1042
|
+
connected: false,
|
|
1043
|
+
});
|
|
1044
|
+
const account = client.expectCurrentAccount(accountID);
|
|
1045
|
+
|
|
1046
|
+
// Prepare a group -- this will be a non-account dependency of a forthcoming map.
|
|
1047
|
+
const group = client.createGroup();
|
|
1048
|
+
group.addMember("everyone", "writer");
|
|
1049
|
+
|
|
1050
|
+
// Create a sync server and disable transaction verification
|
|
1051
|
+
const syncServer = await setupTestAccount({ isSyncServer: true });
|
|
1052
|
+
syncServer.node.syncManager.disableTransactionVerification();
|
|
1053
|
+
|
|
1054
|
+
// Connect the client, but don't setup syncing just yet...
|
|
1055
|
+
const { peer } = getSyncServerConnectedPeer({
|
|
1056
|
+
peerId: client.getCurrentAgent().id,
|
|
1057
|
+
syncServer: syncServer.node,
|
|
1058
|
+
});
|
|
1059
|
+
|
|
1060
|
+
// Disable reconciliation while we setup syncing because we don't want the
|
|
1061
|
+
// server to know about our forthcoming map's dependencies (group + account).
|
|
1062
|
+
const blocker = blockMessageTypeOnOutgoingPeer(peer, "load", {});
|
|
1063
|
+
client.syncManager.addPeer(peer);
|
|
1064
|
+
blocker.unblock();
|
|
1065
|
+
|
|
1066
|
+
// Create a map and set a value on it.
|
|
1067
|
+
// If transaction verification were enabled, this would trigger LOAD messages
|
|
1068
|
+
// from the server to the client asking for the group and account. However, we
|
|
1069
|
+
// don't expect to see those messages since we disabled transaction verification.
|
|
1070
|
+
const map = group.createMap();
|
|
1071
|
+
map.set("hello", "world");
|
|
1072
|
+
await map.core.waitForSync();
|
|
1073
|
+
|
|
1074
|
+
const syncMessages = SyncMessagesLog.getMessages({
|
|
1075
|
+
Account: account.core,
|
|
1076
|
+
Group: group.core,
|
|
1077
|
+
Map: map.core,
|
|
1078
|
+
});
|
|
1079
|
+
expect(
|
|
1080
|
+
syncMessages.some(
|
|
1081
|
+
(msg) => msg.includes("LOAD Account") || msg.includes("LOAD Group"),
|
|
1082
|
+
),
|
|
1083
|
+
).toBe(false);
|
|
1084
|
+
|
|
1085
|
+
// Verify the map is available on the server (transaction was accepted)
|
|
1086
|
+
const mapOnServerCore = await syncServer.node.loadCoValueCore(map.core.id);
|
|
1087
|
+
expect(mapOnServerCore.isAvailable()).toBe(true);
|
|
1088
|
+
});
|
|
1037
1089
|
});
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, test } from "vitest";
|
|
2
|
+
import { setCoValueLoadingRetryDelay } from "../config";
|
|
3
|
+
import {
|
|
4
|
+
SyncMessagesLog,
|
|
5
|
+
TEST_NODE_CONFIG,
|
|
6
|
+
blockMessageTypeOnOutgoingPeer,
|
|
7
|
+
getSyncServerConnectedPeer,
|
|
8
|
+
loadCoValueOrFail,
|
|
9
|
+
setupTestAccount,
|
|
10
|
+
setupTestNode,
|
|
11
|
+
} from "./testUtils";
|
|
12
|
+
import { Peer } from "../exports";
|
|
13
|
+
import { ServerPeerSelector } from "../sync";
|
|
14
|
+
|
|
15
|
+
beforeEach(async () => {
|
|
16
|
+
// We want to simulate a real world communication that happens asynchronously
|
|
17
|
+
TEST_NODE_CONFIG.withAsyncPeers = true;
|
|
18
|
+
|
|
19
|
+
SyncMessagesLog.clear();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe("sharding", () => {
|
|
23
|
+
test("server peers are not filtered by default", async () => {
|
|
24
|
+
const { node: client } = setupTestNode({
|
|
25
|
+
connected: false,
|
|
26
|
+
});
|
|
27
|
+
const group = client.createGroup();
|
|
28
|
+
|
|
29
|
+
const allPeers: Peer[] = [];
|
|
30
|
+
for (let i = 0; i < 5; i++) {
|
|
31
|
+
const syncServer = await setupTestAccount({ isSyncServer: true });
|
|
32
|
+
|
|
33
|
+
const { peer } = getSyncServerConnectedPeer({
|
|
34
|
+
peerId: client.getCurrentAgent().id,
|
|
35
|
+
syncServer: syncServer.node,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
client.syncManager.addPeer(peer);
|
|
39
|
+
allPeers.push(peer);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const serverPeers = client.syncManager.getServerPeers(group.id);
|
|
43
|
+
expect(serverPeers.map((p) => p.id)).toEqual(allPeers.map((p) => p.id));
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("server peers are filtered when a serverPeerSelector is set", async () => {
|
|
47
|
+
const firstAlphabetical: ServerPeerSelector = (id, serverPeers) => {
|
|
48
|
+
return serverPeers.sort((a, b) => a.id.localeCompare(b.id)).slice(0, 1);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const { node: client } = setupTestNode({
|
|
52
|
+
connected: false,
|
|
53
|
+
});
|
|
54
|
+
client.syncManager.serverPeerSelector = firstAlphabetical;
|
|
55
|
+
const group = client.createGroup();
|
|
56
|
+
|
|
57
|
+
const allPeers: Peer[] = [];
|
|
58
|
+
for (let i = 0; i < 5; i++) {
|
|
59
|
+
const syncServer = await setupTestAccount({ isSyncServer: true });
|
|
60
|
+
|
|
61
|
+
const { peer } = getSyncServerConnectedPeer({
|
|
62
|
+
peerId: client.getCurrentAgent().id,
|
|
63
|
+
syncServer: syncServer.node,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
client.syncManager.addPeer(peer);
|
|
67
|
+
allPeers.push(peer);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const serverPeers = client.syncManager.getServerPeers(group.id);
|
|
71
|
+
expect(serverPeers.length).toBe(1);
|
|
72
|
+
expect(serverPeers[0]!.id).toEqual(
|
|
73
|
+
allPeers.sort((a, b) => a.id.localeCompare(b.id))[0]!.id,
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
});
|
package/src/tests/sync.test.ts
CHANGED
|
@@ -180,9 +180,7 @@ test("should not verify transactions when SyncManager has verification disabled"
|
|
|
180
180
|
madeAt: Date.now(),
|
|
181
181
|
},
|
|
182
182
|
],
|
|
183
|
-
undefined,
|
|
184
183
|
Crypto.sign(agent.currentSignerSecret(), "hash_z12345678"),
|
|
185
|
-
"immediate",
|
|
186
184
|
true,
|
|
187
185
|
);
|
|
188
186
|
|
|
@@ -1117,3 +1115,46 @@ describe("SyncManager.handleSyncMessage", () => {
|
|
|
1117
1115
|
expect(peerState.knownStates.has(group.id)).toBe(true);
|
|
1118
1116
|
});
|
|
1119
1117
|
});
|
|
1118
|
+
|
|
1119
|
+
describe("SyncManager.trackDirtyCoValues", () => {
|
|
1120
|
+
test("should track the dirty coValues", async () => {
|
|
1121
|
+
const node = createTestNode();
|
|
1122
|
+
|
|
1123
|
+
const tracking = node.syncManager.trackDirtyCoValues();
|
|
1124
|
+
|
|
1125
|
+
const group = node.createGroup();
|
|
1126
|
+
const map = group.createMap();
|
|
1127
|
+
map.set("key1", "value1", "trusting");
|
|
1128
|
+
|
|
1129
|
+
const trackedValues = tracking.done();
|
|
1130
|
+
expect(trackedValues.size).toBe(2);
|
|
1131
|
+
expect(trackedValues.has(map.id)).toBe(true);
|
|
1132
|
+
expect(trackedValues.has(group.id)).toBe(true);
|
|
1133
|
+
});
|
|
1134
|
+
|
|
1135
|
+
test("should track the dirty coValues only when active", async () => {
|
|
1136
|
+
const node = createTestNode();
|
|
1137
|
+
|
|
1138
|
+
const group = node.createGroup();
|
|
1139
|
+
|
|
1140
|
+
const tracking1 = node.syncManager.trackDirtyCoValues();
|
|
1141
|
+
|
|
1142
|
+
const map1 = group.createMap();
|
|
1143
|
+
map1.set("key1", "value1", "trusting");
|
|
1144
|
+
|
|
1145
|
+
const tracking2 = node.syncManager.trackDirtyCoValues();
|
|
1146
|
+
|
|
1147
|
+
const map2 = group.createMap();
|
|
1148
|
+
map2.set("key2", "value2", "trusting");
|
|
1149
|
+
|
|
1150
|
+
const tracked1 = tracking1.done();
|
|
1151
|
+
|
|
1152
|
+
const map3 = group.createMap();
|
|
1153
|
+
map3.set("key3", "value3", "trusting");
|
|
1154
|
+
|
|
1155
|
+
const tracked2 = tracking2.done();
|
|
1156
|
+
|
|
1157
|
+
expect(Array.from(tracked1)).toEqual([map1.id, map2.id]);
|
|
1158
|
+
expect(Array.from(tracked2)).toEqual([map2.id, map3.id]);
|
|
1159
|
+
});
|
|
1160
|
+
});
|