Esempio n. 1
0
def test_answer_source_count(rule, expected_result):
    rule_evaluator = get_rule_evaluator(answer_store=AnswerStore([{
        "answer_id":
        "some-answer",
        "value": ["array element 1", "array element 2"],
    }]), )
    assert rule_evaluator.evaluate(rule=rule) is expected_result
Esempio n. 2
0
def test_answer_source_not_on_path_non_repeating_section(is_answer_on_path):
    schema = get_mock_schema()

    location = Location(section_id="test-section", block_id="test-block")

    if is_answer_on_path:
        schema.get_block_for_answer_id = Mock(
            return_value={"id": "block-on-path"})
        answer_id = "answer-on-path"
        expected_result = True
    else:
        schema.get_block_for_answer_id = Mock(
            return_value={"id": "block-not-on-path"})
        answer_id = "answer-not-on-path"
        expected_result = False

    answer = Answer(answer_id=answer_id, value="Yes")

    rule_evaluator = get_rule_evaluator(
        schema=schema,
        answer_store=AnswerStore([answer.to_dict()]),
        location=location,
        routing_path_block_ids=["block-on-path"],
    )

    assert (rule_evaluator.evaluate(
        rule={
            Operator.EQUAL: [
                "Yes",
                {
                    "source": "answers",
                    "identifier": "answer-on-path"
                },
            ]
        }) == expected_result)
Esempio n. 3
0
def get_rule_evaluator(
    *,
    language="en",
    schema: QuestionnaireSchema = None,
    answer_store: AnswerStore = AnswerStore(),
    list_store: ListStore = ListStore(),
    metadata: Optional[dict] = None,
    response_metadata: Mapping = None,
    location: Union[Location,
                    RelationshipLocation] = Location(section_id="test-section",
                                                     block_id="test-block"),
    routing_path_block_ids: Optional[list] = None,
):
    if not schema:
        schema = get_mock_schema()
        schema.is_repeating_answer = Mock(return_value=True)
        schema.get_default_answer = Mock(return_value=None)

    return RuleEvaluator(
        language=language,
        schema=schema,
        metadata=metadata or {},
        response_metadata=response_metadata,
        answer_store=answer_store,
        list_store=list_store,
        location=location,
        routing_path_block_ids=routing_path_block_ids,
    )
def _get_checkbox_answer_data(answer_store: AnswerStore,
                              answer_schema: Mapping,
                              value: ListAnswer) -> dict[str, str]:
    qcodes_and_values = []
    for user_answer in value:
        # find the option in the schema which matches the users answer
        option = next(
            (option for option in answer_schema["options"]
             if option["value"] == user_answer),
            None,
        )

        if option:
            if "detail_answer" in option:
                detail_answer = answer_store.get_answer(
                    option["detail_answer"]["id"])
                # if the user has selected an option with a detail answer we need to find the detail answer value it refers to.
                # the detail answer value can be empty, in this case we just use the main value (e.g. other)
                user_answer = detail_answer.value or user_answer  # type: ignore

            qcodes_and_values.append((option.get("q_code"), user_answer))

    checkbox_answer_data: dict[str, str] = OrderedDict()

    if all(q_code is not None for (q_code, _) in qcodes_and_values):
        checkbox_answer_data.update(qcodes_and_values)
    else:
        checkbox_answer_data[answer_schema["q_code"]] = str(
            [v for (_, v) in qcodes_and_values])

    return checkbox_answer_data
Esempio n. 5
0
def test_nested_rules(operator, operands, expected_result):
    rule_evaluator = get_rule_evaluator(
        answer_store=AnswerStore([
            {
                "answer_id": "answer-1",
                "list_item_id": "item-1",
                "value": "Yes, I do",
            },
            {
                "answer_id": "answer-2",
                "list_item_id": "item-1",
                "value": 10,
            },
        ]),
        metadata={
            "region_code": "GB-NIR",
            "language_code": "en"
        },
        list_store=ListStore([{
            "name": "some-list",
            "items": get_list_items(5),
            "same_name_items": get_list_items(3),
        }], ),
        location=Location(section_id="some-section",
                          block_id="some-block",
                          list_item_id="item-1"),
    )

    assert rule_evaluator.evaluate(
        rule={operator: operands}) is expected_result
