Skip to content

Commit a8a7fee

Browse files
committed
tests coverage for atomic operations, fix tests
1 parent 0cd7ef1 commit a8a7fee

File tree

4 files changed

+152
-8
lines changed

4 files changed

+152
-8
lines changed

tests/fixtures/app.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from pytest import fixture # noqa PT013
66

77
from fastapi_jsonapi import RoutersJSONAPI, init
8+
from fastapi_jsonapi.atomic import AtomicOperations
89
from tests.fixtures.views import (
910
DetailViewBaseGeneric,
1011
ListViewBaseGeneric,
@@ -144,7 +145,11 @@ def add_routers(app_plain: FastAPI):
144145
schema_in_post=ComputerInSchema,
145146
)
146147

148+
atomic = AtomicOperations()
149+
147150
app_plain.include_router(router, prefix="")
151+
app_plain.include_router(atomic.router, prefix="")
152+
148153
init(app_plain)
149154

150155
return app_plain

tests/test_api/test_api_sqla_with_includes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -921,7 +921,7 @@ async def test_create_user_and_fetch_data(self, app: FastAPI, client: AsyncClien
921921
assert response_data["data"]["id"] == user_id
922922

923923
async def test_create_id_by_client(self):
924-
resource_type = "user"
924+
resource_type = "user_custom_b"
925925
app = build_app_custom(
926926
model=User,
927927
schema=UserSchema,
@@ -1110,7 +1110,7 @@ async def test_do_nothing_with_field_not_presented_in_model(
11101110
class UserPatchSchemaWithExtraAttribute(UserPatchSchema):
11111111
attr_which_is_not_presented_in_model: str
11121112

1113-
resource_type = "user"
1113+
resource_type = "user_custom_a"
11141114
app = build_app_custom(
11151115
model=User,
11161116
schema=UserSchema,

tests/test_api/test_routers.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from fastapi_jsonapi.views.view_base import ViewBase
1919
from tests.fixtures.db_connection import async_session_dependency
2020
from tests.fixtures.views import SessionDependency, common_handler
21+
from tests.misc.utils import fake
2122
from tests.models import User
2223
from tests.schemas import (
2324
UserAttributesBaseSchema,
@@ -29,7 +30,7 @@
2930
pytestmark = mark.asyncio
3031

3132

32-
def build_app(detail_view) -> FastAPI:
33+
def build_app(detail_view, resource_type: str) -> FastAPI:
3334
app = FastAPI(
3435
title="FastAPI and SQLAlchemy",
3536
debug=True,
@@ -45,7 +46,7 @@ def build_app(detail_view) -> FastAPI:
4546
class_detail=detail_view,
4647
class_list=ListViewBaseGeneric,
4748
schema=UserSchema,
48-
resource_type="user",
49+
resource_type=resource_type,
4950
schema_in_patch=UserPatchSchema,
5051
schema_in_post=UserInSchema,
5152
model=User,
@@ -93,7 +94,7 @@ class DependencyInjectionDetailView(DetailViewBaseGeneric):
9394
),
9495
}
9596

96-
app = build_app(DependencyInjectionDetailView)
97+
app = build_app(DependencyInjectionDetailView, resource_type="test_dependency_handler_call")
9798
async with AsyncClient(app=app, base_url="http://test") as client:
9899
res = await client.get("/users/1")
99100

@@ -139,7 +140,8 @@ class DependencyInjectionDetailView(DetailViewBaseGeneric):
139140
),
140141
}
141142

142-
app = build_app(DependencyInjectionDetailView)
143+
resource_type = fake.word()
144+
app = build_app(DependencyInjectionDetailView, resource_type=resource_type)
143145
async with AsyncClient(app=app, base_url="http://test") as client:
144146
res = await client.get(f"/users/{user_1.id}", headers={"X-AUTH": "not_admin"})
145147

@@ -160,7 +162,7 @@ class DependencyInjectionDetailView(DetailViewBaseGeneric):
160162
"data": {
161163
"attributes": UserAttributesBaseSchema.from_orm(user_1).dict(),
162164
"id": str(user_1.id),
163-
"type": "user",
165+
"type": resource_type,
164166
},
165167
"jsonapi": {"version": "1.0"},
166168
"meta": None,
@@ -192,7 +194,7 @@ class DependencyInjectionDetailView(DetailViewBaseGeneric):
192194
),
193195
}
194196

