Example #1
0
def get_block(eq_id, form_type, collection_id, group_id, group_instance, block_id):  # pylint: disable=unused-argument
    # Filter answers down to those we may need to render
    answer_store = get_answer_store(current_user)
    path_finder = PathFinder(g.schema_json, answer_store, get_metadata(current_user))

    current_location = Location(group_id, group_instance, block_id)

    valid_group = group_id in SchemaHelper.get_group_ids(g.schema_json)

    if not valid_group or current_location not in path_finder.get_routing_path(group_id, group_instance):
        raise NotFound

    block = _render_schema(current_location)

    error_messages = SchemaHelper.get_messages(g.schema_json)
    form, template_params = get_form_for_location(block, current_location, answer_store, error_messages)

    content = {'form': form, 'block': block}

    if template_params:
        content.update(template_params)

    template = block['type'] if block and 'type' in block and block['type'] else 'questionnaire'

    return _build_template(current_location, content, template)
    def test_child_answers_define_parent(self):
        for schema_file in self.all_schema_files():
            with open(schema_file, encoding="utf8") as file:
                schema_json = load(file)

                for block in SchemaHelper.get_blocks(schema_json):
                    answers_by_id = SchemaHelper.get_answers_by_id_for_block(
                        block)

                    for answer_id, answer in answers_by_id.items():
                        if answer['type'] in ['Radio', 'Checkbox']:
                            child_answer_ids = (o['child_answer_id']
                                                for o in answer['options']
                                                if 'child_answer_id' in o)

                            for child_answer_id in child_answer_ids:
                                if child_answer_id not in answers_by_id:
                                    self.fail(
                                        "Child answer with id '%s' does not exist in schema %s"
                                        % (child_answer_id, schema_file))
                                if 'parent_answer_id' not in answers_by_id[
                                        child_answer_id]:
                                    self.fail(
                                        "Child answer '%s' does not define parent_answer_id '%s' in schema %s"
                                        % (child_answer_id, answer_id,
                                           schema_file))
                                if answers_by_id[child_answer_id][
                                        'parent_answer_id'] != answer_id:
                                    self.fail(
                                        "Child answer '%s' defines incorrect parent_answer_id '%s' in schema %s: "
                                        "Should be '%s" %
                                        (child_answer_id,
                                         answers_by_id[child_answer_id]
                                         ['parent_answer_id'], schema_file,
                                         answer_id))
Example #3
0
def convert_answers_to_data(answer_store, questionnaire_json, routing_path):
    """
    Convert answers into the data format below
    "data": {
          "001": "01-01-2016",
          "002": "30-03-2016"
        }
    :param answer_store: questionnaire answers
    :param questionnaire_json: The survey json
    :param routing_path: the path followed in the questionnaire
    :return: data in a formatted form
    """
    data = OrderedDict()
    for location in routing_path:
        answers_in_block = answer_store.filter(location=location)
        block_json = SchemaHelper.get_block(questionnaire_json, location.block_id)
        answer_schema_list = SchemaHelper.get_answers_by_id_for_block(block_json)

        for answer in answers_in_block:
            answer_schema = answer_schema_list[answer['answer_id']]
            value = answer['value']

            if answer_schema is not None and value is not None:
                if answer_schema['type'] != 'Checkbox' or any('q_code' not in option for option in answer_schema['options']):
                    data[answer_schema['q_code']] = _get_answer_data(data, answer_schema['q_code'], value)
                else:
                    data.update(_get_checkbox_answer_data(answer_schema, value))
    return data
    def test_post_form_for_household_composition(self):

        survey = load_schema_file("census_household.json")

        block_json = SchemaHelper.get_block(survey, 'household-composition')
        location = Location('who-lives-here', 0, 'household-composition')
        error_messages = SchemaHelper.get_messages(survey)

        form, _ = post_form_for_location(
            block_json, location, AnswerStore(), {
                'household-0-first-name': 'Joe',
                'household-0-last-name': '',
                'household-1-first-name': 'Bob',
                'household-1-last-name': 'Seymour',
            }, error_messages)

        self.assertEqual(len(form.household.entries), 2)
        self.assertEqual(form.household.entries[0].data, {
            'first-name': 'Joe',
            'middle-names': '',
            'last-name': ''
        })
        self.assertEqual(form.household.entries[1].data, {
            'first-name': 'Bob',
            'middle-names': '',
            'last-name': 'Seymour'
        })
    def test_form_date_range_populates_data(self):
        with self.test_request_context():
            survey = load_schema_file("1_0102.json")

            block_json = SchemaHelper.get_block(survey, "reporting-period")
            error_messages = SchemaHelper.get_messages(survey)

            data = {
                'period-from-day': '01',
                'period-from-month': '3',
                'period-from-year': '2016',
                'period-to-day': '31',
                'period-to-month': '3',
                'period-to-year': '2016'
            }

            expected_form_data = {
                'csrf_token': '',
                'period-from': {
                    'day': '01',
                    'month': '3',
                    'year': '2016'
                },
                'period-to': {
                    'day': '31',
                    'month': '3',
                    'year': '2016'
                }
            }
            form = generate_form(block_json, data, error_messages)

            self.assertEqual(form.data, expected_form_data)
