Beispiel #1
0
    def test_remove_all_answers_with_list_item_id(self):
        answer_store = AnswerStore(existing_answers=[
            {
                "answer_id": "test1",
                "value": 1,
                "list_item_id": "abcdef"
            },
            {
                "answer_id": "test2",
                "value": 2,
                "list_item_id": "abcdef"
            },
            {
                "answer_id": "test3",
                "value": 3,
                "list_item_id": "uvwxyz"
            },
        ])

        questionnaire_store = MagicMock(
            spec=QuestionnaireStore,
            completed_blocks=[],
            answer_store=answer_store,
            list_store=MagicMock(spec=ListStore),
            progress_store=ProgressStore(),
        )

        self.questionnaire_store_updater = QuestionnaireStoreUpdater(
            self.location, self.schema, questionnaire_store,
            self.current_question)
        self.questionnaire_store_updater.remove_list_item_and_answers(
            "abc", "abcdef")

        assert len(answer_store) == 1
        assert answer_store.get_answer("test3", "uvwxyz")
Beispiel #2
0
 def _deserialize(self, data):
     json_data = json.loads(data, use_decimal=True)
     self.progress_store = ProgressStore(json_data.get("PROGRESS"))
     self.set_metadata(json_data.get("METADATA", {}))
     self.answer_store = AnswerStore(json_data.get("ANSWERS"))
     self.list_store = ListStore.deserialize(json_data.get("LISTS"))
     self.collection_metadata = json_data.get("COLLECTION_METADATA", {})
def test_minimum_and_maximum_offset_dates(app, value_source_resolver, rule_evaluator):
    value_source_resolver.metadata = {"date": "2018-02-20"}
    answer_store = AnswerStore()

    test_answer_id = Answer(answer_id="date", value="2018-03-20")
    answer_store.add_or_update(test_answer_id)
    value_source_resolver.answer_store = answer_store
    answer = {
        "id": "date_answer",
        "type": "Date",
        "minimum": {
            "value": {"identifier": "date", "source": "metadata"},
            "offset_by": {"days": -10},
        },
        "maximum": {
            "value": {"identifier": "date", "source": "answers"},
            "offset_by": {"years": 1},
        },
    }

    handler = DateHandler(answer, value_source_resolver, rule_evaluator, error_messages)
    minimum_date = handler.get_date_value("minimum")
    maximum_date = handler.get_date_value("maximum")

    assert minimum_date == parse_datetime("2018-02-10")
    assert maximum_date == parse_datetime("2019-03-20")
    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,
            ))
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_detail_answer_mandatory_only_checked_if_option_selected(self):
        # The detail_answer can only be mandatory if the option it is associated with is answered
        with self.app_request_context():
            schema = load_schema_from_name("test_checkbox_detail_answer_multiple")

            question_schema = schema.get_block("mandatory-checkbox").get("question")

            #  Option is selected therefore the detail answer should be mandatory (schema defined)
            form = generate_form(
                schema,
                question_schema,
                AnswerStore(),
                metadata=None,
                form_data=MultiDict({"mandatory-checkbox-answer": "Your choice"}),
            )

            detail_answer_field = getattr(form, "your-choice-answer-mandatory")
            self.assertIsInstance(detail_answer_field.validators[0], ResponseRequired)

            #  Option not selected therefore the detail answer should not be mandatory
            form = generate_form(
                schema,
                question_schema,
                AnswerStore(),
                metadata=None,
                data={"mandatory-checkbox-answer": "Ham"},
            )

            detail_answer_field = getattr(form, "your-choice-answer-mandatory")
            self.assertEqual(detail_answer_field.validators, ())
Beispiel #7
0
    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,
            ))
Beispiel #8
0
    def test_evaluate_when_rule_fetches_answer_using_list_item_id(self):
        when = {
            "when": [{
                "id": "my_answer",
                "condition": "equals",
                "value": "an answer"
            }]
        }

        list_item_id = "abc123"

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

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

        schema = Mock(get_schema())
        schema.get_list_item_id_for_answer_id = Mock(return_value=list_item_id)

        self.assertTrue(
            evaluate_when_rules(
                when_rules=when["when"],
                schema=schema,
                metadata={},
                answer_store=answer_store,
                list_store=ListStore(),
                current_location=current_location,
            ))
