diff --git a/testsuite/tests/apicast/auth/test_basic_auth_app_id.py b/testsuite/tests/apicast/auth/test_basic_auth_app_id.py index a461ea8c..ee58c65a 100644 --- a/testsuite/tests/apicast/auth/test_basic_auth_app_id.py +++ b/testsuite/tests/apicast/auth/test_basic_auth_app_id.py @@ -1,65 +1,106 @@ """ Service requires credentials (app_id, app_key) to be passed using the Basic Auth - Rewrite ./spec/functional_specs/auth/basic_auth_app_id_spec.rb """ import pytest - from threescale_api.resources import Service +from packaging.version import Version # noqa # pylint: disable=unused-import +from testsuite import TESTED_VERSION # noqa # pylint: disable=unused-import +from testsuite.capabilities import Capability +from testsuite.gateways.apicast.selfmanaged import SelfManagedApicast +from testsuite.gateways.apicast.system import SystemApicast +from testsuite.httpx import HttpxClient from testsuite.utils import basic_auth_string @pytest.fixture(scope="module") def service_settings(service_settings): - "Set auth mode to app_id/app_key" + """Set auth mode to app_id/app_key.""" service_settings.update({"backend_version": Service.AUTH_APP_ID_KEY}) return service_settings @pytest.fixture(scope="module") def service_proxy_settings(service_proxy_settings): - "Set credentials location to 'authorization' (Basic HTTP auth)" + """Set credentials location to 'authorization' (Basic HTTP auth).""" service_proxy_settings.update({"credentials_location": "authorization"}) return service_proxy_settings -@pytest.mark.smoke -def test_basic_auth_app_id_key(application, api_client): - """Test client access with Basic HTTP Auth using app id and app key - - Configure Api/Service to use App ID / App Key Authentication - and Basic HTTP Auth to pass the credentials. +@pytest.fixture(scope="module") +def http_client(application): + """Provide an HttpxClient instance using HTTP 1.1.""" + client = HttpxClient(False, application) + client.auth = None # No default authentication + yield client + client.close() - Then request made with appropriate Basic auth made has to pass as expected""" +@pytest.fixture(scope="module") +def valid_auth_headers(application): + """Generate valid Basic Auth headers.""" creds = application.authobj().credentials - expected_authorization = basic_auth_string(creds["app_id"], creds["app_key"]) - - response = api_client().get("/get") + authorization = basic_auth_string(creds["app_id"], creds["app_key"]) + return {"Authorization": authorization} - assert response.status_code == 200 - assert response.request.headers["Authorization"] == expected_authorization +@pytest.fixture(scope="module") +def malformed_request(http_client): + """Create a function to make requests with malformed auth headers.""" -def test_basic_auth_app_id_403_with_query(application, api_client): - "Forbid access if credentials passed wrong way" - client = api_client() + def prepare_request(): + headers = {"Authorization": "Basic test123?"} # Malformed authorization header + return http_client.get("/get", headers=headers) - client.auth = application.authobj(location="query") + return prepare_request - response = client.get("/get") - assert response.status_code == 403 +@pytest.fixture( + scope="module", + params=[ + SystemApicast, + pytest.param(SelfManagedApicast, marks=pytest.mark.required_capabilities(Capability.CUSTOM_ENVIRONMENT)), + ], +) +def gateway_kind(request): + """Gateway class to use for tests""" + return request.param -def test_basic_auth_app_id_403_without_auth(api_client): - "Forbid access if no credentials" +@pytest.mark.smoke +def test_basic_auth_success(http_client, valid_auth_headers): + """Test valid Basic HTTP Auth using app_id and app_key.""" + response = http_client.get("/get", headers=valid_auth_headers) + assert response.status_code == 200, "Valid request failed unexpectedly." + assert response.request.headers["Authorization"] == valid_auth_headers["Authorization"] + + +@pytest.mark.parametrize( + "auth_method, expected_status", + [ + ("query", 403), # Credentials passed as query parameters + (None, 403), # No credentials + ], +) +def test_basic_auth_failure(api_client, application, auth_method, expected_status): + """Test forbidden access when credentials are passed incorrectly or missing.""" client = api_client() + client.auth = application.authobj(location=auth_method) if auth_method else None + response = client.get("/get") + assert response.status_code == expected_status - client.auth = None - response = client.get("/get") +@pytest.mark.skipif("TESTED_VERSION < Version('2.14')") +@pytest.mark.issue("https://issues.redhat.com/browse/THREESCALE-11435") +# pylint: disable=unused-argument +def test_basic_auth_malformed_secret(http_client, valid_auth_headers, malformed_request, gateway_kind): + """Test malformed Basic Auth headers.""" + # Valid request + response = http_client.get("/get", headers=valid_auth_headers) + assert response.status_code == 200, "Valid request failed unexpectedly." - assert response.status_code == 403 + # Malformed request + malformed_status_code = malformed_request().status_code + assert malformed_status_code == 403, "Malformed request did not return 403 as expected." diff --git a/testsuite/tests/prometheus/system/test_internal_calls.py b/testsuite/tests/prometheus/system/test_internal_calls.py index 1dea043d..d07bdc87 100644 --- a/testsuite/tests/prometheus/system/test_internal_calls.py +++ b/testsuite/tests/prometheus/system/test_internal_calls.py @@ -19,6 +19,9 @@ ] +REQUEST_NUM = 42 + + @pytest.fixture(scope="session") def backend_listener_url(testconfig): """ @@ -76,7 +79,8 @@ def test_utilization(url, prometheus, application, backend_listener_url, auth_he service_id = application.service.entity_id app_plan_id = application.entity["plan_id"] - requests.get(url.format(backend_listener_url, service_id, app_plan_id), verify=False, headers=auth_headers) + for _ in range(REQUEST_NUM): + requests.get(url.format(backend_listener_url, service_id, app_plan_id), verify=False, headers=auth_headers) # prometheus is downloading metrics periodicity, we need to wait for next fetch prometheus.wait_on_next_scrape("backend-worker") @@ -91,7 +95,9 @@ def test_utilization(url, prometheus, application, backend_listener_url, auth_he lambda x: x["metric"]["controller"].startswith("admin/api"), ) - assert counts_after == counts_before + for key, count in counts_after.items(): + if int(count) >= int(counts_before[key]) + REQUEST_NUM: + assert counts_after == counts_before, f"looks like {key} is increased by internal calls" def extract_call_metrics(prometheus, query, container, predicate=None): diff --git a/testsuite/tests/toolbox/test_activedoc.py b/testsuite/tests/toolbox/test_activedoc.py index 0adc2fde..3a6bdd93 100644 --- a/testsuite/tests/toolbox/test_activedoc.py +++ b/testsuite/tests/toolbox/test_activedoc.py @@ -9,7 +9,9 @@ from testsuite.utils import blame, blame_desc, randomize from testsuite import rawobj -SWAGGER_LINK = "https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v2.0/json/petstore.json" +SWAGGER_LINK = ( + "https://raw.githubusercontent.com/OAI/learn.openapis.org/refs/heads/main/examples/v2.0/json/petstore.json" +) @pytest.fixture(scope="module") diff --git a/testsuite/tests/ui/conftest.py b/testsuite/tests/ui/conftest.py index a8fc47eb..f79561d4 100644 --- a/testsuite/tests/ui/conftest.py +++ b/testsuite/tests/ui/conftest.py @@ -465,46 +465,51 @@ def get_resultsdir_path(node): return path +# pylint: disable=too-many-locals def fullpage_screenshot(driver, file_path): """ - A full-page screenshot function. It scroll the website and screenshots it. + A full-page screenshot function. It scrolls the website and screenshots it. - Creates multiple files - Screenshots are made only vertically (on Y axis) """ - # Removal of the height: 100% style, that disables scroll. - driver.execute_script("document.body.style.height = 'unset'") - driver.execute_script("document.body.parentNode.style.height = 'unset'") + try: + # Removal of the height: 100% style, that disables scroll. + driver.execute_script("document.body.style.height = 'unset'") + driver.execute_script("document.body.parentNode.style.height = 'unset'") - total_height = driver.execute_script("return document.body.parentNode.scrollHeight") - viewport_height = driver.execute_script("return window.innerHeight") + total_height = driver.execute_script("return document.body.parentNode.scrollHeight") + viewport_height = driver.execute_script("return window.innerHeight") - screenshot_bytes = driver.get_screenshot_as_png() - screenshot = Image.open(io.BytesIO(screenshot_bytes)) - width, height = screenshot.size - del screenshot - - scaling_constant = float(height) / float(viewport_height) - stitched_image = Image.new("RGB", (width, int(total_height * scaling_constant))) - part = 0 - - for scroll in range(0, total_height, viewport_height): - driver.execute_script("window.scrollTo({0}, {1})".format(0, scroll)) screenshot_bytes = driver.get_screenshot_as_png() screenshot = Image.open(io.BytesIO(screenshot_bytes)) - - if scroll + viewport_height > total_height: - offset = (0, int(math.ceil((total_height - viewport_height) * scaling_constant))) - else: - offset = (0, int(math.ceil(scroll * scaling_constant))) - - stitched_image.paste(screenshot, offset) + width, height = screenshot.size del screenshot - part += 1 - date = datetime.today().strftime("%Y-%m-%d-%H:%M:%S") - fullpath = f"{file_path}/{date}.png" - stitched_image.save(fullpath) - return fullpath + scaling_constant = float(height) / float(viewport_height) + stitched_image = Image.new("RGB", (width, int(total_height * scaling_constant))) + part = 0 + + for scroll in range(0, total_height, viewport_height): + driver.execute_script("window.scrollTo({0}, {1})".format(0, scroll)) + screenshot_bytes = driver.get_screenshot_as_png() + screenshot = Image.open(io.BytesIO(screenshot_bytes)) + + if scroll + viewport_height > total_height: + offset = (0, int(math.ceil((total_height - viewport_height) * scaling_constant))) + else: + offset = (0, int(math.ceil(scroll * scaling_constant))) + + stitched_image.paste(screenshot, offset) + del screenshot + part += 1 + + date = datetime.today().strftime("%Y-%m-%d-%H:%M:%S") + fullpath = f"{file_path}/{date}.png" + stitched_image.save(fullpath) + return fullpath + # pylint: disable=broad-exception-caught + except Exception as e: + return f"Error: Failed to take full-page screenshot. Details: {str(e)}" @pytest.fixture(scope="module")