Files
homaroma/apps/mcp-server/storefront-toolkit.test.ts
T
2026-10-11 06:43:08 +07:00

77 lines
4.4 KiB
TypeScript

import { describe, expect, test } from "bun:test";
import type { AxiosInstance } from "axios";
import { handleStorefrontTool, STOREFRONT_TOOL_DEFINITIONS } from "./storefront-toolkit";
function fakeApi(sections: any[] = []) {
const calls: Array<{ method: string; path: string; body?: unknown }> = [];
const api = {
get: async (path: string) => {
calls.push({ method: "GET", path });
return { data: path === "/settings/footer-layout" ? { version: "v1", layout: {} } : sections };
},
patch: async (path: string, body: unknown) => { calls.push({ method: "PATCH", path, body }); return { data: { success: true } }; },
post: async (path: string, body?: unknown) => { calls.push({ method: "POST", path, body }); return { data: { success: true } }; },
put: async (path: string, body: unknown) => { calls.push({ method: "PUT", path, body }); return { data: { success: true } }; },
delete: async (path: string) => { calls.push({ method: "DELETE", path }); return { data: { success: true } }; },
} as unknown as AxiosInstance;
return { api, calls };
}
const value = (response: any) => JSON.parse(response.content[0].text);
describe("storefront MCP tools", () => {
test("definitions expose the complete new workflow", () => {
expect(STOREFRONT_TOOL_DEFINITIONS.map((tool) => tool.name)).toEqual([
"get_footer_layout", "patch_footer_layout", "get_category_sections", "seed_category_sections",
"add_category_section", "update_category_section", "reorder_category_sections", "delete_category_section",
]);
});
test("footer write requires version and forwards backend dry run", async () => {
const { api, calls } = fakeApi();
const missing = await handleStorefrontTool(api, "patch_footer_layout", { columns: ["brand"] });
expect(value(missing).code).toBe("VERSION_REQUIRED");
expect(calls).toHaveLength(0);
const preview = await handleStorefrontTool(api, "patch_footer_layout", { columns: ["brand"], dryRun: true });
expect(preview?.isError).toBeUndefined();
expect(calls[0]).toEqual({ method: "PATCH", path: "/settings/footer-layout", body: { columns: ["brand"], dryRun: true } });
await handleStorefrontTool(api, "patch_footer_layout", { finale: { enabled: true }, expectedVersion: "v1" });
expect(calls[1]?.body).toEqual({ finale: { enabled: true }, expectedVersion: "v1" });
});
test("footer validation returns field paths without a request", async () => {
const { api, calls } = fakeApi();
const response = await handleStorefrontTool(api, "patch_footer_layout", { columns: ["brand", "brand"], dryRun: true });
expect(value(response).code).toBe("INVALID_INPUT");
expect(calls).toHaveLength(0);
});
test("category dry run reads but never writes", async () => {
const { api, calls } = fakeApi();
const response = await handleStorefrontTool(api, "seed_category_sections", { categoryId: 9, dryRun: true });
expect(value(response).dryRun).toBe(true);
expect(calls).toEqual([{ method: "GET", path: "/categories/9/sections" }]);
});
test("category update rejects wrong ownership and locked changes", async () => {
const { api, calls } = fakeApi([{ id: 7, type: "CATEGORY_HEADER", isLocked: true }]);
expect(value(await handleStorefrontTool(api, "update_category_section", { categoryId: 9, sectionId: 8, isActive: false })).code).toBe("NOT_FOUND");
expect(value(await handleStorefrontTool(api, "update_category_section", { categoryId: 9, sectionId: 7, isActive: false })).code).toBe("CONFLICT");
expect(calls.every((call) => call.method === "GET")).toBe(true);
});
test("reorder rejects missing IDs before backend write", async () => {
const { api, calls } = fakeApi([{ id: 1 }, { id: 2 }]);
const response = await handleStorefrontTool(api, "reorder_category_sections", { categoryId: 9, sections: [{ id: 1, order: 1 }] });
expect(value(response).code).toBe("INVALID_INPUT");
expect(calls.every((call) => call.method === "GET")).toBe(true);
});
test("backend conflict includes current version", async () => {
const { api } = fakeApi();
api.patch = async () => { throw { response: { status: 409, data: { code: "VERSION_CONFLICT", error: "Changed", currentVersion: "v2" } } }; };
const response = await handleStorefrontTool(api, "patch_footer_layout", { columns: ["brand"], expectedVersion: "v1" });
expect(value(response)).toMatchObject({ code: "VERSION_CONFLICT", message: "Changed", details: { status: 409, currentVersion: "v2" } });
});
});