Beispiel #1
0
def test_get_length_validator_with_max_length_override():
    answer = {"max_length": 30}

    text_area_handler = TextAreaHandler(
        answer, {"MAX_LENGTH_EXCEEDED": "%(max)d characters"}, AnswerStore(),
        {})
    validator = text_area_handler.get_length_validator()

    assert validator.max == 30
def test_converter_checkboxes_with_q_codes(fake_questionnaire_store):
    routing_path = RoutingPath(["crisps"], section_id="food")
    fake_questionnaire_store.answer_store = AnswerStore(
        [Answer("crisps-answer", ["Ready salted", "Sweet chilli"]).to_dict()])

    question = {
        "id":
        "crisps-question",
        "answers": [{
            "id":
            "crisps-answer",
            "type":
            "Checkbox",
            "options": [
                {
                    "label": "Ready salted",
                    "value": "Ready salted",
                    "q_code": "1"
                },
                {
                    "label": "Sweet chilli",
                    "value": "Sweet chilli",
                    "q_code": "2"
                },
                {
                    "label": "Cheese and onion",
                    "value": "Cheese and onion",
                    "q_code": "3",
                },
                {
                    "label": "Other",
                    "q_code": "4",
                    "description": "Choose any other flavour",
                    "value": "Other",
                    "detail_answer": {
                        "mandatory": True,
                        "id": "other-answer-mandatory",
                        "label": "Please specify other",
                        "type": "TextField",
                    },
                },
            ],
        }],
    }

    questionnaire = make_schema("0.0.1", "section-1", "favourite-food",
                                "crisps", question)

    # When
    answer_object = convert_answers(QuestionnaireSchema(questionnaire),
                                    fake_questionnaire_store, routing_path)

    # Then
    assert len(answer_object["data"]) == 2
    assert answer_object["data"]["1"] == "Ready salted"
    assert answer_object["data"]["2"] == "Sweet chilli"
Beispiel #3
0
 def setUp(self):
     super().setUp()
     self.block_type = "SectionSummary"
     self.schema = load_schema_from_name("test_section_summary")
     self.language = "en"
     self.metadata = {}
     self.response_metadata = {}
     self.answer_store = AnswerStore()
     self.list_store = ListStore()
     self.progress_store = ProgressStore()
Beispiel #4
0
    def test_evaluate_date_rule_invalid(self):
        when = {
            "id": "date-answer",
            "condition": "greater than",
            "date_comparison": {"id": "compare_date_answer"},
        }
        answer_store = AnswerStore({})
        result = evaluate_date_rule(when, answer_store, get_schema_mock(), None, None)

        self.assertFalse(result)
    def setUp(self):
        self.store = AnswerStore()

        answer1 = Answer(answer_id="set-minimum", value=10)
        answer2 = Answer(answer_id="set-maximum", value=20)
        answer3 = Answer(answer_id="set-maximum-cat", value="cat")

        self.store.add_or_update(answer1)
        self.store.add_or_update(answer2)
        self.store.add_or_update(answer3)
