浏览代码

Merge pull request #2245 from zauberzeug/pytest-example

Introduce new testing module and a new pytest example
Rodja Trappe 1 年之前
父节点
当前提交
aa624e8f51
共有 84 个文件被更改,包括 231 次插入263 次删除
  1. 1 1
      .gitignore
  2. 1 1
      README.md
  3. 1 0
      examples/pytest/.gitignore
  4. 1 0
      examples/pytest/conftest.py
  5. 12 0
      examples/pytest/main.py
  6. 17 0
      examples/pytest/test_main_page.py
  7. 7 0
      nicegui/testing/__init__.py
  8. 112 0
      nicegui/testing/conftest.py
  9. 2 3
      nicegui/testing/screen.py
  10. 0 0
      screenshot.png
  11. 1 1
      tests/README.md
  12. 1 112
      tests/conftest.py
  13. 1 2
      tests/test_aggrid.py
  14. 1 2
      tests/test_api_router.py
  15. 1 2
      tests/test_audio.py
  16. 1 2
      tests/test_auto_context.py
  17. 1 2
      tests/test_binding.py
  18. 1 2
      tests/test_button.py
  19. 1 2
      tests/test_carousel.py
  20. 1 2
      tests/test_chat.py
  21. 1 2
      tests/test_code.py
  22. 1 2
      tests/test_color_input.py
  23. 1 2
      tests/test_colors.py
  24. 1 2
      tests/test_context_menu.py
  25. 1 2
      tests/test_dark_mode.py
  26. 1 2
      tests/test_date.py
  27. 1 2
      tests/test_dialog.py
  28. 4 6
      tests/test_download.py
  29. 1 2
      tests/test_echart.py
  30. 1 2
      tests/test_editor.py
  31. 1 2
      tests/test_element.py
  32. 1 2
      tests/test_element_delete.py
  33. 1 2
      tests/test_endpoint_docs.py
  34. 1 2
      tests/test_events.py
  35. 1 2
      tests/test_expansion.py
  36. 1 2
      tests/test_favicon.py
  37. 1 2
      tests/test_header.py
  38. 1 2
      tests/test_highchart.py
  39. 1 2
      tests/test_image.py
  40. 1 2
      tests/test_input.py
  41. 1 2
      tests/test_interactive_image.py
  42. 1 2
      tests/test_javascript.py
  43. 1 2
      tests/test_joystick.py
  44. 1 2
      tests/test_json_editor.py
  45. 1 2
      tests/test_keyboard.py
  46. 1 2
      tests/test_knob.py
  47. 1 2
      tests/test_label.py
  48. 1 2
      tests/test_leaflet.py
  49. 1 2
      tests/test_lifecycle.py
  50. 1 2
      tests/test_link.py
  51. 1 2
      tests/test_log.py
  52. 1 2
      tests/test_markdown.py
  53. 1 2
      tests/test_menu.py
  54. 1 2
      tests/test_mermaid.py
  55. 1 2
      tests/test_notification.py
  56. 1 2
      tests/test_number.py
  57. 1 2
      tests/test_observables.py
  58. 1 2
      tests/test_open.py
  59. 1 2
      tests/test_page.py
  60. 1 2
      tests/test_page_title.py
  61. 1 2
      tests/test_pagination.py
  62. 1 2
      tests/test_plotly.py
  63. 1 2
      tests/test_prod_js.py
  64. 1 2
      tests/test_query.py
  65. 1 2
      tests/test_radio.py
  66. 1 2
      tests/test_refreshable.py
  67. 1 2
      tests/test_scene.py
  68. 1 2
      tests/test_select.py
  69. 1 1
      tests/test_serving_files.py
  70. 1 2
      tests/test_spinner.py
  71. 1 2
      tests/test_splitter.py
  72. 1 2
      tests/test_stepper.py
  73. 1 2
      tests/test_storage.py
  74. 1 2
      tests/test_table.py
  75. 1 2
      tests/test_tabs.py
  76. 1 2
      tests/test_tailwind.py
  77. 1 2
      tests/test_time.py
  78. 1 2
      tests/test_timeline.py
  79. 1 2
      tests/test_timer.py
  80. 1 2
      tests/test_toggle.py
  81. 1 2
      tests/test_tree.py
  82. 1 2
      tests/test_upload.py
  83. 1 2
      tests/test_video.py
  84. 1 0
      website/examples.py

+ 1 - 1
.gitignore

@@ -4,7 +4,7 @@ __pycache__/
 dist
 dist
 /test.py
 /test.py
 *.pickle
 *.pickle
