Ejemplo n.º 1
0
    def __init__(self,
                 storage: EncryptedQuestionnaireStorage,
                 version: Optional[int] = None):
        self._storage = storage
        if version is None:
            version = self.get_latest_version_number()
        self.version = version
        self._metadata: dict[str, Any] = {}
        # self.metadata is a read-only view over self._metadata
        self.metadata: Mapping[str, Any] = MappingProxyType(self._metadata)
        self.response_metadata: Mapping[str, Any] = {}
        self.list_store = ListStore()
        self.answer_store = AnswerStore()
        self.progress_store = ProgressStore()
        self.submitted_at: Optional[datetime]
        self.collection_exercise_sid: Optional[str]

        (
            raw_data,
            self.collection_exercise_sid,
            version,
            self.submitted_at,
        ) = self._storage.get_user_data()

        if raw_data:
            self._deserialize(raw_data)
        if version is not None:
            self.version = version
Ejemplo n.º 2
0
def test_list_source_count_in_transform():
    placeholder_list = [{
        "placeholder":
        "number_of_people",
        "transforms": [{
            "transform": "add",
            "arguments": {
                "lhs": {
                    "source": "list",
                    "identifier": "people"
                },
                "rhs": {
                    "value": 1
                },
            },
        }],
    }]

    list_store = ListStore()
    list_store.add_list_item("people")

    parser = PlaceholderParser(language="en", list_store=list_store)
    placeholders = parser(placeholder_list)

    assert placeholders["number_of_people"] == 2
Ejemplo n.º 3
0
def test_choose_content_to_display(content_variant_schema):
    schema = QuestionnaireSchema(content_variant_schema)
    answer_store = AnswerStore({})
    answer_store.add_or_update(Answer(answer_id="age-answer", value="18"))
    metadata = {}

    block = schema.get_block("block1")
    section_id = schema.get_section_id_for_block_id(block["id"])

    content_to_display = choose_content_to_display(
        schema.get_block("block1"),
        schema,
        metadata,
        answer_store,
        ListStore({}),
        Location(section_id=section_id, block_id=block["id"]),
    )

    assert content_to_display[0]["title"] == "You are over 16"

    answer_store = AnswerStore({})

    content_to_display = choose_content_to_display(
        schema.get_block("block1"),
        schema,
        metadata,
        answer_store,
        ListStore({}),
        Location(section_id=section_id, block_id=block["id"]),
    )

    assert content_to_display[0]["title"] == "You are ageless"
Ejemplo n.º 4
0
def test_choose_question_to_display(question_variant_schema):
    schema = QuestionnaireSchema(question_variant_schema)
    answer_store = AnswerStore({})
    answer_store.add_or_update(Answer(answer_id="when-answer", value="yes"))
    metadata = {}

    block = schema.get_block("block1")
    section_id = schema.get_section_id_for_block_id(block["id"])

    question_to_display = choose_question_to_display(
        schema.get_block("block1"),
        schema,
        metadata,
        answer_store,
        ListStore({}),
        Location(section_id=section_id, block_id=block["id"]),
    )

    assert question_to_display["title"] == "Question 1, Yes"

    answer_store = AnswerStore({})

    question_to_display = choose_question_to_display(
        schema.get_block("block1"),
        schema,
        metadata,
        answer_store,
        ListStore({}),
        Location(section_id=section_id, block_id=block["id"]),
    )

    assert question_to_display["title"] == "Question 1, No"
Ejemplo n.º 5
0
def test_list_source_count_in_transform(mock_renderer):
    placeholder_list = [
        {
            "placeholder": "number_of_people",
            "transforms": [
                {
                    "transform": "add",
                    "arguments": {
                        "lhs": {
                            "source": "list",
                            "identifier": "people",
                            "selector": "count",
                        },
                        "rhs": {"value": 1},
                    },
                }
            ],
        }
    ]

    list_store = ListStore()
    list_store.add_list_item("people")

    parser = PlaceholderParser(
        language="en",
        answer_store=AnswerStore(),
        list_store=list_store,
        metadata={},
        response_metadata={},
        schema=QuestionnaireSchema({}),
        renderer=mock_renderer,
    )
    placeholders = parser(placeholder_list)

    assert placeholders["number_of_people"] == 2
