Spaces:
Sleeping
Sleeping
File size: 4,239 Bytes
06b349d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | import pytest
from app.models import Book, Status
def seed(client, *books): # books: (title, author, status) tuples
store = client.app.state.store
for title, author, status in books:
book = Book(id=store._next_id, title=title, author=author, status=status)
store._books[book.id] = book
store._next_id += 1
def test_list_empty_returns_empty_array(client):
r = client.get("/api/books")
assert r.status_code == 200
assert r.json() == []
def test_list_all_in_id_order(client):
seed(
client,
("Dune", "Frank Herbert", Status.READING),
("Emma", None, Status.TO_READ),
("Ulysses", "James Joyce", Status.DONE),
)
r = client.get("/api/books")
assert r.status_code == 200
assert r.json() == [
{"id": 1, "title": "Dune", "author": "Frank Herbert", "status": "reading"},
{"id": 2, "title": "Emma", "author": None, "status": "to-read"},
{"id": 3, "title": "Ulysses", "author": "James Joyce", "status": "done"},
]
@pytest.mark.parametrize(
("status", "expected_ids"),
[("to-read", [2, 4]), ("reading", [1]), ("done", [3])],
)
def test_list_filtered_by_status(client, status, expected_ids):
seed(
client,
("Dune", "Frank Herbert", Status.READING),
("Emma", None, Status.TO_READ),
("Ulysses", "James Joyce", Status.DONE),
("Beloved", "Toni Morrison", Status.TO_READ),
)
r = client.get("/api/books", params={"status": status})
assert r.status_code == 200
body = r.json()
assert [b["id"] for b in body] == expected_ids
assert all(b["status"] == status for b in body)
def test_list_invalid_status_gives_422(client):
r = client.get("/api/books", params={"status": "bogus"})
assert r.status_code == 422
detail = r.json()["detail"]
assert isinstance(detail, list)
assert detail[0]["loc"] == ["query", "status"]
def test_patch_updates_status_and_persists(client):
seed(
client,
("Dune", "Frank Herbert", Status.READING),
("Emma", None, Status.TO_READ),
)
r = client.patch("/api/books/1", json={"status": "done"})
assert r.status_code == 200
assert r.json() == {
"id": 1,
"title": "Dune",
"author": "Frank Herbert",
"status": "done",
}
listed = client.get("/api/books").json()
assert [b["status"] for b in listed] == ["done", "to-read"]
def test_patch_missing_id_gives_404(client):
seed(client, ("Dune", "Frank Herbert", Status.READING))
r = client.patch("/api/books/99", json={"status": "done"})
assert r.status_code == 404
assert r.json() == {"detail": "Book not found"}
@pytest.mark.parametrize(
"kwargs",
[
{"json": {"status": "bogus"}},
{"json": {}},
{},
],
ids=["bad-status", "missing-status", "missing-body"],
)
def test_patch_invalid_body_gives_422(client, kwargs):
seed(client, ("Dune", "Frank Herbert", Status.READING))
r = client.patch("/api/books/1", **kwargs)
assert r.status_code == 422
assert isinstance(r.json()["detail"], list)
assert client.get("/api/books").json()[0]["status"] == "reading"
def test_patch_non_integer_id_gives_422(client):
r = client.patch("/api/books/abc", json={"status": "done"})
assert r.status_code == 422
assert r.json()["detail"][0]["loc"] == ["path", "book_id"]
def test_stats_empty_store_all_zero(client):
r = client.get("/api/stats")
assert r.status_code == 200
assert r.json() == {
"total": 0,
"by_status": {"to-read": 0, "reading": 0, "done": 0},
}
def test_stats_counts_seeded_books_and_tracks_patch(client):
seed(
client,
("Dune", "Frank Herbert", Status.READING),
("Emma", None, Status.TO_READ),
("Ulysses", "James Joyce", Status.DONE),
("Beloved", "Toni Morrison", Status.DONE),
)
assert client.get("/api/stats").json() == {
"total": 4,
"by_status": {"to-read": 1, "reading": 1, "done": 2},
}
client.patch("/api/books/1", json={"status": "done"})
assert client.get("/api/stats").json() == {
"total": 4,
"by_status": {"to-read": 1, "reading": 0, "done": 3},
}
|