-tests/screenshots/
+screenshots/
 tests/media/
 tests/media/
 venv
 venv
 .idea
 .idea

+ 1 - 1
README.md

@@ -1,5 +1,5 @@
 <a href="http://nicegui.io/#about">
 <a href="http://nicegui.io/#about">
-  <img src="https://raw.githubusercontent.com/zauberzeug/nicegui/main/sceenshots/ui-elements-narrow.png"
+  <img src="https://raw.githubusercontent.com/zauberzeug/nicegui/main/screenshot.png"
     width="200" align="right" alt="Try online!" />
     width="200" align="right" alt="Try online!" />
 </a>
 </a>
 
 

+ 1 - 0
examples/pytest/.gitignore

@@ -0,0 +1 @@
+screenshots/

+ 1 - 0
examples/pytest/conftest.py

@@ -0,0 +1 @@
+from nicegui.testing.conftest import *

+ 12 - 0
examples/pytest/main.py

@@ -0,0 +1,12 @@
+#!/usr/bin/env python3
+from nicegui import ui
+
+
+@ui.page('/')
+def main_page() -> None:
+    ui.markdown('Try running `pytest` on this project!')
+    ui.button('Click me', on_click=lambda: ui.notify('Button clicked!'))
+
+
+if __name__ in {'__main__', '__mp_main__'}:
+    ui.run()

+ 17 - 0
examples/pytest/test_main_page.py

@@ -0,0 +1,17 @@
+from main import main_page
+from nicegui.testing import Screen
+
+
+def test_markdown_message(screen: Screen) -> None:
+    main_page()
+
+    screen.open('/')
+    screen.should_contain('Try running')
+
+
+def test_button_click(screen: Screen) -> None:
+    main_page()
+
+    screen.open('/')
+    screen.click('Click me')
+    screen.should_contain('Button clicked!')

+ 7 - 0
nicegui/testing/__init__.py

@@ -0,0 +1,7 @@
+from . import conftest
+from .screen import Screen
+
+__all__ = [
+    'conftest',
+    'Screen',
+]

+ 112 - 0
nicegui/testing/conftest.py

@@ -0,0 +1,112 @@
+import importlib
+import os
+import shutil
+from pathlib import Path
+from typing import Dict, Generator
+
+import icecream
+import pytest
+from selenium import webdriver
+from selenium.webdriver.chrome.service import Service
+from starlette.routing import Route
+
+from nicegui import Client, app, binding, core
+from nicegui.page import page
+
+from .screen import Screen
+
+# pylint: disable=redefined-outer-name
+
+DOWNLOAD_DIR = Path(__file__).parent / 'download'
+
+icecream.install()
+
+
+@pytest.fixture
+def chrome_options(chrome_options: webdriver.ChromeOptions) -> webdriver.ChromeOptions:
+    """Configure the Chrome driver options."""
+    chrome_options.add_argument('disable-dev-shm-using')
+    chrome_options.add_argument('no-sandbox')
+    chrome_options.add_argument('headless')
+    # check if we are running on GitHub Actions
+    if 'GITHUB_ACTIONS' in os.environ:
+        chrome_options.add_argument('disable-gpu')
+    else:
+        chrome_options.add_argument('--use-gl=angle')
+    chrome_options.add_argument('window-size=600x600')
+    chrome_options.add_experimental_option('prefs', {
+        "download.default_directory": str(DOWNLOAD_DIR),
+        "download.prompt_for_download": False,  # To auto download the file
+        "download.directory_upgrade": True,
+    })
+    if 'CHROME_BINARY_LOCATION' in os.environ:
+        chrome_options.binary_location = os.environ['CHROME_BINARY_LOCATION']
+    return chrome_options
+
+
+@pytest.fixture
+def capabilities(capabilities: Dict) -> Dict:
+    """Configure the Chrome driver capabilities."""
+    capabilities['goog:loggingPrefs'] = {'browser': 'ALL'}
+    return capabilities
+
+
+@pytest.fixture(autouse=True)
+def reset_globals() -> Generator[None, None, None]:
+    """Reset the global state of the NiceGUI package."""
+    for route in app.routes:
+        if isinstance(route, Route) and route.path.startswith('/_nicegui/auto/static/'):
+            app.remove_route(route.path)
+    for path in {'/'}.union(Client.page_routes.values()):
+        app.remove_route(path)
+    app.openapi_schema = None
+    app.middleware_stack = None
+    app.user_middleware.clear()
+    # NOTE favicon routes must be removed separately because they are not "pages"
+    for route in app.routes:
+        if isinstance(route, Route) and route.path.endswith('/favicon.ico'):
+            app.routes.remove(route)
+    importlib.reload(core)
+    Client.instances.clear()
+    Client.page_routes.clear()
+    Client.auto_index_client = Client(page('/'), shared=True).__enter__()
+    app.reset()
+    # NOTE we need to re-add the auto index route because we removed all routes above
+    app.get('/')(Client.auto_index_client.build_response)
+    binding.reset()
+    yield
+
+
+@pytest.fixture(scope='session', autouse=True)
+def remove_all_screenshots() -> None:
+    """Remove all screenshots from the screenshot directory before the test session."""
+    if os.path.exists(Screen.SCREENSHOT_DIR):
+        for name in os.listdir(Screen.SCREENSHOT_DIR):
+            os.remove(os.path.join(Screen.SCREENSHOT_DIR, name))
+
+
+@pytest.fixture(scope='function')
+def driver(chrome_options: webdriver.ChromeOptions) -> webdriver.Chrome:
+    """Create a new Chrome driver instance."""
+    s = Service()
+    driver_ = webdriver.Chrome(service=s, options=chrome_options)
+    driver_.implicitly_wait(Screen.IMPLICIT_WAIT)
+    driver_.set_page_load_timeout(4)
+    yield driver_
+    driver_.quit()
+
+
+@pytest.fixture
+def screen(driver: webdriver.Chrome, request: pytest.FixtureRequest, caplog: pytest.LogCaptureFixture) \
+        -> Generator[Screen, None, None]:
+    """Create a new Screen instance."""
+    screen_ = Screen(driver, caplog)
+    yield screen_
+    if screen_.is_open:
+        screen_.shot(request.node.name)
+    logs = screen_.caplog.get_records('call')
+    screen_.stop_server()
+    if DOWNLOAD_DIR.exists():
+        shutil.rmtree(DOWNLOAD_DIR)
+    if logs:
+        pytest.fail('There were unexpected logs. See "Captured log call" below.', pytrace=False)

