import json
import pytest

from typedjsonrpc.registry import Registry


def test_register():
    registry = Registry()

    def foo(x):
        return x
    registry.register("bar", foo)
    assert "bar" in registry._name_to_method
    assert registry._name_to_method["bar"] == foo


def test_method():
    registry = Registry()

    @registry.method(x=str)
    def foo(x):
        return x
    expected_name = "{}.{}".format(foo.__module__, foo.__name__)
    assert expected_name in registry._name_to_method
    assert registry._name_to_method[expected_name] == foo


def test_method_correct_argtypes():
    registry = Registry()

    @registry.method(some_text=str, some_number=int)
    def foo(some_text, some_number):
        return some_text + str(some_number)
    assert foo("Hello", 5) == "Hello5"
    assert foo(some_text="Hello", some_number=5) == "Hello5"
    assert foo("Hello", some_number=5) == "Hello5"
    assert foo(some_number=5, some_text="Hello") == "Hello5"

    @registry.method()
    def bar():
        return "Works"
    assert bar() == "Works"

    @registry.method(some_text=str, some_number=int)
    def stuff(some_number, some_text):
        return str(some_number) + some_text
    assert stuff(42, "Answer") == "42Answer"


def test_method_args():
    registry = Registry()

    @registry.method(some_text=str, some_number=int)
    def foo(some_text, some_number, *args):
        return some_text
    assert foo("Hi", 5, 6, "Test") == "Hi"

    @registry.method(some_text=str, some_number=int)
    def bar(some_text, some_number, *args, **kwargs):
        return some_number
    assert bar("Hi", 5, bla=6, stuff="Test") == 5
    with pytest.raises(TypeError):
        bar("Hi", test=7)


def test_method_defaults():
    registry = Registry()

    @registry.method(some_number=int, some_text=str)
    def foo(some_number, some_text="Test"):
        return some_text
    assert foo(5) == "Test"
    assert foo(5, "Hello") == "Hello"


def test_method_wrong_type_declarations():
    registry = Registry()

    with pytest.raises(Exception):
        @registry.method(some_text=str, some_number=int)
        def foo(some_text, some_stuff):
            return some_text + some_stuff


def test_method_wrong_argument_order():
    registry = Registry()

    @registry.method(some_text=str, some_number=int)
    def foo(some_text, some_number):
        return some_text + str(some_number)
    assert foo("Answer", 42) == "Answer42"
    with pytest.raises(TypeError):
        foo(42, "Answer")


def test_dispatch_keyword_args():
    registry = Registry()

    def add(x, y):
        return x + y
    registry.register("add", add)

    class FakeRequest(object):
        def get_data(self):
            return json.dumps({
                "jsonrpc": "2.0",
                "method": "add",
                "params": {
                    "x": 1,
                    "y": 2,
                },
                "id": "bogus",
            })
    fake_request = FakeRequest()
    response = registry.dispatch(fake_request)
    assert response == json.dumps(3)


def test_dispatch_positional_args():
    registry = Registry()

    def add(x, y):
        return x + y
    registry.register("add", add)

    class FakeRequest(object):
        def get_data(self):
            return json.dumps({
                "jsonrpc": "2.0",
                "method": "add",
                "params": [1, 2],
                "id": "bogus",
            })
    fake_request = FakeRequest()
    response = registry.dispatch(fake_request)
    assert response == json.dumps(3)


def test_dispatch_invalid_method():
    registry = Registry()

    class FakeRequest(object):
        def get_data(self):
            return json.dumps({
                "jsonrpc": "2.0",
                "method": "bogus",
                "params": [1, 2],
                "id": "bogus",
            })
    fake_request = FakeRequest()
    with pytest.raises(Exception):
        registry.dispatch(fake_request)

@@ -1409,32 +1409,63 @@
 return some_text
+ + str(some_number) + str(args)
 %0A    assert foo(
@@ -1490,16 +1490,28 @@
 ) == %22Hi
+5(6, 'Test')
 %22%0A%0A    @
@@ -1632,22 +1632,65 @@
 rn some_
-number
+text + str(some_number) + str(args) + str(kwargs)
 %0A    ass
@@ -1705,16 +1705,23 @@
 %22Hi%22, 5,
+ %22foo%22,
  bla=6, 
@@ -1737,17 +1737,56 @@
 st%22) == 
-5
+%22Hi5('foo',)%7B'stuff': 'Test', 'bla': 6%7D%22
 %0A    wit

Use *args and **kwargs in the test function