Selaa lähdekoodia

Merge pull request #2245 from zauberzeug/pytest-example

Introduce new testing module and a new pytest example
Rodja Trappe 1 vuosi sitten
vanhempi
säilyke
aa624e8f51
84 muutettua tiedostoa jossa 231 lisäystä ja 263 poistoa
  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
 /test.py
 *.pickle
-tests/screenshots/
+screenshots/
 tests/media/
 venv
 .idea

+ 1 - 1
README.md

@@ -1,5 +1,5 @@
 <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!" />
 </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 time
 from contextlib import contextmanager
+from pathlib import Path
 from typing import List, Optional, Union
 
 import pytest
@@ -16,13 +17,11 @@ from selenium.webdriver.remote.webelement import WebElement
 from nicegui import app, ui
 from nicegui.server import Server
 
-from .test_helpers import TEST_DIR
-
 
 class Screen:
     PORT = 3392
     IMPLICIT_WAIT = 4
-    SCREENSHOT_DIR = TEST_DIR / 'screenshots'
+    SCREENSHOT_DIR = Path('screenshots')
 
     def __init__(self, selenium: webdriver.Chrome, caplog: pytest.LogCaptureFixture) -> None:
         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
 from nicegui import ui
-from .screen import Screen
+from nicegui.testing import Screen
 
 def test_hello_world(screen: Screen):
     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 nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import 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 .screen import Screen
+from nicegui.testing import Screen
 
 
 def test_prefix(screen: Screen):

+ 1 - 2
tests/test_audio.py

@@ -1,6 +1,5 @@
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import 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 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):

+ 1 - 2
tests/test_binding.py

@@ -1,8 +1,7 @@
 from selenium.webdriver.common.keys import Keys
 
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import 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 .screen import Screen
+from nicegui.testing import Screen
 
 
 def test_quasar_colors(screen: Screen):

+ 1 - 2
tests/test_carousel.py

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

+ 1 - 2
tests/test_chat.py

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

+ 1 - 2
tests/test_code.py

@@ -1,6 +1,5 @@
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import 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 nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 def test_entering_color(screen: Screen):

+ 1 - 2
tests/test_colors.py

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

+ 1 - 2
tests/test_context_menu.py

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

+ 1 - 2
tests/test_dark_mode.py

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

+ 1 - 2
tests/test_date.py

@@ -1,6 +1,5 @@
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import 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 nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import 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 nicegui import app, ui
-
-from .conftest import DOWNLOAD_DIR
-from .screen import Screen
+from nicegui.testing import Screen, conftest
 
 
 @pytest.fixture
@@ -27,7 +25,7 @@ def test_download_text_file(screen: Screen, test_route: str):  # pylint: disable
     screen.open('/')
     screen.click('Download')
     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):
@@ -38,7 +36,7 @@ def test_downloading_local_file_as_src(screen: Screen):
     route_count_before_download = len(app.routes)
     screen.click('download')
     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
 
 
@@ -48,4 +46,4 @@ def test_download_raw_data(screen: Screen):
     screen.open('/')
     screen.click('download')
     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 .screen import Screen
+from nicegui.testing import Screen
 
 
 def test_create_dynamically(screen: Screen):

+ 1 - 2
tests/test_editor.py

@@ -1,7 +1,6 @@
 
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import 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 nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 def test_classes(screen: Screen):

+ 1 - 2
tests/test_element_delete.py

@@ -1,6 +1,5 @@
 from nicegui import binding, ui
-
-from .screen import Screen
+from nicegui.testing import 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
 
 from nicegui import __version__
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 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.events import ClickEventArguments
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 def click_sync_no_args():

+ 1 - 2
tests/test_expansion.py

@@ -1,6 +1,5 @@
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import 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 nicegui import favicon, ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 DEFAULT_FAVICON_PATH = Path(__file__).parent.parent / 'nicegui' / 'static' / 'favicon.ico'
 LOGO_FAVICON_PATH = Path(__file__).parent.parent / 'website' / 'static' / 'logo_square.png'

+ 1 - 2
tests/test_header.py

@@ -1,8 +1,7 @@
 import pytest
 
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 @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 nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 def test_change_chart_series(screen: Screen):

+ 1 - 2
tests/test_image.py

@@ -1,8 +1,7 @@
 from pathlib import Path
 
 from nicegui import app, ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 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 nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import 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 nicegui import Client, ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 def test_set_source_in_tab(screen: Screen):

+ 1 - 2
tests/test_javascript.py

@@ -1,8 +1,7 @@
 import pytest
 
 from nicegui import Client, ui
-
-from .screen import Screen
+from nicegui.testing import 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 nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 def test_joystick(screen: Screen):

+ 1 - 2
tests/test_json_editor.py

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

+ 1 - 2
tests/test_keyboard.py

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

+ 1 - 2
tests/test_knob.py

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

+ 1 - 2
tests/test_label.py

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

+ 1 - 2
tests/test_leaflet.py

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

+ 1 - 2
tests/test_lifecycle.py

@@ -1,8 +1,7 @@
 from typing import List
 
 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):

+ 1 - 2
tests/test_link.py

@@ -1,6 +1,5 @@
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import 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 .screen import Screen
+from nicegui.testing import Screen
 
 
 def test_log(screen: Screen):

+ 1 - 2
tests/test_markdown.py

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

+ 1 - 2
tests/test_menu.py

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

+ 1 - 2
tests/test_mermaid.py

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

+ 1 - 2
tests/test_notification.py

@@ -1,6 +1,5 @@
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import 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 nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import 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.observables import ObservableDict, ObservableList, ObservableSet
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 # pylint: disable=global-statement
 count = 0

+ 1 - 2
tests/test_open.py

@@ -1,8 +1,7 @@
 import pytest
 
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 @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 nicegui import Client, background_tasks, ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 def test_page(screen: Screen):

+ 1 - 2
tests/test_page_title.py

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

+ 1 - 2
tests/test_pagination.py

@@ -1,6 +1,5 @@
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import 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
 
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import 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 nicegui import __version__
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 def test_dev_mode(screen: Screen) -> None:

+ 1 - 2
tests/test_query.py

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

+ 1 - 2
tests/test_radio.py

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

+ 1 - 2
tests/test_refreshable.py

@@ -1,8 +1,7 @@
 import asyncio
 
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 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.elements.scene_object3d import Object3D
-
-from .screen import Screen
+from nicegui.testing import 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 nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 def test_select(screen: Screen):

+ 1 - 1
tests/test_serving_files.py

@@ -6,8 +6,8 @@ import pytest
 import requests
 
 from nicegui import __version__, app, ui
+from nicegui.testing import Screen
 
-from .screen import Screen
 from .test_helpers import TEST_DIR
 
 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 nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 
 def test_spinner(screen: Screen):

+ 1 - 2
tests/test_splitter.py

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

+ 1 - 2
tests/test_stepper.py

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

+ 1 - 2
tests/test_storage.py

@@ -4,8 +4,7 @@ from pathlib import Path
 import httpx
 
 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):

+ 1 - 2
tests/test_table.py

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

+ 1 - 2
tests/test_tabs.py

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

+ 1 - 2
tests/test_tailwind.py

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

+ 1 - 2
tests/test_time.py

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

+ 1 - 2
tests/test_timeline.py

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

+ 1 - 2
tests/test_timer.py

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

+ 1 - 2
tests/test_toggle.py

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

+ 1 - 2
tests/test_tree.py

@@ -1,6 +1,5 @@
 from nicegui import ui
-
-from .screen import Screen
+from nicegui.testing import 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 nicegui import events, ui
-
-from .screen import Screen
+from nicegui.testing import Screen
 
 test_path1 = Path('tests/test_upload.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 .screen import Screen
+from nicegui.testing import 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('Editable table', 'editable table 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'),
 ]