def store_to_serialize():
    answer_store = AnswerStore()

    answer_store.add_or_update(
        Answer(answer_id="answer1", value=10, list_item_id="abc123"))
    answer_store.add_or_update(
        Answer(answer_id="answer2", value=20, list_item_id="xyz987"))
    answer_store.add_or_update(Answer(answer_id="answer3", value=30))

    return answer_store
    def test_form_ids_match_block_answer_ids(self):
        with self.app_request_context():
            schema = load_schema_from_name("test_textfield")

            question_schema = schema.get_block("name-block").get("question")

            form = generate_form(schema, question_schema, AnswerStore(), metadata=None)

            for answer_id in schema.get_answer_ids_for_block("name-block"):
                self.assertTrue(hasattr(form, answer_id))
    def test_invalid_maximum_period_limit_and_single_date_periods(self):
        with self.app_request_context():
            schema = load_schema_from_name("test_date_validation_range")

            question_schema = {
                "id": "date-range-question",
                "type": "DateRange",
                "period_limits": {"maximum": {"days": 8}},
                "answers": [
                    {
                        "id": "date-range-from",
                        "label": "Period from",
                        "mandatory": True,
                        "type": "Date",
                        "minimum": {"value": "2018-01-10", "offset_by": {"days": -5}},
                    },
                    {
                        "id": "date-range-to",
                        "label": "Period to",
                        "mandatory": True,
                        "type": "Date",
                        "maximum": {"value": "2018-01-10", "offset_by": {"days": 5}},
                    },
                ],
            }

            form_data = MultiDict(
                {
                    "date-range-from-day": "6",
                    "date-range-from-month": "1",
                    "date-range-from-year": "2018",
                    "date-range-to-day": "15",
                    "date-range-to-month": "1",
                    "date-range-to-year": "2018",
                }
            )

            form = generate_form(
                schema,
                question_schema,
                AnswerStore(),
                metadata=None,
                form_data=form_data,
            )

            with self.assertRaises(Exception) as ite:
                with patch(
                    "app.questionnaire.questionnaire_schema.QuestionnaireSchema.get_all_questions_for_block",
                    return_value=[question_schema],
                ):
                    form.validate()
                    self.assertEqual(
                        "The schema has invalid period_limits for date-range-question",
                        str(ite.exception),
                    )
Beispiel #9
0
def test_questionnaire_store_missing_keys(questionnaire_store, basic_input):
    # Given
    del basic_input["PROGRESS"]
    questionnaire_store.input_data = json_dumps(basic_input)
    # When
    store = QuestionnaireStore(questionnaire_store.storage)
    # Then
    assert store.metadata.copy() == basic_input["METADATA"]
    assert store.response_metadata == basic_input["RESPONSE_METADATA"]
    assert store.answer_store == AnswerStore(basic_input["ANSWERS"])
    assert not store.progress_store.serialize()
 def test_questionnaire_store_missing_keys(self):
     # Given
     expected = get_basic_input()
     del expected["PROGRESS"]
     self.input_data = json.dumps(expected)
     # When
     store = QuestionnaireStore(self.storage)
     # Then
     self.assertEqual(store.metadata.copy(), expected["METADATA"])
     self.assertEqual(store.response_metadata, expected["RESPONSE_METADATA"])
     self.assertEqual(store.answer_store, AnswerStore(expected["ANSWERS"]))
     self.assertEqual(store.progress_store.serialize(), [])
    def test_bespoke_message_for_date_validation_range(self):
        with self.app_request_context():
            schema = load_schema_from_name("test_date_validation_range")

            question_schema = {
                "id": "date-range-question",
                "type": "DateRange",
                "validation": {"messages": {"DATE_PERIOD_TOO_SMALL": "Test Message"}},
                "period_limits": {"minimum": {"days": 20}},
                "answers": [
                    {
                        "id": "date-range-from",
                        "label": "Period from",
                        "mandatory": True,
                        "type": "Date",
                    },
                    {
                        "id": "date-range-to",
                        "label": "Period to",
                        "mandatory": True,
                        "type": "Date",
                    },
                ],
            }

            form_data = MultiDict(
                {
                    "date-range-from-day": "25",
                    "date-range-from-month": "1",
                    "date-range-from-year": "2018",
                    "date-range-to-day": "26",
                    "date-range-to-month": "1",
                    "date-range-to-year": "2018",
                }
            )

            form = generate_form(
                schema,
                question_schema,
                AnswerStore(),
                metadata=None,
                form_data=form_data,
            )

            with patch(
                "app.questionnaire.questionnaire_schema.QuestionnaireSchema.get_all_questions_for_block",
                return_value=[question_schema],
            ):
                form.validate()
                self.assertIn(
                    form.question_errors["date-range-question"], "Test Message"
                )
Beispiel #12
0
 def test_custom_section_summary_page_title(self):
     current_location = Location(section_id="property-details-section")
     summary_context = SectionSummaryContext(
         self.language,
         self.schema,
         AnswerStore([]),
         self.list_store,
         self.progress_store,
         self.metadata,
     )
     context = summary_context(current_location)
     self.assertEqual("Custom section summary title",
                      context["summary"]["page_title"])
