test_input.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import pytest
  2. from selenium.webdriver.common.by import By
  3. from selenium.webdriver.common.keys import Keys
  4. from nicegui import ui
  5. from nicegui.testing import Screen
  6. def test_input(screen: Screen):
  7. ui.input('Your name', value='John Doe')
  8. screen.open('/')
  9. screen.should_contain('Your name')
  10. element = screen.selenium.find_element(By.XPATH, '//*[@aria-label="Your name"]')
  11. assert element.get_attribute('type') == 'text'
  12. assert element.get_attribute('value') == 'John Doe'
  13. element.send_keys(' Jr.')
  14. assert element.get_attribute('value') == 'John Doe Jr.'
  15. def test_password(screen: Screen):
  16. ui.input('Your password', value='123456', password=True)
  17. screen.open('/')
  18. screen.should_contain('Your password')
  19. element = screen.selenium.find_element(By.XPATH, '//*[@aria-label="Your password"]')
  20. assert element.get_attribute('type') == 'password'
  21. assert element.get_attribute('value') == '123456'
  22. element.send_keys('789')
  23. screen.wait(0.5)
  24. assert element.get_attribute('value') == '123456789'
  25. def test_toggle_button(screen: Screen):
  26. ui.input('Your password', value='123456', password=True, password_toggle_button=True)
  27. screen.open('/')
  28. screen.should_contain('Your password')
  29. screen.should_contain('visibility_off')
  30. element = screen.selenium.find_element(By.XPATH, '//*[@aria-label="Your password"]')
  31. assert element.get_attribute('type') == 'password'
  32. assert element.get_attribute('value') == '123456'
  33. screen.click('visibility_off')
  34. screen.wait(0.5)
  35. assert element.get_attribute('type') == 'text'
  36. screen.click('visibility')
  37. screen.wait(0.5)
  38. assert element.get_attribute('type') == 'password'
  39. @pytest.mark.parametrize('use_callable', [False, True])
  40. def test_input_validation(use_callable: bool, screen: Screen):
  41. if use_callable:
  42. input_ = ui.input('Name', validation=lambda x: 'Short' if len(x) < 3 else 'Still short' if len(x) < 5 else None)
  43. else:
  44. input_ = ui.input('Name', validation={'Short': lambda x: len(x) >= 3, 'Still short': lambda x: len(x) >= 5})
  45. screen.open('/')
  46. screen.should_contain('Name')
  47. element = screen.selenium.find_element(By.XPATH, '//*[@aria-label="Name"]')
  48. element.send_keys('Jo')
  49. screen.should_contain('Short')
  50. assert input_.error == 'Short'
  51. assert not input_.validate()
  52. element.send_keys('hn')
  53. screen.should_contain('Still short')
  54. assert input_.error == 'Still short'
  55. assert not input_.validate()
  56. element.send_keys(' Doe')
  57. screen.wait(1.0)
  58. screen.should_not_contain('Short')
  59. screen.should_not_contain('Still short')
  60. assert input_.error is None
  61. assert input_.validate()
  62. def test_input_with_multi_word_error_message(screen: Screen):
  63. input_ = ui.input(label='some input')
  64. ui.button('set error', on_click=lambda: input_.props('error error-message="Some multi word error message"'))
  65. screen.open('/')
  66. screen.should_not_contain('Some multi word error message')
  67. screen.click('set error')
  68. screen.should_contain('Some multi word error message')
  69. def test_autocompletion(screen: Screen):
  70. input_ = ui.input('Input', autocomplete=['foo', 'bar', 'baz'])
  71. screen.open('/')
  72. element = screen.selenium.find_element(By.XPATH, '//*[@aria-label="Input"]')
  73. element.send_keys('f')
  74. screen.should_contain('oo')
  75. element.send_keys('l')
  76. screen.wait(0.5)
  77. screen.should_not_contain('oo')
  78. element.send_keys(Keys.BACKSPACE)
  79. screen.should_contain('oo')
  80. element.send_keys(Keys.TAB)
  81. screen.wait(0.2)
  82. assert element.get_attribute('value') == 'foo'
  83. assert input_.value == 'foo'
  84. element.send_keys(Keys.BACKSPACE)
  85. element.send_keys(Keys.BACKSPACE)
  86. element.send_keys('x')
  87. element.send_keys(Keys.TAB)
  88. screen.wait(0.5)
  89. assert element.get_attribute('value') == 'fx'
  90. assert input_.value == 'fx'
  91. input_.set_autocomplete(['one', 'two'])
  92. element.send_keys(Keys.BACKSPACE)
  93. element.send_keys(Keys.BACKSPACE)
  94. element.send_keys('o')
  95. screen.should_contain('ne')
  96. def test_clearable_input(screen: Screen):
  97. input_ = ui.input(value='foo').props('clearable')
  98. ui.label().bind_text_from(input_, 'value', lambda value: f'value: {value}')
  99. screen.open('/')
  100. screen.should_contain('value: foo')
  101. screen.click('cancel')
  102. screen.should_contain('value: None')
  103. def test_update_input(screen: Screen):
  104. input_ = ui.input('Name', value='Pete')
  105. screen.open('/')
  106. element = screen.selenium.find_element(By.XPATH, '//*[@aria-label="Name"]')
  107. assert element.get_attribute('value') == 'Pete'
  108. element.send_keys('r')
  109. screen.wait(0.5)
  110. assert element.get_attribute('value') == 'Peter'
  111. input_.value = 'Pete'
  112. screen.wait(0.5)
  113. assert element.get_attribute('value') == 'Pete'
  114. def test_switching_focus(screen: Screen):
  115. input1 = ui.input()
  116. input2 = ui.input()
  117. ui.button('focus 1', on_click=lambda: input1.run_method('focus'))
  118. ui.button('focus 2', on_click=lambda: input2.run_method('focus'))
  119. screen.open('/')
  120. elements = screen.selenium.find_elements(By.XPATH, '//input')
  121. assert len(elements) == 2
  122. screen.click('focus 1')
  123. screen.wait(0.3)
  124. assert elements[0] == screen.selenium.switch_to.active_element
  125. screen.click('focus 2')
  126. screen.wait(0.3)
  127. assert elements[1] == screen.selenium.switch_to.active_element