Coverage for src/tests/api/v1/club/members/test_presenters.py: 100%
69 statements
« prev ^ index » next coverage.py v7.11.0, created at 2024-01-01 00:00 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2024-01-01 00:00 +0000
1"""Module for testing the member JSON:API resource."""
3import json
5from typing import Any, AsyncGenerator
7import pytest
9from deepdiff import DeepDiff
10from kwai_api.v1.club.members.presenters import (
11 JsonApiContactPresenter,
12 JsonApiMemberPresenter,
13 JsonApiPersonPresenter,
14 JsonApiUploadMemberPresenter,
15)
16from kwai_bc_club.domain.contact import ContactEntity, ContactIdentifier
17from kwai_bc_club.domain.country import CountryEntity
18from kwai_bc_club.domain.file_upload import FileUploadEntity
19from kwai_bc_club.domain.member import MemberEntity, MemberIdentifier
20from kwai_bc_club.domain.person import PersonEntity, PersonIdentifier
21from kwai_bc_club.domain.value_objects import Address, Birthdate, Gender, License
22from kwai_bc_club.import_members import MemberImportResult, OkMemberImportResult
23from kwai_core.domain.presenter import IterableResult
24from kwai_core.domain.value_objects.date import Date
25from kwai_core.domain.value_objects.email_address import EmailAddress
26from kwai_core.domain.value_objects.identifier import IntIdentifier
27from kwai_core.domain.value_objects.name import Name
28from kwai_core.domain.value_objects.owner import Owner
29from kwai_core.domain.value_objects.unique_id import UniqueId
32@pytest.fixture
33def contact(country: CountryEntity) -> ContactEntity:
34 """A fixture for a contact entity."""
35 return ContactEntity(
36 id=ContactIdentifier(1),
37 emails=(EmailAddress("jigoro.kano@kwai.com"),),
38 address=Address(
39 address="",
40 postal_code="",
41 city="Tokyo",
42 county="",
43 country=country,
44 ),
45 )
48@pytest.fixture
49def expected_contact_json(
50 contact: ContactEntity, expected_country_json: dict[str, Any]
51) -> dict[str, Any]:
52 """A fixture for a JSON:API resource of a contact."""
53 return {
54 "data": {
55 "id": "1",
56 "type": "contacts",
57 "attributes": {
58 "emails": ["jigoro.kano@kwai.com"],
59 "address": "",
60 "postal_code": "",
61 "city": "Tokyo",
62 "county": "",
63 "mobile": "",
64 "tel": "",
65 "remark": "",
66 },
67 "meta": {
68 "created_at": str(contact.traceable_time.created_at),
69 "updated_at": str(contact.traceable_time.updated_at),
70 },
71 "relationships": {
72 "country": {
73 "data": {
74 "id": expected_country_json["data"]["id"],
75 "type": expected_country_json["data"]["type"],
76 }
77 }
78 },
79 },
80 "included": [
81 expected_country_json["data"],
82 ],
83 }
86@pytest.fixture
87def person(contact: ContactEntity, country: CountryEntity) -> PersonEntity:
88 """A fixture for a person entity."""
89 return PersonEntity(
90 id=PersonIdentifier(1),
91 name=Name(first_name="Jigoro", last_name="Kano"),
92 gender=Gender.MALE,
93 birthdate=Birthdate(Date.create(year=1860, month=10, day=28)),
94 contact=contact,
95 nationality=country,
96 )
99@pytest.fixture
100def expected_person_json(
101 person: PersonEntity,
102 expected_contact_json: dict[str, Any],
103 expected_country_json: dict[str, Any],
104) -> dict[str, Any]:
105 """A fixture for a JSON:API resource of a person."""
106 return {
107 "data": {
108 "id": "1",
109 "type": "persons",
110 "attributes": {
111 "first_name": "Jigoro",
112 "last_name": "Kano",
113 "gender": 1,
114 "birthdate": "1860-10-28",
115 "remark": "",
116 },
117 "meta": {
118 "created_at": str(person.traceable_time.created_at),
119 "updated_at": str(person.traceable_time.updated_at),
120 },
121 "relationships": {
122 "nationality": {
123 "data": {
124 "id": expected_country_json["data"]["id"],
125 "type": expected_country_json["data"]["type"],
126 }
127 },
128 "contact": {
129 "data": {
130 "id": expected_contact_json["data"]["id"],
131 "type": expected_contact_json["data"]["type"],
132 }
133 },
134 },
135 },
136 "included": [expected_contact_json["data"], expected_country_json["data"]],
137 }
140def test_create_contact_document(
141 contact: ContactEntity, expected_contact_json: dict[str, Any]
142):
143 """Test the creation of a contact document."""
144 contact_document = JsonApiContactPresenter().present(contact).get_document()
145 json_resource = json.loads(contact_document.model_dump_json())
147 diff = DeepDiff(json_resource, expected_contact_json, ignore_order=True)
148 assert not diff, f"JSON structure is not as expected: {diff}"
151@pytest.fixture
152def member(person: PersonEntity) -> MemberEntity:
153 """A fixture for a member entity."""
154 return MemberEntity(
155 id=MemberIdentifier(1),
156 license=License(number="1234567890", end_date=Date.today().add(years=1)),
157 person=person,
158 )
161def test_create_person_document(
162 person: PersonEntity, expected_person_json: dict[str, Any]
163):
164 """Test the creation of a person document."""
165 person_document = JsonApiPersonPresenter().present(person).get_document()
166 json_resource = json.loads(person_document.model_dump_json())
168 diff = DeepDiff(json_resource, expected_person_json, ignore_order=True)
169 assert not diff, f"JSON structure is not as expected: {diff}"
172@pytest.fixture
173def expected_member_json(
174 member: MemberEntity, expected_person_json: dict[str, Any]
175) -> dict[str, Any]:
176 """A fixture for a JSON:API resource of a member."""
177 return {
178 "data": {
179 "id": str(member.uuid),
180 "type": "members",
181 "attributes": {
182 "license_number": "1234567890",
183 "license_end_date": str(member.license.end_date),
184 "remark": "",
185 "active": True,
186 "competition": False,
187 },
188 "meta": {
189 "created_at": str(member.traceable_time.created_at),
190 "updated_at": str(member.traceable_time.updated_at),
191 },
192 "relationships": {
193 "person": {
194 "data": {
195 "id": expected_person_json["data"]["id"],
196 "type": expected_person_json["data"]["type"],
197 }
198 }
199 },
200 },
201 "included": [expected_person_json["data"], *expected_person_json["included"]],
202 }
205def test_create_member_document(
206 member: MemberEntity, expected_member_json: dict[str, Any]
207):
208 """Test the creation of a JSON:API document for a Member resource."""
209 member_document = JsonApiMemberPresenter().present(member).get_document()
210 json_resource = json.loads(member_document.model_dump_json())
211 diff = DeepDiff(json_resource, expected_member_json, ignore_order=True)
212 assert not diff, f"JSON structure is not expected: {diff}"
215@pytest.fixture
216def make_member_import(make_member):
217 """Fixture factory for creating a member import result."""
219 def _make_member_import():
220 return OkMemberImportResult(
221 file_upload=FileUploadEntity(
222 filename="test.csv",
223 owner=Owner(
224 id=IntIdentifier(1),
225 uuid=UniqueId.generate(),
226 name=Name(first_name="Jigoro", last_name="Kano"),
227 ),
228 ),
229 row=1,
230 member=make_member(),
231 )
233 return _make_member_import
236async def member_import_generator(
237 make_member_import,
238) -> AsyncGenerator[MemberImportResult, None]:
239 """A generator for member import."""
240 yield make_member_import()
243@pytest.fixture
244def iterable_result(make_member_import) -> IterableResult[MemberImportResult]:
245 """A fixture that creates a IterableResult for an upload member result."""
246 return IterableResult[MemberImportResult](
247 count=0, iterator=member_import_generator(make_member_import)
248 )
251async def test_jsonapi_member_upload_presenter(iterable_result):
252 """Test a presenter for an iterable result containing uploaded members."""
253 presenter = JsonApiUploadMemberPresenter()
254 await presenter.present(iterable_result)
255 document = presenter.get_document()
256 assert document is not None, "The presenter should contain a document."
257 assert len(document.data.relationships.members.data) == 1, (
258 "There should be 1 member in the members relationship"
259 )
260 assert document.data.relationships.members.data[0].id != "0", (
261 "The member should have an id"
262 )