import pytest
from dcjdict.decode import from_jdict, JsonableDict
from typing import Literal

from .cases import *


class A_ConversionToDataclass:
    def should_assert_all_fields_are_done(self):
        with pytest.raises(ValueError):
            from_jdict({}, Value)

    def should_avoid_decode_no_data_class(self):
        with pytest.raises(TypeError):
            from_jdict({}, NoDataclass)

    def should_avoid_construct_without_compulsory(self):
        @dataclass
        class Value:
            a: int

        with pytest.raises(ValueError):
            from_jdict({}, Value)

    def should_construct_with_default(self):
        @dataclass
        class Value:
            a: int = 1
            b: int = field(default=2)
            c: int = field(default_factory=lambda: 5)

        assert from_jdict({}, Value) == Value()

    def should_constuct_with_other_dataclass_as_field(self):
        @dataclass
        class Sub:
            a: int = 1

        @dataclass
        class Value:
            sub: Sub

        assert from_jdict({"sub": {}}, Value) == Value(Sub())

    def should_construct_from_jsonable_dict(self):

        for case in CASES:
            assert case.value == from_jdict(case.jdict, Value), case.name

    def should_construct_from_literal(self):
        @dataclass
        class A:
            a: Literal["a", "b", "c"]

        assert from_jdict({"a": "b"}, A) == A("b")

        with pytest.raises(ValueError):
            from_jdict({"a": "d"}, A)
