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) })