We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/jmagar/homelab-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
import { describe, expect, it } from "vitest";
import { createFormatter, FormatterFactory, JSONFormatter, MarkdownFormatter } from "./strategy.js";
describe("MarkdownFormatter", () => {
it("should return string data as-is", () => {
const formatter = new MarkdownFormatter();
const input = "## Container: test\n\nStatus: running";
const result = formatter.format(input);
expect(result).toBe(input);
});
it("should wrap non-string data in pretty-printed JSON code block by default", () => {
const formatter = new MarkdownFormatter();
const input = { name: "test-container", status: "running" };
const result = formatter.format(input);
expect(result).toContain("```json");
expect(result).toContain('"name": "test-container"');
expect(result).toContain('"status": "running"');
expect(result).toContain("```");
// Default is pretty-printed (indented)
expect(result).toContain("\n ");
});
it("should handle arrays", () => {
const formatter = new MarkdownFormatter();
const input = ["item1", "item2", "item3"];
const result = formatter.format(input);
expect(result).toContain("```json");
expect(result).toContain('"item1"');
expect(result).toContain("```");
});
it("should use compact JSON in code block when compact option is true", () => {
const formatter = new MarkdownFormatter({ compact: true });
const input = { name: "test", status: "running" };
const result = formatter.format(input);
expect(result).toContain("```json");
// Compact: no indentation
expect(result).toBe('```json\n{"name":"test","status":"running"}\n```');
});
});
describe("JSONFormatter", () => {
it("should wrap string data in structured object", () => {
const formatter = new JSONFormatter();
const input = "## Container: test\n\nStatus: running";
const result = formatter.format(input);
const parsed = JSON.parse(result);
expect(parsed.output).toBe(input);
expect(parsed.format).toBe("text");
});
it("should default to compact output", () => {
const formatter = new JSONFormatter();
const input = { name: "test-container", status: "running" };
const result = formatter.format(input);
// Compact: no whitespace/indentation
expect(result).toBe('{"name":"test-container","status":"running"}');
// But still valid JSON
const parsed = JSON.parse(result);
expect(parsed.name).toBe("test-container");
});
it("should serialize objects directly", () => {
const formatter = new JSONFormatter();
const input = {
name: "test-container",
status: "running",
ports: [8080, 8443],
};
const result = formatter.format(input);
const parsed = JSON.parse(result);
expect(parsed.name).toBe("test-container");
expect(parsed.status).toBe("running");
expect(parsed.ports).toEqual([8080, 8443]);
});
it("should handle arrays directly", () => {
const formatter = new JSONFormatter();
const input = [
{ id: "abc123", name: "container1" },
{ id: "def456", name: "container2" },
];
const result = formatter.format(input);
const parsed = JSON.parse(result);
expect(Array.isArray(parsed)).toBe(true);
expect(parsed).toHaveLength(2);
expect(parsed[0].name).toBe("container1");
});
it("should handle nested objects", () => {
const formatter = new JSONFormatter();
const input = {
container: {
name: "test",
config: {
ports: [8080],
volumes: ["/data"],
},
},
};
const result = formatter.format(input);
const parsed = JSON.parse(result);
expect(parsed.container.config.ports).toEqual([8080]);
});
it("should pretty-print when compact is false", () => {
const formatter = new JSONFormatter({ compact: false });
const input = { name: "test", value: 42 };
const result = formatter.format(input);
// Pretty-printed: has indentation
expect(result).toContain("\n ");
expect(result).toBe(JSON.stringify(input, null, 2));
});
it("should pretty-print string wrapper when compact is false", () => {
const formatter = new JSONFormatter({ compact: false });
const input = "some text";
const result = formatter.format(input);
expect(result).toContain("\n ");
const parsed = JSON.parse(result);
expect(parsed.output).toBe("some text");
expect(parsed.format).toBe("text");
});
});
describe("FormatterFactory", () => {
it("should create MarkdownFormatter for 'markdown' format", () => {
const formatter = FormatterFactory.create("markdown");
expect(formatter).toBeInstanceOf(MarkdownFormatter);
});
it("should create JSONFormatter for 'json' format", () => {
const formatter = FormatterFactory.create("json");
expect(formatter).toBeInstanceOf(JSONFormatter);
});
it("should throw error for unsupported format", () => {
// @ts-expect-error - Testing invalid format
expect(() => FormatterFactory.create("xml")).toThrow("Unsupported format");
});
});
describe("createFormatter with options", () => {
it("should pass compact option to JSONFormatter", () => {
const compactFormatter = createFormatter("json", { compact: true });
const prettyFormatter = createFormatter("json", { compact: false });
const data = { key: "value" };
const compact = compactFormatter.format(data);
const pretty = prettyFormatter.format(data);
expect(compact).toBe('{"key":"value"}');
expect(pretty).toBe('{\n "key": "value"\n}');
});
it("should pass compact option to MarkdownFormatter", () => {
const compactFormatter = createFormatter("markdown", { compact: true });
const prettyFormatter = createFormatter("markdown", { compact: false });
const data = { key: "value" };
const compact = compactFormatter.format(data);
const pretty = prettyFormatter.format(data);
expect(compact).toBe('```json\n{"key":"value"}\n```');
expect(pretty).toBe('```json\n{\n "key": "value"\n}\n```');
});
it("should default JSONFormatter to compact", () => {
const defaultFormatter = createFormatter("json");
const data = { a: 1, b: 2 };
expect(defaultFormatter.format(data)).toBe('{"a":1,"b":2}');
});
it("should default MarkdownFormatter to pretty-print", () => {
const defaultFormatter = createFormatter("markdown");
const data = { a: 1 };
expect(defaultFormatter.format(data)).toContain("\n ");
});
});
describe("Strategy pattern integration", () => {
it("should allow swapping formatters without changing client code", () => {
const data = { name: "test", status: "running" };
// Use markdown formatter
const mdFormatter = FormatterFactory.create("markdown");
const mdResult = mdFormatter.format(data);
expect(mdResult).toContain("```json");
// Use JSON formatter
const jsonFormatter = FormatterFactory.create("json");
const jsonResult = jsonFormatter.format(data);
const parsed = JSON.parse(jsonResult);
expect(parsed.name).toBe("test");
});
it("should preserve markdown output through markdown formatter", () => {
const markdownOutput = "## Container: test\n\n- Status: running\n- Image: nginx:latest";
const formatter = FormatterFactory.create("markdown");
const result = formatter.format(markdownOutput);
// Should return the markdown string unchanged
expect(result).toBe(markdownOutput);
});
it("should wrap markdown output for JSON consumers", () => {
const markdownOutput = "## Container: test\n\n- Status: running";
const formatter = FormatterFactory.create("json");
const result = formatter.format(markdownOutput);
const parsed = JSON.parse(result);
expect(parsed.output).toBe(markdownOutput);
expect(parsed.format).toBe("text");
});
});