""" Comprehensive binding tests for all bindable FastHTML components. This test suite covers: - Input (text) - already tested - Checkbox - already tested - Textarea - Select (single) - Select (multiple) - Range (slider) - Radio buttons - Button - Input with Datalist (combobox) """ from dataclasses import dataclass from fasthtml.components import ( Label, Select, Option ) from myfasthtml.controls.helpers import mk from myfasthtml.core.bindings import Binding @dataclass class Data: value: str = "hello world" @dataclass class NumericData: value: int = 50 @dataclass class BoolData: value: bool = True @dataclass class ListData: value: list = None def __post_init__(self): if self.value is None: self.value = [] class TestBindingSelect: """Tests for binding Select components (single selection).""" def test_i_can_bind_select_single(self, user, rt): """ Single select should bind with data. Selecting an option should update the label. """ @rt("/") def index(): data = Data("option1") select_elt = Select( Option("Option 1", value="option1"), Option("Option 2", value="option2"), Option("Option 3", value="option3"), name="select_name" ) label_elt = Label() mk.manage_binding(select_elt, Binding(data)) mk.manage_binding(label_elt, Binding(data)) return select_elt, label_elt user.open("/") user.should_see("option1") testable_select = user.find_element("select") testable_select.select("option2") user.should_see("option2") testable_select.select("option3") user.should_see("option3") def test_i_can_bind_select_by_text(self, user, rt): """ Selecting by visible text should work with binding. """ @rt("/") def index(): data = Data("opt1") select_elt = Select( Option("First Option", value="opt1"), Option("Second Option", value="opt2"), Option("Third Option", value="opt3"), name="select_name" ) label_elt = Label() mk.manage_binding(select_elt, Binding(data)) mk.manage_binding(label_elt, Binding(data)) return select_elt, label_elt user.open("/") user.should_see("opt1") testable_select = user.find_element("select") testable_select.select_by_text("Second Option") user.should_see("opt2") def test_select_with_default_selected_option(self, user, rt): """ Select with a pre-selected option should initialize correctly. """ @rt("/") def index(): data = Data("option2") select_elt = Select( Option("Option 1", value="option1"), Option("Option 2", value="option2", selected=True), Option("Option 3", value="option3"), name="select_name" ) label_elt = Label() mk.manage_binding(select_elt, Binding(data)) mk.manage_binding(label_elt, Binding(data)) return select_elt, label_elt user.open("/") user.should_see("option2") class TestBindingSelectMultiple: """Tests for binding Select components with multiple selection.""" def test_i_can_bind_select_multiple(self, user, rt): """ Multiple select should bind with list data. Selecting multiple options should update the label. """ @rt("/") def index(): data = ListData(["option1"]) select_elt = Select( Option("Option 1", value="option1"), Option("Option 2", value="option2"), Option("Option 3", value="option3"), name="select_name", multiple=True ) label_elt = Label() mk.manage_binding(select_elt, Binding(data)) mk.manage_binding(label_elt, Binding(data)) return select_elt, label_elt user.open("/") user.should_see("['option1']") testable_select = user.find_element("select") testable_select.select("option2") user.should_see("['option1', 'option2']") testable_select.select("option3") user.should_see("['option1', 'option2', 'option3']") def test_i_can_deselect_from_multiple_select(self, user, rt): """ Deselecting options from multiple select should update binding. """ @rt("/") def index(): data = ListData(["option1", "option2"]) select_elt = Select( Option("Option 1", value="option1"), Option("Option 2", value="option2"), Option("Option 3", value="option3"), name="select_name", multiple=True ) label_elt = Label() mk.manage_binding(select_elt, Binding(data)) mk.manage_binding(label_elt, Binding(data)) return select_elt, label_elt user.open("/") user.should_see("['option1', 'option2']") testable_select = user.find_element("select") testable_select.deselect("option1") user.should_see("['option2']")