about summary refs log tree commit diff
path: root/tests/test_gn2_smoke.py
diff options
context:
space:
mode:
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