Skip to content

Commit

Permalink
Add location survey to main flow
Browse files Browse the repository at this point in the history
  • Loading branch information
erikh360 committed Aug 16, 2023
1 parent d31136b commit 3382a12
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 12 deletions.
6 changes: 6 additions & 0 deletions yal/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from yal.servicefinder_feedback_survey import ServiceFinderFeedbackSurveyApplication
from yal.surveys.baseline import Application as BaselineSurveyApplication
from yal.surveys.endline import Application as EndlineSurveyApplication
from yal.surveys.location import Application as LocationSurveyApplication
from yal.terms_and_conditions import Application as TermsApplication
from yal.usertest_feedback import Application as FeedbackApplication
from yal.utils import (
Expand Down Expand Up @@ -91,6 +92,7 @@
"remind me tomorrow",
"i m not interested",
}
EJAF_LOCATION_SURVEY_KEYWORDS = {"location"}


class Application(
Expand All @@ -112,6 +114,7 @@ class Application(
BaselineSurveyApplication,
EndlineSurveyApplication,
EndlineTermsApplication,
LocationSurveyApplication,
):
START_STATE = "state_start"

Expand Down Expand Up @@ -271,6 +274,9 @@ async def process_message(self, message):
):
self.user.session_id = None
self.state_name = EndlineSurveyApplication.SURVEY_VALIDATION_STATE
elif keyword in EJAF_LOCATION_SURVEY_KEYWORDS:
self.user.session_id = None
self.state_name = LocationSurveyApplication.START_STATE

except Exception:
logger.exception("Application error")
Expand Down
20 changes: 16 additions & 4 deletions yal/surveys/location.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
)
from vaccine.validators import nonempty_validator
from yal import rapidpro
from yal.askaquestion import Application as AAQApplication
from yal.change_preferences import Application as ChangePreferencesApplication
from yal.utils import get_generic_error, normalise_phonenumber


Expand Down Expand Up @@ -217,7 +219,7 @@ async def state_location_update_status(self):
return await self.go_to_state("state_location_end")

async def state_location_end(self):
msg = self._(
question = self._(
"\n".join(
[
"*And that's a wrap!*",
Expand All @@ -231,8 +233,18 @@ async def state_location_end(self):
]
)
)
return EndState(
return WhatsAppButtonState(
self,
msg,
next=self.START_STATE,
question=question,
choices=[
Choice("menu", self._("Go to the menu")),
Choice("aaq", self._("Ask a question")),
Choice("update_settings", self._("Update Settings")),
],
next={
"menu": "state_pre_mainmenu",
"aaq": AAQApplication.START_STATE,
"update_settings": ChangePreferencesApplication.START_STATE,
},
error=self._(get_generic_error()),
)
15 changes: 15 additions & 0 deletions yal/tests/states_dictionary.md
Original file line number Diff line number Diff line change
Expand Up @@ -754,3 +754,18 @@
| endline_12_q7_platfor_review | TRUE | Text | Did you ever go to one of the services that BWise recommended? |
| endline_12_q8_platfor_review | TRUE | Text | Since joining BWise, have you ever felt like you needed to speak to a counsellor about your mental or sexual health? |
| endline_12_q9_platfor_review | TRUE | Text | Did you know you can request a callback from a LoveLife counsellor through the B-Wise WhatsApp chatbot? |


## EJAF Location Survey
| state_name | accepts_user_input | data_type | description |
| ---------- | ------------------ | --------- | ----------- |
| state_location_introduction | TRUE | Text | Surveu introduction
| state_location_not_invited | FALSE | Text | Tells user they weren't invited to the study
| state_location_already_completed | FALSE | Text | Tells user they already completed the study
| state_location_province | TRUE | Text | Ask user which province they live in
| state_location_not_recruiting | FALSE | Text | Tells user we're not recruiting in the province they live in
| state_location_name_city | TRUE | Text | Ask user the name of the city they live in
| state_location_area_type | TRUE | Text | Ask user the area type they live in
| state_location_group_invite | TRUE | Text | Invite user to group discussions
| state_location_update_status | FALSE | Text | Updates ejaf_location_survey_status contact field on rapidpro
| state_location_end | TRUE | Text | Tells user the survey is over with some prompts to go to different places
43 changes: 35 additions & 8 deletions yal/tests/surveys/test_location.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,25 @@
from yal import config

# TODO: fix this import once this flow is hooked up in main application
from yal.surveys.location import Application
from yal.main import Application


@pytest.fixture
def tester():
return AppTester(Application)


def get_rapidpro_contact(urn):
status = "pending"
if "27820001002" in urn:
status = "completed"
if "27820001003" in urn:
status = None
return {
"fields": {"ejaf_location_survey_status": status},
}


@pytest.fixture(autouse=True)
async def rapidpro_mock():
Sanic.test_mode = True
Expand All @@ -27,6 +38,21 @@ def update_contact(request):
tstate.requests.append(request)
return response.json({}, status=200)

@app.route("/api/v2/contacts.json", methods=["GET"])
def get_contact(request):
tstate.requests.append(request)

urn = request.args.get("urn")
contacts = [get_rapidpro_contact(urn)]

return response.json(
{
"results": contacts,
"next": None,
},
status=200,
)

async with run_sanic(app) as server:
url = config.RAPIDPRO_URL
config.RAPIDPRO_URL = f"http://{server.host}:{server.port}"
Expand All @@ -38,22 +64,23 @@ def update_contact(request):

@pytest.mark.asyncio
async def test_state_location_introduction_already_completed(tester: AppTester):
tester.setup_user_address("27820001002")
tester.setup_state("state_location_introduction")
tester.user.metadata["ejaf_location_survey_status"] = "completed"

await tester.user_input(session=Message.SESSION_EVENT.NEW)

tester.assert_state("state_location_introduction")
tester.assert_state("state_start")

tester.assert_message("This number has already completed the location survey.")


@pytest.mark.asyncio
async def test_state_location_introduction_not_invited(tester: AppTester):
tester.setup_user_address("27820001003")
tester.setup_state("state_location_introduction")
await tester.user_input(session=Message.SESSION_EVENT.NEW)

tester.assert_state("state_location_introduction")
tester.assert_state("state_start")

tester.assert_message(
"Unfortunately it looks like we already have enough people answering this "
Expand Down Expand Up @@ -124,7 +151,7 @@ async def test_state_location_province_excluded(tester: AppTester):
tester.setup_state("state_location_province")
await tester.user_input("4")

tester.assert_state("state_location_introduction")
tester.assert_state("state_start")
tester.assert_message(
"\n".join(
[
Expand Down Expand Up @@ -199,7 +226,7 @@ async def test_state_location_group_invite_submit(tester: AppTester, rapidpro_mo
tester.setup_state("state_location_group_invite")
await tester.user_input("1")

tester.assert_state("state_location_introduction")
tester.assert_state("state_location_end")
tester.assert_message(
"\n".join(
[
Expand All @@ -215,8 +242,8 @@ async def test_state_location_group_invite_submit(tester: AppTester, rapidpro_mo
)
)

assert len(rapidpro_mock.tstate.requests) == 1
request = rapidpro_mock.tstate.requests[0]
assert len(rapidpro_mock.tstate.requests) == 2
request = rapidpro_mock.tstate.requests[1]
assert json.loads(request.body.decode("utf-8")) == {
"fields": {"ejaf_location_survey_status": "completed"},
}

0 comments on commit 3382a12

Please sign in to comment.