def get_schema(): schema = QuestionnaireSchema( { "questionnaire_flow": { "type": "Linear", "options": {"summary": {"collapsible": False}}, } } ) return schema
def test_get_group_for_list_collector_child_block(): survey_json = { "sections": [ { "id": "section1", "groups": [ { "id": "group", "blocks": [ { "id": "list-collector", "type": "ListCollector", "for_list": "list", "question": {}, "add_block": { "id": "add-block", "type": "ListAddQuestion", "question": {}, }, "edit_block": { "id": "edit-block", "type": "ListEditQuestion", "question": {}, }, "remove_block": { "id": "remove-block", "type": "ListRemoveQuestion", "question": {}, }, } ], } ], } ] } schema = QuestionnaireSchema(survey_json) group = schema.get_group_for_block_id("add-block") assert group is not None assert group["id"] == "group"
def test_submission_language_code_in_payload(self): with patch( "app.views.handlers.submission.get_session_store", return_value=self.session_store, ): submission_handler = SubmissionHandler( QuestionnaireSchema({}), self.questionnaire_store_mock(), {}) assert submission_handler.get_payload( )["submission_language_code"] == "cy"
def load_schema_from_params(eq_id, form_type, language_code=None): language_code = language_code or DEFAULT_LANGUAGE_CODE cache_key = (eq_id, form_type, language_code) if cache_key not in schema_cache: schema_json = _load_schema_file('{}_{}.json'.format(eq_id, form_type), language_code) schema_cache[cache_key] = QuestionnaireSchema(schema_json, language_code) return schema_cache[cache_key]
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 = {} 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["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, 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 get_state_for_group(self, group, group_instance=None): if isinstance(group, str): # lookup group by group ID group = self.schema.get_group(group) if (QuestionnaireSchema.is_confirmation_group(group) or QuestionnaireSchema.is_summary_group(group)): # summary/confirmations are special cases as we don't want to # render until the whole survey is complete. They're also never # show as complete return self.NOT_STARTED if self.all_sections_complete( ) else self.SKIPPED if self._should_skip(group): return self.SKIPPED block_states = [ state for location, state in self._get_block_states_for_group( group, group_instance) ] def eval_state(state_to_compare): return (state == state_to_compare for state in block_states) group_state = self.NOT_STARTED if all(eval_state(self.SKIPPED)): group_state = self.SKIPPED elif not self.routing_path: group_state = self.NOT_STARTED elif all(eval_state(self.INVALID)): group_state = self.INVALID elif all(state in self.COMPLETED_STATES for state in block_states): group_state = self.COMPLETED elif any(eval_state(self.COMPLETED)): group_state = self.STARTED return group_state
def test_relationship_answer(self): with self._app.test_request_context(): routing_path = [Location(group_id='relationship-group', group_instance=0, block_id='relationship-block')] user_answer = [create_answer('relationship-answer', 'Unrelated', group_id='relationship-group', block_id='relationship-block'), create_answer('relationship-answer', 'Partner', group_id='relationship-group', block_id='relationship-block', answer_instance=1), create_answer('relationship-answer', 'Husband or wife', group_id='relationship-group', block_id='relationship-block', answer_instance=2)] questionnaire = make_schema('0.0.2', 'section-1', 'relationship-group', 'relationship-block', [ { 'id': 'relationship-question', 'type': 'Relationship', 'answers': [ { 'id': 'relationship-answer', 'q_code': '1', 'type': 'Relationship', 'options': [ { 'label': 'Husband or wife', 'value': 'Husband or wife' }, { 'label': 'Partner', 'value': 'Partner' }, { 'label': 'Unrelated', 'value': 'Unrelated' } ] } ] } ]) # When answer_object = convert_answers(self.metadata, self.collection_metadata, QuestionnaireSchema(questionnaire), AnswerStore(user_answer), routing_path) # Then self.assertEqual(len(answer_object['data']), 3) self.assertEqual(answer_object['data'][0]['value'], 'Unrelated') self.assertEqual(answer_object['data'][0]['group_instance'], 0) self.assertEqual(answer_object['data'][0]['answer_instance'], 0) self.assertEqual(answer_object['data'][1]['value'], 'Partner') self.assertEqual(answer_object['data'][1]['group_instance'], 0) self.assertEqual(answer_object['data'][1]['answer_instance'], 1) self.assertEqual(answer_object['data'][2]['value'], 'Husband or wife') self.assertEqual(answer_object['data'][2]['group_instance'], 0) self.assertEqual(answer_object['data'][2]['answer_instance'], 2)
def test_transform_variants_with_no_variants(question_schema): schema = QuestionnaireSchema(question_schema) answer_store = AnswerStore({}) 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"]), ) assert transformed_block == block
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_has_expired_no_submitted_at_return_false(storage, language, app): with app.app_context(): set_storage_data(storage) questionnaire_store = QuestionnaireStore(storage) schema = QuestionnaireSchema( {"post_submission": { "view_response": True }}) view_submitted_response = ViewSubmittedResponse( schema, questionnaire_store, language) assert view_submitted_response.has_expired is False
def test_returns_ordered_map(self): questionnaire = { 'sections': [{ 'id': 'section1', 'groups': [{ 'id': 'group1', 'blocks': [{ 'id': 'block1', 'questions': [{ 'id': 'question1', 'answers': [{ 'id': 'answer1', 'type': 'TextArea' }] }] }] }] }] } schema = QuestionnaireSchema(questionnaire) answer = Answer( answer_id='answer1', group_instance=1, value=25, ) for i in range(0, 100): answer.answer_instance = i self.store.add(answer) last_instance = -1 self.assertEqual(len(self.store.answers), 100) mapped = get_mapped_answers(schema, self.store, block_id='block1', group_instance=1) for key, _ in mapped.items(): pos = key.find('_') instance = 0 if pos == -1 else int(key[pos + 1:]) self.assertGreater(instance, last_instance) last_instance = instance
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, QuestionnaireSchema(questionnaire), AnswerStore(user_answer), {}) self.assertFalse(answer_object['flushed'])
def test_case_ref_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_ref'], self.metadata['case_ref'])
def test_converter_raises_runtime_error_for_unsupported_version(self): with self._app.test_request_context(): questionnaire = {'survey_id': '021', 'data_version': '-0.0.1'} with self.assertRaises(DataVersionError) as err: convert_answers(self.metadata, QuestionnaireSchema(questionnaire), AnswerStore(), {}) self.assertEqual(str(err.exception), 'Data version -0.0.1 not supported')
def test_converter_raises_runtime_error_for_unsupported_version( fake_questionnaire_store, ): questionnaire = {"survey_id": "021", "data_version": "-0.0.1"} with pytest.raises(DataVersionError) as err: convert_answers( QuestionnaireSchema(questionnaire), fake_questionnaire_store, {} ) assert "Data version -0.0.1 not supported" in str(err.value)
def test_ref_period_end_date_is_not_in_output(self): with self._app.test_request_context(): user_answer = [create_answer('GHI', 0)] questionnaire = {'survey_id': '021', 'data_version': '0.0.2'} self.metadata['ref_p_end_date'] = None answer_object = convert_answers(self.metadata, self.collection_metadata, QuestionnaireSchema(questionnaire), AnswerStore(user_answer), {}) self.assertFalse( 'ref_period_end_date' in answer_object['metadata']) del self.metadata['ref_p_end_date'] answer_object = convert_answers(self.metadata, self.collection_metadata, QuestionnaireSchema(questionnaire), AnswerStore(user_answer), {}) self.assertFalse( 'ref_period_end_date' in answer_object['metadata'])
def test_should_repeat_for_answer_until(self): questionnaire = { 'survey_id': '021', 'data_version': '0.0.1', 'sections': [{ 'id': 'section1', 'groups': [ { 'id': 'group-1', 'blocks': [ { 'id': 'block-1', 'questions': [{ 'id': 'question-2', 'answers': [ { 'id': 'my_answer', 'type': 'TextField' } ] }] } ] } ] }] } schema = QuestionnaireSchema(questionnaire) # Given repeat = { 'type': 'until', 'when': [ { 'id': 'my_answer', 'condition': 'equals', 'value': 'Done' } ] } answer_store = AnswerStore({}) current_path = [Location('group-1', 0, 'block-1')] answer_on_path = get_answer_ids_on_routing_path(schema, current_path) self.assertEqual(evaluate_repeat(repeat, answer_store, answer_on_path), 1) answer_store.add(Answer(answer_id='my_answer', value='Not Done', group_instance=0)) self.assertEqual(evaluate_repeat(repeat, answer_store, answer_on_path), 2) answer_store.add(Answer(answer_id='my_answer', value='Done', group_instance=1)) self.assertEqual(evaluate_repeat(repeat, answer_store, answer_on_path), 2)
def test_path_finder_instantiated_once(self, mock_path_finder, _, __, ___): g.schema = QuestionnaireSchema({}) # Werkzeug LocalProxy only instantiates an object on # attribute access. We use an example of a fake # method call to check the mock (which will be the PathFinder # class outside of this test) is only called once. with self.app_request_context(): path_finder.some_method_call() path_finder.some_method_call() self.assertEqual(1, len(mock_path_finder.mock_calls))
def test_group_has_questions_returns_false_when_group_doesnt_have_questionnaire_blocks(self): survey_json = { 'sections': [{ 'id': 'section1', 'groups': [{ 'id': 'non-question-group', 'blocks': [ { 'id': 'summary-block', 'type': 'Summary' } ] }] }] } schema = QuestionnaireSchema(survey_json) has_questions = schema.group_has_questions('non-question-group') self.assertFalse(has_questions)
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_is_confirmation(self): survey_json = { 'sections': [{ 'id': 'section-1', 'groups': [{ 'id': 'group-1', 'blocks': [ { 'id': 'block-1', 'type': 'Confirmation' } ] }] }] } schema = QuestionnaireSchema(survey_json) self.assertTrue(schema.is_confirmation_section(schema.get_section('section-1'))) self.assertTrue(schema.is_confirmation_group(schema.get_group('group-1'))) self.assertFalse(schema.is_summary_section(schema.get_section('section-1'))) self.assertFalse(schema.is_summary_group(schema.get_group('group-1')))
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"
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"
def test_started_at_should_be_set_in_payload_if_present_in_collection_metadata( self): with self._app.test_request_context(): questionnaire = {'survey_id': '021', 'data_version': '0.0.2'} answer_object = convert_answers(self.metadata, self.collection_metadata, QuestionnaireSchema(questionnaire), AnswerStore(), {}) self.assertEqual(answer_object['started_at'], self.collection_metadata['started_at'])
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, self.collection_metadata, QuestionnaireSchema(questionnaire), AnswerStore(user_answer), {}, flushed=True) self.assertTrue(answer_object['flushed'])
def test_started_at_should_not_be_set_in_payload_if_absent_in_metadata( self): with self._app.test_request_context(): questionnaire = {'survey_id': '021', 'data_version': '0.0.2'} metadata_copy = copy.copy(self.metadata) del metadata_copy['started_at'] answer_object = convert_answers(metadata_copy, QuestionnaireSchema(questionnaire), AnswerStore(), {}) self.assertFalse('started_at' in answer_object)
def test_repeat_with_answer_count_minus_one_added_to_dependencies(self): survey_json = { 'sections': [{ 'id': 'default-section', 'groups': [ { 'id': 'driving-group', 'blocks': [{ 'type': 'Question', 'id': 'driving-block', 'questions': [{ 'id': 'driving-question', 'type': 'General', 'answers': [{ 'id': 'driving-answer', 'type': 'TextField' }] }] }] }, { 'id': 'dependent-group', 'routing_rules': [{ 'repeat': { 'type': 'answer_count_minus_one', 'answer_id': 'driving-answer' } }], 'blocks': [{ 'type': 'Question', 'id': 'dependent-block', 'questions': [{ 'id': 'dependent-question', 'type': 'General', 'answers': [{ 'id': 'dependent-answer', 'type': 'TextField' }] }] }] }] }] } schema = QuestionnaireSchema(survey_json) dependencies = get_group_dependencies(schema) self.assertEqual(len(dependencies), 1) self.assertEqual(dependencies['dependent-group'], ['driving-block']) self.assertEqual(dependencies['group_drivers'], []) self.assertEqual(dependencies['block_drivers'], ['driving-block'])
def test_ref_period_start_and_end_date_is_in_output(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), {}) self.assertEqual( answer_object['metadata']['ref_period_start_date'], '2016-02-02') self.assertEqual(answer_object['metadata']['ref_period_end_date'], '2016-03-03')
def test_submitted_at_should_be_set_in_payload(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), {}) self.assertLess( datetime.now(timezone.utc) - dateutil.parser.parse(answer_object['submitted_at']), timedelta(seconds=5))
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"