Skip to content

Commit 2c15685

Browse files
tests
1 parent c334805 commit 2c15685

File tree

1 file changed

+108
-0
lines changed

1 file changed

+108
-0
lines changed

keras_remote/cli/output_test.py

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
"""Tests for keras_remote.cli.output — LiveOutputPanel."""
2+
3+
from unittest import mock
4+
5+
from absl.testing import absltest
6+
from rich.console import Console
7+
from rich.text import Text
8+
9+
from keras_remote.cli.output import LiveOutputPanel
10+
11+
12+
def _make_non_terminal_console():
13+
"""Create a Console that reports is_terminal=False."""
14+
return Console(force_terminal=False, file=open("/dev/null", "w"))
15+
16+
17+
class MakePanelTest(absltest.TestCase):
18+
"""Tests for _make_panel rendering logic."""
19+
20+
def test_shows_last_max_lines(self):
21+
panel = LiveOutputPanel("Title", max_lines=3)
22+
for i in range(10):
23+
panel._lines.append(f"line {i}")
24+
25+
content = panel._make_panel().renderable
26+
27+
self.assertNotIn("line 6", content)
28+
self.assertIn("line 7", content)
29+
self.assertIn("line 9", content)
30+
31+
def test_error_shows_all_lines(self):
32+
panel = LiveOutputPanel("Title", max_lines=3)
33+
for i in range(10):
34+
panel._lines.append(f"line {i}")
35+
panel._has_error = True
36+
37+
content = panel._make_panel().renderable
38+
39+
self.assertIn("line 0", content)
40+
self.assertIn("line 9", content)
41+
42+
def test_subtitle_suppressed_on_error(self):
43+
panel = LiveOutputPanel("Title")
44+
panel._has_error = True
45+
46+
self.assertIsNone(panel._make_panel().subtitle)
47+
48+
def test_subtitle_suppressed_when_show_subtitle_false(self):
49+
panel = LiveOutputPanel("Title", show_subtitle=False)
50+
panel._start_time = 0
51+
panel._phrase_order = list(range(10))
52+
53+
self.assertIsNone(panel._make_panel().subtitle)
54+
55+
56+
class TransientBehaviorTest(absltest.TestCase):
57+
"""Tests for transient panel clearing/persistence on exit."""
58+
59+
def test_transient_clears_on_success(self):
60+
panel = LiveOutputPanel("Test", transient=True)
61+
panel._live = mock.MagicMock()
62+
panel.on_output("some output")
63+
64+
panel.__exit__(None, None, None)
65+
66+
update_calls = [
67+
c
68+
for c in panel._live.update.call_args_list
69+
if isinstance(c.args[0], Text)
70+
]
71+
self.assertLen(update_calls, 1)
72+
73+
def test_transient_persists_on_mark_error(self):
74+
panel = LiveOutputPanel("Test", transient=True)
75+
panel._live = mock.MagicMock()
76+
panel.on_output("some output")
77+
panel.mark_error()
78+
79+
panel.__exit__(None, None, None)
80+
81+
update_calls = [
82+
c
83+
for c in panel._live.update.call_args_list
84+
if isinstance(c.args[0], Text)
85+
]
86+
self.assertEmpty(update_calls)
87+
88+
def test_transient_persists_on_exception(self):
89+
console = _make_non_terminal_console()
90+
panel = LiveOutputPanel("Test", transient=True, target_console=console)
91+
92+
with self.assertRaises(RuntimeError), panel:
93+
raise RuntimeError("fail")
94+
95+
self.assertTrue(panel._has_error)
96+
97+
def test_exception_sets_has_error_without_mark_error(self):
98+
console = _make_non_terminal_console()
99+
panel = LiveOutputPanel("Test", target_console=console)
100+
101+
with self.assertRaises(TypeError), panel:
102+
raise TypeError("bad")
103+
104+
self.assertTrue(panel._has_error)
105+
106+
107+
if __name__ == "__main__":
108+
absltest.main()

0 commit comments

Comments
 (0)