Skip to content

Commit ff859d1

Browse files
committed
extra tests coverage
1 parent 3845368 commit ff859d1

1 file changed

Lines changed: 163 additions & 65 deletions

File tree

tests/test_api/test_api_sqla_with_includes.py

Lines changed: 163 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
from collections import defaultdict
23
from itertools import chain, zip_longest
34
from json import dumps
45
from typing import Dict, List
@@ -598,75 +599,172 @@ async def test_many_to_many_load_inner_includes_to_parents(
598599
assert ("child", ViewBase.get_db_item_id(child_4)) not in included_data
599600

600601

601-
@mark.parametrize(
602-
"include, expected_relationships",
603-
[
604-
(
605-
["posts", "posts.user"],
606-
["user"],
607-
),
608-
(
609-
["posts", "posts.comments"],
610-
["comments"],
611-
),
612-
(
613-
["posts", "posts.user", "posts.comments"],
614-
["user", "comments"],
615-
),
616-
],
617-
)
618-
async def test_get_users_with_posts_and_inner_includes(
619-
app: FastAPI,
620-
client: AsyncClient,
621-
user_1: User,
622-
user_2: User,
623-
user_1_posts: list[PostComment],
624-
user_1_post_for_comments: Post,
625-
user_2_comment_for_one_u1_post: PostComment,
626-
include: list[str],
627-
expected_relationships: list[str],
628-
):
629-
"""
630-
Test if requesting `posts.user` and `posts.comments`
631-
returns posts with both `user` and `comments`
632-
"""
633-
assert user_1_posts
634-
assert user_2_comment_for_one_u1_post.author_id == user_2.id
635-
include_param = ",".join(include)
636-
resource_type = "user"
637-
url = app.url_path_for(f"get_{resource_type}_list")
638-
url = f"{url}?filter[name]={user_1.name}&include={include_param}"
639-
response = await client.get(url)
640-
assert response.status_code == status.HTTP_200_OK, response.text
641-
response_json = response.json()
602+
class TestUserWithPostsWithInnerIncludes:
603+
@mark.parametrize(
604+
"include, expected_relationships_post, case_name",
605+
[
606+
(
607+
["posts", "posts.user"],
608+
["user"],
609+
"",
610+
),
611+
(
612+
["posts", "posts.comments"],
613+
["comments"],
614+
"",
615+
),
616+
(
617+
["posts", "posts.user", "posts.comments"],
618+
["user", "comments"],
619+
"case_1",
620+
),
621+
(
622+
["posts", "posts.user", "posts.comments", "posts.comments.author"],
623+
["user", "comments"],
624+
"case_2",
625+
),
626+
],
627+
)
628+
async def test_get_users_with_posts_and_inner_includes(
629+
self,
630+
app: FastAPI,
631+
client: AsyncClient,
632+
user_1: User,
633+
user_2: User,
634+
user_1_posts: list[PostComment],
635+
user_1_post_for_comments: Post,
636+
user_2_comment_for_one_u1_post: PostComment,
637+
include: list[str],
638+
expected_relationships_post: list[str],
639+
case_name: bool,
640+
):
641+
"""
642+
Test if requesting `posts.user` and `posts.comments`
643+
returns posts with both `user` and `comments`
644+
"""
645+
assert user_1_posts
646+
assert user_2_comment_for_one_u1_post.author_id == user_2.id
647+
include_param = ",".join(include)
648+
resource_type = "user"
649+
url = app.url_path_for(f"get_{resource_type}_list")
650+
url = f"{url}?filter[name]={user_1.name}&include={include_param}"
651+
response = await client.get(url)
652+
assert response.status_code == status.HTTP_200_OK, response.text
653+
response_json = response.json()
642654

643-
result_data = response_json["data"]
655+
result_data = response_json["data"]
644656

645-
assert result_data == [
646-
{
647-
"id": str(user_1.id),
648-
"type": resource_type,
649-
"attributes": UserAttributesBaseSchema.from_orm(user_1).dict(),
650-
"relationships": {
651-
"posts": {
652-
"data": [
653-
# relationship info
654-
{"id": str(p.id), "type": "post"}
655-
# for every post
656-
for p in user_1_posts
657-
],
657+
assert result_data == [
658+
{
659+
"id": str(user_1.id),
660+
"type": resource_type,
661+
"attributes": UserAttributesBaseSchema.from_orm(user_1).dict(),
662+
"relationships": {
663+
"posts": {
664+
"data": [
665+
# relationship info
666+
{"id": str(p.id), "type": "post"}
667+
# for every post
668+
for p in user_1_posts
669+
],
670+
},
658671
},
659672
},
660-
},
661-
]
662-
included_data = response_json["included"]
663-
664-
included_posts = [item for item in included_data if item["type"] == "post"]
665-
for post in included_posts:
666-
post_relationships = set(post.get("relationships", {}))
667-
assert post_relationships.intersection(expected_relationships) == set(
668-
expected_relationships,
669-
), f"Expected relationships {expected_relationships} not found in post {post['id']}"
673+
]
674+
included_data = response_json["included"]
675+
676+
included_posts = [item for item in included_data if item["type"] == "post"]
677+
for post in included_posts:
678+
post_relationships = set(post.get("relationships", {}))
679+
assert post_relationships.intersection(expected_relationships_post) == set(
680+
expected_relationships_post,
681+
), f"Expected relationships {expected_relationships_post} not found in post {post['id']}"
682+
683+
if not case_name:
684+
return
685+
included_as_map, expected_includes = self.prepare_expected_includes(
686+
included=included_data,
687+
user_1=user_1,
688+
user_2=user_2,
689+
user_1_posts=user_1_posts,
690+
user_2_comment_for_one_u1_post=user_2_comment_for_one_u1_post,
691+
)
692+
693+
if case_name == "case_2":
694+
assert "user" in expected_includes
695+
elif case_name == "case_1":
696+
expected_includes.pop("user", None)
697+
for pc in expected_includes["post_comment"]:
698+
pc.pop("relationships", None)
699+
700+
assert included_as_map == expected_includes
701+
702+
def prepare_expected_includes(
703+
self,
704+
included: list[dict],
705+
user_1: User,
706+
user_2: User,
707+
user_1_posts: list[PostComment],
708+
user_2_comment_for_one_u1_post: PostComment,
709+
):
710+
included_as_map = defaultdict(list)
711+
for item in included:
712+
included_as_map[item["type"]].append(item)
713+
714+
expected_includes = {
715+
"post": [
716+
#
717+
{
718+
"id": str(p.id),
719+
"type": "post",
720+
"attributes": PostAttributesBaseSchema.from_orm(p).dict(),
721+
"relationships": {
722+
"user": {
723+
"data": {
724+
"id": str(user_1.id),
725+
"type": "user",
726+
},
727+
},
728+
"comments": {
729+
"data": [
730+
{
731+
"id": str(user_2_comment_for_one_u1_post.id),
732+
"type": "post_comment",
733+
},
734+
]
735+
if p.id == user_2_comment_for_one_u1_post.post_id
736+
else [],
737+
},
738+
},
739+
}
740+
#
741+
for p in user_1_posts
742+
],
743+
"post_comment": [
744+
{
745+
"id": str(user_2_comment_for_one_u1_post.id),
746+
"type": "post_comment",
747+
"attributes": PostCommentAttributesBaseSchema.from_orm(user_2_comment_for_one_u1_post).dict(),
748+
"relationships": {
749+
"author": {
750+
"data": {
751+
"id": str(user_2.id),
752+
"type": "user",
753+
},
754+
},
755+
},
756+
},
757+
],
758+
"user": [
759+
{
760+
"id": str(user_2.id),
761+
"type": "user",
762+
"attributes": UserAttributesBaseSchema.from_orm(user_2).dict(),
763+
},
764+
],
765+
}
766+
767+
return included_as_map, expected_includes
670768

671769

672770
async def test_method_not_allowed(app: FastAPI, client: AsyncClient):

0 commit comments

Comments
 (0)