195-
app = build_app(DependencyInjectionDetailView)
197+
app = build_app(DependencyInjectionDetailView, resource_type="test_manipulate_data_layer_kwargs")
196198
async with AsyncClient(app=app, base_url="http://test") as client:
197199
res = await client.get(f"/users/{user_1.id}")
198200

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import logging
2+
3+
from httpx import AsyncClient
4+
from pytest import mark # noqa
5+
from sqlalchemy import and_, or_, select
6+
from sqlalchemy.engine import Result
7+
from sqlalchemy.ext.asyncio import AsyncSession
8+
from starlette import status
9+
10+
from tests.misc.utils import fake
11+
from tests.models import User
12+
from tests.schemas import UserAttributesBaseSchema
13+
14+
pytestmark = mark.asyncio
15+
16+
logging.basicConfig(level=logging.DEBUG)
17+
18+
19+
class TestAtomicCreateObjects:
20+
async def test_operations_empty_list(self, client: AsyncClient):
21+
data_atomic_request = {
22+
"atomic:operations": [],
23+
}
24+
response = await client.post("/operations", json=data_atomic_request)
25+
assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY, response.text
26+
assert response.json() == {
27+
# TODO: JSON:API exception!
28+
"detail": [
29+
{
30+
"loc": ["body", "atomic:operations"],
31+
"msg": "ensure this value has at least 1 items",
32+
"type": "value_error.list.min_items",
33+
"ctx": {"limit_value": 1},
34+
},
35+
],
36+
}
37+
38+
async def test_create_one_object(
39+
self,
40+
client: AsyncClient,
41+
async_session: AsyncSession,
42+
):
43+
user = UserAttributesBaseSchema(
44+
name=fake.name(),
45+
age=fake.pyint(min_value=13, max_value=99),
46+
email=fake.email(),
47+
)
48+
data_atomic_request = {
49+
"atomic:operations": [
50+
{
51+
"op": "add",
52+
"data": {
53+
"type": "user",
54+
"attributes": user.dict(),
55+
},
56+
},
57+
],
58+
}
59+
response = await client.post("/operations", json=data_atomic_request)
60+
assert response.status_code == status.HTTP_200_OK, response.text
61+
response_data = response.json()
62+
assert "atomic:results" in response_data, response_data
63+
results = response_data["atomic:results"]
64+
assert results, results
65+
result: dict = results[0]
66+
stmt = select(User).where(
67+
User.name == user.name,
68+
User.age == user.age,
69+
User.email == user.email,
70+
)
71+
db_result: Result = await async_session.execute(stmt)
72+
user_obj: User = db_result.scalar_one()
73+
assert result.pop("meta") is None
74+
assert result == {
75+
"data": {
76+
"attributes": UserAttributesBaseSchema.from_orm(user_obj).dict(),
77+
"id": str(user_obj.id),
78+
"type": "user",
79+
},
80+
}
81+
82+
async def test_create_two_objects(
83+
self,
84+
client: AsyncClient,
85+
async_session: AsyncSession,
86+
):
87+
user_data_1 = UserAttributesBaseSchema(
88+
name=fake.name(),
89+
age=fake.pyint(min_value=13, max_value=99),
90+
email=fake.email(),
91+
)
92+
user_data_2 = UserAttributesBaseSchema(
93+
name=fake.name(),
94+
age=fake.pyint(min_value=13, max_value=99),
95+
email=fake.email(),
96+
)
97+
users_data = [user_data_1, user_data_2]
98+
data_atomic_request = {
99+
"atomic:operations": [
100+
{
101+
"op": "add",
102+
"data": {
103+
"type": "user",
104+
"attributes": user_data.dict(),
105+
},
106+
}
107+
for user_data in users_data
108+
],
109+
}
110+
response = await client.post("/operations", json=data_atomic_request)
111+
assert response.status_code == status.HTTP_200_OK, response.text
112+
response_data = response.json()
113+
assert "atomic:results" in response_data, response_data
114+
results = response_data["atomic:results"]
115+
assert results, results
116+
stmt = select(User).where(
117+
or_(
118+
and_(
119+
User.name == user_data.name,
120+
User.age == user_data.age,
121+
User.email == user_data.email,
122+
)
123+
for user_data in users_data
124+
),
125+
)
126+
db_result: Result = await async_session.execute(stmt)
127+
users: list[User] = db_result.scalars().all()
128+
assert len(users) == len(results)
129+
for result, user in zip(results, users):
130+
assert result.pop("meta") is None
131+
assert result == {
132+
"data": {
133+
"attributes": UserAttributesBaseSchema.from_orm(user).dict(),
134+
"id": str(user.id),
135+
"type": "user",
136+
},
137+
}

0 commit comments

Comments
 (0)