import pytest
from src.util.counter_object import CounterObject


class TestCounterObject:

    def test_constructor(self) -> int:
        """
        Cases:
            カウンターオブジェクト生成時に、数値を渡すと例外が発生しないこと
        Arranges:
            なし
        Expects:
            例外が発生しないこと
        """
        # Act
        CounterObject(1)

        # Expects
        pass

    def test_constructor_string_number(self) -> int:
        """
        Cases:
            カウンターオブジェクト生成時に、文字列型の数値を渡すと例外が発生しないこと
        Arranges:
            なし
        Expects:
            例外が発生しないこと
        """
        # Act
        CounterObject("1")

        # Expects
        pass

    def test_raise_constructor_string(self) -> int:
        """
        Cases:
            カウンターオブジェクト生成時に、文字列を渡すと例外が発生すること
        Arranges:
            なし
        Expects:
            発生した例外が期待値と一致すること
        """
        # Act
        with pytest.raises(Exception) as e:
            CounterObject("test1")

        # Expects
        assert "invalid literal for int() with base 10:" in str(e.value)

    def test_describe(self) -> int:
        """
        Cases:
            カウンターオブジェクトにて保持した値を返すこと(インスタンス生成時引数なし)
        Arranges:
            なし
        Expects:
            問い合わせた値が期待値と一致する
        """

        # Act
        sut = CounterObject()
        actual = sut.describe()

        # Expects
        assert actual == 1

    def test_describe_argument(self) -> int:
        """
        Cases:
            カウンターオブジェクトにて保持した値を返すこと(インスタンス生成時引数あり)
        Arranges:
            なし
        Expects:
            問い合わせた値が期待値と一致する
        """

        # Act
        sut = CounterObject(3)
        actual = sut.describe()

        # Expects
        assert actual == 3

    def test_raise_describe(self) -> int:
        """
        Cases:
            カウンターオブジェクトの保持した値を問い合わせる際、引数を渡すと例外が発生すること
        Arranges:
            なし
        Expects:
            問い合わせた値が期待値と一致する
        """

        # Act
        with pytest.raises(Exception) as e:
            sut = CounterObject()
            sut.describe(1)

        # Expects
        assert str(e.value) == 'describe() takes 1 positional argument but 2 were given'

    def test_increment(self) -> int:
        """
        Cases:
            カウンターオブジェクトにて保持した値がインクリメントされていること(引数なし)
        Arranges:
            なし
        Expects:
            戻り値が期待値と一致する
        """

        # Act
        sut = CounterObject()
        sut.increment()
        actual = sut.increment()

        # Expects
        assert actual == 3

    def test_increment_argument(self) -> int:
        """
        Cases:
            カウンターオブジェクトにて保持した値がインクリメントされていること(引数あり)
        Arranges:
            なし
        Expects:
            戻り値が期待値と一致する
        """

        # Act
        sut = CounterObject(5)
        sut.increment(2)
        actual = sut.increment(2)

        # Expects
        assert actual == 9

    def test_raise_increment(self) -> int:
        """
        Cases:
            文字列を引数で渡すことで、例外が発生すること
        Arranges:
            なし
        Expects:
            発生した例外が期待値と一致する
        """

        # Act
        with pytest.raises(Exception) as e:
            sut = CounterObject(5)
            sut.increment('aaa')
            sut.increment('aaa')

        # Expects
        assert str(e.value) == "unsupported operand type(s) for +=: 'int' and 'str'"

    def test_decrement(self) -> int:
        """
        Cases:
            カウンターオブジェクトにて保持した値がデクリメントされていること(引数なし)
        Arranges:
            なし
        Expects:
            戻り値が期待値と一致する
        """

        # Act
        sut = CounterObject()
        sut.decrement()
        actual = sut.decrement()

        # Expects
        assert actual == -1

    def test_decrement_argument(self) -> int:
        """
        Cases:
            カウンターオブジェクトにて保持した値がデクリメントされていること(引数あり)
        Arranges:
            なし
        Expects:
            戻り値が期待値と一致する
        """

        # Act
        sut = CounterObject(5)
        sut.decrement(2)
        actual = sut.decrement(2)

        # Expects
        assert actual == 1

    def test_raise_decrement(self) -> int:
        """
        Cases:
            文字列を引数で渡すことで、例外が発生すること
        Arranges:
            なし
        Expects:
            発生した例外が期待値と一致する
        """

        # Act
        with pytest.raises(Exception) as e:
            sut = CounterObject(5)
            sut.decrement('aaa')
            sut.decrement('aaa')

        # Expects
        assert str(e.value) == "unsupported operand type(s) for -=: 'int' and 'str'"
