cojson 0.13.25 → 0.13.28
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 +12 -0
- package/dist/coValueCore/coValueCore.d.ts +4 -3
- package/dist/coValueCore/coValueCore.d.ts.map +1 -1
- package/dist/coValueCore/coValueCore.js +82 -66
- package/dist/coValueCore/coValueCore.js.map +1 -1
- package/dist/coValues/group.d.ts.map +1 -1
- package/dist/coValues/group.js +3 -1
- package/dist/coValues/group.js.map +1 -1
- package/dist/localNode.d.ts +1 -0
- package/dist/localNode.d.ts.map +1 -1
- package/dist/localNode.js +5 -2
- package/dist/localNode.js.map +1 -1
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +3 -1
- package/dist/permissions.js.map +1 -1
- package/dist/sync.d.ts +6 -6
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +100 -66
- package/dist/sync.js.map +1 -1
- package/dist/tests/SyncStateManager.test.js +1 -1
- package/dist/tests/SyncStateManager.test.js.map +1 -1
- package/dist/tests/group.removeMember.test.d.ts +2 -0
- package/dist/tests/group.removeMember.test.d.ts.map +1 -0
- package/dist/tests/group.removeMember.test.js +133 -0
- package/dist/tests/group.removeMember.test.js.map +1 -0
- package/dist/tests/sync.mesh.test.js +47 -3
- package/dist/tests/sync.mesh.test.js.map +1 -1
- package/dist/tests/sync.peerReconciliation.test.js +71 -2
- package/dist/tests/sync.peerReconciliation.test.js.map +1 -1
- package/dist/tests/testUtils.d.ts.map +1 -1
- package/dist/tests/testUtils.js +1 -0
- package/dist/tests/testUtils.js.map +1 -1
- package/package.json +1 -1
- package/src/coValueCore/coValueCore.ts +111 -80
- package/src/coValues/group.ts +4 -1
- package/src/localNode.ts +6 -2
- package/src/permissions.ts +6 -1
- package/src/sync.ts +117 -71
- package/src/tests/SyncStateManager.test.ts +1 -1
- package/src/tests/group.removeMember.test.ts +255 -0
- package/src/tests/sync.mesh.test.ts +60 -2
- package/src/tests/sync.peerReconciliation.test.ts +90 -2
- package/src/tests/testUtils.ts +1 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, test } from "vitest";
|
|
2
|
+
import { RawCoList } from "../coValues/coList.js";
|
|
3
|
+
import { RawCoMap } from "../coValues/coMap.js";
|
|
4
|
+
import { RawCoStream } from "../coValues/coStream.js";
|
|
5
|
+
import { RawBinaryCoStream } from "../coValues/coStream.js";
|
|
6
|
+
import { WasmCrypto } from "../crypto/WasmCrypto.js";
|
|
7
|
+
import { RawAccountID } from "../exports.js";
|
|
8
|
+
import {
|
|
9
|
+
SyncMessagesLog,
|
|
10
|
+
createTwoConnectedNodes,
|
|
11
|
+
loadCoValueOrFail,
|
|
12
|
+
setupTestAccount,
|
|
13
|
+
setupTestNode,
|
|
14
|
+
} from "./testUtils.js";
|
|
15
|
+
|
|
16
|
+
let jazzCloud = setupTestNode({ isSyncServer: true });
|
|
17
|
+
|
|
18
|
+
beforeEach(async () => {
|
|
19
|
+
SyncMessagesLog.clear();
|
|
20
|
+
jazzCloud = setupTestNode({ isSyncServer: true });
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe("Group.removeMember", () => {
|
|
24
|
+
test("a reader member should be able to revoke themselves", async () => {
|
|
25
|
+
const admin = await setupTestAccount({
|
|
26
|
+
connected: true,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const reader = await setupTestAccount({
|
|
30
|
+
connected: true,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const group = admin.node.createGroup();
|
|
34
|
+
const readerOnAdminNode = await loadCoValueOrFail(
|
|
35
|
+
admin.node,
|
|
36
|
+
reader.accountID,
|
|
37
|
+
);
|
|
38
|
+
group.addMember(readerOnAdminNode, "reader");
|
|
39
|
+
|
|
40
|
+
const groupOnReaderNode = await loadCoValueOrFail(reader.node, group.id);
|
|
41
|
+
expect(groupOnReaderNode.myRole()).toEqual("reader");
|
|
42
|
+
|
|
43
|
+
await groupOnReaderNode.removeMember(
|
|
44
|
+
reader.node.expectCurrentAccount("reader"),
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
expect(groupOnReaderNode.myRole()).toEqual(undefined);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("a writer member should be able to revoke themselves", async () => {
|
|
51
|
+
const admin = await setupTestAccount({
|
|
52
|
+
connected: true,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const writer = await setupTestAccount({
|
|
56
|
+
connected: true,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const group = admin.node.createGroup();
|
|
60
|
+
const writerOnAdminNode = await loadCoValueOrFail(
|
|
61
|
+
admin.node,
|
|
62
|
+
writer.accountID,
|
|
63
|
+
);
|
|
64
|
+
group.addMember(writerOnAdminNode, "writer");
|
|
65
|
+
|
|
66
|
+
const groupOnWriterNode = await loadCoValueOrFail(writer.node, group.id);
|
|
67
|
+
expect(groupOnWriterNode.myRole()).toEqual("writer");
|
|
68
|
+
|
|
69
|
+
await groupOnWriterNode.removeMember(
|
|
70
|
+
writer.node.expectCurrentAccount("writer"),
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
expect(groupOnWriterNode.myRole()).toEqual(undefined);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("a writeOnly member should be able to revoke themselves", async () => {
|
|
77
|
+
const admin = await setupTestAccount({
|
|
78
|
+
connected: true,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const writeOnly = await setupTestAccount({
|
|
82
|
+
connected: true,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const group = admin.node.createGroup();
|
|
86
|
+
const writeOnlyOnAdminNode = await loadCoValueOrFail(
|
|
87
|
+
admin.node,
|
|
88
|
+
writeOnly.accountID,
|
|
89
|
+
);
|
|
90
|
+
group.addMember(writeOnlyOnAdminNode, "writeOnly");
|
|
91
|
+
|
|
92
|
+
const groupOnWriteOnlyNode = await loadCoValueOrFail(
|
|
93
|
+
writeOnly.node,
|
|
94
|
+
group.id,
|
|
95
|
+
);
|
|
96
|
+
expect(groupOnWriteOnlyNode.myRole()).toEqual("writeOnly");
|
|
97
|
+
|
|
98
|
+
await groupOnWriteOnlyNode.removeMember(
|
|
99
|
+
writeOnly.node.expectCurrentAccount("writeOnly"),
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
expect(groupOnWriteOnlyNode.myRole()).toEqual(undefined);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test("an admin member should be able to revoke themselves", async () => {
|
|
106
|
+
const admin = await setupTestAccount({
|
|
107
|
+
connected: true,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const otherAdmin = await setupTestAccount({
|
|
111
|
+
connected: true,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const group = admin.node.createGroup();
|
|
115
|
+
const otherAdminOnAdminNode = await loadCoValueOrFail(
|
|
116
|
+
admin.node,
|
|
117
|
+
otherAdmin.accountID,
|
|
118
|
+
);
|
|
119
|
+
group.addMember(otherAdminOnAdminNode, "admin");
|
|
120
|
+
|
|
121
|
+
const groupOnOtherAdminNode = await loadCoValueOrFail(
|
|
122
|
+
otherAdmin.node,
|
|
123
|
+
group.id,
|
|
124
|
+
);
|
|
125
|
+
expect(groupOnOtherAdminNode.myRole()).toEqual("admin");
|
|
126
|
+
|
|
127
|
+
await groupOnOtherAdminNode.removeMember(
|
|
128
|
+
otherAdmin.node.expectCurrentAccount("admin"),
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
expect(groupOnOtherAdminNode.myRole()).toEqual(undefined);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test("a writer member cannot remove other accounts", async () => {
|
|
135
|
+
const admin = await setupTestAccount({
|
|
136
|
+
connected: true,
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
const writer = await setupTestAccount({
|
|
140
|
+
connected: true,
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
const otherMember = await setupTestAccount({
|
|
144
|
+
connected: true,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
const group = admin.node.createGroup();
|
|
148
|
+
const writerOnAdminNode = await loadCoValueOrFail(
|
|
149
|
+
admin.node,
|
|
150
|
+
writer.accountID,
|
|
151
|
+
);
|
|
152
|
+
const otherMemberOnAdminNode = await loadCoValueOrFail(
|
|
153
|
+
admin.node,
|
|
154
|
+
otherMember.accountID,
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
group.addMember(writerOnAdminNode, "writer");
|
|
158
|
+
group.addMember(otherMemberOnAdminNode, "reader");
|
|
159
|
+
|
|
160
|
+
const groupOnWriterNode = await loadCoValueOrFail(writer.node, group.id);
|
|
161
|
+
expect(groupOnWriterNode.myRole()).toEqual("writer");
|
|
162
|
+
|
|
163
|
+
const otherMemberOnWriterNode = await loadCoValueOrFail(
|
|
164
|
+
writer.node,
|
|
165
|
+
otherMember.accountID,
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
await groupOnWriterNode.removeMember(otherMemberOnWriterNode);
|
|
169
|
+
|
|
170
|
+
expect(groupOnWriterNode.roleOf(otherMember.accountID)).toEqual("reader");
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
test("a writeOnly member cannot remove other accounts", async () => {
|
|
174
|
+
const admin = await setupTestAccount({
|
|
175
|
+
connected: true,
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
const writeOnly = await setupTestAccount({
|
|
179
|
+
connected: true,
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
const otherMember = await setupTestAccount({
|
|
183
|
+
connected: true,
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
const group = admin.node.createGroup();
|
|
187
|
+
const writeOnlyOnAdminNode = await loadCoValueOrFail(
|
|
188
|
+
admin.node,
|
|
189
|
+
writeOnly.accountID,
|
|
190
|
+
);
|
|
191
|
+
const otherMemberOnAdminNode = await loadCoValueOrFail(
|
|
192
|
+
admin.node,
|
|
193
|
+
otherMember.accountID,
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
group.addMember(writeOnlyOnAdminNode, "writeOnly");
|
|
197
|
+
group.addMember(otherMemberOnAdminNode, "reader");
|
|
198
|
+
|
|
199
|
+
const groupOnWriteOnlyNode = await loadCoValueOrFail(
|
|
200
|
+
writeOnly.node,
|
|
201
|
+
group.id,
|
|
202
|
+
);
|
|
203
|
+
expect(groupOnWriteOnlyNode.myRole()).toEqual("writeOnly");
|
|
204
|
+
|
|
205
|
+
const otherMemberOnWriteOnlyNode = await loadCoValueOrFail(
|
|
206
|
+
writeOnly.node,
|
|
207
|
+
otherMember.accountID,
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
await groupOnWriteOnlyNode.removeMember(otherMemberOnWriteOnlyNode);
|
|
211
|
+
|
|
212
|
+
expect(groupOnWriteOnlyNode.roleOf(otherMember.accountID)).toEqual(
|
|
213
|
+
"reader",
|
|
214
|
+
);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
test("a reader member cannot remove other accounts", async () => {
|
|
218
|
+
const admin = await setupTestAccount({
|
|
219
|
+
connected: true,
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
const reader = await setupTestAccount({
|
|
223
|
+
connected: true,
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
const otherMember = await setupTestAccount({
|
|
227
|
+
connected: true,
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
const group = admin.node.createGroup();
|
|
231
|
+
const readerOnAdminNode = await loadCoValueOrFail(
|
|
232
|
+
admin.node,
|
|
233
|
+
reader.accountID,
|
|
234
|
+
);
|
|
235
|
+
const otherMemberOnAdminNode = await loadCoValueOrFail(
|
|
236
|
+
admin.node,
|
|
237
|
+
otherMember.accountID,
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
group.addMember(readerOnAdminNode, "reader");
|
|
241
|
+
group.addMember(otherMemberOnAdminNode, "writer");
|
|
242
|
+
|
|
243
|
+
const groupOnReaderNode = await loadCoValueOrFail(reader.node, group.id);
|
|
244
|
+
expect(groupOnReaderNode.myRole()).toEqual("reader");
|
|
245
|
+
|
|
246
|
+
const otherMemberOnReaderNode = await loadCoValueOrFail(
|
|
247
|
+
reader.node,
|
|
248
|
+
otherMember.accountID,
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
await groupOnReaderNode.removeMember(otherMemberOnReaderNode);
|
|
252
|
+
|
|
253
|
+
expect(groupOnReaderNode.roleOf(otherMember.accountID)).toEqual("writer");
|
|
254
|
+
});
|
|
255
|
+
});
|
|
@@ -4,6 +4,7 @@ import { expectMap } from "../coValue";
|
|
|
4
4
|
import {
|
|
5
5
|
SyncMessagesLog,
|
|
6
6
|
blockMessageTypeOnOutgoingPeer,
|
|
7
|
+
connectedPeersWithMessagesTracking,
|
|
7
8
|
loadCoValueOrFail,
|
|
8
9
|
setupTestNode,
|
|
9
10
|
waitFor,
|
|
@@ -76,8 +77,8 @@ describe("multiple clients syncing with the a cloud-like server mesh", () => {
|
|
|
76
77
|
"core -> storage | CONTENT Group header: true new: After: 0 New: 3",
|
|
77
78
|
"storage -> core | KNOWN Group sessions: header/3",
|
|
78
79
|
"core -> storage | CONTENT Map header: true new: After: 0 New: 1",
|
|
79
|
-
"storage -> core | KNOWN Map sessions: header/1",
|
|
80
80
|
"client -> edge-italy | LOAD Map sessions: empty",
|
|
81
|
+
"storage -> core | KNOWN Map sessions: header/1",
|
|
81
82
|
"edge-italy -> core | LOAD Map sessions: empty",
|
|
82
83
|
"core -> edge-italy | CONTENT Group header: true new: After: 0 New: 3",
|
|
83
84
|
"edge-italy -> core | KNOWN Group sessions: header/3",
|
|
@@ -138,8 +139,8 @@ describe("multiple clients syncing with the a cloud-like server mesh", () => {
|
|
|
138
139
|
"core -> storage | CONTENT Group header: true new: After: 0 New: 5",
|
|
139
140
|
"storage -> core | KNOWN Group sessions: header/5",
|
|
140
141
|
"core -> storage | CONTENT Map header: true new: After: 0 New: 1",
|
|
141
|
-
"storage -> core | KNOWN Map sessions: header/1",
|
|
142
142
|
"client -> edge-italy | LOAD Map sessions: empty",
|
|
143
|
+
"storage -> core | KNOWN Map sessions: header/1",
|
|
143
144
|
"edge-italy -> core | LOAD Map sessions: empty",
|
|
144
145
|
"core -> edge-italy | CONTENT ParentGroup header: true new: After: 0 New: 6",
|
|
145
146
|
"edge-italy -> core | KNOWN ParentGroup sessions: header/6",
|
|
@@ -355,6 +356,7 @@ describe("multiple clients syncing with the a cloud-like server mesh", () => {
|
|
|
355
356
|
syncServer: storage.node,
|
|
356
357
|
});
|
|
357
358
|
|
|
359
|
+
storagePeer.role = "storage";
|
|
358
360
|
storagePeer.priority = 100;
|
|
359
361
|
|
|
360
362
|
const group = coreServer.node.createGroup();
|
|
@@ -402,4 +404,60 @@ describe("multiple clients syncing with the a cloud-like server mesh", () => {
|
|
|
402
404
|
|
|
403
405
|
expect(mapOnClient.get("hello")).toEqual("world");
|
|
404
406
|
});
|
|
407
|
+
|
|
408
|
+
test("a stuck server peer should not block the load from other server peers", async () => {
|
|
409
|
+
const client = setupTestNode();
|
|
410
|
+
const coreServer = setupTestNode({
|
|
411
|
+
isSyncServer: true,
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
const anotherServer = setupTestNode({});
|
|
415
|
+
|
|
416
|
+
const { peer: peerToCoreServer } = client.connectToSyncServer({
|
|
417
|
+
syncServerName: "core",
|
|
418
|
+
syncServer: coreServer.node,
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
const { peer1, peer2 } = connectedPeersWithMessagesTracking({
|
|
422
|
+
peer1: {
|
|
423
|
+
id: anotherServer.node.getCurrentAgent().id,
|
|
424
|
+
role: "server",
|
|
425
|
+
name: "another-server",
|
|
426
|
+
},
|
|
427
|
+
peer2: {
|
|
428
|
+
id: client.node.getCurrentAgent().id,
|
|
429
|
+
role: "client",
|
|
430
|
+
name: "client",
|
|
431
|
+
},
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
blockMessageTypeOnOutgoingPeer(peerToCoreServer, "load");
|
|
435
|
+
|
|
436
|
+
client.node.syncManager.addPeer(peer1);
|
|
437
|
+
anotherServer.node.syncManager.addPeer(peer2);
|
|
438
|
+
|
|
439
|
+
const group = anotherServer.node.createGroup();
|
|
440
|
+
const map = group.createMap();
|
|
441
|
+
|
|
442
|
+
map.set("hello", "world", "trusting");
|
|
443
|
+
|
|
444
|
+
const mapOnClient = await loadCoValueOrFail(client.node, map.id);
|
|
445
|
+
|
|
446
|
+
expect(
|
|
447
|
+
SyncMessagesLog.getMessages({
|
|
448
|
+
Group: group.core,
|
|
449
|
+
Map: map.core,
|
|
450
|
+
}),
|
|
451
|
+
).toMatchInlineSnapshot(`
|
|
452
|
+
[
|
|
453
|
+
"client -> another-server | LOAD Map sessions: empty",
|
|
454
|
+
"another-server -> client | CONTENT Group header: true new: After: 0 New: 3",
|
|
455
|
+
"client -> another-server | KNOWN Group sessions: header/3",
|
|
456
|
+
"another-server -> client | CONTENT Map header: true new: After: 0 New: 1",
|
|
457
|
+
"client -> another-server | KNOWN Map sessions: header/1",
|
|
458
|
+
]
|
|
459
|
+
`);
|
|
460
|
+
|
|
461
|
+
expect(mapOnClient.get("hello")).toEqual("world");
|
|
462
|
+
});
|
|
405
463
|
});
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { assert, beforeEach, describe, expect, test } from "vitest";
|
|
2
2
|
import { expectMap } from "../coValue";
|
|
3
3
|
import { WasmCrypto } from "../crypto/WasmCrypto";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
SyncMessagesLog,
|
|
6
|
+
loadCoValueOrFail,
|
|
7
|
+
setupTestAccount,
|
|
8
|
+
setupTestNode,
|
|
9
|
+
waitFor,
|
|
10
|
+
} from "./testUtils";
|
|
5
11
|
|
|
6
12
|
let jazzCloud = setupTestNode({ isSyncServer: true });
|
|
7
13
|
|
|
@@ -146,7 +152,9 @@ describe("peer reconciliation", () => {
|
|
|
146
152
|
});
|
|
147
153
|
|
|
148
154
|
test("correctly handle server restarts in the middle of a sync", async () => {
|
|
149
|
-
const client = setupTestNode(
|
|
155
|
+
const client = setupTestNode({
|
|
156
|
+
connected: true,
|
|
157
|
+
});
|
|
150
158
|
|
|
151
159
|
const group = client.node.createGroup();
|
|
152
160
|
const map = group.createMap();
|
|
@@ -182,10 +190,90 @@ describe("peer reconciliation", () => {
|
|
|
182
190
|
"server -> client | KNOWN Group sessions: empty",
|
|
183
191
|
"client -> server | LOAD Map sessions: header/2",
|
|
184
192
|
"server -> client | KNOWN Map sessions: empty",
|
|
193
|
+
"client -> server | CONTENT Map header: false new: After: 1 New: 1",
|
|
194
|
+
"server -> client | KNOWN CORRECTION Map sessions: empty",
|
|
195
|
+
"client -> server | CONTENT Map header: true new: After: 0 New: 2",
|
|
196
|
+
"server -> client | LOAD Group sessions: empty",
|
|
185
197
|
"client -> server | CONTENT Group header: true new: After: 0 New: 3",
|
|
198
|
+
"server -> client | KNOWN CORRECTION Map sessions: empty",
|
|
199
|
+
"client -> server | CONTENT Map header: true new: After: 0 New: 2",
|
|
200
|
+
"server -> client | KNOWN Group sessions: header/3",
|
|
201
|
+
"server -> client | KNOWN Map sessions: header/2",
|
|
202
|
+
"client -> server | LOAD Group sessions: header/3",
|
|
186
203
|
"server -> client | KNOWN Group sessions: header/3",
|
|
204
|
+
"client -> server | LOAD Map sessions: header/2",
|
|
205
|
+
"server -> client | KNOWN Map sessions: header/2",
|
|
206
|
+
]
|
|
207
|
+
`);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
test("correctly handle server restarts in the middle of a sync (2 - account)", async () => {
|
|
211
|
+
const client = await setupTestAccount({
|
|
212
|
+
connected: true,
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
const group = client.node.createGroup();
|
|
216
|
+
const map = group.createMap();
|
|
217
|
+
|
|
218
|
+
map.set("hello", "world", "trusting");
|
|
219
|
+
|
|
220
|
+
await map.core.waitForSync();
|
|
221
|
+
|
|
222
|
+
jazzCloud.restart();
|
|
223
|
+
SyncMessagesLog.clear();
|
|
224
|
+
client.connectToSyncServer();
|
|
225
|
+
|
|
226
|
+
map.set("hello", "updated", "trusting");
|
|
227
|
+
|
|
228
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
229
|
+
|
|
230
|
+
client.connectToSyncServer();
|
|
231
|
+
|
|
232
|
+
await waitFor(() => {
|
|
233
|
+
const mapOnSyncServer = jazzCloud.node.getCoValue(map.id);
|
|
234
|
+
|
|
235
|
+
expect(mapOnSyncServer.loadingState).toBe("available");
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
expect(
|
|
239
|
+
SyncMessagesLog.getMessages({
|
|
240
|
+
Account: client.node.expectCurrentAccount("client account").core,
|
|
241
|
+
Profile: client.node.expectProfileLoaded(client.accountID).core,
|
|
242
|
+
ProfileGroup: client.node.expectProfileLoaded(client.accountID).group
|
|
243
|
+
.core,
|
|
244
|
+
Group: group.core,
|
|
245
|
+
Map: map.core,
|
|
246
|
+
}),
|
|
247
|
+
).toMatchInlineSnapshot(`
|
|
248
|
+
[
|
|
249
|
+
"client -> server | LOAD Account sessions: header/4",
|
|
250
|
+
"server -> client | KNOWN Account sessions: empty",
|
|
251
|
+
"client -> server | LOAD ProfileGroup sessions: header/5",
|
|
252
|
+
"server -> client | KNOWN ProfileGroup sessions: empty",
|
|
253
|
+
"client -> server | LOAD Profile sessions: header/1",
|
|
254
|
+
"server -> client | KNOWN Profile sessions: empty",
|
|
255
|
+
"client -> server | LOAD Group sessions: header/3",
|
|
256
|
+
"server -> client | KNOWN Group sessions: empty",
|
|
257
|
+
"client -> server | LOAD Map sessions: header/2",
|
|
258
|
+
"server -> client | KNOWN Map sessions: empty",
|
|
259
|
+
"client -> server | CONTENT Map header: false new: After: 1 New: 1",
|
|
260
|
+
"server -> client | KNOWN CORRECTION Map sessions: empty",
|
|
187
261
|
"client -> server | CONTENT Map header: true new: After: 0 New: 2",
|
|
262
|
+
"server -> client | LOAD Account sessions: empty",
|
|
263
|
+
"client -> server | CONTENT Account header: true new: After: 0 New: 4",
|
|
264
|
+
"server -> client | LOAD Group sessions: empty",
|
|
265
|
+
"client -> server | CONTENT Group header: true new: After: 0 New: 3",
|
|
266
|
+
"server -> client | KNOWN CORRECTION Map sessions: empty",
|
|
267
|
+
"client -> server | CONTENT Map header: true new: After: 0 New: 2",
|
|
268
|
+
"server -> client | KNOWN Account sessions: header/4",
|
|
269
|
+
"server -> client | KNOWN Group sessions: header/3",
|
|
188
270
|
"server -> client | KNOWN Map sessions: header/2",
|
|
271
|
+
"client -> server | LOAD Account sessions: header/4",
|
|
272
|
+
"server -> client | KNOWN Account sessions: header/4",
|
|
273
|
+
"client -> server | LOAD ProfileGroup sessions: header/5",
|
|
274
|
+
"server -> client | KNOWN ProfileGroup sessions: empty",
|
|
275
|
+
"client -> server | LOAD Profile sessions: header/1",
|
|
276
|
+
"server -> client | KNOWN Profile sessions: empty",
|
|
189
277
|
"client -> server | LOAD Group sessions: header/3",
|
|
190
278
|
"server -> client | KNOWN Group sessions: header/3",
|
|
191
279
|
"client -> server | LOAD Map sessions: header/2",
|