Skip to content

Commit 8307321

Browse files
committed
🩹 fix(interactive-settings): improve input cancellation handling && update reset tests && sort filtered diff files
1 parent 1cb2cbe commit 8307321

File tree

3 files changed

+77
-71
lines changed

3 files changed

+77
-71
lines changed

tests/unit/test_interactive_settings.py

Lines changed: 51 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -149,16 +149,16 @@ def test_configure_global_settings_cancel_api_key(self, mock_text, mock_load):
149149

150150
mock_text.assert_called_once()
151151

152-
@patch("tgit.interactive_settings.load_global_settings")
153-
@patch("tgit.interactive_settings.questionary.text")
154-
@patch("tgit.interactive_settings.questionary.confirm")
152+
@patch("pathlib.Path.write_text")
153+
@patch("tgit.interactive_settings.json.dumps")
154+
@patch("tgit.interactive_settings.json.loads")
155155
@patch("tgit.interactive_settings.Path.home")
156-
@patch("tgit.interactive_settings.yaml.safe_load")
157-
@patch("tgit.interactive_settings.yaml.safe_dump")
158-
@patch("builtins.open", new_callable=mock_open)
159-
def test_configure_global_settings_complete(self, mock_file, mock_dump, mock_load_yaml, mock_home, mock_confirm, mock_text):
156+
@patch("tgit.interactive_settings.questionary.confirm")
157+
@patch("tgit.interactive_settings.questionary.text")
158+
@patch("tgit.interactive_settings.load_global_settings")
159+
def test_configure_global_settings_complete(self, mock_load_global_settings, mock_text, mock_confirm, mock_home, mock_loads, mock_dumps, mock_write_text):
160160
"""Test _configure_global_settings complete flow."""
161-
mock_load_yaml.return_value = {}
161+
mock_loads.return_value = {}
162162
mock_home.return_value = Path("/home/user")
163163

