Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 121bca9

Browse files
committed
add remaining routes
1 parent 0274549 commit 121bca9

File tree

6 files changed

+193
-7
lines changed

6 files changed

+193
-7
lines changed

project/app/api/crud.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,18 @@ async def get(id: int) -> Union[dict, None]:
2626
async def get_all() -> List:
2727
summaries = await TextSummary.all().values()
2828
return summaries
29+
30+
31+
async def delete(id: int) -> int:
32+
summary = await TextSummary.filter(id=id).first().delete()
33+
return summary
34+
35+
36+
async def put(id: int, payload: SummaryPayloadSchema) -> Union[dict, None]:
37+
summary = await TextSummary.filter(id=id).update(
38+
url=payload.url, summary=payload.summary
39+
)
40+
if summary:
41+
updated_summary = await TextSummary.filter(id=id).first().values()
42+
return updated_summary[0]
43+
return None

project/app/api/ping.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
@router.get("/ping")
1212
async def pong(settings: Settings = Depends(get_settings)):
1313
return {
14-
"ping": "pong",
14+
"ping": "pong!",
1515
"environment": settings.environment,
1616
"testing": settings.testing,
1717
}

project/app/api/summaries.py

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,17 @@
33

44
from typing import List
55

6-
from fastapi import APIRouter, HTTPException
6+
from fastapi import APIRouter, HTTPException, Path
77

88
from app.api import crud
9-
from app.models.pydantic import SummaryPayloadSchema, SummaryResponseSchema
109
from app.models.tortoise import SummarySchema
1110

11+
from app.models.pydantic import ( # isort:skip
12+
SummaryPayloadSchema,
13+
SummaryResponseSchema,
14+
SummaryUpdatePayloadSchema,
15+
)
16+
1217
router = APIRouter()
1318

1419

@@ -21,7 +26,7 @@ async def create_summary(payload: SummaryPayloadSchema) -> SummaryResponseSchema
2126

2227

2328
@router.get("/{id}/", response_model=SummarySchema)
24-
async def read_summary(id: int) -> SummarySchema:
29+
async def read_summary(id: int = Path(..., gt=0)) -> SummarySchema:
2530
summary = await crud.get(id)
2631
if not summary:
2732
raise HTTPException(status_code=404, detail="Summary not found")
@@ -32,3 +37,25 @@ async def read_summary(id: int) -> SummarySchema:
3237
@router.get("/", response_model=List[SummarySchema])
3338
async def read_all_summaries() -> List[SummarySchema]:
3439
return await crud.get_all()
40+
41+
42+
@router.delete("/{id}/", response_model=SummaryResponseSchema)
43+
async def delete_summary(id: int = Path(..., gt=0)) -> SummaryResponseSchema:
44+
summary = await crud.get(id)
45+
if not summary:
46+
raise HTTPException(status_code=404, detail="Summary not found")
47+
48+
await crud.delete(id)
49+
50+
return summary
51+
52+
53+
@router.put("/{id}/", response_model=SummarySchema)
54+
async def update_summary(
55+
payload: SummaryUpdatePayloadSchema, id: int = Path(..., gt=0)
56+
) -> SummarySchema:
57+
summary = await crud.put(id, payload)
58+
if not summary:
59+
raise HTTPException(status_code=404, detail="Summary not found")
60+
61+
return summary

project/app/models/pydantic.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
# project/app/models/pydantic.py
22

33

4-
from pydantic import BaseModel
4+
from pydantic import AnyHttpUrl, BaseModel
55

66

77
class SummaryPayloadSchema(BaseModel):
8-
url: str
8+
url: AnyHttpUrl
99

1010

1111
class SummaryResponseSchema(SummaryPayloadSchema):
1212
id: int
13+
14+
15+
class SummaryUpdatePayloadSchema(SummaryPayloadSchema):
16+
summary: str

project/tests/test_ping.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
def test_ping(test_app):
55
response = test_app.get("/ping")
66
assert response.status_code == 200
7-
assert response.json() == {"environment": "dev", "ping": "pong", "testing": True}
7+
assert response.json() == {"environment": "dev", "ping": "pong!", "testing": True}

project/tests/test_summaries.py

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
import json
55

6+
import pytest
7+
68

79
def test_create_summary(test_app_with_db):
810
response = test_app_with_db.post(
@@ -26,6 +28,10 @@ def test_create_summaries_invalid_json(test_app):
2628
]
2729
}
2830

31+
response = test_app.post("/summaries/", data=json.dumps({"url": "invalid://url"}))
32+
assert response.status_code == 422
33+
assert response.json()["detail"][0]["msg"] == "URL scheme not permitted"
34+
2935

