import pytest from multiplayer_crosswords.crossword import Crossword, Orientation, PlacedWord from unittest.mock import MagicMock from multiplayer_crosswords.dictionary import Dictionary from multiplayer_crosswords.utils import load_en_dictionary, load_de_dictionary class DummyWord: def __init__(self, word): self.word = word class DummyDictionary: def __init__(self, words): self.words = words def make_crossword(rows=5, cols=5): dictionary = DummyDictionary([DummyWord("HELLO"), DummyWord("WORLD")]) return Crossword(rows, cols, dictionary) def test_can_place_word_empty_grid_horizontal(): cw = make_crossword() word = DummyWord("HELLO") assert cw.can_place_word(word, 0, 0, Orientation.HORIZONTAL) assert not cw.can_place_word(word, 0, 1, Orientation.HORIZONTAL) # would go out of bounds def test_can_place_word_empty_grid_vertical(): cw = make_crossword() word = DummyWord("HELLO") assert cw.can_place_word(word, 0, 0, Orientation.VERTICAL) assert not cw.can_place_word(word, 1, 0, Orientation.VERTICAL) # would go out of bounds def test_add_word_and_grid_update(): cw = make_crossword() word = DummyWord("HELLO") assert cw.add_word(word, 0, 0, Orientation.HORIZONTAL) # Check grid contents assert cw.grid[0][0] == "H" assert cw.grid[0][1] == "E" assert cw.grid[0][2] == "L" assert cw.grid[0][3] == "L" assert cw.grid[0][4] == "O" # Start and end blocks assert cw.grid[0][0-0][0-1] == "#" if cw._in_bounds(0, -1) else True assert cw.grid[0][5] == "#" if cw._in_bounds(0, 5) else True def test_cannot_place_overlapping_different_letter(): cw = make_crossword() word1 = DummyWord("HELLO") word2 = DummyWord("WORLD") assert cw.add_word(word1, 0, 0, Orientation.HORIZONTAL) # Try to place "WORLD" vertically overlapping 'E' with 'O' assert not cw.can_place_word(word2, 0, 1, Orientation.VERTICAL) def test_can_place_overlapping_same_letter(): cw = make_crossword() word1 = DummyWord("HELLO") word2 = DummyWord("EVE") assert cw.add_word(word1, 0, 0, Orientation.HORIZONTAL) # "EVE" vertical, E overlaps at (0,1) word2 = DummyWord("EVE") assert cw.can_place_word(word2, 0, 1, Orientation.VERTICAL) assert cw.add_word(word2, 0, 1, Orientation.VERTICAL) def test_blocks_are_placed_correctly(): cw = make_crossword() word = DummyWord("HI") assert cw.add_word(word, 2, 2, Orientation.HORIZONTAL) # Start block assert cw.grid[2][1] == "#" # End block assert cw.grid[2][4] == "#" def test_str_representation(): cw = make_crossword() word = DummyWord("HI") cw.add_word(word, 0, 0, Orientation.HORIZONTAL) s = str(cw) assert "HI" in s assert "." in s def test_placed_words_tracking(): cw = make_crossword() word = DummyWord("HI") cw.add_word(word, 1, 1, Orientation.VERTICAL) assert len(cw.placed_words) == 1 placed = cw.placed_words[0] assert placed.word == word assert placed.row == 1 assert placed.col == 1 assert placed.orientation == Orientation.VERTICAL def test_valid_hello_world_crossword(): cw = make_crossword() assert cw.add_word(DummyWord("HELLO"), 1, 0, Orientation.HORIZONTAL) assert cw.add_word(DummyWord("WORLD"), 0, 4, Orientation.VERTICAL) assert str(cw).count('H') == 1 assert str(cw).count('E') == 1 assert str(cw).count('L') == 3 assert str(cw).count('O') == 1 assert str(cw).count('W') == 1 assert str(cw).count('R') == 1 assert str(cw).count('D') == 1 def test_crossword_generation(): dictionary = load_de_dictionary() crossword = Crossword.generate(15, 15, dictionary) assert crossword is not None # Basic checks on the generated crossword assert len(crossword.grid) == 15 assert all(len(row) == 15 for row in crossword.grid) assert len(crossword.placed_words) > 0 # print the crossword for visual inspection print(crossword)