Files
wehub-resource-sync b7f52be4c9
CI / Run CI (push) Has been cancelled
CI / check-backend (push) Has been cancelled
CI / check-frontend (push) Has been cancelled
CI / tests (push) Has been cancelled
CI / e2e-tests (push) Has been cancelled
Copilot Setup Steps / copilot-setup-steps (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:48:47 +08:00

735 lines
24 KiB
Python

import pytest
from chainlit.input_widget import (
Checkbox,
MultiSelect,
NumberInput,
RadioGroup,
Select,
Slider,
Switch,
Tab,
Tags,
TextInput,
)
class TestInputWidgetBase:
"""Test suite for base InputWidget validation."""
def test_input_widget_requires_id_and_label(self):
"""Test that InputWidget requires both id and label."""
with pytest.raises(ValueError, match="Must provide key and label"):
Switch(id="", label="Test Label")
with pytest.raises(ValueError, match="Must provide key and label"):
Switch(id="test_id", label="")
class TestSwitchWidget:
"""Test suite for Switch input widget."""
def test_switch_initialization(self):
"""Test Switch widget initialization."""
switch = Switch(id="test_switch", label="Enable Feature")
assert switch.id == "test_switch"
assert switch.label == "Enable Feature"
assert switch.type == "switch"
assert switch.initial is False
assert switch.disabled is False
def test_switch_with_initial_value(self):
"""Test Switch widget with initial value."""
switch = Switch(id="test_switch", label="Enable Feature", initial=True)
assert switch.initial is True
def test_switch_with_tooltip_and_description(self):
"""Test Switch widget with tooltip and description."""
switch = Switch(
id="test_switch",
label="Enable Feature",
tooltip="Toggle this feature",
description="This enables the advanced feature",
)
assert switch.tooltip == "Toggle this feature"
assert switch.description == "This enables the advanced feature"
def test_switch_disabled(self):
"""Test Switch widget in disabled state."""
switch = Switch(id="test_switch", label="Enable Feature", disabled=True)
assert switch.disabled is True
def test_switch_to_dict(self):
"""Test Switch widget serialization."""
switch = Switch(
id="test_switch",
label="Enable Feature",
initial=True,
tooltip="Toggle",
description="Description",
disabled=False,
)
result = switch.to_dict()
assert result["type"] == "switch"
assert result["id"] == "test_switch"
assert result["label"] == "Enable Feature"
assert result["initial"] is True
assert result["tooltip"] == "Toggle"
assert result["description"] == "Description"
assert result["disabled"] is False
class TestSliderWidget:
"""Test suite for Slider input widget."""
def test_slider_initialization(self):
"""Test Slider widget initialization."""
slider = Slider(id="test_slider", label="Temperature")
assert slider.id == "test_slider"
assert slider.label == "Temperature"
assert slider.type == "slider"
assert slider.initial == 0
assert slider.min == 0
assert slider.max == 10
assert slider.step == 1
def test_slider_with_custom_range(self):
"""Test Slider widget with custom range."""
slider = Slider(
id="test_slider",
label="Temperature",
initial=0.5,
min=0.0,
max=1.0,
step=0.1,
)
assert slider.initial == 0.5
assert slider.min == 0.0
assert slider.max == 1.0
assert slider.step == 0.1
def test_slider_to_dict(self):
"""Test Slider widget serialization."""
slider = Slider(
id="test_slider",
label="Temperature",
initial=0.7,
min=0.0,
max=2.0,
step=0.1,
tooltip="Adjust temperature",
)
result = slider.to_dict()
assert result["type"] == "slider"
assert result["id"] == "test_slider"
assert result["label"] == "Temperature"
assert result["initial"] == 0.7
assert result["min"] == 0.0
assert result["max"] == 2.0
assert result["step"] == 0.1
assert result["tooltip"] == "Adjust temperature"
class TestSelectWidget:
"""Test suite for Select input widget."""
def test_select_with_values(self):
"""Test Select widget with values list."""
select = Select(
id="test_select",
label="Choose Model",
values=["gpt-4", "gpt-3.5", "claude"],
)
assert select.id == "test_select"
assert select.label == "Choose Model"
assert select.type == "select"
assert select.items == {
"gpt-4": "gpt-4",
"gpt-3.5": "gpt-3.5",
"claude": "claude",
}
def test_select_with_items(self):
"""Test Select widget with items dict."""
items = {"gpt4": "GPT-4", "gpt35": "GPT-3.5", "claude": "Claude"}
select = Select(id="test_select", label="Choose Model", items=items)
assert select.items == items
def test_select_with_initial_index(self):
"""Test Select widget with initial_index."""
select = Select(
id="test_select",
label="Choose Model",
values=["gpt-4", "gpt-3.5", "claude"],
initial_index=1,
)
assert select.initial == "gpt-3.5"
def test_select_with_initial_value(self):
"""Test Select widget with initial_value."""
select = Select(
id="test_select",
label="Choose Model",
values=["gpt-4", "gpt-3.5", "claude"],
initial_value="claude",
)
assert select.initial == "claude"
def test_select_requires_values_or_items(self):
"""Test that Select requires either values or items."""
with pytest.raises(ValueError, match="Must provide values or items"):
Select(id="test_select", label="Choose Model")
def test_select_cannot_have_both_values_and_items(self):
"""Test that Select cannot have both values and items."""
with pytest.raises(ValueError, match="only provide either values or items"):
Select(
id="test_select",
label="Choose Model",
values=["a", "b"],
items={"a": "A"},
)
def test_select_initial_index_requires_values(self):
"""Test that initial_index requires values."""
with pytest.raises(
ValueError,
match="Initial_index can only be used in combination with values",
):
Select(
id="test_select",
label="Choose Model",
items={"a": "A"},
initial_index=0,
)
def test_select_to_dict(self):
"""Test Select widget serialization."""
select = Select(
id="test_select",
label="Choose Model",
values=["gpt-4", "gpt-3.5"],
initial_index=0,
tooltip="Select a model",
)
result = select.to_dict()
assert result["type"] == "select"
assert result["id"] == "test_select"
assert result["label"] == "Choose Model"
assert result["initial"] == "gpt-4"
assert len(result["items"]) == 2
assert result["items"][0] == {"label": "gpt-4", "value": "gpt-4"}
assert result["tooltip"] == "Select a model"
class TestTextInputWidget:
"""Test suite for TextInput widget."""
def test_textinput_initialization(self):
"""Test TextInput widget initialization."""
text_input = TextInput(id="test_input", label="Enter Name")
assert text_input.id == "test_input"
assert text_input.label == "Enter Name"
assert text_input.type == "textinput"
assert text_input.initial is None
assert text_input.placeholder is None
assert text_input.multiline is False
def test_textinput_with_initial_and_placeholder(self):
"""Test TextInput widget with initial value and placeholder."""
text_input = TextInput(
id="test_input",
label="Enter Name",
initial="John Doe",
placeholder="Enter your name",
)
assert text_input.initial == "John Doe"
assert text_input.placeholder == "Enter your name"
def test_textinput_multiline(self):
"""Test TextInput widget in multiline mode."""
text_input = TextInput(
id="test_input", label="Enter Description", multiline=True
)
assert text_input.multiline is True
def test_textinput_to_dict(self):
"""Test TextInput widget serialization."""
text_input = TextInput(
id="test_input",
label="Enter Name",
initial="Default",
placeholder="Type here",
multiline=True,
tooltip="Enter your name",
)
result = text_input.to_dict()
assert result["type"] == "textinput"
assert result["id"] == "test_input"
assert result["label"] == "Enter Name"
assert result["initial"] == "Default"
assert result["placeholder"] == "Type here"
assert result["multiline"] is True
assert result["tooltip"] == "Enter your name"
class TestNumberInputWidget:
"""Test suite for NumberInput widget."""
def test_numberinput_initialization(self):
"""Test NumberInput widget initialization."""
number_input = NumberInput(id="test_number", label="Enter Age")
assert number_input.id == "test_number"
assert number_input.label == "Enter Age"
assert number_input.type == "numberinput"
assert number_input.initial is None
assert number_input.placeholder is None
def test_numberinput_with_initial(self):
"""Test NumberInput widget with initial value."""
number_input = NumberInput(
id="test_number", label="Enter Age", initial=25.5, placeholder="Age"
)
assert number_input.initial == 25.5
assert number_input.placeholder == "Age"
def test_numberinput_to_dict(self):
"""Test NumberInput widget serialization."""
number_input = NumberInput(
id="test_number",
label="Enter Age",
initial=30.0,
placeholder="Enter a number",
tooltip="Your age",
)
result = number_input.to_dict()
assert result["type"] == "numberinput"
assert result["id"] == "test_number"
assert result["label"] == "Enter Age"
assert result["initial"] == 30.0
assert result["placeholder"] == "Enter a number"
assert result["tooltip"] == "Your age"
class TestTagsWidget:
"""Test suite for Tags widget."""
def test_tags_initialization(self):
"""Test Tags widget initialization."""
tags = Tags(id="test_tags", label="Add Tags")
assert tags.id == "test_tags"
assert tags.label == "Add Tags"
assert tags.type == "tags"
assert tags.initial == []
assert tags.values == []
def test_tags_with_initial_values(self):
"""Test Tags widget with initial values."""
tags = Tags(
id="test_tags",
label="Add Tags",
initial=["python", "javascript"],
values=["python", "javascript", "go", "rust"],
)
assert tags.initial == ["python", "javascript"]
assert tags.values == ["python", "javascript", "go", "rust"]
def test_tags_to_dict(self):
"""Test Tags widget serialization."""
tags = Tags(
id="test_tags",
label="Add Tags",
initial=["tag1"],
tooltip="Add your tags",
)
result = tags.to_dict()
assert result["type"] == "tags"
assert result["id"] == "test_tags"
assert result["label"] == "Add Tags"
assert result["initial"] == ["tag1"]
assert result["tooltip"] == "Add your tags"
class TestMultiSelectWidget:
"""Test suite for MultiSelect widget."""
def test_multiselect_with_values(self):
"""Test MultiSelect widget with values list."""
multi_select = MultiSelect(
id="test_multiselect",
label="Choose Languages",
values=["Python", "JavaScript", "Go"],
)
assert multi_select.id == "test_multiselect"
assert multi_select.label == "Choose Languages"
assert multi_select.type == "multiselect"
assert multi_select.items == {
"Python": "Python",
"JavaScript": "JavaScript",
"Go": "Go",
}
def test_multiselect_with_items(self):
"""Test MultiSelect widget with items dict."""
items = {"py": "Python", "js": "JavaScript", "go": "Go"}
multi_select = MultiSelect(
id="test_multiselect", label="Choose Languages", items=items
)
assert multi_select.items == items
def test_multiselect_with_initial(self):
"""Test MultiSelect widget with initial selection."""
multi_select = MultiSelect(
id="test_multiselect",
label="Choose Languages",
values=["Python", "JavaScript", "Go"],
initial=["Python", "Go"],
)
assert multi_select.initial == ["Python", "Go"]
def test_multiselect_requires_values_or_items(self):
"""Test that MultiSelect requires either values or items."""
with pytest.raises(ValueError, match="Must provide values or items"):
MultiSelect(id="test_multiselect", label="Choose Languages")
def test_multiselect_cannot_have_both_values_and_items(self):
"""Test that MultiSelect cannot have both values and items."""
with pytest.raises(ValueError, match="only provide either values or items"):
MultiSelect(
id="test_multiselect",
label="Choose Languages",
values=["a", "b"],
items={"a": "A"},
)
def test_multiselect_to_dict(self):
"""Test MultiSelect widget serialization."""
multi_select = MultiSelect(
id="test_multiselect",
label="Choose Languages",
values=["Python", "JavaScript"],
initial=["Python"],
tooltip="Select languages",
)
result = multi_select.to_dict()
assert result["type"] == "multiselect"
assert result["id"] == "test_multiselect"
assert result["label"] == "Choose Languages"
assert result["initial"] == ["Python"]
assert len(result["items"]) == 2
assert result["tooltip"] == "Select languages"
class TestCheckboxWidget:
"""Test suite for Checkbox widget."""
def test_checkbox_initialization(self):
"""Test Checkbox widget initialization."""
checkbox = Checkbox(id="test_checkbox", label="Accept Terms")
assert checkbox.id == "test_checkbox"
assert checkbox.label == "Accept Terms"
assert checkbox.type == "checkbox"
assert checkbox.initial is False
def test_checkbox_with_initial_value(self):
"""Test Checkbox widget with initial value."""
checkbox = Checkbox(id="test_checkbox", label="Accept Terms", initial=True)
assert checkbox.initial is True
def test_checkbox_to_dict(self):
"""Test Checkbox widget serialization."""
checkbox = Checkbox(
id="test_checkbox",
label="Accept Terms",
initial=True,
tooltip="Check to accept",
description="Terms and conditions",
)
result = checkbox.to_dict()
assert result["type"] == "checkbox"
assert result["id"] == "test_checkbox"
assert result["label"] == "Accept Terms"
assert result["initial"] is True
assert result["tooltip"] == "Check to accept"
assert result["description"] == "Terms and conditions"
class TestRadioGroupWidget:
"""Test suite for RadioGroup widget."""
def test_radiogroup_with_values(self):
"""Test RadioGroup widget with values list."""
radio = RadioGroup(
id="test_radio", label="Choose Size", values=["Small", "Medium", "Large"]
)
assert radio.id == "test_radio"
assert radio.label == "Choose Size"
assert radio.type == "radio"
assert radio.items == {"Small": "Small", "Medium": "Medium", "Large": "Large"}
def test_radiogroup_with_items(self):
"""Test RadioGroup widget with items dict."""
items = {"s": "Small", "m": "Medium", "l": "Large"}
radio = RadioGroup(id="test_radio", label="Choose Size", items=items)
assert radio.items == items
def test_radiogroup_with_initial_index(self):
"""Test RadioGroup widget with initial_index."""
radio = RadioGroup(
id="test_radio",
label="Choose Size",
values=["Small", "Medium", "Large"],
initial_index=1,
)
assert radio.initial == "Medium"
def test_radiogroup_with_initial_value(self):
"""Test RadioGroup widget with initial_value."""
radio = RadioGroup(
id="test_radio",
label="Choose Size",
values=["Small", "Medium", "Large"],
initial_value="Large",
)
assert radio.initial == "Large"
def test_radiogroup_requires_values_or_items(self):
"""Test that RadioGroup requires either values or items."""
with pytest.raises(ValueError, match="Must provide values or items"):
RadioGroup(id="test_radio", label="Choose Size")
def test_radiogroup_cannot_have_both_values_and_items(self):
"""Test that RadioGroup cannot have both values and items."""
with pytest.raises(ValueError, match="only provide either values or items"):
RadioGroup(
id="test_radio",
label="Choose Size",
values=["a", "b"],
items={"a": "A"},
)
def test_radiogroup_initial_index_requires_values(self):
"""Test that initial_index requires values."""
with pytest.raises(
ValueError,
match="Initial_index can only be used in combination with values",
):
RadioGroup(
id="test_radio", label="Choose Size", items={"a": "A"}, initial_index=0
)
def test_radiogroup_to_dict(self):
"""Test RadioGroup widget serialization."""
radio = RadioGroup(
id="test_radio",
label="Choose Size",
values=["Small", "Medium"],
initial_index=0,
tooltip="Select size",
)
result = radio.to_dict()
assert result["type"] == "radio"
assert result["id"] == "test_radio"
assert result["label"] == "Choose Size"
assert result["initial"] == "Small"
assert len(result["items"]) == 2
assert result["items"][0] == {"label": "Small", "value": "Small"}
assert result["tooltip"] == "Select size"
class TestTabWidget:
"""Test suite for Tab widget."""
def test_tab_initialization(self):
"""Test Tab initialization."""
tab = Tab(id="test_tab", label="Settings")
assert tab.id == "test_tab"
assert tab.label == "Settings"
assert tab.inputs == []
def test_tab_with_inputs(self):
"""Test Tab with input widgets."""
switch = Switch(id="switch1", label="Enable")
slider = Slider(id="slider1", label="Value")
tab = Tab(id="test_tab", label="Settings", inputs=[switch, slider])
assert len(tab.inputs) == 2
assert tab.inputs[0] == switch
assert tab.inputs[1] == slider
def test_tab_to_dict(self):
"""Test Tab serialization."""
switch = Switch(id="switch1", label="Enable", initial=True)
slider = Slider(id="slider1", label="Value", initial=5)
tab = Tab(id="test_tab", label="Settings", inputs=[switch, slider])
result = tab.to_dict()
assert result["id"] == "test_tab"
assert result["label"] == "Settings"
assert len(result["inputs"]) == 2
assert result["inputs"][0]["type"] == "switch"
assert result["inputs"][0]["id"] == "switch1"
assert result["inputs"][1]["type"] == "slider"
assert result["inputs"][1]["id"] == "slider1"
def test_tab_to_dict_empty_inputs(self):
"""Test Tab serialization with no inputs."""
tab = Tab(id="test_tab", label="Empty Tab")
result = tab.to_dict()
assert result["id"] == "test_tab"
assert result["label"] == "Empty Tab"
assert result["inputs"] == []
class TestInputWidgetEdgeCases:
"""Test suite for InputWidget edge cases."""
def test_all_widgets_have_consistent_common_fields(self):
"""Test that all widgets support common fields."""
widgets = [
Switch(
id="test",
label="Test",
tooltip="Tooltip",
description="Description",
disabled=True,
),
Slider(
id="test",
label="Test",
tooltip="Tooltip",
description="Description",
disabled=True,
),
Checkbox(
id="test",
label="Test",
tooltip="Tooltip",
description="Description",
disabled=True,
),
TextInput(
id="test",
label="Test",
tooltip="Tooltip",
description="Description",
disabled=True,
),
NumberInput(
id="test",
label="Test",
tooltip="Tooltip",
description="Description",
disabled=True,
),
Tags(
id="test",
label="Test",
tooltip="Tooltip",
description="Description",
disabled=True,
),
]
for widget in widgets:
assert widget.tooltip == "Tooltip"
assert widget.description == "Description"
assert widget.disabled is True
result = widget.to_dict()
assert result["tooltip"] == "Tooltip"
assert result["description"] == "Description"
assert result["disabled"] is True
def test_select_with_complex_items(self):
"""Test Select with complex item labels and values."""
items = {
"option_1": "Option One with Spaces",
"option_2": "Option Two (with parentheses)",
"option_3": "Option Three - with dashes",
}
select = Select(id="test_select", label="Choose", items=items)
result = select.to_dict()
assert len(result["items"]) == 3
assert {"label": "option_1", "value": "Option One with Spaces"} in result[
"items"
]
def test_multiselect_initial_with_multiple_values(self):
"""Test MultiSelect with multiple initial values."""
multi_select = MultiSelect(
id="test",
label="Choose",
values=["A", "B", "C", "D"],
initial=["A", "C", "D"],
)
assert len(multi_select.initial) == 3
assert "A" in multi_select.initial
assert "C" in multi_select.initial
assert "D" in multi_select.initial
def test_slider_with_negative_range(self):
"""Test Slider with negative range."""
slider = Slider(id="test", label="Test", min=-10, max=10, initial=-5, step=1)
assert slider.min == -10
assert slider.max == 10
assert slider.initial == -5
def test_textinput_empty_initial_value(self):
"""Test TextInput with empty string as initial value."""
text_input = TextInput(id="test", label="Test", initial="")
assert text_input.initial == ""
result = text_input.to_dict()
assert result["initial"] == ""