Example #6
0
    def setUp(self):
        super().setUp()

        survey = load_schema_file("census_household.json")
        self.block_json = SchemaHelper.get_block(survey,
                                                 'household-composition')
        self.error_messages = SchemaHelper.get_messages(survey)
    def test_get_form_deserialises_month_year_dates(self):
        survey = load_schema_file("test_dates.json")

        block_json = SchemaHelper.get_block(survey, "date-block")
        location = SchemaHelper.get_first_location(survey)
        error_messages = SchemaHelper.get_messages(survey)

        form, _ = get_form_for_location(
            block_json, location,
            AnswerStore([{
                'answer_id': 'month-year-answer',
                'group_id': 'a23d36db-6b07-4ce0-94b2-a843369511e3',
                'group_instance': 0,
                'block_id': 'date-block',
                'value': '05/2015',
                'answer_instance': 0,
            }]), error_messages)

        self.assertTrue(hasattr(form, "month-year-answer"))

        month_year_field = getattr(form, "month-year-answer")

        self.assertEquals(month_year_field.data, {
            'month': '5',
            'year': '2015',
        })
    def test_post_form_for_radio_other_selected(self):
        with self.test_request_context():
            survey = load_schema_file("test_radio.json")

            block_json = SchemaHelper.get_block(survey, 'radio-mandatory')
            location = Location('radio', 0, 'radio-mandatory')
            error_messages = SchemaHelper.get_messages(survey)

            answer_store = AnswerStore([{
                'answer_id': 'radio-mandatory-answer',
                'block_id': 'radio-mandatory',
                'value': 'Other',
                'answer_instance': 0,
            }, {
                'answer_id': 'other-answer-mandatory',
                'block_id': 'block-1',
                'value': 'Other text field value',
                'answer_instance': 0,
            }])

            radio_answer = SchemaHelper.get_first_answer_for_block(block_json)
            text_answer = 'other-answer-mandatory'

            form, _ = post_form_for_location(
                block_json, location, answer_store,
                MultiDict({
                    '{answer_id}'.format(answer_id=radio_answer['id']):
                    'Other',
                    '{answer_id}'.format(answer_id=text_answer):
                    'Other text field value',
                }), error_messages)

            other_text_field = getattr(form, 'other-answer-mandatory')
            self.assertEqual(other_text_field.data, 'Other text field value')
Example #9
0
    def test_generate_relationship_form_errors_are_correctly_mapped(self):
        with self.test_request_context():
            survey = load_schema_file("test_relationship_household.json")
            block_json = SchemaHelper.get_block(survey, 'relationships')
            error_messages = SchemaHelper.get_messages(survey)

            answer = SchemaHelper.get_first_answer_for_block(block_json)

            generated_form = generate_relationship_form(
                block_json, 3, None, error_messages=error_messages)

            form = generate_relationship_form(
                block_json,
                3, {
                    'csrf_token': generated_form.csrf_token.current_token,
                    '{answer_id}-0'.format(answer_id=answer['id']): '1',
                    '{answer_id}-1'.format(answer_id=answer['id']): '3',
                },
                error_messages=error_messages)

            form.validate()
            mapped_errors = form.map_errors()

            message = "Not a valid choice"

            self.assertTrue(
                self._error_exists(answer['id'], message, mapped_errors))