Ejemplo n.º 6
0
def test_transform_variants_with_question_variants(question_variant_schema):
    schema = QuestionnaireSchema(question_variant_schema)
    answer_store = AnswerStore({})
    answer_store.add_or_update(Answer(answer_id="when-answer", value="no"))
    metadata = {}

    block = schema.get_block("block1")
    section_id = schema.get_section_id_for_block_id(block["id"])

    transformed_block = transform_variants(
        block,
        schema,
        metadata,
        answer_store,
        ListStore({}),
        Location(section_id=section_id, block_id=block["id"]),
    )

    compare_transformed_block(block, transformed_block, "Question 1, No")

    answer_store.add_or_update(Answer(answer_id="when-answer", value="yes"))

    transformed_block = transform_variants(
        block,
        schema,
        metadata,
        answer_store,
        ListStore({}),
        Location(section_id=section_id, block_id=block["id"]),
    )

    compare_transformed_block(block, transformed_block, "Question 1, Yes")
def test_titles_for_repeating_section_summary(people_answer_store):
    schema = load_schema_from_name(
        "test_repeating_sections_with_hub_and_spoke")

    section_summary_context = SectionSummaryContext(
        DEFAULT_LANGUAGE_CODE,
        schema,
        people_answer_store,
        ListStore([
            {
                "items": ["PlwgoG", "UHPLbX"],
                "name": "people"
            },
            {
                "items": ["gTrlio"],
                "name": "visitors"
            },
        ]),
        ProgressStore(),
        {},
        current_location=Location(
            section_id="personal-details-section",
            list_name="people",
            list_item_id="PlwgoG",
        ),
        routing_path=MagicMock(),
    )

    context = section_summary_context()

    assert context["summary"]["title"] == "Toni Morrison"

    section_summary_context = SectionSummaryContext(
        DEFAULT_LANGUAGE_CODE,
        schema,
        people_answer_store,
        ListStore([
            {
                "items": ["PlwgoG", "UHPLbX"],
                "name": "people"
            },
            {
                "items": ["gTrlio"],
                "name": "visitors"
            },
        ]),
        ProgressStore(),
        {},
        current_location=Location(
            block_id="personal-summary",
            section_id="personal-details-section",
            list_name="people",
            list_item_id="UHPLbX",
        ),
        routing_path=MagicMock(),
    )

    context = section_summary_context()
    assert context["summary"]["title"] == "Barry Pheloung"
def test_transform_variants_list_collector(list_collector_variant_schema):
    schema = QuestionnaireSchema(list_collector_variant_schema)
    answer_store = AnswerStore({})
    answer_store.add_or_update(Answer(answer_id="when-answer", value="no"))
    metadata = {}
    response_metadata = {}

    block = schema.get_block("block1")
    section_id = schema.get_section_id_for_block_id(block["id"])

    transformed_block = transform_variants(
        block,
        schema,
        metadata,
        response_metadata,
        answer_store,
        ListStore({}),
        Location(section_id=section_id, block_id=block["id"]),
    )

    compare_transformed_block(
        block["add_block"], transformed_block["add_block"], "Add, No"
    )
    compare_transformed_block(
        block["remove_block"], transformed_block["remove_block"], "Remove, No"
    )
    compare_transformed_block(
        block["edit_block"], transformed_block["edit_block"], "Edit, No"
    )

    answer_store.add_or_update(Answer(answer_id="when-answer", value="yes"))

    transformed_block = transform_variants(
        block,
        schema,
        metadata,
        response_metadata,
        answer_store,
        ListStore({}),
        Location(section_id=section_id, block_id=block["id"]),
    )

    compare_transformed_block(
        block["add_block"], transformed_block["add_block"], "Add, Yes"
    )
    compare_transformed_block(
        block["remove_block"], transformed_block["remove_block"], "Remove, Yes"
    )
    compare_transformed_block(
        block["edit_block"], transformed_block["edit_block"], "Edit, Yes"
    )
