def test_routing_path_empty_routing_rules(self):
        schema = load_schema_from_name("test_checkbox")
        section_id = schema.get_section_id_for_block_id("mandatory-checkbox")
        expected_path = RoutingPath(
            ["mandatory-checkbox", "non-mandatory-checkbox", "summary"],
            section_id="default-section",
        )

        answer_1 = Answer(answer_id="mandatory-checkbox-answer", value="Cheese")
        answer_2 = Answer(answer_id="non-mandatory-checkbox-answer", value="deep pan")

        answer_store = AnswerStore()
        answer_store.add_or_update(answer_1)
        answer_store.add_or_update(answer_2)

        progress_store = ProgressStore(
            [
                {
                    "section_id": "default-section",
                    "list_item_id": None,
                    "status": CompletionStatus.COMPLETED,
                    "block_ids": ["mandatory-checkbox"],
                }
            ]
        )

        path_finder = PathFinder(
            schema, answer_store, self.list_store, progress_store, self.metadata
        )
        routing_path = path_finder.routing_path(section_id=section_id)

        self.assertEqual(routing_path, expected_path)
    def test_minimum_and_maximum_offset_dates(self, mock1):
        test_metadata = {'date': '2018-02-20'}
        store = AnswerStore()

        test_answer_id = Answer(
            answer_id='date',
            answer_instance=1,
            group_instance=0,
            value='2018-03-20',
        )
        store.add_or_update(test_answer_id)

        answer = {
            'id': 'date_answer',
            'type': 'Date',
            'minimum': {
                'meta': 'date',
                'offset_by': {
                    'days': -10
                }
            },
            'maximum': {
                'answer_id': 'date',
                'offset_by': {
                    'years': 1
                }
            }
        }

        offset_dates = get_dates_for_single_date_period_validation(
            answer, store, metadata=test_metadata)

        self.assertEqual(offset_dates, (convert_to_datetime('2018-02-10'),
                                        convert_to_datetime('2019-03-20')))