Example #10
0
    def test_generate_relationship_form_creates_form_from_data(self):
        with self.test_request_context():
            survey = load_schema_file("test_relationship_household.json")
            block_json = SchemaHelper.get_block(survey, 'relationships')
            error_messages = SchemaHelper.get_messages(survey)

            answer = SchemaHelper.get_first_answer_for_block(block_json)

            form = generate_relationship_form(
                block_json,
                3, {
                    '{answer_id}-0'.format(answer_id=answer['id']):
                    'Husband or Wife',
                    '{answer_id}-1'.format(answer_id=answer['id']):
                    'Brother or Sister',
                    '{answer_id}-2'.format(answer_id=answer['id']):
                    'Relation - other',
                },
                error_messages=error_messages)

            self.assertTrue(hasattr(form, answer['id']))

            expected_form_data = [
                'Husband or Wife', 'Brother or Sister', 'Relation - other'
            ]
            self.assertEqual(form.data[answer['id']], expected_form_data)
Example #11
0
    def get_location_path(self, group_id=None, group_instance=0):
        """
        Returns a list of url locations visited based on answers provided
        :return: List of block location dicts, with preceeding/closing interstitial pages included
        """
        if group_id is None:
            group_id = SchemaHelper.get_first_group_id(self.survey_json)

        routing_path = self.get_routing_path(group_id, group_instance)
        can_reach_summary = self.can_reach_summary(routing_path)

        location_path = [
            Location(group_id, 0, block_id)
            for block_id in self.preceeding_path
        ]

        location_path += routing_path

        if can_reach_summary:
            for block_id in PathFinder.CLOSING_INTERSTITIAL_PATH:
                location_path.append(
                    Location(SchemaHelper.get_last_group_id(self.survey_json),
                             0, block_id))

        return location_path
Example #12
0
    def get_blocks(self):
        blocks = []

        for group in SchemaHelper.get_groups(self.survey_json):
            if 'skip_condition' in group:
                skip = evaluate_skip_condition(group['skip_condition'],
                                               self.metadata,
                                               self.answer_store)
                if skip:
                    continue

            no_of_repeats = 1
            repeating_rule = SchemaHelper.get_repeat_rule(group)

            if repeating_rule:
                no_of_repeats = evaluate_repeat(repeating_rule,
                                                self.answer_store)

            for i in range(0, no_of_repeats):
                for block in group['blocks']:
                    if 'skip_condition' in block:
                        skip = evaluate_skip_condition(block['skip_condition'],
                                                       self.metadata,
                                                       self.answer_store)
                        if skip:
                            continue

                    blocks.append({
                        "group_id": group['id'],
                        "group_instance": i,
                        "block": block,
                    })
        return blocks
Example #13
0
def _render_schema(current_location):
    metadata = get_metadata(current_user)
    answer_store = get_answer_store(current_user)
    block_json = SchemaHelper.get_block_for_location(g.schema_json, current_location)
    block_json = _evaluate_skip_conditions(block_json, current_location, answer_store, metadata)
    aliases = SchemaHelper.get_aliases(g.schema_json)
    block_context = build_schema_context(metadata, aliases, answer_store, current_location.group_instance)
    return renderer.render(block_json, **block_context)
