Merge pull request #482 from koic/elicitation_enum_schema
Add `MCP::Elicitation::EnumSchema` builders for SEP-1330
This commit is contained in:
commit
b03da23dd3
1 changed files with 361 additions and 34 deletions
143
test/mcp/elicitation/enum_schema_test.rb
Normal file
143
test/mcp/elicitation/enum_schema_test.rb
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "test_helper"
|
||||
|
||||
module MCP
|
||||
module Elicitation
|
||||
class EnumSchemaTest < ActiveSupport::TestCase
|
||||
test "untitled_single_select returns string + enum schema" do
|
||||
schema = EnumSchema.untitled_single_select(values: ["red", "green", "blue"])
|
||||
|
||||
assert_equal({ type: "string", enum: ["red", "green", "blue"] }, schema.to_h)
|
||||
end
|
||||
|
||||
test "untitled_single_select preserves default value" do
|
||||
schema = EnumSchema.untitled_single_select(values: ["red", "green"], default: "red")
|
||||
|
||||
assert_equal "red", schema.to_h[:default]
|
||||
end
|
||||
|
||||
test "titled_single_select returns string + oneOf schema" do
|
||||
schema = EnumSchema.titled_single_select(
|
||||
options: [
|
||||
{ value: "small", title: "Small" },
|
||||
{ value: "large", title: "Large" },
|
||||
],
|
||||
)
|
||||
|
||||
assert_equal(
|
||||
{
|
||||
type: "string",
|
||||
oneOf: [
|
||||
{ const: "small", title: "Small" },
|
||||
{ const: "large", title: "Large" },
|
||||
],
|
||||
},
|
||||
schema.to_h,
|
||||
)
|
||||
end
|
||||
|
||||
test "untitled_multi_select returns array + items.enum schema" do
|
||||
schema = EnumSchema.untitled_multi_select(values: ["a", "b", "c"])
|
||||
|
||||
assert_equal(
|
||||
{ type: "array", items: { type: "string", enum: ["a", "b", "c"] } },
|
||||
schema.to_h,
|
||||
)
|
||||
end
|
||||
|
||||
test "untitled_multi_select preserves default array" do
|
||||
schema = EnumSchema.untitled_multi_select(values: ["a", "b"], default: ["a"])
|
||||
|
||||
assert_equal ["a"], schema.to_h[:default]
|
||||
end
|
||||
|
||||
test "titled_multi_select returns array + items.anyOf schema" do
|
||||
schema = EnumSchema.titled_multi_select(
|
||||
options: [
|
||||
{ value: "us", title: "United States" },
|
||||
{ value: "jp", title: "Japan" },
|
||||
],
|
||||
)
|
||||
|
||||
assert_equal(
|
||||
{
|
||||
type: "array",
|
||||
items: {
|
||||
anyOf: [
|
||||
{ const: "us", title: "United States" },
|
||||
{ const: "jp", title: "Japan" },
|
||||
],
|
||||
},
|
||||
},
|
||||
schema.to_h,
|
||||
)
|
||||
end
|
||||
|
||||
test "legacy_titled returns enum + enumNames" do
|
||||
schema = EnumSchema.legacy_titled(
|
||||
values: ["s", "m", "l"],
|
||||
value_titles: ["Small", "Medium", "Large"],
|
||||
)
|
||||
|
||||
assert_equal(
|
||||
{
|
||||
type: "string",
|
||||
enum: ["s", "m", "l"],
|
||||
enumNames: ["Small", "Medium", "Large"],
|
||||
},
|
||||
schema.to_h,
|
||||
)
|
||||
end
|
||||
|
||||
test "title and description are included when provided" do
|
||||
schema = EnumSchema.untitled_single_select(
|
||||
values: ["a"],
|
||||
title: "Color",
|
||||
description: "Pick a color",
|
||||
)
|
||||
|
||||
assert_equal "Color", schema.to_h[:title]
|
||||
assert_equal "Pick a color", schema.to_h[:description]
|
||||
end
|
||||
|
||||
test "raises ArgumentError when values array is empty" do
|
||||
assert_raises(ArgumentError) do
|
||||
EnumSchema.untitled_single_select(values: [])
|
||||
end
|
||||
end
|
||||
|
||||
test "raises ArgumentError when titled options miss :value" do
|
||||
assert_raises(ArgumentError) do
|
||||
EnumSchema.titled_single_select(options: [{ title: "missing value" }])
|
||||
end
|
||||
end
|
||||
|
||||
test "raises ArgumentError when titled options miss :title" do
|
||||
assert_raises(ArgumentError) do
|
||||
EnumSchema.titled_single_select(options: [{ value: "v" }])
|
||||
end
|
||||
end
|
||||
|
||||
test "raises ArgumentError when legacy value_titles length differs" do
|
||||
assert_raises(ArgumentError) do
|
||||
EnumSchema.legacy_titled(values: ["a", "b"], value_titles: ["A"])
|
||||
end
|
||||
end
|
||||
|
||||
test "preserves an empty-string default value" do
|
||||
# Regression for `unless @default.nil?`: empty-but-non-nil defaults must still survive `to_h`
|
||||
# (the guard distinguishes nil from "absent vs supplied", not truthy vs falsey).
|
||||
schema = EnumSchema.untitled_single_select(values: ["", "yes", "no"], default: "")
|
||||
|
||||
assert_equal "", schema.to_h[:default]
|
||||
end
|
||||
|
||||
test "preserves an empty-array default for multi-select" do
|
||||
schema = EnumSchema.untitled_multi_select(values: ["a", "b"], default: [])
|
||||
|
||||
assert_equal [], schema.to_h[:default]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in a new issue