"""Test suite focusing on validation backend features."""

__author__ = "Jens Finkhaeuser"
__copyright__ = "Copyright (c) 2018 Jens Finkhaeuser"
__license__ = "MIT"
__all__ = ()

import pytest

from prance import BaseParser
from prance import ValidationError
from prance.util import validation_backends

from . import none_of


def test_bad_backend():
    with pytest.raises(ValueError):
        BaseParser("tests/specs/petstore.yaml", backend="does_not_exist")


@pytest.mark.skipif(none_of("flex"), reason="Missing dependencies: flex")
def test_flex_issue_5_integer_keys():
    # Must succeed with default (flex) parser; note the parser does not stringify the response code
    parser = BaseParser("tests/specs/issue_5.yaml", backend="flex")
    assert 200 in parser.specification["paths"]["/test"]["post"]["responses"]


@pytest.mark.skipif(none_of("flex"), reason="Missing dependencies: flex")
def test_flex_validate_success():
    parser = BaseParser("tests/specs/petstore.yaml", backend="flex")


@pytest.mark.skipif(none_of("flex"), reason="Missing dependencies: flex")
def test_flex_validate_failure():
    with pytest.raises(ValidationError):
        parser = BaseParser("tests/specs/missing_reference.yaml", backend="flex")


@pytest.mark.skipif(
    none_of("swagger-spec-validator"),
    reason="Missing dependencies: swagger-spec-validator",
)
def test_swagger_spec_validator_issue_5_integer_keys():
    # Must fail in implicit strict mode.
    with pytest.raises(ValidationError):
        BaseParser("tests/specs/issue_5.yaml", backend="swagger-spec-validator")

    # Must fail in explicit strict mode.
    with pytest.raises(ValidationError):
        BaseParser(
            "tests/specs/issue_5.yaml", backend="swagger-spec-validator", strict=True
        )

    # Must succeed in non-strict/lenient mode
    parser = BaseParser(
        "tests/specs/issue_5.yaml", backend="swagger-spec-validator", strict=False
    )
    assert "200" in parser.specification["paths"]["/test"]["post"]["responses"]


@pytest.mark.skipif(
    none_of("swagger-spec-validator"),
    reason="Missing dependencies: swagger-spec-validator",
)
def test_swagger_spec_validator_validate_success():
    parser = BaseParser("tests/specs/petstore.yaml", backend="swagger-spec-validator")


@pytest.mark.skipif(
    none_of("swagger-spec-validator"),
    reason="Missing dependencies: swagger-spec-validator",
)
def test_swagger_spec_validator_validate_failure():
    with pytest.raises(ValidationError):
        parser = BaseParser(
            "tests/specs/missing_reference.yaml", backend="swagger-spec-validator"
        )


@pytest.mark.skipif(
    none_of("openapi-spec-validator"),
    reason="Missing dependencies: openapi-spec-validator",
)
def test_openapi_spec_validator_issue_5_integer_keys():
    # Must fail in implicit strict mode.
    with pytest.raises(ValidationError):
        BaseParser("tests/specs/issue_5.yaml", backend="openapi-spec-validator")

    # Must fail in explicit strict mode.
    with pytest.raises(ValidationError):
        BaseParser(
            "tests/specs/issue_5.yaml", backend="openapi-spec-validator", strict=True
        )

    # Must succeed in non-strict/lenient mode
    parser = BaseParser(
        "tests/specs/issue_5.yaml", backend="openapi-spec-validator", strict=False
    )
    assert "200" in parser.specification["paths"]["/test"]["post"]["responses"]


@pytest.mark.skipif(
    none_of("openapi-spec-validator"),
    reason="Missing dependencies: openapi-spec-validator",
)
def test_openapi_spec_validator_issue_36_error_reporting():
    with pytest.raises(ValidationError, match=r"Strict mode enabled"):
        BaseParser("tests/specs/issue_36.yaml", backend="openapi-spec-validator")


@pytest.mark.skipif(
    none_of("openapi-spec-validator"),
    reason="Missing dependencies: openapi-spec-validator",
)
def test_openapi_spec_validator_validate_success():
    parser = BaseParser("tests/specs/petstore.yaml", backend="openapi-spec-validator")


@pytest.mark.skipif(
    none_of("openapi-spec-validator"),
    reason="Missing dependencies: openapi-spec-validator",
)
def test_openapi_spec_validator_validate_failure():
    with pytest.raises(ValidationError):
        parser = BaseParser(
            "tests/specs/missing_reference.yaml", backend="openapi-spec-validator"
        )


@pytest.mark.skipif(
    none_of("openapi-spec-validator"),
    reason="Missing dependencies: openapi-spec-validator",
)
def test_openapi_spec_validator_issue_20_spec_version_handling():
    # The spec is OpenAPI 3, but broken. Need to set 'strict' to False to stringify keys
    with pytest.raises(ValidationError):
        parser = BaseParser(
            "tests/specs/issue_20.yaml", backend="openapi-spec-validator", strict=False
        )

    # Lazy parsing should let us validate what's happening
    parser = BaseParser(
        "tests/specs/issue_20.yaml",
        backend="openapi-spec-validator",
        strict=False,
        lazy=True,
    )
    assert not parser.valid
    assert parser.version_parsed == ()

    with pytest.raises(ValidationError):
        parser.parse()

    # After parsing, the specs are not valid, but the correct version is
    # detected.
    assert not parser.valid
    assert parser.version_parsed == (3, 0, 0)
