diff options
Diffstat (limited to 'tests/test_gn2_smoke.py')
| -rw-r--r-- | tests/test_gn2_smoke.py | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/tests/test_gn2_smoke.py b/tests/test_gn2_smoke.py new file mode 100644 index 0000000..7c23642 --- /dev/null +++ b/tests/test_gn2_smoke.py @@ -0,0 +1,167 @@ +""" +Smoke tests for the genenetwork2 web frontend. + +These tests make HTTP requests to gn2 and assert on status codes and key +page content. They do not require authentication and do not parse full +HTML — just enough to confirm the page rendered without error and the +expected structural marker is present. + +Run with: + + pytest -m "gn2 and smoke" +""" + +import pytest + + +pytestmark = [pytest.mark.gn2, pytest.mark.smoke] + +# --------------------------------------------------------------------------- +# Known-good test data +# --------------------------------------------------------------------------- +_DATASET = "HC_M2_0606_P" +_TRAIT_ID = "1435395_s_at" +_SEARCH_SPECIES = "mouse" +_SEARCH_GROUP = "BXD" +_SEARCH_TYPE = "Hippocampus mRNA" + + +# --------------------------------------------------------------------------- +# Home page +# --------------------------------------------------------------------------- + +class TestHomePage: + def test_returns_200(self, gn2_url, http): + resp = http.get(gn2_url + "/", timeout=30) + assert resp.status_code == 200 + + def test_content_type_is_html(self, gn2_url, http): + resp = http.get(gn2_url + "/", timeout=30) + assert "text/html" in resp.headers.get("Content-Type", "") + + def test_search_form_present(self, gn2_url, http): + resp = http.get(gn2_url + "/", timeout=30) + # The search button has id="btsearch" (from existing gn2 test suite). + assert "btsearch" in resp.text, ( + "Search button element (#btsearch) not found on home page" + ) + + +# --------------------------------------------------------------------------- +# Dataset search +# --------------------------------------------------------------------------- + +class TestSearch: + def test_search_returns_200(self, gn2_url, http): + params = { + "species": _SEARCH_SPECIES, + "group": _SEARCH_GROUP, + "type": _SEARCH_TYPE, + "dataset": _DATASET, + "search_terms_or": "", + "search_terms_and": "MEAN=(15 16) LRS=(23 46)", + } + resp = http.get(gn2_url + "/search", params=params, timeout=60) + assert resp.status_code == 200 + + def test_search_shows_results_found(self, gn2_url, http): + params = { + "species": _SEARCH_SPECIES, + "group": _SEARCH_GROUP, + "type": _SEARCH_TYPE, + "dataset": _DATASET, + "search_terms_or": "", + "search_terms_and": "MEAN=(15 16) LRS=(23 46)", + } + resp = http.get(gn2_url + "/search", params=params, timeout=60) + assert "records found" in resp.text, ( + "Search results page does not contain 'records found'" + ) + + +# --------------------------------------------------------------------------- +# Trait page +# --------------------------------------------------------------------------- + +class TestTraitPage: + def test_known_trait_returns_200(self, gn2_url, http): + resp = http.get( + gn2_url + "/show_trait", + params={"trait_id": _TRAIT_ID, "dataset": _DATASET}, + timeout=60, + ) + assert resp.status_code == 200, ( + f"Expected 200 for show_trait?trait_id={_TRAIT_ID}&dataset={_DATASET}, " + f"got {resp.status_code}" + ) + + def test_trait_page_has_data_form(self, gn2_url, http): + resp = http.get( + gn2_url + "/show_trait", + params={"trait_id": _TRAIT_ID, "dataset": _DATASET}, + timeout=60, + ) + assert 'id="trait_data_form"' in resp.text, ( + "Trait page is missing the #trait_data_form element" + ) + + def test_trait_page_references_dataset(self, gn2_url, http): + resp = http.get( + gn2_url + "/show_trait", + params={"trait_id": _TRAIT_ID, "dataset": _DATASET}, + timeout=60, + ) + assert _DATASET in resp.text, ( + f"Dataset name '{_DATASET}' not found in trait page" + ) + + def test_unknown_trait_does_not_500(self, gn2_url, http): + resp = http.get( + gn2_url + "/show_trait", + params={"trait_id": "nonexistent_00000", "dataset": "NONEXISTENT_XYZ"}, + timeout=60, + ) + assert resp.status_code != 500, ( + f"Unknown trait/dataset caused 500: {resp.text[:500]}" + ) + + +# --------------------------------------------------------------------------- +# gn2 → gn-auth authorization call-through +# +# When gn2 renders the trait page for a public trait, it calls gn-auth's +# POST /auth/data/authorisation internally. A 200 response with the data +# form present confirms that the gn2 → gn-auth auth call succeeded. +# --------------------------------------------------------------------------- + +class TestGn2ToGnAuthAuthFlow: + def test_public_trait_page_renders_without_auth(self, gn2_url, http): + """ + The trait page for a known public trait must render fully without + the user being logged in. A 200 response with the data form confirms + that gn2 successfully called gn-auth's data/authorisation endpoint + and got a public-access response. + """ + resp = http.get( + gn2_url + "/show_trait", + params={"trait_id": _TRAIT_ID, "dataset": _DATASET}, + timeout=60, + ) + assert resp.status_code == 200 + assert 'id="trait_data_form"' in resp.text + + +# --------------------------------------------------------------------------- +# gn2 OAuth2 endpoints — basic reachability +# --------------------------------------------------------------------------- + +class TestOAuth2Endpoints: + def test_login_page_reachable(self, gn2_url, http): + """The OAuth2 authorise redirect must be reachable (not 500).""" + resp = http.get(gn2_url + "/login", timeout=30, allow_redirects=True) + assert resp.status_code != 500 + + def test_oauth2_code_endpoint_without_code_does_not_500(self, gn2_url, http): + """The callback endpoint without a code param should 400/redirect, not 500.""" + resp = http.get(gn2_url + "/oauth2/code", timeout=30, allow_redirects=False) + assert resp.status_code != 500 |