+ 2 - 3
tests/screen.py → nicegui/testing/screen.py

@@ -3,6 +3,7 @@ import re
 import threading
 import threading
 import time
 import time
 from contextlib import contextmanager
 from contextlib import contextmanager
+from pathlib import Path
 from typing import List, Optional, Union
 from typing import List, Optional, Union
 
 
 import pytest
 import pytest
@@ -16,13 +17,11 @@ from selenium.webdriver.remote.webelement import WebElement
 from nicegui import app, ui
 from nicegui import app, ui
 from nicegui.server import Server
 from nicegui.server import Server
 
 
-from .test_helpers import TEST_DIR
-
 
 
 class Screen:
 class Screen:
     PORT = 3392
     PORT = 3392
     IMPLICIT_WAIT = 4
     IMPLICIT_WAIT = 4
-    SCREENSHOT_DIR = TEST_DIR / 'screenshots'
+    SCREENSHOT_DIR = Path('screenshots')
 
 
     def __init__(self, selenium: webdriver.Chrome, caplog: pytest.LogCaptureFixture) -> None:
     def __init__(self, selenium: webdriver.Chrome, caplog: pytest.LogCaptureFixture) -> None:
         self.selenium = selenium
         self.selenium = selenium

+ 0 - 0
sceenshots/ui-elements-narrow.png → screenshot.png


+ 1 - 1
tests/README.md

@@ -61,7 +61,7 @@ Here is a very simple example:
 
 
 ```py
 ```py
 from nicegui import ui
 from nicegui import ui
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 def test_hello_world(screen: Screen):
 def test_hello_world(screen: Screen):
     ui.label('Hello, world')
     ui.label('Hello, world')

+ 1 - 112
tests/conftest.py