Esempio n. 6
0
def test_answer_source_with_list_item_selector_list_first_item(
        answer_value, expected_result):
    rule_evaluator = get_rule_evaluator(
        answer_store=AnswerStore([{
            "answer_id": "some-answer",
            "list_item_id": "item-1",
            "value": answer_value,
        }]),
        list_store=ListStore([{
            "name": "some-list",
            "items": get_list_items(3)
        }]),
    )

    assert (rule_evaluator.evaluate(
        rule={
            Operator.EQUAL: [
                {
                    "source": "answers",
                    "identifier": "some-answer",
                    "list_item_selector": {
                        "source": "list",
                        "identifier": "some-list",
                        "selector": "first",
                    },
                },
                3,
            ]
        }) is expected_result)
def test_answer_source_with_routing_path_block_ids_outside_repeat(
        is_answer_on_path):
    schema = get_mock_schema()

    location = Location(section_id="test-section", block_id="test-block")

    if is_answer_on_path:
        schema.get_block_for_answer_id = Mock(
            return_value={"id": f"block-on-path"})
        answer_id = "answer-on-path"
        expected_result = "Yes"
    else:
        schema.get_block_for_answer_id = Mock(
            return_value={"id": f"block-not-on-path"})
        answer_id = "answer-not-on-path"
        expected_result = None

    answer = Answer(answer_id=answer_id, value="Yes")

    value_source_resolver = get_value_source_resolver(
        schema=schema,
        answer_store=AnswerStore([answer.to_dict()]),
        list_store=ListStore([{
            "name": "some-list",
            "items": get_list_items(3)
        }]),
        location=location,
        list_item_id=location.list_item_id,
        routing_path_block_ids=["block-on-path"],
    )

    assert (value_source_resolver.resolve({
        "source": "answers",
        "identifier": "answer-on-path"
    }) == expected_result)
def get_value_source_resolver(
    schema: QuestionnaireSchema = None,
    answer_store: AnswerStore = AnswerStore(),
    list_store: ListStore = ListStore(),
    metadata: Optional[dict] = None,
    location: Union[Location,
                    RelationshipLocation] = Location(section_id="test-section",
                                                     block_id="test-block"),
    list_item_id: Optional[str] = None,
    routing_path_block_ids: Optional[list] = None,
    use_default_answer=False,
    escape_answer_values=False,
):
    if not schema:
        schema = get_mock_schema()
        schema.is_repeating_answer = Mock(return_value=bool(list_item_id))

    if not use_default_answer:
        schema.get_default_answer = Mock(return_value=None)

    return ValueSourceResolver(
        answer_store=answer_store,
        list_store=list_store,
        metadata=metadata,
        schema=schema,
        location=location,
        list_item_id=list_item_id,
        routing_path_block_ids=routing_path_block_ids,
        use_default_answer=use_default_answer,
        escape_answer_values=escape_answer_values,
    )
Esempio n. 9
0
def test_answer_source_with_list_item_selector_location(
        answer_value, expected_result):
    rule_evaluator = get_rule_evaluator(
        answer_store=AnswerStore([{
            "answer_id": "some-answer",
            "list_item_id": "item-1",
            "value": answer_value,
        }]),
        location=Location(section_id="some-section",
                          block_id="some-block",
                          list_item_id="item-1"),
    )

    assert (rule_evaluator.evaluate(rule={
        Operator.EQUAL: [
            {
                "source": "answers",
                "identifier": "some-answer",
                "list_item_selector": {
                    "source": "location",
                    "identifier": "list_item_id",
                },
            },
            3,
        ]
    }, ) is expected_result)