def test_unique_id_generation():
    """
    Ensure that every id generated is unique per questionnaire.
    """
    # Mock the app.data_models.list_store.random_string method to return duplicates.
    with patch(
        "app.data_models.list_store.random_string",
        side_effect=["first", "first", "second"],
    ):
        store = ListStore()
        # pylint: disable=protected-access
        store._lists["test"] = ListModel(name="test", items=["first"])
        result = store._generate_identifier()

    assert result == "second"
def test_renders_text_plural_from_list():
    renderer = PlaceholderRenderer(language="en",
                                   list_store=ListStore(),
                                   schema=Mock())

    rendered_text = renderer.render_placeholder(
        {
            "text_plural": {
                "forms": {
                    "one": "Yes, {number_of_people} person lives here",
                    "other": "Yes, {number_of_people} people live here",
                },
                "count": {
                    "source": "list",
                    "identifier": "household"
                },
            },
            "placeholders": [{
                "placeholder": "number_of_people",
                "value": {
                    "source": "list",
                    "identifier": "household"
                },
            }],
        },
        None,
    )

    assert rendered_text == "Yes, 0 people live here"
Ejemplo n.º 11
0
def test_primary_person_not_in_payload_when_not_answered(fake_questionnaire_store):
    routing_path = [
        RoutingPath(
            ["list-collector", "next-interstitial", "another-list-collector-block"],
            section_id="section-1",
        )
    ]

    answer_objects = [
        {"answer_id": "first-name", "value": "1", "list_item_id": "xJlKBy"},
        {"answer_id": "last-name", "value": "1", "list_item_id": "xJlKBy"},
        {"answer_id": "first-name", "value": "2", "list_item_id": "RfAGDc"},
        {"answer_id": "last-name", "value": "2", "list_item_id": "RfAGDc"},
        {"answer_id": "anyone-else", "value": "No"},
        {"answer_id": "another-anyone-else", "value": "No"},
        {"answer_id": "extraneous-answer", "value": "Bad", "list_item_id": "123"},
    ]

    answers = AnswerStore(answer_objects)

    list_store = ListStore(
        existing_items=[{"name": "people", "items": ["xJlKBy", "RfAGDc"]}]
    )

    fake_questionnaire_store.answer_store = answers
    fake_questionnaire_store.list_store = list_store

    schema = load_schema_from_name("test_list_collector")

    output = convert_answers(schema, fake_questionnaire_store, routing_path)

    data_dict = json_loads(json_dumps(output["data"]["lists"]))

    assert "primary_person" not in data_dict[0]
Ejemplo n.º 12
0
 def _deserialize(self, data: str) -> None:
     json_data = json_loads(data)
     self.progress_store = ProgressStore(json_data.get("PROGRESS"))
     self.set_metadata(json_data.get("METADATA", {}))
     self.answer_store = AnswerStore(json_data.get("ANSWERS"))
     self.list_store = ListStore.deserialize(json_data.get("LISTS"))
     self.response_metadata = json_data.get("RESPONSE_METADATA", {})
    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_placeholder_resolves_same_name_items():
    list_store = ListStore(
        [
            {
                "items": ["abc123", "cde456", "fgh789"],
                "same_name_items": ["abc123", "fgh789"],
                "name": "people",
            }
        ]
    )
    placeholder_list = [
        {
            "placeholder": "answer",
            "value": {
                "source": "list",
                "id_selector": "same_name_items",
                "identifier": "people",
            },
        },
    ]

    parser = PlaceholderParser(
        language="en",
        list_store=list_store,
        list_item_id="abc123",
    )

    placeholders = parser(placeholder_list)

    assert placeholders["answer"] == ["abc123", "fgh789"]
