diff --git a/yal/assessments.py b/yal/assessments.py index 284e5e9c..399b9192 100644 --- a/yal/assessments.py +++ b/yal/assessments.py @@ -441,6 +441,15 @@ async def state_handle_assessment_reminder_response(self): return await self.go_to_state("state_pre_mainmenu") async def state_not_interested(self): + msisdn = utils.normalise_phonenumber(self.inbound.from_addr) + whatsapp_id = msisdn.lstrip(" + ") + data = { + "endline_survey_started": "", + } + error = await rapidpro.update_profile(whatsapp_id, data, self.user.metadata) + if error: + return await self.go_to_state("state_error") + return WhatsAppButtonState( self, question=self._( diff --git a/yal/endline_terms_and_conditions.py b/yal/endline_terms_and_conditions.py index c75ec1ea..6f1dc368 100644 --- a/yal/endline_terms_and_conditions.py +++ b/yal/endline_terms_and_conditions.py @@ -193,6 +193,105 @@ async def state_monthly_household_income_endline(self): ] ) ) + return ChoiceState( + self, + question=question, + error=error, + choices=choices, + next="state_household_number_of_people", + ) + + async def state_household_number_of_people(self): + choices = [ + Choice("one", self._("Just me")), + Choice("two", self._("Two people")), + Choice("three", self._("Three people")), + Choice("four", self._("Four people")), + Choice("five", self._("Five people")), + Choice("six", self._("Six people")), + Choice("seven", self._("Seven people")), + Choice("eight_more", self._("Eight or more")), + Choice("rather", "Rather not say"), + Choice("skip_question", self._("Skip question")), + ] + + question = self._( + "\n".join( + [ + "*How many people (including yourself) live in the household now?" + " Don’t forget to include babies.*", + "", + "(If you’re unsure - this counts as anyone sleeping the house" + "4 nights in the past week).", + ] + ) + ) + error = self._( + "\n".join( + [ + "*Oops. We did not understand your answer*", + "Please respond with the *number* of an option below", + "", + "How many people (including yourself) live in the household now?", + ] + ) + ) + + next = ( + { + "one": "state_submit_terms_and_conditions_endline", + "two": "state_submit_terms_and_conditions_endline", + "three": "state_submit_terms_and_conditions_endline", + "four": "state_submit_terms_and_conditions_endline", + "five": "state_submit_terms_and_conditions_endline", + "six": "state_submit_terms_and_conditions_endline", + "seven": "state_submit_terms_and_conditions_endline", + "eight_more": "state_household_number_of_people_more", + }, + ) + return ChoiceState( + self, + question=question, + error=error, + choices=choices, + next=next, + ) + + async def state_household_number_of_people_more(self): + choices = [ + Choice("eight", self._("Including me")), + Choice("nine", self._("Nine people")), + Choice("ten", self._("Ten people")), + Choice("eleven", self._("Eleven people")), + Choice("twelve", self._("Twelve people")), + Choice("thirteen", self._("Thirteen people")), + Choice("fourteen", self._("Fourteen people")), + Choice("fifteen", self._("Fifteen people")), + Choice("rather", "Rather not say"), + Choice("skip_question", self._("Skip question")), + ] + + question = self._( + "\n".join( + [ + "*Okay - you said there are 8 or more people in your household.*", + "*How many people (including yourself) live in the household now?*", + " Don’t forget to include babies." "", + "(If you’re unsure - this counts as anyone sleeping the house" + " 4 nights in the past week).", + ] + ) + ) + error = self._( + "\n".join( + [ + "*Oops. We did not understand your answer*", + "Please respond with the *number* of an option below", + "", + "How many people (including yourself) live in the household now?", + ] + ) + ) return ChoiceState( self, question=question, diff --git a/yal/main.py b/yal/main.py index bd7fc84f..dcd4a594 100644 --- a/yal/main.py +++ b/yal/main.py @@ -128,8 +128,32 @@ async def process_message(self, message): self.delete_metadata(key) keyword = utils.clean_inbound(message.content) + + baseline_survey_completed = self.user.metadata.get( + "baseline_survey_completed" + ) + endline_survey_completed = self.user.metadata.get( + "endline_survey_completed" + ) + + endline_survey_started = self.user.metadata.get("endline_survey_started") + endline_reminder = self.user.metadata.get("endline_reminder") + feedback_state = await self.get_feedback_state() + payload = utils.get_by_path( + message.transport_metadata, "message", "button", "payload" + ) + # Restart keywords that interrupt the current flow + if ( + keyword in GREETING_KEYWORDS + or keyword in TRACKING_KEYWORDS + or keyword in TRACKING_KEYWORDS_ROUND_2 + ): + self.user.session_id = None + self.state_name = self.START_STATE + + elif ( keyword in EMERGENCY_KEYWORDS and message.transport_metadata.get("message", {}).get("type") != "interactive" @@ -149,62 +173,46 @@ async def process_message(self, message): self.user.session_id = None self.state_name = PleaseCallMeApplication.CONFIRM_REDIRECT - if ( - keyword in GREETING_KEYWORDS - or keyword in TRACKING_KEYWORDS - or keyword in TRACKING_KEYWORDS_ROUND_2 - ): - self.user.session_id = None - self.state_name = self.START_STATE - - if keyword in HELP_KEYWORDS: + elif keyword in HELP_KEYWORDS: self.user.session_id = None self.state_name = PleaseCallMeApplication.START_STATE - if keyword in OPTOUT_KEYWORDS: + elif keyword in OPTOUT_KEYWORDS: self.user.session_id = None self.state_name = OptOutApplication.START_STATE - if keyword in FEEDBACK_KEYWORDS: + elif keyword in FEEDBACK_KEYWORDS: self.user.session_id = None self.state_name = FeedbackApplication.START_STATE - if keyword in AAQ_KEYWORDS: + elif keyword in AAQ_KEYWORDS: self.user.session_id = None self.state_name = AaqApplication.START_STATE - if keyword in CALLBACK_CHECK_KEYWORDS: + elif keyword in CALLBACK_CHECK_KEYWORDS: self.user.session_id = None self.state_name = PleaseCallMeApplication.CALLBACK_RESPONSE_STATE - if keyword in QA_RESET_FEEDBACK_TIMESTAMP_KEYWORDS: + elif keyword in QA_RESET_FEEDBACK_TIMESTAMP_KEYWORDS: self.user.session_id = None self.state_name = "state_qa_reset_feedback_timestamp_keywords" - if keyword in ONBOARDING_REMINDER_KEYWORDS: - if self.user.metadata.get("onboarding_reminder_sent"): - self.user.session_id = None - self.state_name = OnboardingApplication.REMINDER_STATE - if keyword in ASSESSMENT_REENGAGEMENT_KEYWORDS: - if self.user.metadata.get("assessment_reminder_sent"): - self.user.session_id = None - self.state_name = AssessmentApplication.REMINDER_STATE + elif keyword in ONBOARDING_REMINDER_KEYWORDS and self.user.metadata.get( + "onboarding_reminder_sent" + ): + self.user.session_id = None + self.state_name = OnboardingApplication.REMINDER_STATE + elif keyword in ASSESSMENT_REENGAGEMENT_KEYWORDS and self.user.metadata.get( + "assessment_reminder_sent" + ): + self.user.session_id = None + self.state_name = AssessmentApplication.REMINDER_STATE - if keyword in SURVEY_KEYWORDS: + elif keyword in SURVEY_KEYWORDS: self.user.session_id = None self.state_name = "state_baseline_start" - baseline_survey_completed = self.user.metadata.get( - "baseline_survey_completed" - ) - endline_survey_completed = self.user.metadata.get( - "endline_survey_completed" - ) - - endline_survey_started = self.user.metadata.get("endline_survey_started") - endline_reminder = self.user.metadata.get("endline_reminder") - - if ( + elif ( keyword in EJAF_ENDLINE_SURVEY_KEYWORDS and baseline_survey_completed and not endline_survey_completed @@ -225,32 +233,30 @@ async def process_message(self, message): else: self.state_name = EndlineTermsApplication.START_STATE - if endline_survey_started and keyword not in EJAF_ENDLINE_SURVEY_KEYWORDS: - self.user.session_id = None - self.state_name = EndlineSurveyApplication.SURVEY_VALIDATION_STATE - # Fields that RapidPro sets after a feedback push message - feedback_state = await self.get_feedback_state() - if feedback_state: + elif feedback_state: if not self.user.session_id: self.user.session_id = random_id() message.session_event = Message.SESSION_EVENT.RESUME self.state_name = feedback_state # Replies to template push messages - payload = utils.get_by_path( - message.transport_metadata, "message", "button", "payload" - ) - if payload: - if payload.startswith("state_") and payload in dir(self): - self.user.session_id = None - self.state_name = payload - elif payload.startswith("page_id_") and is_integer( - payload.split("_")[-1] - ): - self.user.session_id = None - self.save_metadata("push_related_page_id", payload.split("_")[-1]) - self.state_name = "state_prep_push_msg_related_page" + elif payload and payload.startswith("state_") and payload in dir(self): + self.user.session_id = None + self.state_name = payload + + elif ( + payload + and payload.startswith("page_id_") + and is_integer(payload.split("_")[-1]) + ): + self.user.session_id = None + self.save_metadata("push_related_page_id", payload.split("_")[-1]) + self.state_name = "state_prep_push_msg_related_page" + + elif endline_survey_started and keyword not in EJAF_ENDLINE_SURVEY_KEYWORDS: + self.user.session_id = None + self.state_name = EndlineSurveyApplication.SURVEY_VALIDATION_STATE except Exception: logger.exception("Application error") diff --git a/yal/tests/states_dictionary.md b/yal/tests/states_dictionary.md index b9bbb631..da96b6c6 100644 --- a/yal/tests/states_dictionary.md +++ b/yal/tests/states_dictionary.md @@ -612,6 +612,8 @@ | state_platform_review_endline | False | Text | Review the platform | | state_relationship_status_endline | False | Text | endline relationship status | | state_submit_terms_and_conditions_endline | False | Text | Endline Terms and Condition Submit | +| state_household_number_of_people | False | Text | Endline number of peopleing living in househould | +| state_household_number_of_people_more | False | Text | Endline number of peopleing living in househould if more than 8 people | | state_not_interested | False | Text | Endline Survery not interested | | state_monthly_household_income_endline | False | Text | Endline household income | | state_start_terms | False | Text | Endline terms and conditions | diff --git a/yal/tests/surveys/test_endline.py b/yal/tests/surveys/test_endline.py index 344598dd..5e81d1ca 100644 --- a/yal/tests/surveys/test_endline.py +++ b/yal/tests/surveys/test_endline.py @@ -1033,6 +1033,30 @@ async def test_state_body_image_assessment_endline_reminder( tester.assert_metadata("assessment_reminder_type", "endline reengagement 30min") +@pytest.mark.asyncio +async def test_endline_menu_during_assessment(tester: AppTester, rapidpro_mock): + tester.user.metadata["endline_survey_started"] = True + tester.user.metadata["baseline_survey_completed"] = True + tester.user.metadata["terms_accepted"] = True + tester.user.metadata["onboarding_completed"] = True + tester.setup_state("state_gender_attitude_assessment_endline") + + await tester.user_input("menu") + tester.assert_state("state_mainmenu") + + +@pytest.mark.asyncio +async def test_endline_stop_during_assessment(tester: AppTester, rapidpro_mock): + tester.user.metadata["endline_survey_started"] = True + tester.user.metadata["baseline_survey_completed"] = True + tester.user.metadata["terms_accepted"] = True + tester.user.metadata["onboarding_completed"] = True + tester.setup_state("state_gender_attitude_assessment_endline") + + await tester.user_input("stop") + tester.assert_state("state_optout") + + @pytest.mark.asyncio async def test_endline_flow(tester: AppTester, rapidpro_mock): await tester.user_input( diff --git a/yal/tests/test_endline_terms_and_condition.py b/yal/tests/test_endline_terms_and_condition.py index 7a8ca44c..1fd8c403 100644 --- a/yal/tests/test_endline_terms_and_condition.py +++ b/yal/tests/test_endline_terms_and_condition.py @@ -78,9 +78,57 @@ async def test_state_monthly_household_income_endline(tester: AppTester, rapidpr tester.setup_state("state_monthly_household_income_endline") await tester.user_input("1") + tester.assert_state("state_household_number_of_people") + + message = "\n".join( + [ + "*How many people (including yourself) live in the household now?" + " Don’t forget to include babies.*", + "", + "(If you’re unsure - this counts as anyone sleeping the house" + "4 nights in the past week).", + "1. Just me", + "2. Two people", + "3. Three people", + "4. Four people", + "5. Five people", + "6. Six people", + "7. Seven people", + "8. Eight or more", + "9. Rather not say", + "10. Skip question", + ] + ) + tester.assert_message(message) + + +# @pytest.mark.asyncio +# async def test_state_household_number_of_people(tester: AppTester, rapidpro_mock): +# tester.setup_state("state_household_number_of_people") +# await tester.user_input("2") + +# tester.assert_state("state_submit_terms_and_conditions_endline") + + +# @pytest.mark.asyncio +# async def test_state_household_number_of_people_more( +# tester: AppTester, rapidpro_mock +# ): +# tester.setup_state("state_household_number_of_people") +# await tester.user_input("8") + +# tester.assert_state("state_household_number_of_people_more") + + +@pytest.mark.asyncio +async def test_state_household_number_of_people_more(tester: AppTester, rapidpro_mock): + tester.setup_state("state_household_number_of_people_more") + await tester.user_input("1") + tester.assert_state("state_survey_question") message = "\n".join(["◼️◽️◽️◽️", "-----", "", "*I'm my own boss.* 😎"]) + tester.assert_message(message) diff --git a/yal/tests/test_main.py b/yal/tests/test_main.py index 872065a7..372c057f 100644 --- a/yal/tests/test_main.py +++ b/yal/tests/test_main.py @@ -418,6 +418,485 @@ async def test_state_start_contact_fields( assert "blankfield" not in tester.user.metadata +@pytest.mark.asyncio +async def test_help_keywords(tester: AppTester, rapidpro_mock): + rapidpro_mock.tstate.contact_fields["onboarding_completed"] = "TRUE" + rapidpro_mock.tstate.contact_fields["terms_accepted"] = "TRUE" + await tester.user_input("help") + tester.assert_state("state_in_hours") + + +@pytest.mark.asyncio +async def test_feedback_keywords(tester: AppTester, rapidpro_mock): + rapidpro_mock.tstate.contact_fields["onboarding_completed"] = "TRUE" + rapidpro_mock.tstate.contact_fields["terms_accepted"] = "TRUE" + rapidpro_mock.tstate.contact_fields["usertesting_feedback_complete"] = "PENDING" + await tester.user_input("feedback") + tester.assert_state("state_feedback_pleasecallme") + + +@pytest.mark.asyncio +async def test_assessment_reminder_keywords( + tester: AppTester, rapidpro_mock, contentrepo_api_mock +): + rapidpro_mock.tstate.contact_fields["onboarding_completed"] = True + rapidpro_mock.tstate.contact_fields["terms_accepted"] = True + rapidpro_mock.tstate.contact_fields["assessment_reminder_sent"] = True + rapidpro_mock.tstate.contact_fields[ + "assessment_reminder_name" + ] = "locus_of_control_endline" + + await tester.user_input("continue now") + tester.assert_state("state_survey_question") + + +@pytest.mark.asyncio +async def test_endline_catch_all( + tester: AppTester, rapidpro_mock, contentrepo_api_mock +): + rapidpro_mock.tstate.contact_fields["onboarding_completed"] = True + rapidpro_mock.tstate.contact_fields["terms_accepted"] = True + rapidpro_mock.tstate.contact_fields["assessment_reminder_sent"] = True + rapidpro_mock.tstate.contact_fields["endline_survey_started"] = True + + await tester.user_input("this is giberish") + tester.assert_state("state_survey_validation") + + +@pytest.mark.asyncio +async def test_survey_stop(tester: AppTester, rapidpro_mock, contentrepo_api_mock): + rapidpro_mock.tstate.contact_fields["onboarding_completed"] = True + rapidpro_mock.tstate.contact_fields["terms_accepted"] = True + rapidpro_mock.tstate.contact_fields["assessment_reminder_sent"] = True + rapidpro_mock.tstate.contact_fields["endline_survey_started"] = True + + await tester.user_input("stop") + tester.assert_state("state_optout") + + +@pytest.mark.asyncio +async def test_terms_accepted(tester: AppTester, rapidpro_mock, contentrepo_api_mock): + + rapidpro_mock.tstate.contact_fields["terms_accepted"] = True + + await tester.user_input("hi") + tester.assert_state("state_persona_name") + + +@pytest.mark.asyncio +async def test_endline_terms_accepted( + tester: AppTester, rapidpro_mock, contentrepo_api_mock +): + rapidpro_mock.tstate.contact_fields["endline_terms_accepted"] = True + + await tester.user_input("hi") + tester.assert_state("state_survey_question") + + +@pytest.mark.asyncio +async def test_state_locus_of_control_assessment_later( + tester: AppTester, rapidpro_mock, contentrepo_api_mock +): + await tester.user_input( + "test", + transport_metadata={ + "message": { + "button": {"payload": "state_locus_of_control_assessment_later"} + } + }, + ) + + message = "\n".join( + [ + "🤖 No worries, we get it!", + "", + "I'll send you a reminder message in 1 hour, so you can come back " + "and answer these questions.", + "", + "Check you later 🤙🏾", + ] + ) + tester.assert_message(message) + + +@pytest.mark.asyncio +async def test_state_sexual_health_literacy_assessment( + tester: AppTester, rapidpro_mock, contentrepo_api_mock +): + await tester.user_input( + "test", + transport_metadata={ + "message": { + "button": {"payload": "state_sexual_health_literacy_assessment"} + } + }, + ) + + message = "\n".join( + [ + "◼️◽️◽️◽️◽️◽️◽️◽️◽️◽️", + "-----", + "", + "Is the following statement true or false?", + "", + "People can reduce the risk of getting sexual STIs" + " by using condoms every time they have sexual intercourse.", + "", + "🤖 Reply with the number of your chosen answer:", + "", + "1. True", + "2. False", + ] + ) + + tester.assert_message(message) + tester.assert_state("state_survey_question") + tester.assert_metadata("assessment_name", "sexual_health_literacy") + tester.assert_metadata( + "assessment_end_state", "state_sexual_health_literacy_assessment_end" + ) + + +@pytest.mark.asyncio +async def test_state_sexual_health_literacy_assessment_end( + tester: AppTester, rapidpro_mock, contentrepo_api_mock +): + await tester.user_input( + "test", + transport_metadata={ + "message": { + "button": {"payload": "state_sexual_health_literacy_assessment_end"} + } + }, + ) + + message = "\n".join( + [ + "*What would you like to do now?*", + "1. Go to the menu", + "2. Ask a question", + "3. Update settings", + ] + ) + + tester.assert_message(message) + tester.assert_state("state_generic_what_would_you_like_to_do") + + +@pytest.mark.asyncio +async def test_state_depression_and_anxiety_assessment_end( + tester: AppTester, rapidpro_mock, contentrepo_api_mock +): + await tester.user_input( + "test", + transport_metadata={ + "message": { + "button": {"payload": "state_depression_and_anxiety_assessment_end"} + } + }, + ) + + message = "\n".join( + [ + "*What would you like to do now?*", + "1. Go to the menu", + "2. Ask a question", + "3. Update settings", + ] + ) + + tester.assert_message(message) + tester.assert_state("state_generic_what_would_you_like_to_do") + + +@pytest.mark.asyncio +async def test_state_depression_and_anxiety_assessment_later( + tester: AppTester, rapidpro_mock, contentrepo_api_mock +): + await tester.user_input( + "test", + transport_metadata={ + "message": { + "button": {"payload": "state_depression_and_anxiety_assessment_later"} + } + }, + ) + + message = "\n".join( + [ + "🤖 No worries, we get it!", + "", + "I'll send you a reminder message in 1 hour, so you can come back " + "and answer these questions.", + "", + "Check you later 🤙🏾", + ] + ) + tester.assert_message(message) + + +@pytest.mark.asyncio +async def test_state_connectedness_assessment_end( + tester: AppTester, rapidpro_mock, contentrepo_api_mock +): + await tester.user_input( + "test", + transport_metadata={ + "message": {"button": {"payload": "state_connectedness_assessment_end"}} + }, + ) + + message = "\n".join( + [ + "*What would you like to do now?*", + "1. Go to the menu", + "2. Ask a question", + "3. Update settings", + ] + ) + + tester.assert_message(message) + tester.assert_state("state_generic_what_would_you_like_to_do") + + +@pytest.mark.asyncio +async def test_state_connectedness_assessment_later( + tester: AppTester, rapidpro_mock, contentrepo_api_mock +): + await tester.user_input( + "test", + transport_metadata={ + "message": {"button": {"payload": "state_connectedness_assessment_later"}} + }, + ) + + message = "\n".join( + [ + "🤖 No worries, we get it!", + "", + "I'll send you a reminder message in 1 hour, so you can come back " + "and answer these questions.", + "", + "Check you later 🤙🏾", + ] + ) + tester.assert_message(message) + + +@pytest.mark.asyncio +async def test_state_gender_attitude_assessment_end( + tester: AppTester, rapidpro_mock, contentrepo_api_mock +): + await tester.user_input( + "test", + transport_metadata={ + "message": {"button": {"payload": "state_gender_attitude_assessment_end"}} + }, + ) + + message = "\n".join( + [ + "*What would you like to do now?*", + "1. Go to the menu", + "2. Ask a question", + "3. Update settings", + ] + ) + + tester.assert_message(message) + tester.assert_state("state_generic_what_would_you_like_to_do") + + +@pytest.mark.asyncio +async def test_state_gender_attitude_assessment_later( + tester: AppTester, rapidpro_mock, contentrepo_api_mock +): + await tester.user_input( + "test", + transport_metadata={ + "message": {"button": {"payload": "state_gender_attitude_assessment_later"}} + }, + ) + + message = "\n".join( + [ + "🤖 No worries, we get it!", + "", + "I'll send you a reminder message in 1 hour, so you can come back " + "and answer these questions.", + "", + "Check you later 🤙🏾", + ] + ) + tester.assert_message(message) + + +@pytest.mark.asyncio +async def test_state_body_image_assessment_end( + tester: AppTester, rapidpro_mock, contentrepo_api_mock +): + await tester.user_input( + "test", + transport_metadata={ + "message": {"button": {"payload": "state_body_image_assessment_end"}} + }, + ) + + message = "\n".join( + [ + "*What would you like to do now?*", + "1. Go to the menu", + "2. Ask a question", + "3. Update settings", + ] + ) + + tester.assert_message(message) + tester.assert_state("state_generic_what_would_you_like_to_do") + + +@pytest.mark.asyncio +async def test_state_body_image_assessment_later( + tester: AppTester, rapidpro_mock, contentrepo_api_mock +): + await tester.user_input( + "test", + transport_metadata={ + "message": {"button": {"payload": "state_body_image_assessment_later"}} + }, + ) + + message = "\n".join( + [ + "🤖 No worries, we get it!", + "", + "I'll send you a reminder message in 1 hour, so you can come back " + "and answer these questions.", + "", + "Check you later 🤙🏾", + ] + ) + tester.assert_message(message) + + +@pytest.mark.asyncio +async def test_state_self_perceived_healthcare_assessment_end( + tester: AppTester, rapidpro_mock, contentrepo_api_mock +): + await tester.user_input( + "test", + transport_metadata={ + "message": { + "button": {"payload": "state_self_perceived_healthcare_assessment_end"} + } + }, + ) + + message = "\n".join( + [ + "*What would you like to do now?*", + "1. Go to the menu", + "2. Ask a question", + "3. Update settings", + ] + ) + + tester.assert_message(message) + tester.assert_state("state_generic_what_would_you_like_to_do") + + +@pytest.mark.asyncio +async def test_state_self_perceived_healthcare_assessment_later( + tester: AppTester, rapidpro_mock, contentrepo_api_mock +): + await tester.user_input( + "test", + transport_metadata={ + "message": { + "button": { + "payload": "state_self_perceived_healthcare_assessment_later" + } + } + }, + ) + + message = "\n".join( + [ + "🤖 No worries, we get it!", + "", + "I'll send you a reminder message in 1 hour, so you can come back " + "and answer these questions.", + "", + "Check you later 🤙🏾", + ] + ) + tester.assert_message(message) + + +@pytest.mark.asyncio +async def test_baseline_survey_start_keywords( + tester: AppTester, rapidpro_mock, contentrepo_api_mock +): + rapidpro_mock.tstate.contact_fields["onboarding_completed"] = True + rapidpro_mock.tstate.contact_fields["terms_accepted"] = True + rapidpro_mock.tstate.contact_fields["assessment_reminder_sent"] = True + await tester.user_input("baseline") + tester.assert_state("state_survey_question") + + +@pytest.mark.asyncio +async def test_endline_survey_start_keywords( + tester: AppTester, rapidpro_mock, contentrepo_api_mock +): + rapidpro_mock.tstate.contact_fields["onboarding_completed"] = True + rapidpro_mock.tstate.contact_fields["terms_accepted"] = True + rapidpro_mock.tstate.contact_fields["baseline_survey_completed"] = True + rapidpro_mock.tstate.contact_fields["endline_survey_completed"] = False + + await tester.user_input("answer") + tester.assert_state("state_start_terms") + + +@pytest.mark.asyncio +async def test_endline_remind_me_tomorrow_keywords( + tester: AppTester, rapidpro_mock, contentrepo_api_mock +): + rapidpro_mock.tstate.contact_fields["onboarding_completed"] = True + rapidpro_mock.tstate.contact_fields["terms_accepted"] = True + rapidpro_mock.tstate.contact_fields["baseline_survey_completed"] = True + rapidpro_mock.tstate.contact_fields["endline_survey_completed"] = False + + await tester.user_input("remind me tomorrow") + tester.assert_state("state_remind_tomorrow") + + +@pytest.mark.asyncio +async def test_endline_survey_not_interested_reminder_keywords( + tester: AppTester, rapidpro_mock, contentrepo_api_mock +): + rapidpro_mock.tstate.contact_fields["onboarding_completed"] = True + rapidpro_mock.tstate.contact_fields["terms_accepted"] = True + rapidpro_mock.tstate.contact_fields["baseline_survey_completed"] = True + rapidpro_mock.tstate.contact_fields["endline_survey_completed"] = False + rapidpro_mock.tstate.contact_fields["endline_reminder"] = True + + await tester.user_input("I'm not interested") + tester.assert_state("state_reminder_not_interested") + + +@pytest.mark.asyncio +async def test_endline_survey_not_interested_keywords( + tester: AppTester, rapidpro_mock, contentrepo_api_mock +): + rapidpro_mock.tstate.contact_fields["onboarding_completed"] = True + rapidpro_mock.tstate.contact_fields["terms_accepted"] = True + rapidpro_mock.tstate.contact_fields["baseline_survey_completed"] = True + rapidpro_mock.tstate.contact_fields["endline_survey_completed"] = False + + await tester.user_input("I'm not interested") + tester.assert_state("state_no_consent") + + @pytest.mark.asyncio async def test_tracked_keywords_saved( tester: AppTester, rapidpro_mock, contentrepo_api_mock