Skip to content

Commit e1a1d3c

Browse files
committed
test: add tests for new model selection
1 parent 3f50778 commit e1a1d3c

File tree

5 files changed

+115
-21
lines changed

5 files changed

+115
-21
lines changed

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
- Run commands should be prefixed with `uv`: `uv run ...`
99
- Use `asyncio` features, if such is needed
1010
- Prefer early returns
11+
- Private methods always go below public methods
1112
- Absolutely no useless comments! Every class and method does not need to be documented (unless it is legitimetly complex or "lib-ish")
1213
- Imports belong at the top of files, not inside functions (unless needed to avoid circular imports)
1314

src/agent_chat_cli/components/model_selection_menu.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
from agent_chat_cli.core.actions import Actions
1111

1212
MODELS = [
13-
{"id": "opus", "label": "Opus"},
1413
{"id": "sonnet", "label": "Sonnet"},
1514
{"id": "haiku", "label": "Haiku"},
15+
{"id": "opus", "label": "Opus"},
1616
]
1717

1818

src/agent_chat_cli/core/styles.tcss

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -108,34 +108,17 @@ TextArea .text-area--cursor {
108108
padding-left: 2;
109109
}
110110

111-
SlashCommandMenu {
111+
SlashCommandMenu, ModelSelectionMenu {
112112
height: auto;
113113
max-height: 10;
114114
display: none;
115115
}
116116

117-
SlashCommandMenu.visible {
117+
SlashCommandMenu.visible, ModelSelectionMenu.visible {
118118
display: block;
119119
}
120120

121-
SlashCommandMenu OptionList {
122-
height: auto;
123-
max-height: 10;
124-
border: solid $primary;
125-
background: transparent;
126-
}
127-
128-
ModelSelectionMenu {
129-
height: auto;
130-
max-height: 10;
131-
display: none;
132-
}
133-
134-
ModelSelectionMenu.visible {
135-
display: block;
136-
}
137-
138-
ModelSelectionMenu OptionList {
121+
SlashCommandMenu OptionList, ModelSelectionMenu OptionList {
139122
height: auto;
140123
max-height: 10;
141124
border: solid $primary;
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import pytest
2+
from unittest.mock import AsyncMock, MagicMock
3+
4+
from textual.app import App, ComposeResult
5+
from textual.widgets import OptionList
6+
7+
from agent_chat_cli.components.model_selection_menu import ModelSelectionMenu
8+
9+
10+
class ModelSelectionMenuApp(App):
11+
def __init__(self):
12+
super().__init__()
13+
self.mock_actions = MagicMock()
14+
self.mock_actions.change_model = AsyncMock()
15+
16+
def compose(self) -> ComposeResult:
17+
yield ModelSelectionMenu(actions=self.mock_actions)
18+
19+
20+
class TestModelSelectionMenuVisibility:
21+
@pytest.fixture
22+
def app(self):
23+
return ModelSelectionMenuApp()
24+
25+
async def test_hidden_by_default(self, app):
26+
async with app.run_test():
27+
menu = app.query_one(ModelSelectionMenu)
28+
29+
assert menu.is_visible is False
30+
31+
async def test_show_makes_visible(self, app):
32+
async with app.run_test():
33+
menu = app.query_one(ModelSelectionMenu)
34+
menu.show()
35+
36+
assert menu.is_visible is True
37+
38+
async def test_hide_makes_invisible(self, app):
39+
async with app.run_test():
40+
menu = app.query_one(ModelSelectionMenu)
41+
menu.show()
42+
menu.hide()
43+
44+
assert menu.is_visible is False
45+
46+
async def test_show_highlights_first_option(self, app):
47+
async with app.run_test():
48+
menu = app.query_one(ModelSelectionMenu)
49+
menu.show()
50+
51+
option_list = menu.query_one(OptionList)
52+
assert option_list.highlighted == 0
53+
54+
55+
class TestModelSelectionMenuSelection:
56+
@pytest.fixture
57+
def app(self):
58+
return ModelSelectionMenuApp()
59+
60+
async def test_sonnet_command_calls_change_model(self, app):
61+
async with app.run_test() as pilot:
62+
menu = app.query_one(ModelSelectionMenu)
63+
menu.show()
64+
65+
await pilot.press("enter")
66+
67+
app.mock_actions.change_model.assert_called_once_with("sonnet")
68+
69+
async def test_haiku_command_calls_change_model(self, app):
70+
async with app.run_test() as pilot:
71+
menu = app.query_one(ModelSelectionMenu)
72+
menu.show()
73+
74+
await pilot.press("down")
75+
await pilot.press("enter")
76+
77+
app.mock_actions.change_model.assert_called_once_with("haiku")
78+
79+
async def test_opus_command_calls_change_model(self, app):
80+
async with app.run_test() as pilot:
81+
menu = app.query_one(ModelSelectionMenu)
82+
menu.show()
83+
84+
await pilot.press("down")
85+
await pilot.press("down")
86+
await pilot.press("enter")
87+
88+
app.mock_actions.change_model.assert_called_once_with("opus")
89+
90+
async def test_selection_hides_menu(self, app):
91+
async with app.run_test() as pilot:
92+
menu = app.query_one(ModelSelectionMenu)
93+
menu.show()
94+
95+
await pilot.press("enter")
96+
97+
assert menu.is_visible is False

tests/components/test_slash_command_menu.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ def __init__(self):
1515
self.mock_actions.clear = AsyncMock()
1616
self.mock_actions.new = AsyncMock()
1717
self.mock_actions.save = AsyncMock()
18+
self.mock_actions.show_model_menu = MagicMock()
1819

1920
def compose(self) -> ComposeResult:
2021
yield SlashCommandMenu(actions=self.mock_actions)
@@ -79,6 +80,17 @@ async def test_clear_command_calls_clear(self, app):
7980

8081
app.mock_actions.clear.assert_called_once()
8182

83+
async def test_model_command_calls_show_model_menu(self, app):
84+
async with app.run_test() as pilot:
85+
menu = app.query_one(SlashCommandMenu)
86+
menu.show()
87+
88+
await pilot.press("down")
89+
await pilot.press("down")
90+
await pilot.press("enter")
91+
92+
app.mock_actions.show_model_menu.assert_called_once()
93+
8294
async def test_exit_command_calls_quit(self, app):
8395
async with app.run_test() as pilot:
8496
menu = app.query_one(SlashCommandMenu)
@@ -87,6 +99,7 @@ async def test_exit_command_calls_quit(self, app):
8799
await pilot.press("down")
88100
await pilot.press("down")
89101
await pilot.press("down")
102+
await pilot.press("down")
90103
await pilot.press("enter")
91104

92105
app.mock_actions.quit.assert_called_once()

0 commit comments

Comments
 (0)