Beispiel #13
0
def fake_questionnaire_store():
    storage = Mock()
    storage.get_user_data = Mock(return_value=("{}", "ce_sid", 1, None))
    questionnaire_store = QuestionnaireStore(storage)
    questionnaire_store.submitted_at = SUBMITTED_AT
    questionnaire_store.metadata = {"tx_id": "123456789", "ru_name": "Apple"}
    questionnaire_store.answer_store = AnswerStore(
        [
            Answer("name-answer", "John Smith", None).to_dict(),
            Answer("address-answer", "NP10 8XG", None).to_dict(),
        ]
    )
    return questionnaire_store
Beispiel #14
0
def test_questionnaire_store_updates_storage(questionnaire_store, basic_input):
    # Given
    store = QuestionnaireStore(questionnaire_store.storage)
    store.set_metadata(basic_input["METADATA"])
    store.answer_store = AnswerStore(basic_input["ANSWERS"])
    store.response_metadata = basic_input["RESPONSE_METADATA"]
    store.progress_store = ProgressStore(basic_input["PROGRESS"])

    # When
    store.save()

    # Then
    assert basic_input == json_loads(questionnaire_store.output_data)
    def test_get_calculation_total_with_no_input(self):
        store = AnswerStore()

        answer_total = Answer(answer_id="total-answer", value=10)

        store.add_or_update(answer_total)

        with self.app_request_context():
            schema = load_schema_from_name("test_sum_equal_validation_against_total")

            question_schema = schema.get_block("breakdown-block").get("question")

            form_data = MultiDict(
                {
                    "breakdown-1": "",
                    "breakdown-2": "",
                    "breakdown-3": "",
                    "breakdown-4": "",
                }
            )

            expected_form_data = {
                "csrf_token": "",
                "breakdown-1": None,
                "breakdown-2": None,
                "breakdown-3": None,
                "breakdown-4": None,
            }
            form = generate_form(
                schema, question_schema, store, metadata=None, form_data=form_data
            )

            form.validate()
            self.assertEqual(form.data, expected_form_data)
            self.assertEqual(
                form.question_errors["breakdown-question"],
                schema.error_messages["TOTAL_SUM_NOT_EQUALS"] % {"total": "10"},
                AnswerStore(),
            )
