def setUp(self):
     self.minefield_repository = InMemoryMinefieldRepository()
     self.turn_repository = InMemoryTurnRepository()
     board = Board(row_count=3, column_count=5)
     self.subject = CreateMinefieldUseCase(
         board=board,
         mine_planter=LazyBeeMinePlanter(),
         minefield_repository=self.minefield_repository,
         turn_repository=self.turn_repository,
     )
class CreateMinefieldUseCaseTest(TestCase):
    def setUp(self):
        self.minefield_repository = InMemoryMinefieldRepository()
        self.turn_repository = InMemoryTurnRepository()
        board = Board(row_count=3, column_count=5)
        self.subject = CreateMinefieldUseCase(
            board=board,
            mine_planter=LazyBeeMinePlanter(),
            minefield_repository=self.minefield_repository,
            turn_repository=self.turn_repository,
        )

    def test_create_minefield_should_create_a_minefield(self):
        spy = Mock(CreateMinefieldUseCaseObserver)
        self.subject(column_index=0, row_index=0, observer=spy)

        captured_minefield_identifier = spy.did_create_minefield.call_args[1]["minefield_identifier"]

        fetched_minefield = None

        def did_fetch_minefield(minefield: Minefield):
            nonlocal fetched_minefield
            fetched_minefield = minefield

        self.minefield_repository.fetch_minefield(
            minefield_identifier=captured_minefield_identifier, success=did_fetch_minefield
        )
        expected_mine_coordinates = [
            Coordinate(row_index=0, column_index=0),
            Coordinate(row_index=1, column_index=1),
            Coordinate(row_index=2, column_index=2),
        ]
        expected_board = Board(row_count=3, column_count=5)
        expected_minefield = Minefield(
            identifier=captured_minefield_identifier, board=expected_board, mine_coordinates=expected_mine_coordinates
        )
        assert_minefields_equal(fetched_minefield, expected_minefield, self)

    def test_create_minefield_should_create_a_first_turn(self):
        spy = Mock(CreateMinefieldUseCaseObserver)
        self.subject(row_index=0, column_index=1, observer=spy)

        captured_minefield_identifier = spy.did_create_minefield.call_args[1]["minefield_identifier"]
        captured_first_turn = spy.did_create_minefield.call_args[1]["first_turn"]

        fetched_turn_list = None
        fetched_minefield_identifier = None

        def did_fetch_ordererd_turns(turn_list: List[Turn], minefield_identifier: UUID):
            nonlocal fetched_turn_list
            nonlocal fetched_minefield_identifier
            fetched_turn_list = turn_list
            fetched_minefield_identifier = minefield_identifier

        self.turn_repository.fetch_ordered_turns(
            last_turn_identifier=captured_first_turn.identifier, success=did_fetch_ordererd_turns
        )

        expected_turn_list = [
            Turn(
                identifier=captured_first_turn.identifier,
                coordinate=Coordinate(row_index=0, column_index=1),
                action=TurnAction.RevealCell,
                parent_turn_identifier=None,
                minefield_identifier=captured_minefield_identifier,
            )
        ]

        assert_turn_lists_equal(fetched_turn_list, expected_turn_list, self)
        self.assertEqual(fetched_minefield_identifier, captured_minefield_identifier)

    def test_create_minefield_should_notify_observer_with_game_state(self):
        spy = Mock(CreateMinefieldUseCaseObserver)
        self.subject(row_index=0, column_index=1, observer=spy)

        keyword_arguments = spy.did_create_minefield.call_args[1]
        captured_game_state = keyword_arguments["game_state"]
        self.assertEqual(captured_game_state, GameState.Started)