123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- from typing import Optional
- import pytest
- from selenium.webdriver import Keys
- from nicegui import ui
- from nicegui.testing import Screen
- def test_select(screen: Screen):
- ui.select(['A', 'B', 'C'], value='A')
- screen.open('/')
- screen.should_contain('A')
- screen.should_not_contain('B')
- screen.should_not_contain('C')
- screen.click('A') # open the dropdown
- screen.click('B') # close the dropdown
- screen.wait(0.5)
- screen.should_not_contain('A')
- screen.should_contain('B')
- screen.should_not_contain('C')
- def test_select_with_input(screen: Screen):
- ui.select(['A', 'AB', 'XYZ'], with_input=True)
- screen.open('/')
- screen.find_by_tag('input').click()
- screen.should_contain('XYZ')
- screen.find_by_tag('input').send_keys('A')
- screen.wait(0.5)
- screen.should_contain('A')
- screen.should_contain('AB')
- screen.should_not_contain('XYZ')
- screen.find_by_tag('input').send_keys('ABC' + Keys.ENTER)
- screen.find_by_tag('input').click()
- screen.should_not_contain('ABC')
- def test_replace_select(screen: Screen):
- with ui.row() as container:
- ui.select(['A'], value='A')
- def replace():
- container.clear()
- with container:
- ui.select(['B'], value='B')
- ui.button('Replace', on_click=replace)
- screen.open('/')
- screen.should_contain('A')
- screen.click('Replace')
- screen.should_contain('B')
- screen.should_not_contain('A')
- def test_multi_select(screen: Screen):
- s = ui.select(['Alice', 'Bob', 'Carol'], value='Alice', multiple=True).props('use-chips')
- ui.label().bind_text_from(s, 'value', backward=str)
- screen.open('/')
- screen.should_contain("['Alice']")
- screen.click('Alice')
- screen.click('Bob')
- screen.should_contain("['Alice', 'Bob']")
- screen.click('cancel') # remove icon
- screen.should_contain("['Bob']")
- def test_changing_options(screen: Screen):
- s = ui.select([10, 20, 30], value=10)
- ui.label().bind_text_from(s, 'value', lambda v: f'value = {v}')
- ui.button('reverse', on_click=lambda: (s.options.reverse(), s.update()))
- ui.button('clear', on_click=lambda: (s.options.clear(), s.update()))
- screen.open('/')
- screen.click('reverse')
- screen.should_contain('value = 10')
- screen.click('clear')
- screen.should_contain('value = None')
- def test_set_options(screen: Screen):
- s = ui.select([1, 2, 3], value=1)
- ui.button('Set new options', on_click=lambda: s.set_options([4, 5, 6], value=4))
- screen.open('/')
- screen.click('Set new options')
- screen.click('4')
- screen.should_contain('5')
- screen.should_contain('6')
- @pytest.mark.parametrize('option_dict', [False, True])
- @pytest.mark.parametrize('multiple', [False, True])
- @pytest.mark.parametrize('new_value_mode', ['add', 'add-unique', 'toggle', None])
- def test_add_new_values(screen: Screen, option_dict: bool, multiple: bool, new_value_mode: Optional[str]):
- options = {'a': 'A', 'b': 'B', 'c': 'C'} if option_dict else ['a', 'b', 'c']
- if option_dict and new_value_mode == 'add':
- with pytest.raises(ValueError, match='new_value_mode "add" is not supported for dict options'):
- ui.select(options=options, multiple=multiple, new_value_mode=new_value_mode)
- return
- s = ui.select(options=options, multiple=multiple, new_value_mode=new_value_mode)
- ui.label().bind_text_from(s, 'value', lambda v: f'value = {v}')
- ui.label().bind_text_from(s, 'options', lambda v: f'options = {v}')
- screen.open('/')
- screen.should_contain('value = []' if multiple else 'value = None')
- screen.should_contain("options = {'a': 'A', 'b': 'B', 'c': 'C'}" if option_dict else "options = ['a', 'b', 'c']")
- screen.find_by_class('q-select').click()
- screen.wait(0.5)
- screen.find_all('A' if option_dict else 'a')[-1].click()
- screen.should_contain("value = ['a']" if multiple else 'value = a')
- if new_value_mode:
- for _ in range(2):
- screen.find_by_tag('input').send_keys(Keys.BACKSPACE + 'd')
- screen.wait(0.5)
- screen.find_by_tag('input').click()
- screen.wait(0.5)
- screen.find_by_tag('input').send_keys(Keys.ENTER)
- screen.wait(0.5)
- if new_value_mode == 'add':
- screen.should_contain("value = ['a', 'd', 'd']" if multiple else 'value = d')
- screen.should_contain("options = {'a': 'A', 'b': 'B', 'c': 'C', 'd': 'd', 'd': 'd'}" if option_dict else
- "options = ['a', 'b', 'c', 'd', 'd']")
- elif new_value_mode == 'add-unique':
- screen.should_contain("value = ['a', 'd', 'd']" if multiple else 'value = d')
- screen.should_contain("options = {'a': 'A', 'b': 'B', 'c': 'C', 'd': 'd'}" if option_dict else
- "options = ['a', 'b', 'c', 'd']")
- elif new_value_mode == 'toggle':
- screen.should_contain("value = ['a']" if multiple else 'value = None')
- screen.should_contain("options = {'a': 'A', 'b': 'B', 'c': 'C'}" if option_dict else
- "options = ['a', 'b', 'c']")
- @pytest.mark.parametrize('multiple', [False, True])
- def test_keep_filtered_options(multiple: bool, screen: Screen):
- ui.select(options=['A1', 'A2', 'B1', 'B2'], with_input=True, multiple=multiple)
- screen.open('/')
- screen.find_by_tag('input').click()
- screen.should_contain('A1')
- screen.should_contain('A2')
- screen.should_contain('B1')
- screen.should_contain('B2')
- screen.find_by_tag('input').send_keys('A')
- screen.wait(0.5)
- screen.should_contain('A1')
- screen.should_contain('A2')
- screen.should_not_contain('B1')
- screen.should_not_contain('B2')
- screen.click('A1')
- screen.wait(0.5)
- screen.find_by_tag('input').click()
- screen.should_contain('A1')
- screen.should_contain('A2')
- if multiple:
- screen.should_not_contain('B1')
- screen.should_not_contain('B2')
- else:
- screen.should_contain('B1')
- screen.should_contain('B2')
- def test_select_validation(screen: Screen):
- ui.select(['A', 'BC', 'DEF'], value='A', validation={'Too long': lambda v: len(v) < 3})
- screen.open('/')
- screen.click('A')
- screen.click('DEF')
- screen.should_contain('Too long')
|