Пример #3
0
    def test_bespoke_message_for_sum_validation(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")

            question_schema["validation"] = {
                "messages": {
                    "TOTAL_SUM_NOT_EQUALS": "Test Message"
                }
            }

            data = {"breakdown-1": "3", "breakdown-2": "5"}

            form = generate_form(schema,
                                 question_schema,
                                 store,
                                 metadata=None,
                                 formdata=data)

            with patch(
                    "app.questionnaire.questionnaire_schema.QuestionnaireSchema.get_all_questions_for_block",
                    return_value=[question_schema],
            ):
                form.validate()
                self.assertIn(form.question_errors["breakdown-question"],
                              "Test Message")
    def test_get_routing_path_when_first_block_in_group_skipped(self):
        # Given
        schema = load_schema_from_name("test_skip_condition_group")
        answer_store = AnswerStore()
        answer_store.add_or_update(
            Answer(answer_id="do-you-want-to-skip-answer", value="Yes")
        )

        # When
        path_finder = PathFinder(
            schema, answer_store, self.list_store, self.progress_store, self.metadata
        )

        # Then
        expected_route = [
            {
                "block_id": "do-you-want-to-skip-block",
                "group_id": "do-you-want-to-skip-group",
            },
            {"block_id": "summary", "group_id": "should-skip-group"},
        ]

        section_id = schema.get_section_id_for_block_id("summary")
        pytest.xfail(
            reason="Known bug when skipping last group due to summary bundled into it"
        )

        self.assertEqual(
            path_finder.routing_path(section_id=section_id), expected_route
        )
Пример #5
0
def relationship_answer_store():
    answer_store = AnswerStore()

    answer_store.add_or_update(
        Answer(
            answer_id="relationship-answer",
            value=[
                {
                    "list_item_id": "abc123",
                    "to_list_item_id": "xyz987",
                    "relationship": "Husband or Wife",
                },
                {
                    "list_item_id": "abc123",
                    "to_list_item_id": "123abc",
                    "relationship": "Son or Daughter",
                },
                {
                    "list_item_id": "xyz987",
                    "to_list_item_id": "123abc",
                    "relationship": "Son or Daughter",
                },
            ],
        ))

    return answer_store
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_transform_variants_with_question_variants(question_variant_schema):
    schema = QuestionnaireSchema(question_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, transformed_block, "Question 1, 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, transformed_block, "Question 1, Yes")
Пример #9
0
    def test_generate_form_with_title_and_no_answer_label(self):
        """
        Checks that the form is still generated when there is no answer label but there is a question title
        """
        store = AnswerStore()

        conditional_answer = Answer(answer_id="behalf-of-answer", value="chad")

        store.add_or_update(conditional_answer)

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

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

            data = {"feeling-answer": "good"}

            expected_form_data = {"csrf_token": "", "feeling-answer": "good"}

            with patch("app.questionnaire.path_finder.evaluate_goto",
                       return_value=False):
                form = generate_form(schema,
                                     question_schema,
                                     store,
                                     metadata={},
                                     formdata=data)

            form.validate()
            assert form.data == expected_form_data
Пример #10
0
    def test_routing_ignores_answers_not_on_path(self):
        when = {
            'when': [{
                'id': 'some-answer',
                'condition': 'equals',
                'value': 'some value'
            }]
        }
        answer_store = AnswerStore({})
        answer_store.add_or_update(
            Answer(
                answer_id='some-answer',
                value='some value',
                group_instance=0,
            ))

        routing_path = [Location('test', 0, 'test_block_id')]
        with patch('app.questionnaire.rules._get_answers_on_path',
                   return_value=answer_store):
            self.assertTrue(
                evaluate_when_rules(when['when'], get_schema_mock(), {},
                                    answer_store, 0, None))

        with patch('app.questionnaire.rules._is_answer_on_path',
                   return_value=False):
            self.assertFalse(
                evaluate_when_rules(when['when'],
                                    get_schema_mock(), {},
                                    answer_store,
                                    0,
                                    None,
                                    routing_path=routing_path))
Пример #11
0
    def test_evaluate_goto_returns_true_when_answer_value_not_equals_any_match_values(
            self):

        goto = {
            "id":
            "next-question",
            "when": [{
                "id": "my_answers",
                "condition": "not equals any",
                "values": ["answer1", "answer2"],
            }],
        }
        answer_store = AnswerStore()
        answer_store.add_or_update(
            Answer(answer_id="my_answers", value="answer3"))

        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_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"))

        current_location = Location(section_id="some-section",
                                    block_id="some-block")

        self.assertFalse(
            evaluate_goto(
                goto_rule=goto_rule,
                schema=get_schema_mock(),
                metadata={},
                answer_store=answer_store,
                list_store=ListStore(),
                current_location=current_location,
            ))
Пример #13
0
    def test_meta_comparison_missing(self):
        # Given
        goto_rule = {
            "id":
            "next-question",
            "when": [{
                "condition": "equals",
                "meta": "variant_flags.does_not_exist.does_not_exist",
                "value": True,
            }],
        }
        answer_store = AnswerStore()
        answer_store.add_or_update(Answer(answer_id="my_answer", value="Yes"))
        metadata = {"varient_flags": {"sexual_identity": True}}

        current_location = Location(section_id="some-section",
                                    block_id="some-block")

        self.assertFalse(
            evaluate_goto(
                goto_rule=goto_rule,
                schema=get_schema(),
                metadata=metadata,
                answer_store=answer_store,
                list_store=ListStore(),
                current_location=current_location,
            ))
Пример #14
0
    def test_evaluate_when_rules_condition_is_not_met(self):
        # Given
        answer_1 = Answer(
            answer_id='my_answers',
            answer_instance=0,
            group_instance=0,
            value=10,
        )
        answer_2 = Answer(
            answer_id='my_answers',
            answer_instance=1,
            group_instance=0,
            value=20,
        )
        answer_store = AnswerStore({})
        answer_store.add_or_update(answer_1)
        answer_store.add_or_update(answer_2)

        when = {
            'id': 'next-question',
            'when': [{
                'id': 'my_answers',
                'condition': 'not set',
                'value': '2'
            }]
        }

        # When
        with self.assertRaises(Exception) as err:
            evaluate_when_rules(when['when'], get_schema_mock(), None,
                                answer_store, 0, None)
        self.assertEqual(
            'Multiple answers (2) found evaluating when rule for answer (my_answers)',
            str(err.exception))
Пример #15
0
    def test_evaluate_skip_condition_returns_false_when_both_or_rules_false(
            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_or_update(
            Answer(answer_id='this', value='not correct'))
        answer_store.add_or_update(
            Answer(answer_id='that', value='not correct'))

        # When
        condition = evaluate_skip_conditions(skip_conditions,
                                             get_schema_mock(), {},
                                             answer_store)

        # Then
        self.assertFalse(condition)
Пример #16
0
    def test_should_not_go_to_next_question_when_second_condition_fails(self):
        # Given
        goto_rule = {
            'id':
            'next-question',
            'when': [{
                'id': 'my_answer',
                'condition': 'equals',
                'value': 'Yes'
            }, {
                'condition': 'equals',
                'meta': 'sexual_identity',
                'value': False
            }]
        }
        answer_store = AnswerStore({})
        answer_store.add_or_update(Answer(answer_id='my_answer', value='Yes'))
        metadata = {'sexual_identity': True}

        # When
        goto = evaluate_goto(goto_rule, get_schema_mock(), metadata,
                             answer_store, 0)

        # Then
        self.assertFalse(goto)
Пример #17
0
    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_or_update(Answer(answer_id='this', value='value'))
        answer_store.add_or_update(
            Answer(answer_id='that', value='other value'))

        # When
        condition = evaluate_skip_conditions(skip_conditions,
                                             get_schema_mock(), {},
                                             answer_store)

        # Then
        self.assertTrue(condition)
Пример #18
0
    def test_should_not_go_to_next_question_when_second_condition_fails(self):
        # Given
        goto_rule = {
            "id":
            "next-question",
            "when": [
                {
                    "id": "my_answer",
                    "condition": "equals",
                    "value": "Yes"
                },
                {
                    "condition": "equals",
                    "meta": "sexual_identity",
                    "value": False
                },
            ],
        }
        answer_store = AnswerStore()
        answer_store.add_or_update(Answer(answer_id="my_answer", value="Yes"))
        metadata = {"sexual_identity": True}

        current_location = Location(section_id="some-section",
                                    block_id="some-block")

        self.assertFalse(
            evaluate_goto(
                goto_rule=goto_rule,
                schema=get_schema(),
                metadata=metadata,
                answer_store=answer_store,
                list_store=ListStore(),
                current_location=current_location,
            ))
Пример #19
0
    def test_evaluate_when_rule_with_invalid_list_item_id(self):
        when = {
            "when": [{
                "id": "my_answer",
                "condition": "equals",
                "value": "an answer"
            }]
        }

        answer_store = AnswerStore()
        answer_store.add_or_update(
            Answer(answer_id="my_answer",
                   value="an answer",
                   list_item_id="abc123"))

        current_location = Location(section_id="some-section",
                                    block_id="some-block",
                                    list_item_id="123abc")

        schema = Mock(get_schema())
        schema.get_list_item_id_for_answer_id = Mock(return_value="123abc")

        self.assertFalse(
            evaluate_when_rules(
                when_rules=when["when"],
                schema=schema,
                metadata={},
                answer_store=answer_store,
                list_store=ListStore(),
                current_location=current_location,
            ))
def test_get_referenced_offset_value_with_list_item_id(app, schema_mock):
    list_item_id = "abcde"
    answer_store = AnswerStore()

    test_answer_id = Answer(answer_id="date",
                            value="2018-03-20",
                            list_item_id=list_item_id)

    location = Location(section_id="test", list_item_id=list_item_id)

    answer_store.add_or_update(test_answer_id)

    answer = {
        "maximum": {
            "value": {
                "identifier": "date",
                "source": "answers"
            },
            "offset_by": {
                "months": 1
            },
        }
    }

    handler = DateHandler(answer, answer_store=answer_store, location=location)
    maximum_date = handler.get_date_value("maximum")

    assert maximum_date == convert_to_datetime("2018-04-20")
Пример #21
0
    def test_answer_count_when_rule_equal_2(self):
        """Assert that an `answer_count` can be used in a when block and the
            value is correctly matched """
        answer_group_id = 'repeated-answer'
        when = [{
            'type': 'answer_count',
            'answer_ids': [answer_group_id],
            'condition': 'equals',
            'value': 2,
        }]

        answer_store = AnswerStore({})
        answer_store.add_or_update(
            Answer(
                answer_id=answer_group_id,
                group_instance=0,
                group_instance_id='group-1-0',
                value=10,
            ))
        answer_store.add_or_update(
            Answer(
                answer_id=answer_group_id,
                group_instance=1,
                group_instance_id='group-1-1',
                value=20,
            ))

        self.assertTrue(
            evaluate_when_rules(when, get_schema_mock(), {}, answer_store, 0,
                                None))
Пример #22
0
    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_or_update(Answer(answer_id="my_answer", value="No"))

        current_location = Location(section_id="some-section",
                                    block_id="some-block")

        self.assertFalse(
            evaluate_goto(
                goto_rule=goto_rule,
                schema=get_schema(),
                metadata={},
                answer_store=answer_store,
                list_store=ListStore(),
                current_location=current_location,
            ))
    def test_routing_path_with_conditional_path(self):
        schema = load_schema_from_name("test_routing_number_equals")
        section_id = schema.get_section_id_for_block_id("number-question")
        expected_path = RoutingPath(
            ["number-question", "correct-answer", "summary"],
            section_id="default-section",
        )

        answer = Answer(answer_id="answer", value=123)
        answer_store = AnswerStore()
        answer_store.add_or_update(answer)
        progress_store = ProgressStore(
            [
                {
                    "section_id": "default-section",
                    "list_item_id": None,
                    "status": CompletionStatus.COMPLETED,
                    "block_ids": ["number-question"],
                }
            ]
        )
        path_finder = PathFinder(
            schema, answer_store, self.list_store, progress_store, self.metadata
        )

        routing_path = path_finder.routing_path(section_id=section_id)

        self.assertEqual(routing_path, expected_path)
Пример #24
0
    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")

            data = {
                "breakdown-1": "",
                "breakdown-2": "",
                "breakdown-3": "",
                "breakdown-4": "",
            }

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

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

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

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

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

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

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

            self.assertEqual(
                form.question_errors["breakdown-question"],
                schema.error_messages["TOTAL_SUM_NOT_EQUALS"] %
                dict(total="10"),
            )
    def test_get_referenced_offset_value_for_answer_id(self, mock1):
        store = AnswerStore()

        test_answer_id = Answer(
            answer_id='date',
            answer_instance=1,
            group_instance=0,
            value='2018-03-20',
        )
        store.add_or_update(test_answer_id)

        answer_maximum = {'answer_id': 'date', 'offset_by': {'months': 1}}

        value = get_referenced_offset_value(answer_maximum, store, {})

        self.assertEqual(value, convert_to_datetime('2018-04-20'))
Пример #26
0
    def test_do_not_go_to_next_question_for_answer(self):
        # Given
        goto_rule = {
            'id': 'next-question',
            'when': [{
                'id': 'my_answer',
                'condition': 'equals',
                'value': 'Yes'
            }]
        }
        answer_store = AnswerStore({})

        answer_store.add_or_update(Answer(answer_id='my_answer', value='No'))

        self.assertFalse(
            evaluate_goto(goto_rule, get_schema_mock(), {}, answer_store, 0))
    def test_get_next_location_confirmation(self):
        answer = Answer(
            answer_id='character-answer',
            value='Orson Krennic',
        )
        answer_store = AnswerStore()
        answer_store.add_or_update(answer)

        schema = load_schema_from_params('0', 'rogue_one')
        navigator = PathFinder(schema, answer_store, {}, [])

        with patch('app.questionnaire.rules.evaluate_when_rules',
                   return_value=True):
            next_location = navigator.get_next_location(
                Location('rogue-one', 0, 'film-takings'))

        self.assertEqual('summary', next_location.block_id)
Пример #28
0
    def test_evaluate_goto_returns_true_when_value_not_contained_in_list(self):

        goto = {
            'id':
            'next-question',
            'when': [{
                'id': 'my_answers',
                'condition': 'not contains',
                'value': 'answer1'
            }]
        }
        answer_store = AnswerStore({})
        answer_store.add_or_update(
            Answer(answer_id='my_answers', value=['answer2', 'answer3']))

        self.assertTrue(
            evaluate_goto(goto, get_schema_mock(), {}, answer_store, 0))
Пример #29
0
    def test_should_minus_one_from_maximum_repeats(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 = {'answer_id': 'my_answer', 'type': 'answer_count_minus_one'}
        answer_store = AnswerStore({})
        for i in range(27):
            answer_store.add_or_update(
                Answer(answer_id='my_answer', value='3', answer_instance=i))

        current_path = [Location('group-1', 0, 'block-1')]

        # When
        number_of_repeats = evaluate_repeat(repeat, answer_store, schema,
                                            current_path)

        self.assertEqual(number_of_repeats, 24)
Пример #30
0
    def test_routing_ignores_answers_not_on_path(self):
        when = {
            "when": [{
                "id": "some-answer",
                "condition": "equals",
                "value": "some value"
            }]
        }
        answer_store = AnswerStore()
        answer_store.add_or_update(
            Answer(answer_id="some-answer", value="some value"))

        routing_path = [
            Location(section_id="some-section", block_id="test_block_id")
        ]
        current_location = Location(section_id="some-section",
                                    block_id="some-block")

        self.assertTrue(
            evaluate_when_rules(
                when_rules=when["when"],
                schema=get_schema(),
                metadata={},
                answer_store=answer_store,
                list_store=ListStore(),
                current_location=current_location,
            ))

        current_location = Location(section_id="some-section",
                                    block_id="some-block")

        with patch("app.questionnaire.rules._is_answer_on_path",
                   return_value=False):
            self.assertFalse(
                evaluate_when_rules(
                    when_rules=when["when"],
                    schema=get_schema(),
                    metadata={},
                    answer_store=answer_store,
                    list_store=ListStore(),
                    current_location=current_location,
                    routing_path_block_ids=routing_path,
                ))