From 64b47d3e684c5f3e6fdce740239a09a9f23e7f69 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Wed, 9 Jul 2025 14:45:04 -0400 Subject: [PATCH] Add CLI and API endpoint tests --- src/tests/test_api_new_endpoints.py | 111 ++++++++++++++++++++++ src/tests/test_cli_config_set_extra.py | 44 +++++++++ src/tests/test_cli_entry_add_commands.py | 112 +++++++++++++++++++++++ 3 files changed, 267 insertions(+) create mode 100644 src/tests/test_api_new_endpoints.py create mode 100644 src/tests/test_cli_config_set_extra.py create mode 100644 src/tests/test_cli_entry_add_commands.py diff --git a/src/tests/test_api_new_endpoints.py b/src/tests/test_api_new_endpoints.py new file mode 100644 index 0000000..a07de53 --- /dev/null +++ b/src/tests/test_api_new_endpoints.py @@ -0,0 +1,111 @@ +from types import SimpleNamespace +import pytest + +from seedpass import api +from test_api import client + + +def test_create_and_modify_totp_entry(client): + cl, token = client + calls = {} + + def add_totp(label, seed, **kwargs): + calls["create"] = kwargs + return "uri" + + def modify(idx, **kwargs): + calls["modify"] = (idx, kwargs) + + api._pm.entry_manager.add_totp = add_totp + api._pm.entry_manager.modify_entry = modify + api._pm.entry_manager.get_next_index = lambda: 5 + api._pm.parent_seed = "seed" + + headers = {"Authorization": f"Bearer {token}"} + res = cl.post( + "/api/v1/entry", + json={ + "type": "totp", + "label": "T", + "index": 1, + "secret": "abc", + "period": 60, + "digits": 8, + "notes": "n", + }, + headers=headers, + ) + assert res.status_code == 200 + assert res.json() == {"id": 5, "uri": "uri"} + assert calls["create"] == { + "index": 1, + "secret": "abc", + "period": 60, + "digits": 8, + "notes": "n", + "archived": False, + } + + res = cl.put( + "/api/v1/entry/5", + json={"period": 90, "digits": 6}, + headers=headers, + ) + assert res.status_code == 200 + assert calls["modify"][0] == 5 + assert calls["modify"][1]["period"] == 90 + assert calls["modify"][1]["digits"] == 6 + + +def test_create_and_modify_ssh_entry(client): + cl, token = client + calls = {} + + def add_ssh(label, seed, **kwargs): + calls["create"] = kwargs + return 2 + + def modify(idx, **kwargs): + calls["modify"] = (idx, kwargs) + + api._pm.entry_manager.add_ssh_key = add_ssh + api._pm.entry_manager.modify_entry = modify + api._pm.parent_seed = "seed" + + headers = {"Authorization": f"Bearer {token}"} + res = cl.post( + "/api/v1/entry", + json={"type": "ssh", "label": "S", "index": 2, "notes": "n"}, + headers=headers, + ) + assert res.status_code == 200 + assert res.json() == {"id": 2} + assert calls["create"] == {"index": 2, "notes": "n", "archived": False} + + res = cl.put( + "/api/v1/entry/2", + json={"notes": "x"}, + headers=headers, + ) + assert res.status_code == 200 + assert calls["modify"][0] == 2 + assert calls["modify"][1]["notes"] == "x" + + +def test_update_config_secret_mode(client): + cl, token = client + called = {} + + def set_secret(val): + called["val"] = val + + api._pm.config_manager.set_secret_mode_enabled = set_secret + headers = {"Authorization": f"Bearer {token}"} + res = cl.put( + "/api/v1/config/secret_mode_enabled", + json={"value": True}, + headers=headers, + ) + assert res.status_code == 200 + assert res.json() == {"status": "ok"} + assert called["val"] is True diff --git a/src/tests/test_cli_config_set_extra.py b/src/tests/test_cli_config_set_extra.py new file mode 100644 index 0000000..21e8309 --- /dev/null +++ b/src/tests/test_cli_config_set_extra.py @@ -0,0 +1,44 @@ +import pytest +from types import SimpleNamespace +from typer.testing import CliRunner + +from seedpass.cli import app +from seedpass import cli + +runner = CliRunner() + + +@pytest.mark.parametrize( + "key,value,method,expected", + [ + ("secret_mode_enabled", "true", "set_secret_mode_enabled", True), + ("clipboard_clear_delay", "10", "set_clipboard_clear_delay", 10), + ("additional_backup_path", "", "set_additional_backup_path", None), + ( + "relays", + "wss://a.com, wss://b.com", + "set_relays", + ["wss://a.com", "wss://b.com"], + ), + ], +) +def test_config_set_variants(monkeypatch, key, value, method, expected): + called = {} + + def func(val, **kwargs): + called["val"] = val + called.update(kwargs) + + pm = SimpleNamespace( + config_manager=SimpleNamespace(**{method: func}), + select_fingerprint=lambda fp: None, + ) + monkeypatch.setattr(cli, "PasswordManager", lambda: pm) + + result = runner.invoke(app, ["config", "set", key, value]) + + assert result.exit_code == 0 + assert "Updated" in result.stdout + assert called.get("val") == expected + if key == "relays": + assert called.get("require_pin") is False diff --git a/src/tests/test_cli_entry_add_commands.py b/src/tests/test_cli_entry_add_commands.py new file mode 100644 index 0000000..b69f652 --- /dev/null +++ b/src/tests/test_cli_entry_add_commands.py @@ -0,0 +1,112 @@ +import pytest +from types import SimpleNamespace +from typer.testing import CliRunner + +from seedpass.cli import app +from seedpass import cli + +runner = CliRunner() + + +@pytest.mark.parametrize( + "command,method,cli_args,expected_args,expected_kwargs,stdout", + [ + ( + "add-totp", + "add_totp", + [ + "Label", + "--index", + "1", + "--secret", + "abc", + "--period", + "45", + "--digits", + "7", + ], + ("Label", "seed"), + {"index": 1, "secret": "abc", "period": 45, "digits": 7}, + "otpauth://uri", + ), + ( + "add-ssh", + "add_ssh_key", + ["Label", "--index", "2", "--notes", "n"], + ("Label", "seed"), + {"index": 2, "notes": "n"}, + "3", + ), + ( + "add-pgp", + "add_pgp_key", + [ + "Label", + "--index", + "3", + "--key-type", + "rsa", + "--user-id", + "uid", + "--notes", + "n", + ], + ("Label", "seed"), + {"index": 3, "key_type": "rsa", "user_id": "uid", "notes": "n"}, + "4", + ), + ( + "add-nostr", + "add_nostr_key", + ["Label", "--index", "4", "--notes", "n"], + ("Label",), + {"index": 4, "notes": "n"}, + "5", + ), + ( + "add-seed", + "add_seed", + ["Label", "--index", "5", "--words", "12", "--notes", "n"], + ("Label", "seed"), + {"index": 5, "words_num": 12, "notes": "n"}, + "6", + ), + ( + "add-key-value", + "add_key_value", + ["Label", "--value", "val", "--notes", "note"], + ("Label", "val"), + {"notes": "note"}, + "7", + ), + ( + "add-managed-account", + "add_managed_account", + ["Label", "--index", "7", "--notes", "n"], + ("Label", "seed"), + {"index": 7, "notes": "n"}, + "8", + ), + ], +) +def test_entry_add_commands( + monkeypatch, command, method, cli_args, expected_args, expected_kwargs, stdout +): + called = {} + + def func(*args, **kwargs): + called["args"] = args + called["kwargs"] = kwargs + return stdout + + pm = SimpleNamespace( + entry_manager=SimpleNamespace(**{method: func}), + parent_seed="seed", + select_fingerprint=lambda fp: None, + ) + monkeypatch.setattr(cli, "PasswordManager", lambda: pm) + result = runner.invoke(app, ["entry", command] + cli_args) + assert result.exit_code == 0 + assert stdout in result.stdout + assert called["args"] == expected_args + assert called["kwargs"] == expected_kwargs