def test_dynamic_options_values_with_non_checkbox_answer_source():
    answer = {
        "id": "answer",
        "label": "Label",
        "type": "Checkbox",
        "dynamic_options": {
            "values": {"source": "answers", "identifier": "non-checkbox-answer"},
            "transform": {"option-label-from-value": ["self", "non-checkbox-answer"]},
        },
    }

    validator = OptionAnswerValidator(
        answer,
        questionnaire_schema=get_mock_schema(
            answers_with_context={
                "non-checkbox-answer": {
                    "answer": {"id": "non-checkbox-answer", "type": "Radio"}
                }
            }
        ),
    )
    validator.validate_dynamic_options()

    expected_error = {
        "message": validator.DYNAMIC_OPTIONS_REFERENCES_NON_CHECKBOX_ANSWER,
        "value_source": {"source": "answers", "identifier": "non-checkbox-answer"},
        "answer_id": "answer",
    }

    assert validator.errors == [expected_error]
def test_dynamic_options_values_with_invalid_value_rule():
    answer = {
        "id": "answer",
        "label": "Label",
        "type": "Checkbox",
        "dynamic_options": {
            "values": {
                "map": [
                    {"format-date": [{"date": ["now"]}, "yyyy-MM-dd"]},
                    {
                        "date-range": [
                            {
                                "date": [
                                    {
                                        "source": "response_metadata",
                                        "identifier": "started_at",
                                    }
                                ]
                            },
                            7,
                        ]
                    },
                ]
            },
            "transform": {"format-date": [{"date": ["self"]}, "EEEE d MMMM yyyy"]},
        },
    }

    validator = OptionAnswerValidator(
        answer,
        questionnaire_schema=get_mock_schema(
            answers_with_context={
                "checkbox-answer": {
                    "answer": {"id": "checkbox-answer", "type": "Checkbox"}
                }
            }
        ),
    )
    validator.validate_dynamic_options()

    expected_error = {
        "message": RulesValidator.MAP_OPERATOR_WITHOUT_SELF_REFERENCE,
        "origin_id": "answer",
        "rule": {"format-date": [{"date": ["now"]}, "yyyy-MM-dd"]},
    }

    assert validator.errors == [expected_error]
def test_dynamic_options_transform_with_invalid_answer_id_reference():
    answer = {
        "id": "answer",
        "label": "Label",
        "type": "Checkbox",
        "dynamic_options": {
            "values": {"source": "answers", "identifier": "checkbox-answer"},
            "transform": {"option-label-from-value": ["self", "non-existing-answer"]},
        },
    }

    validator = OptionAnswerValidator(
        answer,
        questionnaire_schema=get_mock_schema(
            answers_with_context={
                "checkbox-answer": {
                    "answer": {"id": "checkbox-answer", "type": "Checkbox"}
                }
            }
        ),
    )
    validator.validate_dynamic_options()

    option_label_from_value_do_not_match_error = {
        "message": validator.DYNAMIC_OPTIONS_SOURCE_IDENTIFIER_AND_OPTION_LABEL_FROM_VALUE_MISMATCH,
        "source_identifier": "checkbox-answer",
        "transform_identifier": "non-existing-answer",
        "answer_id": "answer",
    }

    answer_reference_invalid_error = {
        "message": ValueSourceValidator.ANSWER_SOURCE_REFERENCE_INVALID,
        "identifier": "non-existing-answer",
        "origin_id": "answer",
    }

    assert validator.errors == [
        option_label_from_value_do_not_match_error,
        answer_reference_invalid_error,
    ]
def test_dynamic_options_source_identifier_and_option_label_from_value_mismatch():
    answer = {
        "id": "answer",
        "label": "Label",
        "type": "Radio",
        "dynamic_options": {
            "values": {"source": "answers", "identifier": "checkbox-answer"},
            "transform": {
                "option-label-from-value": ["self", "mismatch-checkbox-answer"]
            },
        },
    }

    validator = OptionAnswerValidator(
        answer,
        questionnaire_schema=get_mock_schema(
            answers_with_context={
                "checkbox-answer": {
                    "answer": {"id": "checkbox-answer", "type": "Checkbox"}
                },
                "mismatch-checkbox-answer": {
                    "answer": {"id": "mismatch-checkbox-answer", "type": "Checkbox"}
                },
            }
        ),
    )
    validator.validate_dynamic_options()

    expected_error = {
        "message": validator.DYNAMIC_OPTIONS_SOURCE_IDENTIFIER_AND_OPTION_LABEL_FROM_VALUE_MISMATCH,
        "source_identifier": "checkbox-answer",
        "transform_identifier": "mismatch-checkbox-answer",
        "answer_id": "answer",
    }

    assert validator.errors == [expected_error]
def test_dynamic_options_transform_allows_non_map_self_reference():
    answer = {
        "id": "answer",
        "label": "Label",
        "type": "Checkbox",
        "dynamic_options": {
            "values": {"source": "answers", "identifier": "checkbox-answer"},
            "transform": {"option-label-from-value": ["self", "checkbox-answer"]},
        },
    }

    validator = OptionAnswerValidator(
        answer,
        questionnaire_schema=get_mock_schema(
            answers_with_context={
                "checkbox-answer": {
                    "answer": {"id": "checkbox-answer", "type": "Checkbox"}
                }
            }
        ),
    )
    validator.validate_dynamic_options()

    assert not validator.errors