@@ -1,112 +1 @@
-import importlib
-import os
-import shutil
-from pathlib import Path
-from typing import Dict, Generator
-
-import icecream
-import pytest
-from selenium import webdriver
-from selenium.webdriver.chrome.service import Service
-from starlette.routing import Route
-
-from nicegui import Client, app, binding, core
-from nicegui.page import page
-
-from .screen import Screen
-
-# pylint: disable=redefined-outer-name
-
-DOWNLOAD_DIR = Path(__file__).parent / 'download'
-
-icecream.install()
-
-
-@pytest.fixture
-def chrome_options(chrome_options: webdriver.ChromeOptions) -> webdriver.ChromeOptions:
-    """Configure the Chrome driver options."""
-    chrome_options.add_argument('disable-dev-shm-using')
-    chrome_options.add_argument('no-sandbox')
-    chrome_options.add_argument('headless')
-    # check if we are running on GitHub Actions
-    if 'GITHUB_ACTIONS' in os.environ:
-        chrome_options.add_argument('disable-gpu')
-    else:
-        chrome_options.add_argument('--use-gl=angle')
-    chrome_options.add_argument('window-size=600x600')
-    chrome_options.add_experimental_option('prefs', {
-        "download.default_directory": str(DOWNLOAD_DIR),
-        "download.prompt_for_download": False,  # To auto download the file
-        "download.directory_upgrade": True,
-    })
-    if 'CHROME_BINARY_LOCATION' in os.environ:
-        chrome_options.binary_location = os.environ['CHROME_BINARY_LOCATION']
-    return chrome_options
-
-
-@pytest.fixture
-def capabilities(capabilities: Dict) -> Dict:
-    """Configure the Chrome driver capabilities."""
-    capabilities['goog:loggingPrefs'] = {'browser': 'ALL'}
-    return capabilities
-
-
-@pytest.fixture(autouse=True)
-def reset_globals() -> Generator[None, None, None]:
-    """Reset the global state of the NiceGUI package."""
-    for route in app.routes:
-        if isinstance(route, Route) and route.path.startswith('/_nicegui/auto/static/'):
-            app.remove_route(route.path)
-    for path in {'/'}.union(Client.page_routes.values()):
-        app.remove_route(path)
-    app.openapi_schema = None
-    app.middleware_stack = None
-    app.user_middleware.clear()
-    # NOTE favicon routes must be removed separately because they are not "pages"
-    for route in app.routes:
-        if isinstance(route, Route) and route.path.endswith('/favicon.ico'):
-            app.routes.remove(route)
-    importlib.reload(core)
-    Client.instances.clear()
-    Client.page_routes.clear()
-    Client.auto_index_client = Client(page('/'), shared=True).__enter__()
-    app.reset()
-    # NOTE we need to re-add the auto index route because we removed all routes above
-    app.get('/')(Client.auto_index_client.build_response)
-    binding.reset()
-    yield
-
-
-@pytest.fixture(scope='session', autouse=True)
-def remove_all_screenshots() -> None:
-    """Remove all screenshots from the screenshot directory before the test session."""
-    if os.path.exists(Screen.SCREENSHOT_DIR):
-        for name in os.listdir(Screen.SCREENSHOT_DIR):
-            os.remove(os.path.join(Screen.SCREENSHOT_DIR, name))
-
-
-@pytest.fixture(scope='function')
-def driver(chrome_options: webdriver.ChromeOptions) -> webdriver.Chrome:
-    """Create a new Chrome driver instance."""
-    s = Service()
-    driver_ = webdriver.Chrome(service=s, options=chrome_options)
-    driver_.implicitly_wait(Screen.IMPLICIT_WAIT)
-    driver_.set_page_load_timeout(4)
-    yield driver_
-    driver_.quit()
-
-
-@pytest.fixture
-def screen(driver: webdriver.Chrome, request: pytest.FixtureRequest, caplog: pytest.LogCaptureFixture) \
-        -> Generator[Screen, None, None]:
-    """Create a new Screen instance."""
-    screen_ = Screen(driver, caplog)
-    yield screen_
-    if screen_.is_open:
-        screen_.shot(request.node.name)
-    logs = screen_.caplog.get_records('call')
-    screen_.stop_server()
-    if DOWNLOAD_DIR.exists():
-        shutil.rmtree(DOWNLOAD_DIR)
-    if logs:
-        pytest.fail('There were unexpected logs. See "Captured log call" below.', pytrace=False)
+from nicegui.testing.conftest import *  # pylint: disable=wildcard-import,unused-wildcard-import

+ 1 - 2
tests/test_aggrid.py

@@ -5,8 +5,7 @@ from selenium.webdriver.common.action_chains import ActionChains
 from selenium.webdriver.common.keys import Keys
 from selenium.webdriver.common.keys import Keys
 
 
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_update_table(screen: Screen):
 def test_update_table(screen: Screen):

+ 1 - 2
tests/test_api_router.py

@@ -1,7 +1,6 @@
 
 
 from nicegui import APIRouter, app, ui
 from nicegui import APIRouter, app, ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_prefix(screen: Screen):
 def test_prefix(screen: Screen):

+ 1 - 2
tests/test_audio.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_replace_audio(screen: Screen):
 def test_replace_audio(screen: Screen):

+ 1 - 2
tests/test_auto_context.py

