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')) self.assertFalse( evaluate_goto(goto_rule, get_schema_mock(), {}, answer_store, 0))
def test_evaluate_skip_condition_returns_true_when_that_rule_true(self): skip_condition = [{ 'when': [{ 'id': 'this', 'condition': 'equals', 'value': 'value' }] }, { 'when': [{ 'id': 'that', 'condition': 'equals', 'value': 'other value' }] }] answer_store = AnswerStore() answer_store.add(Answer(answer_id='that', value='other value')) self.assertTrue( evaluate_skip_condition(skip_condition, {}, answer_store))
def test_case_id_should_be_set_in_payload(self): with self._app.test_request_context(): questionnaire = {'survey_id': '021', 'data_version': '0.0.2'} answer_object = convert_answers(self.metadata, QuestionnaireSchema(questionnaire), AnswerStore(), {}) self.assertEqual(answer_object['case_id'], self.metadata['case_id'])
def test_evaluate_date_rule_greater_than_with_id(self): when = { 'id': 'date-answer', 'condition': 'greater than', 'date_comparison': { 'id': 'compare_date_answer' } } answer_store = AnswerStore({}) answer_store.add(Answer(answer_id='compare_date_answer', value='2018-02-03')) answer_value = '2018-02-04' result = evaluate_date_rule(when, answer_store, get_schema_mock(), 0, None, answer_value) self.assertTrue(result) answer_value = '2018-02-03' result = evaluate_date_rule(when, answer_store, get_schema_mock(), 0, None, answer_value) self.assertFalse(result)
def test_get_checkbox_answer_with_duplicate_child_answer_ids(self): with self._app.test_request_context(): routing_path = [ Location(group_id='favourite-food', group_instance=0, block_id='crisps') ] answers = [ create_answer('crisps-answer', ['Ready salted', 'Other'], group_id='favourite-food', block_id='crisps') ] answers += [ create_answer('other-answer-mandatory', 'Other', group_id='favourite-food', block_id='crisps', group_instance=1) ] answers += [ create_answer('other-answer-mandatory', 'Other', group_id='favourite-food', block_id='crisps', group_instance=1) ] questionnaire = make_schema( '0.0.1', 'section-1', 'favourite-food', 'crisps', [{ 'id': 'crisps-question', 'answers': [{ 'id': 'crisps-answer', 'type': 'Checkbox', 'options': [{ 'label': 'Other', 'q_code': '4', 'description': 'Choose any other flavour', 'value': 'Other', 'child_answer_id': 'other-answer-mandatory' }] }] }]) with self.assertRaises(Exception) as err: convert_answers(self.metadata, self.collection_metadata, QuestionnaireSchema(questionnaire), AnswerStore(answers), routing_path) self.assertEqual( 'Multiple answers found for {}'.format('other-answer-mandatory'), str(err.exception))
def test_do_not_go_to_next_question_for_multiple_answers(self): # Given goto_rule = { 'id': 'next-question', 'when': [{ 'id': 'my_answer', 'condition': 'equals', 'value': 'Yes' }, { 'id': 'my_other_answer', 'condition': 'equals', 'value': '2' }] } answer_store = AnswerStore({}) answer_store.add(Answer(answer_id='my_answer', value='No')) self.assertFalse( evaluate_goto(goto_rule, get_schema_mock(), {}, answer_store, 0))
def test_get_next_location_summary(self): survey = load_schema_file("0_star_wars.json") answer_1 = Answer(group_id="14ba4707-321d-441d-8d21-b8367366e766", block_id="choose-your-side-block", answer_id="ca3ce3a3-ae44-4e30-8f85-5b6a7a2fb23c", value="Light Side") answer_2 = Answer( group_id="14ba4707-321d-441d-8d21-b8367366e766", block_id="96682325-47ab-41e4-a56e-8315a19ffe2a", answer_id="2e0989b8-5185-4ba6-b73f-c126e3a06ba7", value="No", ) answers = AnswerStore() answers.add(answer_1) answers.add(answer_2) path_finder = PathFinder(survey, answer_store=answers) current_location = Location('14ba4707-321d-441d-8d21-b8367366e766', 0, 'an3b74d1-b687-4051-9634-a8f9ce10ard') next_location = path_finder.get_next_location( current_location=current_location) expected_next_location = Location( "14ba4707-321d-441d-8d21-b8367366e766", 0, '846f8514-fed2-4bd7-8fb2-4b5fcb1622b1') self.assertEqual(expected_next_location, next_location) current_location = expected_next_location next_location = path_finder.get_next_location( current_location=current_location) expected_next_location = Location( "14ba4707-321d-441d-8d21-b8367366e766", 0, 'summary') self.assertEqual(expected_next_location, next_location)
def test_previous_with_conditional_path(self): schema = load_schema_from_params('0', 'star_wars') schema.answer_is_in_repeating_group = MagicMock(return_value=False) expected_path = [ Location('star-wars', 0, 'choose-your-side-block'), Location('star-wars', 0, 'dark-side-pick-character-ship'), Location('star-wars', 0, 'light-side-ship-type'), Location('star-wars', 0, 'star-wars-trivia'), Location('star-wars', 0, 'star-wars-trivia-part-2'), Location('star-wars', 0, 'star-wars-trivia-part-3'), ] answer_1 = Answer( answer_id='choose-your-side-answer', value='Dark Side' ) answer_2 = Answer( answer_id='dark-side-pick-ship-answer', value='Can I be a pain and have a goodies ship', ) answers = AnswerStore() answers.add(answer_1) answers.add(answer_2) current_location = expected_path[3] expected_previous_location = expected_path[2] path_finder = PathFinder(schema, answer_store=answers, metadata={}, completed_blocks=[]) actual_previous_block = path_finder.get_previous_location(current_location=current_location) self.assertEqual(actual_previous_block, expected_previous_location) current_location = expected_path[2] expected_previous_location = expected_path[1] actual_previous_block = path_finder.get_previous_location(current_location=current_location) self.assertEqual(actual_previous_block, expected_previous_location)
def test_sum_calculated_field(self): store = AnswerStore() answer_total = Answer( answer_id='total-answer', answer_instance=1, group_instance=1, value=10, ) store.add(answer_total) with self.app_request_context(): schema = load_schema_from_params( 'test', 'sum_equal_validation_against_total') block_json = schema.get_block('breakdown-block') data = { 'breakdown-1': '', 'breakdown-2': '5', 'breakdown-3': '4', 'breakdown-4': '1' } expected_form_data = { 'csrf_token': '', 'breakdown-1': None, 'breakdown-2': Decimal('5'), 'breakdown-3': Decimal('4'), 'breakdown-4': Decimal('1') } form = generate_form(schema, block_json, store, metadata=None, group_instance=0, formdata=data) form.validate() self.assertEqual(form.data, expected_form_data)
def test_evaluate_not_set_when_rules_should_return_true(self): when = { 'when': [ { 'id': 'my_answers', 'condition': 'not set' } ] } answer_store = AnswerStore({}) self.assertTrue(evaluate_when_rules(when, get_schema_mock(), {}, answer_store, 0))
def test_transform_variants_with_content(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"]) transformed_block = transform_variants( block, schema, metadata, answer_store, ListStore({}), Location(section_id=section_id, block_id=block["id"]), ) assert transformed_block != block assert "content_variants" not in transformed_block assert transformed_block["content"][0]["title"] == "You are over 16"
def test_evaluate_skip_condition_returns_false_when_no_skip_condition( self): # Given skip_conditions = None # When condition = evaluate_skip_conditions(skip_conditions, get_schema_mock(), {}, AnswerStore({})) # Then self.assertFalse(condition)
def test_convert_answers_flushed_flag_overriden_to_true(self): with self._app.test_request_context(): user_answer = [create_answer('GHI', 0)] questionnaire = {'survey_id': '021', 'data_version': '0.0.2'} answer_object = convert_answers(self.metadata, QuestionnaireSchema(questionnaire), AnswerStore(user_answer), {}, flushed=True) self.assertTrue(answer_object['flushed'])
def test_given_interstitial_page_when_get_page_title_then_group_title_and_survey_title( self): # Given schema = load_schema_from_params('test', 'interstitial_page') # When page_title = get_page_title_for_location( schema, Location('favourite-foods', 0, 'breakfast-interstitial'), {}, AnswerStore()) # Then self.assertEqual(page_title, 'Favourite food - Interstitial Pages')
def test_answer_count_when_rule_not_equal(self): # pylint: disable=no-self-use """Assert that an `answer_count` can be used in a when block and the False is returned when the values do not match. """ answer_group_id = 'repeated-answer' when = [{ 'answer_count': answer_group_id, 'condition': 'equals', 'value': 1, }] answer_store = AnswerStore({}) self.assertFalse(evaluate_when_rules(when, get_schema_mock(), {}, answer_store, 0))
def test_meta_comparison_missing(self): # Given goto_rule = { 'id': 'next-question', 'when': [ { 'condition': 'equals', 'meta': 'varient_flags.does_not_exist.does_not_exist', 'value': True } ] } answer_store = AnswerStore({}) answer_store.add(Answer(answer_id='my_answer', value='Yes')) metadata = {'varient_flags': {'sexual_identity': True}} # When goto = evaluate_goto(goto_rule, get_schema_mock(), metadata, answer_store, 0) # Then self.assertFalse(goto)
def test_answer_count_when_rule_id_takes_precident(self): """Assert that if somehow, both `id` and `answer_count` are present in a when clause the `id` takes precident and no errors are thrown. """ answer_group_id = 'repeated-answer' ref_id = 'just-a-regular-answer' when = [{ 'id': ref_id, 'answer_count': answer_group_id, 'condition': 'equals', 'value': 10, }] answer_store = AnswerStore({}) answer_store.add(Answer( answer_id=ref_id, group_instance=0, value=10, )) self.assertTrue( evaluate_when_rules(when, get_schema_mock(), {}, answer_store, 0, None))
def test_submitted_at_should_be_set_in_payload(self): with self.application.test_request_context(): user_answer = [create_answer('GHI', 0)] questionnaire = { "survey_id": "021", "data_version": "0.0.2" } answer_object = convert_answers(metadata, questionnaire, AnswerStore(user_answer), {}) self.assertLess(datetime.now(timezone.utc) - dateutil.parser.parse(answer_object['submitted_at']), timedelta(seconds=5))
def test_converter_raises_runtime_error_for_unsupported_version(self): with self.application.test_request_context(): questionnaire = { "survey_id": "021", "data_version": "-0.0.1" } with self.assertRaises(DataVersionError) as err: convert_answers(metadata, questionnaire, AnswerStore(), {}) self.assertEqual(str(err.exception), 'Data version -0.0.1 not supported')
def test_id_when_rule_answer_count_equal_0(self): """Assert that an `answer_count` can be used in a when block and the correct value is fetched. """ answer_group_id = 'repeated-answer' when = [{ 'answer_count': answer_group_id, 'condition': 'equals', 'value': 0, }] answer_store = AnswerStore({}) self.assertTrue(evaluate_when_rules(when, get_schema_mock(), {}, answer_store, 0))
def __init__(self, storage): self._storage = storage self._initial_data = {} self.metadata = {} self.answer_store = AnswerStore() self.completed_blocks = [] if self._storage.exists(): raw_data = self._storage.get_user_data() self._initial_data = self._deserialise(raw_data) data_copy = self._deserialise(raw_data) self._set_data(data_copy)
def test_given_introduction_page_when_get_page_title_then_defaults_to_survey_title( self): # Given schema = load_schema_from_params('test', 'final_confirmation') # When page_title = get_page_title_for_location( schema, Location('final-confirmation', 0, 'introduction'), {}, AnswerStore()) # Then self.assertEqual(page_title, 'Final confirmation to submit')
def test_convert_answers_flushed_flag_default_is_false(self): with self._app.test_request_context(): user_answer = [create_answer('GHI', 0)] questionnaire = {'survey_id': '021', 'data_version': '0.0.2'} answer_object = convert_answers(self.metadata, self.collection_metadata, QuestionnaireSchema(questionnaire), AnswerStore(user_answer), {}) self.assertFalse(answer_object['flushed'])
def test_date_form_empty_data(self): schema = load_schema_from_params('test', 'dates') error_messages = schema.error_messages answers = schema.get_answers_by_id_for_block('date-block') with self.app_request_context('/'): form = get_date_form(AnswerStore(), {}, answers['single-date-answer'], error_messages=error_messages) self.assertIsNone(form().data)
def test_get_referenced_offset_value_for_answer_id(app): answer_store = AnswerStore() test_answer_id = Answer(answer_id="date", value="2018-03-20") answer_store.add_or_update(test_answer_id) answer = { "maximum": { "value": { "identifier": "date", "source": "answers" } } } handler = DateHandler(answer, answer_store=answer_store) maximum_date = handler.get_date_value("maximum") maximum_date = handler.transform_date_by_offset(maximum_date, {"months": 1}) assert maximum_date == convert_to_datetime("2018-04-20")
def test_get_next_location_should_not_skip_group(self): # Given survey = load_schema_file('test_skip_condition_group.json') current_location = Location('do-you-want-to-skip-group', 0, 'do-you-want-to-skip') answer_store = AnswerStore() answer_store.add( Answer(group_id='do-you-want-to-skip-group', block_id='do-you-want-to-skip', answer_id='do-you-want-to-skip-answer', value='No')) # When path_finder = PathFinder(survey, answer_store=answer_store) # Then expected_location = Location('should-skip-group', 0, 'should-skip') self.assertEqual( path_finder.get_next_location(current_location=current_location), expected_location)
def test_go_to_next_question_for_multiple_answers(self): # Given goto = { "id": "next-question", "when": [ { "id": "my_answer", "condition": "equals", "value": "Yes" }, { "id": "my_other_answer", "condition": "equals", "value": "2" }, ], } answer_store = AnswerStore() answer_store.add_or_update(Answer(answer_id="my_answer", value="Yes")) answer_store.add_or_update( Answer(answer_id="my_other_answer", value="2")) current_location = Location(section_id="some-section", block_id="some-block") self.assertTrue( evaluate_goto( goto_rule=goto, schema=get_schema(), metadata={}, answer_store=answer_store, list_store=ListStore(), current_location=current_location, ))
def test_route_based_on_answer_count(self): schema = load_schema_from_params('test', 'routing_answer_count') answer_group_id = 'first-name' answer_store = AnswerStore({}) answer_store.add(Answer( answer_id=answer_group_id, answer_instance=0, value='alice', )) answer_store.add(Answer( answer_id=answer_group_id, answer_instance=1, value='bob', )) completed_blocks = [ Location('multiple-questions-group', 0, 'household-composition') ] expected_next_location = Location('group-equal-2', 0, 'group-equal-2-block') should_not_be_present = Location('group-less-than-2', 0, 'group-less-than-2-block') path_finder = PathFinder(schema, answer_store, metadata={}, completed_blocks=completed_blocks) path = path_finder.build_path() self.assertNotIn(should_not_be_present, path) self.assertIn(expected_next_location, path)
def test_repeating_groups_no_of_answers_minus_one(self): survey = load_schema_file("test_repeating_household.json") # Default is to count answers, so switch to using value survey['groups'][-1]['routing_rules'][0]['repeat'][ 'type'] = 'answer_count_minus_one' expected_path = [ Location("multiple-questions-group", 0, "household-composition"), Location("repeating-group", 0, "repeating-block-1"), Location("repeating-group", 0, "repeating-block-2"), ] answer = Answer(group_id="multiple-questions-group", group_instance=0, answer_instance=0, answer_id="first-name", block_id="household-composition", value="Joe Bloggs") answer_2 = Answer(group_id="multiple-questions-group", group_instance=0, answer_instance=1, answer_id="first-name", block_id="household-composition", value="Sophie Bloggs") answers = AnswerStore() answers.add(answer) answers.add(answer_2) path_finder = PathFinder(survey, answer_store=answers) self.assertEqual(expected_path, path_finder.get_routing_path())
def test_evaluate_skip_condition_returns_true_when_more_than_one_rule_is_true(self): # Given skip_conditions = [ { 'when': [ { 'id': 'this', 'condition': 'equals', 'value': 'value' } ] }, { 'when': [ { 'id': 'that', 'condition': 'equals', 'value': 'other value' } ] } ] answer_store = AnswerStore({}) answer_store.add(Answer(answer_id='this', value='value')) answer_store.add(Answer(answer_id='that', value='other value')) # When condition = evaluate_skip_conditions(skip_conditions, get_schema_mock(), {}, answer_store) # Then self.assertTrue(condition)