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
276 lines
7.0 KiB
TypeScript
276 lines
7.0 KiB
TypeScript
import test from "ava";
|
|
import { newHocuspocus, newHocuspocusProvider } from "../utils/index.ts";
|
|
import { retryableAssertion } from "../utils/retryableAssertion.ts";
|
|
|
|
test("executes the onDestroy hook and has the instance", async (t) => {
|
|
await new Promise(async (resolve) => {
|
|
const hocuspocus = await newHocuspocus(t, {
|
|
async onDestroy({ instance }) {
|
|
t.is(instance, hocuspocus);
|
|
|
|
resolve("done");
|
|
},
|
|
});
|
|
|
|
await hocuspocus.server!.destroy();
|
|
});
|
|
});
|
|
|
|
test("destroy works if no document is open", async (t) => {
|
|
await new Promise(async (resolve) => {
|
|
const hocuspocus = await newHocuspocus(t);
|
|
|
|
await hocuspocus.server!.destroy();
|
|
|
|
t.pass();
|
|
resolve("");
|
|
});
|
|
});
|
|
|
|
test("executes the onDestroy hook from a custom extension", async (t) => {
|
|
await new Promise(async (resolve) => {
|
|
class CustomExtension {
|
|
async onDestroy() {
|
|
t.pass();
|
|
|
|
resolve("done");
|
|
}
|
|
}
|
|
|
|
const hocuspocus = await newHocuspocus(t, {
|
|
extensions: [new CustomExtension()],
|
|
});
|
|
|
|
await hocuspocus.server!.destroy();
|
|
});
|
|
});
|
|
|
|
test("destroy closes all connections", async (t) => {
|
|
await new Promise(async (resolve) => {
|
|
const hocuspocus = await newHocuspocus(t);
|
|
|
|
const provider1 = newHocuspocusProvider(t, hocuspocus);
|
|
|
|
await retryableAssertion(t, (t2) => t2.is(provider1.synced, true));
|
|
|
|
t.is(hocuspocus.getConnectionsCount(), 1);
|
|
t.is(hocuspocus.getDocumentsCount(), 1);
|
|
|
|
await hocuspocus.server!.destroy();
|
|
|
|
t.is(hocuspocus.getConnectionsCount(), 0);
|
|
t.is(hocuspocus.getDocumentsCount(), 0);
|
|
|
|
resolve("");
|
|
});
|
|
});
|
|
|
|
test("destroy does not call onStoreDocument if nothing debounced", async (t) => {
|
|
await new Promise(async (resolve) => {
|
|
const server = await newHocuspocus(t, {
|
|
async onStoreDocument() {
|
|
t.fail();
|
|
},
|
|
});
|
|
|
|
const provider = newHocuspocusProvider(t, server);
|
|
|
|
await retryableAssertion(t, (t2) => t2.is(provider.synced, true));
|
|
|
|
await server.server!.destroy();
|
|
|
|
resolve("");
|
|
});
|
|
});
|
|
|
|
test("destroy does not call onStoreDocument after debounced onStoreDocument executes", async (t) => {
|
|
await new Promise(async (resolve) => {
|
|
let called = 0;
|
|
|
|
const server = await newHocuspocus(t, {
|
|
debounce: 200,
|
|
unloadImmediately: true,
|
|
async onStoreDocument() {
|
|
called += 1;
|
|
},
|
|
});
|
|
|
|
const provider = newHocuspocusProvider(t, server, {
|
|
onSynced() {
|
|
// Dummy change to trigger onStoreDocument
|
|
provider.document.getArray("foo").push(["foo"]);
|
|
},
|
|
});
|
|
|
|
await retryableAssertion(t, (t2) => t2.is(provider.synced, true));
|
|
|
|
// Wait for the debounced onStoreDocument to execute
|
|
await new Promise((r) => setTimeout(r, 400));
|
|
|
|
await server.server!.destroy();
|
|
|
|
t.is(called, 1);
|
|
|
|
resolve("");
|
|
});
|
|
});
|
|
|
|
test("destroy calls onStoreDocument before returning if debounced", async (t) => {
|
|
await new Promise(async (resolve) => {
|
|
let called = false;
|
|
|
|
const hocuspocus = await newHocuspocus(t, {
|
|
async onStoreDocument() {
|
|
called = true;
|
|
},
|
|
});
|
|
|
|
const provider = newHocuspocusProvider(t, hocuspocus, {
|
|
onSynced() {
|
|
// Dummy change to trigger onStoreDocument
|
|
provider.document.getArray("foo").push(["foo"]);
|
|
},
|
|
});
|
|
|
|
const provider1 = newHocuspocusProvider(t, hocuspocus);
|
|
|
|
await retryableAssertion(t, (t2) => t2.is(provider1.synced, true));
|
|
|
|
t.is(called, false);
|
|
await hocuspocus.server!.destroy();
|
|
t.is(called, true);
|
|
|
|
resolve("");
|
|
});
|
|
});
|
|
|
|
test("destroy calls onStoreDocument before returning, even with unloadImmediately=false if debounced", async (t) => {
|
|
await new Promise(async (resolve) => {
|
|
let called = false;
|
|
|
|
const hocuspocus = await newHocuspocus(t, {
|
|
async onStoreDocument() {
|
|
called = true;
|
|
},
|
|
unloadImmediately: false,
|
|
});
|
|
|
|
const provider = newHocuspocusProvider(t, hocuspocus, {
|
|
onSynced() {
|
|
// Dummy change to trigger onStoreDocument
|
|
provider.document.getArray("foo").push(["foo"]);
|
|
},
|
|
});
|
|
|
|
const provider1 = newHocuspocusProvider(t, hocuspocus);
|
|
|
|
await retryableAssertion(t, (t2) => t2.is(provider1.synced, true));
|
|
await retryableAssertion(t, (t2) => t2.is(provider.synced, true));
|
|
|
|
t.is(called, false);
|
|
await hocuspocus.server!.destroy();
|
|
t.is(called, true);
|
|
|
|
resolve("");
|
|
});
|
|
});
|
|
|
|
test("destroy calls onStoreDocument before returning, even with unloadImmediately=false, with multiple docs if debounced", async (t) => {
|
|
await new Promise(async (resolve) => {
|
|
let called = 0;
|
|
|
|
const hocuspocus = await newHocuspocus(t, {
|
|
async onStoreDocument() {
|
|
called += 1;
|
|
},
|
|
unloadImmediately: false,
|
|
});
|
|
|
|
const provider1 = newHocuspocusProvider(t, hocuspocus, {
|
|
name: "test1",
|
|
onSynced() {
|
|
provider1.document.getArray("foo").push(["foo"]);
|
|
},
|
|
});
|
|
const provider2 = newHocuspocusProvider(t, hocuspocus, {
|
|
name: "test2",
|
|
onSynced() {
|
|
provider2.document.getArray("foo").push(["foo"]);
|
|
},
|
|
});
|
|
const provider3 = newHocuspocusProvider(t, hocuspocus, {
|
|
name: "test3",
|
|
onSynced() {
|
|
provider3.document.getArray("foo").push(["foo"]);
|
|
},
|
|
});
|
|
|
|
await retryableAssertion(t, (t2) => t2.is(provider1.synced, true));
|
|
await retryableAssertion(t, (t2) => t2.is(provider2.synced, true));
|
|
await retryableAssertion(t, (t2) => t2.is(provider3.synced, true));
|
|
|
|
// Wait for all changes to reach the server and trigger debounced stores
|
|
await retryableAssertion(t, (t2) => {
|
|
t2.true(hocuspocus.debouncer.isDebounced("onStoreDocument-test1"));
|
|
t2.true(hocuspocus.debouncer.isDebounced("onStoreDocument-test2"));
|
|
t2.true(hocuspocus.debouncer.isDebounced("onStoreDocument-test3"));
|
|
});
|
|
|
|
t.is(called, 0);
|
|
await hocuspocus.server!.destroy();
|
|
await retryableAssertion(t, (t2) => t2.is(called, 3));
|
|
|
|
resolve("");
|
|
});
|
|
});
|
|
|
|
test("destroy calls onStoreDocument before returning, with multiple docs if debounced", async (t) => {
|
|
await new Promise(async (resolve) => {
|
|
let called = 0;
|
|
|
|
const hocuspocus = await newHocuspocus(t, {
|
|
async onStoreDocument() {
|
|
called += 1;
|
|
},
|
|
unloadImmediately: true,
|
|
});
|
|
|
|
const provider1 = newHocuspocusProvider(t, hocuspocus, {
|
|
name: "test1",
|
|
onSynced() {
|
|
provider1.document.getArray("foo").push(["foo"]);
|
|
},
|
|
});
|
|
const provider2 = newHocuspocusProvider(t, hocuspocus, {
|
|
name: "test2",
|
|
onSynced() {
|
|
provider2.document.getArray("foo").push(["foo"]);
|
|
},
|
|
});
|
|
const provider3 = newHocuspocusProvider(t, hocuspocus, {
|
|
name: "test3",
|
|
onSynced() {
|
|
provider3.document.getArray("foo").push(["foo"]);
|
|
},
|
|
});
|
|
|
|
await retryableAssertion(t, (t2) => t2.is(provider1.synced, true));
|
|
await retryableAssertion(t, (t2) => t2.is(provider2.synced, true));
|
|
await retryableAssertion(t, (t2) => t2.is(provider3.synced, true));
|
|
|
|
// Wait for all changes to reach the server and trigger debounced stores
|
|
await retryableAssertion(t, (t2) => {
|
|
t2.true(hocuspocus.debouncer.isDebounced("onStoreDocument-test1"));
|
|
t2.true(hocuspocus.debouncer.isDebounced("onStoreDocument-test2"));
|
|
t2.true(hocuspocus.debouncer.isDebounced("onStoreDocument-test3"));
|
|
});
|
|
|
|
t.is(called, 0);
|
|
await hocuspocus.server!.destroy();
|
|
|
|
await retryableAssertion(t, (t2) => t2.is(called, 3));
|
|
|
|
resolve("");
|
|
});
|
|
});
|