about summary refs log tree commit diff
path: root/tests/test_gn2_smoke.py
diff options
context:
space:
mode:
authorFrederick Muriuki Muriithi2026-05-27 13:49:30 -0500
committerFrederick Muriuki Muriithi2026-05-27 13:49:30 -0500
commit1655d8e45bbf8b0524af6529c142ada98ddace54 (patch)
tree3016c16af0bb4f2e57fffb22264e22ac6b1fc6bb /tests/test_gn2_smoke.py
downloadgn-integration-tests-1655d8e45bbf8b0524af6529c142ada98ddace54.tar.gz
Initialise with smoke tests for various GeneNetwork services.
The code in this commit was written by claude code, and is yet to be
reviewed. Expect changes once the code has been reviewed.
Diffstat (limited to 'tests/test_gn2_smoke.py')
-rw-r--r--tests/test_gn2_smoke.py167
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