test: share skill command workspace fixtures

This commit is contained in:
Peter Steinberger
2026-04-20 16:10:26 +01:00
parent c067c16360
commit c705720d87

View File

@@ -8,6 +8,49 @@ let listSkillCommandsForWorkspace: typeof import("./skill-commands.js").listSkil
let resolveSkillCommandInvocation: typeof import("./skill-commands.js").resolveSkillCommandInvocation;
let skillCommandsTesting: typeof import("./skill-commands.js").__testing;
const tempDirs: string[] = [];
async function makeTempDir(prefix: string) {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), prefix));
tempDirs.push(dir);
return dir;
}
async function createWorkspace(parentDir: string, name: string) {
const workspace = path.join(parentDir, name);
await fs.mkdir(workspace, { recursive: true });
return workspace;
}
async function createMainAndResearchWorkspaces(prefix: string) {
const baseDir = await makeTempDir(prefix);
const mainWorkspace = await createWorkspace(baseDir, "main");
const researchWorkspace = await createWorkspace(baseDir, "research");
return { mainWorkspace, researchWorkspace };
}
function listMainResearchSkillCommands(params: {
mainWorkspace: string;
researchWorkspace: string;
}) {
return listSkillCommandsForAgents({
cfg: {
agents: {
list: [
{ id: "main", workspace: params.mainWorkspace, skills: ["demo-skill"] },
{ id: "research", workspace: params.researchWorkspace, skills: ["extra-skill"] },
],
},
},
agentIds: ["main", "research"],
});
}
function expectDemoAndExtraSkillCommands(commands: ReturnType<typeof listSkillCommandsForAgents>) {
expect(commands.map((entry) => entry.skillName)).toEqual(["demo-skill", "extra-skill"]);
expect(commands.map((entry) => entry.name)).toEqual(["demo_skill", "extra_skill"]);
}
function resolveUniqueSkillCommandName(base: string, used: Set<string>): string {
let name = base;
let suffix = 2;
@@ -101,6 +144,10 @@ beforeAll(async () => {
} = await import("./skill-commands.js"));
});
afterAll(async () => {
await Promise.all(tempDirs.splice(0).map((dir) => fs.rm(dir, { recursive: true, force: true })));
});
beforeEach(() => {
vi.clearAllMocks();
});
@@ -143,24 +190,9 @@ describe("resolveSkillCommandInvocation", () => {
});
describe("listSkillCommandsForAgents", () => {
const tempDirs: string[] = [];
const makeTempDir = async (prefix: string) => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), prefix));
tempDirs.push(dir);
return dir;
};
afterAll(async () => {
await Promise.all(
tempDirs.splice(0).map((dir) => fs.rm(dir, { recursive: true, force: true })),
);
});
it("deduplicates by skillName across agents, keeping the first registration", async () => {
const baseDir = await makeTempDir("openclaw-skills-");
const mainWorkspace = path.join(baseDir, "main");
const researchWorkspace = path.join(baseDir, "research");
await fs.mkdir(mainWorkspace, { recursive: true });
await fs.mkdir(researchWorkspace, { recursive: true });
const { mainWorkspace, researchWorkspace } =
await createMainAndResearchWorkspaces("openclaw-skills-");
const commands = listSkillCommandsForAgents({
cfg: {
@@ -180,8 +212,7 @@ describe("listSkillCommandsForAgents", () => {
it("scopes to specific agents when agentIds is provided", async () => {
const baseDir = await makeTempDir("openclaw-skills-filter-");
const researchWorkspace = path.join(baseDir, "research");
await fs.mkdir(researchWorkspace, { recursive: true });
const researchWorkspace = await createWorkspace(baseDir, "research");
const commands = listSkillCommandsForAgents({
cfg: {
@@ -197,53 +228,29 @@ describe("listSkillCommandsForAgents", () => {
});
it("prevents cross-agent skill leakage when each agent has an allowlist", async () => {
const baseDir = await makeTempDir("openclaw-skills-leak-");
const mainWorkspace = path.join(baseDir, "main");
const researchWorkspace = path.join(baseDir, "research");
await fs.mkdir(mainWorkspace, { recursive: true });
await fs.mkdir(researchWorkspace, { recursive: true });
const { mainWorkspace, researchWorkspace } =
await createMainAndResearchWorkspaces("openclaw-skills-leak-");
const commands = listSkillCommandsForAgents({
cfg: {
agents: {
list: [
{ id: "main", workspace: mainWorkspace, skills: ["demo-skill"] },
{ id: "research", workspace: researchWorkspace, skills: ["extra-skill"] },
],
},
},
agentIds: ["main", "research"],
});
const commands = listMainResearchSkillCommands({ mainWorkspace, researchWorkspace });
expect(commands.map((entry) => entry.skillName)).toEqual(["demo-skill", "extra-skill"]);
expect(commands.map((entry) => entry.name)).toEqual(["demo_skill", "extra_skill"]);
expectDemoAndExtraSkillCommands(commands);
});
it("merges allowlists for agents that share one workspace", async () => {
const baseDir = await makeTempDir("openclaw-skills-shared-");
const sharedWorkspace = path.join(baseDir, "research");
await fs.mkdir(sharedWorkspace, { recursive: true });
const sharedWorkspace = await createWorkspace(baseDir, "research");
const commands = listSkillCommandsForAgents({
cfg: {
agents: {
list: [
{ id: "main", workspace: sharedWorkspace, skills: ["demo-skill"] },
{ id: "research", workspace: sharedWorkspace, skills: ["extra-skill"] },
],
},
},
agentIds: ["main", "research"],
const commands = listMainResearchSkillCommands({
mainWorkspace: sharedWorkspace,
researchWorkspace: sharedWorkspace,
});
expect(commands.map((entry) => entry.skillName)).toEqual(["demo-skill", "extra-skill"]);
expect(commands.map((entry) => entry.name)).toEqual(["demo_skill", "extra_skill"]);
expectDemoAndExtraSkillCommands(commands);
});
it("deduplicates overlapping allowlists for shared workspace", async () => {
const baseDir = await makeTempDir("openclaw-skills-overlap-");
const sharedWorkspace = path.join(baseDir, "research");
await fs.mkdir(sharedWorkspace, { recursive: true });
const sharedWorkspace = await createWorkspace(baseDir, "research");
const commands = listSkillCommandsForAgents({
cfg: {
@@ -264,8 +271,7 @@ describe("listSkillCommandsForAgents", () => {
it("keeps workspace unrestricted when one co-tenant agent has no skills filter", async () => {
const baseDir = await makeTempDir("openclaw-skills-unfiltered-");
const sharedWorkspace = path.join(baseDir, "research");
await fs.mkdir(sharedWorkspace, { recursive: true });
const sharedWorkspace = await createWorkspace(baseDir, "research");
const commands = listSkillCommandsForAgents({
cfg: {
@@ -286,8 +292,7 @@ describe("listSkillCommandsForAgents", () => {
it("merges empty allowlist with non-empty allowlist for shared workspace", async () => {
const baseDir = await makeTempDir("openclaw-skills-empty-");
const sharedWorkspace = path.join(baseDir, "research");
await fs.mkdir(sharedWorkspace, { recursive: true });
const sharedWorkspace = await createWorkspace(baseDir, "research");
const commands = listSkillCommandsForAgents({
cfg: {
@@ -306,8 +311,7 @@ describe("listSkillCommandsForAgents", () => {
it("uses inherited defaults for agents that share one workspace", async () => {
const baseDir = await makeTempDir("openclaw-skills-defaults-");
const sharedWorkspace = path.join(baseDir, "shared-defaults");
await fs.mkdir(sharedWorkspace, { recursive: true });
const sharedWorkspace = await createWorkspace(baseDir, "shared-defaults");
const commands = listSkillCommandsForAgents({
cfg: {
@@ -330,8 +334,7 @@ describe("listSkillCommandsForAgents", () => {
it("does not inherit defaults when an agent sets an explicit empty skills list", async () => {
const baseDir = await makeTempDir("openclaw-skills-defaults-empty-");
const sharedWorkspace = path.join(baseDir, "shared-defaults");
await fs.mkdir(sharedWorkspace, { recursive: true });
const sharedWorkspace = await createWorkspace(baseDir, "shared-defaults");
const commands = listSkillCommandsForAgents({
cfg: {
@@ -353,9 +356,8 @@ describe("listSkillCommandsForAgents", () => {
it("skips agents with missing workspaces gracefully", async () => {
const baseDir = await makeTempDir("openclaw-skills-missing-");
const validWorkspace = path.join(baseDir, "research");
const validWorkspace = await createWorkspace(baseDir, "research");
const missingWorkspace = path.join(baseDir, "nonexistent");
await fs.mkdir(validWorkspace, { recursive: true });
const commands = listSkillCommandsForAgents({
cfg: {
@@ -376,22 +378,9 @@ describe("listSkillCommandsForAgents", () => {
});
describe("listSkillCommandsForWorkspace", () => {
const tempDirs: string[] = [];
const makeTempDir = async (prefix: string) => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), prefix));
tempDirs.push(dir);
return dir;
};
afterAll(async () => {
await Promise.all(
tempDirs.splice(0).map((dir) => fs.rm(dir, { recursive: true, force: true })),
);
});
it("inherits defaults when agentId is provided without an explicit skill filter", async () => {
const baseDir = await makeTempDir("openclaw-skills-workspace-defaults-");
const sharedWorkspace = path.join(baseDir, "shared-defaults");
await fs.mkdir(sharedWorkspace, { recursive: true });
const sharedWorkspace = await createWorkspace(baseDir, "shared-defaults");
const commands = listSkillCommandsForWorkspace({
workspaceDir: sharedWorkspace,