Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion cecli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -1441,7 +1441,10 @@ def get_io(pretty):
pre_init_io.tool_output()
webbrowser.open(urls.release_notes)
return await graceful_exit(coder)
elif args.show_release_notes is None and is_first_run:
elif args.show_release_notes is None and is_first_run and not args.yes_always:
# Suppress the first-run release-notes prompt when --yes-always is set,
# so automated/headless runs don't have the browser hijacked by an
# auto-confirmed offer_url. Explicit --show-release-notes still opens.
pre_init_io.tool_output()
await pre_init_io.offer_url(
urls.release_notes,
Expand Down
32 changes: 32 additions & 0 deletions tests/basic/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,38 @@ def test_main_exit_calls_version_check(dummy_io, git_temp_dir, mocker):
mock_input_output.assert_called_once()


def test_suppress_release_notes_prompt_with_yes_always(dummy_io, git_temp_dir, mocker):
mock_input_output = mocker.patch("cecli.io.InputOutput")
mock_input_output.return_value.confirm_ask = AsyncMock(return_value=True)
mock_input_output.return_value.offer_url = AsyncMock()
mocker.patch("cecli.main.is_first_run_of_new_version", return_value=True)

main(["--exit", "--yes-always"], **dummy_io)
mock_input_output.return_value.offer_url.assert_not_called()


def test_shows_release_notes_prompt_on_first_run(dummy_io, git_temp_dir, mocker):
mock_input_output = mocker.patch("cecli.io.InputOutput")
mock_input_output.return_value.confirm_ask = AsyncMock(return_value=True)
mock_input_output.return_value.offer_url = AsyncMock()
mocker.patch("cecli.main.is_first_run_of_new_version", return_value=True)

main(["--exit"], **dummy_io)
mock_input_output.return_value.offer_url.assert_called_once()


def test_explicit_show_release_notes_with_yes_always(dummy_io, git_temp_dir, mocker):
mock_input_output = mocker.patch("cecli.io.InputOutput")
mock_input_output.return_value.confirm_ask = AsyncMock(return_value=True)
mock_input_output.return_value.offer_url = AsyncMock()
mocker.patch("cecli.main.is_first_run_of_new_version", return_value=True)
mocker.patch("webbrowser.open")

main(["--exit", "--yes-always", "--show-release-notes"], **dummy_io)
# The explicit --show-release-notes code path uses webbrowser.open directly, not offer_url
mock_input_output.return_value.offer_url.assert_not_called()


def test_main_message_adds_to_input_history(dummy_io, mocker):
mocker.patch("cecli.coders.base_coder.Coder.run")
MockInputOutput = mocker.patch("cecli.io.InputOutput", autospec=True)
Expand Down
Loading