Skip to content

Commit 90f3953

Browse files
test(cli): add failing tests for TableFormatter
1 parent 0ec6b6a commit 90f3953

File tree

1 file changed

+211
-0
lines changed

1 file changed

+211
-0
lines changed
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
"""Regression tests for TableFormatter class.
2+
3+
Tests focus on behavioral contracts for table rendering:
4+
- Column alignment (left, right, center)
5+
- Auto-width calculation
6+
- Header and separator rendering
7+
- Row data handling
8+
9+
Reference: R02 §5 (02-list_output_format_specification_v2.md)
10+
Reference: R06 §3.6 (06-dependency_analysis_v0.md)
11+
"""
12+
13+
import pytest
14+
15+
16+
class TestColumnDef:
17+
"""Tests for ColumnDef dataclass."""
18+
19+
def test_column_def_has_required_fields(self):
20+
"""ColumnDef must have name, width, and align fields."""
21+
from hatch.cli.cli_utils import ColumnDef
22+
23+
col = ColumnDef(name="Test", width=10)
24+
assert col.name == "Test"
25+
assert col.width == 10
26+
assert col.align == "left" # Default alignment
27+
28+
def test_column_def_accepts_auto_width(self):
29+
"""ColumnDef width can be 'auto' for auto-calculation."""
30+
from hatch.cli.cli_utils import ColumnDef
31+
32+
col = ColumnDef(name="Test", width="auto")
33+
assert col.width == "auto"
34+
35+
def test_column_def_accepts_alignment_options(self):
36+
"""ColumnDef supports left, right, and center alignment."""
37+
from hatch.cli.cli_utils import ColumnDef
38+
39+
left = ColumnDef(name="Left", width=10, align="left")
40+
right = ColumnDef(name="Right", width=10, align="right")
41+
center = ColumnDef(name="Center", width=10, align="center")
42+
43+
assert left.align == "left"
44+
assert right.align == "right"
45+
assert center.align == "center"
46+
47+
48+
class TestTableFormatter:
49+
"""Tests for TableFormatter class."""
50+
51+
def test_table_formatter_accepts_column_definitions(self):
52+
"""TableFormatter initializes with column definitions."""
53+
from hatch.cli.cli_utils import TableFormatter, ColumnDef
54+
55+
columns = [
56+
ColumnDef(name="Name", width=20),
57+
ColumnDef(name="Value", width=10),
58+
]
59+
formatter = TableFormatter(columns)
60+
assert formatter is not None
61+
62+
def test_add_row_stores_data(self):
63+
"""add_row stores row data for rendering."""
64+
from hatch.cli.cli_utils import TableFormatter, ColumnDef
65+
66+
columns = [ColumnDef(name="Col1", width=10)]
67+
formatter = TableFormatter(columns)
68+
formatter.add_row(["value1"])
69+
formatter.add_row(["value2"])
70+
71+
# Verify rows are stored (implementation detail, but necessary for render)
72+
assert len(formatter._rows) == 2
73+
74+
def test_render_produces_string_output(self):
75+
"""render() returns a string with table content."""
76+
from hatch.cli.cli_utils import TableFormatter, ColumnDef
77+
78+
columns = [ColumnDef(name="Name", width=10)]
79+
formatter = TableFormatter(columns)
80+
formatter.add_row(["Test"])
81+
82+
output = formatter.render()
83+
assert isinstance(output, str)
84+
assert len(output) > 0
85+
86+
def test_render_includes_header_row(self):
87+
"""Rendered output includes column headers."""
88+
from hatch.cli.cli_utils import TableFormatter, ColumnDef
89+
90+
columns = [
91+
ColumnDef(name="Name", width=15),
92+
ColumnDef(name="Status", width=10),
93+
]
94+
formatter = TableFormatter(columns)
95+
formatter.add_row(["test-item", "active"])
96+
97+
output = formatter.render()
98+
assert "Name" in output
99+
assert "Status" in output
100+
101+
def test_render_includes_separator_line(self):
102+
"""Rendered output includes separator line after headers."""
103+
from hatch.cli.cli_utils import TableFormatter, ColumnDef
104+
105+
columns = [ColumnDef(name="Name", width=10)]
106+
formatter = TableFormatter(columns)
107+
formatter.add_row(["Test"])
108+
109+
output = formatter.render()
110+
# Separator uses box-drawing character or dashes
111+
assert "─" in output or "-" in output
112+
113+
def test_render_includes_data_rows(self):
114+
"""Rendered output includes all added data rows."""
115+
from hatch.cli.cli_utils import TableFormatter, ColumnDef
116+
117+
columns = [ColumnDef(name="Item", width=15)]
118+
formatter = TableFormatter(columns)
119+
formatter.add_row(["first-item"])
120+
formatter.add_row(["second-item"])
121+
formatter.add_row(["third-item"])
122+
123+
output = formatter.render()
124+
assert "first-item" in output
125+
assert "second-item" in output
126+
assert "third-item" in output
127+
128+
def test_left_alignment_pads_right(self):
129+
"""Left-aligned columns pad values on the right."""
130+
from hatch.cli.cli_utils import TableFormatter, ColumnDef
131+
132+
columns = [ColumnDef(name="Name", width=10, align="left")]
133+
formatter = TableFormatter(columns)
134+
formatter.add_row(["abc"])
135+
136+
output = formatter.render()
137+
lines = output.strip().split("\n")
138+
# Find data row (skip header and separator)
139+
data_line = lines[-1]
140+
# Left-aligned: value followed by spaces
141+
assert "abc" in data_line
142+
143+
def test_right_alignment_pads_left(self):
144+
"""Right-aligned columns pad values on the left."""
145+
from hatch.cli.cli_utils import TableFormatter, ColumnDef
146+
147+
columns = [ColumnDef(name="Count", width=10, align="right")]
148+
formatter = TableFormatter(columns)
149+
formatter.add_row(["42"])
150+
151+
output = formatter.render()
152+
lines = output.strip().split("\n")
153+
data_line = lines[-1]
154+
# Right-aligned: spaces followed by value
155+
assert "42" in data_line
156+
157+
def test_auto_width_calculates_from_content(self):
158+
"""Auto width calculates based on header and data content."""
159+
from hatch.cli.cli_utils import TableFormatter, ColumnDef
160+
161+
columns = [ColumnDef(name="Name", width="auto")]
162+
formatter = TableFormatter(columns)
163+
formatter.add_row(["short"])
164+
formatter.add_row(["much-longer-value"])
165+
166+
output = formatter.render()
167+
# Output should accommodate the longest value
168+
assert "much-longer-value" in output
169+
170+
def test_empty_table_renders_headers_only(self):
171+
"""Table with no rows renders headers and separator."""
172+
from hatch.cli.cli_utils import TableFormatter, ColumnDef
173+
174+
columns = [ColumnDef(name="Empty", width=10)]
175+
formatter = TableFormatter(columns)
176+
177+
output = formatter.render()
178+
assert "Empty" in output
179+
# Should have header and separator, but no data rows
180+
181+
def test_multiple_columns_separated(self):
182+
"""Multiple columns are visually separated."""
183+
from hatch.cli.cli_utils import TableFormatter, ColumnDef
184+
185+
columns = [
186+
ColumnDef(name="Col1", width=10),
187+
ColumnDef(name="Col2", width=10),
188+
ColumnDef(name="Col3", width=10),
189+
]
190+
formatter = TableFormatter(columns)
191+
formatter.add_row(["a", "b", "c"])
192+
193+
output = formatter.render()
194+
assert "Col1" in output
195+
assert "Col2" in output
196+
assert "Col3" in output
197+
assert "a" in output
198+
assert "b" in output
199+
assert "c" in output
200+
201+
def test_truncation_with_ellipsis(self):
202+
"""Values exceeding column width are truncated with ellipsis."""
203+
from hatch.cli.cli_utils import TableFormatter, ColumnDef
204+
205+
columns = [ColumnDef(name="Name", width=8)]
206+
formatter = TableFormatter(columns)
207+
formatter.add_row(["very-long-value-that-exceeds-width"])
208+
209+
output = formatter.render()
210+
# Should truncate and add ellipsis
211+
assert "…" in output or "..." in output

0 commit comments

Comments
 (0)