From 3bc9d9177d1677df601f1f93e550513b16ddc589 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 14 Mar 2026 02:33:47 +0000 Subject: [PATCH] test: share workspace skill test helpers --- ...erged-skills-into-target-workspace.test.ts | 78 ++++++++++--------- src/agents/skills.test.ts | 34 ++++---- 2 files changed, 53 insertions(+), 59 deletions(-) diff --git a/src/agents/skills.build-workspace-skills-prompt.syncs-merged-skills-into-target-workspace.test.ts b/src/agents/skills.build-workspace-skills-prompt.syncs-merged-skills-into-target-workspace.test.ts index 0ee8a39a0b0..1f4da5163e1 100644 --- a/src/agents/skills.build-workspace-skills-prompt.syncs-merged-skills-into-target-workspace.test.ts +++ b/src/agents/skills.build-workspace-skills-prompt.syncs-merged-skills-into-target-workspace.test.ts @@ -25,6 +25,33 @@ async function createCaseDir(prefix: string): Promise { return dir; } +async function syncSourceSkillsToTarget(sourceWorkspace: string, targetWorkspace: string) { + await withEnv({ HOME: sourceWorkspace, PATH: "" }, () => + syncSkillsToWorkspace({ + sourceWorkspaceDir: sourceWorkspace, + targetWorkspaceDir: targetWorkspace, + bundledSkillsDir: path.join(sourceWorkspace, ".bundled"), + managedSkillsDir: path.join(sourceWorkspace, ".managed"), + }), + ); +} + +async function expectSyncedSkillConfinement(params: { + sourceWorkspace: string; + targetWorkspace: string; + safeSkillDirName: string; + escapedDest: string; +}) { + expect(await pathExists(params.escapedDest)).toBe(false); + await syncSourceSkillsToTarget(params.sourceWorkspace, params.targetWorkspace); + expect( + await pathExists( + path.join(params.targetWorkspace, "skills", params.safeSkillDirName, "SKILL.md"), + ), + ).toBe(true); + expect(await pathExists(params.escapedDest)).toBe(false); +} + beforeAll(async () => { fixtureRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-skills-sync-suite-")); syncSourceTemplateDir = await createCaseDir("source-template"); @@ -115,14 +142,7 @@ describe("buildWorkspaceSkillsPrompt", () => { "dir", ); - await withEnv({ HOME: sourceWorkspace, PATH: "" }, () => - syncSkillsToWorkspace({ - sourceWorkspaceDir: sourceWorkspace, - targetWorkspaceDir: targetWorkspace, - bundledSkillsDir: path.join(sourceWorkspace, ".bundled"), - managedSkillsDir: path.join(sourceWorkspace, ".managed"), - }), - ); + await syncSourceSkillsToTarget(sourceWorkspace, targetWorkspace); const prompt = buildPrompt(targetWorkspace, { bundledSkillsDir: path.join(targetWorkspace, ".bundled"), @@ -151,21 +171,12 @@ describe("buildWorkspaceSkillsPrompt", () => { expect(path.relative(path.join(targetWorkspace, "skills"), escapedDest).startsWith("..")).toBe( true, ); - expect(await pathExists(escapedDest)).toBe(false); - - await withEnv({ HOME: sourceWorkspace, PATH: "" }, () => - syncSkillsToWorkspace({ - sourceWorkspaceDir: sourceWorkspace, - targetWorkspaceDir: targetWorkspace, - bundledSkillsDir: path.join(sourceWorkspace, ".bundled"), - managedSkillsDir: path.join(sourceWorkspace, ".managed"), - }), - ); - - expect( - await pathExists(path.join(targetWorkspace, "skills", "safe-traversal-skill", "SKILL.md")), - ).toBe(true); - expect(await pathExists(escapedDest)).toBe(false); + await expectSyncedSkillConfinement({ + sourceWorkspace, + targetWorkspace, + safeSkillDirName: "safe-traversal-skill", + escapedDest, + }); }); it("keeps synced skills confined under target workspace when frontmatter name is absolute", async () => { const sourceWorkspace = await createCaseDir("source"); @@ -180,21 +191,12 @@ describe("buildWorkspaceSkillsPrompt", () => { description: "Absolute skill", }); - expect(await pathExists(absoluteDest)).toBe(false); - - await withEnv({ HOME: sourceWorkspace, PATH: "" }, () => - syncSkillsToWorkspace({ - sourceWorkspaceDir: sourceWorkspace, - targetWorkspaceDir: targetWorkspace, - bundledSkillsDir: path.join(sourceWorkspace, ".bundled"), - managedSkillsDir: path.join(sourceWorkspace, ".managed"), - }), - ); - - expect( - await pathExists(path.join(targetWorkspace, "skills", "safe-absolute-skill", "SKILL.md")), - ).toBe(true); - expect(await pathExists(absoluteDest)).toBe(false); + await expectSyncedSkillConfinement({ + sourceWorkspace, + targetWorkspace, + safeSkillDirName: "safe-absolute-skill", + escapedDest: absoluteDest, + }); }); it("filters skills based on env/config gates", async () => { const workspaceDir = await createCaseDir("workspace"); diff --git a/src/agents/skills.test.ts b/src/agents/skills.test.ts index 394f476ffa8..c5c8c2077d9 100644 --- a/src/agents/skills.test.ts +++ b/src/agents/skills.test.ts @@ -49,6 +49,16 @@ const withClearedEnv = ( } }; +async function writeEnvSkill(workspaceDir: string) { + const skillDir = path.join(workspaceDir, "skills", "env-skill"); + await writeSkill({ + dir: skillDir, + name: "env-skill", + description: "Needs env", + metadata: '{"openclaw":{"requires":{"env":["ENV_KEY"]},"primaryEnv":"ENV_KEY"}}', + }); +} + beforeAll(async () => { await fixtureSuite.setup(); tempHome = await createTempHomeEnv("openclaw-skills-home-"); @@ -240,13 +250,7 @@ describe("buildWorkspaceSkillsPrompt", () => { describe("applySkillEnvOverrides", () => { it("sets and restores env vars", async () => { const workspaceDir = await makeWorkspace(); - const skillDir = path.join(workspaceDir, "skills", "env-skill"); - await writeSkill({ - dir: skillDir, - name: "env-skill", - description: "Needs env", - metadata: '{"openclaw":{"requires":{"env":["ENV_KEY"]},"primaryEnv":"ENV_KEY"}}', - }); + await writeEnvSkill(workspaceDir); const entries = loadWorkspaceSkillEntries(workspaceDir, resolveTestSkillDirs(workspaceDir)); @@ -269,13 +273,7 @@ describe("applySkillEnvOverrides", () => { it("keeps env keys tracked until all overlapping overrides restore", async () => { const workspaceDir = await makeWorkspace(); - const skillDir = path.join(workspaceDir, "skills", "env-skill"); - await writeSkill({ - dir: skillDir, - name: "env-skill", - description: "Needs env", - metadata: '{"openclaw":{"requires":{"env":["ENV_KEY"]},"primaryEnv":"ENV_KEY"}}', - }); + await writeEnvSkill(workspaceDir); const entries = loadWorkspaceSkillEntries(workspaceDir, resolveTestSkillDirs(workspaceDir)); @@ -301,13 +299,7 @@ describe("applySkillEnvOverrides", () => { it("applies env overrides from snapshots", async () => { const workspaceDir = await makeWorkspace(); - const skillDir = path.join(workspaceDir, "skills", "env-skill"); - await writeSkill({ - dir: skillDir, - name: "env-skill", - description: "Needs env", - metadata: '{"openclaw":{"requires":{"env":["ENV_KEY"]},"primaryEnv":"ENV_KEY"}}', - }); + await writeEnvSkill(workspaceDir); const snapshot = buildWorkspaceSkillSnapshot(workspaceDir, { ...resolveTestSkillDirs(workspaceDir),