Ejemplo n.º 15
0
def test_multiple_metadata_list_transform_placeholder(mock_renderer):
    placeholder_list = [
        {
            "placeholder": "dates",
            "transforms": [
                {
                    "transform": "concatenate_list",
                    "arguments": {
                        "list_to_concatenate": [
                            {"source": "metadata", "identifier": "ref_p_start_date"},
                            {"source": "metadata", "identifier": "ref_p_end_date"},
                        ],
                        "delimiter": " ",
                    },
                }
            ],
        }
    ]

    parser = PlaceholderParser(
        language="en",
        answer_store=AnswerStore(),
        list_store=ListStore(),
        metadata={"ref_p_start_date": "2019-02-11", "ref_p_end_date": "2019-10-11"},
        response_metadata={},
        schema=QuestionnaireSchema({}),
        renderer=mock_renderer,
    )
    placeholders = parser(placeholder_list)

    assert placeholders["dates"] == "2019-02-11 2019-10-11"
    def test_meta_comparison_missing(self):
        # Given
        goto_rule = {
            "id":
            "next-question",
            "when": [{
                "condition": "equals",
                "meta": "variant_flags.does_not_exist.does_not_exist",
                "value": True,
            }],
        }
        answer_store = AnswerStore()
        answer_store.add_or_update(Answer(answer_id="my_answer", value="Yes"))
        metadata = {"varient_flags": {"sexual_identity": True}}

        current_location = Location(section_id="some-section",
                                    block_id="some-block")

        self.assertFalse(
            evaluate_goto(
                goto_rule=goto_rule,
                schema=get_schema(),
                metadata=metadata,
                answer_store=answer_store,
                list_store=ListStore(),
                current_location=current_location,
            ))
Ejemplo n.º 17
0
def test_placeholder_default_value(default_placeholder_value_schema, mock_renderer):
    placeholder_list = [
        {
            "placeholder": "answer_employee",
            "transforms": [
                {
                    "transform": "format_number",
                    "arguments": {
                        "number": {"source": "answers", "identifier": "employees-no"}
                    },
                }
            ],
        }
    ]
    parser = PlaceholderParser(
        language="en",
        answer_store=AnswerStore(),
        list_store=ListStore(),
        metadata={},
        response_metadata={},
        schema=default_placeholder_value_schema,
        renderer=mock_renderer,
    )

    placeholders = parser(placeholder_list)
    assert placeholders["answer_employee"] == "0"
Ejemplo n.º 18
0
    def test_do_not_go_to_next_question_for_date_answer(self):

        goto_rule = {
            "id":
            "next-question",
            "when": [{
                "id": "date-answer",
                "condition": "equals",
                "date_comparison": {
                    "value": "2018-01"
                },
            }],
        }

        answer_store = AnswerStore({})
        answer_store.add_or_update(
            Answer(answer_id="date-answer", value="2018-02-01"))

        current_location = Location(section_id="some-section",
                                    block_id="some-block")

        self.assertFalse(
            evaluate_goto(
                goto_rule=goto_rule,
                schema=get_schema_mock(),
                metadata={},
                answer_store=answer_store,
                list_store=ListStore(),
                current_location=current_location,
            ))
Ejemplo n.º 19
0
 def setUp(self):
     super().setUp()
     self.schema = load_schema_from_name("test_section_summary")
     self.answer_store = AnswerStore()
     self.list_store = ListStore()
     self.progress_store = ProgressStore()
     self.block_type = "SectionSummary"
Ejemplo n.º 20
0
def test_placeholder_resolves_list_item_value_based_on_first_item_in_list(
    mock_renderer,
):
    placeholder_list = [
        {
            "placeholder": "first_person_list_item_id",
            "value": {
                "source": "list",
                "selector": "first",
                "identifier": "people",
            },
        }
    ]

    list_store = ListStore([{"items": ["item-1", "item-2"], "name": "people"}])

    parser = PlaceholderParser(
        language="en",
        answer_store=AnswerStore(),
        list_store=list_store,
        metadata={},
        response_metadata={},
        schema=QuestionnaireSchema({}),
        renderer=mock_renderer,
    )

    placeholders = parser(placeholder_list)

    assert str(placeholders["first_person_list_item_id"]) == list_store["people"].first