Example #14
0
def _remove_repeating_on_household_answers(answer_store, group_id):
    answer_store.remove(group_id=group_id, block_id='household-composition')
    questionnaire_store = get_questionnaire_store(current_user.user_id, current_user.user_ik)
    for answer in SchemaHelper.get_answers_that_repeat_in_block(g.schema_json, 'household-composition'):
        groups_to_delete = SchemaHelper.get_groups_that_repeat_with_answer_id(g.schema_json, answer['id'])
        for group in groups_to_delete:
            answer_store.remove(group_id=group['id'])
            questionnaire_store.completed_blocks[:] = [b for b in questionnaire_store.completed_blocks if
                                                       b.group_id != group['id']]
    def setUp(self):
        self.app = create_app()
        self.app.config['SERVER_NAME'] = "test"
        self.app_context = self.app.app_context()
        self.app_context.push()

        survey = load_schema_file("census_household.json")
        self.block_json = SchemaHelper.get_block(survey, 'household-composition')
        self.error_messages = SchemaHelper.get_messages(survey)
Example #16
0
    def build_navigation(self, current_group_id, current_group_instance):
        """
        Build navigation based on the current group/instance selected

        :param current_group_id:
        :param current_group_instance:
        :return:
        """
        if self.survey_json.get('navigation', False) is False:
            return None

        navigation = []

        last_group_id = SchemaHelper.get_last_group_id(self.survey_json)

        for group in filter(lambda x: 'hide_in_navigation' not in x,
                            self.survey_json['groups']):
            logger.debug("building frontend navigation", group_id=group['id'])

            first_location = Location(group['id'], 0, group['blocks'][0]['id'])
            last_block_in_group = SchemaHelper.get_last_block_in_group(group)

            is_summary_or_confirm_group = last_block_in_group and \
                SchemaHelper.is_summary_or_confirmation(last_block_in_group)

            last_block_location = Location(group['id'], 0,
                                           last_block_in_group['id'])
            can_get_to_summary = is_summary_or_confirm_group and self.routing_path and \
                last_block_location in self.routing_path

            skip_group = self._should_skip_group(current_group_instance, group)
            if not skip_group:
                repeating_rule = SchemaHelper.get_repeat_rule(group)
                if repeating_rule:
                    logger.debug("building repeating navigation",
                                 group_id=group['id'])
                    navigation.extend(
                        self._build_repeating_navigation(
                            repeating_rule, group, current_group_id,
                            current_group_instance))
                elif last_group_id == group['id'] and can_get_to_summary:
                    logger.debug("building navigation", group_id=group['id'])
                    if len(self.completed_blocks) > 0 and set(
                            self.routing_path[:-1]).issubset(
                                self.completed_blocks):
                        navigation.append(
                            self._build_single_navigation(
                                group, current_group_id, first_location))
                elif last_group_id != group[
                        'id'] and not is_summary_or_confirm_group:
                    logger.debug("building navigation", group_id=group['id'])
                    navigation.append(
                        self._build_single_navigation(group, current_group_id,
                                                      first_location))

        return navigation
    def test_form_ids_match_block_answer_ids(self):
        survey = load_schema_file("1_0102.json")

        block_json = SchemaHelper.get_block(survey, "reporting-period")
        error_messages = SchemaHelper.get_messages(survey)

        form = generate_form(block_json, {}, error_messages)

        for answer in SchemaHelper.get_answers_for_block(block_json):
            self.assertTrue(hasattr(form, answer['id']))
Example #18
0
    def test_get_repeating_rule(self):
        survey = load_schema_file("test_repeating_household.json")
        groups = [group for group in SchemaHelper.get_groups(survey)]
        rule = SchemaHelper.get_repeat_rule(groups[1])

        self.assertEqual(
            {
                'type': 'answer_count',
                'answer_id': 'first-name',
                'navigation_label_answer_ids': ['first-name', 'last-name'],
            }, rule)
    def test_option_has_other(self):
        with self.test_request_context():
            survey = load_schema_file("test_checkbox.json")
            block_json = SchemaHelper.get_block(survey, "mandatory-checkbox")
            error_messages = SchemaHelper.get_messages(survey)

            form = generate_form(block_json, {}, error_messages)

            self.assertFalse(
                form.option_has_other("mandatory-checkbox-answer", 1))
            self.assertTrue(
                form.option_has_other("mandatory-checkbox-answer", 6))
