From 861e23b02c0b479f761f82632da069083cb5f584 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 19 Apr 2026 00:31:48 +0100 Subject: [PATCH] test: share config surface loader fixture --- .../load-channel-config-surface.test.ts | 181 ++++++------------ 1 file changed, 60 insertions(+), 121 deletions(-) diff --git a/src/config/load-channel-config-surface.test.ts b/src/config/load-channel-config-surface.test.ts index dd77594b388..a3ac1f1f3e0 100644 --- a/src/config/load-channel-config-surface.test.ts +++ b/src/config/load-channel-config-surface.test.ts @@ -59,31 +59,50 @@ async function importLoaderWithFailingJitiAndWorkingBun() { } } +function expectedOkSchema(type: string) { + return { + schema: { + type: "object", + properties: { + ok: { type }, + }, + }, + }; +} + +function createDemoConfigSchemaModule(repoRoot: string, sourceLines?: string[]) { + const packageRoot = path.join(repoRoot, "extensions", "demo"); + const modulePath = path.join(packageRoot, "src", "config-schema.js"); + + fs.mkdirSync(path.join(packageRoot, "src"), { recursive: true }); + fs.writeFileSync( + path.join(packageRoot, "package.json"), + JSON.stringify({ name: "@openclaw/demo", type: "module" }, null, 2), + "utf8", + ); + fs.writeFileSync( + modulePath, + [ + ...(sourceLines ?? [ + "export const DemoChannelConfigSchema = {", + " schema: {", + " type: 'object',", + " properties: { ok: { type: 'string' } },", + " },", + "};", + ]), + "", + ].join("\n"), + "utf8", + ); + + return { packageRoot, modulePath }; +} + describe("loadChannelConfigSurfaceModule", () => { it("prefers the source-aware loader over bun when both succeed", async () => { await withTempDir({ prefix: "openclaw-config-surface-" }, async (repoRoot) => { - const packageRoot = path.join(repoRoot, "extensions", "demo"); - const modulePath = path.join(packageRoot, "src", "config-schema.js"); - - fs.mkdirSync(path.join(packageRoot, "src"), { recursive: true }); - fs.writeFileSync( - path.join(packageRoot, "package.json"), - JSON.stringify({ name: "@openclaw/demo", type: "module" }, null, 2), - "utf8", - ); - fs.writeFileSync( - modulePath, - [ - "export const DemoChannelConfigSchema = {", - " schema: {", - " type: 'object',", - " properties: { ok: { type: 'string' } },", - " },", - "};", - "", - ].join("\n"), - "utf8", - ); + const { modulePath } = createDemoConfigSchemaModule(repoRoot); const spawnSync = vi.fn(() => ({ error: undefined, @@ -107,14 +126,7 @@ describe("loadChannelConfigSurfaceModule", () => { await expect( imported.loadChannelConfigSurfaceModule(modulePath, { repoRoot }), - ).resolves.toMatchObject({ - schema: { - type: "object", - properties: { - ok: { type: "string" }, - }, - }, - }); + ).resolves.toMatchObject(expectedOkSchema("string")); expect(spawnSync).not.toHaveBeenCalled(); } finally { vi.doUnmock("node:child_process"); @@ -124,68 +136,21 @@ describe("loadChannelConfigSurfaceModule", () => { it("does not require bun when the source-aware loader succeeds", async () => { await withTempDir({ prefix: "openclaw-config-surface-" }, async (repoRoot) => { - const packageRoot = path.join(repoRoot, "extensions", "demo"); - const modulePath = path.join(packageRoot, "src", "config-schema.js"); - - fs.mkdirSync(path.join(packageRoot, "src"), { recursive: true }); - fs.writeFileSync( - path.join(packageRoot, "package.json"), - JSON.stringify({ name: "@openclaw/demo", type: "module" }, null, 2), - "utf8", - ); - fs.writeFileSync( - modulePath, - [ - "export const DemoChannelConfigSchema = {", - " schema: {", - " type: 'object',", - " properties: { ok: { type: 'string' } },", - " },", - "};", - "", - ].join("\n"), - "utf8", - ); + const { modulePath } = createDemoConfigSchemaModule(repoRoot); const { loadChannelConfigSurfaceModule: loadWithMissingBun, spawnSync } = await importLoaderWithMissingBun(); - await expect(loadWithMissingBun(modulePath, { repoRoot })).resolves.toMatchObject({ - schema: { - type: "object", - properties: { - ok: { type: "string" }, - }, - }, - }); + await expect(loadWithMissingBun(modulePath, { repoRoot })).resolves.toMatchObject( + expectedOkSchema("string"), + ); expect(spawnSync).not.toHaveBeenCalled(); }); }); it("falls back to bun when the source-aware loader fails", async () => { await withTempDir({ prefix: "openclaw-config-surface-" }, async (repoRoot) => { - const packageRoot = path.join(repoRoot, "extensions", "demo"); - const modulePath = path.join(packageRoot, "src", "config-schema.js"); - - fs.mkdirSync(path.join(packageRoot, "src"), { recursive: true }); - fs.writeFileSync( - path.join(packageRoot, "package.json"), - JSON.stringify({ name: "@openclaw/demo", type: "module" }, null, 2), - "utf8", - ); - fs.writeFileSync( - modulePath, - [ - "export const DemoChannelConfigSchema = {", - " schema: {", - " type: 'object',", - " properties: { ok: { type: 'string' } },", - " },", - "};", - "", - ].join("\n"), - "utf8", - ); + const { modulePath } = createDemoConfigSchemaModule(repoRoot); const { loadChannelConfigSurfaceModule: loadWithFailingJiti, @@ -193,14 +158,9 @@ describe("loadChannelConfigSurfaceModule", () => { createJiti, } = await importLoaderWithFailingJitiAndWorkingBun(); - await expect(loadWithFailingJiti(modulePath, { repoRoot })).resolves.toMatchObject({ - schema: { - type: "object", - properties: { - ok: { type: "number" }, - }, - }, - }); + await expect(loadWithFailingJiti(modulePath, { repoRoot })).resolves.toMatchObject( + expectedOkSchema("number"), + ); expect(createJiti).toHaveBeenCalled(); expect(spawnSync).toHaveBeenCalledWith("bun", expect.any(Array), expect.any(Object)); }); @@ -208,29 +168,15 @@ describe("loadChannelConfigSurfaceModule", () => { it("retries from an isolated package copy when extension-local node_modules is broken", async () => { await withTempDir({ prefix: "openclaw-config-surface-" }, async (repoRoot) => { - const packageRoot = path.join(repoRoot, "extensions", "demo"); - const modulePath = path.join(packageRoot, "src", "config-schema.js"); - - fs.mkdirSync(path.join(packageRoot, "src"), { recursive: true }); - fs.writeFileSync( - path.join(packageRoot, "package.json"), - JSON.stringify({ name: "@openclaw/demo", type: "module" }, null, 2), - "utf8", - ); - fs.writeFileSync( - modulePath, - [ - "import { z } from 'zod';", - "export const DemoChannelConfigSchema = {", - " schema: {", - " type: 'object',", - " properties: { ok: { type: z.object({}).shape ? 'string' : 'string' } },", - " },", - "};", - "", - ].join("\n"), - "utf8", - ); + const { packageRoot, modulePath } = createDemoConfigSchemaModule(repoRoot, [ + "import { z } from 'zod';", + "export const DemoChannelConfigSchema = {", + " schema: {", + " type: 'object',", + " properties: { ok: { type: z.object({}).shape ? 'string' : 'string' } },", + " },", + "};", + ]); fs.mkdirSync(path.join(repoRoot, "node_modules", "zod"), { recursive: true }); fs.writeFileSync( @@ -265,14 +211,7 @@ describe("loadChannelConfigSurfaceModule", () => { ); await expect(loadChannelConfigSurfaceModule(modulePath, { repoRoot })).resolves.toMatchObject( - { - schema: { - type: "object", - properties: { - ok: { type: "string" }, - }, - }, - }, + expectedOkSchema("string"), ); }); });