UNPKG

winterspec

Version:

Write Winter-CG compatible routes with filesystem routing and tons of features

85 lines (84 loc) 3.16 kB
import path from "node:path"; import hash from "object-hash"; import getPort from "@ava/get-port"; import { registerSharedWorker } from "ava/plugin"; import { devServer } from "../../dev/dev.js"; import { loadConfig } from "../../config/index.js"; import { fileURLToPath } from "node:url"; import { once } from "node:events"; const getWorker = async (initialData) => { const key = hash(initialData); const dirname = path.dirname(fileURLToPath(import.meta.url)); const filename = new URL(`file:${path.resolve(dirname, "worker-wrapper.ts")}#${key}`); if (process.env.IS_TESTING_EDGESPEC) { const { registerSharedTypeScriptWorker } = await import("ava-typescript-worker"); const normalizedCrossPlatformFilePath = process.platform === "win32" ? { ...filename, pathname: filename.pathname.replace("/", "") } : filename; return registerSharedTypeScriptWorker({ filename: normalizedCrossPlatformFilePath, initialData: initialData, }); } return registerSharedWorker({ filename, initialData: initialData, supportedProtocols: ["ava-4"], }); }; /** * Start a test dev server for AVA. This works in watch mode too! * Check out the [docs](https://github.com/tscircuit/winterspec/blob/main/docs/testing.md) for more information. * * @param t test context from AVA */ export const getTestServer = async (t, options) => { const rootDirectory = options?.rootDirectory ?? process.cwd(); const worker = await getWorker({ rootDirectory, }); const [port] = await Promise.all([getPort(), worker.available]); let httpServerRpcCallback; const onReceivedBuildResult = (build) => { if (build.type === "failure") { console.error(build.errorMessage); t.fail("Failed to build"); } }; const serverFixture = await devServer.headless.startServer({ port, config: await loadConfig(rootDirectory), rpcChannel: { post: (data) => worker.publish(data), on: (data) => { httpServerRpcCallback = data; }, }, middleware: options?.middleware ?? [], onBuildEnd(build) { onReceivedBuildResult(build); }, }); const messageHandlerAbortController = new AbortController(); const messageHandlerPromise = Promise.race([ once(messageHandlerAbortController.signal, "abort"), (async () => { for await (const msg of worker.subscribe()) { httpServerRpcCallback(msg.data); if (messageHandlerAbortController.signal.aborted) { break; } } })(), ]); t.teardown(async () => { messageHandlerAbortController.abort(); await messageHandlerPromise; await serverFixture.stop(); }); // Calling .getBuildResult() here handles the case where the build is already ready but the build errored and we need to log & cancel the test onReceivedBuildResult(await serverFixture.getBuildResult()); return { port, }; };