Esempio n. 10
0
def test_map_with_nested_date_operator(offset, expected_result):
    rule = {
        Operator.MAP: [
            {
                Operator.FORMAT_DATE: [
                    {
                        Operator.DATE: [
                            "self",
                            offset,
                        ]
                    },
                    "d MMMM yyyy",
                ]
            },
            {
                "source": "answers",
                "identifier": "checkbox-answer"
            },
        ]
    }

    rule_evaluator = get_rule_evaluator(answer_store=AnswerStore([{
        "answer_id":
        "checkbox-answer",
        "value": ["2021-01-01", "2021-01-02", "2021-01-03"],
    }]))

    assert rule_evaluator.evaluate(rule=rule) == expected_result
Esempio n. 11
0
def test_format_date(rule, expected_result):
    rule_evaluator = get_rule_evaluator(answer_store=AnswerStore([{
        "answer_id":
        "some-answer",
        "value":
        "2021-01-01",
    }]), )
    assert rule_evaluator.evaluate(rule=rule) == expected_result
Esempio n. 12
0
def test_date_value(rule, expected_result):
    rule_evaluator = get_rule_evaluator(
        answer_store=AnswerStore([{
            "answer_id": "some-answer",
            "value": current_date_as_yyyy_mm_dd,
        }]),
        metadata={"some-metadata": current_date_as_yyyy_mm_dd},
    )

    assert (rule_evaluator.evaluate(rule=rule, ) is expected_result)
def test_answer_source():
    value_source_resolver = get_value_source_resolver(answer_store=AnswerStore(
        [{
            "answer_id": "some-answer",
            "value": "Yes"
        }]), )

    assert (value_source_resolver.resolve({
        "source": "answers",
        "identifier": "some-answer"
    }) == "Yes")
Esempio n. 14
0
def rule_evaluator(mock_schema, response_metadata):
    evaluator = RuleEvaluator(
        answer_store=AnswerStore(),
        list_store=ListStore(),
        metadata={},
        response_metadata=response_metadata,
        schema=mock_schema,
        location=None,
    )

    return evaluator
def test_answer_value_can_be_escaped(answer_value, escaped_value):
    value_source_resolver = get_value_source_resolver(
        answer_store=AnswerStore([{
            "answer_id": "some-answer",
            "value": answer_value,
        }]),
        escape_answer_values=True,
    )
    assert (value_source_resolver.resolve({
        "source": "answers",
        "identifier": "some-answer"
    }) == escaped_value)
Esempio n. 16
0
def value_source_resolver(mock_schema, response_metadata):
    resolver = ValueSourceResolver(
        answer_store=AnswerStore(),
        list_store=ListStore(),
        metadata={},
        response_metadata=response_metadata,
        schema=mock_schema,
        location=None,
        list_item_id=None,
        routing_path_block_ids=None,
        use_default_answer=True,
    )

    return resolver
def test_answer_source_with_list_item_id_no_list_item_selector():
    value_source_resolver = get_value_source_resolver(
        answer_store=AnswerStore([{
            "answer_id": "some-answer",
            "list_item_id": "item-1",
            "value": "Yes"
        }]),
        list_item_id="item-1",
    )

    assert (value_source_resolver.resolve({
        "source": "answers",
        "identifier": "some-answer"
    }) == "Yes")
Esempio n. 18
0
def test_answer_source(answer_value, expected_result):
    rule_evaluator = get_rule_evaluator(answer_store=AnswerStore([{
        "answer_id":
        "some-answer",
        "value":
        answer_value
    }]), )

    assert (rule_evaluator.evaluate(
        rule={
            Operator.EQUAL: [{
                "source": "answers",
                "identifier": "some-answer"
            }, 3]
        }) is expected_result)
