Files
standardnotes-app-web/packages/snjs/mocha/migrations/2020-01-15-web.test.js
2022-07-06 14:04:30 +02:00

585 lines
27 KiB
JavaScript

/* eslint-disable no-unused-expressions */
/* eslint-disable no-undef */
import * as Factory from '../lib/factory.js'
import FakeWebCrypto from '../lib/fake_web_crypto.js'
chai.use(chaiAsPromised)
const expect = chai.expect
describe('2020-01-15 web migration', () => {
beforeEach(() => {
localStorage.clear()
})
afterEach(() => {
localStorage.clear()
})
/**
* This test will pass but sync afterwards will not be successful
* as we are using a random value for the legacy session token
*/
it('2020-01-15 migration with passcode and account', async function () {
const application = await Factory.createAppWithRandNamespace()
/** Create legacy migrations value so that base migration detects old app */
await application.deviceInterface.setRawStorageValue('migrations', JSON.stringify(['anything']))
const operator003 = new SNProtocolOperator003(new FakeWebCrypto())
const identifier = 'foo'
const passcode = 'bar'
/** Create old version passcode parameters */
const passcodeKey = await operator003.createRootKey(identifier, passcode)
await application.deviceInterface.setRawStorageValue(
'offlineParams',
JSON.stringify(passcodeKey.keyParams.getPortableValue()),
)
/** Create arbitrary storage values and make sure they're migrated */
const arbitraryValues = {
foo: 'bar',
zar: 'tar',
har: 'car',
}
for (const key of Object.keys(arbitraryValues)) {
await application.deviceInterface.setRawStorageValue(key, arbitraryValues[key])
}
/** Create old version account parameters */
const password = 'tar'
const accountKey = await operator003.createRootKey(identifier, password)
/** Create legacy storage and encrypt it with passcode */
const embeddedStorage = {
mk: accountKey.masterKey,
ak: accountKey.dataAuthenticationKey,
pw: accountKey.serverPassword,
jwt: 'anything',
/** Legacy versions would store json strings inside of embedded storage */
auth_params: JSON.stringify(accountKey.keyParams.getPortableValue()),
}
const storagePayload = new DecryptedPayload({
uuid: await operator003.crypto.generateUUID(),
content_type: ContentType.EncryptedStorage,
content: {
storage: embeddedStorage,
},
})
const encryptionParams = await operator003.generateEncryptedParametersAsync(storagePayload, passcodeKey)
const persistPayload = new EncryptedPayload({ ...storagePayload, ...encryptionParams })
await application.deviceInterface.setRawStorageValue('encryptedStorage', JSON.stringify(persistPayload))
/** Create encrypted item and store it in db */
const notePayload = Factory.createNotePayload()
const noteEncryptionParams = await operator003.generateEncryptedParametersAsync(notePayload, accountKey)
const noteEncryptedPayload = new EncryptedPayload({ ...notePayload, ...noteEncryptionParams })
await application.deviceInterface.saveRawDatabasePayload(noteEncryptedPayload, application.identifier)
/** Run migration */
await application.prepareForLaunch({
receiveChallenge: async (challenge) => {
application.submitValuesForChallenge(challenge, [CreateChallengeValue(challenge.prompts[0], passcode)])
},
})
await application.launch(true)
expect(application.sessionManager.online()).to.equal(true)
expect(application.protocolService.rootKeyEncryption.keyMode).to.equal(KeyMode.RootKeyPlusWrapper)
/** Should be decrypted */
const storageMode = application.diskStorageService.domainKeyForMode(StorageValueModes.Default)
const valueStore = application.diskStorageService.values[storageMode]
expect(valueStore.content_type).to.not.be.ok
expect(await application.deviceInterface.getRawStorageValue('offlineParams')).to.not.be.ok
const keyParams = await application.diskStorageService.getValue(StorageKey.RootKeyParams, StorageValueModes.Nonwrapped)
expect(typeof keyParams).to.equal('object')
/** Embedded value should match */
const migratedKeyParams = await application.diskStorageService.getValue(
StorageKey.RootKeyParams,
StorageValueModes.Nonwrapped,
)
expect(migratedKeyParams).to.eql(JSON.parse(embeddedStorage.auth_params))
const rootKey = await application.protocolService.getRootKey()
expect(rootKey.masterKey).to.equal(accountKey.masterKey)
expect(rootKey.dataAuthenticationKey).to.equal(accountKey.dataAuthenticationKey)
/** Application should not retain server password from legacy versions */
expect(rootKey.serverPassword).to.not.be.ok
expect(rootKey.keyVersion).to.equal(ProtocolVersion.V003)
expect(application.protocolService.rootKeyEncryption.keyMode).to.equal(KeyMode.RootKeyPlusWrapper)
/** Expect note is decrypted */
expect(application.itemManager.getDisplayableNotes().length).to.equal(1)
const retrievedNote = application.itemManager.getDisplayableNotes()[0]
expect(retrievedNote.uuid).to.equal(notePayload.uuid)
expect(retrievedNote.content.text).to.equal(notePayload.content.text)
/** Ensure arbitrary values have been migrated */
for (const key of Object.keys(arbitraryValues)) {
const value = await application.diskStorageService.getValue(key)
expect(arbitraryValues[key]).to.equal(value)
}
console.warn('Expecting exception due to deiniting application while trying to renew session')
await Factory.safeDeinit(application)
}).timeout(15000)
it('2020-01-15 migration with passcode only', async function () {
const application = await Factory.createAppWithRandNamespace()
/** Create legacy migrations value so that base migration detects old app */
await application.deviceInterface.setRawStorageValue('migrations', JSON.stringify(['anything']))
const operator003 = new SNProtocolOperator003(new FakeWebCrypto())
const identifier = 'foo'
const passcode = 'bar'
/** Create old version passcode parameters */
const passcodeKey = await operator003.createRootKey(identifier, passcode)
await application.deviceInterface.setRawStorageValue(
'offlineParams',
JSON.stringify(passcodeKey.keyParams.getPortableValue()),
)
/** Create arbitrary storage values and make sure they're migrated */
const arbitraryValues = {
foo: 'bar',
zar: 'tar',
har: 'car',
}
for (const key of Object.keys(arbitraryValues)) {
await application.deviceInterface.setRawStorageValue(key, arbitraryValues[key])
}
const embeddedStorage = {
...arbitraryValues,
}
const storagePayload = new DecryptedPayload({
uuid: await operator003.crypto.generateUUID(),
content: {
storage: embeddedStorage,
},
content_type: ContentType.EncryptedStorage,
})
const encryptionParams = await operator003.generateEncryptedParametersAsync(storagePayload, passcodeKey)
const persistPayload = new EncryptedPayload({ ...storagePayload, ...encryptionParams })
await application.deviceInterface.setRawStorageValue('encryptedStorage', JSON.stringify(persistPayload))
/** Create encrypted item and store it in db */
const notePayload = Factory.createNotePayload()
const noteEncryptionParams = await operator003.generateEncryptedParametersAsync(notePayload, passcodeKey)
const noteEncryptedPayload = new EncryptedPayload({ ...notePayload, ...noteEncryptionParams })
await application.deviceInterface.saveRawDatabasePayload(noteEncryptedPayload, application.identifier)
await application.prepareForLaunch({
receiveChallenge: async (challenge) => {
application.submitValuesForChallenge(challenge, [CreateChallengeValue(challenge.prompts[0], passcode)])
},
})
await application.launch(true)
expect(application.protocolService.rootKeyEncryption.keyMode).to.equal(KeyMode.WrapperOnly)
/** Should be decrypted */
const storageMode = application.diskStorageService.domainKeyForMode(StorageValueModes.Default)
const valueStore = application.diskStorageService.values[storageMode]
expect(valueStore.content_type).to.not.be.ok
expect(await application.deviceInterface.getRawStorageValue('offlineParams')).to.not.be.ok
/** Embedded value should match */
const migratedKeyParams = await application.diskStorageService.getValue(
StorageKey.RootKeyParams,
StorageValueModes.Nonwrapped,
)
expect(migratedKeyParams).to.eql(embeddedStorage.auth_params)
const rootKey = await application.protocolService.getRootKey()
expect(rootKey.masterKey).to.equal(passcodeKey.masterKey)
expect(rootKey.dataAuthenticationKey).to.equal(passcodeKey.dataAuthenticationKey)
/** Root key is in memory with passcode only, so server password can be defined */
expect(rootKey.serverPassword).to.be.ok
expect(rootKey.keyVersion).to.equal(ProtocolVersion.V003)
expect(application.protocolService.rootKeyEncryption.keyMode).to.equal(KeyMode.WrapperOnly)
/** Expect note is decrypted */
expect(application.itemManager.getDisplayableNotes().length).to.equal(1)
const retrievedNote = application.itemManager.getDisplayableNotes()[0]
expect(retrievedNote.uuid).to.equal(notePayload.uuid)
expect(retrievedNote.content.text).to.equal(notePayload.content.text)
/** Ensure arbitrary values have been migrated */
for (const key of Object.keys(arbitraryValues)) {
const value = await application.diskStorageService.getValue(key)
expect(arbitraryValues[key]).to.equal(value)
}
await Factory.safeDeinit(application)
})
/**
* This test will pass but sync afterwards will not be successful
* as we are using a random value for the legacy session token
*/
it('2020-01-15 migration with account only', async function () {
const application = await Factory.createAppWithRandNamespace()
/** Create legacy migrations value so that base migration detects old app */
await application.deviceInterface.setRawStorageValue('migrations', JSON.stringify(['anything']))
const operator003 = new SNProtocolOperator003(new FakeWebCrypto())
const identifier = 'foo'
/** Create old version account parameters */
const password = 'tar'
const accountKey = await operator003.createRootKey(identifier, password)
/** Create arbitrary storage values and make sure they're migrated */
const storage = {
foo: 'bar',
zar: 'tar',
har: 'car',
mk: accountKey.masterKey,
ak: accountKey.dataAuthenticationKey,
pw: accountKey.serverPassword,
jwt: 'anything',
/** Legacy versions would store json strings inside of embedded storage */
auth_params: JSON.stringify(accountKey.keyParams.getPortableValue()),
}
for (const key of Object.keys(storage)) {
await application.deviceInterface.setRawStorageValue(key, storage[key])
}
/** Create encrypted item and store it in db */
const notePayload = Factory.createNotePayload()
const noteEncryptionParams = await operator003.generateEncryptedParametersAsync(notePayload, accountKey)
const noteEncryptedPayload = new EncryptedPayload({ ...notePayload, ...noteEncryptionParams })
await application.deviceInterface.saveRawDatabasePayload(noteEncryptedPayload, application.identifier)
/** Run migration */
const promptValueReply = (prompts) => {
const values = []
for (const prompt of prompts) {
if (prompt.validation === ChallengeValidation.LocalPasscode) {
values.push(CreateChallengeValue(prompt, passcode))
} else {
/** We will be prompted to reauthetnicate our session, not relevant to this test
* but pass any value to avoid exception
*/
values.push(CreateChallengeValue(prompt, 'foo'))
}
}
return values
}
const receiveChallenge = async (challenge) => {
application.addChallengeObserver(challenge, {
onInvalidValue: (value) => {
const values = promptValueReply([value.prompt])
application.submitValuesForChallenge(challenge, values)
},
})
const initialValues = promptValueReply(challenge.prompts)
application.submitValuesForChallenge(challenge, initialValues)
}
await application.prepareForLaunch({
receiveChallenge: receiveChallenge,
})
await application.launch(true)
expect(application.sessionManager.online()).to.equal(true)
expect(application.protocolService.rootKeyEncryption.keyMode).to.equal(KeyMode.RootKeyOnly)
/** Should be decrypted */
const storageMode = application.diskStorageService.domainKeyForMode(StorageValueModes.Default)
const valueStore = application.diskStorageService.values[storageMode]
expect(valueStore.content_type).to.not.be.ok
/** Embedded value should match */
const migratedKeyParams = await application.diskStorageService.getValue(
StorageKey.RootKeyParams,
StorageValueModes.Nonwrapped,
)
expect(migratedKeyParams).to.eql(accountKey.keyParams.getPortableValue())
const rootKey = await application.protocolService.getRootKey()
expect(rootKey).to.be.ok
expect(await application.deviceInterface.getRawStorageValue('migrations')).to.not.be.ok
expect(await application.deviceInterface.getRawStorageValue('auth_params')).to.not.be.ok
expect(await application.deviceInterface.getRawStorageValue('jwt')).to.not.be.ok
const keyParams = await application.diskStorageService.getValue(StorageKey.RootKeyParams, StorageValueModes.Nonwrapped)
expect(typeof keyParams).to.equal('object')
expect(rootKey.masterKey).to.equal(accountKey.masterKey)
expect(rootKey.dataAuthenticationKey).to.equal(accountKey.dataAuthenticationKey)
expect(rootKey.serverPassword).to.not.be.ok
expect(rootKey.keyVersion).to.equal(ProtocolVersion.V003)
expect(application.protocolService.rootKeyEncryption.keyMode).to.equal(KeyMode.RootKeyOnly)
/** Expect note is decrypted */
expect(application.itemManager.getDisplayableNotes().length).to.equal(1)
const retrievedNote = application.itemManager.getDisplayableNotes()[0]
expect(retrievedNote.uuid).to.equal(notePayload.uuid)
expect(retrievedNote.content.text).to.equal(notePayload.content.text)
/** Ensure arbitrary values have been migrated */
for (const key of Object.keys(storage)) {
/** Is stringified in storage, but parsed in storageService */
if (key === 'auth_params') {
continue
}
const value = await application.diskStorageService.getValue(key)
expect(storage[key]).to.equal(value)
}
console.warn('Expecting exception due to deiniting application while trying to renew session')
await Factory.safeDeinit(application)
})
it('2020-01-15 migration with no account and no passcode', async function () {
const application = await Factory.createAppWithRandNamespace()
/** Create legacy migrations value so that base migration detects old app */
await application.deviceInterface.setRawStorageValue('migrations', JSON.stringify(['anything']))
/** Create arbitrary storage values and make sure they're migrated */
const storage = {
foo: 'bar',
zar: 'tar',
har: 'car',
}
for (const key of Object.keys(storage)) {
await application.deviceInterface.setRawStorageValue(key, storage[key])
}
/** Create item and store it in db */
const notePayload = Factory.createNotePayload()
await application.deviceInterface.saveRawDatabasePayload(notePayload.ejected(), application.identifier)
/** Run migration */
await application.prepareForLaunch({
receiveChallenge: (_challenge) => {
return null
},
})
await application.launch(true)
expect(application.protocolService.rootKeyEncryption.keyMode).to.equal(KeyMode.RootKeyNone)
/** Should be decrypted */
const storageMode = application.diskStorageService.domainKeyForMode(StorageValueModes.Default)
const valueStore = application.diskStorageService.values[storageMode]
expect(valueStore.content_type).to.not.be.ok
const rootKey = await application.protocolService.getRootKey()
expect(rootKey).to.not.be.ok
expect(application.protocolService.rootKeyEncryption.keyMode).to.equal(KeyMode.RootKeyNone)
expect(await application.deviceInterface.getRawStorageValue('migrations')).to.not.be.ok
/** Expect note is decrypted */
expect(application.itemManager.getDisplayableNotes().length).to.equal(1)
const retrievedNote = application.itemManager.getDisplayableNotes()[0]
expect(retrievedNote.uuid).to.equal(notePayload.uuid)
expect(retrievedNote.content.text).to.equal(notePayload.content.text)
/** Ensure arbitrary values have been migrated */
for (const key of Object.keys(storage)) {
const value = await application.diskStorageService.getValue(key)
expect(storage[key]).to.equal(value)
}
await Factory.safeDeinit(application)
})
/**
* This test will pass but sync afterwards will not be successful
* as we are using a random value for the legacy session token
*/
it('2020-01-15 migration from app v1.0.1 with account only', async function () {
const application = await Factory.createAppWithRandNamespace()
/** Create legacy migrations value so that base migration detects old app */
await application.deviceInterface.setRawStorageValue('migrations', JSON.stringify(['anything']))
const operator001 = new SNProtocolOperator001(new FakeWebCrypto())
const identifier = 'foo'
/** Create old version account parameters */
const password = 'tar'
const accountKey = await operator001.createRootKey(identifier, password)
/** Create arbitrary storage values and make sure they're migrated */
const storage = {
mk: accountKey.masterKey,
pw: accountKey.serverPassword,
jwt: 'anything',
/** Legacy versions would store json strings inside of embedded storage */
auth_params: JSON.stringify(accountKey.keyParams.getPortableValue()),
user: JSON.stringify({ uuid: 'anything', email: 'anything' }),
}
for (const key of Object.keys(storage)) {
await application.deviceInterface.setRawStorageValue(key, storage[key])
}
/** Create encrypted item and store it in db */
const notePayload = Factory.createNotePayload()
const noteEncryptionParams = await operator001.generateEncryptedParametersAsync(notePayload, accountKey)
const noteEncryptedPayload = new EncryptedPayload({ ...notePayload, ...noteEncryptionParams })
await application.deviceInterface.saveRawDatabasePayload(noteEncryptedPayload, application.identifier)
/** Run migration */
const promptValueReply = (prompts) => {
const values = []
for (const prompt of prompts) {
/** We will be prompted to reauthetnicate our session, not relevant to this test
* but pass any value to avoid exception
*/
values.push(CreateChallengeValue(prompt, 'foo'))
}
return values
}
const receiveChallenge = async (challenge) => {
application.addChallengeObserver(challenge, {
onInvalidValue: (value) => {
const values = promptValueReply([value.prompt])
application.submitValuesForChallenge(challenge, values)
},
})
const initialValues = promptValueReply(challenge.prompts)
application.submitValuesForChallenge(challenge, initialValues)
}
await application.prepareForLaunch({
receiveChallenge: receiveChallenge,
})
await application.launch(true)
expect(application.sessionManager.online()).to.equal(true)
expect(application.sessionManager.getUser()).to.be.ok
expect(application.protocolService.rootKeyEncryption.keyMode).to.equal(KeyMode.RootKeyOnly)
/** Should be decrypted */
const storageMode = application.diskStorageService.domainKeyForMode(StorageValueModes.Default)
const valueStore = application.diskStorageService.values[storageMode]
expect(valueStore.content_type).to.not.be.ok
/** Embedded value should match */
const migratedKeyParams = await application.diskStorageService.getValue(
StorageKey.RootKeyParams,
StorageValueModes.Nonwrapped,
)
expect(migratedKeyParams).to.eql(accountKey.keyParams.getPortableValue())
const rootKey = await application.protocolService.getRootKey()
expect(rootKey).to.be.ok
expect(await application.deviceInterface.getRawStorageValue('migrations')).to.not.be.ok
expect(await application.deviceInterface.getRawStorageValue('auth_params')).to.not.be.ok
expect(await application.deviceInterface.getRawStorageValue('jwt')).to.not.be.ok
expect(await application.deviceInterface.getRawStorageValue('ak')).to.not.be.ok
expect(await application.deviceInterface.getRawStorageValue('mk')).to.not.be.ok
expect(await application.deviceInterface.getRawStorageValue('pw')).to.not.be.ok
const keyParams = await application.diskStorageService.getValue(StorageKey.RootKeyParams, StorageValueModes.Nonwrapped)
expect(typeof keyParams).to.equal('object')
expect(rootKey.masterKey).to.equal(accountKey.masterKey)
expect(rootKey.dataAuthenticationKey).to.equal(accountKey.dataAuthenticationKey)
expect(rootKey.serverPassword).to.not.be.ok
expect(rootKey.keyVersion).to.equal(ProtocolVersion.V001)
expect(application.protocolService.rootKeyEncryption.keyMode).to.equal(KeyMode.RootKeyOnly)
/** Expect note is decrypted */
expect(application.itemManager.getDisplayableNotes().length).to.equal(1)
const retrievedNote = application.itemManager.getDisplayableNotes()[0]
expect(retrievedNote.uuid).to.equal(notePayload.uuid)
expect(retrievedNote.content.text).to.equal(notePayload.content.text)
/** Ensure arbitrary values have been migrated */
for (const key of Object.keys(storage)) {
/** Is stringified in storage, but parsed in storageService */
const value = await application.diskStorageService.getValue(key)
if (key === 'auth_params') {
continue
} else if (key === 'user') {
expect(storage[key]).to.equal(JSON.stringify(value))
} else {
expect(storage[key]).to.equal(value)
}
}
await Factory.safeDeinit(application)
})
it('2020-01-15 migration from 002 app with account and passcode but missing offlineParams.version', async function () {
/**
* There was an issue where if the user had offlineParams but it was missing the version key,
* the user could not get past the passcode migration screen.
*/
const application = await Factory.createAppWithRandNamespace()
/** Create legacy migrations value so that base migration detects old app */
await application.deviceInterface.setRawStorageValue('migrations', JSON.stringify(['anything']))
const operator002 = new SNProtocolOperator002(new FakeWebCrypto())
const identifier = 'foo'
const passcode = 'bar'
/** Create old version passcode parameters */
const passcodeKey = await operator002.createRootKey(identifier, passcode)
/** The primary chaos agent */
const offlineParams = passcodeKey.keyParams.getPortableValue()
omitInPlace(offlineParams, ['version'])
await application.deviceInterface.setRawStorageValue('offlineParams', JSON.stringify(offlineParams))
/** Create old version account parameters */
const password = 'tar'
const accountKey = await operator002.createRootKey(identifier, password)
/** Create legacy storage and encrypt it with passcode */
const embeddedStorage = {
mk: accountKey.masterKey,
ak: accountKey.dataAuthenticationKey,
pw: accountKey.serverPassword,
jwt: 'anything',
/** Legacy versions would store json strings inside of embedded storage */
auth_params: JSON.stringify(accountKey.keyParams.getPortableValue()),
user: JSON.stringify({ uuid: 'anything', email: 'anything' }),
}
const storagePayload = new DecryptedPayload({
uuid: await operator002.crypto.generateUUID(),
content_type: ContentType.EncryptedStorage,
content: {
storage: embeddedStorage,
},
})
const encryptionParams = await operator002.generateEncryptedParametersAsync(storagePayload, passcodeKey)
const persistPayload = new EncryptedPayload({ ...storagePayload, ...encryptionParams })
await application.deviceInterface.setRawStorageValue('encryptedStorage', JSON.stringify(persistPayload))
/** Create encrypted item and store it in db */
const notePayload = Factory.createNotePayload()
const noteEncryptionParams = await operator002.generateEncryptedParametersAsync(notePayload, accountKey)
const noteEncryptedPayload = new EncryptedPayload({ ...notePayload, ...noteEncryptionParams })
await application.deviceInterface.saveRawDatabasePayload(noteEncryptedPayload, application.identifier)
/** Runs migration */
await application.prepareForLaunch({
receiveChallenge: async (challenge) => {
application.submitValuesForChallenge(challenge, [CreateChallengeValue(challenge.prompts[0], passcode)])
},
})
await application.launch(true)
expect(application.sessionManager.online()).to.equal(true)
expect(application.sessionManager.getUser()).to.be.ok
expect(application.protocolService.rootKeyEncryption.keyMode).to.equal(KeyMode.RootKeyPlusWrapper)
/** Should be decrypted */
const storageMode = application.diskStorageService.domainKeyForMode(StorageValueModes.Default)
const valueStore = application.diskStorageService.values[storageMode]
expect(valueStore.content_type).to.not.be.ok
/** Embedded value should match */
const migratedKeyParams = await application.diskStorageService.getValue(
StorageKey.RootKeyParams,
StorageValueModes.Nonwrapped,
)
expect(migratedKeyParams).to.eql(accountKey.keyParams.getPortableValue())
const rootKey = await application.protocolService.getRootKey()
expect(rootKey).to.be.ok
expect(await application.deviceInterface.getRawStorageValue('migrations')).to.not.be.ok
expect(await application.deviceInterface.getRawStorageValue('auth_params')).to.not.be.ok
expect(await application.deviceInterface.getRawStorageValue('jwt')).to.not.be.ok
expect(await application.deviceInterface.getRawStorageValue('ak')).to.not.be.ok
expect(await application.deviceInterface.getRawStorageValue('mk')).to.not.be.ok
expect(await application.deviceInterface.getRawStorageValue('pw')).to.not.be.ok
const keyParams = await application.diskStorageService.getValue(StorageKey.RootKeyParams, StorageValueModes.Nonwrapped)
expect(typeof keyParams).to.equal('object')
expect(rootKey.masterKey).to.equal(accountKey.masterKey)
expect(rootKey.dataAuthenticationKey).to.equal(accountKey.dataAuthenticationKey)
expect(rootKey.serverPassword).to.not.be.ok
expect(rootKey.keyVersion).to.equal(ProtocolVersion.V002)
/** Expect note is decrypted */
expect(application.itemManager.getDisplayableNotes().length).to.equal(1)
const retrievedNote = application.itemManager.getDisplayableNotes()[0]
expect(retrievedNote.uuid).to.equal(notePayload.uuid)
expect(retrievedNote.content.text).to.equal(notePayload.content.text)
await Factory.safeDeinit(application)
})
})