


























@@ -107,6 +107,40 @@ const {
107107 runtimeErrors,
108108} = mocks;
109109110+function mockCall(mock: unknown, index = 0): Array<unknown> {
111+const calls = (mock as { mock?: { calls?: Array<Array<unknown>> } }).mock?.calls ?? [];
112+const call = calls.at(index);
113+expect(call, `mock call ${index + 1}`).toBeDefined();
114+return call as Array<unknown>;
115+}
116+117+function mockFirstObjectArg(mock: unknown): Record<string, unknown> {
118+const [arg] = mockCall(mock);
119+expect(arg).toBeTypeOf("object");
120+expect(arg).not.toBeNull();
121+return arg as Record<string, unknown>;
122+}
123+124+function expectObjectFields(value: unknown, expected: Record<string, unknown>): void {
125+expect(value).toBeTypeOf("object");
126+expect(value).not.toBeNull();
127+const record = value as Record<string, unknown>;
128+for (const [key, expectedValue] of Object.entries(expected)) {
129+expect(record[key], key).toEqual(expectedValue);
130+}
131+}
132+133+function expectLogger(value: unknown): void {
134+expect(value).toBeTypeOf("object");
135+expect(value).not.toBeNull();
136+}
137+138+function expectStatusWorkspaceCall(workspaceDir: string): void {
139+const [actualWorkspaceDir, options] = mockCall(buildWorkspaceSkillStatusMock);
140+expect(actualWorkspaceDir).toBe(workspaceDir);
141+expectObjectFields(options, { config: {} });
142+}
143+110144vi.mock("../runtime.js", () => ({
111145defaultRuntime: mocks.defaultRuntime,
112146}));
@@ -220,9 +254,10 @@ describe("skills cli commands", () => {
220254query: "calendar",
221255limit: undefined,
222256});
223-expect(runtimeLogs).toEqual(
224-expect.arrayContaining([expect.stringContaining("calendar v1.2.3 Calendar")]),
225-);
257+expect(
258+runtimeLogs.some((line) => line.includes("calendar v1.2.3 Calendar")),
259+"search result log",
260+).toBe(true);
226261});
227262228263it("installs a skill from ClawHub into the active workspace", async () => {
@@ -235,13 +270,14 @@ describe("skills cli commands", () => {
235270236271await runCommand(["skills", "install", "calendar", "--version", "1.2.3"]);
237272238-expect(installSkillFromClawHubMock).toHaveBeenCalledWith({
273+const installArgs = mockFirstObjectArg(installSkillFromClawHubMock);
274+expectObjectFields(installArgs, {
239275workspaceDir: "/tmp/workspace",
240276slug: "calendar",
241277version: "1.2.3",
242278force: false,
243-logger: expect.any(Object),
244279});
280+expectLogger(installArgs.logger);
245281expect(
246282runtimeLogs.some((line) =>
247283line.includes("Installed calendar@1.2.3 -> /tmp/workspace/skills/calendar"),
@@ -267,10 +303,8 @@ describe("skills cli commands", () => {
267303{},
268304"/tmp/workspace-writer/project",
269305);
270-expect(installSkillFromClawHubMock).toHaveBeenCalledWith(
271-expect.objectContaining({
272-workspaceDir: "/tmp/workspace-writer",
273-}),
306+expect(mockFirstObjectArg(installSkillFromClawHubMock).workspaceDir).toBe(
307+"/tmp/workspace-writer",
274308);
275309});
276310@@ -290,10 +324,8 @@ describe("skills cli commands", () => {
290324291325expect(resolveAgentIdByWorkspacePathMock).not.toHaveBeenCalled();
292326expect(resolveAgentWorkspaceDirMock).toHaveBeenCalledWith({}, "main");
293-expect(installSkillFromClawHubMock).toHaveBeenCalledWith(
294-expect.objectContaining({
295-workspaceDir: "/tmp/workspace-main",
296-}),
327+expect(mockFirstObjectArg(installSkillFromClawHubMock).workspaceDir).toBe(
328+"/tmp/workspace-main",
297329);
298330});
299331@@ -309,10 +341,8 @@ describe("skills cli commands", () => {
309341await runCommand(["skills", "--agent", "writer", "install", "calendar"]);
310342311343expect(resolveAgentWorkspaceDirMock).toHaveBeenCalledWith({}, "writer");
312-expect(installSkillFromClawHubMock).toHaveBeenCalledWith(
313-expect.objectContaining({
314-workspaceDir: "/tmp/workspace-writer",
315-}),
344+expect(mockFirstObjectArg(installSkillFromClawHubMock).workspaceDir).toBe(
345+"/tmp/workspace-writer",
316346);
317347});
318348@@ -332,14 +362,16 @@ describe("skills cli commands", () => {
332362await runCommand(["skills", "update", "--all"]);
333363334364expect(readTrackedClawHubSkillSlugsMock).toHaveBeenCalledWith("/tmp/workspace");
335-expect(updateSkillsFromClawHubMock).toHaveBeenCalledWith({
365+const updateAllArgs = mockFirstObjectArg(updateSkillsFromClawHubMock);
366+expectObjectFields(updateAllArgs, {
336367workspaceDir: "/tmp/workspace",
337368slug: undefined,
338-logger: expect.any(Object),
339369});
340-expect(runtimeLogs).toEqual(
341-expect.arrayContaining([expect.stringContaining("Updated calendar: 1.2.2 -> 1.2.3")]),
342-);
370+expectLogger(updateAllArgs.logger);
371+expect(
372+runtimeLogs.some((line) => line.includes("Updated calendar: 1.2.2 -> 1.2.3")),
373+"update result log",
374+).toBe(true);
343375expect(runtimeErrors).toStrictEqual([]);
344376});
345377@@ -363,11 +395,12 @@ describe("skills cli commands", () => {
363395});
364396365397expect(readTrackedClawHubSkillSlugsMock).toHaveBeenCalledWith("/tmp/workspace-writer");
366-expect(updateSkillsFromClawHubMock).toHaveBeenCalledWith({
398+const updateInferredArgs = mockFirstObjectArg(updateSkillsFromClawHubMock);
399+expectObjectFields(updateInferredArgs, {
367400workspaceDir: "/tmp/workspace-writer",
368401slug: undefined,
369-logger: expect.any(Object),
370402});
403+expectLogger(updateInferredArgs.logger);
371404});
372405373406it("lets --agent override cwd-inferred workspace for updates", async () => {
@@ -390,11 +423,12 @@ describe("skills cli commands", () => {
390423});
391424392425expect(resolveAgentIdByWorkspacePathMock).not.toHaveBeenCalled();
393-expect(updateSkillsFromClawHubMock).toHaveBeenCalledWith({
426+const updateOverrideArgs = mockFirstObjectArg(updateSkillsFromClawHubMock);
427+expectObjectFields(updateOverrideArgs, {
394428workspaceDir: "/tmp/workspace-main",
395429slug: "calendar",
396-logger: expect.any(Object),
397430});
431+expectLogger(updateOverrideArgs.logger);
398432});
399433400434it.each([
@@ -419,7 +453,7 @@ describe("skills cli commands", () => {
419453label: "check",
420454argv: ["skills", "check", "--json"],
421455assert: (payload: Record<string, unknown>) => {
422-expect(payload.summary).toMatchObject({
456+expectObjectFields(payload.summary, {
423457total: 1,
424458eligible: 1,
425459});
@@ -428,10 +462,7 @@ describe("skills cli commands", () => {
428462])("routes skills $label JSON output through stdout", async ({ argv, assert }) => {
429463await runCommand(argv);
430464431-expect(buildWorkspaceSkillStatusMock).toHaveBeenCalledWith(
432-"/tmp/workspace",
433-expect.objectContaining({ config: {} }),
434-);
465+expectStatusWorkspaceCall("/tmp/workspace");
435466expect(
436467defaultRuntime.writeStdout.mock.calls.length + defaultRuntime.writeJson.mock.calls.length,
437468).toBeGreaterThan(0);
@@ -456,10 +487,7 @@ describe("skills cli commands", () => {
456487await runCommand(argv);
457488});
458489459-expect(buildWorkspaceSkillStatusMock).toHaveBeenCalledWith(
460-"/tmp/workspace-writer",
461-expect.objectContaining({ config: {} }),
462-);
490+expectStatusWorkspaceCall("/tmp/workspace-writer");
463491});
464492465493it.each([
@@ -476,10 +504,7 @@ describe("skills cli commands", () => {
476504});
477505478506expect(resolveAgentIdByWorkspacePathMock).not.toHaveBeenCalled();
479-expect(buildWorkspaceSkillStatusMock).toHaveBeenCalledWith(
480-"/tmp/workspace-writer",
481-expect.objectContaining({ config: {} }),
482-);
507+expectStatusWorkspaceCall("/tmp/workspace-writer");
483508});
484509485510it("falls back to the default agent outside configured workspaces", async () => {
@@ -493,10 +518,7 @@ describe("skills cli commands", () => {
493518494519expect(resolveAgentIdByWorkspacePathMock).toHaveBeenCalledWith({}, "/tmp/unrelated");
495520expect(resolveDefaultAgentIdMock).toHaveBeenCalledWith({});
496-expect(buildWorkspaceSkillStatusMock).toHaveBeenCalledWith(
497-"/tmp/workspace-main",
498-expect.objectContaining({ config: {} }),
499-);
521+expectStatusWorkspaceCall("/tmp/workspace-main");
500522});
501523502524it("keeps non-JSON skills list output on stdout with human-readable formatting", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。