Skip to content

Commit 881b624

Browse files
authored
Merge pull request #23 from smekcio/chore/tests-coverage-hardening
test: raise coverage to 100% and fix lint in tests
2 parents 098c691 + b2a1490 commit 881b624

16 files changed

Lines changed: 972 additions & 4 deletions

tests/cli/integration/test_init_command.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,53 @@ def test_init_non_interactive_requires_context_fields(runner, monkeypatch, tmp_p
7676
],
7777
)
7878
assert result.exit_code == 2
79+
80+
81+
def test_init_interactive_respects_provided_options_and_keeps_active_profile(
82+
runner, monkeypatch, tmp_path
83+
) -> None:
84+
config_path = tmp_path / "config.json"
85+
monkeypatch.setattr(paths, "config_file", lambda: config_path)
86+
87+
seed_result = runner.invoke(
88+
app,
89+
[
90+
"--json",
91+
"init",
92+
"--name",
93+
"seed",
94+
"--env",
95+
"DEMO",
96+
"--context-type",
97+
"nip",
98+
"--context-value",
99+
"111",
100+
"--non-interactive",
101+
"--set-active",
102+
],
103+
)
104+
assert seed_result.exit_code == 0
105+
106+
result = runner.invoke(
107+
app,
108+
[
109+
"--json",
110+
"init",
111+
"--name",
112+
"second",
113+
"--env",
114+
"TEST",
115+
"--base-url",
116+
"https://example.test",
117+
"--context-type",
118+
"nip",
119+
"--context-value",
120+
"222",
121+
],
122+
input="second\n",
123+
)
124+
assert result.exit_code == 0
125+
payload = _json_output(result.stdout)
126+
assert payload["ok"] is True
127+
assert payload["profile"] == "second"
128+
assert payload["data"]["active_profile"] == "seed"

tests/cli/unit/test_auth_manager.py

Lines changed: 112 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,15 @@ def test_status_and_logout(monkeypatch) -> None:
180180

181181

182182
def test_select_certificate_and_require_non_empty_errors() -> None:
183+
cert = manager._select_certificate(
184+
[
185+
{"usage": ["KsefTokenEncryption"], "certificate": ""},
186+
{"usage": ["KsefTokenEncryption"], "certificate": "CERT"},
187+
],
188+
"KsefTokenEncryption",
189+
)
190+
assert cert == "CERT"
191+
183192
with pytest.raises(CliError) as cert_error:
184193
manager._select_certificate([], "KsefTokenEncryption")
185194
assert cert_error.value.code == ExitCode.API_ERROR
@@ -214,10 +223,31 @@ def test_resolve_base_url_uses_profile_when_missing(monkeypatch) -> None:
214223
assert manager.resolve_base_url(None, profile="demo") == "https://profile.example"
215224

216225

226+
def test_resolve_base_url_falls_back_when_profile_base_url_empty(monkeypatch) -> None:
227+
monkeypatch.setattr(
228+
manager,
229+
"load_config",
230+
lambda: CliConfig(
231+
active_profile="demo",
232+
profiles={
233+
"demo": ProfileConfig(
234+
name="demo",
235+
env="DEMO",
236+
base_url=" ",
237+
context_type="nip",
238+
context_value="123",
239+
)
240+
},
241+
),
242+
)
243+
assert manager.resolve_base_url(None, profile="demo") == manager.KsefEnvironment.DEMO.value
244+
245+
217246
def test_resolve_lighthouse_base_url_prefers_explicit_value() -> None:
218-
assert manager.resolve_lighthouse_base_url(" https://api-latarnia-test.ksef.mf.gov.pl/ ") == (
219-
"https://api-latarnia-test.ksef.mf.gov.pl/"
220-
).strip()
247+
assert (
248+
manager.resolve_lighthouse_base_url(" https://api-latarnia-test.ksef.mf.gov.pl/ ")
249+
== ("https://api-latarnia-test.ksef.mf.gov.pl/").strip()
250+
)
221251

222252

223253
def test_resolve_lighthouse_base_url_uses_profile_mapping(monkeypatch) -> None:
@@ -269,6 +299,28 @@ def test_resolve_lighthouse_base_url_invalid_profile_base_fallback(monkeypatch)
269299
)
270300

271301

