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"
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()
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), )
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" )
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"])
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
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(), )
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(), )
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"], )
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"
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"])
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))
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’"
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
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)