diff --git a/.gitignore b/.gitignore index 9222576..2201bd6 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ super-linter.log common/pattern-vault.init scratch tests/ci/__pycache__/* +tests/ci/.results/* diff --git a/tests/ci/helpers.py b/tests/ci/helpers.py index 914477c..930cb78 100644 --- a/tests/ci/helpers.py +++ b/tests/ci/helpers.py @@ -1,3 +1,6 @@ +import os + +import pytest import requests from ocp_resources.gateway_gateway_networking_k8s_io import Gateway from ocp_resources.route import Route @@ -53,3 +56,33 @@ def assert_url_reachable(url, timeout=60): assert ( response.status_code == 200 ), f"Expected a 200 from '{url}' but got {response.status_code}" + + +def kubeadmin_password(): + """Return kubeadmin password from env or the file next to VP_HUBCONFIG.""" + password = os.getenv("KUBEADMIN_PASSWORD") or os.getenv("VP_KUBEADMIN") + if password: + return password.strip() + + kubeconfig = os.getenv("VP_HUBCONFIG") + if not kubeconfig: + pytest.fail( + "Set KUBEADMIN_PASSWORD or VP_HUBCONFIG (with a sibling admin-password file)" + ) + + candidates = [] + if kubeconfig.endswith("-kubeconfig"): + candidates.append(f"{kubeconfig[: -len('-kubeconfig')]}-admin-password") + candidates.append(os.path.join(os.path.dirname(kubeconfig), "kubeadmin-password")) + + for path in candidates: + if os.path.isfile(path): + with open(path, encoding="utf-8") as handle: + value = handle.read().strip() + if value: + return value + + pytest.fail( + "kubeadmin password not found; set KUBEADMIN_PASSWORD or place " + "-admin-password next to VP_HUBCONFIG" + ) diff --git a/tests/ci/test_hub.py b/tests/ci/test_hub.py index bb9547c..8aaf618 100644 --- a/tests/ci/test_hub.py +++ b/tests/ci/test_hub.py @@ -1,7 +1,28 @@ +import os + import pytest +from playwright.sync_api import sync_playwright from validatedpatterns_tests.interop import components, subscription -from .helpers import assert_url_reachable, gateway_url, route_url +from .helpers import ( + assert_url_reachable, + gateway_url, + kubeadmin_password, + route_url, +) + + +def _results_dir(): + path = os.path.join(os.path.dirname(os.path.abspath(__file__)), ".results") + os.makedirs(path, exist_ok=True) + return path + + +def _openshift_login(page, url, password): + page.goto(url) + page.get_by_label("Username *").fill("kubeadmin") + page.get_by_label("Password *").fill(password) + page.get_by_role("button", name="Log in").click() @pytest.mark.parametrize( @@ -48,7 +69,8 @@ def test_pod_status(openshift_dyn_client): "patterns-operator", "vp-gitops", "vault", - "golang-external-secrets", + "external-secrets", + "external-secrets-operator", "vp-s4-storage", "travel-agency", "travel-control", @@ -90,3 +112,82 @@ def test_travel_control_gateway(openshift_dyn_client): openshift_dyn_client, "travel-control", "travel-control-gateway" ) assert_url_reachable(url) + + +@pytest.mark.parametrize( + "openshift_dyn_client", + ["VP_HUBCONFIG"], + indirect=True, +) +def test_travel_control_dashboard(openshift_dyn_client): + console_url = route_url(openshift_dyn_client, "openshift-console", "console") + dashboard_url = gateway_url( + openshift_dyn_client, "travel-control", "travel-control-gateway" + ) + password = kubeadmin_password() + results_dir = _results_dir() + + with sync_playwright() as playwright: + browser = playwright.chromium.launch(headless=True) + context = browser.new_context(ignore_https_errors=True) + context.set_default_timeout(120_000) + page = context.new_page() + try: + _openshift_login(page, console_url, password) + page.goto(dashboard_url) + page.locator('[id="travels\\.uk_ratio"]').fill("98") + page.locator('[id="travels\\.uk_device_mobile"]').fill("5") + page.locator('[id="travels\\.uk_user_registered"]').fill("89") + page.locator('[id="travels\\.uk_travel_t3"]').fill("71") + page.locator('[id="viaggi\\.it_ratio"]').fill("0") + page.locator('[id="viaggi\\.it_device_mobile"]').fill("100") + page.locator('[id="viaggi\\.it_user_registered"]').fill("99") + page.locator('[id="viaggi\\.it_travel_t2"]').fill("80") + page.locator('[id="voyages\\.fr_ratio"]').fill("51") + page.locator('[id="voyages\\.fr_travel_t1"]').fill("59") + page.screenshot( + path=os.path.join(results_dir, "travel_control_dashboard.png"), + full_page=True, + ) + finally: + context.close() + browser.close() + + +@pytest.mark.parametrize( + "openshift_dyn_client", + ["VP_HUBCONFIG"], + indirect=True, +) +def test_kiali_traffic_graph(openshift_dyn_client): + kiali_url = route_url(openshift_dyn_client, "istio-system", "kiali") + password = kubeadmin_password() + results_dir = _results_dir() + + with sync_playwright() as playwright: + browser = playwright.chromium.launch(headless=True) + context = browser.new_context(ignore_https_errors=True) + context.set_default_timeout(120_000) + page = context.new_page() + try: + _openshift_login(page, kiali_url, password) + page.get_by_role("link", name="Traffic Graph").click() + page.locator('[data-test="namespace-dropdown"]').click() + page.locator('[id="namespace-list-item\\[travel-agency\\]"]').get_by_role( + "checkbox" + ).check() + page.locator('[id="namespace-list-item\\[travel-control\\]"]').get_by_role( + "checkbox" + ).check() + page.locator('[id="namespace-list-item\\[travel-portal\\]"]').get_by_role( + "checkbox" + ).check() + page.locator('[data-test="namespace-dropdown"]').click() + page.wait_for_timeout(5000) + page.screenshot( + path=os.path.join(results_dir, "kiali_traffic_graph.png"), + full_page=True, + ) + finally: + context.close() + browser.close() diff --git a/tests/ci/ui/conftest.py b/tests/ci/ui/conftest.py deleted file mode 100644 index 22d036d..0000000 --- a/tests/ci/ui/conftest.py +++ /dev/null @@ -1,9 +0,0 @@ -import pytest - - -@pytest.fixture(scope="session") -def browser_context_args(browser_context_args): - return { - **browser_context_args, - "ignore_https_errors": True, - } diff --git a/tests/ci/ui/test_travelops.py.j2 b/tests/ci/ui/test_travelops.py.j2 deleted file mode 100644 index a5cfa7d..0000000 --- a/tests/ci/ui/test_travelops.py.j2 +++ /dev/null @@ -1,47 +0,0 @@ -from playwright.sync_api import Page - - -def test_travelops_adjust_requests_on_travel_control_dashboard(page: Page): - # Log in to Openshift console - page.goto("{{ hub_console.stdout }}") - page.get_by_label("Username *").fill("kubeadmin") - page.get_by_label("Password *").fill("{{ kubeadmin }}") - page.get_by_role("button", name="Log in").click() - - # Go to travel control dashboard and adjust requests - page.goto("{{ travel_control_dashboard }}") - page.locator('[id="travels\\.uk_ratio"]').fill("98") - page.locator('[id="travels\\.uk_device_mobile"]').fill("5") - page.locator('[id="travels\\.uk_user_registered"]').fill("89") - page.locator('[id="travels\\.uk_travel_t3"]').fill("71") - page.locator('[id="viaggi\\.it_ratio"]').fill("0") - page.locator('[id="viaggi\\.it_device_mobile"]').fill("100") - page.locator('[id="viaggi\\.it_user_registered"]').fill("99") - page.locator('[id="viaggi\\.it_travel_t2"]').fill("80") - page.locator('[id="voyages\\.fr_ratio"]').fill("51") - page.locator('[id="voyages\\.fr_travel_t1"]').fill("59") - page.screenshot(path="travel_control_dashboard.png", full_page=True) - - -def test_travelops_travel_agency_traffic_graph(page: Page): - # Log in - page.goto("https://kiali-istio-system.apps.{{ hub_cluster }}") - page.get_by_label("Username *").fill("kubeadmin") - page.get_by_label("Password *").fill("{{ kubeadmin }}") - page.get_by_role("button", name="Log in").click() - - # Go to kiali travel-agency traffic graph and verify apps - page.get_by_role("link", name="Traffic Graph").click() - page.locator('[data-test="namespace-dropdown"]').click() - page.locator('[id="namespace-list-item\\[travel-agency\\]"]').get_by_role( - "checkbox" - ).check() - page.locator('[id="namespace-list-item\\[travel-control\\]"]').get_by_role( - "checkbox" - ).check() - page.locator('[id="namespace-list-item\\[travel-portal\\]"]').get_by_role( - "checkbox" - ).check() - page.locator('[data-test="namespace-dropdown"]').click() - page.wait_for_timeout(5000) - page.screenshot(path="kiali_traffic_graph.png", full_page=True)