test_number.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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_number_input(screen: Screen):
  7. ui.number('Number', value=42)
  8. ui.button('Button')
  9. screen.open('/')
  10. screen.should_contain_input('42')
  11. element = screen.selenium.find_element(By.XPATH, '//*[@aria-label="Number"]')
  12. element.send_keys('00')
  13. screen.click('Button')
  14. screen.should_contain_input('4200')
  15. def test_apply_format_on_blur(screen: Screen):
  16. ui.number('Number', format='%.4f', value=3.14159)
  17. ui.button('Button')
  18. screen.open('/')
  19. screen.should_contain_input('3.1416')
  20. element = screen.selenium.find_element(By.XPATH, '//*[@aria-label="Number"]')
  21. element.send_keys('789')
  22. screen.click('Button')
  23. screen.should_contain_input('3.1417')
  24. element.click()
  25. element.send_keys(Keys.BACKSPACE * 10 + '2')
  26. screen.click('Button')
  27. screen.should_contain_input('2.0000')
  28. def test_max_value(screen: Screen):
  29. ui.number('Number', min=0, max=10, value=5)
  30. ui.button('Button')
  31. screen.open('/')
  32. screen.should_contain_input('5')
  33. element = screen.selenium.find_element(By.XPATH, '//*[@aria-label="Number"]')
  34. element.send_keys('6')
  35. screen.click('Button')
  36. screen.should_contain_input('10')
  37. def test_clearable_number(screen: Screen):
  38. number = ui.number(value=42).props('clearable')
  39. ui.label().bind_text_from(number, 'value', lambda value: f'value: {value}')
  40. screen.open('/')
  41. screen.should_contain('value: 42')
  42. screen.click('cancel')
  43. screen.should_contain('value: None')
  44. screen.click('value: None') # loose focus
  45. screen.wait(0.5)
  46. screen.should_contain('value: None')
  47. def test_out_of_limits(screen: Screen):
  48. number = ui.number('Number', min=0, max=10, value=5)
  49. ui.label().bind_text_from(number, 'out_of_limits', lambda value: f'out_of_limits: {value}')
  50. screen.open('/')
  51. screen.should_contain('out_of_limits: False')
  52. number.value = 11
  53. screen.should_contain('out_of_limits: True')
  54. number.max = 15
  55. screen.should_contain('out_of_limits: False')
  56. @pytest.mark.parametrize('precision', [None, 1, -1])
  57. def test_rounding(precision: int, screen: Screen):
  58. number = ui.number('Number', value=12, precision=precision)
  59. ui.label().bind_text_from(number, 'value', lambda value: f'number=_{value}_')
  60. screen.open('/')
  61. screen.should_contain('number=_12_')
  62. element = screen.selenium.find_element(By.XPATH, '//*[@aria-label="Number"]')
  63. element.send_keys('.345')
  64. screen.click('number=') # blur the number input
  65. if precision is None:
  66. screen.should_contain('number=_12.345_')
  67. elif precision == 1:
  68. screen.should_contain('number=_12.3_')
  69. elif precision == -1:
  70. screen.should_contain('number=_10.0_')
  71. def test_int_float_conversion_on_error1(screen: Screen):
  72. ui.number('Number', validation={'Error': lambda value: value == 1}, value=1)
  73. screen.open('/')
  74. element = screen.selenium.find_element(By.XPATH, '//*[@aria-label="Number"]')
  75. element.send_keys('2')
  76. screen.should_contain('Error')
  77. assert element.get_attribute('value') == '12'
  78. def test_int_float_conversion_on_error2(screen: Screen):
  79. ui.number('Number', validation={'Error': lambda value: value == 1.02}, value=1.02)
  80. screen.open('/')
  81. element = screen.selenium.find_element(By.XPATH, '//*[@aria-label="Number"]')
  82. element.send_keys(Keys.BACKSPACE)
  83. screen.should_contain('Error')
  84. assert element.get_attribute('value') == '1.0'
  85. def test_changing_limits(screen: Screen):
  86. number = ui.number('Number', max=0, value=0)
  87. ui.button('Raise max', on_click=lambda: setattr(number, 'max', 1))
  88. ui.button('Step up', on_click=lambda: number.run_method('(e) => e.getNativeElement().stepUp()'))
  89. screen.open('/')
  90. screen.should_contain_input('0')
  91. screen.click('Step up')
  92. screen.should_contain_input('0')
  93. screen.click('Raise max')
  94. screen.should_contain_input('0')
  95. screen.click('Step up')
  96. screen.should_contain_input('1')
  97. def test_none_values(screen: Screen):
  98. n = ui.number('Number', on_change=lambda e: ui.label(f'event: {e.value}'))
  99. ui.label().bind_text_from(n, 'value', lambda value: f'model: {value}')
  100. screen.open('/')
  101. element = screen.selenium.find_element(By.XPATH, '//*[@aria-label="Number"]')
  102. element.send_keys('0')
  103. screen.should_contain_input('0')
  104. screen.should_contain('model: 0')
  105. screen.should_contain('event: 0')
  106. element.send_keys(Keys.BACKSPACE)
  107. screen.should_contain_input('')
  108. screen.should_contain('model: None')
  109. screen.should_contain('event: None')
  110. element.send_keys('1')
  111. screen.should_contain_input('1')
  112. screen.should_contain('model: 1')
  113. screen.should_contain('event: 1')