Beispiel #9
0
    def test_new_routing_basic_and_conditional_path(self):
        # Given
        schema = load_schema_from_name("test_new_routing_number_equals")
        section_id = schema.get_section_id_for_block_id("number-question")
        expected_path = RoutingPath(
            ["number-question", "correct-answer"],
            section_id="default-section",
        )

        answer_1 = Answer(answer_id="answer", value=123)

        answer_store = AnswerStore()
        answer_store.add_or_update(answer_1)

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

        # Then
        self.assertEqual(routing_path, expected_path)
    def test_routing_path_should_not_skip_group(self):
        # Given
        schema = load_schema_from_name("test_skip_condition_group")

        section_id = schema.get_section_id_for_block_id("do-you-want-to-skip")
        answer_store = AnswerStore()
        answer_store.add_or_update(
            Answer(answer_id="do-you-want-to-skip-answer", value="No"))
        progress_store = ProgressStore([{
            "section_id": "default-section",
            "list_item_id": None,
            "status": CompletionStatus.COMPLETED,
            "block_ids": ["do-you-want-to-skip"],
        }])

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

        # Then
        expected_routing_path = RoutingPath(
            [
                "do-you-want-to-skip", "should-skip", "last-group-block",
                "summary"
            ],
            section_id="default-section",
        )

        with patch("app.questionnaire.path_finder.evaluate_skip_conditions",
                   return_value=False):
            self.assertEqual(routing_path, expected_routing_path)
Beispiel #11
0
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")
    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 = QuestionnaireSchema.get_mutable_deepcopy(
                schema.get_block("breakdown-block").get("question")
            )

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

            form_data = MultiDict({"breakdown-1": "3", "breakdown-2": "5"})

            form = generate_form(
                schema, question_schema, store, metadata=None, form_data=form_data
            )

            with patch(
                "app.questionnaire.questionnaire_schema.QuestionnaireSchema.get_all_questions_for_block",
                return_value=[question_schema],
            ):
                form.validate()
                self.assertIn(
                    form.question_errors["breakdown-question"], "Test Message"
                )
Beispiel #13
0
 def _deserialize(self, data: str) -> None:
     json_data = json_loads(data)
     self.progress_store = ProgressStore(json_data.get("PROGRESS"))
     self.set_metadata(json_data.get("METADATA", {}))
     self.answer_store = AnswerStore(json_data.get("ANSWERS"))
     self.list_store = ListStore.deserialize(json_data.get("LISTS"))
     self.response_metadata = json_data.get("RESPONSE_METADATA", {})
Beispiel #14
0
    def test_routing_path_with_conditional_path(self):
        schema = load_schema_from_name("test_new_routing_number_equals")
        section_id = schema.get_section_id_for_block_id("number-question")
        expected_path = RoutingPath(
            ["number-question", "correct-answer"],
            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,
            self.response_metadata,
        )

        routing_path = path_finder.routing_path(section_id=section_id)

        self.assertEqual(routing_path, expected_path)
    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)
