import pytest
from jsonschema import validate, ValidationError

from app.core.services.api import Parameter, API, ArgParameter, KeywordParameter


class TestParameter(object):
    def test_bad_type(self):
        with pytest.raises(ValueError):
            Parameter("", "", dict)

    def test_schema(self):
        assert {"type": "string"} == Parameter("", "", str).schema
        assert {"type": "number"} == Parameter("", "", int).schema
        assert {"type": "boolean"} == Parameter("", "", bool).schema

    def test_info(self):
        assert Parameter("a", "b", str).info == {
            "name": "a",
            "description": "b",
            "type": "text"
        }


class TestAPI(object):
    def test_validate_schema_without_args(self):
        api = API("uid", "name", "desc")
        obj = {"command": "uid"}

        assert validate(obj, api.schema) is None

        with pytest.raises(ValidationError):
            validate({"command": "uid", "args": {}}, api.schema)

    def test_validate_schema_with_args(self):
        api = API("uid", "name", "desc", [
            ArgParameter("a1", "d1", str),
            KeywordParameter("a2", "d2", int),
            ArgParameter("a3", "d3", bool),
        ])

        obj = {
            "command": "uid",
            "args": ["string", False],
            "kwargs": {"a2": 5},
        }
        assert validate(obj, api.schema) is None

        with pytest.raises(ValidationError):
            validate({"command": "uid"}, api.schema)

        with pytest.raises(ValidationError):
            validate({"command": "uid", "args": dict(a1="a", a2="", a3=True)},
                     api.schema)

    def test_info(self):
        api = API("uid", "name", "desc", [
            KeywordParameter("a2", "d2", int),
            ArgParameter("a1", "d1", str),
            KeywordParameter("a3", "d3", bool),
        ])

        assert api.info == {
            "name": "name",
            "id": "uid",
            "description": "desc",
            "args": [x.info for x in api.args],
            "kwargs": {p.name: p.info for p in api.kwargs}
        }

@@ -2099,16 +2099,591 @@
 args%7D%0A        %7D%0A
+%0A    def test_call(self):%0A        api = API(%22uid%22, %22name%22, %22desc%22, %5B%0A            KeywordParameter(%22a2%22, %22d2%22, int),%0A            ArgParameter(%22a1%22, %22d1%22, str),%0A            KeywordParameter(%22a3%22, %22d3%22, bool),%0A            ArgParameter(%22a4%22, %22d1%22, str),%0A            KeywordParameter(%22a5%22, %22d1%22, str),%0A%0A        %5D)%0A%0A        def test_func(a, b, a2, a3, a5):%0A            return %22%7B%7D%7B%7D%7B%7D%7B%7D%7B%7D%22.format(a, b, a2, a3, a5)%0A%0A        assert %22ab135%22 == api(test_func, %7B%0A            %22command%22: %22uid%22,%0A            %22args%22: %5B%22a%22, %22b%22%5D,%0A            %22kwargs%22: %7B%22a2%22: 1, %22a3%22: 3, %22a5%22: 5%7D%0A        %7D)%0A

Add test cases.