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,
            ))
Exemple #10
0
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)