Ejemplo n.º 21
0
def test_first_non_empty_item_transform_placeholder(mock_renderer):
    placeholder_list = [
        {
            "placeholder": "company_name",
            "transforms": [
                {
                    "transform": "first_non_empty_item",
                    "arguments": {
                        "items": [
                            {"source": "metadata", "identifier": "trad_as"},
                            {"source": "metadata", "identifier": "ru_name"},
                        ]
                    },
                }
            ],
        }
    ]

    parser = PlaceholderParser(
        language="en",
        answer_store=AnswerStore(),
        list_store=ListStore(),
        metadata={"ru_name": "ru_name"},
        response_metadata={},
        schema=QuestionnaireSchema({}),
        renderer=mock_renderer,
    )

    placeholders = parser(placeholder_list)

    assert placeholders["company_name"] == "ru_name"
Ejemplo n.º 22
0
def test_mixed_transform_placeholder_value(mock_renderer):
    placeholder_list = [
        {
            "placeholder": "age",
            "transforms": [
                {
                    "transform": "calculate_date_difference",
                    "arguments": {
                        "first_date": {
                            "source": "answers",
                            "identifier": "date-of-birth-answer",
                        },
                        "second_date": {"value": "2019-02-02"},
                    },
                }
            ],
        }
    ]

    parser = PlaceholderParser(
        language="en",
        answer_store=AnswerStore(
            [{"answer_id": "date-of-birth-answer", "value": "1999-01-01"}]
        ),
        list_store=ListStore(),
        metadata={},
        response_metadata={},
        schema=QuestionnaireSchema({}),
        renderer=mock_renderer,
    )
    placeholders = parser(placeholder_list)

    assert placeholders["age"] == "20 years"
Ejemplo n.º 23
0
def test_checkbox_transform_placeholder(mock_renderer):
    placeholder_list = [
        {
            "placeholder": "toppings",
            "transforms": [
                {
                    "transform": "concatenate_list",
                    "arguments": {
                        "list_to_concatenate": [
                            {"source": "answers", "identifier": "checkbox-answer"}
                        ],
                        "delimiter": ", ",
                    },
                }
            ],
        }
    ]

    parser = PlaceholderParser(
        language="en",
        answer_store=AnswerStore(
            [
                {"answer_id": "checkbox-answer", "value": ["Ham", "Cheese"]},
            ]
        ),
        list_store=ListStore(),
        metadata={},
        response_metadata={},
        schema=QuestionnaireSchema({}),
        renderer=mock_renderer,
    )

    placeholders = parser(placeholder_list)

    assert placeholders["toppings"] == "Ham, Cheese"
def test_list_source_count():
    placeholder_list = [
        {
            "placeholder": "number_of_people",
            "value": {"source": "list", "identifier": "people"},
        }
    ]

    list_store = ListStore()
    list_store.add_list_item("people")
    list_store.add_list_item("people")

    parser = PlaceholderParser(language="en", list_store=list_store)
    placeholders = parser(placeholder_list)

    assert placeholders["number_of_people"] == 2
    def test_should_not_go_to_next_question_when_second_condition_fails(self):
        # Given
        goto_rule = {
            "id":
            "next-question",
            "when": [
                {
                    "id": "my_answer",
                    "condition": "equals",
                    "value": "Yes"
                },
                {
                    "condition": "equals",
                    "meta": "sexual_identity",
                    "value": False
                },
            ],
        }
        answer_store = AnswerStore()
        answer_store.add_or_update(Answer(answer_id="my_answer", value="Yes"))
        metadata = {"sexual_identity": True}

        current_location = Location(section_id="some-section",
                                    block_id="some-block")

        self.assertFalse(
            evaluate_goto(
                goto_rule=goto_rule,
                schema=get_schema(),
                metadata=metadata,
                answer_store=answer_store,
                list_store=ListStore(),
                current_location=current_location,
            ))
def test_placeholder_resolves_answer_value_based_on_first_item_in_list():
    placeholder_list = [
        {
            "placeholder": "answer",
            "value": {
                "source": "answers",
                "identifier": "favourite-drink-answer",
                "list_item_selector": {
                    "source": "list",
                    "id": "people",
                    "id_selector": "first",
                },
            },
        }
    ]

    list_store = ListStore([{"items": ["abc123", "123abc"], "name": "people"}])

    answer_store = AnswerStore(
        [
            {
                "answer_id": "favourite-drink-answer",
                "value": "Coffee",
                "list_item_id": "abc123",
            }
        ]
    )

    parser = PlaceholderParser(
        language="en", list_store=list_store, answer_store=answer_store
    )

    placeholders = parser(placeholder_list)
    assert str(placeholders["answer"]) == "Coffee"