Example #20
0
    def get_routing_path(self, group_id=None, group_instance=0):
        """
        Returns a list of the block ids visited based on answers provided
        :return: List of block location dicts
        """
        if group_id is None:
            group_id = SchemaHelper.get_first_group_id(self.survey_json)

        first_block_in_group = SchemaHelper.get_first_block_id_for_group(
            self.survey_json, group_id)
        location = Location(group_id, group_instance, first_block_in_group)

        return self.build_path(self.get_blocks(), location)
    def test_generate_relationship_form_creates_empty_form(self):
        survey = load_schema_file("test_relationship_household.json")
        block_json = SchemaHelper.get_block(survey, 'relationships')
        error_messages = SchemaHelper.get_messages(survey)

        answer = SchemaHelper.get_first_answer_for_block(block_json)

        form = generate_relationship_form(block_json,
                                          3, {},
                                          error_messages=error_messages)

        self.assertTrue(hasattr(form, answer['id']))
        self.assertEqual(len(form.data[answer['id']]), 3)
    def test_get_other_answer_invalid(self):
        with self.test_request_context():
            survey = load_schema_file("test_checkbox.json")
            block_json = SchemaHelper.get_block(survey, "mandatory-checkbox")
            error_messages = SchemaHelper.get_messages(survey)

            form = generate_form(block_json,
                                 {"other-answer-mandatory": "Some data"},
                                 error_messages)

            field = form.get_other_answer("mandatory-checkbox-answer", 4)

            self.assertEqual(None, field)
Example #23
0
    def test_generate_month_year_date_form_creates_empty_form(self):
        survey = load_schema_file("test_dates.json")
        block_json = SchemaHelper.get_block(survey, 'date-block')
        error_messages = SchemaHelper.get_messages(survey)

        answers = SchemaHelper.get_answers_by_id_for_block(block_json)

        form = get_month_year_form(answers['month-year-answer'],
                                   error_messages=error_messages)

        self.assertFalse(hasattr(form, 'day'))
        self.assertTrue(hasattr(form, 'month'))
        self.assertTrue(hasattr(form, 'year'))
