import sys from types import SimpleNamespace from pathlib import Path sys.path.append(str(Path(__file__).resolve().parents[1])) import main from seedpass.core.entry_types import EntryType def make_pm(search_results, entry=None, totp_code="123456"): entry_mgr = SimpleNamespace( search_entries=lambda q: search_results, retrieve_entry=lambda idx: entry, get_totp_code=lambda idx, seed: totp_code, ) pg = SimpleNamespace(generate_password=lambda l, i: "pw") pm = SimpleNamespace( entry_manager=entry_mgr, password_generator=pg, nostr_client=SimpleNamespace(close_client_pool=lambda: None), parent_seed="seed", inactivity_timeout=1, clipboard_clear_delay=45, ) return pm def test_search_command(monkeypatch, capsys): pm = make_pm([(0, "Example", "user", "", False, EntryType.PASSWORD)]) monkeypatch.setattr(main, "PasswordManager", lambda *a, **k: pm) monkeypatch.setattr(main, "configure_logging", lambda: None) monkeypatch.setattr(main, "initialize_app", lambda: None) monkeypatch.setattr(main.signal, "signal", lambda *a, **k: None) rc = main.main(["search", "ex"]) assert rc == 0 out = capsys.readouterr().out assert "Example" in out def test_get_command(monkeypatch, capsys): entry = {"type": EntryType.PASSWORD.value, "length": 8} pm = make_pm([(0, "Example", "user", "", False, EntryType.PASSWORD)], entry=entry) monkeypatch.setattr(main, "PasswordManager", lambda *a, **k: pm) monkeypatch.setattr(main, "configure_logging", lambda: None) monkeypatch.setattr(main, "initialize_app", lambda: None) monkeypatch.setattr(main.signal, "signal", lambda *a, **k: None) rc = main.main(["get", "ex"]) assert rc == 0 out = capsys.readouterr().out assert "pw" in out def test_totp_command(monkeypatch, capsys): entry = {"type": EntryType.TOTP.value, "period": 30, "index": 0} pm = make_pm([(0, "Example", None, None, False, EntryType.TOTP)], entry=entry) called = {} monkeypatch.setattr(main, "PasswordManager", lambda *a, **k: pm) monkeypatch.setattr(main, "configure_logging", lambda: None) monkeypatch.setattr(main, "initialize_app", lambda: None) monkeypatch.setattr(main.signal, "signal", lambda *a, **k: None) monkeypatch.setattr( main, "copy_to_clipboard", lambda v, d: (called.setdefault("val", v), True)[1] ) rc = main.main(["totp", "ex"]) assert rc == 0 out = capsys.readouterr().out assert "123456" in out assert "copied to clipboard" in out.lower() assert called.get("val") == "123456" def test_search_command_no_results(monkeypatch, capsys): pm = make_pm([]) monkeypatch.setattr(main, "PasswordManager", lambda *a, **k: pm) monkeypatch.setattr(main, "configure_logging", lambda: None) monkeypatch.setattr(main, "initialize_app", lambda: None) monkeypatch.setattr(main.signal, "signal", lambda *a, **k: None) rc = main.main(["search", "none"]) assert rc == 0 out = capsys.readouterr().out assert "No matching entries found" in out def test_get_command_multiple_matches(monkeypatch, capsys): matches = [ (0, "Example", "user", "", False, EntryType.PASSWORD), (1, "Ex2", "bob", "", False, EntryType.PASSWORD), ] pm = make_pm(matches) monkeypatch.setattr(main, "PasswordManager", lambda *a, **k: pm) monkeypatch.setattr(main, "configure_logging", lambda: None) monkeypatch.setattr(main, "initialize_app", lambda: None) monkeypatch.setattr(main.signal, "signal", lambda *a, **k: None) rc = main.main(["get", "ex"]) assert rc == 1 out = capsys.readouterr().out assert "Matches" in out def test_get_command_wrong_type(monkeypatch, capsys): entry = {"type": EntryType.TOTP.value} pm = make_pm([(0, "Example", None, None, False, EntryType.TOTP)], entry=entry) monkeypatch.setattr(main, "PasswordManager", lambda *a, **k: pm) monkeypatch.setattr(main, "configure_logging", lambda: None) monkeypatch.setattr(main, "initialize_app", lambda: None) monkeypatch.setattr(main.signal, "signal", lambda *a, **k: None) rc = main.main(["get", "ex"]) assert rc == 1 out = capsys.readouterr().out assert "Entry is not a password entry" in out def test_totp_command_multiple_matches(monkeypatch, capsys): matches = [ (0, "GH", None, None, False, EntryType.TOTP), (1, "Git", None, None, False, EntryType.TOTP), ] pm = make_pm(matches) monkeypatch.setattr(main, "PasswordManager", lambda *a, **k: pm) monkeypatch.setattr(main, "configure_logging", lambda: None) monkeypatch.setattr(main, "initialize_app", lambda: None) monkeypatch.setattr(main.signal, "signal", lambda *a, **k: None) rc = main.main(["totp", "g"]) assert rc == 1 out = capsys.readouterr().out assert "Matches" in out def test_totp_command_wrong_type(monkeypatch, capsys): entry = {"type": EntryType.PASSWORD.value, "length": 8} pm = make_pm([(0, "Example", "user", "", False, EntryType.PASSWORD)], entry=entry) monkeypatch.setattr(main, "PasswordManager", lambda *a, **k: pm) monkeypatch.setattr(main, "configure_logging", lambda: None) monkeypatch.setattr(main, "initialize_app", lambda: None) monkeypatch.setattr(main.signal, "signal", lambda *a, **k: None) rc = main.main(["totp", "ex"]) assert rc == 1 out = capsys.readouterr().out assert "Entry is not a TOTP entry" in out def test_main_fingerprint_option(monkeypatch): """Ensure the argparse CLI forwards the fingerprint to PasswordManager.""" called = {} def fake_pm(fingerprint=None): called["fp"] = fingerprint return make_pm([]) monkeypatch.setattr(main, "PasswordManager", fake_pm) monkeypatch.setattr(main, "configure_logging", lambda: None) monkeypatch.setattr(main, "initialize_app", lambda: None) monkeypatch.setattr(main.signal, "signal", lambda *a, **k: None) rc = main.main(["--fingerprint", "abc", "search", "q"]) assert rc == 0 assert called.get("fp") == "abc"