@@ -3,8 +3,7 @@ import asyncio
 from selenium.webdriver.common.by import By
 from selenium.webdriver.common.by import By
 
 
 from nicegui import Client, background_tasks, ui
 from nicegui import Client, background_tasks, ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_adding_element_to_shared_index_page(screen: Screen):
 def test_adding_element_to_shared_index_page(screen: Screen):

+ 1 - 2
tests/test_binding.py

@@ -1,8 +1,7 @@
 from selenium.webdriver.common.keys import Keys
 from selenium.webdriver.common.keys import Keys
 
 
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_ui_select_with_tuple_as_key(screen: Screen):
 def test_ui_select_with_tuple_as_key(screen: Screen):

+ 1 - 2
tests/test_button.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_quasar_colors(screen: Screen):
 def test_quasar_colors(screen: Screen):

+ 1 - 2
tests/test_carousel.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_carousel(screen: Screen):
 def test_carousel(screen: Screen):

+ 1 - 2
tests/test_chat.py

@@ -1,8 +1,7 @@
 from selenium.webdriver.common.by import By
 from selenium.webdriver.common.by import By
 
 
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_no_html(screen: Screen):
 def test_no_html(screen: Screen):

+ 1 - 2
tests/test_code.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_code(screen: Screen):
 def test_code(screen: Screen):

+ 1 - 2
tests/test_color_input.py

@@ -1,8 +1,7 @@
 from selenium.webdriver.common.keys import Keys
 from selenium.webdriver.common.keys import Keys
 
 
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_entering_color(screen: Screen):
 def test_entering_color(screen: Screen):

+ 1 - 2
tests/test_colors.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_replace_colors(screen: Screen):
 def test_replace_colors(screen: Screen):

+ 1 - 2
tests/test_context_menu.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_context_menu(screen: Screen):
 def test_context_menu(screen: Screen):

+ 1 - 2
tests/test_dark_mode.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_dark_mode(screen: Screen):
 def test_dark_mode(screen: Screen):

+ 1 - 2
tests/test_date.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_date(screen: Screen):
 def test_date(screen: Screen):

+ 1 - 2
tests/test_dialog.py

@@ -3,8 +3,7 @@ from typing import List
 from selenium.webdriver.common.keys import Keys
 from selenium.webdriver.common.keys import Keys
 
 
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_open_close_dialog(screen: Screen):
 def test_open_close_dialog(screen: Screen):

+ 4 - 6
tests/test_download.py

@@ -5,9 +5,7 @@ import pytest
 from fastapi.responses import PlainTextResponse
 from fastapi.responses import PlainTextResponse
 
 
 from nicegui import app, ui
 from nicegui import app, ui
-
-from .conftest import DOWNLOAD_DIR
-from .screen import Screen
+from nicegui.testing import Screen, conftest
 
 
 
 
 @pytest.fixture
 @pytest.fixture
@@ -27,7 +25,7 @@ def test_download_text_file(screen: Screen, test_route: str):  # pylint: disable
     screen.open('/')
     screen.open('/')
     screen.click('Download')
     screen.click('Download')
     screen.wait(0.5)
     screen.wait(0.5)
-    assert (DOWNLOAD_DIR / 'test.txt').read_text() == 'test'
+    assert (conftest.DOWNLOAD_DIR / 'test.txt').read_text() == 'test'
 
 
 
 
 def test_downloading_local_file_as_src(screen: Screen):
 def test_downloading_local_file_as_src(screen: Screen):
@@ -38,7 +36,7 @@ def test_downloading_local_file_as_src(screen: Screen):
     route_count_before_download = len(app.routes)
     route_count_before_download = len(app.routes)
     screen.click('download')
     screen.click('download')
     screen.wait(0.5)
     screen.wait(0.5)
-    assert (DOWNLOAD_DIR / 'slide1.jpg').exists()
+    assert (conftest.DOWNLOAD_DIR / 'slide1.jpg').exists()
     assert len(app.routes) == route_count_before_download
     assert len(app.routes) == route_count_before_download
 
 
 
 
@@ -48,4 +46,4 @@ def test_download_raw_data(screen: Screen):
     screen.open('/')
     screen.open('/')
     screen.click('download')
     screen.click('download')
     screen.wait(0.5)
     screen.wait(0.5)
-    assert (DOWNLOAD_DIR / 'test.txt').read_text() == 'test'
+    assert (conftest.DOWNLOAD_DIR / 'test.txt').read_text() == 'test'

+ 1 - 2
tests/test_echart.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_create_dynamically(screen: Screen):
 def test_create_dynamically(screen: Screen):

+ 1 - 2
tests/test_editor.py

@@ -1,7 +1,6 @@
 
 
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_editor(screen: Screen):
 def test_editor(screen: Screen):

