Back to Repositories

Testing Panel Component Rendering and Styling in Textualize/rich

This test suite validates the Panel component functionality in the Rich library, focusing on rendering panels with various configurations and styles. The tests ensure proper panel formatting, sizing, and title/subtitle display.

Test Coverage Overview

The test suite provides comprehensive coverage of the Panel component’s core features.

  • Basic panel rendering with different content
  • Panel sizing and expansion behavior
  • Nested panel rendering
  • Title and subtitle handling
  • Console width and measurement validation
  • ANSI color and styling verification

Implementation Analysis

The tests utilize pytest’s parametrize feature for efficient test case management. The implementation focuses on comparing rendered output against expected string representations, using StringIO for console output capture and verification.

Key patterns include fixture-based testing, console dimension control, and style verification using ANSI escape sequences.

Technical Details

  • Testing Framework: pytest
  • Key Dependencies: rich.console, rich.panel, rich.segment
  • Mock Console: StringIO-based output capture
  • Test Utilities: Console width/height control, ANSI color support

Best Practices Demonstrated

The test suite exemplifies several testing best practices.

  • Parameterized test cases for multiple scenarios
  • Isolated console environment for consistent testing
  • Explicit dimension and styling control
  • Comprehensive edge case coverage
  • Clear separation of test cases and expected results

textualize/rich

tests/test_panel.py

            
import io

import pytest

from rich.console import Console
from rich.panel import Panel
from rich.segment import Segment
from rich.style import Style
from rich.text import Text

tests = [
    Panel("Hello, World", padding=0),
    Panel("Hello, World", expand=False, padding=0),
    Panel.fit("Hello, World", padding=0),
    Panel("Hello, World", width=8, padding=0),
    Panel(Panel("Hello, World", padding=0), padding=0),
    Panel("Hello, World", title="FOO", padding=0),
    Panel("Hello, World", subtitle="FOO", padding=0),
]

expected = [
    "╭────────────────────────────────────────────────╮
│Hello, World                                    │
╰────────────────────────────────────────────────╯
",
    "╭────────────╮
│Hello, World│
╰────────────╯
",
    "╭────────────╮
│Hello, World│
╰────────────╯
",
    "╭──────╮
│Hello,│
│World │
╰──────╯
",
    "╭────────────────────────────────────────────────╮
│╭──────────────────────────────────────────────╮│
││Hello, World                                  ││
│╰──────────────────────────────────────────────╯│
╰────────────────────────────────────────────────╯
",
    "╭───────────────────── FOO ──────────────────────╮
│Hello, World                                    │
╰────────────────────────────────────────────────╯
",
    "╭────────────────────────────────────────────────╮
│Hello, World                                    │
╰───────────────────── FOO ──────────────────────╯
",
]


def render(panel, width=50) -> str:
    console = Console(file=io.StringIO(), width=50, legacy_windows=False)
    console.print(panel)
    result = console.file.getvalue()
    print(result)
    return result


@pytest.mark.parametrize("panel,expected", zip(tests, expected))
def test_render_panel(panel, expected) -> None:
    assert render(panel) == expected


def test_console_width() -> None:
    console = Console(file=io.StringIO(), width=50, legacy_windows=False)
    panel = Panel("Hello, World", expand=False)
    min_width, max_width = panel.__rich_measure__(console, console.options)
    assert min_width == 16
    assert max_width == 16


def test_fixed_width() -> None:
    console = Console(file=io.StringIO(), width=50, legacy_windows=False)
    panel = Panel("Hello World", width=20)
    min_width, max_width = panel.__rich_measure__(console, console.options)
    assert min_width == 20
    assert max_width == 20


def test_render_size() -> None:
    console = Console(width=63, height=46, legacy_windows=False)
    options = console.options.update_dimensions(80, 4)
    lines = console.render_lines(Panel("foo", title="Hello"), options=options)
    print(repr(lines))
    expected = [
        [
            Segment("╭─", Style()),
            Segment(
                "────────────────────────────────── Hello ───────────────────────────────────"
            ),
            Segment("─╮", Style()),
        ],
        [
            Segment("│", Style()),
            Segment(" ", Style()),
            Segment("foo"),
            Segment(
                "                                                                         ",
                Style(),
            ),
            Segment(" ", Style()),
            Segment("│", Style()),
        ],
        [
            Segment("│", Style()),
            Segment(" ", Style()),
            Segment(
                "                                                                            ",
                Style(),
            ),
            Segment(" ", Style()),
            Segment("│", Style()),
        ],
        [
            Segment(
                "╰──────────────────────────────────────────────────────────────────────────────╯",
                Style(),
            )
        ],
    ]
    assert lines == expected


def test_title_text() -> None:
    panel = Panel(
        "Hello, World",
        title=Text("title", style="red"),
        subtitle=Text("subtitle", style="magenta bold"),
    )
    console = Console(
        file=io.StringIO(),
        width=50,
        height=20,
        legacy_windows=False,
        force_terminal=True,
        color_system="truecolor",
    )
    console.print(panel)

    result = console.file.getvalue()
    print(repr(result))
    expected = "╭────────────────────\x1b[31m title \x1b[0m─────────────────────╮
│ Hello, World                                   │
╰───────────────────\x1b[1;35m subtitle \x1b[0m───────────────────╯
"
    assert result == expected


if __name__ == "__main__":
    expected = []
    for panel in tests:
        result = render(panel)
        print(result)
        expected.append(result)
    print("--")
    print()
    print(f"expected={repr(expected)}")