mcpb/test/init.test.ts
2025-11-01 12:31:25 -07:00

398 lines
11 KiB
TypeScript

import { existsSync, readFileSync } from "fs";
import {
buildManifest,
createMcpConfig,
getDefaultAuthorEmail,
getDefaultAuthorName,
getDefaultAuthorUrl,
getDefaultEntryPoint,
getDefaultRepositoryUrl,
readPackageJson,
} from "../src/cli/init.js";
import { DEFAULT_MANIFEST_VERSION } from "../src/shared/constants.js";
// Mock the fs module
jest.mock("fs", () => ({
existsSync: jest.fn(),
readFileSync: jest.fn(),
writeFileSync: jest.fn(),
}));
describe("init functions", () => {
beforeEach(() => {
jest.clearAllMocks();
});
describe("readPackageJson", () => {
it("should return empty object when package.json doesn't exist", () => {
(existsSync as jest.Mock).mockReturnValue(false);
const result = readPackageJson("/test/path");
expect(result).toEqual({});
});
it("should parse package.json when it exists", () => {
(existsSync as jest.Mock).mockReturnValue(true);
const mockPackageData = { name: "test-package", version: "1.0.0" };
(readFileSync as jest.Mock).mockReturnValue(
JSON.stringify(mockPackageData),
);
const result = readPackageJson("/test/path");
expect(result).toEqual(mockPackageData);
});
it("should return empty object when package.json is invalid", () => {
(existsSync as jest.Mock).mockReturnValue(true);
(readFileSync as jest.Mock).mockReturnValue("invalid json");
const result = readPackageJson("/test/path");
expect(result).toEqual({});
});
});
describe("getDefaultAuthorName", () => {
it("should return string author when author is string", () => {
const result = getDefaultAuthorName({ author: "John Doe" });
expect(result).toBe("John Doe");
});
it("should return author.name when author is object", () => {
const result = getDefaultAuthorName({ author: { name: "John Doe" } });
expect(result).toBe("John Doe");
});
it("should return empty string when no author", () => {
const result = getDefaultAuthorName({});
expect(result).toBe("");
});
});
describe("getDefaultAuthorEmail", () => {
it("should return author.email when author is object with email", () => {
const result = getDefaultAuthorEmail({
author: { email: "john@example.com" },
});
expect(result).toBe("john@example.com");
});
it("should return empty string when author is string", () => {
const result = getDefaultAuthorEmail({ author: "John Doe" });
expect(result).toBe("");
});
it("should return empty string when no email", () => {
const result = getDefaultAuthorEmail({ author: { name: "John" } });
expect(result).toBe("");
});
});
describe("getDefaultAuthorUrl", () => {
it("should return author.url when author is object with url", () => {
const result = getDefaultAuthorUrl({
author: { url: "https://example.com" },
});
expect(result).toBe("https://example.com");
});
it("should return empty string when author is string", () => {
const result = getDefaultAuthorUrl({ author: "John Doe" });
expect(result).toBe("");
});
it("should return empty string when no url", () => {
const result = getDefaultAuthorUrl({ author: { name: "John" } });
expect(result).toBe("");
});
});
describe("getDefaultRepositoryUrl", () => {
it("should return string repository when repository is string", () => {
const result = getDefaultRepositoryUrl({
repository: "https://github.com/user/repo",
});
expect(result).toBe("https://github.com/user/repo");
});
it("should return repository.url when repository is object", () => {
const result = getDefaultRepositoryUrl({
repository: { type: "git", url: "https://github.com/user/repo" },
});
expect(result).toBe("https://github.com/user/repo");
});
it("should return empty string when no repository", () => {
const result = getDefaultRepositoryUrl({});
expect(result).toBe("");
});
});
describe("createMcpConfig", () => {
it("should create node config", () => {
const result = createMcpConfig("node", "server/index.js");
expect(result).toEqual({
command: "node",
args: ["${__dirname}/server/index.js"],
env: {},
});
});
it("should create python config", () => {
const result = createMcpConfig("python", "server/main.py");
expect(result).toEqual({
command: "python",
args: ["${__dirname}/server/main.py"],
env: {
PYTHONPATH: "${__dirname}/server/lib",
},
});
});
it("should create binary config", () => {
const result = createMcpConfig("binary", "server/my-server");
expect(result).toEqual({
command: "${__dirname}/server/my-server",
args: [],
env: {},
});
});
});
describe("getDefaultEntryPoint", () => {
it("should return node default", () => {
expect(getDefaultEntryPoint("node")).toBe("server/index.js");
});
it("should return python default", () => {
expect(getDefaultEntryPoint("python")).toBe("server/main.py");
});
it("should return binary default", () => {
expect(getDefaultEntryPoint("binary")).toBe("server/my-server");
});
});
describe("buildManifest", () => {
it("should build minimal manifest", () => {
const manifest = buildManifest(
{
name: "test-extension",
displayName: "test-extension",
version: "1.0.0",
description: "Test description",
authorName: "John Doe",
},
undefined, // longDescription
{
authorEmail: "",
authorUrl: "",
},
{
homepage: "",
documentation: "",
support: "",
},
{
icon: "",
icons: [],
screenshots: [],
},
{
serverType: "node",
entryPoint: "server/index.js",
mcp_config: {
command: "node",
args: ["${__dirname}/server/index.js"],
env: {},
},
},
[], // tools
false, // toolsGenerated
[], // prompts
false, // promptsGenerated
undefined, // compatibility
{}, // userConfig
{
keywords: "",
license: "",
},
undefined,
);
expect(manifest).toEqual({
manifest_version: DEFAULT_MANIFEST_VERSION,
name: "test-extension",
version: "1.0.0",
description: "Test description",
author: {
name: "John Doe",
},
server: {
type: "node",
entry_point: "server/index.js",
mcp_config: {
command: "node",
args: ["${__dirname}/server/index.js"],
env: {},
},
},
});
});
it("should include optional fields when provided", () => {
const manifest = buildManifest(
{
name: "test-extension",
displayName: "Test Extension",
version: "1.0.0",
description: "Test description",
authorName: "John Doe",
},
"This is a detailed long description with more information.", // longDescription
{
authorEmail: "john@example.com",
authorUrl: "https://example.com",
},
{
homepage: "https://homepage.example.com",
documentation: "https://docs.example.com",
support: "https://support.example.com",
},
{
icon: "icon.png",
icons: [
{
src: "assets/icons/icon-16-light.png",
size: "16x16",
theme: "light",
},
{
src: "assets/icons/icon-16-dark.png",
size: "16x16",
theme: "dark",
},
],
screenshots: ["screen1.png", "screen2.png"],
},
{
serverType: "python",
entryPoint: "server/main.py",
mcp_config: {
command: "python",
args: ["${__dirname}/server/main.py"],
env: { PYTHONPATH: "${__dirname}/server/lib" },
},
},
[
{ name: "tool1", description: "Tool 1 description" },
{ name: "tool2" },
], // tools
false, // toolsGenerated
[
{
name: "analyze_code",
description: "Code analysis prompt",
text: "Analyze the following code...",
},
], // prompts
false, // promptsGenerated
{
claude_desktop: ">=0.4.0",
platforms: ["darwin", "linux"],
runtimes: { python: ">=3.8,<4.0" },
}, // compatibility
{
api_key: {
type: "string",
title: "API Key",
description: "Your API key",
required: true,
sensitive: true,
},
}, // userConfig
{
keywords: "test, extension, mcp",
license: "MIT",
repository: { type: "git", url: "https://github.com/user/repo" },
},
{
resources: "resources/${locale}.json",
default_locale: "en-US",
},
);
expect(manifest).toEqual({
manifest_version: DEFAULT_MANIFEST_VERSION,
name: "test-extension",
display_name: "Test Extension",
version: "1.0.0",
description: "Test description",
long_description:
"This is a detailed long description with more information.",
author: {
name: "John Doe",
email: "john@example.com",
url: "https://example.com",
},
homepage: "https://homepage.example.com",
documentation: "https://docs.example.com",
support: "https://support.example.com",
icon: "icon.png",
icons: [
{
src: "assets/icons/icon-16-light.png",
size: "16x16",
theme: "light",
},
{
src: "assets/icons/icon-16-dark.png",
size: "16x16",
theme: "dark",
},
],
screenshots: ["screen1.png", "screen2.png"],
localization: {
resources: "resources/${locale}.json",
default_locale: "en-US",
},
server: {
type: "python",
entry_point: "server/main.py",
mcp_config: {
command: "python",
args: ["${__dirname}/server/main.py"],
env: { PYTHONPATH: "${__dirname}/server/lib" },
},
},
tools: [
{ name: "tool1", description: "Tool 1 description" },
{ name: "tool2" },
],
prompts: [
{
name: "analyze_code",
description: "Code analysis prompt",
text: "Analyze the following code...",
},
],
compatibility: {
claude_desktop: ">=0.4.0",
platforms: ["darwin", "linux"],
runtimes: { python: ">=3.8,<4.0" },
},
user_config: {
api_key: {
type: "string",
title: "API Key",
description: "Your API key",
required: true,
sensitive: true,
},
},
keywords: ["test", "extension", "mcp"],
license: "MIT",
repository: { type: "git", url: "https://github.com/user/repo" },
});
});
});
});