cojson 0.18.29 → 0.18.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +9 -0
  3. package/dist/PeerState.d.ts +23 -14
  4. package/dist/PeerState.d.ts.map +1 -1
  5. package/dist/PeerState.js +74 -23
  6. package/dist/PeerState.js.map +1 -1
  7. package/dist/SyncStateManager.d.ts +3 -3
  8. package/dist/SyncStateManager.d.ts.map +1 -1
  9. package/dist/SyncStateManager.js +18 -44
  10. package/dist/SyncStateManager.js.map +1 -1
  11. package/dist/coValueContentMessage.d.ts.map +1 -1
  12. package/dist/coValueContentMessage.js +2 -1
  13. package/dist/coValueContentMessage.js.map +1 -1
  14. package/dist/coValueCore/PeerKnownState.d.ts +21 -0
  15. package/dist/coValueCore/PeerKnownState.d.ts.map +1 -0
  16. package/dist/coValueCore/PeerKnownState.js +52 -0
  17. package/dist/coValueCore/PeerKnownState.js.map +1 -0
  18. package/dist/coValueCore/coValueCore.d.ts +39 -8
  19. package/dist/coValueCore/coValueCore.d.ts.map +1 -1
  20. package/dist/coValueCore/coValueCore.js +139 -40
  21. package/dist/coValueCore/coValueCore.js.map +1 -1
  22. package/dist/coValueCore/decryptTransactionChangesAndMeta.d.ts.map +1 -1
  23. package/dist/coValueCore/decryptTransactionChangesAndMeta.js +0 -5
  24. package/dist/coValueCore/decryptTransactionChangesAndMeta.js.map +1 -1
  25. package/dist/coValueCore/verifiedState.d.ts +0 -14
  26. package/dist/coValueCore/verifiedState.d.ts.map +1 -1
  27. package/dist/coValueCore/verifiedState.js +2 -32
  28. package/dist/coValueCore/verifiedState.js.map +1 -1
  29. package/dist/coValues/coList.d.ts +3 -4
  30. package/dist/coValues/coList.d.ts.map +1 -1
  31. package/dist/coValues/coList.js +4 -4
  32. package/dist/coValues/coList.js.map +1 -1
  33. package/dist/coValues/coMap.d.ts +3 -4
  34. package/dist/coValues/coMap.d.ts.map +1 -1
  35. package/dist/coValues/coMap.js +5 -4
  36. package/dist/coValues/coMap.js.map +1 -1
  37. package/dist/coValues/coStream.d.ts +3 -3
  38. package/dist/coValues/coStream.d.ts.map +1 -1
  39. package/dist/coValues/coStream.js +3 -4
  40. package/dist/coValues/coStream.js.map +1 -1
  41. package/dist/coValues/group.d.ts +3 -3
  42. package/dist/coValues/group.d.ts.map +1 -1
  43. package/dist/coValues/group.js +74 -52
  44. package/dist/coValues/group.js.map +1 -1
  45. package/dist/exports.d.ts +2 -2
  46. package/dist/exports.d.ts.map +1 -1
  47. package/dist/exports.js +2 -2
  48. package/dist/exports.js.map +1 -1
  49. package/dist/localNode.d.ts.map +1 -1
  50. package/dist/localNode.js +7 -5
  51. package/dist/localNode.js.map +1 -1
  52. package/dist/permissions.d.ts +5 -1
  53. package/dist/permissions.d.ts.map +1 -1
  54. package/dist/permissions.js +173 -109
  55. package/dist/permissions.js.map +1 -1
  56. package/dist/sync.d.ts.map +1 -1
  57. package/dist/sync.js +33 -44
  58. package/dist/sync.js.map +1 -1
  59. package/dist/tests/PeerKnownState.test.d.ts +2 -0
  60. package/dist/tests/PeerKnownState.test.d.ts.map +1 -0
  61. package/dist/tests/PeerKnownState.test.js +342 -0
  62. package/dist/tests/PeerKnownState.test.js.map +1 -0
  63. package/dist/tests/PeerState.test.js +17 -16
  64. package/dist/tests/PeerState.test.js.map +1 -1
  65. package/dist/tests/StorageApiAsync.test.js +12 -12
  66. package/dist/tests/StorageApiAsync.test.js.map +1 -1
  67. package/dist/tests/StorageApiSync.test.js +11 -11
  68. package/dist/tests/StorageApiSync.test.js.map +1 -1
  69. package/dist/tests/SyncStateManager.test.js +16 -21
  70. package/dist/tests/SyncStateManager.test.js.map +1 -1
  71. package/dist/tests/coValueCore.dependencies.test.js +59 -0
  72. package/dist/tests/coValueCore.dependencies.test.js.map +1 -1
  73. package/dist/tests/coValueCore.test.js +41 -21
  74. package/dist/tests/coValueCore.test.js.map +1 -1
  75. package/dist/tests/group.addMember.test.js +266 -219
  76. package/dist/tests/group.addMember.test.js.map +1 -1
  77. package/dist/tests/group.inheritance.test.js +12 -0
  78. package/dist/tests/group.inheritance.test.js.map +1 -1
  79. package/dist/tests/group.invite.test.js +77 -0
  80. package/dist/tests/group.invite.test.js.map +1 -1
  81. package/dist/tests/group.removeMember.test.js +64 -7
  82. package/dist/tests/group.removeMember.test.js.map +1 -1
  83. package/dist/tests/group.roleOf.test.js +14 -4
  84. package/dist/tests/group.roleOf.test.js.map +1 -1
  85. package/dist/tests/permissions.test.js +51 -202
  86. package/dist/tests/permissions.test.js.map +1 -1
  87. package/dist/tests/sync.content.test.js +2 -2
  88. package/dist/tests/sync.content.test.js.map +1 -1
  89. package/dist/tests/sync.invite.test.js +6 -6
  90. package/dist/tests/sync.load.test.js +22 -22
  91. package/dist/tests/sync.mesh.test.js +9 -9
  92. package/dist/tests/sync.storage.test.js +13 -7
  93. package/dist/tests/sync.storage.test.js.map +1 -1
  94. package/dist/tests/sync.storageAsync.test.js +3 -3
  95. package/dist/tests/sync.test.js +13 -33
  96. package/dist/tests/sync.test.js.map +1 -1
  97. package/dist/tests/sync.upload.test.js +2 -2
  98. package/package.json +3 -3
  99. package/src/PeerState.ts +86 -34
  100. package/src/SyncStateManager.ts +25 -60
  101. package/src/coValueContentMessage.ts +3 -1
  102. package/src/coValueCore/PeerKnownState.ts +74 -0
  103. package/src/coValueCore/coValueCore.ts +180 -49
  104. package/src/coValueCore/decryptTransactionChangesAndMeta.ts +0 -6
  105. package/src/coValueCore/verifiedState.ts +2 -37
  106. package/src/coValues/coList.ts +7 -7
  107. package/src/coValues/coMap.ts +9 -7
  108. package/src/coValues/coStream.ts +6 -5
  109. package/src/coValues/group.ts +99 -60
  110. package/src/exports.ts +2 -1
  111. package/src/localNode.ts +7 -5
  112. package/src/permissions.ts +204 -123
  113. package/src/sync.ts +37 -53
  114. package/src/tests/PeerKnownState.test.ts +426 -0
  115. package/src/tests/PeerState.test.ts +24 -24
  116. package/src/tests/StorageApiAsync.test.ts +12 -12
  117. package/src/tests/StorageApiSync.test.ts +11 -11
  118. package/src/tests/SyncStateManager.test.ts +23 -53
  119. package/src/tests/coValueCore.dependencies.test.ts +87 -0
  120. package/src/tests/coValueCore.test.ts +64 -22
  121. package/src/tests/group.addMember.test.ts +384 -345
  122. package/src/tests/group.inheritance.test.ts +33 -0
  123. package/src/tests/group.invite.test.ts +117 -0
  124. package/src/tests/group.removeMember.test.ts +95 -9
  125. package/src/tests/group.roleOf.test.ts +16 -4
  126. package/src/tests/permissions.test.ts +56 -295
  127. package/src/tests/sync.content.test.ts +2 -2
  128. package/src/tests/sync.invite.test.ts +6 -6
  129. package/src/tests/sync.load.test.ts +22 -22
  130. package/src/tests/sync.mesh.test.ts +9 -9
  131. package/src/tests/sync.storage.test.ts +13 -8
  132. package/src/tests/sync.storageAsync.test.ts +3 -3
  133. package/src/tests/sync.test.ts +21 -50
  134. package/src/tests/sync.upload.test.ts +2 -2
  135. package/dist/PeerKnownStates.d.ts +0 -19
  136. package/dist/PeerKnownStates.d.ts.map +0 -1
  137. package/dist/PeerKnownStates.js +0 -64
  138. package/dist/PeerKnownStates.js.map +0 -1
  139. package/dist/tests/PeerKnownStates.test.d.ts +0 -2
  140. package/dist/tests/PeerKnownStates.test.d.ts.map +0 -1
  141. package/dist/tests/PeerKnownStates.test.js +0 -77
  142. package/dist/tests/PeerKnownStates.test.js.map +0 -1
  143. package/src/PeerKnownStates.ts +0 -93
  144. package/src/tests/PeerKnownStates.test.ts +0 -99
