init test commit
This commit is contained in:
Binary file not shown.
BIN
trade-hub/backend/tests/__pycache__/conftest.cpython-314.pyc
Normal file
BIN
trade-hub/backend/tests/__pycache__/conftest.cpython-314.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
trade-hub/backend/tests/__pycache__/test_api.cpython-314.pyc
Normal file
BIN
trade-hub/backend/tests/__pycache__/test_api.cpython-314.pyc
Normal file
Binary file not shown.
4
trade-hub/backend/tests/conftest.py
Normal file
4
trade-hub/backend/tests/conftest.py
Normal file
@@ -0,0 +1,4 @@
|
||||
"""Point the backend at the tiny fixture dataset before the app is imported."""
|
||||
import os
|
||||
|
||||
os.environ["DATA_DIR"] = os.path.join(os.path.dirname(__file__), "fixtures")
|
||||
3
trade-hub/backend/tests/fixtures/fps-items.json
vendored
Normal file
3
trade-hub/backend/tests/fixtures/fps-items.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[
|
||||
{"className": "BEHR_Rifle_Ballistic_01", "reference": "ref-3", "itemName": "behr_rifle_ballistic_01", "type": "WeaponPersonal", "subType": "Medium", "size": 2, "grade": 1, "name": "<= PLACEHOLDER =>", "tags": "weapon", "classification": "FPS.Weapon.Medium", "stdItem": {"UUID": "fps-uuid-1", "ClassName": "BEHR_Rifle_Ballistic_01", "Size": 2, "Grade": 1, "Width": 0.15, "Height": 0.15, "Length": 0.9, "Mass": 4, "Type": "WeaponPersonal.Medium", "Name": "Behring Rifle", "Description": "A ballistic rifle.", "DescriptionText": "", "Manufacturer": {"Name": "Behring", "Code": "BEHR", "UUID": "m-behr"}, "Tags": ["weapon"], "Ports": [{"PortName": "magazine_attach", "Size": 1}]}}
|
||||
]
|
||||
6
trade-hub/backend/tests/fixtures/manufacturers.json
vendored
Normal file
6
trade-hub/backend/tests/fixtures/manufacturers.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
[
|
||||
{"Code": "ANVL", "Name": "Anvil Aerospace", "Reference": "m1", "Description": "Anvil makes ships."},
|
||||
{"Code": "BEHR", "Name": "Behring", "Reference": "m-behr", "Description": "Behring makes weapons."},
|
||||
{"Code": "UNKN", "Name": "Unknown Manufacturer", "Reference": "m-unkn", "Description": ""},
|
||||
{"Code": "PHLD", "Name": "<= PLACEHOLDER =>", "Reference": "m-phld", "Description": ""}
|
||||
]
|
||||
4
trade-hub/backend/tests/fixtures/ship-items.json
vendored
Normal file
4
trade-hub/backend/tests/fixtures/ship-items.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
[
|
||||
{"className": "BEHR_Shield_S1", "reference": "ref-1", "itemName": "behr_shield_s1", "type": "Shield", "subType": "UNDEFINED", "size": 1, "grade": 2, "name": "<= PLACEHOLDER =>", "tags": "shield", "classification": "Ship.Shield", "stdItem": {"UUID": "si-uuid-1", "ClassName": "BEHR_Shield_S1", "Size": 1, "Grade": 2, "Width": 0.5, "Height": 0.5, "Length": 1.0, "Mass": 20, "Type": "Shield.UNDEFINED", "Name": "Behring Shield S1", "Description": "A size 1 shield.", "DescriptionText": "", "Manufacturer": {"Name": "Behring", "Code": "BEHR", "UUID": "m-behr"}, "Tags": ["shield"], "Ports": []}},
|
||||
{"className": "TEST_Ph_Item", "reference": "ref-2", "itemName": "test_ph_item", "type": "PowerPlant", "subType": "UNDEFINED", "size": 2, "grade": 1, "name": "<= PLACEHOLDER =>", "tags": "", "classification": "Ship.PowerPlant", "stdItem": {"UUID": "si-uuid-2", "ClassName": "TEST_Ph_Item", "Size": 2, "Grade": 1, "Width": 0.5, "Height": 0.5, "Length": 0.5, "Mass": 10, "Type": "PowerPlant.UNDEFINED", "Name": "<= PLACEHOLDER =>", "Description": "", "DescriptionText": "", "Manufacturer": {"Name": "<= PLACEHOLDER =>", "Code": "UNKN", "UUID": "m-unkn"}, "Tags": [], "Ports": [{"PortName": "connect", "Size": 1}]}}
|
||||
]
|
||||
4
trade-hub/backend/tests/fixtures/ships.json
vendored
Normal file
4
trade-hub/backend/tests/fixtures/ships.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
[
|
||||
{"UUID": "ship-uuid-1", "ClassName": "ANVL_Carrack", "Name": "Anvil Carrack", "Description": "Long-range explorer.", "DescriptionText": "Long-range explorer.", "Career": "Exploration", "Role": "Expedition", "Manufacturer": {"UUID": "m1", "Code": "ANVL", "Name": "Anvil Aerospace"}, "Size": 4, "Length": 35.0, "Width": 23.0, "Height": 8.5, "Crew": 4, "Mass": 2000000, "IsSpaceship": true, "IsVehicle": false, "IsGravlev": false},
|
||||
{"UUID": "ship-uuid-2", "ClassName": "TEST_Placeholder_Ship", "Name": "<= PLACEHOLDER =>", "Description": "", "DescriptionText": "", "Career": "", "Role": "", "Manufacturer": {"UUID": "m2", "Code": "UNKN", "Name": "Unknown Manufacturer"}, "Size": 1, "Length": 10.0, "Width": 5.0, "Height": 3.0, "Crew": 1, "Mass": 50000, "IsSpaceship": true, "IsVehicle": false, "IsGravlev": false}
|
||||
]
|
||||
157
trade-hub/backend/tests/test_api.py
Normal file
157
trade-hub/backend/tests/test_api.py
Normal file
@@ -0,0 +1,157 @@
|
||||
"""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)
|
||||
Reference in New Issue
Block a user