def test_evaluate_when_rule_with_invalid_list_item_id(self): when = { "when": [{ "id": "my_answer", "condition": "equals", "value": "an answer" }] } answer_store = AnswerStore() answer_store.add_or_update( Answer(answer_id="my_answer", value="an answer", list_item_id="abc123")) current_location = Location(section_id="some-section", block_id="some-block", list_item_id="123abc") schema = Mock(get_schema()) schema.is_repeating_answer = Mock(return_value=False) self.assertFalse( evaluate_when_rules( when_rules=when["when"], schema=schema, metadata={}, answer_store=answer_store, list_store=ListStore(), current_location=current_location, ))
def test_primary_person_returns_false_on_invalid_id(self): answer_store = AnswerStore() list_store = ListStore(existing_items=[{ "name": "people", "primary_person": "abcdef", "items": ["abcdef", "12345"], }]) current_location = Location(section_id="some-section", block_id="some-block") when_rules = [{ "list": "people", "id_selector": "primary_person", "condition": "equals", "comparison": { "source": "location", "id": "invalid-location-id" }, }] self.assertFalse( evaluate_when_rules( when_rules, get_schema(), {}, answer_store, list_store, current_location=current_location, ))
def test_when_rule_returns_first_item_in_list(self): answer_store = AnswerStore() list_store = ListStore(existing_items=[{ "name": "people", "items": ["abcdef", "12345"] }]) current_location = Location( section_id="some-section", block_id="some-block", list_name="people", list_item_id="abcdef", ) when_rules = [{ "list": "people", "id_selector": "first", "condition": "equals", "comparison": { "source": "location", "id": "list_item_id" }, }] self.assertTrue( evaluate_when_rules( when_rules=when_rules, schema=get_schema(), metadata={}, answer_store=answer_store, list_store=list_store, current_location=current_location, ))
def _is_section_enabled(self, section: Mapping) -> bool: if "enabled" not in section: return True enabled = section["enabled"] if isinstance(enabled, dict): when_rule_evaluator = RuleEvaluator( self._schema, self._answer_store, self._list_store, self._metadata, self._response_metadata, location=None, routing_path_block_ids=None, ) return bool(when_rule_evaluator.evaluate(enabled["when"])) return any( evaluate_when_rules( condition["when"], self._schema, self._metadata, self._answer_store, self._list_store, ) for condition in enabled)
def test_primary_person_checks_location(self): answer_store = AnswerStore() list_store = ListStore(existing_items=[{ "name": "people", "primary_person": "abcdef", "items": ["abcdef", "12345"], }]) current_location = RelationshipLocation( section_id="some-section", block_id="some-block", list_item_id="abcdef", to_list_item_id="12345", list_name="household", ) when_rules = [{ "list": "people", "id_selector": "primary_person", "condition": "equals", "comparison": { "source": "location", "id": "list_item_id" }, }] self.assertTrue( evaluate_when_rules( when_rules=when_rules, schema=get_schema(), metadata={}, answer_store=answer_store, list_store=list_store, current_location=current_location, ))
def test_routing_ignores_answers_not_on_path(self): when = { "when": [{ "id": "some-answer", "condition": "equals", "value": "some value" }] } answer_store = AnswerStore() answer_store.add_or_update( Answer(answer_id="some-answer", value="some value")) routing_path = [ Location(section_id="some-section", block_id="test_block_id") ] current_location = Location(section_id="some-section", block_id="some-block") self.assertTrue( evaluate_when_rules( when_rules=when["when"], schema=get_schema(), metadata={}, answer_store=answer_store, list_store=ListStore(), current_location=current_location, )) current_location = Location(section_id="some-section", block_id="some-block") with patch("app.questionnaire.when_rules._is_answer_on_path", return_value=False): self.assertFalse( evaluate_when_rules( when_rules=when["when"], schema=get_schema(), metadata={}, answer_store=answer_store, list_store=ListStore(), current_location=current_location, routing_path_block_ids=routing_path, ))
def test_evaluate_not_set_when_rules_should_return_true(self): when = {"when": [{"id": "my_answers", "condition": "not set"}]} answer_store = AnswerStore() current_location = Location(section_id="some-section", block_id="some-block") self.assertTrue( evaluate_when_rules( when_rules=when["when"], schema=get_schema(), metadata={}, answer_store=answer_store, list_store=ListStore(), current_location=current_location, ))
def test_routing_answer_not_on_path_when_in_a_repeat(self): when = { "when": [{ "id": "some-answer", "condition": "equals", "value": "some value" }] } answer_store = AnswerStore() answer = Answer(answer_id="some-answer", value="some value") answer_store.add_or_update(answer) routing_path = [ Location( section_id="some-section", block_id="test_block_id", list_name="people", list_item_id="abc123", ) ] current_location = Location( section_id="some-section", block_id="some-block", list_name="people", list_item_id="abc123", ) with patch("app.questionnaire.when_rules.get_answer_for_answer_id", return_value=answer): with patch("app.questionnaire.when_rules._is_answer_on_path", return_value=False): self.assertFalse( evaluate_when_rules( when_rules=when["when"], schema=get_schema(), metadata={}, answer_store=answer_store, list_store=ListStore(), current_location=current_location, routing_path_block_ids=routing_path, ))
def test_list_rules_equals(self): answer_store = AnswerStore() list_store = ListStore(existing_items=[{ "name": "people", "items": ["abcdef"] }]) when_rules = [{"list": "people", "condition": "equals", "value": 1}] current_location = Location(section_id="some-section", block_id="some-block") self.assertTrue( evaluate_when_rules( when_rules=when_rules, schema=get_schema(), metadata={}, answer_store=answer_store, list_store=list_store, current_location=current_location, ))
def choose_variant( block, schema, metadata, response_metadata, answer_store, list_store, variants_key, single_key, current_location, ): if block.get(single_key): return block[single_key] for variant in block.get(variants_key, []): when_rules = variant.get("when", []) if isinstance(when_rules, dict): when_rule_evaluator = RuleEvaluator( schema, answer_store, list_store, metadata, response_metadata, location=current_location, ) if when_rule_evaluator.evaluate(when_rules): return variant[single_key] elif evaluate_when_rules( when_rules, schema, metadata, answer_store, list_store, current_location=current_location, ): return variant[single_key]
def test_when_rule_comparing_answer_values(self): answers = { "low": Answer(answer_id="low", value=1), "medium": Answer(answer_id="medium", value=5), "high": Answer(answer_id="high", value=10), "list_answer": Answer(answer_id="list_answer", value=["a", "abc", "cba"]), "other_list_answer": Answer(answer_id="other_list_answer", value=["x", "y", "z"]), "other_list_answer_2": Answer(answer_id="other_list_answer_2", value=["a", "abc", "cba"]), "text_answer": Answer(answer_id="small_string", value="abc"), "other_text_answer": Answer(answer_id="other_string", value="xyz"), } # An answer that won't be added to the answer store. missing_answer = Answer(answer_id="missing", value=1) param_list = [ (answers["medium"], "equals", answers["medium"], True), (answers["medium"], "equals", answers["low"], False), (answers["medium"], "greater than", answers["low"], True), (answers["medium"], "greater than", answers["high"], False), (answers["medium"], "less than", answers["high"], True), (answers["medium"], "less than", answers["low"], False), (answers["medium"], "equals", missing_answer, False), (answers["list_answer"], "contains", answers["text_answer"], True), (answers["list_answer"], "contains", answers["other_text_answer"], False), ( answers["list_answer"], "not contains", answers["other_text_answer"], True, ), (answers["list_answer"], "not contains", answers["text_answer"], False), ( answers["list_answer"], "contains any", answers["other_list_answer_2"], True, ), ( answers["list_answer"], "contains any", answers["other_list_answer"], False, ), ( answers["list_answer"], "contains all", answers["other_list_answer"], False, ), ( answers["list_answer"], "contains all", answers["other_list_answer_2"], True, ), (answers["text_answer"], "equals any", answers["list_answer"], True), (answers["text_answer"], "equals any", answers["other_list_answer"], False), ( answers["text_answer"], "not equals any", answers["other_list_answer"], True, ), (answers["text_answer"], "not equals any", answers["list_answer"], False), ] for lhs, comparison, rhs, expected_result in param_list: # Given with self.subTest(lhs=lhs, comparison=comparison, rhs=rhs, expected_result=expected_result): answer_store = AnswerStore() for answer in answers.values(): answer_store.add_or_update(answer) when = [{ "id": lhs.answer_id, "condition": comparison, "comparison": { "id": rhs.answer_id, "source": "answers" }, }] current_location = Location(section_id="some-section", block_id="some-block") self.assertEqual( evaluate_when_rules( when_rules=when, schema=get_schema(), metadata={}, answer_store=answer_store, list_store=ListStore(), current_location=current_location, routing_path_block_ids=None, ), expected_result, )
def test_evaluate_when_rule_raises_if_bad_when_condition(self): when = {"when": [{"condition": "not set"}]} answer_store = AnswerStore() with self.assertRaises(Exception): evaluate_when_rules(when["when"], get_schema(), {}, answer_store, ListStore(), None)