"""Public available-items listing: open access, owner attribution, no notes.""" from fastapi.testclient import TestClient from app.api import app PASSWORD = "correct horse battery staple" CARROCK = "ANVL_Carrack" RIFLE = "BEHR_Rifle_Ballistic_01" IRON_ORE = "Carryable_TBO_FL_1SCU_Commodity_Metal_Ore_Iron" def authed_client(username: str) -> TestClient: client = TestClient(app) resp = client.post( "/api/v1/auth/register", json={"username": username, "password": PASSWORD} ) assert resp.status_code == 201, resp.text return client def add(client: TestClient, class_name: str, quantity: int = 1, notes: str = ""): resp = client.post( "/api/v1/me/inventory", json={"class_name": class_name, "quantity": quantity, "notes": notes}, ) assert resp.status_code in (200, 201), resp.text return resp def offer(client: TestClient, class_name: str, quantity: int = 1): add(client, class_name, quantity) resp = client.patch( f"/api/v1/me/inventory/{class_name}", json={"visibility": "available"} ) assert resp.status_code == 200, resp.text def public_items(**params): return TestClient(app).get("/api/v1/available", params=params).json() def test_listing_is_public_and_empty_by_default(): body = public_items() assert body["total"] == 0 assert body["items"] == [] assert body["page"] == 1 def test_private_items_are_not_listed_until_marked_available(): alice = authed_client("alice") add(alice, CARROCK) assert public_items()["total"] == 0 alice.patch(f"/api/v1/me/inventory/{CARROCK}", json={"visibility": "available"}) body = public_items() assert body["total"] == 1 assert body["items"][0]["class_name"] == CARROCK alice.patch(f"/api/v1/me/inventory/{CARROCK}", json={"visibility": "private"}) assert public_items()["total"] == 0 def test_listing_shows_owner_and_catalog_details_but_not_notes(): alice = authed_client("alice") offer(alice, CARROCK, quantity=3) alice.patch(f"/api/v1/me/inventory/{CARROCK}", json={"notes": "hidden stash"}) item = public_items()["items"][0] assert item["username"] == "alice" assert item["name"] == "Anvil Carrack" assert item["category"] == "ships" assert item["manufacturer"]["code"] == "ANVL" assert item["quantity"] == 3 assert "notes" not in item assert "hidden stash" not in str(public_items()) def test_each_owner_appears_as_its_own_offer(): offer(authed_client("alice"), CARROCK, quantity=1) offer(authed_client("bob"), CARROCK, quantity=2) items = public_items(sort="quantity")["items"] assert [(i["username"], i["quantity"], i["class_name"]) for i in items] == [ ("bob", 2, CARROCK), ("alice", 1, CARROCK), ] def test_removing_an_offer_removes_it_from_the_listing(): alice = authed_client("alice") offer(alice, CARROCK) assert public_items()["total"] == 1 assert alice.delete(f"/api/v1/me/inventory/{CARROCK}").status_code == 204 assert public_items()["total"] == 0 assert public_items()["items"] == [] def test_listing_filters_by_category_and_searches_owner_or_item(): offer(authed_client("alice"), CARROCK) offer(authed_client("bob"), RIFLE) assert [i["class_name"] for i in public_items(category="ships")["items"]] == [CARROCK] assert [i["username"] for i in public_items(search="bob")["items"]] == ["bob"] assert [i["class_name"] for i in public_items(search="carrack")["items"]] == [CARROCK] def test_listing_paginates_and_rejects_unknown_sort(): for quantity, class_name in ((1, CARROCK), (2, RIFLE)): offer(authed_client(f"pilot{quantity}"), class_name, quantity=quantity) body = public_items(page=2, page_size=1) assert body["total"] == 2 assert body["total_pages"] == 2 assert len(body["items"]) == 1 assert public_items(page_size=500)["page_size"] == 100 assert TestClient(app).get("/api/v1/available?sort=bogus").status_code == 422 def test_commodity_offers_are_listed_with_owner(): alice = authed_client("alice") offer(alice, IRON_ORE, quantity=12) body = public_items() assert body["total"] == 1 item = body["items"][0] assert item["name"] == "Iron (Ore)" assert item["category"] == "commodities" assert item["quantity"] == 12 assert item["username"] == "alice"