302+
def test_resolve_lighthouse_base_url_fallback_when_profile_base_url_empty(monkeypatch) -> None:
303+
monkeypatch.setattr(
304+
manager,
305+
"load_config",
306+
lambda: CliConfig(
307+
active_profile="demo",
308+
profiles={
309+
"demo": ProfileConfig(
310+
name="demo",
311+
env="DEMO",
312+
base_url=" ",
313+
context_type="nip",
314+
context_value="123",
315+
)
316+
},
317+
),
318+
)
319+
assert manager.resolve_lighthouse_base_url(None, profile="demo") == (
320+
KsefLighthouseEnvironment.TEST.value
321+
)
322+
323+
272324
def test_refresh_access_token_missing_token_in_response(monkeypatch) -> None:
273325
class _FakeClientNoToken:
274326
def __init__(self) -> None:
@@ -492,3 +544,60 @@ def test_login_with_xades_loader_errors_are_mapped(monkeypatch) -> None:
492544
save=False,
493545
)
494546
assert exc.value.code == ExitCode.VALIDATION_ERROR
547+
548+
549+
def test_login_with_token_without_save(monkeypatch) -> None:
550+
monkeypatch.setattr(manager, "create_client", lambda base_url: _FakeClient())
551+
monkeypatch.setattr(manager, "AuthCoordinator", _FakeAuthCoordinator)
552+
monkeypatch.setattr(
553+
manager,
554+
"save_tokens",
555+
lambda *args, **kwargs: (_ for _ in ()).throw(
556+
AssertionError("save_tokens should not be called")
557+
),
558+
)
559+
monkeypatch.setattr(
560+
manager,
561+
"set_cached_metadata",
562+
lambda *args, **kwargs: (_ for _ in ()).throw(
563+
AssertionError("set_cached_metadata should not be called")
564+
),
565+
)
566+
567+
result = manager.login_with_token(
568+
profile="demo",
569+
base_url="https://api-demo.ksef.mf.gov.pl",
570+
token="TOKEN",
571+
context_type="nip",
572+
context_value="5265877635",
573+
poll_interval=0.0,
574+
max_attempts=1,
575+
save=False,
576+
)
577+
assert result["saved"] is False
578+
579+
580+
def test_refresh_access_token_success_without_save(monkeypatch) -> None:
581+
monkeypatch.setattr(manager, "get_tokens", lambda profile: ("acc", "ref"))
582+
monkeypatch.setattr(manager, "create_client", lambda base_url: _FakeClient())
583+
monkeypatch.setattr(
584+
manager,
585+
"save_tokens",
586+
lambda *args, **kwargs: (_ for _ in ()).throw(
587+
AssertionError("save_tokens should not be called")
588+
),
589+
)
590+
monkeypatch.setattr(
591+
manager,
592+
"set_cached_metadata",
593+
lambda *args, **kwargs: (_ for _ in ()).throw(
594+
AssertionError("set_cached_metadata should not be called")
595+
),
596+
)
597+
598+
result = manager.refresh_access_token(
599+
profile="demo",
600+
base_url="https://api-demo.ksef.mf.gov.pl",
601+
save=False,
602+
)
603+
assert result["saved"] is False

tests/cli/unit/test_config_loader_profiles.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,18 @@ def test_loader_profile_parser_skips_invalid_entries(monkeypatch, tmp_path) -> N
8282
assert loader.load_config().profiles == {}
8383

8484

85+
def test_loader_accepts_non_dict_profiles_key(monkeypatch, tmp_path) -> None:
86+
config_path = tmp_path / "config.json"
87+
monkeypatch.setattr(paths, "config_file", lambda: config_path)
88+
config_path.write_text(
89+
json.dumps({"active_profile": "demo", "profiles": []}),
90+
encoding="utf-8",
91+
)
92+
loaded = loader.load_config()
93+
assert loaded.profiles == {}
94+
assert loaded.active_profile is None
95+
96+
8597
def test_loader_skips_non_string_profile_names(monkeypatch, tmp_path) -> None:
8698
config_path = tmp_path / "config.json"
8799
monkeypatch.setattr(paths, "config_file", lambda: config_path)
@@ -293,3 +305,27 @@ def test_profiles_upsert_and_active_fallback() -> None:
293305

294306
profiles.delete_profile(config, name="one")
295307
assert config.active_profile == "two"
308+
309+
310+
def test_profiles_delete_non_active_profile_keeps_active() -> None:
311+
config = CliConfig(
312+
active_profile="one",
313+
profiles={
314+
"one": ProfileConfig(
315+
name="one",
316+
env="DEMO",
317+
base_url="https://api-demo.ksef.mf.gov.pl",
318+
context_type="nip",
319+
context_value="1",
320+
),
321+
"two": ProfileConfig(
322+
name="two",
323+
env="TEST",
324+
base_url="https://api-test.ksef.mf.gov.pl",
325+
context_type="nip",
326+
context_value="2",
327+
),
328+
},
329+
)
330+
profiles.delete_profile(config, name="two")
331+
assert config.active_profile == "one"

tests/cli/unit/test_core_coverage.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,18 @@ def _fake_entrypoint() -> None:
4444
assert called["value"] is True
4545

4646

47+
def test_cli_main_module_import_does_not_invoke_entrypoint(monkeypatch) -> None:
48+
called = {"value": False}
49+
50+
def _fake_entrypoint() -> None:
51+
called["value"] = True
52+
53+
monkeypatch.setattr(app_module, "app_entrypoint", _fake_entrypoint)
54+
main_module = importlib.import_module("ksef_client.cli.__main__")
55+
importlib.reload(main_module)
56+
assert called["value"] is False
57+
58+
4759
def test_config_loader_and_profiles(monkeypatch, tmp_path: Path) -> None:
4860
monkeypatch.setattr(paths, "config_file", lambda: tmp_path / "config.json")
4961
cfg = loader.load_config()

tests/cli/unit/test_output_human.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ def test_human_renderer_success_skips_raw_response_payload(capsys) -> None:
6161
assert "raw" not in out
6262

6363

64+
def test_human_renderer_success_without_data(capsys) -> None:
65+
renderer = HumanRenderer(no_color=True)
66+
renderer.success(command="send.status", profile="demo", data=None)
67+
out = capsys.readouterr().out
68+
assert "OK" in out
69+
assert "send.status" in out
70+
71+
6472
def test_human_renderer_error_prints_hint(capsys) -> None:
6573
renderer = HumanRenderer(no_color=True)
6674
renderer.error(

0 commit comments

Comments
 (0)