@@ -1040,6 +1040,39 @@ describe("extend with role mapping", () => {
1040
1040
  expect(childGroupOnNode2.roleOf(node3.accountID)).toEqual("reader");
1041
1041
  });
1042
1042
 
1043
+ test("mapping to manager should add the ability to add members", async () => {
1044
+ const { node1, node2, node3 } = await createThreeConnectedNodes(
1045
+ "server",
1046
+ "server",
1047
+ "server",
1048
+ );
1049
+
1050
+ const group = node1.node.createGroup();
1051
+ group.addMember(
1052
+ await loadCoValueOrFail(node1.node, node2.accountID),
1053
+ "reader",
1054
+ );
1055
+
1056
+ const childGroup = node1.node.createGroup();
1057
+ childGroup.extend(group, "manager");
1058
+
1059
+ expect(childGroup.roleOf(node2.accountID)).toEqual("manager");
1060
+
1061
+ await childGroup.core.waitForSync();
1062
+
1063
+ const childGroupOnNode2 = await loadCoValueOrFail(
1064
+ node2.node,
1065
+ childGroup.id,
1066
+ );
1067
+
1068
+ childGroupOnNode2.addMember(
1069
+ await loadCoValueOrFail(node2.node, node3.accountID),
1070
+ "reader",
1071
+ );
1072
+
1073
+ expect(childGroupOnNode2.roleOf(node3.accountID)).toEqual("reader");
1074
+ });
1075
+
1043
1076
  test("mapping to reader should remove the ability to add members", async () => {
1044
1077
  const { node1, node2, node3 } = await createThreeConnectedNodes(
1045
1078
  "server",
@@ -8,13 +8,72 @@ import {
8
8
  setupTestNode,
9
9
  waitFor,
10
10
  } from "./testUtils.js";
11
+ import { AccountRole } from "../permissions.js";
11
12
 
12
13
  beforeEach(async () => {
13
14
  SyncMessagesLog.clear();
14
15
  setupTestNode({ isSyncServer: true });
15
16
  });
16
17
 
18
+ // [fromRole, toRole, canCreateInvite]
19
+ const CAN_CREATE_INVITE_MATRIX: [AccountRole, AccountRole, boolean][] = [
20
+ ["admin", "admin", true],
21
+ ["admin", "manager", true],
22
+ ["admin", "writer", true],
23
+ ["admin", "reader", true],
24
+ ["admin", "writeOnly", true],
25
+
26
+ ["manager", "admin", false],
27
+ ["manager", "manager", false],
28
+ ["manager", "writer", true],
29
+ ["manager", "reader", true],
30
+ ["manager", "writeOnly", true],
31
+
32
+ ["writer", "admin", false],
33
+ ["writer", "manager", false],
34
+ ["writer", "writer", false],
35
+ ["writer", "reader", false],
36
+ ["writer", "writeOnly", false],
37
+
38
+ ["reader", "admin", false],
39
+ ["reader", "manager", false],
40
+ ["reader", "writer", false],
41
+ ["reader", "reader", false],
42
+ ["reader", "writeOnly", false],
43
+
44
+ ["writeOnly", "admin", false],
45
+ ["writeOnly", "manager", false],
46
+ ["writeOnly", "writer", false],
47
+ ["writeOnly", "reader", false],
48
+ ["writeOnly", "writeOnly", false],
49
+ ];
50
+
17
51
  describe("Group invites", () => {
52
+ for (const [fromRole, toRole, canCreateInvite] of CAN_CREATE_INVITE_MATRIX) {
53
+ test(`${fromRole} should ${canCreateInvite ? "be able" : "not be able"} to create an invite for ${toRole}`, async () => {
54
+ const admin = await setupTestAccount({
55
+ connected: true,
56
+ });
57
+
58
+ const group = admin.node.createGroup();
59
+
60
+ const adminOnAdminNode = await loadCoValueOrFail(
61
+ admin.node,
62
+ admin.accountID,
63
+ );
64
+
65
+ group.addMember(adminOnAdminNode, fromRole);
66
+
67
+ if (canCreateInvite) {
68
+ expect(group.createInvite(toRole)).toBeDefined();
69
+ } else {
70
+ expect(() => {
71
+ group.createInvite(toRole);
72
+ }).toThrow(`Failed to set role ${toRole}Invite to`);
73
+ }
74
+ });
75
+ }
76
+
18
77
  test("should be able to accept a reader invite", async () => {
19
78
  const admin = await setupTestAccount({
20
79
  connected: true,
@@ -193,6 +252,64 @@ describe("Group invites", () => {
193
252
  });
194
253
  });
195
254
 
255
+ test("should be able to accept a manager invite", async () => {
256
+ const admin = await setupTestAccount({
257
+ connected: true,
258
+ });
259
+
260
+ const newMember = await setupTestAccount({
261
+ connected: true,
262
+ });
263
+
264
+ const group = admin.node.createGroup();
265
+
266
+ const person = group.createMap({
267
+ name: "John Doe",
268
+ });
269
+
270
+ const inviteSecret = group.createInvite("manager");
271
+
272
+ const personOnNewMemberNode = await loadCoValueOrFail(
273
+ newMember.node,
274
+ person.id,
275
+ );
276
+ expect(personOnNewMemberNode.get("name")).toEqual(undefined);
277
+
278
+ await newMember.node.acceptInvite(group.id, inviteSecret);
279
+
280
+ await waitFor(() => {
281
+ expect(
282
+ expectMap(personOnNewMemberNode.core.getCurrentContent()).get("name"),
283
+ ).toEqual("John Doe");
284
+ });
285
+
286
+ const groupOnNewMemberNode = await loadCoValueOrFail(
287
+ newMember.node,
288
+ group.id,
289
+ );
290
+
291
+ expect(groupOnNewMemberNode.roleOf(newMember.accountID)).toEqual("manager");
292
+
293
+ // Verify admin access by adding another member
294
+ const reader = await setupTestAccount({
295
+ connected: true,
296
+ });
297
+
298
+ const readerOnNewMemberNode = await loadCoValueOrFail(
299
+ newMember.node,
300
+ reader.accountID,
301
+ );
302
+ groupOnNewMemberNode.addMember(readerOnNewMemberNode, "reader");
303
+
304
+ const personOnReaderNode = await loadCoValueOrFail(reader.node, person.id);
305
+
306
+ await waitFor(() => {
307
+ expect(
308
+ expectMap(personOnReaderNode.core.getCurrentContent()).get("name"),
309
+ ).toEqual("John Doe");
310
+ });
311
+ });
312
+
196
313
  test("should not be able to accept an invite twice", async () => {
197
314
  const admin = await setupTestAccount({
198
315
  connected: true,
@@ -8,6 +8,7 @@ import {
8
8
  setupTestNode,
9
9
  waitFor,
10
10
  } from "./testUtils.js";
11
+ import { expectGroup } from "../typeUtils/expectGroup.js";
11
12
 
12
13
  setCoValueLoadingRetryDelay(10);
13
14
 
@@ -78,9 +79,15 @@ describe("Group.removeMember", () => {
78
79
  expect(mapOnAliceNode.get("test")).toEqual("test");
79
80
  });
80
81
 
81
- for (const member of ["writer", "reader", "writeOnly", "admin"] as const) {
82
+ for (const member of [
83
+ "writer",
84
+ "reader",
85
+ "writeOnly",
86
+ "manager",
87
+ "admin",
88
+ ] as const) {
82
89
  test(`${member} member should be able to revoke themselves`, async () => {
83
- const admin = await setupTestAccount({
90
+ const superAdmin = await setupTestAccount({
84
91
  connected: true,
85
92
  });
86
93
 
@@ -88,9 +95,9 @@ describe("Group.removeMember", () => {
88
95
  connected: true,
89
96
  });
90
97
 
91
- const group = admin.node.createGroup();
98
+ const group = superAdmin.node.createGroup();
92
99
  group.addMember(
93
- await loadCoValueOrFail(admin.node, client.accountID),
100
+ await loadCoValueOrFail(superAdmin.node, client.accountID),
94
101
  member,
95
102
  );
96
103
 
@@ -116,6 +123,10 @@ describe("Group.removeMember", () => {
116
123
  connected: true,
117
124
  });
118
125
 
126
+ const manager = await setupTestAccount({
127
+ connected: true,
128
+ });
129
+
119
130
  const writer = await setupTestAccount({
120
131
  connected: true,
121
132
  });
@@ -133,6 +144,10 @@ describe("Group.removeMember", () => {
133
144
  });
134
145
 
135
146
  const group = admin.node.createGroup();
147
+ group.addMember(
148
+ await loadCoValueOrFail(admin.node, manager.accountID),
149
+ "manager",
150
+ );
136
151
  group.addMember(
137
152
  await loadCoValueOrFail(admin.node, writer.accountID),
138
153
  "writer",
@@ -152,23 +167,50 @@ describe("Group.removeMember", () => {
152
167
 
153
168
  const loadedGroup = await loadCoValueOrFail(client.node, group.id);
154
169
 
170
+ // expect(async () => {
155
171
  loadedGroup.removeMember(
156
172
  await loadCoValueOrFail(client.node, reader.accountID),
157
173
  );
174
+ // }).rejects.toThrow(
175
+ // `Failed to revoke role to ${reader.accountID} (role of current account is ${member})`,
176
+ // );
177
+
178
+ // expect(async () => {
158
179
  loadedGroup.removeMember(
159
180
  await loadCoValueOrFail(client.node, writeOnly.accountID),
160
181
  );
182
+ // }).rejects.toThrow(
183
+ // `Failed to revoke role to ${writeOnly.accountID} (role of current account is ${member})`,
184
+ // );
185
+
186
+ // expect(async () => {
161
187
  loadedGroup.removeMember(
162
188
  await loadCoValueOrFail(client.node, writer.accountID),
163
189
  );
190
+ // }).rejects.toThrow(
191
+ // `Failed to revoke role to ${writer.accountID} (role of current account is ${member})`,
192
+ // );
193
+
194
+ // expect(async () => {
164
195
  loadedGroup.removeMember(
165
196
  await loadCoValueOrFail(client.node, admin.accountID),
166
197
  );
198
+ // }).rejects.toThrow(
199
+ // `Failed to revoke role to ${admin.accountID} (role of current account is ${member})`,
200
+ // );
167
201
 
202
+ // expect(async () => {
203
+ loadedGroup.removeMember(
204
+ await loadCoValueOrFail(client.node, manager.accountID),
205
+ );
206
+ // }).rejects.toThrow(
207
+ // `Failed to revoke role to ${manager.accountID} (role of current account is ${member})`,
208
+ // );
168
209
  expect(loadedGroup.roleOf(reader.accountID)).toEqual("reader");
169
210
  expect(loadedGroup.roleOf(writer.accountID)).toEqual("writer");
170
211
  expect(loadedGroup.roleOf(writeOnly.accountID)).toEqual("writeOnly");
171
212
  expect(loadedGroup.roleOf(admin.accountID)).toEqual("admin");
213
+ expect(loadedGroup.roleOf(manager.accountID)).toEqual("manager");
172
214
 
173
215
  await loadedGroup.core.waitForSync();
174
216
 
@@ -184,6 +226,9 @@ describe("Group.removeMember", () => {
184
226
  expect((await loadCoValueOrFail(admin.node, group.id)).myRole()).toEqual(
185
227
  "admin",
186
228
  );
229
+ expect(
230
+ (await loadCoValueOrFail(manager.node, group.id)).myRole(),
231
+ ).toEqual("manager");
187
232
  });
188
233
  }
189
234
 
@@ -203,11 +248,17 @@ describe("Group.removeMember", () => {
203
248
  );
204
249
 
205
250
  const loadedGroup = await loadCoValueOrFail(client.node, group.id);
206
-
207
- loadedGroup.removeMember(
208
- await loadCoValueOrFail(client.node, admin.accountID),
251
+ const adminOnClientNode = await loadCoValueOrFail(
252
+ client.node,
253
+ admin.accountID,
209
254
  );
210
255
 
256
+ // expect(() => {
257
+ loadedGroup.removeMember(adminOnClientNode);
258
+ // }).toThrow(
259
+ // `Failed to revoke role to ${admin.accountID} (role of current account is admin)`,
260
+ // );
261
+
211
262
  expect(loadedGroup.roleOf(admin.accountID)).toEqual("admin");
212
263
 
213
264
  await loadedGroup.core.waitForSync();
@@ -217,6 +268,38 @@ describe("Group.removeMember", () => {
217
268
  );
218
269
  });
219
270
 
271
+ test(`managers can remove other managers`, async () => {
272
+ const admin = await setupTestAccount({
273
+ connected: true,
274
+ });
275
+
276
+ const client = await setupTestAccount({
277
+ connected: true,
278
+ });
279
+
280
+ const group = admin.node.createGroup();
281
+ // downgrade admin to manager
282
+ group.addMember(
283
+ await loadCoValueOrFail(admin.node, admin.accountID),
284
+ "manager",
285
+ );
286
+ group.addMember(
287
+ await loadCoValueOrFail(admin.node, client.accountID),
288
+ "manager",
289
+ );
290
+
291
+ const loadedGroup = await loadCoValueOrFail(client.node, group.id);
292
+
293
+ const adminOnClientNode = await loadCoValueOrFail(
294
+ client.node,
295
+ admin.accountID,
296
+ );
297
+
298
+ loadedGroup.removeMember(adminOnClientNode);
299
+
300
+ expect(loadedGroup.roleOf(admin.accountID)).toEqual(undefined);
301
+ });
302
+
220
303
  test("removing a member when inheriting a group where the user lacks read rights", async () => {
221
304
  const admin = await setupTestAccount({
222
305
  connected: true,
@@ -318,7 +401,7 @@ describe("Group.removeMember", () => {
318
401
 
319
402
  const group = admin.node.createGroup();
320
403
 
321
- const childGroup = bob.node.createGroup();
404
+ let childGroup = bob.node.createGroup();
322
405
  group.addMember(bobOnAdminNode, "reader");
323
406
  group.addMember(aliceOnAdminNode, "reader");
324
407
 
@@ -331,9 +414,12 @@ describe("Group.removeMember", () => {
331
414
  group.removeMember(aliceOnAdminNode);
332
415
 
333
416
  // Rotating the child group keys is async when the child group is not loaded
334
- await admin.node.getCoValue(childGroup.id).waitForAvailableOrUnavailable();
335
417
  await admin.node.syncManager.waitForAllCoValuesSync();
336
418
 
419
+ // Reload the group the trigger the loading checks
420
+ childGroup.core.resetParsedTransactions();
421
+ childGroup = expectGroup(childGroup.core.getCurrentContent());
422
+
337
423
  const map = childGroup.createMap();
338
424
  map.set("test", "Not readable by alice");
339
425
 
@@ -8,6 +8,7 @@ import {
8
8
  randomAgentAndSessionID,
9
9
  waitFor,
10
10
  } from "./testUtils";
11
+ import { expectMap } from "../coValue";
11
12
 
12
13
  describe("roleOf", () => {
13
14
  test("returns direct role assignments", () => {
@@ -326,7 +327,11 @@ describe("roleOf", () => {
326
327
  mapOnNode2.set("test", "Updated after the downgrade");
327
328
 
328
329
  expect(mapOnNode2.get("test")).toEqual("Written from everyone");
329
- expect(mapOnNode2.get("fromAdmin")).toEqual("Written from admin");
330
+
331
+ await waitFor(async () => {
332
+ const updatedMap = expectMap(mapOnNode2.core.getCurrentContent());
333
+ expect(updatedMap.get("fromAdmin")).toEqual("Written from admin");
334
+ });
330
335
  });
331
336
 
332
337
  test("switching from everyone writeOnly to writer", async () => {
@@ -347,7 +352,7 @@ describe("roleOf", () => {
347
352
 
348
353
  expect(groupOnNode2.myRole()).toEqual("writeOnly");
349
354
 
350
- const mapOnNode2 = await loadCoValueOrFail(node2.node, map.id);
355
+ let mapOnNode2 = await loadCoValueOrFail(node2.node, map.id);
351
356
 
352
357
  expect(mapOnNode2.get("test")).toEqual(undefined);
353
358
 
@@ -360,12 +365,19 @@ describe("roleOf", () => {
360
365
 
361
366
  group.addMember("everyone", "writer");
362
367
 
363
- await group.core.waitForSync();
368
+ await waitFor(async () => {
369
+ expect(groupOnNode2.core.knownState()).toEqual(group.core.knownState());
370
+ });
364
371
 
365
372
  mapOnNode2.set("test", "Updated after the upgrade");
366
373
 
367
374
  expect(mapOnNode2.get("test")).toEqual("Updated after the upgrade");
368
- expect(mapOnNode2.get("fromAdmin")).toEqual("Written from admin");
375
+
376
+ await waitFor(async () => {
377
+ const updatedMap = expectMap(mapOnNode2.core.getCurrentContent());
378
+ // Get the new content after the invalidation caused by group update
379
+ expect(updatedMap.get("fromAdmin")).toEqual("Written from admin");
380
+ });
369
381
  });
370
382
 
371
383
  test("adding a reader member after writeOnly", async () => {