Skip to content

Commit 981417f

Browse files
authored
chore: designated survivor test suite (#2540)
* chore: designated survivor test suite * add more tests * fix: tests exclusivness * fix removing account from shared vaults test
1 parent 70cc15c commit 981417f

File tree

17 files changed

+537
-95
lines changed

17 files changed

+537
-95
lines changed

packages/api/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
},
3737
"dependencies": {
3838
"@standardnotes/common": "^1.50.0",
39-
"@standardnotes/domain-core": "^1.33.1",
39+
"@standardnotes/domain-core": "^1.34.1",
4040
"@standardnotes/models": "workspace:*",
4141
"@standardnotes/responses": "workspace:*",
4242
"@standardnotes/utils": "workspace:*",

packages/desktop/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
},
3636
"dependencies": {
3737
"@electron/remote": "^2.0.9",
38-
"@standardnotes/domain-core": "^1.33.1",
38+
"@standardnotes/domain-core": "^1.34.1",
3939
"@standardnotes/electron-clear-data": "1.1.1",
4040
"@standardnotes/web": "workspace:*",
4141
"axios": "^1.1.3",

packages/encryption/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
},
3030
"dependencies": {
3131
"@standardnotes/common": "^1.50.0",
32-
"@standardnotes/domain-core": "^1.33.1",
32+
"@standardnotes/domain-core": "^1.34.1",
3333
"@standardnotes/models": "workspace:*",
3434
"@standardnotes/responses": "workspace:*",
3535
"@standardnotes/sncrypto-common": "workspace:*",

packages/features/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
},
2727
"dependencies": {
2828
"@standardnotes/common": "^1.50.0",
29-
"@standardnotes/domain-core": "^1.33.1",
29+
"@standardnotes/domain-core": "^1.34.1",
3030
"reflect-metadata": "^0.1.13"
3131
},
3232
"devDependencies": {

packages/models/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
},
2121
"dependencies": {
2222
"@standardnotes/common": "^1.50.0",
23-
"@standardnotes/domain-core": "^1.33.1",
23+
"@standardnotes/domain-core": "^1.34.1",
2424
"@standardnotes/features": "workspace:*",
2525
"@standardnotes/responses": "workspace:*",
2626
"@standardnotes/sncrypto-common": "workspace:^",

packages/services/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"dependencies": {
1919
"@standardnotes/api": "workspace:^",
2020
"@standardnotes/common": "^1.50.0",
21-
"@standardnotes/domain-core": "^1.33.1",
21+
"@standardnotes/domain-core": "^1.34.1",
2222
"@standardnotes/encryption": "workspace:^",
2323
"@standardnotes/features": "workspace:^",
2424
"@standardnotes/files": "workspace:^",

packages/services/src/Domain/SharedVaults/SharedVaultService.ts

+18-4
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ export class SharedVaultService
9696
await this.handleNotification(event.payload as NotificationServiceEventPayload)
9797
break
9898
case SyncEvent.ReceivedRemoteSharedVaults:
99-
void this.notifyEventSync(SharedVaultServiceEvent.SharedVaultStatusChanged)
99+
void this.notifyEvent(SharedVaultServiceEvent.SharedVaultStatusChanged)
100100
break
101101
}
102102
}
@@ -113,7 +113,20 @@ export class SharedVaultService
113113
break
114114
}
115115
case NotificationType.TYPES.UserRemovedFromSharedVault: {
116-
this.vaultUsers.invalidateVaultUsersCache(event.eventPayload.props.primaryIdentifier.value).catch(console.error)
116+
const vaultOrError = this._getVault.execute<SharedVaultListingInterface>({
117+
sharedVaultUuid: event.eventPayload.props.primaryIdentifier.value,
118+
})
119+
if (!vaultOrError.isFailed()) {
120+
const vault = vaultOrError.getValue()
121+
122+
this.vaultUsers
123+
.invalidateVaultUsersCache(event.eventPayload.props.primaryIdentifier.value)
124+
.catch(console.error)
125+
126+
await this._syncLocalVaultsWithRemoteSharedVaults.execute([vault])
127+
128+
void this.notifyEvent(SharedVaultServiceEvent.SharedVaultStatusChanged)
129+
}
117130
break
118131
}
119132
case NotificationType.TYPES.SharedVaultItemRemoved: {
@@ -124,14 +137,15 @@ export class SharedVaultService
124137
break
125138
}
126139
case NotificationType.TYPES.SharedVaultFileRemoved:
127-
case NotificationType.TYPES.SharedVaultFileUploaded: {
140+
case NotificationType.TYPES.SharedVaultFileUploaded:
141+
case NotificationType.TYPES.UserDesignatedAsSurvivor: {
128142
const vaultOrError = this._getVault.execute<SharedVaultListingInterface>({
129143
sharedVaultUuid: event.eventPayload.props.primaryIdentifier.value,
130144
})
131145
if (!vaultOrError.isFailed()) {
132146
await this._syncLocalVaultsWithRemoteSharedVaults.execute([vaultOrError.getValue()])
133147

134-
void this.notifyEventSync(SharedVaultServiceEvent.SharedVaultStatusChanged)
148+
void this.notifyEvent(SharedVaultServiceEvent.SharedVaultStatusChanged)
135149
}
136150

137151
break
+63-59
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,63 @@
1-
export const BaseTests = [
2-
'memory.test.js',
3-
'protocol.test.js',
4-
'utils.test.js',
5-
'000.test.js',
6-
'001.test.js',
7-
'002.test.js',
8-
'003.test.js',
9-
'004.test.js',
10-
'username.test.js',
11-
'app-group.test.js',
12-
'application.test.js',
13-
'payload.test.js',
14-
'payload_encryption.test.js',
15-
'item.test.js',
16-
'item_manager.test.js',
17-
'features.test.js',
18-
'settings.test.js',
19-
'mfa_service.test.js',
20-
'mutator.test.js',
21-
'mutator_service.test.js',
22-
'payload_manager.test.js',
23-
'collections.test.js',
24-
'note_display_criteria.test.js',
25-
'keys.test.js',
26-
'key_params.test.js',
27-
'key_recovery_service.test.js',
28-
'backups.test.js',
29-
'upgrading.test.js',
30-
'model_tests/importing.test.js',
31-
'model_tests/appmodels.test.js',
32-
'model_tests/items.test.js',
33-
'model_tests/mapping.test.js',
34-
'model_tests/notes_smart_tags.test.js',
35-
'model_tests/notes_tags.test.js',
36-
'model_tests/notes_tags_folders.test.js',
37-
'model_tests/performance.test.js',
38-
'sync_tests/offline.test.js',
39-
'sync_tests/notes_tags.test.js',
40-
'sync_tests/online.test.js',
41-
'sync_tests/conflicting.test.js',
42-
'sync_tests/integrity.test.js',
43-
'auth-fringe-cases.test.js',
44-
'auth.test.js',
45-
'device_auth.test.js',
46-
'storage.test.js',
47-
'protection.test.js',
48-
'singletons.test.js',
49-
'migrations/migration.test.js',
50-
'migrations/tags-to-folders.test.js',
51-
'history.test.js',
52-
'actions.test.js',
53-
'preferences.test.js',
54-
'files.test.js',
55-
'session.test.js',
56-
'session-invalidation.test.js',
57-
'subscriptions.test.js',
58-
'recovery.test.js',
59-
]
1+
export const BaseTests = {
2+
enabled: true,
3+
exclusive: false,
4+
files: [
5+
'memory.test.js',
6+
'protocol.test.js',
7+
'utils.test.js',
8+
'000.test.js',
9+
'001.test.js',
10+
'002.test.js',
11+
'003.test.js',
12+
'004.test.js',
13+
'username.test.js',
14+
'app-group.test.js',
15+
'application.test.js',
16+
'payload.test.js',
17+
'payload_encryption.test.js',
18+
'item.test.js',
19+
'item_manager.test.js',
20+
'features.test.js',
21+
'settings.test.js',
22+
'mfa_service.test.js',
23+
'mutator.test.js',
24+
'mutator_service.test.js',
25+
'payload_manager.test.js',
26+
'collections.test.js',
27+
'note_display_criteria.test.js',
28+
'keys.test.js',
29+
'key_params.test.js',
30+
'key_recovery_service.test.js',
31+
'backups.test.js',
32+
'upgrading.test.js',
33+
'model_tests/importing.test.js',
34+
'model_tests/appmodels.test.js',
35+
'model_tests/items.test.js',
36+
'model_tests/mapping.test.js',
37+
'model_tests/notes_smart_tags.test.js',
38+
'model_tests/notes_tags.test.js',
39+
'model_tests/notes_tags_folders.test.js',
40+
'model_tests/performance.test.js',
41+
'sync_tests/offline.test.js',
42+
'sync_tests/notes_tags.test.js',
43+
'sync_tests/online.test.js',
44+
'sync_tests/conflicting.test.js',
45+
'sync_tests/integrity.test.js',
46+
'auth-fringe-cases.test.js',
47+
'auth.test.js',
48+
'device_auth.test.js',
49+
'storage.test.js',
50+
'protection.test.js',
51+
'singletons.test.js',
52+
'migrations/migration.test.js',
53+
'migrations/tags-to-folders.test.js',
54+
'history.test.js',
55+
'actions.test.js',
56+
'preferences.test.js',
57+
'files.test.js',
58+
'session.test.js',
59+
'session-invalidation.test.js',
60+
'subscriptions.test.js',
61+
'recovery.test.js',
62+
]
63+
}

packages/snjs/mocha/TestRegistry/VaultTests.js

+1
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,6 @@ export const VaultTests = {
2323
'vaults/files.test.js',
2424
'vaults/limits.test.js',
2525
'vaults/quota.test.js',
26+
'vaults/surviving.test.js',
2627
],
2728
}

packages/snjs/mocha/lib/Collaboration.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export const acceptAllInvites = async (context) => {
4141
}
4242
}
4343

