Merge branch 'overstory/builder-action-strip/SeedPass-57f6' into beta

# Conflicts:
#	src/tests/test_tui_v3_parity.py
This commit is contained in:
thePR0M3TH3AN committed 2026-03-06 13:47:40 -05:00
commit 41f000e802
7 files changed
+136 -178

No files matched your search

+40 -169
View File
@@ -348,6 +348,30 @@ async def test_v3_action_bar_labels_include_leading_hotkey_letters() -> None:
assert "Backup Data" in rendered
@pytest.mark.anyio
async def test_v3_action_bar_global_row_uses_correct_handlers() -> None:
app = SeedPassTuiV3(
entry_service_factory=lambda: MockEntryService(),
vault_service_factory=lambda: MockVaultService(),
)
async with app.run_test() as pilot:
await pilot.pause()
bar = app.screen.query_one("#action-bar")
markup = bar.render()
# Backup Data must route to open_backup_parent_seed (has its own screen)
assert "open_backup_parent_seed" in markup
# Remove Seed must route to open_profile_management (not open_palette)
assert "open_profile_management" in markup
# Export/Import Data use open_palette because they need a path argument
# Verify both labels still present
from rich.text import Text
rendered = Text.from_markup(markup).plain
assert "Export Data" in rendered
assert "Import Data" in rendered
assert "Backup Data" in rendered
assert "Remove Seed" in rendered
@pytest.mark.anyio
async def test_v3_action_bar_only_shows_context_actions_for_selected_kind() -> None:
app = SeedPassTuiV3(
@@ -381,181 +405,28 @@ async def test_v3_action_bar_only_shows_context_actions_for_selected_kind() -> N
assert "Export" not in rendered
# ---------------------------------------------------------------------------
# Parity tests: legacy utility/maintenance commands migrated to v3
# ---------------------------------------------------------------------------
def _make_full_app(**extra_services):
"""Build a SeedPassTuiV3 with all mock services wired up."""
entry_svc = MockEntryService()
vault_svc = MockVaultService()
utility_svc = MockUtilityService()
sync_svc = MockSyncService()
nostr_svc = MockNostrService()
config_svc = MockConfigService()
app = SeedPassTuiV3(
entry_service_factory=lambda: entry_svc,
vault_service_factory=lambda: vault_svc,
utility_service_factory=lambda: utility_svc,
sync_service_factory=lambda: sync_svc,
nostr_service_factory=lambda: nostr_svc,
config_service_factory=lambda: config_svc,
)
return app, entry_svc, vault_svc, utility_svc, sync_svc, nostr_svc, config_svc
@pytest.mark.anyio
async def test_v3_checksum_commands() -> None:
app, *_, utility_svc, _, _, _ = _make_full_app()
async with app.run_test() as pilot:
await pilot.pause()
app.action_checksum_verify()
assert utility_svc.checksum_verified is True
app.action_checksum_update()
assert utility_svc.checksum_updated is True
@pytest.mark.anyio
async def test_v3_totp_export_no_path() -> None:
app, entry_svc, *_ = _make_full_app()
# Provide a basic export_totp_entries method
entry_svc.export_totp_entries = lambda: {"1": "otpauth://totp/label?secret=ABC"}
async with app.run_test() as pilot:
await pilot.pause()
# Should not raise; notifies count
app.action_totp_export(None)
@pytest.mark.anyio
async def test_v3_sync_commands() -> None:
app, _, _, _, sync_svc, _, _ = _make_full_app()
async with app.run_test() as pilot:
await pilot.pause()
app.action_sync_now()
assert sync_svc.synced is True
app.action_sync_bg()
assert sync_svc.bg_synced is True
@pytest.mark.anyio
async def test_v3_relay_commands() -> None:
app, _, _, _, _, nostr_svc, _ = _make_full_app()
async with app.run_test() as pilot:
await pilot.pause()
app.action_relay_add("wss://new.relay")
assert "wss://new.relay" in nostr_svc.added
app.action_relay_rm(0)
assert 0 in nostr_svc.removed
app.action_relay_reset()
assert nostr_svc.reset_called is True
@pytest.mark.anyio
async def test_v3_setting_secret() -> None:
app, _, _, _, _, _, config_svc = _make_full_app()
async with app.run_test() as pilot:
await pilot.pause()
app.action_setting_secret("on")
assert config_svc.secret_mode_calls[-1][0] is True
app.action_setting_secret("off")
assert config_svc.secret_mode_calls[-1][0] is False
@pytest.mark.anyio
async def test_v3_setting_offline() -> None:
app, _, _, _, _, _, config_svc = _make_full_app()
async with app.run_test() as pilot:
await pilot.pause()
app.action_setting_offline("on")
assert config_svc.offline_mode_calls[-1] is True
app.action_setting_offline("off")
assert config_svc.offline_mode_calls[-1] is False
@pytest.mark.anyio
async def test_v3_setting_config_keys() -> None:
app, _, _, _, _, _, config_svc = _make_full_app()
async with app.run_test() as pilot:
await pilot.pause()
app.action_setting_quick_unlock("on")
assert config_svc._cfg.get("quick_unlock") == "on"
app.action_setting_timeout("600")
assert config_svc._cfg.get("inactivity_timeout") == "600"
app.action_setting_kdf_mode("argon2id")
assert config_svc._cfg.get("kdf_mode") == "argon2id"
app.action_setting_kdf_iterations("200000")
assert config_svc._cfg.get("kdf_iterations") == "200000"
@pytest.mark.anyio
async def test_v3_archive_filter() -> None:
async def test_v3_action_bar_managed_account_excludes_qr() -> None:
app = SeedPassTuiV3(
entry_service_factory=lambda: MockEntryService(),
vault_service_factory=lambda: MockVaultService(),
)
# Inject a managed_account entry into the mock service
async with app.run_test() as pilot:
await pilot.pause()
app.services["entry"].entries[99] = {
"id": 99,
"label": "test-managed",
"kind": "managed_account",
"index": 0,
}
bar = app.screen.query_one("#action-bar")
app.action_archive_filter("active")
assert app.show_archived is False
assert app.filter_archived_only is False
app.action_archive_filter("all")
assert app.show_archived is True
assert app.filter_archived_only is False
app.action_archive_filter("archived")
assert app.show_archived is True
assert app.filter_archived_only is True
@pytest.mark.anyio
async def test_v3_density() -> None:
app = SeedPassTuiV3(
entry_service_factory=lambda: MockEntryService(),
vault_service_factory=lambda: MockVaultService(),
)
async with app.run_test() as pilot:
app.selected_entry_id = 99
await pilot.pause()
app.action_set_density("compact")
assert app.density_mode == "compact"
app.action_set_density("comfortable")
assert app.density_mode == "comfortable"
@pytest.mark.anyio
async def test_v3_command_processor_routes_utility_commands() -> None:
"""Verify the CommandProcessor correctly routes new utility commands."""
app, *_, utility_svc, sync_svc, nostr_svc, _ = _make_full_app()
async with app.run_test() as pilot:
await pilot.pause()
proc = app.processor
proc.execute("checksum-verify")
assert utility_svc.checksum_verified is True
proc.execute("sync-now")
assert sync_svc.synced is True
proc.execute("relay-add wss://proc.relay")
assert "wss://proc.relay" in nostr_svc.added
proc.execute("archive-filter archived")
assert app.show_archived is True
assert app.filter_archived_only is True
proc.execute("density compact")
assert app.density_mode == "compact"
rendered = Text.from_markup(bar.render()).plain.splitlines()[1]
assert "Context (managed_account):" in rendered
assert "Reveal" in rendered
assert "Load" in rendered
assert "Delete" in rendered
assert " QR" not in rendered
+67
View File
@@ -970,6 +970,73 @@ async def test_tui3_word_by_word_seed_entry_feeds_create_profile_screen() -> Non
)
@pytest.mark.anyio
async def test_tui3_recover_profile_sets_success_status_before_bootstrap() -> None:
app = SeedPassTuiV3()
app._list_boot_profiles = lambda: [
{"fingerprint": "EFBE51E70ED1B53A", "label": "Primary (EFBE51E70ED1B53A)"}
]
booted: dict[str, str] = {}
status_at_boot: list[str] = []
def _recover_profile(*, fingerprint: str, seed: str, password: str) -> None:
pass
def _bootstrap(fingerprint: str, password: str) -> None:
booted["fingerprint"] = fingerprint
# Capture status text at the moment bootstrap fires
try:
status_at_boot.append(
str(app.screen.query_one("#recover-status").render())
)
except Exception:
pass
app._recover_profile = _recover_profile
app._bootstrap_profile_session = _bootstrap
async with app.run_test() as pilot:
await pilot.pause()
app.push_screen(RecoverProfileScreen())
await pilot.pause()
screen = app.screen
screen.query_one("#recover-choice", Input).value = "1"
screen.query_one("#recover-seed", Input).value = (
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
)
screen.query_one("#recover-password", Input).value = "hunter2"
await pilot.press("enter")
await pilot.pause()
assert booted.get("fingerprint") == "EFBE51E70ED1B53A"
assert status_at_boot and "Recovery successful" in status_at_boot[0]
@pytest.mark.anyio
async def test_tui3_add_entry_screen_seedplus_hint_mentions_bip85() -> None:
app, _entry, _vault, _search = _build_app()
async with app.run_test() as pilot:
await pilot.pause()
app.action_add_entry()
await pilot.pause()
screen = app.screen
hint = str(screen.query_one("#seedplus-hint").render())
assert "BIP-85" in hint
assert "Seed+" in hint
@pytest.mark.anyio
async def test_tui3_seed_plus_screen_shows_deterministic_warning() -> None:
app, _entry, _vault, _search = _build_app()
async with app.run_test() as pilot:
await pilot.pause()
app.action_seed_plus()
await pilot.pause()
screen = app.screen
warning = str(screen.query_one("#seedplus-warning").render())
assert "deterministic" in warning.lower()
assert "index" in warning.lower()
@pytest.mark.anyio
async def test_tui3_word_entry_flags_invalid_bip39_word() -> None:
app = SeedPassTuiV3()