From ad4f13e5c9f2cfcc2452c8b6f6adac9c9152c293 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 12 Jun 2026 03:40:40 +0000 Subject: [PATCH] Tighten hand-rolled test fakes to mirror real boundary signatures Replace trailing **kwargs catch-alls on monkeypatched doubles with the full explicit signature of the boundary they stand in for (stream_audio, agent run_session, run_login_flow, llm.run_chain, coding_agent.run, subprocess.run/Popen, httpx.get, typer.confirm, run_init, launch_app, Console.status), so a renamed/removed/typo'd kwarg at the call site fails loudly with a TypeError instead of being silently swallowed. Left intact, deliberately: - delegating wrappers (httpx.Client/os.access) where the real callee enforces the signature - fakes whose captured kwargs dict is itself the assertion subject (exact-set or absence asserts in test_telemetry/test_init_runner) - never-called trackers whose tests assert zero invocations https://claude.ai/code/session_01XVarv54ryA8Eo9zohCKx77 --- tests/test_agent_command.py | 14 ++++----- tests/test_coding_agent.py | 6 ++-- tests/test_context.py | 2 +- tests/test_deploy.py | 6 ++-- tests/test_init_template_serve.py | 2 +- tests/test_login.py | 10 +++++-- tests/test_login_guards.py | 2 +- tests/test_macos_audio_source.py | 4 +-- tests/test_onboard_sections.py | 32 ++++++++++++++++++--- tests/test_output.py | 2 +- tests/test_stream_command.py | 46 +++++++++++++++++------------- tests/test_stream_command_flags.py | 4 ++- tests/test_stream_llm.py | 8 +++--- tests/test_stream_session.py | 24 ++++++++++------ tests/test_streaming_sources.py | 2 +- tests/test_update_check.py | 17 +++++++---- 16 files changed, 117 insertions(+), 64 deletions(-) diff --git a/tests/test_agent_command.py b/tests/test_agent_command.py index de0ea243..ee69be43 100644 --- a/tests/test_agent_command.py +++ b/tests/test_agent_command.py @@ -30,7 +30,7 @@ def test_agent_help_lists_command(): def test_list_voices_prints_and_exits_without_connecting(monkeypatch): called = {"ran": False} - def fake_run_session(*a, **k): + def fake_run_session(api_key, *, renderer, player, mic, config): called["ran"] = True monkeypatch.setattr("aai_cli.commands.agent.run_session", fake_run_session) @@ -61,7 +61,7 @@ def test_agent_unauthenticated_runs_login(monkeypatch): monkeypatch.setattr("aai_cli.context.run_login_flow", _login_result) monkeypatch.setattr("aai_cli.commands.agent.FileSource", lambda src: f"filesrc:{src}") - def fake_run_session(api_key, **_kwargs): + def fake_run_session(api_key, *, renderer, player, mic, config): raise AssertionError(f"agent session should not run after auto-login: {api_key}") monkeypatch.setattr("aai_cli.commands.agent.run_session", fake_run_session) @@ -157,8 +157,8 @@ def _capture_run_session(monkeypatch): """Patch run_session to record its kwargs and return the dict it fills in.""" seen = {} - def fake_run_session(api_key, **kwargs): - seen.update(kwargs) + def fake_run_session(api_key, *, renderer, player, mic, config): + seen.update(renderer=renderer, player=player, mic=mic, config=config) monkeypatch.setattr("aai_cli.commands.agent.run_session", fake_run_session) return seen @@ -227,7 +227,7 @@ def test_agent_file_source_no_start_talking_notice(monkeypatch, tmp_path): monkeypatch.setattr("aai_cli.output.resolve_json", lambda *, explicit: False) monkeypatch.setattr("aai_cli.commands.agent.FileSource", lambda src: "filesrc") - def fake_run_session(api_key, *, renderer, **kwargs): + def fake_run_session(api_key, *, renderer, player, mic, config): renderer.connected() # session.ready arrives even for a file-driven run monkeypatch.setattr("aai_cli.commands.agent.run_session", fake_run_session) @@ -257,7 +257,7 @@ def close(self): monkeypatch.setattr("aai_cli.commands.agent.DuplexAudio", FakeDuplex) - def fake_run_session(api_key, *, renderer, **kwargs): + def fake_run_session(api_key, *, renderer, player, mic, config): renderer.connected() monkeypatch.setattr("aai_cli.commands.agent.run_session", fake_run_session) @@ -344,7 +344,7 @@ def test_agent_output_text_emits_plain_transcript(monkeypatch): config.set_api_key("default", "sk_live") monkeypatch.setattr("aai_cli.commands.agent.FileSource", lambda src: "filesrc") - def fake_run_session(api_key, *, renderer, **kwargs): + def fake_run_session(api_key, *, renderer, player, mic, config): renderer.user_final("hello there") renderer.agent_transcript("hi, how can I help?", interrupted=False) diff --git a/tests/test_coding_agent.py b/tests/test_coding_agent.py index dc2f0674..786efb53 100644 --- a/tests/test_coding_agent.py +++ b/tests/test_coding_agent.py @@ -79,7 +79,7 @@ def test_skill_presence_requires_skill_md(tmp_path): def test_mcp_present_when_claude_mcp_get_succeeds(monkeypatch): calls = [] - def fake_run(cmd, **kwargs): + def fake_run(cmd, *, timeout=120): calls.append(list(cmd)) return subprocess.CompletedProcess(args=cmd, returncode=0, stdout="", stderr="") @@ -92,7 +92,9 @@ def test_mcp_absent_when_claude_mcp_get_fails(monkeypatch): monkeypatch.setattr( coding_agent, "run", - lambda cmd, **kw: subprocess.CompletedProcess(args=cmd, returncode=1, stdout="", stderr=""), + lambda cmd, *, timeout=120: subprocess.CompletedProcess( + args=cmd, returncode=1, stdout="", stderr="" + ), ) assert coding_agent.mcp_present() is False diff --git a/tests/test_context.py b/tests/test_context.py index c9e3e5db..948d8126 100644 --- a/tests/test_context.py +++ b/tests/test_context.py @@ -343,7 +343,7 @@ def test_run_command_auto_logs_in_when_env_key_set_but_error_is_not_a_rejection( monkeypatch.setenv(config.ENV_API_KEY, "sk_env") ran = {"login": 0} - def fake_login(**_kwargs): + def fake_login(*, json_mode=False): ran["login"] += 1 return LoginResult(api_key="sk_auto", session_jwt="j", session_token="t", account_id=7) diff --git a/tests/test_deploy.py b/tests/test_deploy.py index 70ea0d4e..77269c20 100644 --- a/tests/test_deploy.py +++ b/tests/test_deploy.py @@ -55,16 +55,16 @@ def _stub( monkeypatch.setattr("aai_cli.output.is_agentic", lambda: agentic) calls: dict[str, object] = {} - def fake_confirm(prompt: str, *a: object, **k: object) -> bool: + def fake_confirm(prompt: str) -> bool: calls["prompt"] = prompt return confirm monkeypatch.setattr("typer.confirm", fake_confirm) - def fake_run(cmd: list[str], **kwargs: object) -> types.SimpleNamespace: + def fake_run(cmd: list[str], *, cwd: Path, check: bool) -> types.SimpleNamespace: runs = calls.setdefault("runs", []) assert isinstance(runs, list) - runs.append({"cmd": cmd, "cwd": kwargs.get("cwd"), "check": kwargs.get("check")}) + runs.append({"cmd": cmd, "cwd": cwd, "check": check}) return types.SimpleNamespace(returncode=returncode) monkeypatch.setattr("aai_cli.commands.deploy.subprocess.run", fake_run) diff --git a/tests/test_init_template_serve.py b/tests/test_init_template_serve.py index 13a9b630..00bd120f 100644 --- a/tests/test_init_template_serve.py +++ b/tests/test_init_template_serve.py @@ -240,7 +240,7 @@ def test_ask_failure_is_graceful(monkeypatch: pytest.MonkeyPatch) -> None: @pytest.mark.parametrize("template", TOKEN_TEMPLATES) def test_token_mints_token_and_ws_url(template: str, monkeypatch: pytest.MonkeyPatch) -> None: - def fake_get(*_args: object, **_kwargs: object) -> object: + def fake_get(url: str, *, params: object, headers: object) -> object: return SimpleNamespace(raise_for_status=lambda: None, json=lambda: {"token": "tok-1"}) with serve(template) as (module, client): diff --git a/tests/test_login.py b/tests/test_login.py index b5e2b759..993e12fc 100644 --- a/tests/test_login.py +++ b/tests/test_login.py @@ -9,10 +9,14 @@ runner = CliRunner() -def _fake_login_result(key="sk_from_oauth", **_kwargs): +def _login_result(key="sk_from_oauth"): return LoginResult(api_key=key, session_jwt="jwt_x", session_token="tok_x", account_id=7) +def _fake_login_result(*, json_mode=False): + return _login_result() + + def test_login_with_api_key_flag_stores_key(mocker): mocker.patch("aai_cli.commands.login.client.validate_key", autospec=True, return_value=True) result = runner.invoke(app, ["login", "--api-key", "sk_flag", "--json"]) @@ -227,7 +231,9 @@ def test_login_binds_env_to_profile(monkeypatch): def test_sandbox_flag_is_shortcut_for_env(monkeypatch): - monkeypatch.setattr("aai_cli.context.run_login_flow", lambda **_: _fake_login_result("sk_x")) + monkeypatch.setattr( + "aai_cli.context.run_login_flow", lambda *, json_mode=False: _login_result("sk_x") + ) result = runner.invoke(app, ["--sandbox", "login"]) assert result.exit_code == 0 assert config.get_profile_env("default") == "sandbox000" diff --git a/tests/test_login_guards.py b/tests/test_login_guards.py index 28bc0378..2fa62a25 100644 --- a/tests/test_login_guards.py +++ b/tests/test_login_guards.py @@ -14,7 +14,7 @@ runner = CliRunner() -def _fake_login_result(key="sk_from_oauth", **_kwargs): +def _fake_login_result(key="sk_from_oauth"): return LoginResult(api_key=key, session_jwt="jwt_x", session_token="tok_x", account_id=7) diff --git a/tests/test_macos_audio_source.py b/tests/test_macos_audio_source.py index 5266d1bd..fd19a478 100644 --- a/tests/test_macos_audio_source.py +++ b/tests/test_macos_audio_source.py @@ -64,9 +64,9 @@ def test_build_helper_compiles_to_cache(monkeypatch, tmp_path): monkeypatch.setattr(macos, "user_cache_path", lambda _app: tmp_path) seen = {} - def fake_run(cmd, **kwargs): + def fake_run(cmd, *, capture_output, text, check): seen["cmd"] = cmd - seen["kwargs"] = kwargs + seen["kwargs"] = {"capture_output": capture_output, "text": text, "check": check} Path(cmd[-1]).write_bytes(b"binary") return types.SimpleNamespace(returncode=0, stderr="", stdout="") diff --git a/tests/test_onboard_sections.py b/tests/test_onboard_sections.py index 98198729..3a4939d8 100644 --- a/tests/test_onboard_sections.py +++ b/tests/test_onboard_sections.py @@ -254,10 +254,32 @@ def test_build_path_scaffolds(ctx: WizardContext, monkeypatch: pytest.MonkeyPatc calls = 0 seen: dict[str, object] = {} - def _fake_run_init(*a: object, **k: object) -> Path: + def _fake_run_init( + state: object, + *, + template: str | None, + directory: str | None, + no_install: bool, + no_open: bool, + force: bool, + here: bool, + port: int, + json_mode: bool, + launch: bool = True, + ) -> Path: nonlocal calls calls += 1 - seen.update(k) + seen.update( + template=template, + directory=directory, + no_install=no_install, + no_open=no_open, + force=force, + here=here, + port=port, + json_mode=json_mode, + launch=launch, + ) return Path("/scaffolded/app") monkeypatch.setattr(init_cmd, "run_init", _fake_run_init) @@ -354,9 +376,11 @@ def _spy_launch(monkeypatch: pytest.MonkeyPatch) -> dict[str, object]: """Replace init's launch_app with a recorder; returns the captured target + kwargs.""" captured: dict[str, object] = {} - def _fake_launch(target: Path, **k: object) -> None: + def _fake_launch( + target: Path, *, port: int, use_uv: bool, no_open: bool, json_mode: bool + ) -> None: captured["target"] = target - captured.update(k) + captured.update(port=port, use_uv=use_uv, no_open=no_open, json_mode=json_mode) monkeypatch.setattr(init_cmd, "launch_app", _fake_launch) return captured diff --git a/tests/test_output.py b/tests/test_output.py index 018d5d68..962ddfab 100644 --- a/tests/test_output.py +++ b/tests/test_output.py @@ -263,7 +263,7 @@ def test_status_enters_spinner_when_not_json_and_not_quiet(monkeypatch): entered = {"status": False} @contextlib.contextmanager - def fake_status(*a, **k): + def fake_status(message): entered["status"] = True yield diff --git a/tests/test_stream_command.py b/tests/test_stream_command.py index ab7bca21..897c309d 100644 --- a/tests/test_stream_command.py +++ b/tests/test_stream_command.py @@ -21,9 +21,7 @@ runner = CliRunner() -def _drive_turns( - api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None, **_kwargs -): +def _drive_turns(api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None): # Simulate the streaming client driving the renderer callbacks. if on_begin: on_begin(types.SimpleNamespace(id="sess")) @@ -57,7 +55,7 @@ def test_stream_file_uses_filesource(monkeypatch, tmp_path): seen = {} def fake_stream_audio( - api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None, **_kwargs + api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None ): seen["source_type"] = type(source).__name__ seen["rate"] = params.sample_rate @@ -96,7 +94,9 @@ def __iter__(self): order = [] - def fake_stream_audio(api_key, source, *, params, on_begin=None, **_kwargs): + def fake_stream_audio( + api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None + ): if on_begin: on_begin(types.SimpleNamespace(id="x")) # Begin must NOT print "Listening…" order.append("begin") @@ -114,7 +114,7 @@ def test_stream_file_shows_no_listening_notice(monkeypatch, tmp_path): config.set_api_key("default", "sk_live") monkeypatch.setattr("aai_cli.output.resolve_json", lambda *, explicit: False) - def fake(api_key, source, *, params, on_begin=None, **_kwargs): + def fake(api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None): if on_begin: on_begin(types.SimpleNamespace(id="x")) @@ -136,7 +136,9 @@ def test_stream_unauthenticated_runs_login(monkeypatch): monkeypatch.setattr("aai_cli.context._interactive_session", lambda: True) monkeypatch.setattr("aai_cli.context.run_login_flow", _login_result) - def fake_stream_audio(api_key, source, *, params, **_kwargs): + def fake_stream_audio( + api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None + ): raise AssertionError(f"streaming should not start after auto-login: {api_key}") monkeypatch.setattr("aai_cli.commands.stream.client.stream_audio", fake_stream_audio) @@ -147,9 +149,7 @@ def fake_stream_audio(api_key, source, *, params, **_kwargs): def _capture_source(seen): - def fake( - api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None, **_kwargs - ): + def fake(api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None): seen["source"] = source seen["rate"] = params.sample_rate @@ -222,9 +222,7 @@ def test_stream_file_json_output(monkeypatch, tmp_path): config.set_api_key("default", "sk_live") - def fake( - api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None, **_kwargs - ): + def fake(api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None): # In non-follow mode begin/turn/termination must all be wired through to the # renderer (pins the `follow is not None` None-vs-handler choices). if on_begin: @@ -253,7 +251,7 @@ def test_stream_prompt_biases_speech_model(monkeypatch): config.set_api_key("default", "sk_live") seen = {} - def fake(api_key, source, *, params, **kwargs): + def fake(api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None): seen["prompt"] = params.prompt monkeypatch.setattr("aai_cli.commands.stream.client.stream_audio", fake) @@ -276,7 +274,7 @@ def test_stream_youtube_url_downloads_then_streams(monkeypatch, tmp_path): monkeypatch.setattr("aai_cli.commands.stream.youtube.download_audio", lambda url, d: fake) seen = {} - def fake_stream(api_key, source, *, params, **kwargs): + def fake_stream(api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None): seen["source_type"] = type(source).__name__ seen["src"] = getattr(source, "source", None) @@ -300,7 +298,7 @@ def test_stream_podcast_page_url_downloads_then_streams(monkeypatch, tmp_path): monkeypatch.setattr("aai_cli.commands.stream.youtube.download_audio", lambda url, d: fake) seen = {} - def fake_stream(api_key, source, *, params, **kwargs): + def fake_stream(api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None): seen["source_type"] = type(source).__name__ seen["src"] = getattr(source, "source", None) @@ -347,7 +345,9 @@ def test_stream_sample_rate_floor_accepts_one_for_stdin(monkeypatch): config.set_api_key("default", "sk_live") seen = {} - def fake_stream_audio(api_key, source, *, params, **_kwargs): + def fake_stream_audio( + api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None + ): seen["rate"] = params.sample_rate b"".join(source) # drain the StdinSource @@ -361,7 +361,9 @@ def test_stream_reads_raw_pcm_from_stdin(monkeypatch): config.set_api_key("default", "sk_live") seen = {} - def fake_stream_audio(api_key, source, *, params, on_begin=None, **_kwargs): + def fake_stream_audio( + api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None + ): seen["rate"] = params.sample_rate seen["audio"] = b"".join(source) # consume the StdinSource @@ -389,7 +391,9 @@ def __init__(self, *, target_rate=None, device=None, capture_rate=None, on_open= def __iter__(self): return iter([b"mic"]) - def fake_stream_audio(api_key, source, *, params, **_kwargs): + def fake_stream_audio( + api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None + ): if type(source).__name__ == "FakeMic": raise APIError("mic failed") time.sleep(0.2) @@ -406,7 +410,9 @@ def test_stream_output_text_emits_plain_finalized_turns(monkeypatch): # `-o text` -> only finalized transcripts as plain stdout lines (pipe into assembly llm). config.set_api_key("default", "sk_live") - def fake_stream_audio(api_key, source, *, params, on_begin=None, on_turn=None, **_kwargs): + def fake_stream_audio( + api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None + ): if on_turn: on_turn(types.SimpleNamespace(transcript="partial", end_of_turn=False)) on_turn(types.SimpleNamespace(transcript="hello world", end_of_turn=True)) diff --git a/tests/test_stream_command_flags.py b/tests/test_stream_command_flags.py index 7dc06020..0bf7fdf8 100644 --- a/tests/test_stream_command_flags.py +++ b/tests/test_stream_command_flags.py @@ -15,7 +15,9 @@ def test_stream_maps_turn_detection_flags(monkeypatch): config.set_api_key("default", "sk_live") captured = {} - def fake_stream_audio(api_key, source, *, params, **kw): + def fake_stream_audio( + api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None + ): captured["params"] = params monkeypatch.setattr("aai_cli.commands.stream.client.stream_audio", fake_stream_audio) diff --git a/tests/test_stream_llm.py b/tests/test_stream_llm.py index 5f160752..f198da3c 100644 --- a/tests/test_stream_llm.py +++ b/tests/test_stream_llm.py @@ -13,7 +13,7 @@ def test_stream_llm_refreshes_live_over_growing_transcript(monkeypatch): config.set_api_key("default", "sk_live") seen = {"texts": []} - def fake(api_key, source, *, params, on_turn=None, **kwargs): + def fake(api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None): if on_turn: on_turn(types.SimpleNamespace(transcript="hola", end_of_turn=True)) on_turn(types.SimpleNamespace(transcript="mundo", end_of_turn=True)) @@ -59,7 +59,7 @@ def test_stream_llm_chains_multiple_prompts(monkeypatch): config.set_api_key("default", "sk_live") seen = {} - def fake(api_key, source, *, params, on_turn=None, **kwargs): + def fake(api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None): if on_turn: on_turn(types.SimpleNamespace(transcript="hi", end_of_turn=True)) @@ -90,11 +90,11 @@ def test_stream_without_prompt_does_not_transform(monkeypatch): config.set_api_key("default", "sk_live") called = {"ran": False} - def fake(api_key, source, *, params, on_turn=None, **kwargs): + def fake(api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None): if on_turn: on_turn(types.SimpleNamespace(transcript="hi", end_of_turn=True)) - def fake_run_chain(*a, **k): + def fake_run_chain(api_key, prompts, *, transcript_text, model, max_tokens): called["ran"] = True return "x" diff --git a/tests/test_stream_session.py b/tests/test_stream_session.py index 740e98f1..132a488d 100644 --- a/tests/test_stream_session.py +++ b/tests/test_stream_session.py @@ -12,9 +12,7 @@ def _capture_source(seen): - def fake( - api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None, **_kwargs - ): + def fake(api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None): seen["source"] = source seen["rate"] = params.sample_rate @@ -112,7 +110,9 @@ def __iter__(self): mic_on_open[0]() return iter([b"mic"]) - def fake_stream_audio(api_key, source, *, params, on_begin=None, on_turn=None, **_kwargs): + def fake_stream_audio( + api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None + ): source_type = type(source).__name__ source_types.append(source_type) rates.append(params.sample_rate) @@ -190,7 +190,9 @@ def __init__(self, *, target_rate=None, device=None, capture_rate=None, on_open= def __iter__(self): return iter([b"mic"]) - def fake_stream_audio(api_key, source, *, params, **_kwargs): + def fake_stream_audio( + api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None + ): list(source) monkeypatch.setattr("aai_cli.commands.stream.MacSystemAudioSource", FakeSystemAudio) @@ -222,7 +224,9 @@ def __init__(self, *, target_rate=None, device=None, capture_rate=None, on_open= def __iter__(self): return iter([b"mic"]) - def fake_stream_audio(api_key, source, *, params, on_turn=None, **_kwargs): + def fake_stream_audio( + api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None + ): if on_turn: on_turn(types.SimpleNamespace(transcript="", end_of_turn=True)) on_turn(types.SimpleNamespace(transcript=type(source).__name__, end_of_turn=True)) @@ -261,7 +265,9 @@ def __init__(self, *, target_rate=None, device=None, capture_rate=None, on_open= def __iter__(self): return iter([b"mic"]) - def fake_stream_audio(api_key, source, *, params, **_kwargs): + def fake_stream_audio( + api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None + ): chunk = next(iter(source)) speaker_labels_by_chunk[chunk] = params.speaker_labels @@ -308,7 +314,9 @@ def is_alive(self): def join(self, timeout=None): return None - def fake_stream_audio(api_key, source, *, params, **_kwargs): + def fake_stream_audio( + api_key, source, *, params, on_begin=None, on_turn=None, on_termination=None + ): raise APIError(f"{type(source).__name__} failed") monkeypatch.setattr("aai_cli.commands.stream.MacSystemAudioSource", FakeSystemAudio) diff --git a/tests/test_streaming_sources.py b/tests/test_streaming_sources.py index 980a6d7e..76cfeaaf 100644 --- a/tests/test_streaming_sources.py +++ b/tests/test_streaming_sources.py @@ -270,7 +270,7 @@ def terminate(self): def wait(self): pass - def fake_popen(cmd, **kwargs): + def fake_popen(cmd, *, stdout, stderr): captured["cmd"] = cmd return FakeProc() diff --git a/tests/test_update_check.py b/tests/test_update_check.py index acda8cd8..7d50a890 100644 --- a/tests/test_update_check.py +++ b/tests/test_update_check.py @@ -73,11 +73,11 @@ def test_fetch_and_cache_writes_latest(tmp_path, monkeypatch): # Untyped capture dict (mirrors the pattern in tests/test_telemetry.py). captured = {} - def fake_get(url, **kwargs): + def fake_get(url, *, headers, timeout, follow_redirects): captured["url"] = url - captured["headers"] = kwargs.get("headers", {}) - captured["timeout"] = kwargs.get("timeout") - captured["follow_redirects"] = kwargs.get("follow_redirects") + captured["headers"] = headers + captured["timeout"] = timeout + captured["follow_redirects"] = follow_redirects return _fake_response({"tag_name": "v0.4.0"}) monkeypatch.setattr(httpx2, "get", fake_get) @@ -229,9 +229,14 @@ def test_spawn_refresh_is_detached(monkeypatch): # Untyped capture dict (mirrors the pattern in tests/test_telemetry.py). calls = {} - def fake_popen(args, **kwargs): + def fake_popen(args, *, stdout, stderr, start_new_session, env): calls["args"] = args - calls["kwargs"] = kwargs + calls["kwargs"] = { + "stdout": stdout, + "stderr": stderr, + "start_new_session": start_new_session, + "env": env, + } return object() monkeypatch.setattr(update_check.subprocess, "Popen", fake_popen)