test: share workspace skill test helpers

This commit is contained in:
Peter Steinberger
2026-03-14 02:33:47 +00:00
parent 6ad675c1e9
commit 3bc9d9177d
2 changed files with 53 additions and 59 deletions

View File

@@ -25,6 +25,33 @@ async function createCaseDir(prefix: string): Promise<string> {
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");

View File

@@ -49,6 +49,16 @@ const withClearedEnv = <T>(
}
};
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),