+ 1 - 2
tests/test_element.py

@@ -2,8 +2,7 @@ import pytest
 from selenium.webdriver.common.by import By
 from selenium.webdriver.common.by import By
 
 
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_classes(screen: Screen):
 def test_classes(screen: Screen):

+ 1 - 2
tests/test_element_delete.py

@@ -1,6 +1,5 @@
 from nicegui import binding, ui
 from nicegui import binding, ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_remove_element_by_reference(screen: Screen):
 def test_remove_element_by_reference(screen: Screen):

+ 1 - 2
tests/test_endpoint_docs.py

@@ -3,8 +3,7 @@ from typing import Set
 import requests
 import requests
 
 
 from nicegui import __version__
 from nicegui import __version__
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def get_openapi_paths() -> Set[str]:
 def get_openapi_paths() -> Set[str]:

+ 1 - 2
tests/test_events.py

@@ -6,8 +6,7 @@ from selenium.webdriver.common.by import By
 
 
 from nicegui import ui
 from nicegui import ui
 from nicegui.events import ClickEventArguments
 from nicegui.events import ClickEventArguments
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def click_sync_no_args():
 def click_sync_no_args():

+ 1 - 2
tests/test_expansion.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_open_close_expansion(screen: Screen):
 def test_open_close_expansion(screen: Screen):

+ 1 - 2
tests/test_favicon.py

@@ -5,8 +5,7 @@ import requests
 from bs4 import BeautifulSoup
 from bs4 import BeautifulSoup
 
 
 from nicegui import favicon, ui
 from nicegui import favicon, ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 DEFAULT_FAVICON_PATH = Path(__file__).parent.parent / 'nicegui' / 'static' / 'favicon.ico'
 DEFAULT_FAVICON_PATH = Path(__file__).parent.parent / 'nicegui' / 'static' / 'favicon.ico'
 LOGO_FAVICON_PATH = Path(__file__).parent.parent / 'website' / 'static' / 'logo_square.png'
 LOGO_FAVICON_PATH = Path(__file__).parent.parent / 'website' / 'static' / 'logo_square.png'

+ 1 - 2
tests/test_header.py

@@ -1,8 +1,7 @@
 import pytest
 import pytest
 
 
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 @pytest.mark.parametrize('add_scroll_padding', [True, False])
 @pytest.mark.parametrize('add_scroll_padding', [True, False])

+ 1 - 2
tests/test_highchart.py

@@ -1,8 +1,7 @@
 from selenium.webdriver.common.by import By
 from selenium.webdriver.common.by import By
 
 
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_change_chart_series(screen: Screen):
 def test_change_chart_series(screen: Screen):

+ 1 - 2
tests/test_image.py

@@ -1,8 +1,7 @@
 from pathlib import Path
 from pathlib import Path
 
 
 from nicegui import app, ui
 from nicegui import app, ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 example_file = Path(__file__).parent / '../examples/slideshow/slides/slide1.jpg'
 example_file = Path(__file__).parent / '../examples/slideshow/slides/slide1.jpg'
 
 

+ 1 - 2
tests/test_input.py

@@ -2,8 +2,7 @@ from selenium.webdriver.common.by import By
 from selenium.webdriver.common.keys import Keys
 from selenium.webdriver.common.keys import Keys
 
 
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_input(screen: Screen):
 def test_input(screen: Screen):

+ 1 - 2
tests/test_interactive_image.py

@@ -2,8 +2,7 @@ import pytest
 from selenium.webdriver.common.action_chains import ActionChains
 from selenium.webdriver.common.action_chains import ActionChains
 
 
 from nicegui import Client, ui
 from nicegui import Client, ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_set_source_in_tab(screen: Screen):
 def test_set_source_in_tab(screen: Screen):

+ 1 - 2
tests/test_javascript.py

@@ -1,8 +1,7 @@
 import pytest
 import pytest
 
 
 from nicegui import Client, ui
 from nicegui import Client, ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_run_javascript_on_button_press(screen: Screen):
 def test_run_javascript_on_button_press(screen: Screen):

+ 1 - 2
tests/test_joystick.py

@@ -1,8 +1,7 @@
 from selenium.webdriver.common.action_chains import ActionChains
 from selenium.webdriver.common.action_chains import ActionChains
 
 
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_joystick(screen: Screen):
 def test_joystick(screen: Screen):

+ 1 - 2
tests/test_json_editor.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_json_editor_methods(screen: Screen):
 def test_json_editor_methods(screen: Screen):

+ 1 - 2
tests/test_keyboard.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_keyboard(screen: Screen):
 def test_keyboard(screen: Screen):

