"""API tests for the Star Citizen inventory backend (fixture dataset).""" from fastapi.testclient import TestClient from app.api import app client = TestClient(app) def test_healthz(): resp = client.get("/healthz") assert resp.status_code == 200 body = resp.json() assert body["status"] == "ok" assert body["counts"] == {"ships": 2, "ship-items": 2, "fps-items": 1} def test_stats(): resp = client.get("/api/v1/stats") assert resp.status_code == 200 body = resp.json() assert body["categories"] == {"ships": 2, "ship-items": 2, "fps-items": 1} assert body["manufacturers"] == 4 def test_manufacturers_sorted_by_name(): resp = client.get("/api/v1/manufacturers") assert resp.status_code == 200 names = [m["name"] for m in resp.json()] assert names == ["Anvil Aerospace", "Behring", "PHLD", "Unknown Manufacturer"] def test_items_default_pagination(): resp = client.get("/api/v1/items") assert resp.status_code == 200 body = resp.json() assert body["total"] == 5 assert body["page"] == 1 assert body["page_size"] == 25 assert body["total_pages"] == 1 assert len(body["items"]) == 5 def test_items_page_size_capped(): resp = client.get("/api/v1/items", params={"page_size": 500}) assert resp.status_code == 200 assert resp.json()["page_size"] == 100 def test_items_page_size_minimum_enforced(): resp = client.get("/api/v1/items", params={"page_size": 0}) assert resp.status_code == 422 # pydantic ge=1 validation def test_items_category_filter(): resp = client.get("/api/v1/items", params={"category": "ships"}) assert resp.status_code == 200 body = resp.json() assert body["total"] == 2 assert all(i["category"] == "ships" for i in body["items"]) def test_items_invalid_category_rejected(): resp = client.get("/api/v1/items", params={"category": "bogus"}) assert resp.status_code == 422 def test_items_search_matches_name_case_insensitive(): resp = client.get("/api/v1/items", params={"search": "carrack"}) body = resp.json() assert body["total"] == 1 assert body["items"][0]["name"] == "Anvil Carrack" def test_items_search_matches_class_name(): resp = client.get("/api/v1/items", params={"search": "test_ph"}) body = resp.json() assert body["total"] == 1 assert body["items"][0]["class_name"] == "TEST_Ph_Item" def test_items_manufacturer_filter_case_insensitive(): resp = client.get("/api/v1/items", params={"manufacturer": "behr"}) body = resp.json() assert body["total"] == 2 # Behring shield + Behring rifle assert all(i["manufacturer"]["code"] == "BEHR" for i in body["items"]) def test_items_type_filter_case_insensitive(): resp = client.get("/api/v1/items", params={"type": "weaponpersonal"}) body = resp.json() assert body["total"] == 1 assert body["items"][0]["class_name"] == "BEHR_Rifle_Ballistic_01" def test_items_size_filter(): resp = client.get("/api/v1/items", params={"size": 2}) body = resp.json() assert body["total"] == 2 # TEST_Ph_Item (size 2) + rifle (size 2) assert {i["class_name"] for i in body["items"]} == { "TEST_Ph_Item", "BEHR_Rifle_Ballistic_01", } def test_item_detail_ship(): resp = client.get("/api/v1/items/ANVL_Carrack") assert resp.status_code == 200 body = resp.json() assert body["name"] == "Anvil Carrack" assert body["category"] == "ships" assert body["details"]["crew"] == 4 assert body["details"]["is_spaceship"] is True assert body["details"]["length"] == 35.0 def test_item_detail_item_ports(): resp = client.get("/api/v1/items/BEHR_Rifle_Ballistic_01") assert resp.status_code == 200 body = resp.json() assert body["details"]["ports"][0]["PortName"] == "magazine_attach" assert body["details"]["mass"] == 4 def test_item_detail_404(): resp = client.get("/api/v1/items/NOPE_Does_Not_Exist") assert resp.status_code == 404 assert resp.json()["detail"] == "Item 'NOPE_Does_Not_Exist' not found" def test_placeholder_name_falls_back_to_class_name(): # Ship with Name == "<= PLACEHOLDER =>" resp = client.get("/api/v1/items/TEST_Placeholder_Ship") assert resp.status_code == 200 assert resp.json()["name"] == "TEST Placeholder Ship" # Item with stdItem.Name == "<= PLACEHOLDER =>" resp = client.get("/api/v1/items/TEST_Ph_Item") assert resp.status_code == 200 assert resp.json()["name"] == "TEST Ph Item" def test_manufacturer_placeholder_name_falls_back_to_code(): # manufacturers.json entry with Name == "<= PLACEHOLDER =>" resp = client.get("/api/v1/manufacturers") phld = [m for m in resp.json() if m["code"] == "PHLD"] assert len(phld) == 1 assert phld[0]["name"] == "PHLD" # Item whose embedded manufacturer Name is a placeholder resp = client.get("/api/v1/items/TEST_Ph_Item") assert resp.json()["manufacturer"]["name"] == "UNKN" def test_deterministic_sort_order(): body = client.get("/api/v1/items", params={"page_size": 100}).json() keys = [(i["category"], i["name"].lower()) for i in body["items"]] assert keys == sorted(keys)