snapshot of https://github.com/ueberdosis/hocuspocus.git @ cf3cfa355b4d3bb61c6b6c80071f71783e32470e (2026-09-15)
Some checks failed
build / lint (22) (push) Failing after 17s
build / test (22) (push) Failing after 8s
build / lint (23) (push) Failing after 2s
build / build (22) (push) Has been skipped
build / build (23) (push) Has been skipped
build / test (23) (push) Failing after 4s
docsearch / docsearch (push) Failing after 1s
Some checks failed
build / lint (22) (push) Failing after 17s
build / test (22) (push) Failing after 8s
build / lint (23) (push) Failing after 2s
build / build (22) (push) Has been skipped
build / build (23) (push) Has been skipped
build / test (23) (push) Failing after 4s
docsearch / docsearch (push) Failing after 1s
This commit is contained in:
187
tests/provider/hasUnsyncedChanges.ts
Normal file
187
tests/provider/hasUnsyncedChanges.ts
Normal file
@@ -0,0 +1,187 @@
|
||||
import test from 'ava'
|
||||
import * as Y from 'yjs'
|
||||
import { retryableAssertion } from '../utils/retryableAssertion.ts'
|
||||
import { newHocuspocus, newHocuspocusProvider, sleep } from '../utils/index.ts'
|
||||
|
||||
test("initially doesn't have unsynced changes", async t => {
|
||||
return new Promise(async resolve => {
|
||||
|
||||
const server = await newHocuspocus(t)
|
||||
|
||||
const provider = newHocuspocusProvider(t, server)
|
||||
|
||||
t.is(provider.hasUnsyncedChanges, false)
|
||||
t.is(provider.synced, false)
|
||||
|
||||
setTimeout(() => {
|
||||
t.is(provider.hasUnsyncedChanges, false)
|
||||
t.is(provider.synced, true)
|
||||
|
||||
resolve()
|
||||
}, 200)
|
||||
})
|
||||
})
|
||||
|
||||
test('has unsynced changes when updating', async t => {
|
||||
const server = await newHocuspocus(t)
|
||||
|
||||
const provider = newHocuspocusProvider(t, server, {
|
||||
awareness: undefined,
|
||||
})
|
||||
|
||||
provider.document.getMap('test').set('foo', 'bar')
|
||||
t.is(provider.hasUnsyncedChanges, true)
|
||||
|
||||
// changes are synced
|
||||
await retryableAssertion(t, tt => {
|
||||
tt.is(provider.hasUnsyncedChanges, false)
|
||||
})
|
||||
})
|
||||
|
||||
test('has unsynced changes when in readonly mode', async t => {
|
||||
const server = await newHocuspocus(t, {
|
||||
async onAuthenticate({ connectionConfig }) {
|
||||
connectionConfig.readOnly = true
|
||||
},
|
||||
})
|
||||
|
||||
const provider = newHocuspocusProvider(t, server, { token: 'readonly' })
|
||||
|
||||
provider.document.getMap('test').set('foo', 'bar')
|
||||
|
||||
await retryableAssertion(t, tt => {
|
||||
tt.is(provider.hasUnsyncedChanges, true)
|
||||
})
|
||||
|
||||
await sleep(100)
|
||||
|
||||
// confirm that the changes are not synced later either
|
||||
t.is(provider.hasUnsyncedChanges, true)
|
||||
})
|
||||
|
||||
test('has no unsynced changes when in readonly mode and no changes', async t => {
|
||||
const server = await newHocuspocus(t, {
|
||||
async onAuthenticate({ connectionConfig }) {
|
||||
connectionConfig.readOnly = true
|
||||
},
|
||||
})
|
||||
|
||||
const provider = newHocuspocusProvider(t, server, { token: 'readonly' })
|
||||
|
||||
// first, unsyncedChanges is briefly set to true when we're waiting for the ack of the initial sync
|
||||
await new Promise((resolve, reject) => {
|
||||
provider.on('unsyncedChanges', () => {
|
||||
provider.off('unsyncedChanges')
|
||||
if (provider.hasUnsyncedChanges) {
|
||||
resolve('done')
|
||||
} else {
|
||||
reject()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// then, it should be set to false when the sync message is confirmed
|
||||
await retryableAssertion(t, tt => {
|
||||
tt.is(provider.hasUnsyncedChanges, false)
|
||||
})
|
||||
})
|
||||
|
||||
test('has unsynced changes when in readonly mode and receiving external update', async t => {
|
||||
const server = await newHocuspocus(t, {
|
||||
async onAuthenticate({ connectionConfig, token }) {
|
||||
if (token === 'readonly') {
|
||||
connectionConfig.readOnly = true
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const provider = newHocuspocusProvider(t, server, {
|
||||
token: 'readonly',
|
||||
})
|
||||
|
||||
provider.document.getMap('test').set('foo', 'bar')
|
||||
|
||||
t.is(provider.hasUnsyncedChanges, true)
|
||||
|
||||
await sleep(100)
|
||||
|
||||
t.is(provider.hasUnsyncedChanges, true)
|
||||
|
||||
const provider2 = newHocuspocusProvider(t, server, {
|
||||
token: 'full-access',
|
||||
})
|
||||
|
||||
provider2.document.getMap('test2').set('foo', 'bar')
|
||||
|
||||
t.is(provider2.hasUnsyncedChanges, true)
|
||||
|
||||
await retryableAssertion(t, tt => {
|
||||
tt.is(provider2.hasUnsyncedChanges, false)
|
||||
})
|
||||
|
||||
t.is(provider.hasUnsyncedChanges, true)
|
||||
})
|
||||
|
||||
test('has unsynced changes when in readonly mode and initial document has changed', async t => {
|
||||
const server = await newHocuspocus(t, {
|
||||
async onAuthenticate({ connectionConfig }) {
|
||||
connectionConfig.readOnly = true
|
||||
},
|
||||
})
|
||||
|
||||
const document = new Y.Doc()
|
||||
document.getMap('test').set('foo', 'bar')
|
||||
|
||||
const provider = newHocuspocusProvider(t, server, { document, token: 'readonly' })
|
||||
|
||||
await retryableAssertion(t, tt => {
|
||||
tt.is(provider.hasUnsyncedChanges, true)
|
||||
})
|
||||
|
||||
await sleep(100)
|
||||
|
||||
t.is(provider.hasUnsyncedChanges, true)
|
||||
})
|
||||
|
||||
test('has unsynced changes when in readonly mode and initial document has changed (deletion)', async t => {
|
||||
const document = new Y.Doc()
|
||||
document.getMap('test').set('foo', 'bar')
|
||||
const initialState = Y.encodeStateAsUpdate(document)
|
||||
|
||||
const server = await newHocuspocus(t, {
|
||||
async onLoadDocument() {
|
||||
return initialState
|
||||
},
|
||||
async onAuthenticate({ connectionConfig }) {
|
||||
connectionConfig.readOnly = true
|
||||
},
|
||||
})
|
||||
|
||||
document.getMap('test').delete('foo')
|
||||
|
||||
const provider = newHocuspocusProvider(t, server, { document, token: 'readonly' })
|
||||
|
||||
await retryableAssertion(t, tt => {
|
||||
tt.is(provider.hasUnsyncedChanges, true)
|
||||
})
|
||||
|
||||
await sleep(100)
|
||||
|
||||
t.is(provider.hasUnsyncedChanges, true)
|
||||
})
|
||||
|
||||
test('has no unsynced changes when in readonly mode and initial document has not changed', async t => {
|
||||
const server = await newHocuspocus(t, {
|
||||
async onAuthenticate({ connectionConfig }) {
|
||||
connectionConfig.readOnly = true
|
||||
},
|
||||
})
|
||||
|
||||
const document = new Y.Doc()
|
||||
|
||||
const provider = newHocuspocusProvider(t, server, { document, token: 'readonly' })
|
||||
|
||||
await sleep(200)
|
||||
|
||||
t.is(provider.hasUnsyncedChanges, false)
|
||||
})
|
||||
Reference in New Issue
Block a user