"""Tests for UI rendering - catches Rich markup errors before deployment.""" import pytest from io import StringIO from rich.console import Console from rich.panel import Panel from rich.table import Table from rich.text import Text from rich.align import Align from rich.box import ROUNDED def test_menu_render_no_markup_errors(): """Test that the main menu renders without Rich markup errors.""" # Simulate the menu rendering code output = StringIO() console = Console(file=output, width=80, height=24, force_terminal=True, color_system="truecolor") username = "testuser" width = 80 height = 24 pieces = "♔ ♕ ♖ ♗ ♘ ♙" # Title section console.print(Align.center(Text(pieces, style="dim white"))) console.print() console.print(Align.center(Text("S H E L L M A T E", style="bold bright_green"))) console.print(Align.center(Text("━" * 20, style="green"))) console.print(Align.center(Text("SSH into Chess Mastery", style="italic bright_black"))) console.print(Align.center(Text(pieces[::-1], style="dim white"))) console.print() # Menu table - this is where markup errors often occur menu_table = Table(show_header=False, box=None, padding=(0, 2)) menu_table.add_column(justify="center") menu_table.add_row(Text(f"Welcome, {username}!", style="cyan")) menu_table.add_row("") menu_table.add_row("[bright_white on blue] 1 [/bright_white on blue] Play vs AI [dim]♔ vs ♚[/dim]") menu_table.add_row("[bright_white on magenta] 2 [/bright_white on magenta] Play vs Human [dim]♔ vs ♔[/dim]") menu_table.add_row("[bright_white on green] 3 [/bright_white on green] Learn & Practice [dim]📖[/dim]") menu_table.add_row("[bright_white on red] q [/bright_white on red] Quit [dim]👋[/dim]") menu_table.add_row("") menu_table.add_row(Text("Press a key to select...", style="dim italic")) panel_width = min(45, width - 4) panel = Panel( Align.center(menu_table), box=ROUNDED, border_style="bright_blue", width=panel_width, padding=(1, 2), ) console.print(Align.center(panel)) # Footer console.print() console.print(Align.center(Text(f"Terminal: {width}×{height}", style="dim"))) # If we got here without exception, markup is valid rendered = output.getvalue() # Check key content is present (content may have ANSI codes) assert "S H E L L M A T E" in rendered or "SHELLMATE" in rendered assert "Welcome" in rendered assert "Play vs AI" in rendered def test_game_status_render(): """Test that game status panel renders correctly.""" output = StringIO() console = Console(file=output, width=80, height=24, force_terminal=True) status_lines = [] status_lines.append("[bold white]White ♔ to move[/bold white]") status_lines.append("[dim]Moves: e2e4 e7e5 g1f3[/dim]") status_lines.append("") status_lines.append("[dim]Enter move (e.g. e2e4) │ [q]uit │ [r]esign[/dim]") panel = Panel( "\n".join(status_lines), box=ROUNDED, border_style="blue", width=50, title="[bold]Game Status[/bold]" ) console.print(panel) rendered = output.getvalue() assert "White" in rendered assert "Game Status" in rendered def test_chess_board_render(): """Test that chess board renders without errors.""" output = StringIO() PIECES = { 'K': '♔', 'Q': '♕', 'R': '♖', 'B': '♗', 'N': '♘', 'P': '♙', 'k': '♚', 'q': '♛', 'r': '♜', 'b': '♝', 'n': '♞', 'p': '♟', } # Simplified board rendering (plain text) lines = [] lines.append(" a b c d e f g h") lines.append(" +---+---+---+---+---+---+---+---+") # Render rank 8 with pieces pieces_row = ['r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'] row = " 8 |" for file, piece_char in enumerate(pieces_row): char = PIECES.get(piece_char, '?') row += f" {char} |" row += " 8" lines.append(row) lines.append(" +---+---+---+---+---+---+---+---+") for line in lines: output.write(line + "\n") rendered = output.getvalue() assert "a b c" in rendered assert "♜" in rendered # Black rook assert "+---+" in rendered def test_narrow_terminal_render(): """Test that menu renders correctly on narrow terminals.""" output = StringIO() console = Console(file=output, width=40, height=20, force_terminal=True) # Small terminal fallback console.print(Align.center(Text("♟ SHELLMATE ♟", style="bold green"))) console.print() menu_table = Table(show_header=False, box=None) menu_table.add_column(justify="center") menu_table.add_row(Text("Welcome!", style="cyan")) menu_table.add_row("[dim]1. Play[/dim]") menu_table.add_row("[dim]q. Quit[/dim]") console.print(Align.center(menu_table)) rendered = output.getvalue() assert "SHELLMATE" in rendered def test_markup_escape_special_chars(): """Test that usernames with special chars don't break markup.""" output = StringIO() console = Console(file=output, width=80, height=24, force_terminal=True) # Usernames that could break markup test_usernames = [ "normal_user", "user[with]brackets", "userangles", "[admin]", "test/path", ] for username in test_usernames: # Using Text() object safely escapes special characters console.print(Text(f"Welcome, {username}!", style="cyan")) rendered = output.getvalue() assert "normal_user" in rendered # Text() should have escaped the brackets safely