def test_answer_source_with_dict_answer_selector():
    value_source_resolver = get_value_source_resolver(answer_store=AnswerStore(
        [{
            "answer_id": "some-answer",
            "value": {
                "years": 1,
                "months": 10
            },
        }]), )

    assert (value_source_resolver.resolve({
        "source": "answers",
        "identifier": "some-answer",
        "selector": "years",
    }) == 1)
def test_answer_value_with_selector_can_be_escaped():
    value_source_resolver = get_value_source_resolver(
        answer_store=AnswerStore([{
            "answer_id": "some-answer",
            "value": {
                "key_1": HTML_CONTENT,
                "key_2": 1
            },
        }]),
        escape_answer_values=True,
    )
    assert (value_source_resolver.resolve({
        "source": "answers",
        "identifier": "some-answer",
        "selector": "key_1"
    }) == ESCAPED_CONTENT)
def test_list_item_id_ignored_if_answer_not_in_list_collector_or_repeat():
    schema = get_mock_schema()
    schema.is_repeating_answer = Mock(return_value=False)

    value_source_resolver = get_value_source_resolver(
        schema=schema,
        answer_store=AnswerStore([{
            "answer_id": "some-answer",
            "value": "Yes"
        }]),
        list_item_id="item-1",
    )

    assert (value_source_resolver.resolve({
        "source": "answers",
        "identifier": "some-answer"
    }) == "Yes")
def test_answer_source_with_list_item_selector_location_none():
    value_source_resolver = get_value_source_resolver(
        answer_store=AnswerStore([{
            "answer_id": "some-answer",
            "list_item_id": "item-1",
            "value": "Yes",
        }]),
        location=None,
    )
    with pytest.raises(InvalidLocationException):
        value_source_resolver.resolve({
            "source": "answers",
            "identifier": "some-answer",
            "list_item_selector": {
                "source": "location",
                "id": "list_item_id"
            },
        })
def test_answer_source_with_list_item_selector_location():
    value_source_resolver = get_value_source_resolver(
        answer_store=AnswerStore([{
            "answer_id": "some-answer",
            "list_item_id": "item-1",
            "value": "Yes",
        }]),
        location=Location(section_id="some-section",
                          block_id="some-block",
                          list_item_id="item-1"),
    )

    assert (value_source_resolver.resolve({
        "source": "answers",
        "identifier": "some-answer",
        "list_item_selector": {
            "source": "location",
            "id": "list_item_id"
        },
    }) == "Yes")
Esempio n. 24
0
def test_answer_source_with_dict_answer_selector(answer_value,
                                                 expected_result):
    rule_evaluator = get_rule_evaluator(answer_store=AnswerStore([{
        "answer_id": "some-answer",
        "value": {
            "years": answer_value,
            "months": 10
        },
    }]), )

    assert (rule_evaluator.evaluate(
        rule={
            Operator.EQUAL: [
                {
                    "source": "answers",
                    "identifier": "some-answer",
                    "selector": "years",
                },
                3,
            ]
        }) is expected_result)
def test_answer_source_outside_of_repeating_section():
    schema = get_mock_schema()

    schema.is_repeating_answer = Mock(return_value=False)
    answer_store = AnswerStore([{"answer_id": "some-answer", "value": "Yes"}])

    value_source_resolver = get_value_source_resolver(
        schema=schema,
        answer_store=answer_store,
        list_store=ListStore([{
            "name": "some-list",
            "items": get_list_items(3)
        }]),
        location=Location(section_id="some-section",
                          block_id="some-block",
                          list_item_id="item-1"),
    )

    assert (value_source_resolver.resolve({
        "source": "answers",
        "identifier": "some-answer"
    }) == "Yes")
