|
|
|
|
|
"""Unit tests for Wrdler rectangular grid support in models.py""" |
|
|
import pytest |
|
|
from wrdler.models import Coord, Word, Puzzle, GameState |
|
|
|
|
|
|
|
|
class TestCoordRectangular: |
|
|
"""Tests for Coord.in_bounds_rect() method""" |
|
|
|
|
|
def test_in_bounds_rect_valid_coords(self): |
|
|
"""Test that valid coordinates pass boundary check""" |
|
|
|
|
|
assert Coord(0, 0).in_bounds_rect(6, 8) is True |
|
|
assert Coord(5, 7).in_bounds_rect(6, 8) is True |
|
|
assert Coord(3, 4).in_bounds_rect(6, 8) is True |
|
|
|
|
|
def test_in_bounds_rect_invalid_coords(self): |
|
|
"""Test that out-of-bounds coordinates fail boundary check""" |
|
|
|
|
|
assert Coord(6, 0).in_bounds_rect(6, 8) is False |
|
|
assert Coord(0, 8).in_bounds_rect(6, 8) is False |
|
|
assert Coord(-1, 0).in_bounds_rect(6, 8) is False |
|
|
assert Coord(0, -1).in_bounds_rect(6, 8) is False |
|
|
|
|
|
def test_in_bounds_backward_compatibility(self): |
|
|
"""Test that legacy in_bounds() still works for square grids""" |
|
|
assert Coord(0, 0).in_bounds(12) is True |
|
|
assert Coord(11, 11).in_bounds(12) is True |
|
|
assert Coord(12, 0).in_bounds(12) is False |
|
|
|
|
|
|
|
|
class TestPuzzleRectangular: |
|
|
"""Tests for Puzzle with rectangular grid dimensions""" |
|
|
|
|
|
def test_puzzle_default_dimensions(self): |
|
|
"""Test that Puzzle defaults to Wrdler dimensions (6x8)""" |
|
|
puzzle = Puzzle(words=[]) |
|
|
assert puzzle.grid_rows == 6 |
|
|
assert puzzle.grid_cols == 8 |
|
|
|
|
|
def test_puzzle_custom_dimensions(self): |
|
|
"""Test that Puzzle can use custom dimensions""" |
|
|
puzzle = Puzzle(words=[], grid_rows=10, grid_cols=12) |
|
|
assert puzzle.grid_rows == 10 |
|
|
assert puzzle.grid_cols == 12 |
|
|
|
|
|
def test_puzzle_no_radar_field(self): |
|
|
"""Test that radar field is removed from Puzzle""" |
|
|
puzzle = Puzzle(words=[]) |
|
|
assert not hasattr(puzzle, 'radar') |
|
|
|
|
|
|
|
|
class TestGameStateRectangular: |
|
|
"""Tests for GameState with rectangular grid support""" |
|
|
|
|
|
def test_gamestate_default_dimensions(self): |
|
|
"""Test that GameState defaults to Wrdler dimensions (6x8)""" |
|
|
state = GameState() |
|
|
assert state.grid_rows == 6 |
|
|
assert state.grid_cols == 8 |
|
|
|
|
|
def test_gamestate_free_letters_field(self): |
|
|
"""Test that free_letters field exists and is initialized""" |
|
|
state = GameState() |
|
|
assert hasattr(state, 'free_letters') |
|
|
assert isinstance(state.free_letters, set) |
|
|
assert len(state.free_letters) == 0 |
|
|
|
|
|
def test_gamestate_free_letters_used_field(self): |
|
|
"""Test that free_letters_used field exists and is initialized to 0""" |
|
|
state = GameState() |
|
|
assert hasattr(state, 'free_letters_used') |
|
|
assert state.free_letters_used == 0 |
|
|
|
|
|
def test_gamestate_grid_size_property_square(self): |
|
|
"""Test grid_size property works for square grids""" |
|
|
state = GameState(grid_rows=12, grid_cols=12) |
|
|
assert state.grid_size == 12 |
|
|
|
|
|
def test_gamestate_grid_size_property_rectangular_raises(self): |
|
|
"""Test grid_size property raises ValueError for rectangular grids""" |
|
|
state = GameState(grid_rows=6, grid_cols=8) |
|
|
with pytest.raises(ValueError, match="grid_size not applicable"): |
|
|
_ = state.grid_size |
|
|
|
|
|
|
|
|
class TestWordHorizontalOnly: |
|
|
"""Tests for Word with horizontal-only placement (Wrdler requirement)""" |
|
|
|
|
|
def test_word_horizontal_valid(self): |
|
|
"""Test that horizontal words are created correctly""" |
|
|
word = Word(text="WORD", start=Coord(0, 0), direction="H") |
|
|
assert word.direction == "H" |
|
|
assert len(word.cells) == 4 |
|
|
assert word.cells[0] == Coord(0, 0) |
|
|
assert word.cells[3] == Coord(0, 3) |
|
|
|
|
|
def test_word_horizontal_fits_in_8_cols(self): |
|
|
"""Test that words fit within 8-column grid""" |
|
|
|
|
|
word = Word(text="TESTWORD", start=Coord(0, 0), direction="H") |
|
|
assert all(c.in_bounds_rect(6, 8) for c in word.cells) |
|
|
|
|
|
|
|
|
word = Word(text="TEST", start=Coord(0, 4), direction="H") |
|
|
assert all(c.in_bounds_rect(6, 8) for c in word.cells) |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
pytest.main([__file__, "-v"]) |