44-
const inviteContext = async (context, contactContext, sharedVault, contact, permission) => {
44+
export const inviteContext = async (context, contactContext, sharedVault, contact, permission) => {
4545
contactContext.lockSyncing()
4646

4747
const inviteOrError = await context.vaultInvites.inviteContactToSharedVault(sharedVault, contact, permission)
@@ -207,3 +207,12 @@ export const moveItemToVault = async (context, sharedVault, item) => {
207207

208208
return result.getValue()
209209
}
210+
211+
export const designateSharedVaultSurvior = async (context, sharedVault, survivorUuid) => {
212+
const result = await context.vaultUsers.designateSurvivor(sharedVault, survivorUuid)
213+
if (result.isFailed()) {
214+
throw new Error(result.getError())
215+
}
216+
217+
return result.getValue()
218+
}

packages/snjs/mocha/test.html

+18-11
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@
3838
<script type="module">
3939
import MainRegistry from './TestRegistry/MainRegistry.js'
4040

41+
const urlSearchParams = new URLSearchParams(window.location.search);
42+
const testSuite = urlSearchParams.get('suite');
43+
if (testSuite === 'vaults') {
44+
MainRegistry.VaultTests.exclusive = true;
45+
} else if (testSuite === 'base') {
46+
MainRegistry.BaseTests.exclusive = true;
47+
}
48+
4149
const loadTest = (fileName) => {
4250
return new Promise((resolve) => {
4351
const script = document.createElement('script');
@@ -56,18 +64,17 @@
5664
}
5765
}
5866

59-
if (MainRegistry.VaultTests.enabled) {
60-
InternalFeatureService.get().enableFeature(InternalFeature.Vaults);
61-
if (MainRegistry.VaultTests.exclusive) {
62-
await loadTests(MainRegistry.VaultTests.files);
63-
} else {
64-
await loadTests([
65-
...MainRegistry.BaseTests,
66-
...MainRegistry.VaultTests.files
67-
]);
68-
}
67+
InternalFeatureService.get().enableFeature(InternalFeature.Vaults);
68+
69+
if (MainRegistry.VaultTests.exclusive) {
70+
await loadTests(MainRegistry.VaultTests.files);
71+
} else if (MainRegistry.BaseTests.exclusive) {
72+
await loadTests(MainRegistry.BaseTests.files);
6973
} else {
70-
await loadTests(MainRegistry.BaseTests);
74+
await loadTests([
75+
...MainRegistry.BaseTests.files,
76+
...MainRegistry.VaultTests.files
77+
]);
7178
}
7279

7380
mocha.run()

packages/snjs/mocha/vaults/deletion.test.js

+44
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as Factory from '../lib/factory.js'
2+
import * as Utils from '../lib/Utils.js'
23
import * as Collaboration from '../lib/Collaboration.js'
34

45
chai.use(chaiAsPromised)
@@ -167,4 +168,47 @@ describe('shared vault deletion', function () {
167168

168169
await deinitContactContext()
169170
})
171+
172+
it('should remove a user from all shared vaults upon account removal', async () => {
173+
const secondContext = await Factory.createVaultsContextWithRealCrypto()
174+
await secondContext.launch()
175+
await secondContext.register()
176+
177+
const thirdContext = await Factory.createVaultsContextWithRealCrypto()
178+
await thirdContext.launch()
179+
await thirdContext.register()
180+
181+
const firstVault = await Collaboration.createSharedVault(context)
182+
const secondVault = await Collaboration.createSharedVault(thirdContext)
183+
184+
const firstToSecondContact = await Collaboration.createTrustedContactForUserOfContext(context, secondContext)
185+
await Collaboration.createTrustedContactForUserOfContext(secondContext, context)
186+
187+
const thirdToSecondContact = await Collaboration.createTrustedContactForUserOfContext(thirdContext, secondContext)
188+
await Collaboration.createTrustedContactForUserOfContext(thirdContext, context)
189+
190+
await Collaboration.inviteContext(context, secondContext, firstVault, firstToSecondContact, SharedVaultUserPermission.PERMISSIONS.Write)
191+
await Collaboration.inviteContext(thirdContext, secondContext, secondVault, thirdToSecondContact, SharedVaultUserPermission.PERMISSIONS.Write)
192+
193+
const promise = secondContext.awaitNextSyncSharedVaultFromScratchEvent()
194+
195+
await Collaboration.acceptAllInvites(secondContext)
196+
197+
await Utils.awaitPromiseOrThrow(promise, 2.0, 'Waiting for vault to sync')
198+
199+
Factory.handlePasswordChallenges(secondContext.application, secondContext.password)
200+
await secondContext.application.user.deleteAccount()
201+
202+
await context.syncAndAwaitNotificationsProcessing()
203+
await thirdContext.syncAndAwaitNotificationsProcessing()
204+
205+
const sharedVaultUsersInFirstVault = await context.vaultUsers.getSharedVaultUsersFromServer(firstVault)
206+
expect(sharedVaultUsersInFirstVault.length).to.equal(1)
207+
208+
const sharedVaultUsersInSecondVault = await thirdContext.vaultUsers.getSharedVaultUsersFromServer(secondVault)
209+
expect(sharedVaultUsersInSecondVault.length).to.equal(1)
210+
211+
await secondContext.deinit()
212+
await thirdContext.deinit()
213+
})
170214
})

0 commit comments

Comments
 (0)