+ 1 - 2
tests/test_knob.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_knob(screen: Screen):
 def test_knob(screen: Screen):

+ 1 - 2
tests/test_label.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_hello_world(screen: Screen):
 def test_hello_world(screen: Screen):

+ 1 - 2
tests/test_leaflet.py

@@ -1,8 +1,7 @@
 import time
 import time
 
 
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_leaflet(screen: Screen):
 def test_leaflet(screen: Screen):

+ 1 - 2
tests/test_lifecycle.py

@@ -1,8 +1,7 @@
 from typing import List
 from typing import List
 
 
 from nicegui import Client, app, ui
 from nicegui import Client, app, ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_adding_elements_during_onconnect_on_auto_index_page(screen: Screen):
 def test_adding_elements_during_onconnect_on_auto_index_page(screen: Screen):

+ 1 - 2
tests/test_link.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_local_target_linking_on_sub_pages(screen: Screen):
 def test_local_target_linking_on_sub_pages(screen: Screen):

+ 1 - 2
tests/test_log.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_log(screen: Screen):
 def test_log(screen: Screen):

+ 1 - 2
tests/test_markdown.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_markdown(screen: Screen):
 def test_markdown(screen: Screen):

+ 1 - 2
tests/test_menu.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_menu(screen: Screen):
 def test_menu(screen: Screen):

+ 1 - 2
tests/test_mermaid.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_mermaid(screen: Screen):
 def test_mermaid(screen: Screen):

+ 1 - 2
tests/test_notification.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_notification(screen: Screen):
 def test_notification(screen: Screen):

+ 1 - 2
tests/test_number.py

@@ -2,8 +2,7 @@ import pytest
 from selenium.webdriver.common.by import By
 from selenium.webdriver.common.by import By
 
 
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_number_input(screen: Screen):
 def test_number_input(screen: Screen):

+ 1 - 2
tests/test_observables.py

@@ -3,8 +3,7 @@ import sys
 
 
 from nicegui import ui
 from nicegui import ui
 from nicegui.observables import ObservableDict, ObservableList, ObservableSet
 from nicegui.observables import ObservableDict, ObservableList, ObservableSet
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 # pylint: disable=global-statement
 # pylint: disable=global-statement
 count = 0
 count = 0

+ 1 - 2
tests/test_open.py

@@ -1,8 +1,7 @@
 import pytest
 import pytest
 
 
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 @pytest.mark.parametrize('new_tab', [False, True])
 @pytest.mark.parametrize('new_tab', [False, True])

+ 1 - 2
tests/test_page.py

@@ -6,8 +6,7 @@ from fastapi.responses import PlainTextResponse
 from selenium.webdriver.common.by import By
 from selenium.webdriver.common.by import By
 
 
 from nicegui import Client, background_tasks, ui
 from nicegui import Client, background_tasks, ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_page(screen: Screen):
 def test_page(screen: Screen):

+ 1 - 2
tests/test_page_title.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_page_title(screen: Screen):
 def test_page_title(screen: Screen):

+ 1 - 2
tests/test_pagination.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_pagination(screen: Screen):
 def test_pagination(screen: Screen):

+ 1 - 2
tests/test_plotly.py

@@ -2,8 +2,7 @@ import numpy as np
 import plotly.graph_objects as go
 import plotly.graph_objects as go
 
 
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_plotly(screen: Screen):
 def test_plotly(screen: Screen):

+ 1 - 2
tests/test_prod_js.py

@@ -1,8 +1,7 @@
 from selenium.webdriver.common.by import By
 from selenium.webdriver.common.by import By
 
 
 from nicegui import __version__
 from nicegui import __version__
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_dev_mode(screen: Screen) -> None:
 def test_dev_mode(screen: Screen) -> None:

+ 1 - 2
tests/test_query.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_query_body(screen: Screen):
 def test_query_body(screen: Screen):

+ 1 - 2
tests/test_radio.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_changing_options(screen: Screen):
 def test_changing_options(screen: Screen):

+ 1 - 2
tests/test_refreshable.py

@@ -1,8 +1,7 @@
 import asyncio
 import asyncio
 
 
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_refreshable(screen: Screen) -> None:
 def test_refreshable(screen: Screen) -> None:

+ 1 - 2
tests/test_scene.py

@@ -3,8 +3,7 @@ from selenium.common.exceptions import JavascriptException
 
 
 from nicegui import ui
 from nicegui import ui
 from nicegui.elements.scene_object3d import Object3D
 from nicegui.elements.scene_object3d import Object3D
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_moving_sphere_with_timer(screen: Screen):
 def test_moving_sphere_with_timer(screen: Screen):

