Skip to content

Commit

Permalink
fix: Add respondent subject metadata to applet base info (M2-8164, M2…
Browse files Browse the repository at this point in the history
…-8026) (#1646)

* fix: add `respondent_meta` to base info endpoint

`respondent_meta` is already generated in two places, and now it's also
returned by the `/applets/{applet_id}/base_info` endpoint. So ensure
consistent structure, created a static method for generating it in
`SubjectsService`.

* test: add `respondentMeta` tests
  • Loading branch information
farmerpaul authored Nov 5, 2024
1 parent a7cfa5f commit cd06aa6
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 7 deletions.
2 changes: 1 addition & 1 deletion src/apps/activities/api/activities.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ async def applet_activities(
activities_future,
)
applet_detail = AppletSingleLanguageDetailMobilePublic.from_orm(applet)
respondent_meta = {"nickname": subject.nickname if subject else None, "tag": subject.tag if subject else None}
respondent_meta = SubjectsService.to_respondent_meta(subject)

if filters.has_submitted or filters.has_score:
activities = await __filter_activities(
Expand Down
3 changes: 2 additions & 1 deletion src/apps/activities/tests/test_activities.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,8 @@ async def test_activities_applet(
assert result["appletDetail"]["activityFlows"] == []

assert result["respondentMeta"] == {
"nickname": f"{tom.first_name} {tom.last_name}",
"subjectId": str(tom_applet_one_subject.id),
"nickname": tom_applet_one_subject.nickname,
"tag": tom_applet_one_subject.tag,
}

Expand Down
2 changes: 1 addition & 1 deletion src/apps/applets/api/applets.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ async def applet_retrieve(
applet.owner_id = applet_owner.owner_id
return AppletRetrieveResponse(
result=AppletSingleLanguageDetailPublic.from_orm(applet),
respondent_meta={"nickname": subject.nickname if subject else None, "tag": subject.tag if subject else None},
respondent_meta=SubjectsService.to_respondent_meta(subject),
applet_meta=AppletMeta(has_assessment=has_assessment),
)

Expand Down
1 change: 1 addition & 0 deletions src/apps/applets/domain/applet.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,4 @@ class AppletActivitiesBaseInfo(AppletMinimumInfo, PublicModel):
updated_at: datetime.datetime | None
activities: list[ActivityBaseInfo]
activity_flows: list[FlowBaseInfo]
respondent_meta: dict | None = None
4 changes: 3 additions & 1 deletion src/apps/applets/service/applet.py
Original file line number Diff line number Diff line change
Expand Up @@ -766,9 +766,11 @@ async def _get_info_by_id(self, schema: AppletSchema, language: str) -> AppletAc
)
activities = ActivityService(self.session, self.user_id).get_info_by_applet_id(schema.id, language)
activity_flows = FlowService(self.session).get_info_by_applet_id(schema.id, language)
futures = await asyncio.gather(activities, activity_flows)
subject = SubjectsService(self.session, self.user_id).get_by_user_and_applet(self.user_id, schema.id)
futures = await asyncio.gather(activities, activity_flows, subject)
applet.activities = futures[0]
applet.activity_flows = futures[1]
applet.respondent_meta = SubjectsService.to_respondent_meta(futures[2])
return applet

async def has_assessment(self, applet_id: uuid.UUID) -> bool:
Expand Down
23 changes: 20 additions & 3 deletions src/apps/applets/tests/test_applet.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from apps.applets.service.applet import AppletService
from apps.shared.exception import NotFoundError
from apps.shared.test.client import TestClient
from apps.subjects.domain import Subject
from apps.users.domain import User
from apps.workspaces.domain.constants import Role
from apps.workspaces.errors import AppletCreationAccessDenied, AppletEncryptionUpdateDenied
Expand Down Expand Up @@ -468,16 +469,27 @@ async def test_applet_list_with_limit(self, client: TestClient, tom: User, apple
assert len(response.json()["result"]) == 1
assert response.json()["result"][0]["id"] == str(applet_one.id)

async def test_applet_detail(self, client: TestClient, tom: User, applet_one_with_flow: AppletFull):
async def test_applet_detail(
self,
client: TestClient,
tom: User,
applet_one_with_flow: AppletFull,
tom_applet_one_subject: Subject,
):
client.login(tom)
response = await client.get(self.applet_detail_url.format(pk=applet_one_with_flow.id))
assert response.status_code == http.HTTPStatus.OK
result = response.json()["result"]
responseJson = response.json()
result = responseJson["result"]
assert result["displayName"] == applet_one_with_flow.display_name
assert result["ownerId"] == str(tom.id)
assert len(result["activities"]) == 1
assert len(result["activityFlows"]) == 1
assert response.json()["respondentMeta"]["nickname"] == tom.get_full_name()
assert responseJson["respondentMeta"] == {
"subjectId": str(tom_applet_one_subject.id),
"nickname": tom_applet_one_subject.nickname,
"tag": tom_applet_one_subject.tag,
}

async def test_public_applet_detail(self, client: TestClient, applet_one_with_public_link: AppletFull):
response = await client.get(self.public_applet_detail_url.format(key=applet_one_with_public_link.link))
Expand Down Expand Up @@ -637,6 +649,11 @@ async def test_get_applet_activities_info(
assert ResponseType.MULTISELECT not in response.json()["result"]["activities"][0]["containsResponseTypes"]
assert response.json()["result"]["activities"][0]["itemCount"] == 1

respondentMeta = response.json()["result"]["respondentMeta"]
assert respondentMeta["subjectId"] is not None
assert respondentMeta["nickname"] == tom.get_full_name()
assert respondentMeta["tag"] == "Team"

async def test_get_public_applet_activities_info(
self,
client: TestClient,
Expand Down
8 changes: 8 additions & 0 deletions src/apps/subjects/services/subjects.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ def __to_db_model(schema: SubjectCreate):
tag=schema.tag,
)

@staticmethod
def to_respondent_meta(subject: Subject | None):
return {
"subjectId": subject.id if subject else None,
"nickname": subject.nickname if subject else None,
"tag": subject.tag if subject else None,
}

async def create(self, schema: SubjectCreate) -> Subject:
subject_with_secret = await self.get_by_secret_id(schema.applet_id, schema.secret_user_id)
if subject_with_secret and not subject_with_secret.is_deleted:
Expand Down

0 comments on commit cd06aa6

Please sign in to comment.