3036
def test_read_summary(test_app_with_db):
3137
response = test_app_with_db.post(
@@ -48,6 +54,19 @@ def test_read_summary_incorrect_id(test_app_with_db):
4854
assert response.status_code == 404
4955
assert response.json()["detail"] == "Summary not found"
5056

57+
response = test_app_with_db.get("/summaries/0/")
58+
assert response.status_code == 422
59+
assert response.json() == {
60+
"detail": [
61+
{
62+
"loc": ["path", "id"],
63+
"msg": "ensure this value is greater than 0",
64+
"type": "value_error.number.not_gt",
65+
"ctx": {"limit_value": 0},
66+
}
67+
]
68+
}
69+
5170

5271
def test_read_all_summaries(test_app_with_db):
5372
response = test_app_with_db.post(
@@ -60,3 +79,124 @@ def test_read_all_summaries(test_app_with_db):
6079

6180
response_list = response.json()
6281
assert len(list(filter(lambda d: d["id"] == summary_id, response_list))) == 1
82+
83+
84+
def test_remove_summary(test_app_with_db):
85+
response = test_app_with_db.post(
86+
"/summaries/", data=json.dumps({"url": "https://foo.bar"})
87+
)
88+
summary_id = response.json()["id"]
89+
90+
response = test_app_with_db.delete(f"/summaries/{summary_id}/")
91+
assert response.status_code == 200
92+
assert response.json() == {"id": summary_id, "url": "https://foo.bar"}
93+
94+
95+
def test_remove_summary_incorrect_id(test_app_with_db):
96+
response = test_app_with_db.delete("/summaries/999/")
97+
assert response.status_code == 404
98+
assert response.json()["detail"] == "Summary not found"
99+
100+
response = test_app_with_db.delete("/summaries/0/")
101+
assert response.status_code == 422
102+
assert response.json() == {
103+
"detail": [
104+
{
105+
"loc": ["path", "id"],
106+
"msg": "ensure this value is greater than 0",
107+
"type": "value_error.number.not_gt",
108+
"ctx": {"limit_value": 0},
109+
}
110+
]
111+
}
112+
113+
114+
def test_update_summary(test_app_with_db):
115+
response = test_app_with_db.post(
116+
"/summaries/", data=json.dumps({"url": "https://foo.bar"})
117+
)
118+
summary_id = response.json()["id"]
119+
120+
response = test_app_with_db.put(
121+
f"/summaries/{summary_id}/",
122+
data=json.dumps({"url": "https://foo.bar", "summary": "updated!"}),
123+
)
124+
assert response.status_code == 200
125+
126+
response_dict = response.json()
127+
assert response_dict["id"] == summary_id
128+
assert response_dict["url"] == "https://foo.bar"
129+
assert response_dict["summary"] == "updated!"
130+
assert response_dict["created_at"]
131+
132+
133+
@pytest.mark.parametrize(
134+
"summary_id, payload, status_code, detail",
135+
[
136+
[
137+
999,
138+
{"url": "https://foo.bar", "summary": "updated!"},
139+
404,
140+
"Summary not found",
141+
],
142+
[
143+
0,
144+
{"url": "https://foo.bar", "summary": "updated!"},
145+
422,
146+
[
147+
{
148+
"loc": ["path", "id"],
149+
"msg": "ensure this value is greater than 0",
150+
"type": "value_error.number.not_gt",
151+
"ctx": {"limit_value": 0},
152+
}
153+
],
154+
],
155+
[
156+
1,
157+
{},
158+
422,
159+
[
160+
{
161+
"loc": ["body", "url"],
162+
"msg": "field required",
163+
"type": "value_error.missing",
164+
},
165+
{
166+
"loc": ["body", "summary"],
167+
"msg": "field required",
168+
"type": "value_error.missing",
169+
},
170+
],
171+
],
172+
[
173+
1,
174+
{"url": "https://foo.bar"},
175+
422,
176+
[
177+
{
178+
"loc": ["body", "summary"],
179+
"msg": "field required",
180+
"type": "value_error.missing",
181+
}
182+
],
183+
],
184+
],
185+
)
186+
def test_update_summary_invalid(
187+
test_app_with_db, summary_id, payload, status_code, detail
188+
):
189+
response = test_app_with_db.put(
190+
f"/summaries/{summary_id}/", data=json.dumps(payload)
191+
)
192+
assert response.status_code == status_code
193+
assert response.json()["detail"] == detail
194+
195+
196+
def test_update_summary_invalid_url(test_app):
197+
response = test_app.put(
198+
"/summaries/1/",
199+
data=json.dumps({"url": "invalid://url", "summary": "updated!"}),
200+
)
201+
assert response.status_code == 422
202+
assert response.json()["detail"][0]["msg"] == "URL scheme not permitted"

0 commit comments

Comments
 (0)