forked from bitcoinafterlife/bal-electrum-plugin
- #04: Raw/Date selector now reappears on the WILL/HEIR tabs when switching to ADVANCED (and when a raw value is pushed from the wizard), keeping the current value/editor. New BalTimeEditWidget.apply_user_type_visibility() wired into WillSettingsWidget for both the locktime and check-alive boxes. - #3: Building Will report window minimum height 500 -> 450 px. - #5: 'User Type' setting moved to the bottom, above 'Rebroadcast transactions'. - #6: enabling ADVANCED now requires typing 'at My Risk' (case-insensitive); wrong phrase or cancel reverts to BASIC. QInputDialog added to common import. - #7a: on CHECK with an emptied wallet, an extra reassuring line is shown on 'Checking your will': 'Inheritance already executed (on blockchain)' in GREEN (CONFIRMED) or 'Inheritance in mempool (waiting confirmation)' in ORANGE (MEMPOOL). New _executed_inheritance_status() helper. - #7b: 'Balance is too low, or CheckAlive is in the past. Skipped' (space added) recoloured to ORANGE instead of red. - Reset button renamed 'Reset setting' -> 'Reset to Default Setting'. - Added tests/test_group_h_v048.py (8 tests). Version 0.4.7 -> 0.4.8. Full suite: 266 passed; ruff clean; CHANGELOG #24; memory updated (#04 done).
128 lines
4.5 KiB
Python
128 lines
4.5 KiB
Python
"""
|
|
Tests for the v0.4.8 changes (Group H).
|
|
|
|
These tests cover the small, GUI-free DECISION LOGIC introduced in v0.4.8,
|
|
without importing the Qt widgets (which need PyQt6 + an Electrum window). For
|
|
each behaviour we reproduce the exact rule the production code uses, so the
|
|
tests stay fast and headless while still pinning the contract.
|
|
|
|
Covered behaviour:
|
|
|
|
* #7a - "executed inheritance" detection used to show a reassuring note on the
|
|
"Checking your will" row when the wallet is empty because the inheritance was
|
|
already executed (CONFIRMED) or is on its way (MEMPOOL). The rule:
|
|
CONFIRMED takes precedence over MEMPOOL, and only when neither is present is
|
|
the will treated as "really changed" (None).
|
|
* #6 - the "at My Risk" confirmation gate for enabling ADVANCED mode. The
|
|
typed phrase is accepted case-insensitively; anything else (or a cancel)
|
|
must keep the user in BASIC.
|
|
|
|
Run:
|
|
PYTHONPATH=electrum-src python3 -m pytest tests/test_group_h_v048.py -q
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.pardir))
|
|
|
|
|
|
# ------------------------------------------------------------------ #
|
|
# Mocks
|
|
# ------------------------------------------------------------------ #
|
|
|
|
class FakeWillItem:
|
|
"""Minimal will item exposing only ``get_status`` like the real WillItem."""
|
|
|
|
def __init__(self, statuses):
|
|
# ``statuses`` is a set of status names that are True for this item.
|
|
self._statuses = set(statuses)
|
|
|
|
def get_status(self, status):
|
|
return status in self._statuses
|
|
|
|
|
|
def executed_inheritance_status(willitems):
|
|
"""GUI-free copy of ``BalDialog._executed_inheritance_status``.
|
|
|
|
Mirrors the production rule exactly (see bal/gui/qt/dialogs.py):
|
|
* return "CONFIRMED" as soon as any item is confirmed on-chain;
|
|
* otherwise return "MEMPOOL" if any item is in the mempool;
|
|
* otherwise return None.
|
|
"""
|
|
has_mempool = False
|
|
for witem in willitems.values():
|
|
if witem.get_status("CONFIRMED"):
|
|
return "CONFIRMED"
|
|
if witem.get_status("MEMPOOL"):
|
|
has_mempool = True
|
|
return "MEMPOOL" if has_mempool else None
|
|
|
|
|
|
def advanced_phrase_ok(text, accepted):
|
|
"""GUI-free copy of the ADVANCED gate check (see on_user_type_change).
|
|
|
|
Returns True only when ``text`` equals the confirmation phrase ignoring
|
|
surrounding whitespace and letter case. ``accepted`` is False when the input
|
|
dialog was cancelled, which must never enable ADVANCED.
|
|
"""
|
|
if not accepted:
|
|
return False
|
|
return text.strip().lower() == "at my risk"
|
|
|
|
|
|
# ------------------------------------------------------------------ #
|
|
# #7a - executed-inheritance detection
|
|
# ------------------------------------------------------------------ #
|
|
|
|
def test_executed_status_confirmed_wins():
|
|
"""A confirmed transaction reports CONFIRMED even if a mempool one exists."""
|
|
willitems = {
|
|
"a": FakeWillItem({"MEMPOOL"}),
|
|
"b": FakeWillItem({"CONFIRMED"}),
|
|
}
|
|
assert executed_inheritance_status(willitems) == "CONFIRMED"
|
|
|
|
|
|
def test_executed_status_mempool_only():
|
|
"""With only a mempool transaction the status is MEMPOOL."""
|
|
willitems = {"a": FakeWillItem({"MEMPOOL"})}
|
|
assert executed_inheritance_status(willitems) == "MEMPOOL"
|
|
|
|
|
|
def test_executed_status_none_when_neither():
|
|
"""No confirmed/mempool item -> None (the will really has to be rebuilt)."""
|
|
willitems = {"a": FakeWillItem({"VALID"})}
|
|
assert executed_inheritance_status(willitems) is None
|
|
|
|
|
|
def test_executed_status_empty():
|
|
"""No will items at all -> None."""
|
|
assert executed_inheritance_status({}) is None
|
|
|
|
|
|
# ------------------------------------------------------------------ #
|
|
# #6 - "at My Risk" ADVANCED gate
|
|
# ------------------------------------------------------------------ #
|
|
|
|
def test_advanced_phrase_exact():
|
|
"""The exact phrase as shown in the prompt is accepted."""
|
|
assert advanced_phrase_ok("at My Risk", True) is True
|
|
|
|
|
|
def test_advanced_phrase_case_insensitive():
|
|
"""Any capitalisation is accepted (case-insensitive)."""
|
|
for variant in ("at my risk", "AT MY RISK", "At My Risk", " at my risk "):
|
|
assert advanced_phrase_ok(variant, True) is True
|
|
|
|
|
|
def test_advanced_phrase_wrong_text():
|
|
"""A wrong phrase keeps the user in BASIC."""
|
|
assert advanced_phrase_ok("at your risk", True) is False
|
|
assert advanced_phrase_ok("", True) is False
|
|
|
|
|
|
def test_advanced_phrase_cancelled():
|
|
"""Cancelling the dialog (accepted=False) never enables ADVANCED."""
|
|
assert advanced_phrase_ok("at My Risk", False) is False
|