import sys import random import pytest INSTALL_PATH = "/app" sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"]) from helper import get_setting_value # noqa: E402 [flake8 lint suppression] from api_server.api_server_start import app # noqa: E402 [flake8 lint suppression] @pytest.fixture(scope="session") def api_token(): return get_setting_value("API_TOKEN") @pytest.fixture def client(): with app.test_client() as client: yield client @pytest.fixture def test_mac(): # Generate a unique MAC for each test run return "AA:BB:CC:" + ":".join(f"{random.randint(0, 255):02X}" for _ in range(3)) def auth_headers(token): return {"Authorization": f"Bearer {token}"} def test_graphql_debug_get(client): """GET /graphql should return the debug string""" resp = client.get("/graphql") assert resp.status_code == 200 assert resp.data.decode() == "NetAlertX GraphQL server running." def test_graphql_post_unauthorized(client): """POST /graphql without token should return 401""" query = {"query": "{ devices { devName devMac } }"} resp = client.post("/graphql", json=query) assert resp.status_code == 401 assert "Unauthorized access attempt" in resp.json.get("message", "") assert "Forbidden" in resp.json.get("error", "") # --- DEVICES TESTS --- def test_graphql_post_devices(client, api_token): """POST /graphql with a valid token should return device data""" query = { "query": """ { devices { devices { devGUID devGroup devIsRandomMac devParentChildrenCount } count } } """ } resp = client.post("/graphql", json=query, headers=auth_headers(api_token)) assert resp.status_code == 200 body = resp.get_json() # GraphQL spec: response always under "data" assert "data" in body data = body["data"] assert "devices" in data assert isinstance(data["devices"]["devices"], list) assert isinstance(data["devices"]["count"], int) # --- SETTINGS TESTS --- def test_graphql_post_settings(client, api_token): """POST /graphql should return settings data""" query = { "query": """ { settings { settings { setKey setValue setGroup } count } } """ } resp = client.post("/graphql", json=query, headers=auth_headers(api_token)) assert resp.status_code == 200 data = resp.json.get("data", {}) assert "settings" in data assert isinstance(data["settings"]["settings"], list) # --- LANGSTRINGS TESTS --- def test_graphql_post_langstrings_specific(client, api_token): """Retrieve a specific langString in a given language""" query = { "query": """ { langStrings(langCode: "en_us", langStringKey: "settings_other_scanners") { langStrings { langCode langStringKey langStringText } count } } """ } resp = client.post("/graphql", json=query, headers=auth_headers(api_token)) assert resp.status_code == 200 data = resp.json.get("data", {}).get("langStrings", {}) assert data["count"] >= 1 for entry in data["langStrings"]: assert entry["langCode"] == "en_us" assert entry["langStringKey"] == "settings_other_scanners" assert isinstance(entry["langStringText"], str) def test_graphql_post_langstrings_fallback(client, api_token): """Fallback to en_us if requested language string is empty""" query = { "query": """ { langStrings(langCode: "de_de", langStringKey: "settings_other_scanners") { langStrings { langCode langStringKey langStringText } count } } """ } resp = client.post("/graphql", json=query, headers=auth_headers(api_token)) assert resp.status_code == 200 data = resp.json.get("data", {}).get("langStrings", {}) assert data["count"] >= 1 # Ensure fallback occurred if de_de text is empty for entry in data["langStrings"]: assert entry["langStringText"] != "" def test_graphql_post_langstrings_all_languages(client, api_token): """Retrieve all languages for a given key""" query = { "query": """ { enStrings: langStrings(langCode: "en_us", langStringKey: "settings_other_scanners") { langStrings { langCode langStringKey langStringText } count } deStrings: langStrings(langCode: "de_de", langStringKey: "settings_other_scanners") { langStrings { langCode langStringKey langStringText } count } } """ } resp = client.post("/graphql", json=query, headers=auth_headers(api_token)) assert resp.status_code == 200 data = resp.json.get("data", {}) assert "enStrings" in data assert "deStrings" in data # At least one string in each language assert data["enStrings"]["count"] >= 1 assert data["deStrings"]["count"] >= 1 # Ensure langCode matches assert all(e["langCode"] == "en_us" for e in data["enStrings"]["langStrings"])