Beispiel #16
0
def test_get_length_validator():
    text_area_handler = TextAreaHandler(
        {},
        {
            "MAX_LENGTH_EXCEEDED":
            "This is the default max length of %(max)d message"
        },
        AnswerStore(),
        {},
    )
    validator = text_area_handler.get_length_validator()

    assert validator.message == "This is the default max length of %(max)d message"
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_multi_calculation(self):
        store = AnswerStore()

        answer_total = Answer(answer_id="total-answer", value=10)

        store.add_or_update(answer_total)

        with self.app_request_context():
            schema = load_schema_from_name("test_sum_multi_validation_against_total")

            question_schema = schema.get_block("breakdown-block").get("question")

            form_data = MultiDict(
                {
                    "breakdown-1": "",
                    "breakdown-2": "",
                    "breakdown-3": "",
                    "breakdown-4": "",
                }
            )

            # With no answers question validation should pass
            form = generate_form(
                schema, question_schema, store, metadata=None, form_data=form_data
            )
            form.validate()

            self.assertEqual(len(form.question_errors), 0)

            # With the data equaling the total question validation should pass
            form_data["breakdown-1"] = "10"

            form = generate_form(
                schema, question_schema, store, metadata=None, form_data=form_data
            )
            form.validate()

            self.assertEqual(len(form.question_errors), 0)

            # With the data not equaling zero or the total, question validation should fail
            form_data["breakdown-1"] = "1"

            form = generate_form(
                schema, question_schema, store, metadata=None, form_data=form_data
            )
            form.validate()

            self.assertEqual(
                form.question_errors["breakdown-question"],
                schema.error_messages["TOTAL_SUM_NOT_EQUALS"] % {"total": "10"},
            )
    def test_date_range_too_large_period_raises_question_error(self):
        with self.app_request_context():
            schema = load_schema_from_name("test_date_validation_range")

            question_schema = schema.get_block("date-range-block").get("question")

            form_data = MultiDict(
                {
                    "date-range-from-day": "25",
                    "date-range-from-month": "12",
                    "date-range-from-year": "2016",
                    "date-range-to-day": "24",
                    "date-range-to-month": "12",
                    "date-range-to-year": "2017",
                }
            )

            expected_form_data = {
                "csrf_token": "",
                "date-range-from": "2016-12-25",
                "date-range-to": "2017-12-24",
            }
            form = generate_form(
                schema,
                question_schema,
                AnswerStore(),
                metadata=None,
                form_data=form_data,
            )

            form.validate()
            self.assertEqual(form.data, expected_form_data)
            self.assertEqual(
                form.question_errors["date-range-question"],
                schema.error_messages["DATE_PERIOD_TOO_LARGE"]
                % {"max": "1 month, 20 days"},
                AnswerStore(),
            )
    def test_date_range_to_precedes_from_raises_question_error(self):
        with self.app_request_context():
            schema = load_schema_from_name("test_date_range")

            question_schema = schema.get_block("date-block").get("question")

            form_data = MultiDict(
                {
                    "date-range-from-answer-day": "25",
                    "date-range-from-answer-month": "12",
                    "date-range-from-answer-year": "2016",
                    "date-range-to-answer-day": "24",
                    "date-range-to-answer-month": "12",
                    "date-range-to-answer-year": "2016",
                }
            )

            expected_form_data = {
                "csrf_token": "",
                "date-range-from-answer": "2016-12-25",
                "date-range-to-answer": "2016-12-24",
            }

            form = generate_form(
                schema,
                question_schema,
                AnswerStore(),
                metadata=None,
                form_data=form_data,
            )

            form.validate()
            self.assertEqual(form.data, expected_form_data)
            self.assertEqual(
                form.question_errors["date-range-question"],
                schema.error_messages["INVALID_DATE_RANGE"],
                AnswerStore(),
            )
Beispiel #21
0
def relationship_router(answers=None, relationships=None):
    return RelationshipRouter(
        answer_store=AnswerStore(answers),
        relationship_store=RelationshipStore(relationships),
        section_id="relationships-section",
        list_name="people",
        list_item_ids=[
            "abc123", "def123", "ghi123", "jkl123", "mno123", "pqr123"
        ],
        relationships_block_id="relationships",
        unrelated_block_id="related-to-anyone-else",
        unrelated_answer_id="anyone-else-answer",
        unrelated_no_answer_values=["No", "No, they are not related"],
    )
Beispiel #22
0
def test_get_mandatory_validator_mandatory():
    answer = {"mandatory": True}

    text_area_handler = StringHandler(
        answer,
        {"MANDATORY_TEXTFIELD": "This is the default mandatory message"},
        AnswerStore(),
        {},
    )

    validate_with = text_area_handler.get_mandatory_validator()

    assert isinstance(validate_with, ResponseRequired)
    assert validate_with.message == "This is the default mandatory message"
def test_dropdown_answer(fake_questionnaire_store):
    full_routing_path = [
        RoutingPath(["dropdown-block"],
                    section_id="section-1",
                    list_item_id=None)
    ]
    fake_questionnaire_store.answer_store = AnswerStore(
        [Answer("dropdown-answer", "Liverpool").to_dict()])

    question = {
        "id":
        "dropdown-question",
        "answers": [{
            "id":
            "dropdown-answer",
            "type":
            "Dropdown",
            "q_code":
            "1",
            "options": [
                {
                    "label": "Liverpool",
                    "value": "Liverpool"
                },
                {
                    "label": "Chelsea",
                    "value": "Chelsea"
                },
                {
                    "label": "Rugby is better!",
                    "value": "Rugby is better!"
                },
            ],
        }],
    }

    questionnaire = make_schema("0.0.1", "section-1", "dropdown-block",
                                "dropdown-block", question)

    # When
    answer_object = convert_answers(
        QuestionnaireSchema(questionnaire),
        fake_questionnaire_store,
        full_routing_path,
        SUBMITTED_AT,
    )

    # Then
    assert len(answer_object["data"]) == 1
    assert answer_object["data"]["1"] == "Liverpool"
