Files
ITWorx_MCP_Hub-Public/apps/web/tests/schema-input.test.ts
T

92 lines
3.4 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { NULL_INPUT_VALUE, parseSchemaArguments } from "../src/schema-input";
import type { ToolDefinition } from "../src/contracts";
const schema = (properties: NonNullable<ToolDefinition["inputSchema"]["properties"]>, required: string[] = []): ToolDefinition["inputSchema"] => ({
type: "object",
properties,
required,
});
describe("schema-driven tool arguments", () => {
it("parses strings, integers, decimals, booleans, enums, arrays and objects by declared type", () => {
const inputSchema = schema({
query: { type: "string" },
limit: { type: "integer", minimum: 1, maximum: 20 },
score: { type: "number" },
includeClosed: { type: "boolean" },
format: { type: "string", enum: ["compact", "full"] },
labels: { type: "array" },
filters: { type: "object" },
}, ["query", "limit", "includeClosed", "format"]);
expect(parseSchemaArguments({
query: "pull request",
limit: "4",
score: "3.5",
includeClosed: "false",
format: JSON.stringify("full"),
labels: "[\"bug\",\"urgent\"]",
filters: "{\"author\":\"jens\"}",
}, inputSchema)).toEqual({
arguments: {
query: "pull request",
limit: 4,
score: 3.5,
includeClosed: false,
format: "full",
labels: ["bug", "urgent"],
filters: { author: "jens" },
},
errors: {},
valid: true,
});
});
it("reports missing required values, malformed JSON and type mismatches clearly", () => {
const inputSchema = schema({
count: { type: "integer" },
enabled: { type: "boolean" },
tags: { type: "array" },
options: { type: "object" },
}, ["count", "enabled", "tags", "options"]);
const parsed = parseSchemaArguments({ count: "2.3", enabled: "sometimes", tags: "{oops", options: "[]" }, inputSchema);
expect(parsed.valid).toBe(false);
expect(parsed.arguments).toEqual({});
expect(parsed.errors).toEqual({
count: "Enter a whole number.",
enabled: "Choose yes or no.",
tags: "Enter valid JSON for this array.",
options: "Enter a JSON object.",
});
});
it("applies string and numeric bounds and rejects enum values outside the schema", () => {
const inputSchema = schema({
query: { type: "string", minLength: 2, maxLength: 5 },
limit: { type: "integer", minimum: 1, maximum: 8 },
mode: { type: "string", enum: ["safe", "full"] },
});
const parsed = parseSchemaArguments({ query: "x", limit: "9", mode: JSON.stringify("unsafe") }, inputSchema);
expect(parsed.valid).toBe(false);
expect(parsed.errors.query).toBe("Enter at least 2 characters.");
expect(parsed.errors.limit).toBe("Enter a number no greater than 8.");
expect(parsed.errors.mode).toBe("Choose a value listed by this tool's schema.");
});
it("omits empty optional fields and accepts explicit null only for nullable fields", () => {
const inputSchema = schema({ optional: { type: "string" }, nullable: { type: ["string", "null"] } });
expect(parseSchemaArguments({ optional: "", nullable: NULL_INPUT_VALUE }, inputSchema)).toEqual({
arguments: { nullable: null },
errors: {},
valid: true,
});
expect(parseSchemaArguments({ nullable: NULL_INPUT_VALUE }, schema({ nullable: { type: "string" } })).errors.nullable).toBe("This field does not accept null.");
});
});