def test_initiates_subsequent_drill(self): batch1 = DialogEventBatch( phone_number="123456789", seq="0", events=[ NextDrillRequested( phone_number="123456789", user_profile=UserProfile(True), code_validation_payload=CodeValidationPayload(valid=True), ), DrillStarted( phone_number="123456789", user_profile=UserProfile(True), drill=self.drill, first_prompt=self.drill.prompts[0], ), ], ) batch2 = DialogEventBatch( phone_number="987654321", seq="1", events=[ DrillStarted( phone_number="987654321", user_profile=UserProfile(True), drill=self.drill, first_prompt=self.drill.prompts[0], ) ], ) self.assertTrue(initiates_subsequent_drill(batch1)) self.assertFalse(initiates_subsequent_drill(batch2))
def test_get_progress_multiple_users(self): user_id1 = self._make_user_and_get_id() user_id2 = self._make_user_and_get_id(phone_number="987654321") event = DrillStarted( phone_number=self.phone_number, user_profile=UserProfile(True), drill=Drill(slug=get_all_drill_slugs()[0], name="name", prompts=[]), first_prompt=self.prompt, created_time=datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(minutes=32), ) self.repo.update_user(self._make_batch([event])) event2 = DrillStarted( phone_number="987654321", user_profile=UserProfile(True), drill=Drill(slug=get_all_drill_slugs()[1], name="name", prompts=[]), first_prompt=self.prompt, created_time=datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(minutes=32), ) self.repo.update_user(self._make_batch([event2])) drill_progresses = list( self.repo.get_progress_for_users_who_need_drills(30)) self.assertEqual(2, len(drill_progresses)) if drill_progresses[0].user_id == user_id1: drill_progress1 = drill_progresses[0] drill_progress2 = drill_progresses[1] else: drill_progress1 = drill_progresses[1] drill_progress2 = drill_progresses[0] self.assertEqual( DrillProgress( phone_number=self.phone_number, user_id=user_id1, first_unstarted_drill_slug=get_all_drill_slugs()[1], first_incomplete_drill_slug=get_all_drill_slugs()[0], ), drill_progress1, ) self.assertEqual( DrillProgress( phone_number="987654321", user_id=user_id2, first_unstarted_drill_slug=get_all_drill_slugs()[0], first_incomplete_drill_slug=get_all_drill_slugs()[0], ), drill_progress2, )
def test_get_progress_empty(self): drill_progresses = list( self.repo.get_progress_for_users_who_need_drills(30)) self.assertEqual(0, len(drill_progresses)) # no started drills, so we won't receive anything self._make_user_and_get_id() drill_progresses = list( self.repo.get_progress_for_users_who_need_drills(30)) self.assertEqual(0, len(drill_progresses)) for slug in get_all_drill_slugs(): event = DrillStarted( phone_number=self.phone_number, user_profile=UserProfile(True), drill=Drill(slug=slug, name="name", prompts=[]), first_prompt=self.prompt, ) event2 = DrillCompleted( phone_number=self.phone_number, user_profile=UserProfile(True), drill_instance_id=event.drill_instance_id, ) self.repo.update_user(self._make_batch([event, event2])) # all drills complete, so we won't receive anything drill_progresses = list( self.repo.get_progress_for_users_who_need_drills(30)) self.assertEqual(0, len(drill_progresses))
def test_idempotence(self): user_id = self._make_user_and_get_id() event = DrillStarted( phone_number=self.phone_number, user_profile=UserProfile(True), drill=self.drill, first_prompt=self.prompt, ) batch1 = self._make_batch([event]) self.repo.update_user(batch1) user = self.repo.get_user(user_id) self.assertEqual(event.created_time, user.last_interacted_time) event2 = FailedPrompt( phone_number=self.phone_number, user_profile=UserProfile(True), prompt=self.prompt, drill_instance_id=event.drill_instance_id, response="go", abandoned=True, ) batch2 = self._make_batch([event2]) batch2.seq = batch1.seq self.repo.update_user(batch2) user = self.repo.get_user(user_id) self.assertEqual(event.created_time, user.last_interacted_time)
def test_drill_started_and_completed(self): user_id = self._make_user_and_get_id() event = DrillStarted( phone_number=self.phone_number, user_profile=UserProfile(True), drill=Drill(slug=get_all_drill_slugs()[0], name="drill", prompts=[]), first_prompt=self.prompt, ) self.repo.update_user(self._make_batch([event])) drill_status = self.repo.get_drill_status(user_id, get_all_drill_slugs()[0]) self.assertEqual(event.created_time, drill_status.started_time) self.assertIsNone(drill_status.completed_time) event2 = DrillCompleted( phone_number=self.phone_number, user_profile=UserProfile(True), drill_instance_id=event.drill_instance_id, ) self.repo.update_user(self._make_batch([event2])) drill_status = self.repo.get_drill_status(user_id, get_all_drill_slugs()[0]) self.assertEqual(event.created_time, drill_status.started_time) self.assertEqual(event2.created_time, drill_status.completed_time)
def test_user_revalidated(self): user_id = self._make_user_and_get_id() for slug in get_all_drill_slugs(): drill = copy(self.drill) drill.slug = slug event = DrillStarted( phone_number=self.phone_number, user_profile=UserProfile(True), drill=Drill(slug=slug, name="name", prompts=[]), first_prompt=self.prompt, ) event2 = DrillCompleted( phone_number=self.phone_number, user_profile=UserProfile(True), drill_instance_id=event.drill_instance_id, ) self.repo._mark_drill_started(user_id, event, self.repo.engine) self.repo._mark_drill_completed(event2, self.repo.engine) drill_status = self.repo.get_drill_status(user_id, slug) self.assertIsNotNone(drill_status.started_time) self.assertIsNotNone(drill_status.completed_time) self.repo.update_user( self._make_batch([ UserValidated( phone_number=self.phone_number, user_profile=UserProfile(True), code_validation_payload=CodeValidationPayload(valid=True), ) ])) for slug in get_all_drill_slugs(): drill_status = self.repo.get_drill_status(user_id, slug) self.assertIsNone(drill_status.drill_instance_id) self.assertIsNone(drill_status.started_time) self.assertIsNone(drill_status.completed_time)
def test_drill_started(self): original = DrillStarted( phone_number="12345678", user_profile=UserProfile(True), drill=self.drill, first_prompt=self.prompt, drill_instance_id=uuid.uuid4(), ) serialized = original.to_dict() deserialized: DrillStarted = event_from_dict( serialized) # type: ignore self._make_base_assertions(original, deserialized) self.assertEqual(original.drill.name, deserialized.drill.name) self.assertEqual(original.drill_instance_id, deserialized.drill_instance_id) self.assertEqual(original.first_prompt.slug, deserialized.first_prompt.slug)
def test_drill_started(self): profile = UserProfile(validated=True) event = DrillStarted( phone_number="123456789", user_profile=profile, drill=DRILL, first_prompt=DRILL.prompts[0], ) dialog_state = DialogState(phone_number="123456789", seq="0", user_profile=profile) event.apply_to(dialog_state) self.assertEqual(DRILL, dialog_state.current_drill) self.assertEqual( PromptState(slug=DRILL.prompts[0].slug, start_time=event.created_time), dialog_state.current_prompt_state, ) self.assertEqual(event.drill_instance_id, dialog_state.drill_instance_id)
def test_drill_started_event(self): dialog_events: List[DialogEvent] = [ DrillStarted( self.phone, self.validated_user_profile, drill=self.drill, first_prompt=self.drill.prompts[0], ) ] outbound_messages = get_outbound_sms_commands(dialog_events) self.assertEqual(len(outbound_messages), 1) message = outbound_messages[0] self.assertEqual(message.phone_number, self.phone) self.assertEqual(message.event_id, dialog_events[0].event_id) self.assertEqual(message.body, "Hello")
def test_drill_started(self): event = DrillStarted( phone_number=self.phone_number, user_profile=UserProfile(True), drill=self.drill, first_prompt=self.prompt1, ) self.repo.update_user(self._make_batch([event])) drill_instance = self.repo.get_drill_instance(event.drill_instance_id) self.assertIsNotNone(drill_instance) self.assertEqual(event.created_time, drill_instance.current_prompt_start_time) self.assertEqual(self.prompt1.slug, drill_instance.current_prompt_slug) self.assertIsNone(drill_instance.completion_time) self.assertTrue(drill_instance.is_valid)
def test_get_progress_recent_interaction(self): self._make_user_and_get_id() event = DrillStarted( phone_number=self.phone_number, user_profile=UserProfile(True), drill=Drill(slug=get_all_drill_slugs()[0], name="name", prompts=[]), first_prompt=self.prompt, created_time=datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(minutes=20), ) self.repo.update_user(self._make_batch([event])) drill_progresses = list( self.repo.get_progress_for_users_who_need_drills(30)) self.assertEqual(0, len(drill_progresses))
def execute( self, dialog_state: DialogState ) -> List[stopcovid.dialog.models.events.DialogEvent]: drill = get_drill(self.drill_slug) if dialog_state.user_profile.opted_out or not dialog_state.user_profile.validated: logging.warning( f"Attempted to initiate a drill for {dialog_state.phone_number}, " f"who hasn't validated or has opted out.") return [] return [ DrillStarted( phone_number=self.phone_number, user_profile=dialog_state.user_profile, drill=drill, first_prompt=drill.first_prompt(), ) ]
def test_get_progress_for_users_one_user(self): user_id = self._make_user_and_get_id() event = DrillStarted( phone_number=self.phone_number, user_profile=UserProfile(True), drill=Drill(slug=get_all_drill_slugs()[0], name="name", prompts=[]), first_prompt=self.prompt, created_time=datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(minutes=32), ) self.repo.update_user(self._make_batch([event])) drill_progresses = list( self.repo.get_progress_for_users_who_need_drills(30)) self.assertEqual(1, len(drill_progresses)) self.assertEqual( DrillProgress( user_id=user_id, phone_number=self.phone_number, first_incomplete_drill_slug=get_all_drill_slugs()[0], first_unstarted_drill_slug=get_all_drill_slugs()[1], ), drill_progresses[0], ) event2 = DrillCompleted( phone_number=self.phone_number, user_profile=UserProfile(True), drill_instance_id=event.drill_instance_id, created_time=datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(minutes=31), ) self.repo.update_user(self._make_batch([event2])) drill_progresses = list( self.repo.get_progress_for_users_who_need_drills(30)) self.assertEqual(1, len(drill_progresses)) self.assertEqual( DrillProgress( user_id=user_id, phone_number=self.phone_number, first_incomplete_drill_slug=get_all_drill_slugs()[1], first_unstarted_drill_slug=get_all_drill_slugs()[1], ), drill_progresses[0], )
def execute( self, dialog_state: DialogState ) -> List[stopcovid.dialog.models.events.DialogEvent]: if dialog_state.user_profile.opted_out: logging.warning( f"Attempted to initiate a drill for {dialog_state.phone_number} who has opted out." ) return [] return [ DrillStarted( phone_number=self.phone_number, user_profile=dialog_state.user_profile, drill=self.drill, first_prompt=self.drill.first_prompt(), drill_instance_id=self.drill_instance_id, ) ]
def test_delete_user(self): event = DrillStarted( phone_number=self.phone_number, user_profile=UserProfile(True), drill=Drill(slug=get_all_drill_slugs()[0], name="name", prompts=[]), first_prompt=self.prompt, created_time=datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(minutes=32), ) self.repo.update_user(self._make_batch([event])) self.assertIsNotNone( self.repo.get_user_for_phone_number(self.phone_number, self.repo.engine)) self.repo.delete_user_info(self.phone_number) self.assertIsNone( self.repo.get_user_for_phone_number(self.phone_number, self.repo.engine))
def test_last_interacted(self): user_id = self._make_user_and_get_id() event = DrillStarted( phone_number=self.phone_number, user_profile=UserProfile(True), drill=self.drill, first_prompt=self.prompt, ) self.repo.update_user(self._make_batch([event])) user = self.repo.get_user(user_id) self.assertEqual(event.created_time, user.last_interacted_time) event2 = CompletedPrompt( phone_number=self.phone_number, user_profile=UserProfile(True), prompt=self.prompt, drill_instance_id=event.drill_instance_id, response="go", ) self.repo.update_user(self._make_batch([event2])) user = self.repo.get_user(user_id) self.assertEqual(event2.created_time, user.last_interacted_time)