Beispiel #24
0
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)

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

    data_dict = json.loads(json.dumps(output["data"]["answers"],
                                      for_json=True))

    assert sorted(answer_objects, key=lambda x: x["answer_id"]) == sorted(
        data_dict, key=lambda x: x["answer_id"])
Beispiel #25
0
 def test_section_summary_page_title_placeholder_text_plural_replaced(self):
     current_location = Location(section_id="household-count-section")
     answers = [{"answer_id": "number-of-people-answer", "value": 3}]
     summary_context = SectionSummaryContext(
         self.language,
         self.schema,
         AnswerStore(answers),
         self.list_store,
         self.progress_store,
         self.metadata,
     )
     context = summary_context(current_location)
     self.assertEqual(context["summary"]["page_title"],
                      "… people live here")
    def test_questionnaire_store_updates_storage(self):
        # Given
        expected = get_basic_input()
        store = QuestionnaireStore(self.storage)
        store.set_metadata(expected["METADATA"])
        store.answer_store = AnswerStore(expected["ANSWERS"])
        store.collection_metadata = expected["COLLECTION_METADATA"]
        store.progress_store = ProgressStore(expected["PROGRESS"])

        # When
        store.save()  # See setUp - populates self.output_data

        # Then
        self.assertEqual(expected, json.loads(self.output_data))
Beispiel #27
0
def test_chain_transform_placeholder():
    placeholder_list = [{
        "placeholder":
        "persons_name",
        "transforms": [
            {
                "transform": "concatenate_list",
                "arguments": {
                    "list_to_concatenate": [
                        {
                            "source": "answers",
                            "identifier": "first-name"
                        },
                        {
                            "source": "answers",
                            "identifier": "last-name"
                        },
                    ],
                    "delimiter":
                    " ",
                },
            },
            {
                "transform": "format_possessive",
                "arguments": {
                    "string_to_format": {
                        "source": "previous_transform"
                    }
                },
            },
        ],
    }]

    parser = PlaceholderParser(
        language="en",
        answer_store=AnswerStore([
            {
                "answer_id": "first-name",
                "value": "Joe"
            },
            {
                "answer_id": "last-name",
                "value": "Bloggs"
            },
        ]),
    )

    placeholders = parser(placeholder_list)
    assert placeholders["persons_name"] == "Joe Bloggs’"
Beispiel #28
0
def fake_questionnaire_store(fake_metadata, fake_collection_metadata):
    user_answer = Answer(answer_id="GHI", value=0, list_item_id=None)

    storage = MagicMock()
    storage.get_user_data = MagicMock(return_value=("{}", 1))
    storage.add_or_update = MagicMock()

    store = QuestionnaireStore(storage)

    store.answer_store = AnswerStore()
    store.answer_store.add_or_update(user_answer)
    store.metadata = fake_metadata
    store.collection_metadata = fake_collection_metadata

    return store
Beispiel #29
0
 def setUp(self):
     super().setUp()
     self.schema = load_schema_from_name("test_summary")
     self.answer_store = AnswerStore()
     self.list_store = ListStore()
     self.progress_store = ProgressStore()
     self.block_type = "Summary"
     self.rendered_block = {
         "parent_id": "summary-group",
         "id": "summary",
         "type": "Summary",
         "collapsible": True,
     }
     self.current_location = Location(section_id="default-section",
                                      block_id="summary")
    def test_date_range_form(self):
        with self.app_request_context():
            schema = load_schema_from_name("test_date_range")
            question_schema = schema.get_block("date-block").get("question")

            form = generate_form(schema, question_schema, AnswerStore(), metadata=None)

            self.assertTrue(hasattr(form, "date-range-from-answer"))
            self.assertTrue(hasattr(form, "date-range-to-answer"))

            period_from_field = getattr(form, "date-range-from-answer")
            period_to_field = getattr(form, "date-range-to-answer")

            self.assertIsInstance(period_from_field.year.validators[0], DateRequired)
            self.assertIsInstance(period_to_field.year.validators[0], DateRequired)