Ejemplo n.º 27
0
def test_placeholder_resolves_same_name_items(mock_renderer):
    list_store = ListStore(
        [
            {
                "items": ["abc123", "cde456", "fgh789"],
                "same_name_items": ["abc123", "fgh789"],
                "name": "people",
            }
        ]
    )
    placeholder_list = [
        {
            "placeholder": "answer",
            "value": {
                "source": "list",
                "selector": "same_name_items",
                "identifier": "people",
            },
        },
    ]

    parser = PlaceholderParser(
        language="en",
        answer_store=AnswerStore(),
        list_store=list_store,
        metadata={},
        response_metadata={},
        schema=QuestionnaireSchema({}),
        renderer=mock_renderer,
        list_item_id="abc123",
    )

    placeholders = parser(placeholder_list)

    assert placeholders["answer"] == ["abc123", "fgh789"]
Ejemplo n.º 28
0
def test_format_list_answer_transform_placeholder(mock_renderer):
    placeholder_list = [
        {
            "placeholder": "toppings",
            "transforms": [
                {
                    "transform": "format_list",
                    "arguments": {
                        "list_to_format": {
                            "source": "answers",
                            "identifier": "checkbox-answer",
                        }
                    },
                }
            ],
        }
    ]

    parser = PlaceholderParser(
        language="en",
        answer_store=AnswerStore(
            [{"answer_id": "checkbox-answer", "value": ["Ham", "Cheese"]}]
        ),
        list_store=ListStore(),
        metadata={},
        response_metadata={},
        schema=QuestionnaireSchema({}),
        renderer=mock_renderer,
    )

    placeholders = parser(placeholder_list)

    assert placeholders["toppings"] == "<ul><li>Ham</li><li>Cheese</li></ul>"
def test_list_item_conversion_empty_list(fake_questionnaire_store):
    """Test that the list store is populated with an empty list for lists which
    do not have answers yet."""
    routing_path = [
        RoutingPath(
            ["list-collector", "next-interstitial", "another-list-collector-block"],
            section_id="section-1",
        )
    ]

    answer_objects = [
        {"answer_id": "last-name", "value": "2", "list_item_id": "RfAGDc"},
        {"answer_id": "anyone-else", "value": "No"},
        {"answer_id": "another-anyone-else", "value": "No"},
        {"answer_id": "extraneous-answer", "value": "Bad", "list_item_id": "123"},
    ]

    fake_questionnaire_store.answer_store = AnswerStore(answer_objects)
    fake_questionnaire_store.list_store = ListStore()

    schema = load_schema_from_name("test_list_collector")

    output = convert_answers(
        schema, fake_questionnaire_store, routing_path, SUBMITTED_AT
    )

    # Answers not on the routing path
    del answer_objects[0]
    del answer_objects[-1]

    data_dict = json_loads(json_dumps(output["data"]["answers"]))

    assert sorted(answer_objects, key=lambda x: x["answer_id"]) == sorted(
        data_dict, key=lambda x: x["answer_id"]
    )
Ejemplo n.º 30
0
def test_metadata_transform_placeholder(mock_renderer):
    placeholder_list = [
        {
            "placeholder": "start_date",
            "transforms": [
                {
                    "transform": "format_date",
                    "arguments": {
                        "date_to_format": {
                            "source": "metadata",
                            "identifier": "ref_p_start_date",
                        },
                        "date_format": "EEEE d MMMM yyyy",
                    },
                }
            ],
        }
    ]

    parser = PlaceholderParser(
        language="en",
        answer_store=AnswerStore(),
        list_store=ListStore(),
        metadata={"ref_p_start_date": "2019-02-11"},
        response_metadata={},
        schema=QuestionnaireSchema({}),
        renderer=mock_renderer,
    )
    placeholders = parser(placeholder_list)

    assert placeholders["start_date"] == "Monday 11 February 2019"