def test_get_referenced_offset_value_with_list_item_id(
    app, value_source_resolver, rule_evaluator
):
    list_item_id = "abcde"

    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 = AnswerStore()

    answer_store.add_or_update(test_answer_id)
    value_source_resolver.answer_store = answer_store
    value_source_resolver.location = location
    value_source_resolver.list_item_id = list_item_id
    answer = {
        "maximum": {
            "value": {"identifier": "date", "source": "answers"},
            "offset_by": {"months": 1},
        }
    }

    handler = DateHandler(answer, value_source_resolver, rule_evaluator, error_messages)
    maximum_date = handler.get_date_value("maximum")

    assert maximum_date == parse_datetime("2018-04-20")
    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.is_repeating_answer = Mock(return_value=False)

        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_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_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,
            ))
    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 setUp(self):
     super().setUp()
     self.schema = load_schema_from_name("test_calculated_summary")
     answers = [
         {"value": 1, "answer_id": "first-number-answer"},
         {"value": 2, "answer_id": "second-number-answer"},
         {"value": 3, "answer_id": "second-number-answer-unit-total"},
         {"value": 4, "answer_id": "second-number-answer-also-in-total"},
         {"value": 5, "answer_id": "third-number-answer"},
         {"value": 6, "answer_id": "third-and-a-half-number-answer-unit-total"},
         {"value": "No", "answer_id": "skip-fourth-block-answer"},
         {"value": 7, "answer_id": "fourth-number-answer"},
         {"value": 8, "answer_id": "fourth-and-a-half-number-answer-also-in-total"},
         {"value": 9, "answer_id": "fifth-percent-answer"},
         {"value": 10, "answer_id": "fifth-number-answer"},
         {"value": 11, "answer_id": "sixth-percent-answer"},
         {"value": 12, "answer_id": "sixth-number-answer"},
     ]
     self.block_type = "CalculatedSummary"
     self.language = "en"
     self.metadata = {}
     self.response_metadata = {}
     self.answer_store = AnswerStore(answers)
     self.list_store = ListStore()
     self.progress_store = ProgressStore()
    def test_sum_calculated_field(self):
        store = AnswerStore()

        answer_total = Answer(answer_id="total-answer", value=10)

        store.add_or_update(answer_total)

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

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

            form_data = MultiDict(
                {
                    "breakdown-1": "",
                    "breakdown-2": "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, question_schema, store, metadata=None, form_data=form_data
            )

            form.validate()
            self.assertEqual(form.data, expected_form_data)
Beispiel #23
0
    def test_new_routing_path_should_skip_group(self):
        # Given
        schema = load_schema_from_name("test_new_skip_condition_group")

        section_id = schema.get_section_id_for_block_id("do-you-want-to-skip")
        answer_store = AnswerStore()
        answer_store.add_or_update(
            Answer(answer_id="do-you-want-to-skip-answer", value="Yes"))
        progress_store = ProgressStore([{
            "section_id": "default-section",
            "list_item_id": None,
            "status": CompletionStatus.COMPLETED,
            "block_ids": ["do-you-want-to-skip"],
        }])

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

        # Then
        expected_routing_path = RoutingPath(
            ["do-you-want-to-skip"],
            section_id="default-section",
        )

        self.assertEqual(routing_path, expected_routing_path)
    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")

            form_data = MultiDict({"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={}, form_data=form_data
                )

            form.validate()
            assert form.data == expected_form_data
Beispiel #25
0
    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,
            self.response_metadata,
        )

        # Then
        expected_route = RoutingPath(
            section_id="default-section",
            block_ids=["do-you-want-to-skip"],
        )

        self.assertEqual(
            expected_route,
            path_finder.routing_path(section_id="default-section"),
        )
Beispiel #26
0
    def __init__(self,
                 storage: EncryptedQuestionnaireStorage,
                 version: Optional[int] = None):
        self._storage = storage
        if version is None:
            version = self.get_latest_version_number()
        self.version = version
        self._metadata: dict[str, Any] = {}
        # self.metadata is a read-only view over self._metadata
        self.metadata: Mapping[str, Any] = MappingProxyType(self._metadata)
        self.response_metadata: Mapping[str, Any] = {}
        self.list_store = ListStore()
        self.answer_store = AnswerStore()
        self.progress_store = ProgressStore()
        self.submitted_at: Optional[datetime]
        self.collection_exercise_sid: Optional[str]

        (
            raw_data,
            self.collection_exercise_sid,
            version,
            self.submitted_at,
        ) = self._storage.get_user_data()

        if raw_data:
            self._deserialize(raw_data)
        if version is not None:
            self.version = version
    def test_invalid_date_range_and_single_date_periods(self):
        with self.app_request_context():
            store = AnswerStore()
            test_answer_id = Answer(answer_id="date", value="2017-03-20")
            store.add_or_update(test_answer_id)

            schema = load_schema_from_name("test_date_validation_range")

            question_schema = {
                "id": "date-range-question",
                "type": "DateRange",
                "answers": [
                    {
                        "id": "date-range-from",
                        "label": "Period from",
                        "mandatory": True,
                        "type": "Date",
                        "minimum": {"value": "2018-01-10", "offset_by": {"days": -5}},
                    },
                    {
                        "id": "date-range-to",
                        "label": "Period to",
                        "mandatory": True,
                        "type": "Date",
                        "maximum": {
                            "value": {"identifier": "date", "source": "answers"},
                            "offset_by": {"days": 5},
                        },
                    },
                ],
            }

            form_data = MultiDict(
                {
                    "date-range-from-day": "6",
                    "date-range-from-month": "1",
                    "date-range-from-year": "2018",
                    "date-range-to-day": "15",
                    "date-range-to-month": "1",
                    "date-range-to-year": "2018",
                }
            )

            metadata = {"schema_name": "test_date_validation_range"}

            form = generate_form(
                schema, question_schema, store, metadata=metadata, form_data=form_data
            )

            with self.assertRaises(Exception) as ite:
                with patch(
                    "app.questionnaire.questionnaire_schema.QuestionnaireSchema.get_all_questions_for_block",
                    return_value=[question_schema],
                ):
                    form.validate()
                    self.assertEqual(
                        "The schema has invalid date answer limits for date-range-question",
                        str(ite.exception),
                    )
Beispiel #28
0
 def setUp(self):
     super().setUp()
     self.answer_schema = MagicMock()
     self.answer_store = AnswerStore()
     self.list_store = ListStore()
     self.schema = MagicMock()
     self.metadata = {}
     self.response_metadata = {}
    def setUp(self):
        self.store = AnswerStore()

        answer1 = Answer(answer_id="set-minimum", value=10)
        answer2 = Answer(answer_id="set-maximum", value=20)
        answer3 = Answer(answer_id="set-maximum-cat", value="cat")

        self.store.add_or_update(answer1)
        self.store.add_or_update(answer2)
        self.store.add_or_update(answer3)
    def test_multi_calculation(self):
        store = AnswerStore()

        answer_total = Answer(answer_id="total-answer", value=10)

        store.add_or_update(answer_total)

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

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

            form_data = MultiDict(
                {
                    "breakdown-1": "",
                    "breakdown-2": "",
                    "breakdown-3": "",
                    "breakdown-4": "",
                }
            )

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

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

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

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

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

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

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

            self.assertEqual(
                form.question_errors["breakdown-question"],
                schema.error_messages["TOTAL_SUM_NOT_EQUALS"] % {"total": "10"},
            )