-
Notifications
You must be signed in to change notification settings - Fork 23
test: Add Overview page UI tests #850
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
emmaaroche
wants to merge
1
commit into
Kuadrant:main
Choose a base branch
from
emmaaroche:overview-page-ui-tests
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| """Page object for the console plugin Overview page""" | ||
|
|
||
| import backoff | ||
| from playwright.sync_api import Page | ||
| from testsuite.page_objects.navigator import Navigable | ||
|
|
||
|
|
||
| class OverviewPage(Navigable): | ||
| """Page object for Overview page""" | ||
|
|
||
| def __init__(self, page: Page): | ||
| super().__init__(page) | ||
| self.page_heading = page.locator("h1").filter(has_text="Overview") | ||
|
|
||
| def is_displayed(self): | ||
| """Returns the page heading locator""" | ||
| return self.page_heading | ||
|
|
||
| def page_displayed(self): | ||
| """Check if the overview page is displayed""" | ||
| self.page_heading.wait_for(state="visible", timeout=60000) | ||
| return self.page_heading.is_visible() | ||
|
|
||
| def get_metric_count(self, metric_name: str): | ||
| """Get the count from a gateway metric card""" | ||
| metric_card = self.page.locator(f"//div[contains(., '{metric_name}')]").first | ||
| count_element = metric_card.locator("strong").first | ||
| return int(count_element.inner_text().strip()) | ||
|
|
||
| @backoff.on_predicate(backoff.constant, interval=2, max_tries=30, jitter=None) | ||
| def wait_for_healthy_gateways(self, expected_count: int): | ||
| """Wait for the healthy gateways count to reach the expected value""" | ||
| return self.get_metric_count("Healthy Gateways") >= expected_count | ||
|
|
||
| def has_gateway_in_traffic_analysis(self, gateway_name: str): | ||
| """Check if gateway appears in traffic analysis section""" | ||
| return self.page.wait_for_selector(f"//tr//a[@data-test-id='{gateway_name}']") | ||
|
|
||
| def has_httproute_in_section(self, route_name: str): | ||
| """Check if HTTPRoute appears in HTTPRoutes section""" | ||
| return self.page.wait_for_selector(f"//tr//a[@data-test-id='{route_name}']") | ||
|
|
||
| def has_policy_in_section(self, policy_name: str): | ||
| """Check if policy appears in Policies section""" | ||
| return self.page.wait_for_selector(f"//tr//a[@data-test-id='{policy_name}']") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
159 changes: 159 additions & 0 deletions
159
testsuite/tests/singlecluster/ui/console_plugin/overview/test_overview.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| """UI tests for console plugin Overview page""" | ||
|
|
||
| import pytest | ||
| from testsuite.gateway import GatewayListener | ||
| from testsuite.gateway.gateway_api.gateway import KuadrantGateway | ||
| from testsuite.gateway.gateway_api.route import HTTPRoute | ||
| from testsuite.kuadrant.policy.authorization.auth_policy import AuthPolicy | ||
| from testsuite.page_objects.overview.overview_page import OverviewPage | ||
|
|
||
| pytestmark = [pytest.mark.ui] | ||
|
|
||
|
|
||
| def test_overview_page_panels_and_links(navigator): | ||
| """Verify all section panels are visible and Getting started resources has clickable links""" | ||
| # Navigate to overview page | ||
| overview_page = navigator.navigate(OverviewPage) | ||
| assert overview_page.page_displayed(), "Overview page did not load" | ||
|
|
||
| # Verify all expected section panels exist | ||
| getting_started = overview_page.page.get_by_text("Getting started resources") | ||
| assert getting_started.is_visible() | ||
| assert overview_page.page.get_by_role("heading", name="Gateways", exact=True).is_visible() | ||
| assert overview_page.page.get_by_role("heading", name="Gateways - Traffic Analysis", exact=True).is_visible() | ||
| assert overview_page.page.get_by_role("heading", name="Policies", exact=True).is_visible() | ||
| assert overview_page.page.get_by_role("heading", name="HTTPRoutes", exact=True).is_visible() | ||
|
|
||
| # Verify Getting started resources panel has clickable links | ||
| getting_started_section = getting_started.locator("xpath=ancestor::section").first | ||
| links = getting_started_section.get_by_role("link").all() | ||
| clickable_links = [link for link in links if link.is_visible() and link.is_enabled()] | ||
| assert len(clickable_links) > 0, "No clickable links found in Getting started resources panel" | ||
|
|
||
|
|
||
| def test_creation_buttons(navigator): | ||
| """Verify creation buttons are clickable and policy dropdown shows available policy types""" | ||
| # Navigate to overview page | ||
| overview_page = navigator.navigate(OverviewPage) | ||
| assert overview_page.page_displayed(), "Overview page did not load" | ||
|
|
||
| # Verify Create Gateway button is visible and clickable | ||
| create_gateway = overview_page.page.get_by_text("Create Gateway") | ||
| assert create_gateway.is_visible() and create_gateway.is_enabled() | ||
|
|
||
| # Verify Create HTTPRoute button is visible and clickable | ||
| create_httproute = overview_page.page.get_by_text("Create HTTPRoute") | ||
| assert create_httproute.is_visible() and create_httproute.is_enabled() | ||
|
|
||
| # Verify Create Policy button is visible and clickable, then open dropdown | ||
| create_policy = overview_page.page.get_by_text("Create Policy") | ||
| assert create_policy.is_visible() and create_policy.is_enabled() | ||
| create_policy.click() | ||
|
|
||
| # Verify core policies are visible in the dropdown | ||
| core_policies = ["AuthPolicy", "RateLimitPolicy", "DNSPolicy", "TLSPolicy"] | ||
| for policy_type in core_policies: | ||
| menu_item = overview_page.page.get_by_role("menuitem", name=policy_type, exact=True) | ||
| assert menu_item.is_visible(), f"{policy_type} should be visible" | ||
| assert menu_item.is_enabled(), f"{policy_type} should be enabled" | ||
|
|
||
|
|
||
| def test_additional_policy_types_in_dropdown(navigator, openshift_version): | ||
| """Verify additional policy types appear in Create Policy dropdown (OCP 4.20+)""" | ||
| if openshift_version is None: | ||
| pytest.skip("Could not detect OpenShift version") | ||
| if openshift_version < (4, 20): | ||
| pytest.skip("Requires OCP 4.20+ for OIDCPolicy, PlanPolicy, TokenRateLimitPolicy") | ||
|
|
||
| overview_page = navigator.navigate(OverviewPage) | ||
| assert overview_page.page_displayed(), "Overview page did not load" | ||
|
|
||
| # Open Create Policy dropdown | ||
| create_policy = overview_page.page.get_by_text("Create Policy") | ||
| assert create_policy.is_visible() and create_policy.is_enabled() | ||
| create_policy.click() | ||
|
|
||
| # Verify additional policies available in OCP 4.20+ | ||
| additional_policies = ["OIDCPolicy", "PlanPolicy", "TokenRateLimitPolicy"] | ||
| for policy_type in additional_policies: | ||
| menu_item = overview_page.page.get_by_role("menuitem", name=policy_type, exact=True) | ||
| assert menu_item.is_visible(), f"{policy_type} should be visible in OCP 4.20+" | ||
| assert menu_item.is_enabled(), f"{policy_type} should be enabled" | ||
|
|
||
|
|
||
| def test_resources_appear_in_sections(request, navigator, cluster, blame, module_label, wildcard_domain, backend): | ||
| """Verify gateway, HTTPRoute, and policy resources appear in their respective section panels""" | ||
| # Create resources programmatically | ||
| gateway_name = blame("gw") | ||
| gateway = KuadrantGateway.create_instance(cluster, gateway_name, {"app": module_label}) | ||
| gateway.add_listener(GatewayListener(hostname=wildcard_domain)) | ||
| request.addfinalizer(gateway.delete) | ||
| gateway.commit() | ||
|
|
||
| route_name = blame("route") | ||
| route = HTTPRoute.create_instance(cluster, route_name, gateway) | ||
| route.add_backend(backend) | ||
| request.addfinalizer(route.delete) | ||
| route.commit() | ||
|
|
||
| policy_name = blame("policy") | ||
| policy = AuthPolicy.create_instance(cluster, policy_name, gateway) | ||
| policy.authorization.add_opa_policy("denyAll", "allow = false") | ||
| request.addfinalizer(policy.delete) | ||
| policy.commit() | ||
|
|
||
| # Navigate to overview page | ||
| overview_page = navigator.navigate(OverviewPage) | ||
| assert overview_page.page_displayed(), "Overview page did not load" | ||
|
|
||
| # Verify gateway appears in Gateways - Traffic Analysis section panel | ||
| assert overview_page.has_gateway_in_traffic_analysis( | ||
| gateway_name | ||
| ), f"Gateway '{gateway_name}' not visible in traffic analysis section panel" | ||
|
|
||
| # Verify HTTPRoute appears in HTTPRoutes section panel | ||
| assert overview_page.has_httproute_in_section( | ||
| route_name | ||
| ), f"HTTPRoute '{route_name}' not visible in HTTPRoutes section panel" | ||
|
|
||
| # Verify policy appears in Policies section panel | ||
| assert overview_page.has_policy_in_section( | ||
| policy_name | ||
| ), f"Policy '{policy_name}' not visible in Policies section panel" | ||
|
|
||
|
|
||
| def test_gateway_section_status(request, navigator, cluster, blame, module_label, wildcard_domain): | ||
| """Verify gateway status metrics update correctly""" | ||
| # Navigate to overview page and capture initial counts | ||
| overview_page = navigator.navigate(OverviewPage) | ||
| assert overview_page.page_displayed(), "Overview page did not load" | ||
|
|
||
| initial_total = overview_page.get_metric_count("Total Gateways") | ||
| initial_healthy = overview_page.get_metric_count("Healthy Gateways") | ||
| initial_unhealthy = overview_page.get_metric_count("Unhealthy Gateways") | ||
|
|
||
| # Create gateway programmatically | ||
| gateway_name = blame("gw") | ||
| gateway = KuadrantGateway.create_instance(cluster, gateway_name, {"app": module_label}) | ||
| gateway.add_listener(GatewayListener(hostname=wildcard_domain)) | ||
| request.addfinalizer(gateway.delete) | ||
| gateway.commit() | ||
|
|
||
| # Refresh page to see updated metrics | ||
| overview_page = navigator.navigate(OverviewPage) | ||
| assert overview_page.page_displayed(), "Overview page did not load" | ||
|
|
||
| # Verify total gateway count increased | ||
| new_total = overview_page.get_metric_count("Total Gateways") | ||
| assert new_total > initial_total, f"Total Gateways count did not increase (was {initial_total}, now {new_total})" | ||
|
|
||
| # Verify unhealthy count increased (gateway starts as unhealthy while provisioning) | ||
| new_unhealthy = overview_page.get_metric_count("Unhealthy Gateways") | ||
| assert ( | ||
| new_unhealthy > initial_unhealthy | ||
| ), f"Unhealthy count did not increase (was {initial_unhealthy}, now {new_unhealthy})" | ||
|
|
||
| # Wait for gateway to become healthy and verify healthy count increased | ||
| overview_page.wait_for_healthy_gateways(initial_healthy + 1) | ||
| new_healthy = overview_page.get_metric_count("Healthy Gateways") | ||
| assert new_healthy > initial_healthy, f"Healthy count did not increase (was {initial_healthy}, now {new_healthy})" | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We expect the Gateway is first is state "unhealthy" but what if it reconciles so quick the ui plugin will only show "healthy"? This could happen on very fast infrastructures.
This can be left as is for now, but maybe in the future or on certain cloud providers this could cause a false negative fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That’s a fair point! So far I’ve always seen it report Unhealthy, even if just briefly, before becoming Healthy, but I can see how on faster infra that might not always be the case. I will for sure dig into it a bit more in the future, along with some other UI refactoring I want to do 😄