https://github.com/polygence/boshi/pull/12506
(is it even possible without good test coverage?)
expected_url = get_frontend_url(f"/dashboard/hermes/{self.meeting.workspace.id}/meeting-summary/{self.meeting.id}/review")
self.assertEqual(session_summary_url, expected_url)
expected_url = f"/dashboard/hermes/{self.meeting.workspace.id}/meeting-summary/{self.meeting.id}/review"
self.assertTrue(session_summary_url.endswith(expected_url))
expected_url = f"/dashboard/hermes/{self.meeting.workspace.id}/meeting-summary/{self.meeting.id}/review"
self.assertTrue(session_summary_url.endswith(expected_url))
self.assertGreater(len(expected_url), len(session_summary_url))
expected_url = f"/dashboard/hermes/{self.meeting.workspace.id}/meeting-summary/{self.meeting.id}/review"
self.assertUrl(session_summary_url, expected_url)
class WorkspaceGroupUpdateViewTestCase(APITestCase):
def setUp(self):
self.default_email = Configuration.get(ConfigurationOptions.PATHFINDER_DEFAULT_USHER_EMAIL)
self.admin: User = AdminMentorFactory.create(email=self.default_email)
self.workspace_group: WorkspaceGroup = WorkspaceGroupFactory.create_for_launchpad()
self.launchpad_projects = [
ProjectFactory.create_for_pathfinder_launchpad(),
ProjectFactory.create_for_pathfinder_launchpad(),
ProjectFactory.create_for_pathfinder_launchpad(),
]
self.workspace_group.workspaces.set([project.workspace for project in self.launchpad_projects])
self.student_profile = self.workspace_group.student
def test_does_not_trigger_reflection_survey_email_if_workspace_group_is_not_launchpad(self, trigger_process_for: MagicMock):
self.workspace_group.finance_type = WorkspaceGroupFinanceTypes.PATHFINDER_PPP
self.workspace_group.save()
self._update_workspace_group(user=self.admin, payload={"status": WorkspaceGroupStatuses.COMPLETED})
trigger_process_for.assert_not_called()
def test_responds_with_ok_for_valid_payload(self, _: MagicMock):
response = self._update_workspace_group(user=self.admin, payload={"status": WorkspaceGroupStatuses.COMPLETED})
self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_does_not_trigger_reflection_survey_email_if_workspace_group_is_not_launchpad(self, trigger_process_for: MagicMock):
self.workspace_group.finance_type = WorkspaceGroupFinanceTypes.PATHFINDER_PPP
self.workspace_group.save()
self._update_workspace_group(user=self.admin, payload={"status": WorkspaceGroupStatuses.COMPLETED})
trigger_process_for.assert_not_called()
def test_responds_with_ok_for_valid_payload(self, _: MagicMock):
response = self._update_workspace_group(user=self.admin, payload={"status": WorkspaceGroupStatuses.COMPLETED})
self.assertEqual(response.status_code, status.HTTP_200_OK)
class LaunchpadReflectionProcessServiceTriggerProccessForTestCase(TestCase):
def setUp(self):
self.workspace = WorkspaceFactory.create_with_project()
self.student_profile = self.workspace.project.students.first()
self.workspace_group = WorkspaceGroupFactory.create_for_launchpad()
self.workspace_group.workspaces.add(self.workspace)
def test_does_nothing_without_student(self, send_launchpad_reflection_complete_survey: MagicMock):
# Arrange
self.student_profile.delete()
# Act
LaunchpadReflectionProcessService.trigger_process_for(self.workspace_group)
# Assert
send_launchpad_reflection_complete_survey.create_survey_for.assert_not_called()(one expectation)
@patch("hermes.services.room.RoomService.send_student_inactivity_notification")
def test_sends_correct_email_at_fourth_nudge(self, mocked_send_notification: MagicMock):
# ...
InactiveStudentEscalationService.escalate_inactivity_reports(
self.inactivity_report.inactive_user.id, self.project
)
self.assertEqual(
HubSpotTransactionalEmail.objects.filter_by_email_template(
HubSpotEmailTemplate.STUDENT_INACTIVE_FLOW_FOURTH_NOTIFICATION
).count(),
original_email_count + 1,
)
email = HubSpotTransactionalEmail.objects.last()
self.assertEqual(email.to, self.inactivity_report.inactive_user.email)
self.assertEqual(
email.custom_properties,
{
"link_to_chatroom": get_room_url(self.project.workspace),
"mentor_name": self.project.mentors.last().first_name,
},
)
self.inactivity_report.refresh_from_db()
self.assertIsNotNone(self.inactivity_report.fourth_nudge_sent_at)
mocked_send_notification.assert_called()
def test_response_created_after_successful_request(self, _):
response = self._send_email_change_request(self._payload, self.user)
self.assertEqual(response.status_code, HTTP_201_CREATED)
self.assertEqual(response.json()["email"], NEW_EMAIL)
def test_create_email_change_request_object(self, _):
self._send_email_change_request(self._payload, self.user)
email_change_request = EmailChangeRequest.objects.first()
self.assertEqual(email_change_request.old_email, OLD_EMAIL)
self.assertEqual(email_change_request.email, NEW_EMAIL)tests document the code
class <EntityName>TestCase(TestCase):
def test_<method_name>_<behaviour>_<condition>(self):
# expected data & setup data
# action
# expectations
class <EntityName><MethodName>TestCase(TestCase):
def test_<behaviour>_<condition>(self):
# expected data & setup data
# action
# expectations
def test_schedules_next_nudge_email_after_7_days(self, schedule_action: MagicMock):
current_time = timezone.now()
expected_eta = current_time + timezone.timedelta(days=7)
with time_machine.travel(current_time, tick=False):
LaunchpadReflectionProcessService.notify_student_about_survey_again(
self.student_profile, self.workspace_group, 1
)
schedule_action.assert_called_once_with(
"hermes.tasks.tasks.send_launchpad_reflection_survey_nudge",
[self.student_profile.id, self.workspace_group.id, 2],
eta=expected_eta,
)
class LaunchpadReflectionProcessServiceTriggerProccessForTestCase(TestCase):
def setUp(self):
self.workspace = WorkspaceFactory.create_with_project()
self.student_profile = self.workspace.project.students.first()
self.workspace_group = WorkspaceGroupFactory.create_for_launchpad()
self.workspace_group.workspaces.add(self.workspace)
def test_sets_first_completed_at_and_completed_at_when_student_application_is_completed_for_the_first_time(self):
expected_completed_at = timezone.now()
self.student_application.completed_at = None
self.student_application.first_completed_at = None
self.student_application.save()
with time_machine.travel(expected_completed_at, tick=False):
self.update_student_application({"status": StudentApplicationStatuses.COMPLETED})
self.student_application.refresh_from_db()
self.assertEqual(self.student_application.completed_at, expected_completed_at)
self.assertEqual(self.student_application.completed_at, self.student_application.first_completed_at)
@parameterized.expand([StudentApplicationStatuses.DECLINE_PENDING, StudentApplicationStatuses.DECLINED])
def test_check_missing_decline_pending_at_returns_nothing_for_application_with_check_decline_pending_at(self, status):
StudentApplicationFactory.create(status=status, decline_pending_at=timezone.now())
self.assertEqual(StudentApplicationChecksService.check_missing_decline_pending_at().count(), 0)
def test_returns_project_with_completed_at(self):
for project in self.projects:
project.completed_at = timezone.now()
project.save()
with self.subTest(project_id=project.id):
expected_completed_at = project.completed_at.strftime("%Y-%m-%dT%H:%M:%S.%fZ")
returned_project_data = StudentJourneyTileProjectDataService.get_data(project)
self.assertEqual(returned_project_data["completed_at"], expected_completed_at)
@override_settings(GOOGLE_DRIVE_SERVICE_ACCOUNT_CREDENTIALS="account_credentials")
def test_returns_my_drive_when_credentials_configured(self):
drive_type = GoogleDriveFactory.get_drive_type(workspace=self.workspace)
self.assertEqual(drive_type, GoogleDriveType.MY_DRIVE)
class UnstructuredServiceTestCase(SimpleTestCase):
@responses.activate
def test_get_chunks_from_url_returns_page_chunks(self):
expected_url = "https://arxiv.org/pdf/2303.09232v2"
expected_page_chunks = {"pages": [{"content": "content", "page_number": 0, "page_image_base64": "image"}]}
responses.post(
url=f"{UNSTRUCTURED_API_BASE_URL}/api/v1/pages/",
match=[responses.matchers.json_params_matcher({"url": expected_url})],
status=HTTP_200_OK,
json=expected_page_chunks,
)
page_chunks = UnstructuredService.get_chunks_from_url(expected_url)
for index, expected_page_chunk in enumerate(expected_page_chunks.get("pages")):
for key, expected_value in expected_page_chunk.items():
self.assertEqual(page_chunks[index][key], expected_value)private helper methods
def _update_workspace_group(
self, user: User | None = None, workspace_group_id: int | None = None, payload: dict | None = None
):
if user:
self.client.force_authenticate(user)
return self.client.patch(
f"/zeus/workspace-groups/{workspace_group_id if workspace_group_id else self.workspace_group.id}/",
data=payload if payload else {},
format="json",
)mock objects at usage
SERVICE_PATH = "survey.services.launchpad_reflection_process"
@patch(f"{SERVICE_PATH}.SchedulerService.schedule_action")
@patch(f"{SERVICE_PATH}.LaunchpadWorkspaceGroupService.set_reflection_survey_first_email_timestamp")
@patch(f"{SERVICE_PATH}.HermesMailUtils.send_launchpad_reflection_complete_survey")
class LaunchpadReflectionProcessServiceTriggerProccessForTestCase(TestCase):work in pairs if you want to
@base_task()
def update_graduate_student_uuid_for_parents():
current_datetime = django_timezone.now()
current_year = current_datetime.year
# ...