async def test_validate_location_google_places_error(self): """ Errors should be retried 3 times """ base.actions.actions.config.GOOGLE_PLACES_API_KEY = "test_key" form = HealthCheckProfileForm() form.places_lookup = utils.AsyncMock() form.places_lookup.side_effect = Exception() tracker = self.get_tracker_for_text_slot_with_message( "location", "Cape Town", ) dispatcher = CollectingDispatcher() events = await form.validate(dispatcher, tracker, {}) assert events == [ SlotSet("location", None), ] [message] = dispatcher.messages assert message["template"] == "utter_incorrect_location" assert form.places_lookup.call_count == 3 base.actions.actions.config.GOOGLE_PLACES_API_KEY = None
async def test_validate_location_google_places(self): """ If there's are google places API credentials, then do a lookup """ base.actions.actions.config.GOOGLE_PLACES_API_KEY = "test_key" form = HealthCheckProfileForm() form.places_lookup = utils.AsyncMock() form.places_lookup.return_value = { "formatted_address": "Cape Town, South Africa", "geometry": { "location": { "lat": 1.23, "lng": 4.56 } }, } tracker = self.get_tracker_for_text_slot_with_message( "location", "Cape Town", ) events = await form.validate(CollectingDispatcher(), tracker, {}) assert events == [ SlotSet("location", "Cape Town, South Africa"), SlotSet("city_location_coords", "+01.23+004.56/"), ] base.actions.actions.config.GOOGLE_PLACES_API_KEY = None
def test_format_location(self): """ Ensures that the location pin is returned in ISO6709 format """ assert HealthCheckProfileForm.format_location(0, 0) == "+00+000/" assert HealthCheckProfileForm.format_location(-1, -1) == "-01-001/" assert (HealthCheckProfileForm.format_location( 1.234, -5.678) == "+01.234-005.678/") assert (HealthCheckProfileForm.format_location( -12.34, 123.456) == "-12.34+123.456/") assert (HealthCheckProfileForm.format_location( 51.481845, 7.216236) == "+51.481845+007.216236/")
def test_complete_form(self): """ Should do nothing """ form = HealthCheckProfileForm() dispatcher = CollectingDispatcher() tracker = utils.get_tracker_for_slot_from_intent( form, "medical_condition", "no", ) result = form.submit(dispatcher, tracker, {}) assert result == []
async def test_places_lookup_no_results(self): """ If there are no results, should return None """ base.actions.actions.config.GOOGLE_PLACES_API_KEY = "test_key" form = HealthCheckProfileForm() querystring = urlencode({ "key": "test_key", "input": "Cape Town", "sessiontoken": "sessiontoken", "language": "en", "components": "country:za", "location": "-33.2277918,21.8568586", }) request = respx.get( "https://maps.googleapis.com/maps/api/place/autocomplete/json?" f"{querystring}", content=json.dumps({"predictions": []}), ) async with httpx.Client() as client: result = await form.places_lookup(client, "Cape Town", "sessiontoken", "wc") assert result is None assert request.called base.actions.actions.config.GOOGLE_PLACES_API_KEY = None
async def test_validate_yes_no(self): """ Tests that yes no slots validate correctly """ form = HealthCheckProfileForm() for slot in [ "medical_condition_obesity", "medical_condition_diabetes", "medical_condition_hypertension", "medical_condition_cardio", ]: tracker = self.get_tracker_for_text_slot_with_message(slot, "yes") events = await form.validate(CollectingDispatcher(), tracker, {}) assert events == [ SlotSet(slot, "yes"), ] tracker = self.get_tracker_for_text_slot_with_message(slot, "no") events = await form.validate(CollectingDispatcher(), tracker, {}) assert events == [ SlotSet(slot, "no"), ] tracker = self.get_tracker_for_text_slot_with_message( slot, "Invalid") dispatcher = CollectingDispatcher() events = await form.validate(dispatcher, tracker, {}) assert events == [ SlotSet(slot, None), ] [message] = dispatcher.messages assert message["template"] == "utter_incorrect_selection"
def test_required_slots_end(self): """ If there are no more slots to fill, should return an empty list """ form = HealthCheckProfileForm() tracker = utils.get_tracker_for_number_slot_with_value( form, "age", "1", { "age": "18-40", "gender": "male", "province": "wc", "location": "Cape Town, South Africa", "location_confirm": "yes", "medical_condition": "no", }, ) assert form.required_slots(tracker) == []
def test_fix_location_format(self): """ Ensures that both correct and incorrect location pins are returned in ISO6709 format """ test_pairs = ( ("+0+0/", "+00+000/"), ("-1-1/", "-01-001/"), ("+1.234-5.678/", "+01.234-005.678/"), ("-12.34+123.456/", "-12.34+123.456/"), ("+51.481845+7.216236/", "+51.481845+007.216236/"), ) for (invalid, valid) in test_pairs: assert HealthCheckProfileForm.fix_location_format(invalid) == valid assert HealthCheckProfileForm.fix_location_format(valid) == valid error = None try: HealthCheckProfileForm.fix_location_format("invalid") except ValueError as e: error = e assert error
async def test_validate_location_blank_text(self): """ If a message without text content is sent, the error message should be displayed """ form = HealthCheckProfileForm() tracker = self.get_tracker_for_text_slot_with_message("location", "") dispatcher = CollectingDispatcher() events = await form.validate(dispatcher, tracker, {}) assert events == [ SlotSet("location", None), ] [message] = dispatcher.messages assert message["template"] == "utter_incorrect_selection"
async def test_validate_location_text(self): """ If there's no google places API credentials, then just use the text """ form = HealthCheckProfileForm() tracker = self.get_tracker_for_text_slot_with_message( "location", "Cape Town", ) events = await form.validate(CollectingDispatcher(), tracker, {}) assert events == [ SlotSet("location", "Cape Town"), ]
async def test_validate_location_google_places_no_results(self): """ If there are no results, then display error message and ask again """ base.actions.actions.config.GOOGLE_PLACES_API_KEY = "test_key" form = HealthCheckProfileForm() form.places_lookup = utils.AsyncMock() form.places_lookup.return_value = None tracker = self.get_tracker_for_text_slot_with_message( "location", "Cape Town", ) dispatcher = CollectingDispatcher() events = await form.validate(dispatcher, tracker, {}) assert events == [ SlotSet("location", None), ] [message] = dispatcher.messages assert message["template"] == "utter_incorrect_location" base.actions.actions.config.GOOGLE_PLACES_API_KEY = None
async def test_validate_location_confirm(self): """ Should reset answers if user selects no """ form = HealthCheckProfileForm() tracker = self.get_tracker_for_text_slot_with_message( "location_confirm", "yes") events = await form.validate(CollectingDispatcher(), tracker, {}) assert events == [ SlotSet("location_confirm", "yes"), ] tracker = self.get_tracker_for_text_slot_with_message( "location_confirm", "no") events = await form.validate(CollectingDispatcher(), tracker, {}) assert events == [ SlotSet("location_confirm", None), SlotSet("location", None), ]
async def test_validate_province(self): form = HealthCheckProfileForm() dispatcher = CollectingDispatcher() i = 1 for p in ["ec", "fs", "gt", "nl", "lp", "mp", "nw", "nc", "wc"]: tracker = utils.get_tracker_for_number_slot_with_value( form, "province", str(i), { "age": "18-39", "gender": "MALE" }) events = await form.run(dispatcher=dispatcher, tracker=tracker, domain=None) assert events == [ SlotSet("province", p), SlotSet("requested_slot", "location"), ] i += 1
async def test_validate_gender(self): form = HealthCheckProfileForm() dispatcher = CollectingDispatcher() tracker = utils.get_tracker_for_number_slot_with_value( form, "gender", "1", {"age": "18-39"}) events = await form.run(dispatcher=dispatcher, tracker=tracker, domain=None) assert events == [ SlotSet("gender", "MALE"), SlotSet("requested_slot", "province"), ] tracker = utils.get_tracker_for_number_slot_with_value( form, "gender", "2", {"age": "18-39"}) events = await form.run(dispatcher=dispatcher, tracker=tracker, domain=None) assert events == [ SlotSet("gender", "FEMALE"), SlotSet("requested_slot", "province"), ] tracker = utils.get_tracker_for_number_slot_with_value( form, "gender", "3", {"age": "18-39"}) events = await form.run(dispatcher=dispatcher, tracker=tracker, domain=None) assert events == [ SlotSet("gender", "OTHER"), SlotSet("requested_slot", "province"), ] tracker = utils.get_tracker_for_number_slot_with_value( form, "gender", "4", {"age": "18-39"}) events = await form.run(dispatcher=dispatcher, tracker=tracker, domain=None) assert events == [ SlotSet("gender", "RATHER NOT SAY"), SlotSet("requested_slot", "province"), ]
async def test_validate_location_pin(self): """ If a location pin is sent, it should be stored """ form = HealthCheckProfileForm() tracker = self.get_tracker_for_text_slot_with_message( "location", "", { "type": "location", "location": { "latitude": 1.23, "longitude": 4.56 } }, ) events = await form.validate(CollectingDispatcher(), tracker, {}) assert events == [ SlotSet("location", "GPS: 1.23, 4.56"), SlotSet("location_coords", "+01.23+004.56/"), SlotSet("location_confirm", "yes"), ]
async def test_validate_age(self): form = HealthCheckProfileForm() dispatcher = CollectingDispatcher() tracker = utils.get_tracker_for_number_slot_with_value( form, "age", "1") events = await form.run(dispatcher=dispatcher, tracker=tracker, domain=None) assert events == [ SlotSet("age", "<18"), SlotSet("location", "<not collected>"), SlotSet("requested_slot", "gender"), ] tracker = utils.get_tracker_for_number_slot_with_value( form, "age", "2") events = await form.run(dispatcher=dispatcher, tracker=tracker, domain=None) assert events == [ SlotSet("age", "18-39"), SlotSet("requested_slot", "gender") ] tracker = utils.get_tracker_for_number_slot_with_value( form, "age", "3") events = await form.run(dispatcher=dispatcher, tracker=tracker, domain=None) assert events == [ SlotSet("age", "40-65"), SlotSet("requested_slot", "gender") ] tracker = utils.get_tracker_for_number_slot_with_value( form, "age", "4") events = await form.run(dispatcher=dispatcher, tracker=tracker, domain=None) assert events == [ SlotSet("age", ">65"), SlotSet("requested_slot", "gender") ] tracker = utils.get_tracker_for_number_slot_with_value( form, "age", ["2", "39"]) events = await form.run(dispatcher=dispatcher, tracker=tracker, domain=None) assert events == [ SlotSet("age", None), SlotSet("requested_slot", "age") ] tracker = utils.get_tracker_for_number_slot_with_value( form, "age", "not a number") events = await form.run(dispatcher=dispatcher, tracker=tracker, domain=None) assert events == [ SlotSet("age", None), SlotSet("requested_slot", "age") ]
async def test_places_lookup(self): """ Should make the relevant requests to the google places autocomplete API """ base.actions.actions.config.GOOGLE_PLACES_API_KEY = "test_key" form = HealthCheckProfileForm() querystring = urlencode({ "key": "test_key", "input": "Cape Town", "sessiontoken": "sessiontoken", "language": "en", "components": "country:za", "location": "-33.2277918,21.8568586", }) request1 = respx.get( "https://maps.googleapis.com/maps/api/place/autocomplete/json?" f"{querystring}", content=json.dumps({"predictions": [{ "place_id": "placeid" }]}), ) querystring = urlencode({ "key": "test_key", "place_id": "placeid", "sessiontoken": "sessiontoken", "language": "en", "fields": "formatted_address,geometry", }) request2 = respx.get( "https://maps.googleapis.com/maps/api/place/details/json?" f"{querystring}", content=json.dumps({ "result": { "formatted_address": "Cape Town, South Africa", "geometry": { "location": { "lat": 1.23, "lng": 4.56 } }, } }), ) async with httpx.Client() as client: result = await form.places_lookup(client, "Cape Town", "sessiontoken", "wc") assert result == { "formatted_address": "Cape Town, South Africa", "geometry": { "location": { "lat": 1.23, "lng": 4.56 } }, } assert request1.called assert request2.called base.actions.actions.config.GOOGLE_PLACES_API_KEY = None