def test_answer_source_with_list_item_selector_list_first_item():
    value_source_resolver = get_value_source_resolver(
        answer_store=AnswerStore([{
            "answer_id": "some-answer",
            "list_item_id": "item-1",
            "value": "Yes",
        }]),
        list_store=ListStore([{
            "name": "some-list",
            "items": get_list_items(3)
        }]),
    )

    assert (value_source_resolver.resolve({
        "source": "answers",
        "identifier": "some-answer",
        "list_item_selector": {
            "source": "list",
            "id": "some-list",
            "id_selector": "first",
        },
    }) == "Yes")
Esempio n. 27
0
def test_answer_source_default_answer_used_when_no_answer(
        comparison_value, expected_result):
    schema = get_mock_schema()
    schema.get_default_answer = Mock(
        return_value=Answer(answer_id="answer-that-does-not-exist", value=3))

    rule_evaluator = get_rule_evaluator(
        schema=schema,
        answer_store=AnswerStore([{
            "answer_id": "some-answer",
            "value": "No"
        }]),
    )

    assert (rule_evaluator.evaluate(
        rule={
            Operator.EQUAL: [
                {
                    "source": "answers",
                    "identifier": "answer-that-does-not-exist"
                },
                comparison_value,
            ]
        }) is expected_result)
Esempio n. 28
0
def test_answer_source_outside_of_repeating_section():
    schema = get_mock_schema()

    schema.is_repeating_answer = Mock(return_value=False)
    answer_store = AnswerStore([{"answer_id": "some-answer", "value": "Yes"}])

    rule_evaluator = get_rule_evaluator(
        schema=schema,
        answer_store=answer_store,
        location=Location(section_id="some-section",
                          block_id="some-block",
                          list_item_id="item-1"),
    )

    assert (rule_evaluator.evaluate(
        rule={
            Operator.EQUAL: [
                {
                    "source": "answers",
                    "identifier": "some-answer"
                },
                "Yes",
            ]
        }) is True)
def convert_answers_to_payload_0_0_1(
    metadata: MetadataType,
    response_metadata: MetadataType,
    answer_store: AnswerStore,
    list_store: ListStore,
    schema: QuestionnaireSchema,
    full_routing_path: RoutingPath,
) -> OrderedDict[str, Any]:
    """
    Convert answers into the data format below
    list_item_id bound answers are not currently supported
    'data': {
          '001': '01-01-2016',
          '002': '30-03-2016'
        }
    :param metadata: questionnaire metadata
    :param response_metadata: response metadata
    :param answer_store: questionnaire answers
    :param list_store: list store
    :param schema: QuestionnaireSchema class with populated schema json
    :param full_routing_path: a list of section routing paths followed in the questionnaire
    :return: data in a formatted form
    """
    data = OrderedDict()
    for routing_path in full_routing_path:
        for block_id in routing_path:
            answer_ids = schema.get_answer_ids_for_block(block_id)
            answers_in_block = answer_store.get_answers_by_answer_id(
                answer_ids, routing_path.list_item_id)

            for answer_in_block in answers_in_block:
                answer_schema = None

                block = schema.get_block_for_answer_id(
                    answer_in_block.answer_id)
                current_location = Location(
                    block_id=block_id,
                    section_id=routing_path.section_id,
                    list_item_id=routing_path.list_item_id,
                )
                question = choose_question_to_display(
                    block,
                    schema,
                    metadata,
                    response_metadata,
                    answer_store,
                    list_store,
                    current_location=current_location,
                )
                for answer in question["answers"]:
                    if answer["id"] == answer_in_block.answer_id:
                        answer_schema = answer

                value = answer_in_block.value

                if answer_schema is not None and value is not None:
                    if answer_schema["type"] == "Checkbox":
                        data.update(
                            _get_checkbox_answer_data(
                                answer_store,
                                answer_schema,
                                value  # type: ignore
                            ))
                    elif "q_code" in answer_schema:
                        answer_data = _encode_value(value)
                        if answer_data is not None:
                            data[answer_schema[
                                "q_code"]] = _format_downstream_answer(
                                    answer_schema["type"],
                                    answer_in_block.value,
                                    answer_data,
                                )

    return data