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:
6
tests/utils/_force-exit.ts
Normal file
6
tests/utils/_force-exit.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import process from "node:process";
|
||||
import { registerCompletionHandler } from "ava";
|
||||
|
||||
registerCompletionHandler(() => {
|
||||
process.exit(); // eslint-disable-line
|
||||
});
|
||||
9
tests/utils/createDirectory.ts
Normal file
9
tests/utils/createDirectory.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import fs from 'fs'
|
||||
|
||||
export const createDirectory = (dir: string) => {
|
||||
try {
|
||||
fs.mkdir(dir, () => {})
|
||||
} catch {
|
||||
//
|
||||
}
|
||||
}
|
||||
13
tests/utils/flushRedis.ts
Normal file
13
tests/utils/flushRedis.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
// @ts-expect-error
|
||||
import { createClient } from 'redis'
|
||||
import { redisConnectionSettings } from './redisConnectionSettings.ts'
|
||||
|
||||
export const flushRedis = async () => {
|
||||
const client = createClient({
|
||||
url: `redis://${redisConnectionSettings.host}:${redisConnectionSettings.port}`,
|
||||
})
|
||||
|
||||
await client.connect()
|
||||
|
||||
return client.flushDb()
|
||||
}
|
||||
9
tests/utils/index.ts
Normal file
9
tests/utils/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export * from './createDirectory.ts'
|
||||
export * from './flushRedis.ts'
|
||||
export * from './newHocuspocus.ts'
|
||||
export * from './newHocuspocusProvider.ts'
|
||||
export * from './newHocuspocusProviderWebsocket.ts'
|
||||
export * from './randomInteger.ts'
|
||||
export * from './redisConnectionSettings.ts'
|
||||
export * from './removeDirectory.ts'
|
||||
export * from './sleep.ts'
|
||||
35
tests/utils/newHocuspocus.ts
Normal file
35
tests/utils/newHocuspocus.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import type { ExecutionContext } from "ava";
|
||||
import type { ServerConfiguration } from "@hocuspocus/server";
|
||||
import { Server } from "@hocuspocus/server";
|
||||
|
||||
export const newHocuspocus = (
|
||||
t: ExecutionContext,
|
||||
options?: Partial<ServerConfiguration>,
|
||||
) => {
|
||||
const server = new Server({
|
||||
// We don't need the logging in testing.
|
||||
quiet: true,
|
||||
// Binding something port 0 will end up on a random free port.
|
||||
// That's helpful to run tests concurrently.
|
||||
port: 0,
|
||||
// Ava 6+ considers process.exit() in workers an error.
|
||||
// Disable signal handlers to prevent that.
|
||||
stopOnSignals: false,
|
||||
// Add or overwrite settings, depending on the test case.
|
||||
...options,
|
||||
});
|
||||
|
||||
t.teardown(() => {
|
||||
// Close WebSocket connections and shut down the HTTP server.
|
||||
// We avoid calling server.destroy() because it triggers lifecycle
|
||||
// hooks (onDestroy, afterUnloadDocument) which could run assertions
|
||||
// after the test has finished (Ava 6+ treats this as an error).
|
||||
// The _force-exit completion handler ensures the process exits
|
||||
// even if some handles remain open.
|
||||
server.hocuspocus.closeConnections();
|
||||
server.httpServer.closeAllConnections();
|
||||
server.httpServer.close();
|
||||
});
|
||||
|
||||
return server.listen();
|
||||
};
|
||||
32
tests/utils/newHocuspocusProvider.ts
Normal file
32
tests/utils/newHocuspocusProvider.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import type { ExecutionContext } from "ava";
|
||||
import {
|
||||
HocuspocusProvider,
|
||||
type HocuspocusProviderConfiguration,
|
||||
type HocuspocusProviderWebsocket,
|
||||
type HocuspocusProviderWebsocketConfiguration,
|
||||
} from "@hocuspocus/provider";
|
||||
import type { Hocuspocus } from "@hocuspocus/server";
|
||||
import { newHocuspocusProviderWebsocket } from "./newHocuspocusProviderWebsocket.ts";
|
||||
|
||||
export const newHocuspocusProvider = (
|
||||
t: ExecutionContext,
|
||||
server: Hocuspocus,
|
||||
options: Partial<HocuspocusProviderConfiguration> = {},
|
||||
websocketOptions: Partial<HocuspocusProviderWebsocketConfiguration> = {},
|
||||
websocketProvider?: HocuspocusProviderWebsocket,
|
||||
): HocuspocusProvider => {
|
||||
const provider = new HocuspocusProvider({
|
||||
websocketProvider:
|
||||
websocketProvider ??
|
||||
newHocuspocusProviderWebsocket(t, server, websocketOptions),
|
||||
// Just use a generic document name for all tests.
|
||||
name: "hocuspocus-test",
|
||||
// Add or overwrite settings, depending on the test case.
|
||||
...options,
|
||||
});
|
||||
provider.attach();
|
||||
|
||||
t.teardown(() => provider.destroy());
|
||||
|
||||
return provider;
|
||||
};
|
||||
22
tests/utils/newHocuspocusProviderWebsocket.ts
Normal file
22
tests/utils/newHocuspocusProviderWebsocket.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import type { ExecutionContext } from "ava";
|
||||
import type { HocuspocusProviderWebsocketConfiguration } from "@hocuspocus/provider";
|
||||
import { HocuspocusProviderWebsocket } from "@hocuspocus/provider";
|
||||
import type { Hocuspocus } from "@hocuspocus/server";
|
||||
|
||||
export const newHocuspocusProviderWebsocket = (
|
||||
t: ExecutionContext,
|
||||
hocuspocus: Hocuspocus,
|
||||
options: Partial<Omit<HocuspocusProviderWebsocketConfiguration, "url">> = {},
|
||||
) => {
|
||||
const ws = new HocuspocusProviderWebsocket({
|
||||
// We don't need which port the server is running on, but
|
||||
// we can get the URL from the passed server instance.
|
||||
url: hocuspocus.server!.webSocketURL,
|
||||
// Node.js 22+ has native WebSocket support
|
||||
...options,
|
||||
});
|
||||
|
||||
t.teardown(() => ws.destroy());
|
||||
|
||||
return ws;
|
||||
};
|
||||
3
tests/utils/randomInteger.ts
Normal file
3
tests/utils/randomInteger.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export const randomInteger = (min: number, max: number) => {
|
||||
return Math.floor(Math.random() * (max - min + 1) + min)
|
||||
}
|
||||
4
tests/utils/redisConnectionSettings.ts
Normal file
4
tests/utils/redisConnectionSettings.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export const redisConnectionSettings = {
|
||||
host: process.env.REDIS_HOST || '127.0.0.1',
|
||||
port: Number.parseInt(process.env.REDIS_PORT || '', 10) || 6379,
|
||||
}
|
||||
27
tests/utils/removeDirectory.ts
Normal file
27
tests/utils/removeDirectory.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
export const removeDirectory = (dir: string) => {
|
||||
try {
|
||||
const list = fs.readdirSync(dir)
|
||||
|
||||
for (let i = 0; i < list.length; i += 1) {
|
||||
const filename = path.join(dir, list[i])
|
||||
const stat = fs.statSync(filename)
|
||||
|
||||
if (filename === '.' || filename === '..') {
|
||||
// pass these files
|
||||
} else if (stat.isDirectory()) {
|
||||
// rmdir recursively
|
||||
removeDirectory(filename)
|
||||
} else {
|
||||
// rm fiilename
|
||||
fs.unlinkSync(filename)
|
||||
}
|
||||
}
|
||||
|
||||
fs.rmdirSync(dir)
|
||||
} catch {
|
||||
//
|
||||
}
|
||||
}
|
||||
18
tests/utils/retryableAssertion.ts
Normal file
18
tests/utils/retryableAssertion.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import type { ExecutionContext } from 'ava'
|
||||
import { sleep } from './sleep.ts'
|
||||
|
||||
/* eslint-disable no-await-in-loop */
|
||||
export const retryableAssertion = async (t: ExecutionContext, recoverableTry: (tt: ExecutionContext) => void) => {
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (true) {
|
||||
const lastTry = await t.try(recoverableTry)
|
||||
|
||||
if (lastTry.passed) {
|
||||
lastTry.commit()
|
||||
break
|
||||
}
|
||||
lastTry.discard()
|
||||
|
||||
await sleep(100)
|
||||
}
|
||||
}
|
||||
5
tests/utils/sleep.ts
Normal file
5
tests/utils/sleep.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export const sleep = (time: number) => {
|
||||
return new Promise(async resolve => {
|
||||
setTimeout(resolve, time)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user