164164
# Mock all questionary inputs
@@ -180,17 +180,19 @@ def test_configure_global_settings_complete(self, mock_file, mock_dump, mock_loa
180180
# Verify all inputs were called
181181
assert mock_text.call_count == 3
182182
assert mock_confirm.call_count == 4
183-
mock_dump.assert_called_once()
183+
mock_write_text.assert_called_once()
184184

185185

186186
class TestConfigureWorkspaceSettings:
187187
"""Test _configure_workspace_settings function."""
188188

189189
@patch("tgit.interactive_settings.load_workspace_settings")
190+
@patch("tgit.interactive_settings.questionary.confirm")
190191
@patch("tgit.interactive_settings.questionary.text")
191-
def test_configure_workspace_settings_cancel(self, mock_text, mock_load):
192+
def test_configure_workspace_settings_cancel(self, mock_text, mock_confirm, mock_load):
192193
"""Test _configure_workspace_settings with cancel."""
193194
mock_load.return_value = {}
195+
mock_confirm.return_value.ask.return_value = True
194196
mock_text.return_value.ask.return_value = None
195197

196198
_configure_workspace_settings()
@@ -209,64 +211,42 @@ def test_reset_settings_cancel(self, mock_print, mock_select):
209211

210212
_reset_settings()
211213

212-
mock_print.assert_any_call("\n[bold red]Reset Settings[/bold red]")
214+
mock_print.assert_not_called()
213215

214216
@patch("tgit.interactive_settings.questionary.select")
215217
@patch("tgit.interactive_settings.questionary.confirm")
216218
@patch("tgit.interactive_settings.Path.home")
217219
@patch("tgit.interactive_settings.print")
218220
def test_reset_settings_global_confirmed(self, mock_print, mock_home, mock_confirm, mock_select):
219221
"""Test _reset_settings for global settings with confirmation."""
220-
mock_select.return_value.ask.return_value = "Reset global settings"
222+
mock_select.return_value.ask.return_value = "global"
221223
mock_confirm.return_value.ask.return_value = True
222224
mock_home.return_value = Path("/home/user")
223225

224-
with patch("pathlib.Path.exists", return_value=True), patch("pathlib.Path.unlink") as mock_unlink:
225-
_reset_settings()
226-
227-
mock_confirm.assert_called_once()
228-
mock_unlink.assert_called_once()
229-
230-
@patch("tgit.interactive_settings.questionary.select")
231-
@patch("tgit.interactive_settings.questionary.confirm")
232-
@patch("tgit.interactive_settings.print")
233-
def test_reset_settings_workspace_confirmed(self, mock_print, mock_confirm, mock_select):
234-
"""Test _reset_settings for workspace settings with confirmation."""
235-
mock_select.return_value.ask.return_value = "Reset workspace settings"
236-
mock_confirm.return_value.ask.return_value = True
237-
238-
with patch("pathlib.Path.exists", return_value=True), patch("pathlib.Path.unlink") as mock_unlink:
226+
with (
227+
patch("pathlib.Path.exists", return_value=True) as mock_exists,
228+
patch("pathlib.Path.unlink") as mock_unlink,
229+
):
239230
_reset_settings()
240231

241232
mock_confirm.assert_called_once()
242233
mock_unlink.assert_called_once()
234+
mock_print.assert_any_call("[green]Global settings reset successfully![/green]")
243235

244236
@patch("tgit.interactive_settings.questionary.select")
245237
@patch("tgit.interactive_settings.questionary.confirm")
246238
@patch("tgit.interactive_settings.Path.home")
247239
@patch("tgit.interactive_settings.print")
248240
def test_reset_settings_global_cancelled(self, mock_print, mock_home, mock_confirm, mock_select):
249241
"""Test _reset_settings for global settings cancelled."""
250-
mock_select.return_value.ask.return_value = "Reset global settings"
242+
mock_select.return_value.ask.return_value = "global"
251243
mock_confirm.return_value.ask.return_value = False
252244
mock_home.return_value = Path("/home/user")
253245

254-
with patch("pathlib.Path.exists", return_value=True), patch("pathlib.Path.unlink") as mock_unlink:
255-
_reset_settings()
256-
257-
mock_confirm.assert_called_once()
258-
mock_unlink.assert_not_called()
259-
mock_print.assert_any_call("[yellow]Reset cancelled.[/yellow]")
260-
261-
@patch("tgit.interactive_settings.questionary.select")
262-
@patch("tgit.interactive_settings.questionary.confirm")
263-
@patch("tgit.interactive_settings.print")
264-
def test_reset_settings_workspace_cancelled(self, mock_print, mock_confirm, mock_select):
265-
"""Test _reset_settings for workspace settings cancelled."""
266-
mock_select.return_value.ask.return_value = "Reset workspace settings"
267-
mock_confirm.return_value.ask.return_value = False
268-
269-
with patch("pathlib.Path.exists", return_value=True), patch("pathlib.Path.unlink") as mock_unlink:
246+
with (
247+
patch("pathlib.Path.exists", return_value=True) as mock_exists,
248+
patch("pathlib.Path.unlink") as mock_unlink,
249+
):
270250
_reset_settings()
271251

272252
mock_confirm.assert_called_once()
@@ -279,11 +259,12 @@ def test_reset_settings_workspace_cancelled(self, mock_print, mock_confirm, mock
279259
@patch("tgit.interactive_settings.print")
280260
def test_reset_settings_global_file_not_exists(self, mock_print, mock_home, mock_confirm, mock_select):
281261
"""Test _reset_settings for global settings when file doesn't exist."""
282-
mock_select.return_value.ask.return_value = "Reset global settings"
262+
mock_select.return_value.ask.return_value = "global"
283263
mock_confirm.return_value.ask.return_value = True
284264
mock_home.return_value = Path("/home/user")
285265

286-
with patch("pathlib.Path.exists", return_value=False), patch("pathlib.Path.unlink") as mock_unlink:
266+
with patch("pathlib.Path.exists", return_value=False) as mock_exists, \
267+
patch("pathlib.Path.unlink") as mock_unlink:
287268
_reset_settings()
288269

289270
mock_confirm.assert_called_once()
@@ -295,12 +276,34 @@ def test_reset_settings_global_file_not_exists(self, mock_print, mock_home, mock
295276
@patch("tgit.interactive_settings.print")
296277
def test_reset_settings_workspace_file_not_exists(self, mock_print, mock_confirm, mock_select):
297278
"""Test _reset_settings for workspace settings when file doesn't exist."""
298-
mock_select.return_value.ask.return_value = "Reset workspace settings"
279+
mock_select.return_value.ask.return_value = "workspace"
299280
mock_confirm.return_value.ask.return_value = True
300281

301-
with patch("pathlib.Path.exists", return_value=False), patch("pathlib.Path.unlink") as mock_unlink:
282+
with patch("pathlib.Path.exists", return_value=False) as mock_exists, \
283+
patch("pathlib.Path.unlink") as mock_unlink:
302284
_reset_settings()
303285

304286
mock_confirm.assert_called_once()
305287
mock_unlink.assert_not_called()
306288
mock_print.assert_any_call("[yellow]Workspace settings file does not exist.[/yellow]")
289+
290+
@patch("tgit.interactive_settings.questionary.select")
291+
@patch("tgit.interactive_settings.questionary.confirm")
292+
@patch("tgit.interactive_settings.Path.home")
293+
@patch("tgit.interactive_settings.print")
294+
def test_reset_settings_both(self, mock_print, mock_home, mock_confirm, mock_select):
295+
"""Test _reset_settings for both global and workspace settings."""
296+
mock_select.return_value.ask.return_value = "both"
297+
mock_confirm.return_value.ask.return_value = True
298+
mock_home.return_value = Path("/home/user")
299+
300+
with (
301+
patch("pathlib.Path.exists", return_value=True) as mock_exists,
302+
patch("pathlib.Path.unlink") as mock_unlink,
303+
):
304+
_reset_settings()
305+
306+
mock_confirm.assert_called_once()
307+
assert mock_unlink.call_count == 2
308+
mock_print.assert_any_call("[green]Global settings reset successfully![/green]")
309+
mock_print.assert_any_call("[green]Workspace settings reset successfully![/green]")

tgit/commit.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ def get_filtered_diff_files(repo: git.Repo) -> tuple[list[str], list[str]]:
122122
lock_files: list[str] = []
123123

124124
# 过滤文件
125-
for filename in all_changed_files:
125+
for filename in sorted(all_changed_files):
126126
if filename.endswith(".lock"):
127127
lock_files.append(filename)
128128
continue

tgit/interactive_settings.py

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -159,45 +159,48 @@ def _configure_workspace_settings() -> None:
159159
).ask():
160160
return
161161

162-
# Collect all inputs without early returns
163-
api_key = (
164-
questionary.text(
165-
"OpenAI API Key (workspace override)",
166-
default=current_settings.get("apiKey", ""),
167-
).ask()
168-
or ""
169-
)
162+
# Collect all inputs with early returns on cancel
163+
api_key = questionary.text(
164+
"OpenAI API Key (workspace override)",
165+
default=current_settings.get("apiKey", ""),
166+
).ask()
167+
if api_key is None:
168+
return
170169

171-
api_url = (
172-
questionary.text(
173-
"API URL (workspace override)",
174-
default=current_settings.get("apiUrl", ""),
175-
).ask()
176-
or ""
177-
)
170+
api_url = questionary.text(
171+
"API URL (workspace override)",
172+
default=current_settings.get("apiUrl", ""),
173+
).ask()
174+
if api_url is None:
175+
return
178176

179-
model = (
180-
questionary.text(
181-
"Model name (workspace override)",
182-
default=current_settings.get("model", ""),
183-
).ask()
184-
or ""
185-
)
177+
model = questionary.text(
178+
"Model name (workspace override)",
179+
default=current_settings.get("model", ""),
180+
).ask()
181+
if model is None:
182+
return
186183

187184
show_command = questionary.confirm(
188185
"Show git commands before execution",
189186
default=current_settings.get("show_command", True),
190187
).ask()
188+
if show_command is None:
189+
return
191190

192191
skip_confirm = questionary.confirm(
193192
"Skip confirmation prompts",
194193
default=current_settings.get("skip_confirm", False),
195194
).ask()
195+
if skip_confirm is None:
196+
return
196197

197198
commit_emoji = questionary.confirm(
198199
"Use emoji in commit messages",
199200
default=current_settings.get("commit", {}).get("emoji", False),
200201
).ask()
202+
if commit_emoji is None:
203+
return
201204

202205
# Build settings dictionary
203206
new_settings = {

0 commit comments

Comments
 (0)