+ 1 - 2
tests/test_select.py

@@ -4,8 +4,7 @@ import pytest
 from selenium.webdriver import Keys
 from selenium.webdriver import Keys
 
 
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_select(screen: Screen):
 def test_select(screen: Screen):

+ 1 - 1
tests/test_serving_files.py

@@ -6,8 +6,8 @@ import pytest
 import requests
 import requests
 
 
 from nicegui import __version__, app, ui
 from nicegui import __version__, app, ui
+from nicegui.testing import Screen
 
 
-from .screen import Screen
 from .test_helpers import TEST_DIR
 from .test_helpers import TEST_DIR
 
 
 IMAGE_FILE = Path(TEST_DIR).parent / 'examples' / 'slideshow' / 'slides' / 'slide1.jpg'
 IMAGE_FILE = Path(TEST_DIR).parent / 'examples' / 'slideshow' / 'slides' / 'slide1.jpg'

+ 1 - 2
tests/test_spinner.py

@@ -1,8 +1,7 @@
 from selenium.webdriver.common.by import By
 from selenium.webdriver.common.by import By
 
 
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_spinner(screen: Screen):
 def test_spinner(screen: Screen):

+ 1 - 2
tests/test_splitter.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_splitter(screen: Screen):
 def test_splitter(screen: Screen):

+ 1 - 2
tests/test_stepper.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_stepper(screen: Screen):
 def test_stepper(screen: Screen):

+ 1 - 2
tests/test_storage.py

@@ -4,8 +4,7 @@ from pathlib import Path
 import httpx
 import httpx
 
 
 from nicegui import Client, app, background_tasks, ui
 from nicegui import Client, app, background_tasks, ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_browser_data_is_stored_in_the_browser(screen: Screen):
 def test_browser_data_is_stored_in_the_browser(screen: Screen):

+ 1 - 2
tests/test_table.py

@@ -5,8 +5,7 @@ import pandas as pd
 from selenium.webdriver.common.by import By
 from selenium.webdriver.common.by import By
 
 
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def columns() -> List:
 def columns() -> List:

+ 1 - 2
tests/test_tabs.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_with_strings(screen: Screen):
 def test_with_strings(screen: Screen):

+ 1 - 2
tests/test_tailwind.py

@@ -1,6 +1,5 @@
 from nicegui import Tailwind, ui
 from nicegui import Tailwind, ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_tailwind_builder(screen: Screen):
 def test_tailwind_builder(screen: Screen):

+ 1 - 2
tests/test_time.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_time(screen: Screen):
 def test_time(screen: Screen):

+ 1 - 2
tests/test_timeline.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_timeline(screen: Screen):
 def test_timeline(screen: Screen):

+ 1 - 2
tests/test_timer.py

@@ -3,8 +3,7 @@ import asyncio
 import pytest
 import pytest
 
 
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 class Counter:
 class Counter:

+ 1 - 2
tests/test_toggle.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_adding_toggle_options(screen: Screen):
 def test_adding_toggle_options(screen: Screen):

+ 1 - 2
tests/test_tree.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_tree(screen: Screen):
 def test_tree(screen: Screen):

+ 1 - 2
tests/test_upload.py

@@ -2,8 +2,7 @@ from pathlib import Path
 from typing import List
 from typing import List
 
 
 from nicegui import events, ui
 from nicegui import events, ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 test_path1 = Path('tests/test_upload.py').resolve()
 test_path1 = Path('tests/test_upload.py').resolve()
 test_path2 = Path('tests/test_scene.py').resolve()
 test_path2 = Path('tests/test_scene.py').resolve()

+ 1 - 2
tests/test_video.py

@@ -1,6 +1,5 @@
 from nicegui import ui
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 
 
 def test_replace_video(screen: Screen):
 def test_replace_video(screen: Screen):

+ 1 - 0
website/examples.py

@@ -57,4 +57,5 @@ examples: List[Example] = [
     Example('Descope Auth', 'login form and user profile using [Descope](https://descope.com)'),
     Example('Descope Auth', 'login form and user profile using [Descope](https://descope.com)'),
     Example('Editable table', 'editable table allowing to add, edit, delete rows'),
     Example('Editable table', 'editable table allowing to add, edit, delete rows'),
     Example('Editable AG Grid', 'editable AG Grid allowing to add, edit, delete rows'),
     Example('Editable AG Grid', 'editable AG Grid allowing to add, edit, delete rows'),
+    Example('Pytest', 'test a NiceGUI app with pytest'),
 ]
 ]