Example #24
0
    def test_get_parent_options_for_block(self):
        survey = load_schema_file("test_checkbox.json")
        block_json = SchemaHelper.get_block(survey, 'mandatory-checkbox')

        parent_options = SchemaHelper.get_parent_options_for_block(block_json)

        expected = {
            'mandatory-checkbox-answer': {
                'index': 6,
                'child_answer_id': 'other-answer-mandatory'
            }
        }

        self.assertEqual(parent_options, expected)
    def test_get_form_for_household_relationship(self):
        with self.test_request_context():
            survey = load_schema_file("census_household.json")

            block_json = SchemaHelper.get_block(survey,
                                                'household-relationships')
            location = Location('who-lives-here-relationship', 0,
                                'household-relationships')
            error_messages = SchemaHelper.get_messages(survey)

            answer_store = AnswerStore([{
                'group_id': 'who-lives-here-relationship',
                'group_instance': 0,
                'answer_id': 'first-name',
                'block_id': 'household-composition',
                'value': 'Joe',
                'answer_instance': 0,
            }, {
                'group_id': 'who-lives-here-relationship',
                'group_instance': 0,
                'answer_id': 'last-name',
                'block_id': 'household-composition',
                'value': 'Bloggs',
                'answer_instance': 0,
            }, {
                'group_id': 'who-lives-here-relationship',
                'group_instance': 1,
                'answer_id': 'first-name',
                'block_id': 'household-composition',
                'value': 'Jane',
                'answer_instance': 1,
            }, {
                'group_id': 'who-lives-here-relationship',
                'group_instance': 1,
                'answer_id': 'last-name',
                'block_id': 'household-composition',
                'value': 'Bloggs',
                'answer_instance': 1,
            }])
            form, _ = get_form_for_location(block_json, location, answer_store,
                                            error_messages)

            answer = SchemaHelper.get_first_answer_for_block(block_json)

            self.assertTrue(hasattr(form, answer['id']))

            field_list = getattr(form, answer['id'])

            # With two people, we need to define 1 relationship
            self.assertEqual(len(field_list.entries), 1)
    def test_answer_with_child_inherits_mandatory_from_parent(self):
        with self.test_request_context():
            survey = load_schema_file("test_radio.json")

            block_json = SchemaHelper.get_block(survey, "radio-mandatory")
            error_messages = SchemaHelper.get_messages(survey)

            form = generate_form(block_json,
                                 {'radio-mandatory-answer': 'Other'},
                                 error_messages)

            child_field = getattr(form, 'other-answer-mandatory')

            self.assertIsInstance(child_field.validators[0], ResponseRequired)
    def test_answer_with_child_inherits_mandatory_from_parent(self):
        survey = load_schema_file("test_radio.json")

        block_json = SchemaHelper.get_block(survey, "block-1")
        error_messages = SchemaHelper.get_messages(survey)

        form = generate_form(block_json,
                             {'ca3ce3a3-ae44-4e30-8f85-5b6a7a2fb23c': 'Other'},
                             error_messages)

        child_field = getattr(form, 'other-answer-mandatory')

        self.assertIsInstance(child_field.validators[0],
                              validators.InputRequired)
    def test_post_form_for_household_relationship(self):
        with self.test_request_context():
            survey = load_schema_file("census_household.json")

            block_json = SchemaHelper.get_block(survey,
                                                'household-relationships')
            location = Location('who-lives-here-relationship', 0,
                                'household-relationships')
            error_messages = SchemaHelper.get_messages(survey)

            answer_store = AnswerStore([{
                'answer_id': 'first-name',
                'block_id': 'household-composition',
                'value': 'Joe',
                'answer_instance': 0,
            }, {
                'answer_id': 'last-name',
                'block_id': 'household-composition',
                'value': 'Bloggs',
                'answer_instance': 0,
            }, {
                'answer_id': 'first-name',
                'block_id': 'household-composition',
                'value': 'Jane',
                'answer_instance': 1,
            }, {
                'answer_id': 'last-name',
                'block_id': 'household-composition',
                'value': 'Bloggs',
                'answer_instance': 1,
            }])

            answer = SchemaHelper.get_first_answer_for_block(block_json)

            form, _ = post_form_for_location(
                block_json, location, answer_store,
                MultiDict(
                    {'{answer_id}-0'.format(answer_id=answer['id']): '3'}),
                error_messages)

            self.assertTrue(hasattr(form, answer['id']))

            field_list = getattr(form, answer['id'])

            # With two people, we need to define 1 relationship
            self.assertEqual(len(field_list.entries), 1)

            # Check the data matches what was passed from request
            self.assertEqual(field_list.entries[0].data, "3")
    def test_answer_errors_are_mapped(self):
        survey = load_schema_file("1_0112.json")

        block_json = SchemaHelper.get_block(survey, "total-retail-turnover")
        error_messages = SchemaHelper.get_messages(survey)

        form = generate_form(block_json,
                             {'total-retail-turnover-answer': "-1"},
                             error_messages)

        form.validate()
        answer_errors = form.answer_errors('total-retail-turnover-answer')
        self.assertIn(
            "The value cannot be negative. Please correct your answer.",
            answer_errors)
Example #30
0
def get_page_title_for_location(schema_json, current_location):
    block = SchemaHelper.get_block_for_location(schema_json, current_location)
    if block['type'] == 'Interstitial':
        group = SchemaHelper.get_group(schema_json, current_location.group_id)
        page_title = '{group_title} - {survey_title}'.format(
            group_title=group['title'], survey_title=schema_json['title'])
    elif block['type'] == 'Questionnaire':
        first_question = next(SchemaHelper.get_questions_for_block(block))
        page_title = '{question_title} - {survey_title}'.format(
            question_title=first_question['title'],
            survey_title=schema_json['title'])
    else:
        page_title = schema_json['title']

    return TemplateRenderer.safe_content(page_title)