Skip to content

Issue #9 — Dispute Flow Tests #593

@yusuftomilola

Description

@yusuftomilola

The dispute mechanism is the most nuanced part of the contract — it has a time-gated entry, a special Disputed status that blocks all other flows, and a two-outcome resolution. These six tests together form a complete behavioural specification: they verify the happy-path dispute, two ways the window can be closed, both resolution outcomes, and the guard preventing resolution of a non-disputed escrow.

Task

Building on the test file from Issue #3, add the following six tests:

  1. test_raise_dispute_within_window — happy path:

    • Creates escrow, advances ledger by 1 hour (within 24-hour window)
    • Depositor calls raise_dispute
    • Asserts escrow.status == EscrowStatus::Disputed
    • Asserts escrow.dispute_raised_at.is_some()
  2. test_raise_dispute_after_window_fails — guard: window expired:

    • Creates escrow, advances ledger by DISPUTE_WINDOW + 1 seconds
    • Depositor calls raise_dispute
    • Expects panic "Error(Contract, #8)" (DisputeWindowClosed)
  3. test_raise_dispute_when_window_zero_fails — guard: disputes disabled:

    • Initialises the contract with dispute_window_secs = 0 (bypasses the init helper, uses PaymentEscrowContractClient::new directly)
    • Creates an escrow
    • Depositor calls raise_dispute
    • Expects panic "Error(Contract, #8)" (DisputeWindowClosed)
  4. test_resolve_dispute_releases_to_beneficiary — resolution outcome A:

    • Creates escrow, raises dispute, admin calls resolve_dispute with release_to_beneficiary = true
    • Asserts beneficiary's balance is 5_000
    • Asserts escrow.status == EscrowStatus::Released
  5. test_resolve_dispute_refunds_to_depositor — resolution outcome B:

    • Creates escrow, raises dispute, admin calls resolve_dispute with release_to_beneficiary = false
    • Asserts depositor's balance is restored to 10_000
    • Asserts escrow.status == EscrowStatus::Refunded
  6. test_resolve_dispute_on_pending_escrow_fails — guard: no dispute raised:

    • Creates escrow (status stays Pending)
    • Admin calls resolve_dispute without raising a dispute first
    • Expects panic "Error(Contract, #7)" (EscrowNotDisputed)

Files to Modify

  • contracts/payment_escrow/src/test.rs

Acceptance Criteria

  • All six tests are present and correctly named
  • test_raise_dispute_within_window uses advance_time(&env, 3_600) before calling raise_dispute
  • test_raise_dispute_after_window_fails advances by DISPUTE_WINDOW + 1
  • test_raise_dispute_when_window_zero_fails initialises with &0u64 directly (not via init helper)
  • test_resolve_dispute_releases_to_beneficiary passes &true as the last argument
  • test_resolve_dispute_refunds_to_depositor passes &false as the last argument
  • test_resolve_dispute_on_pending_escrow_fails uses #[should_panic(expected = "Error(Contract, #7)")]
  • cargo test -p payment_escrow runs 15 tests, all pass
  • cargo clippy -p payment_escrow -- -D warnings passes

Technical Notes

  • resolve_dispute takes a &bool argument: client.resolve_dispute(&admin, &String::from_str(&env, "esc-001"), &true)
  • For test 3, call client.initialize(&admin, &token, &0u64) directly instead of using the init helper
  • advance_time is the helper defined in Issue FRONTEND: Setup Next.js 14 and Essential Frontend Dependencies #1 — use it, do not manually mutate the ledger inline

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions