diff --git a/ci/github/system-testing/e2e-playwright.bash b/ci/github/system-testing/e2e-playwright.bash index 88d45bd86a4..b0a6e498f66 100755 --- a/ci/github/system-testing/e2e-playwright.bash +++ b/ci/github/system-testing/e2e-playwright.bash @@ -24,6 +24,7 @@ test() { source .venv/bin/activate pushd tests/e2e-playwright make test-sleepers + make test-platform popd } diff --git a/packages/pytest-simcore/src/pytest_simcore/helpers/playwright.py b/packages/pytest-simcore/src/pytest_simcore/helpers/playwright.py index 02b8c457385..22ea24baad0 100644 --- a/packages/pytest-simcore/src/pytest_simcore/helpers/playwright.py +++ b/packages/pytest-simcore/src/pytest_simcore/helpers/playwright.py @@ -339,9 +339,14 @@ def __call__(self, message: str) -> bool: url = f"https://{self.node_id}.services.{self.get_partial_product_url()}" response = httpx.get(url, timeout=10) self.logger.info( - "Querying the service endpoint from the E2E test. Url: %s Response: %s", + "Querying the service endpoint from the E2E test. Url: %s Response: %s TIP: %s", url, response, + ( + "Response 401 is OK. It means that service is ready." + if response.status_code == 401 + else "We are emulating the frontend; a 500 response is acceptable if the service is not yet ready." + ), ) if response.status_code <= 401: # NOTE: If the response status is less than 400, it means that the backend is ready (There are some services that respond with a 3XX) diff --git a/tests/e2e-playwright/Makefile b/tests/e2e-playwright/Makefile index fc4c0463de2..40fe914b9c0 100644 --- a/tests/e2e-playwright/Makefile +++ b/tests/e2e-playwright/Makefile @@ -64,7 +64,8 @@ install-dev install-prod install-ci: _check_venv_active ## install app in develo RETRY_DURATION_SECONDS := 30 RETRY_INTERVAL_SECONDS := 1 -install-ci-up-simcore: install-ci +.PHONY: install-ci-up-simcore +install-ci-up-simcore: install-ci ## run registry and simcore stack locally (push sleepers image and modifies DB) @$(MAKE_C) $(REPO_BASE_DIR) local-registry @$(_transfer-images-to-registry) @$(_up_simcore) @@ -106,6 +107,28 @@ test-sleepers-dev: _check_venv_active ## runs sleepers test on local deploy --autoregister \ $(CURDIR)/tests/sleepers/test_sleepers.py +.PHONY: test-platform +test-platform: _check_venv_active ## runs platform test on local deploy + @pytest \ + -sxvv \ + --color=yes \ + --product-url=http://$(get_my_ip):9081 \ + --autoregister \ + --tracing=on \ + $(CURDIR)/tests/platform_CI_tests/test_platform.py + +.PHONY: test-platform-dev +test-platform-dev: _check_venv_active ## runs platform test on local deploy (with PWDEBUG=1) + @PWDEBUG=1 pytest \ + -sxvv \ + --color=yes \ + --pdb \ + --product-url=http://$(get_my_ip):9081 \ + --headed \ + --autoregister \ + --tracing=on \ + $(CURDIR)/tests/platform_CI_tests/test_platform.py + # Define the files where user input will be saved SLEEPERS_INPUT_FILE := .e2e-playwright-sleepers-env.txt diff --git a/tests/e2e-playwright/tests/conftest.py b/tests/e2e-playwright/tests/conftest.py index 551dc1ad266..665ba78d774 100644 --- a/tests/e2e-playwright/tests/conftest.py +++ b/tests/e2e-playwright/tests/conftest.py @@ -323,6 +323,11 @@ def _do() -> AutoRegisteredUser: return _do +@pytest.fixture(scope="session") +def store_browser_context() -> bool: + return False + + @pytest.fixture def log_in_and_out( page: Page, @@ -331,6 +336,8 @@ def log_in_and_out( user_password: Secret4TestsStr, auto_register: bool, register: Callable[[], AutoRegisteredUser], + store_browser_context: bool, + context: BrowserContext, ) -> Iterator[RestartableWebSocket]: with log_context( logging.INFO, @@ -389,6 +396,9 @@ def log_in_and_out( if quickStartWindowCloseBtnLocator.is_visible(): quickStartWindowCloseBtnLocator.click() + if store_browser_context: + context.storage_state(path="state.json") + # with web_socket_default_log_handler(ws): yield restartable_wb diff --git a/tests/e2e-playwright/tests/platform_CI_tests/conftest.py b/tests/e2e-playwright/tests/platform_CI_tests/conftest.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/e2e-playwright/tests/platform_CI_tests/test_platform.py b/tests/e2e-playwright/tests/platform_CI_tests/test_platform.py new file mode 100644 index 00000000000..edcac0fca64 --- /dev/null +++ b/tests/e2e-playwright/tests/platform_CI_tests/test_platform.py @@ -0,0 +1,86 @@ +# pylint: disable=redefined-outer-name +# pylint: disable=unused-argument +# pylint: disable=unused-variable +# pylint: disable=too-many-arguments +# pylint: disable=too-many-statements +# pylint: disable=no-name-in-module + +from pathlib import Path + +import pytest + + +@pytest.fixture(scope="session") +def store_browser_context() -> bool: + return True + + +@pytest.fixture +def logged_in_context( + playwright, + store_browser_context: bool, + request: pytest.FixtureRequest, + pytestconfig, +): + is_headed = "--headed" in pytestconfig.invocation_params.args + + file_path = Path("state.json") + if not file_path.exists(): + request.getfixturevalue("log_in_and_out") + + browser = playwright.chromium.launch(headless=not is_headed) + context = browser.new_context(storage_state="state.json") + yield context + context.close() + browser.close() + + +@pytest.fixture(scope="module") +def test_module_teardown(): + + yield # Run the tests + + file_path = Path("state.json") + if file_path.exists(): + file_path.unlink() + + +def test_simple_folder_workflow(logged_in_context, product_url, test_module_teardown): + page = logged_in_context.new_page() + + page.goto(f"{product_url}") + page.wait_for_timeout(1000) + page.get_by_test_id("newFolderButton").click() + + with page.expect_response( + lambda response: "folders" in response.url + and response.status == 201 + and response.request.method == "POST" + ) as response_info: + page.get_by_test_id("folderEditorTitle").fill("My new folder") + page.get_by_test_id("folderEditorCreate").click() + + _folder_id = response_info.value.json()["data"]["folderId"] + page.get_by_test_id(f"folderItem_{_folder_id}").click() + page.get_by_test_id("workspacesAndFoldersTreeItem_null_null").click() + + +def test_simple_workspace_workflow( + logged_in_context, product_url, test_module_teardown +): + page = logged_in_context.new_page() + + page.goto(f"{product_url}") + page.wait_for_timeout(1000) + page.get_by_test_id("workspacesAndFoldersTreeItem_-1_null").click() + + with page.expect_response( + lambda response: "workspaces" in response.url + and response.status == 201 + and response.request.method == "POST" + ) as response_info: + page.get_by_test_id("newWorkspaceButton").click() + page.get_by_test_id("workspaceEditorSave").click() + _workspace_id = response_info.value.json()["data"]["workspaceId"] + page.get_by_test_id(f"workspaceItem_{_workspace_id}").click() + page.get_by_test_id("workspacesAndFoldersTreeItem_null_null").click()