def test_code_validation_payload_json_serializable(self): payload = CodeValidationPayload( valid="True", is_demo="False", account_info=AccountInfo( employer_id=1, unit_id=1, employer_name="employer_name", unit_name="unit_name", ), ) self.assertEqual( payload.dict(), { "valid": True, "is_demo": False, "account_info": { "employer_id": 1, "unit_id": 1, "employer_name": "employer_name", "unit_name": "unit_name", }, }, ) # json serialization doesnt blow up payload.json()
def test_revalidate_demo_user(self): validator = MagicMock() validation_payload = CodeValidationPayload(valid=True, is_demo=True) validator.validate_code = MagicMock(return_value=validation_payload) self.assertFalse(self.dialog_state.user_profile.validated) command = ProcessSMSMessage(self.phone_number, "hey", registration_validator=validator) batch = self._process_command(command) self._assert_event_types(batch, DialogEventType.USER_VALIDATED) command = StartDrill(self.phone_number, self.drill.slug, self.drill.dict(), uuid.uuid4()) self._process_command(command) validation_payload = CodeValidationPayload( valid=True, account_info={ "employer_id": 1, "unit_id": 1, "employer_name": "employer_name", "unit_name": "unit_name", }, ) validator.validate_code = MagicMock(return_value=validation_payload) command = ProcessSMSMessage(self.phone_number, "hey", registration_validator=validator) batch = self._process_command(command) self._assert_event_types(batch, DialogEventType.USER_VALIDATED)
def test_advance_demo_user(self, get_drill_mock): validator = MagicMock() validation_payload = CodeValidationPayload(valid=True, is_demo=True) validator.validate_code = MagicMock(return_value=validation_payload) self.assertFalse(self.dialog_state.user_profile.validated) command = ProcessSMSMessage(self.phone_number, "hey", registration_validator=validator) batch = self._process_command(command) self._assert_event_types(batch, DialogEventType.USER_VALIDATED) command = StartDrill(self.phone_number, self.drill.slug) self._process_command(command) # the user's next message isn't a validation code - so we just keep going validation_payload = CodeValidationPayload(valid=False) validator.validate_code = MagicMock(return_value=validation_payload) command = ProcessSMSMessage(self.phone_number, "hey", registration_validator=validator) batch = self._process_command(command) self._assert_event_types(batch, DialogEventType.COMPLETED_PROMPT, DialogEventType.ADVANCED_TO_NEXT_PROMPT)
def validate_code(self, code: str) -> CodeValidationPayload: if code in DRILLS.keys(): return CodeValidationPayload( valid=True, account_info=AccountInfo( employer_id=1, employer_name=code, unit_id=1, unit_name="unit_name", ), ) return CodeValidationPayload(valid=False)
def test_user_revalidated(self): profile = UserProfile(validated=True, is_demo=True) dialog_state = DialogState( "123456789", "0", user_profile=profile, current_drill=DRILL, drill_instance_id=uuid.uuid4(), current_prompt_state=PromptState(slug=DRILL.prompts[0].slug, start_time=NOW), ) event = UserValidated( phone_number="123456789", user_profile=profile, code_validation_payload=CodeValidationPayload( valid=True, is_demo=False, account_info={"foo": "bar"}), ) event.apply_to(dialog_state) self.assertTrue(dialog_state.user_profile.validated) self.assertFalse(dialog_state.user_profile.is_demo) self.assertIsNone(dialog_state.current_drill) self.assertIsNone(dialog_state.current_prompt_state) self.assertIsNone(dialog_state.drill_instance_id) self.assertEqual({"foo": "bar"}, dialog_state.user_profile.account_info)
def test_user_validated(self): profile = UserProfile(validated=False) dialog_state = DialogState(phone_number="123456789", seq="0", user_profile=profile) event = UserValidated( phone_number="123456789", user_profile=profile, code_validation_payload=CodeValidationPayload( valid=True, is_demo=False, account_info={ "employer_id": 1, "unit_id": 1, "employer_name": "employer_name", "unit_name": "unit_name", }, ), ) event.apply_to(dialog_state) self.assertTrue(dialog_state.user_profile.validated) self.assertEqual( { "employer_id": 1, "unit_id": 1, "employer_name": "employer_name", "unit_name": "unit_name", }, dialog_state.user_profile.account_info, )
def test_first_message_validates_user(self): validator = MagicMock() validation_payload = CodeValidationPayload( valid=True, account_info={ "employer_id": 1, "unit_id": 1, "employer_name": "employer_name", "unit_name": "unit_name", }, ) validator.validate_code = MagicMock(return_value=validation_payload) command = ProcessSMSMessage(self.phone_number, "hey", registration_validator=validator) self.assertFalse(self.dialog_state.user_profile.validated) batch = self._process_command(command) self._assert_event_types(batch, DialogEventType.USER_VALIDATED) self.assertEqual( validation_payload, batch.events[0].code_validation_payload # type: ignore ) # and account info is set on the event and user profile self.assertEqual( batch.events[0].user_profile.account_info, AccountInfo( employer_id=1, unit_id=1, employer_name="employer_name", unit_name="unit_name" ), )
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_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_revalidate_user_without_org(self): validator = MagicMock() validation_payload = CodeValidationPayload(valid=True, is_demo=True) validator.validate_code = MagicMock(return_value=validation_payload) self.dialog_state.user_profile.validated = True self.dialog_state.user_profile.account_info = AccountInfo(employer_id=None) command = ProcessSMSMessage(self.phone_number, "hey", registration_validator=validator) batch = self._process_command(command) self._assert_event_types(batch, DialogEventType.USER_VALIDATED) validation_payload = CodeValidationPayload( valid=True, account_info={ "employer_id": 1, "unit_id": 1, "employer_name": "employer_name", "unit_name": "unit_name", }, )
def test_user_validated_event(self): code_validation_payload = CodeValidationPayload(valid=True, is_demo=False) dialog_events: List[DialogEvent] = [ UserValidated(self.phone, self.validated_user_profile, code_validation_payload) ] outbound_messages = get_outbound_sms_commands(dialog_events) self.assertEqual(len(outbound_messages), 0)
def test_user_validated(self): original = UserValidated( "123456789", user_profile=UserProfile(True), code_validation_payload=CodeValidationPayload(valid=True, is_demo=True), ) serialized = original.to_dict() deserialized = event_from_dict(serialized) self._make_base_assertions(original, deserialized)
def test_first_message_does_not_validate_user(self): validator = MagicMock() validation_payload = CodeValidationPayload(valid=False) validator.validate_code = MagicMock(return_value=validation_payload) command = ProcessSMSMessage(self.phone_number, "hey", registration_validator=validator) self.assertFalse(self.dialog_state.user_profile.validated) batch = self._process_command(command) self._assert_event_types(batch, DialogEventType.USER_VALIDATION_FAILED)
def test_doesnt_revalidate_someone_with_an_org(self): validator = MagicMock() validation_payload = CodeValidationPayload(valid=True, is_demo=True) validator.validate_code = MagicMock(return_value=validation_payload) self.dialog_state.user_profile.validated = True self.dialog_state.user_profile.account_info = AccountInfo(employer_id=1) command = ProcessSMSMessage(self.phone_number, "hey", registration_validator=validator) batch = self._process_command(command) # not a USER_VALIDATED event self._assert_event_types(batch, DialogEventType.UNHANDLED_MESSAGE_RECEIVED)
def test_advance_sequence_numbers(self, get_drill_mock): validator = MagicMock() validation_payload = CodeValidationPayload( valid=True, account_info={"company": "WeWork"}) validator.validate_code = MagicMock(return_value=validation_payload) command = ProcessSMSMessage(self.phone_number, "hey", registration_validator=validator) batch = self._process_command(command) self.assertEqual(1, len(batch.events)) self.assertEqual("1", self.dialog_state.seq)
def _make_user_and_get_id(self, **overrides) -> uuid.UUID: return self.repo._create_or_update_user( self._make_batch([ UserValidated( phone_number=overrides.get("phone_number", self.phone_number), user_profile=UserProfile(True), code_validation_payload=CodeValidationPayload(valid=True), ) ]), None, self.repo.engine, )
def test_user_validated(self): profile = UserProfile(validated=False) dialog_state = DialogState("123456789", "0", user_profile=profile) event = UserValidated( phone_number="123456789", user_profile=profile, code_validation_payload=CodeValidationPayload( valid=True, is_demo=False, account_info={"foo": "bar"}), ) event.apply_to(dialog_state) self.assertTrue(dialog_state.user_profile.validated) self.assertEqual({"foo": "bar"}, dialog_state.user_profile.account_info)
def test_revalidate_demo_user(self, get_drill_mock): validator = MagicMock() validation_payload = CodeValidationPayload(valid=True, is_demo=True) validator.validate_code = MagicMock(return_value=validation_payload) self.assertFalse(self.dialog_state.user_profile.validated) command = ProcessSMSMessage(self.phone_number, "hey", registration_validator=validator) batch = self._process_command(command) self._assert_event_types(batch, DialogEventType.USER_VALIDATED) command = StartDrill(self.phone_number, self.drill.slug) self._process_command(command) validation_payload = CodeValidationPayload( valid=True, account_info={"company": "WeWork"}) validator.validate_code = MagicMock(return_value=validation_payload) command = ProcessSMSMessage(self.phone_number, "hey", registration_validator=validator) batch = self._process_command(command) self._assert_event_types(batch, DialogEventType.USER_VALIDATED)
def test_advance_sequence_numbers(self): validator = MagicMock() validation_payload = CodeValidationPayload( valid=True, account_info={ "employer_id": 1, "unit_id": 1, "employer_name": "employer_name", "unit_name": "unit_name", }, ) validator.validate_code = MagicMock(return_value=validation_payload) command = ProcessSMSMessage(self.phone_number, "hey", registration_validator=validator) batch = self._process_command(command) self.assertEqual(1, len(batch.events)) self.assertEqual("1", self.dialog_state.seq)
def test_first_message_validates_user(self, get_drill_mock): validator = MagicMock() validation_payload = CodeValidationPayload( valid=True, account_info={"company": "WeWork"}) validator.validate_code = MagicMock(return_value=validation_payload) command = ProcessSMSMessage(self.phone_number, "hey", registration_validator=validator) self.assertFalse(self.dialog_state.user_profile.validated) batch = self._process_command(command) self._assert_event_types(batch, DialogEventType.USER_VALIDATED) self.assertEqual( validation_payload, batch.events[0].code_validation_payload # type: ignore )
def setUp(self): os.environ["STAGE"] = "test" self.drill_progress_repo = DrillProgressRepository( db.get_test_sqlalchemy_engine) self.drill_progress_repo.drop_and_recreate_tables_testing_only() self.phone_number = "123456789" self.user_id = self.drill_progress_repo._create_or_update_user( DialogEventBatch( events=[ UserValidated(self.phone_number, UserProfile(True), CodeValidationPayload(True)) ], phone_number=self.phone_number, seq="0", batch_id=uuid.uuid4(), ), None, self.drill_progress_repo.engine, ) drill_db_patch = patch( "stopcovid.drill_progress.trigger_reminders.ReminderTriggerer._get_drill_progress_repo", return_value=self.drill_progress_repo, ) drill_db_patch.start() self.addCleanup(drill_db_patch.stop) self.idempotency_checker = IdempotencyChecker( region_name="us-west-2", endpoint_url="http://localhost:9000", aws_access_key_id="fake-key", aws_secret_access_key="fake-secret", ) self.idempotency_checker.drop_and_recreate_table() idempotency_patch = patch( "stopcovid.drill_progress.trigger_reminders.IdempotencyChecker", return_value=self.idempotency_checker, ) idempotency_patch.start() self.addCleanup(idempotency_patch.stop)
def test_user_revalidated(self): drill_instance1 = self._make_drill_instance() drill_instance2 = self._make_drill_instance() self.repo._save_drill_instance(drill_instance1) self.repo._save_drill_instance(drill_instance2) self.assertTrue(drill_instance1.is_valid) self.assertTrue(drill_instance2.is_valid) self.repo.update_user( self._make_batch([ UserValidated( phone_number=self.phone_number, user_profile=UserProfile(True), code_validation_payload=CodeValidationPayload( valid=True, is_demo=True), ) ])) drill_instance1 = self.repo.get_drill_instance( drill_instance1.drill_instance_id) drill_instance2 = self.repo.get_drill_instance( drill_instance2.drill_instance_id) self.assertFalse(drill_instance1.is_valid) self.assertFalse(drill_instance2.is_valid)
def setUp(self): logging.disable(logging.CRITICAL) self.repo = DrillProgressRepository(db.get_test_sqlalchemy_engine) self.repo.drop_and_recreate_tables_testing_only() self.phone_number = "123456789" self.prompt1 = Prompt(slug="first", messages=[]) self.prompt2 = Prompt(slug="second", messages=[]) self.drill = Drill(slug="slug", name="name", prompts=[self.prompt1]) self.seq = 1 self.user_id = self.repo._create_or_update_user( DialogEventBatch( events=[ UserValidated(self.phone_number, UserProfile(True), CodeValidationPayload(True)) ], phone_number=self.phone_number, seq="0", batch_id=uuid.uuid4(), ), None, self.repo.engine, ) self.drill_instance = self._make_drill_instance()
def validate_code(self, code) -> CodeValidationPayload: if code in DRILLS.keys(): return CodeValidationPayload(valid=True, account_info={"code": code}) return CodeValidationPayload(valid=False)