Semantic Scholar MCP Server
by YUZongmin
- test
import { describe, it, expect } from "vitest";
import type { ApiEndpoint, ApiParameter } from "../src/gradio_api";
import { convertParameter } from "../src/gradio_convert";
function createParameter(
override: Partial<ApiParameter> & {
// Require the essential bits we always need to specify
python_type: {
type: string;
description?: string;
};
}
): ApiParameter {
return {
label: "Test Parameter",
// parameter_name is now optional
type: "string",
component: "Textbox",
// Spread the override at the end to allow overriding defaults
...override,
};
}
// Test just the parameter conversion
describe("basic conversions", () => {
it("converts a single basic string parameter", () => {
const param = createParameter({
python_type: {
type: "str",
description: "A text parameter",
},
});
const result = convertParameter(param);
// TypeScript ensures result matches ParameterSchema
expect(result).toEqual({
type: "string",
description: "A text parameter",
});
});
it("uses python_type description when available", () => {
const param = createParameter({
label: "Prompt",
python_type: {
type: "str",
description: "The input prompt text",
},
});
const result = convertParameter(param);
expect(result).toEqual({
type: "string",
description: "The input prompt text",
});
});
it("falls back to label when python_type description is empty", () => {
const param = createParameter({
label: "Prompt",
python_type: {
type: "str",
description: "",
},
});
const result = convertParameter(param);
expect(result).toEqual({
type: "string",
description: "Prompt",
});
});
it("includes default value when specified", () => {
const param = createParameter({
parameter_has_default: true,
parameter_default: "default text",
python_type: {
type: "str",
description: "",
},
});
const result = convertParameter(param);
expect(result).toEqual({
type: "string",
description: "Test Parameter",
default: "default text",
});
});
it("includes example when specified", () => {
const param = createParameter({
example_input: "example text",
python_type: {
type: "str",
description: ""
},
});
const result = convertParameter(param);
expect(result).toEqual({
type: "string",
description: "Test Parameter",
examples: ["example text"],
});
});
it("includes both default and example when specified", () => {
const param = createParameter({
parameter_has_default: true,
parameter_default: "default text",
example_input: "example text",
python_type: {
type: "str",
description:"",
},
});
const result = convertParameter(param);
expect(result).toEqual({
type: "string",
description: "Test Parameter",
default: "default text",
examples: ["example text"],
});
});
});
describe("convertParameter", () => {
it("converts a single parameter correctly", () => {
const param: ApiParameter = {
label: "Input Text",
parameter_name: "text",
parameter_has_default: false,
parameter_default: null,
type: "string",
python_type: {
type: "str",
description: "A text input",
},
component: "Textbox",
};
const result = convertParameter(param);
// TypeScript ensures result matches ParameterSchema
expect(result).toEqual({
type: "string",
description: "A text input",
});
});
});
describe("number type conversions", () => {
// ...existing tests...
it("handles basic number without constraints", () => {
const param = createParameter({
type: "number",
python_type: {
type: "float",
description: "A number parameter",
},
});
const result = convertParameter(param);
expect(result).toEqual({
type: "number",
description: "A number parameter",
});
});
it("parses minimum constraint", () => {
const param = createParameter({
type: "number",
python_type: {
type: "float",
description: "A number parameter (min: 0)",
},
});
const result = convertParameter(param);
expect(result).toEqual({
type: "number",
description: "A number parameter (min: 0)",
minimum: 0,
});
});
it("parses maximum constraint", () => {
const param = createParameter({
type: "number",
python_type: {
type: "float",
description: "A number parameter (maximum=100)",
},
});
const result = convertParameter(param);
expect(result).toEqual({
type: "number",
description: "A number parameter (maximum=100)",
maximum: 100,
});
});
it("parses both min and max constraints", () => {
const param = createParameter({
type: "number",
python_type: {
type: "float",
description: "A number parameter (min: 0, max: 1.0)",
},
});
const result = convertParameter(param);
expect(result).toEqual({
type: "number",
description: "A number parameter (min: 0, max: 1.0)",
minimum: 0,
maximum: 1.0,
});
});
it("parses 'between X and Y' format", () => {
const param = createParameter({
type: "number",
python_type: {
type: "float",
description: "numeric value between 256 and 2048",
},
});
const result = convertParameter(param);
expect(result).toEqual({
type: "number",
description: "numeric value between 256 and 2048",
minimum: 256,
maximum: 2048,
});
});
it("parses large number ranges", () => {
const param = createParameter({
type: "number",
python_type: {
type: "float",
description: "numeric value between 0 and 2147483647",
},
});
const result = convertParameter(param);
expect(result).toEqual({
type: "number",
description: "numeric value between 0 and 2147483647",
minimum: 0,
maximum: 2147483647,
});
});
});
describe("boolean type conversions", () => {
it("handles basic boolean parameter", () => {
const param = createParameter({
type: "boolean",
python_type: {
type: "bool",
description: "A boolean flag",
},
});
const result = convertParameter(param);
expect(result).toEqual({
type: "boolean",
description: "A boolean flag",
});
});
it("handles boolean with default value", () => {
const param = createParameter({
type: "boolean",
parameter_has_default: true,
parameter_default: true,
python_type: {
type: "bool",
description: "",
},
});
const result = convertParameter(param);
expect(result).toEqual({
type: "boolean",
description: "Test Parameter",
default: true,
});
});
it("handles boolean with example", () => {
const param = createParameter({
type: "boolean",
example_input: true,
python_type: {
type: "bool",
description: "",
},
});
const result = convertParameter(param);
expect(result).toEqual({
type: "boolean",
description: "Test Parameter",
examples: [true],
});
});
it("matches the Randomize seed example exactly", () => {
const param = createParameter({
label: "Randomize seed",
parameter_name: "randomize_seed",
parameter_has_default: true,
parameter_default: true,
type: "boolean",
example_input: true,
python_type: {
type: "bool",
description: "",
},
});
const result = convertParameter(param);
expect(result).toEqual({
type: "boolean",
description: "Randomize seed",
default: true,
examples: [true],
});
});
});
describe("literal type conversions", () => {
it("handles Literal type with enum values", () => {
const param = createParameter({
label: "Aspect Ratio",
parameter_name: "aspect_ratio",
parameter_has_default: true,
parameter_default: "1:1",
type: "string",
python_type: {
type: "Literal['1:1', '16:9', '9:16', '4:3']",
description: "",
},
example_input: "1:1",
});
const result = convertParameter(param);
expect(result).toEqual({
type: "string",
description: "Aspect Ratio",
default: "1:1",
examples: ["1:1"],
enum: ["1:1", "16:9", "9:16", "4:3"]
});
});
it("handles boolean-like Literal type with True/False strings", () => {
const param = createParameter({
label: "Is Example Image",
parameter_name: "is_example_image",
parameter_has_default: true,
parameter_default: "False",
type: "string",
python_type: {
type: "Literal['True', 'False']",
description: "",
},
example_input: "True",
});
const result = convertParameter(param);
expect(result).toEqual({
type: "string",
description: "Is Example Image",
default: "False",
examples: ["True"],
enum: ["True", "False"]
});
});
});
describe("file and blob type conversions", () => {
it("handles simple filepath type", () => {
const exampleUrl = "https://example.com/image.png";
const param = createParameter({
type: "Blob | File | Buffer",
python_type: {
type: "filepath",
description: "",
},
example_input: {
path: exampleUrl,
meta: { _type: "gradio.FileData" },
orig_name: "image.png",
url: exampleUrl,
},
});
const result = convertParameter(param);
expect(result).toMatchObject({
type: "string",
description: "Accepts: URL, file path, file name, or resource identifier",
});
});
it("handles complex Dict type for image input", () => {
const exampleUrl = "https://example.com/image.png";
const param = createParameter({
type: "Blob | File | Buffer",
python_type: {
type: "Dict(path: str | None (Path to a local file), url: str | None (Publicly available url), ...)",
description: "For input, either path or url must be provided.",
},
example_input: {
path: exampleUrl,
meta: { _type: "gradio.FileData" },
orig_name: "image.png",
url: exampleUrl,
},
});
const result = convertParameter(param);
expect(result).toMatchObject({
type: "string",
description: "Accepts: URL, file path, file name, or resource identifier",
});
});
it("handles audio file input type", () => {
const exampleUrl = "https://github.com/gradio-app/gradio/raw/main/test/test_files/audio_sample.wav";
const param = createParameter({
type: "",
python_type: {
type: "filepath",
description: "",
},
component: "Audio",
example_input: {
path: exampleUrl,
meta: { _type: "gradio.FileData" },
orig_name: "audio_sample.wav",
url: exampleUrl,
},
});
const result = convertParameter(param);
expect(result).toMatchObject({
type: "string",
description: "Accepts: Audio file URL, file path, file name, or resource identifier",
});
});
it("handles empty type string for audio input", () => {
const param = createParameter({
label: "parameter_1",
parameter_name: "inputs",
parameter_has_default: false,
parameter_default: null,
python_type: {
type: "filepath",
description: "",
},
component: "Audio",
example_input: {
path: "https://github.com/gradio-app/gradio/raw/main/test/test_files/audio_sample.wav",
meta: { _type: "gradio.FileData" },
orig_name: "audio_sample.wav",
url: "https://github.com/gradio-app/gradio/raw/main/test/test_files/audio_sample.wav",
},
});
const result = convertParameter(param);
expect(result).toMatchObject({
type: "string", // Should always be "string" for file inputs
description: "Accepts: Audio file URL, file path, file name, or resource identifier",
});
});
it("handles image file input type", () => {
const param = createParameter({
type: "",
python_type: {
type: "filepath",
description: "",
},
component: "Image",
example_input: {
path: "https://example.com/image.png",
meta: { _type: "gradio.FileData" },
orig_name: "image.png",
url: "https://example.com/image.png",
},
});
const result = convertParameter(param);
expect(result).toMatchObject({
type: "string",
description: "Accepts: Image file URL, file path, file name, or resource identifier",
});
});
});
describe("unnamed parameters", () => {
it("handles parameters without explicit names", () => {
const param = createParameter({
label: "Input Text",
type: "string",
python_type: {
type: "str",
description: "A text input",
},
component: "Textbox",
});
const result = convertParameter(param);
expect(result).toEqual({
type: "string",
description: "A text input",
});
});
it("handles array of unnamed parameters", () => {
const params = [
createParameter({
label: "Image Input",
type: "Blob | File | Buffer",
python_type: {
type: "filepath",
description: "",
},
component: "Image",
example_input: "https://example.com/image.png",
}),
createParameter({
label: "Text Input",
type: "string",
python_type: {
type: "str",
description: "",
},
component: "Textbox",
example_input: "Hello!",
}),
];
// Test each parameter conversion
params.forEach((param, index) => {
const result = convertParameter(param);
expect(result).toBeTruthy();
});
});
});
describe("special cases", () => {
// chatbox historys often have incorrect types/example pairings.
// will later handle python dicts/tuples more elegantly.
it("handles chat history parameter", () => {
const param = createParameter({
label: "Qwen2.5-72B-Instruct",
parameter_name: "history",
component: "Chatbot",
python_type: {
type: "list",
description: "Some other description that should be ignored",
},
});
const result = convertParameter(param);
expect(result).toEqual({
type: "array",
description: "Chat history as an array of message pairs. Each pair is [user_message, assistant_message] where messages can be text strings or null. Advanced: messages can also be file references or UI components."
});
});
it("handles chat history parameter with examples", () => {
const param = createParameter({
label: "Qwen2.5-72B-Instruct",
parameter_name: "history",
component: "Chatbot",
python_type: {
type: "list",
description: "Some other description that should be ignored",
},
example_input: [["Hello", "Hi there!"]], // Example chat history
});
const result = convertParameter(param);
expect(result).toEqual({
type: "array",
description: "Chat history as an array of message pairs. Each pair is [user_message, assistant_message] where messages can be text strings or null. Advanced: messages can also be file references or UI components.",
examples: [[["Hello", "Hi there!"]]]
});
});
it("handles chat history parameter with default value", () => {
const param = createParameter({
label: "Qwen2.5-72B-Instruct",
parameter_name: "history",
component: "Chatbot",
parameter_has_default: true,
parameter_default: [],
python_type: {
type: "list",
description: "Some other description that should be ignored",
}
});
const result = convertParameter(param);
expect(result).toEqual({
type: "array",
description: "Chat history as an array of message pairs. Each pair is [user_message, assistant_message] where messages can be text strings or null. Advanced: messages can also be file references or UI components.",
default: []
});
});
});