test: implementation of basic actual e2e testing for DET#598
test: implementation of basic actual e2e testing for DET#598PastaPastaPasta wants to merge 56 commits intov1.0-devfrom
Conversation
📝 WalkthroughWalkthroughAdds a feature-gated e2e testing system: a new Cargo test target and feature flag, e2e-only accessors in the UI/context, a TestContext and robust harness with retry/error handling, a phased end-to-end test suite, UI hint text tweaks, and CI workflow to run the E2E tests. Changes
Sequence Diagram(s)mermaid Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Port the comprehensive kittest interaction helpers and tests from the react-native branch, adapted for v1.0-dev API (AppState::new returns Self directly). Includes welcome screen, navigation, UI element, resize, and stress tests (20 new tests). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add hint_text to TextEdit widgets that E2E tests need to query via harness.query_by_label(). Covers seed word inputs, wallet name, token keyword search, DPNS name, identity ID, and contract ID fields. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement the first real E2E test phase that imports a wallet via the UI and waits for SPV sync to complete. This is the foundation all other test phases depend on. Changes: - Make `wallets` and `spv_manager` fields public on AppContext for integration test access - Add `set_seed_phrase_length()` method to ImportMnemonicScreen for programmatic word count changes in tests - Implement full phase_00_setup.rs: mnemonic validation, welcome screen dismissal, testnet switch, wallet import via UI interactions (word inputs, alias, save), SPV sync start with error retry, and balance capture Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Track initial wallet count before save so we detect the new wallet specifically, avoiding false positives from leftover DB state - Improve SPV retry: up to 3 retries, non-blocking cooldown via harness.run_steps instead of thread::sleep, propagate restart errors - Assert minimum wallet balance (0.001 DASH) after setup to prevent confusing failures in later phases from insufficient funds Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces the stub with a full implementation that: - Verifies wallet balance is non-zero via AppContext - Extracts a receive address programmatically - Navigates to wallets screen and confirms DASH label in UI - Optionally opens receive dialog and verifies address display Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wallet card verification, receive dialog, and conditional send-to-self. Makes select_hd_wallet() pub for programmatic wallet selection in tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DPNS name lookup via identities > load identity > by DPNS name tab, and contract fetch via contracts > load contracts > add DPNS contract ID. Both operations are best-effort with graceful skip on timeout/error. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Flatten deeply nested if-let chains using let-else early returns - Extract duplicated "click button or push screen" pattern into click_or_push_screen() helper - Extract duplicated "dismiss error" pattern into dismiss_if_present() - Remove trivial dpns_lookup_skipped() single-println wrapper - Remove unused _rt parameter from run() for consistency with phases 01/02 - Remove implementation-history comments (Phase 2 references) - Split DPNS lookup into its own run_dpns_lookup() function for clarity Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement the final E2E phase that stops SPV sync, verifies clean shutdown, and logs a test summary. Also commit the helper infrastructure files (harness, context, mod files) that were missing from prior commits. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace graceful degradation patterns (println warnings, early returns, if-let-Some soft skips) with .expect() and assert!() across phases 00-04. Tests that can't fail aren't tests — if we navigated to a screen, its UI elements must exist; if we submitted an operation, it must complete. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Phase 00: use BTreeSet diff to identify newly imported wallet instead of grabbing first key (which may be a pre-existing wallet) - Phases 01/02: check for "E2E Test Wallet" alias instead of overly broad "DASH" label that matches app chrome - Phase 03: add explicit platform error detection separate from clean not-found responses; tighten "No identity" to "No identity found" - Phase 03: rename submit button "Add Contracts" → "Fetch Contracts" to disambiguate from breadcrumb/heading with same text - Phase 05: replace fixed run_steps(120) with wait_until loop for SPV stop (30s timeout) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove click_or_push_screen fallback in phase 03 — missing buttons now fail the test instead of silently pushing screens directly - Split Send||Receive into independent assertions in phase 02 - Remove dead wallet selection fallback in phase 02 (unreachable after line 13 already asserts wallet label visible) - Add navigate_to_screen_by_click helper that verifies sidebar label presence before navigating (proves left panel renders) - Assert dialog dismissal after Escape in phases 01 and 02 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add pre-flight smoke phase verifying app boots correctly (AppContext, SPV idle, wallets lock, testnet context). Make phase_00_setup idempotent by detecting existing wallets and reusing them instead of failing on UNIQUE constraint. Clean up imported wallet in teardown phase via remove_wallet() so subsequent runs start fresh. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tion - Extract `seed_hash()` method and `seed_hash_prefix()` helper to eliminate inconsistent seed hash access/formatting across 4 files - Extract `open_and_verify_receive_dialog()` helper to deduplicate identical receive dialog test sequences in phase_01 and phase_02 - Remove redundant mnemonic word-count validation from main.rs (kept in phase_00_setup where the mnemonic is actually used) - Remove unused `_rt` parameter from phase_00_setup::run() - Simplify unnecessary block scopes in phase_05_teardown - Clean up unused Queryable import from phase_01_faucet - Replace is_some()/assert!/unwrap() pattern with expect() in phase_02 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Only reuse wallets that match the exact E2E alias. The previous fallback to "first wallet found" could accidentally grab unrelated user wallets if teardown removed the E2E wallet but other wallets existed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The wallets screen has instructional text containing "Import Wallet" which collides with the button label. Use query_by_role_and_label (Button role + exact label) to target the button unambiguously. Also harden wait_for_label/wait_for_label_gone to use query_all variants so they don't panic on multiple matches. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
AccessKit button clicks in egui kittest don't trigger the app's action pipeline, so the ImportMnemonicScreen never appeared after clicking "Import Wallet". Push the screen onto the stack programmatically using ScreenType::ImportMnemonic.create_screen(), matching the pattern used elsewhere (dismiss_welcome_screen, navigate_to_screen). Also harden wait_for_label/wait_for_label_gone to use query_all variants so they don't panic on multiple matches. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
AccessKit interactions in egui_kittest are unreliable: button clicks don't trigger the action pipeline and hint_text isn't exposed as queryable labels. Replace the UI-driven import flow with direct ImportMnemonicScreen manipulation: - Add set_seed_phrase_words(), set_alias(), trigger_save() to ImportMnemonicScreen for programmatic wallet import - Rewrite import_wallet_via_ui to push the screen, set values directly, and call trigger_save() instead of clicking through AccessKit Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SPV status "Running" means the service is active, not that wallet balance reconciliation is complete. Add a polling loop (up to 120s) that waits for total_balance_duffs to reach the minimum threshold before proceeding. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wallets loaded from DB are in a closed state — SPV needs the seed bytes to build the bloom filter and discover transactions. When reusing an existing wallet, unlock it with open_no_password() and call bootstrap_wallet_addresses + handle_wallet_unlocked to register it with the SPV manager before starting sync. Drop the wallets read lock before calling bootstrap methods to avoid potential deadlock. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CoreBackendMode defaults to Rpc, which prevents wallet registration with the SPV bloom filter. Set it to Spv after switching to testnet so handle_wallet_unlocked() actually queues the wallet for SPV load. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Key fixes: - Use AppContext::start_spv() instead of spv_manager.start() so the reconcile + finality listeners are registered before SPV sync begins. Without this, balance updates from SPV never propagated to wallets. - Call refresh_on_arrival() when navigating between screens so freshly imported wallets are picked up by the wallets screen. - Push AddContracts and AddExistingIdentity screens directly onto the stack instead of clicking dropdown popup buttons (AccessKit cannot interact with egui popups). - Use TextInput role queries instead of hint_text labels for token search input (hint_text is invisible to AccessKit). - Add retry logic for platform reads (DPNS lookup, contract fetch) to handle transient testnet errors gracefully. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add push_screen(), type_into_text_input(), and dismiss_if_present() helpers to reduce duplicated boilerplate across test phases. Remove duplicate verify_receive_button_visible() call in phase_02 and consolidate if/else branches in run_dpns_lookup(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Phase 1: verify wallet UI renders "Balance:" label with DASH unit, validate testnet address prefix, remove redundant balance>0 check - Phase 2: add post-send assertions — poll for SPV reconciliation (balance must decrease, fee must be reasonable <1M duffs), soft-check tx count (unconfirmed txs may not appear in SPV history until next block) - Phase 3: DPNS lookup panics on platform error after retries instead of silently accepting transient errors as pass - Phase 4: token search requires results for "dash" keyword (not empty), adds retry loop for transient DAPI errors, panics on exhaustion - context.rs: add pre_send_balance/pre_send_tx_count fields - phase_00: log tx_count in diagnostics Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… assertions - Add panic-safe cleanup guard: wrap all phases in catch_unwind so SPV stop and wallet removal run even if a phase panics - Verify actual balance value in phase_01: parse the numeric balance from the UI label and compare against ctx.balance_duffs instead of just checking label presence - Capture platform error text in phase_03/04: log the actual error message before dismissing, include it in panic messages for diagnosis - Fix silent sidebar fallback: rename navigate_to_screen_by_click to verify_sidebar_label_and_navigate, assert label presence instead of silently falling back to direct navigation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Phase 5 (identity creation) and Phase 6 (DPNS name registration) to the E2E test suite, covering the #1 critical coverage gap. Identity creation uses wallet balance funding with retry logic (3 attempts, 300s timeout). DPNS registration generates unique timestamp-based names to avoid collisions and contested name fees. Source changes: make select fields pub on AddNewIdentityScreen and RegisterDpnsNameScreen to work around AccessKit ComboBox limitations, and expose identities module and AppContext.db for test access. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove dead code (unreachable clicked check), unnecessary inner braces around RwLock writes, redundant variable bindings, and obvious comments. Consolidate duplicate app_ctx fetches in teardown cleanup. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… and SPV gate - Centralize 17 magic numbers into named constants in harness.rs - Add ErrorCategory enum with classify_error() for retryable vs fatal errors - Improve capture_error_text() to search multiple error patterns - Add ensure_spv_tx_ready() gate before tx-writing phases (2, 5) - Fix emergency_cleanup() to remove identity before wallet on panic - Add header_height tracking to TestContext for diagnostics - Hard-fail on identity key setup (phase 5) and identity selection (phase 6) - Verify UI state (Create Identity / Register Name buttons) after screen config - Non-retryable errors now fail immediately instead of wasting retries Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Make timeouts retryable in phase_03 and phase_04 instead of panic-asserting, matching the pattern already used in phase_06 - Fix kittest assertion to require both Import and Create wallet buttons (&&) instead of either (||) - Add "Wallets" to left panel nav label assertions - Improve panic message in type_into_text_input for vanished inputs - Add doc comment on ERROR_PATTERNS explaining priority order - Show actual SpvStatus in phase_00 timeout assertion - Move inner NodeT import to top-level in phase_01 - Use expect() instead of unwrap_or_default() in phase_06 DPNS Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/ui/wallets/wallets_screen/dialogs.rs`:
- Around line 1121-1125: The method close_receive_dialog currently uses
#[allow(dead_code)] and pub(super), making it unreachable from E2E tests;
replace the attribute with #[cfg(feature = "e2e")] and widen visibility to
pub(crate) (or pub) so tests in tests/e2e can call it, keeping the
implementation that resets self.receive_dialog = ReceiveDialogState::default();
ensure the feature gate matches other test helpers in the PR (feature = "e2e").
---
Duplicate comments:
In `@Cargo.toml`:
- Around line 104-110: The Cargo.toml configuration is correct: keep the feature
declaration `e2e = []` and the test target block with name "e2e" and path
"tests/e2e/main.rs" as-is; no code changes are required because the E2E test
target follows the repo convention and has no runtime dependencies, enabling
`--all-features` runs successfully.
These methods were added for E2E tests but never actually called. Remove them rather than carrying dead code. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ility Remove the fragile `#[cfg(feature = "e2e")] pub` / `#[cfg(not(feature = "e2e"))] pub(crate)` field duplication pattern (8 occurrences across 4 files). Instead: - Keep fields at their original visibility (pub(crate) or private) - Add `#[cfg(feature = "e2e")]` impl blocks with accessor/setter methods - Make `ui::identities` module unconditionally `pub` (binary crate, no API surface concern) - Update all E2E test code to use the new method-based API This eliminates the maintenance burden of keeping two visibility declarations in sync for every field that E2E tests need to access. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove 5 unused constants (SEND_TX_TIMEOUT, POST_SEND_RECONCILE_TIMEOUT, MIN_BALANCE_FOR_SEND, MAX_SEND_FEE, IDENTITY_CREATION_TIMEOUT) - Remove unused TestContext fields (pre_send_balance, pre_send_tx_count) - Remove unused wait_for_label_gone helper - Hoist repeated Queryable/NodeT imports to module level in harness.rs - Simplify find_existing_e2e_wallet with iterator chain - Consolidate kittest click tests to reuse create_test_harness() - Replace blanket #![allow(dead_code)] with targeted allow on phase_06_dpns Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (7)
src/ui/mod.rs (1)
85-85:pub mod identitieswidens the public API unconditionally — consider gating behind thee2efeature.The PR deliberately avoids the verbose
#[cfg(feature = "e2e")] pub/#[cfg(not(feature = "e2e"))] pub(crate)pair, but making the wholeidentitiesmodule permanentlypubexposes it to all downstream crates (not just test builds). The other production-only modulewalletsremainspub(crate), creating an inconsistency.If this intentional trade-off is accepted, consider a short doc comment capturing that decision.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/ui/mod.rs` at line 85, The identities module is being made public unconditionally via the declaration pub mod identities which widens the public API inconsistent with the production-only wallets module; either gate identities behind the e2e feature (use cfg(feature = "e2e") so identities is exported only when the e2e feature is enabled) or explicitly document the intentional API exposure by adding a short doc comment above pub mod identities explaining why it must remain public across builds; update the identities declaration or add the doc comment accordingly to restore consistency with wallets and make the intent clear.tests/e2e/helpers/harness.rs (1)
296-332:handle_retry_error: settle steps run unconditionally on the final attempt before the terminal panic.On the path where
attempt == PLATFORM_MAX_RETRIESand the error is retryable, lines 320–324 still dismiss the dialog and runSETTLE_STEPS * attemptframes before the panic on line 327–331. Those frames are wasted since nothing reads their state. Consider short-circuiting the last-attempt panic earlier (before backoff):♻️ Proposed simplification
if !category.is_retryable() { panic!("{} failed with non-retryable error: {}", operation, error_text); } + if attempt == PLATFORM_MAX_RETRIES { + panic!( + "{} failed after {} retries. Last error: {}", + operation, PLATFORM_MAX_RETRIES, error_text + ); + } + dismiss_if_present(harness); if pop_screen { harness.state_mut().screen_stack.pop(); } harness.run_steps(SETTLE_STEPS * attempt as usize); - - if attempt == PLATFORM_MAX_RETRIES { - panic!( - "{} failed after {} retries. Last error: {}", - operation, PLATFORM_MAX_RETRIES, error_text - ); - }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/e2e/helpers/harness.rs` around lines 296 - 332, In handle_retry_error, avoid running dismiss_if_present and harness.run_steps on the final attempt by moving the terminal-attempt check (attempt == PLATFORM_MAX_RETRIES) to occur before calling dismiss_if_present / pop_screen / harness.run_steps; if the attempt equals PLATFORM_MAX_RETRIES, immediately panic with the same message (using operation, PLATFORM_MAX_RETRIES and error_text) so you short-circuit the wasted SETTLE_STEPS backoff instead of executing dismiss_if_present, popping the screen, or calling harness.run_steps.tests/e2e/phases/phase_07_teardown.rs (1)
26-30: Print the test summary before asserting SPV reached a terminal state.If this assertion panics, the entire E2E summary block (lines 54–92) is skipped, making it harder to diagnose which phase produced useful results before teardown failed.
♻️ Proposed fix
+ // ─── 3a. Emit summary before any assertions so it's always visible ── + // (moved summary block here — see below) assert!( spv_stopped, "SPV must reach a terminal state after stop (still active after {}s)", SPV_STOP_TIMEOUT.as_secs() );Move or duplicate the summary print block (or at least the key
eprintln!lines) to before this assertion.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/e2e/phases/phase_07_teardown.rs` around lines 26 - 30, Print the E2E summary before asserting SPV reached a terminal state by moving or duplicating the existing summary eprintln! lines (the summary print block that currently runs later) to just before the assert! that checks spv_stopped; specifically, emit the same eprintln! summary output prior to the assert!(spv_stopped, "SPV must reach a terminal state after stop (still active after {}s)", SPV_STOP_TIMEOUT.as_secs()) so that the summary is printed even if the assertion panics.tests/e2e/main.rs (1)
29-30: Nit: Phase banner says "Wallet UI + Balance Display" but callsphase_01_faucet.The human-readable label suggests balance display, while the module name says "faucet." This could confuse someone reading test output vs. source. Consider aligning the banner with the module name or vice-versa.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/e2e/main.rs` around lines 29 - 30, The printed phase banner text "\n=== Phase 1: Wallet UI + Balance Display ===" is inconsistent with the invoked test module phases::phase_01_faucet::run; update one to match the other so output and implementation align—either change the banner string to reflect the faucet (e.g., "Phase 1: Faucet") or rename/use the correct module/function (phase_01_balance or similar) so the println! and phases::phase_01_faucet::run refer to the same concept.tests/e2e/phases/phase_06_dpns.rs (1)
77-91: Thenth(1)selector to skip the breadcrumb is fragile.If a UI refactor changes the ordering or adds another "Register Name" label, this silently clicks the wrong element. Consider querying by a more specific attribute (e.g., button role or a unique test id) if egui_kittest supports it, or at least add a comment anchoring what
nth(0)andnth(1)correspond to today.That said, the assertion on
reg_count >= 2provides a reasonable guard, so this is fine for now.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/e2e/phases/phase_06_dpns.rs` around lines 77 - 91, The test uses query_all_by_label("Register Name").nth(1) which is fragile; replace the positional selector with a more specific query (e.g., a button role or a test id) or at minimum add a clarifying comment and stronger assertion: update the call site that currently uses query_all_by_label("Register Name").nth(1).expect(...).click() to instead target a unique selector supported by egui_kittest (prefer a role-based or data-testid equivalent) or, if not available, add a comment explaining that nth(0) is the breadcrumb and nth(1) is the action button and tighten the pre-check (replace reg_count >= 2 with an explicit check that the second element is a button) so the intent is clear and the click cannot silently target the wrong element.tests/e2e/phases/phase_00_setup.rs (1)
94-104: Mnemonic is validated twice — here and inmain.rs.The env var is read and validated both in
main.rs(line 14) and here (line 96-97). The duplication is intentional (fail-fast in main + phase-local access), but worth a brief comment noting the redundancy is deliberate so a future maintainer doesn't remove the early check.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/e2e/phases/phase_00_setup.rs` around lines 94 - 104, The mnemonic/env var validation in run (tests/e2e/phases/phase_00_setup.rs) duplicates the check performed in main.rs; add a concise comment above the block in the run function explaining this duplication is deliberate (fail-fast check in main + phase-local validation) so future maintainers don't remove the early check; reference the run function and the mnemonic variable/words validation to make the intent clear.tests/e2e/phases/phase_01_faucet.rs (1)
45-57: Balance parsing relies on exact label format — consider a note or regex.The string-slicing approach (
find("Balance:")→find("DASH")→trim().parse()) works for the current label format but will silently break if the format changes (e.g., extra spaces, currency symbol, thousands separator). This is acceptable for E2E tests, but a brief inline comment documenting the expected format (which is already partially there on line 43) helps future maintainers.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/e2e/phases/phase_01_faucet.rs` around lines 45 - 57, Add a brief inline comment above the ui_balance parsing block (referencing balance_label and the ui_balance computation) that documents the exact expected label format ("Balance: <number> DASH"), noting that the code expects no thousands separators and a decimal point for fractions; optionally mention that if format may change in future consider switching to a regex. This clarifies assumptions for maintainers without altering the current parsing logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@tests/e2e/phases/phase_05_identity.rs`:
- Around line 50-70: The test currently can skip exercising the "no-key click
rejected" path when the action button is absent; update the test around
has_action_button so it either asserts the action button is present before
attempting the click (ensuring the rejection is exercised) or logs which branch
ran; specifically modify the block that computes has_action_button and the
subsequent branch that clicks (referencing has_action_button,
query_all_by_label("Create Identity"), set_wallet_funded_ready, and
assert_identity_step with WalletFundedScreenStep::ReadyToCreate) to fail the
test if the button is missing or to add a distinct println! indicating "action
button absent, click skipped" so CI output shows whether the click was
exercised.
- Around line 11-25: The client-side validation tests are currently gated by
ensure_spv_tx_ready; move the call to ensure_spv_tx_ready so
run_validation_tests(harness) executes unconditionally first in the run function
(keep the identity-creation skip prints as-is). Specifically, in the run
function that accepts Harness<'_, AppState> and TestContext, call
run_validation_tests(harness) before calling ensure_spv_tx_ready(harness, ctx)
so the pure client-side checks run regardless of SPV sync state.
---
Duplicate comments:
In `@tests/e2e/phases/phase_04_tokens.rs`:
- Around line 48-63: The timeout handling in phase_04_tokens.rs is correct:
ensure the code using TOKEN_SEARCH_TIMEOUT, PLATFORM_MAX_RETRIES, attempt, and
completed continues to retry when !completed and only calls panic when attempt
== PLATFORM_MAX_RETRIES; no code change required—leave the println/continue and
the conditional panic as-is to preserve retry behavior.
---
Nitpick comments:
In `@src/ui/mod.rs`:
- Line 85: The identities module is being made public unconditionally via the
declaration pub mod identities which widens the public API inconsistent with the
production-only wallets module; either gate identities behind the e2e feature
(use cfg(feature = "e2e") so identities is exported only when the e2e feature is
enabled) or explicitly document the intentional API exposure by adding a short
doc comment above pub mod identities explaining why it must remain public across
builds; update the identities declaration or add the doc comment accordingly to
restore consistency with wallets and make the intent clear.
In `@tests/e2e/helpers/harness.rs`:
- Around line 296-332: In handle_retry_error, avoid running dismiss_if_present
and harness.run_steps on the final attempt by moving the terminal-attempt check
(attempt == PLATFORM_MAX_RETRIES) to occur before calling dismiss_if_present /
pop_screen / harness.run_steps; if the attempt equals PLATFORM_MAX_RETRIES,
immediately panic with the same message (using operation, PLATFORM_MAX_RETRIES
and error_text) so you short-circuit the wasted SETTLE_STEPS backoff instead of
executing dismiss_if_present, popping the screen, or calling harness.run_steps.
In `@tests/e2e/main.rs`:
- Around line 29-30: The printed phase banner text "\n=== Phase 1: Wallet UI +
Balance Display ===" is inconsistent with the invoked test module
phases::phase_01_faucet::run; update one to match the other so output and
implementation align—either change the banner string to reflect the faucet
(e.g., "Phase 1: Faucet") or rename/use the correct module/function
(phase_01_balance or similar) so the println! and phases::phase_01_faucet::run
refer to the same concept.
In `@tests/e2e/phases/phase_00_setup.rs`:
- Around line 94-104: The mnemonic/env var validation in run
(tests/e2e/phases/phase_00_setup.rs) duplicates the check performed in main.rs;
add a concise comment above the block in the run function explaining this
duplication is deliberate (fail-fast check in main + phase-local validation) so
future maintainers don't remove the early check; reference the run function and
the mnemonic variable/words validation to make the intent clear.
In `@tests/e2e/phases/phase_01_faucet.rs`:
- Around line 45-57: Add a brief inline comment above the ui_balance parsing
block (referencing balance_label and the ui_balance computation) that documents
the exact expected label format ("Balance: <number> DASH"), noting that the code
expects no thousands separators and a decimal point for fractions; optionally
mention that if format may change in future consider switching to a regex. This
clarifies assumptions for maintainers without altering the current parsing
logic.
In `@tests/e2e/phases/phase_06_dpns.rs`:
- Around line 77-91: The test uses query_all_by_label("Register Name").nth(1)
which is fragile; replace the positional selector with a more specific query
(e.g., a button role or a test id) or at minimum add a clarifying comment and
stronger assertion: update the call site that currently uses
query_all_by_label("Register Name").nth(1).expect(...).click() to instead target
a unique selector supported by egui_kittest (prefer a role-based or data-testid
equivalent) or, if not available, add a comment explaining that nth(0) is the
breadcrumb and nth(1) is the action button and tighten the pre-check (replace
reg_count >= 2 with an explicit check that the second element is a button) so
the intent is clear and the click cannot silently target the wrong element.
In `@tests/e2e/phases/phase_07_teardown.rs`:
- Around line 26-30: Print the E2E summary before asserting SPV reached a
terminal state by moving or duplicating the existing summary eprintln! lines
(the summary print block that currently runs later) to just before the assert!
that checks spv_stopped; specifically, emit the same eprintln! summary output
prior to the assert!(spv_stopped, "SPV must reach a terminal state after stop
(still active after {}s)", SPV_STOP_TIMEOUT.as_secs()) so that the summary is
printed even if the assertion panics.
AccessKit Role::Label nodes store display text in value(), not label(). kittest's query methods handle this internally, but there's no public API to read back the matched text from a found node. Add a node_text() helper that mirrors kittest's filter.rs logic exactly (value for Label roles, label for others) and use it in both capture_error_text and the Phase 1 balance check. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Rename phase_01_faucet to phase_01_wallet_ui to match what the phase actually does (no faucet interaction; it verifies balance display and wallet UI elements) - Run validation tests before SPV readiness gate in phase_05 since they are pure client-side checks that don't need SPV - Assert action button is present in sub-test B rather than silently skipping the click path when absent Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
tests/e2e/helpers/harness.rs (1)
372-376:ensure_spv_tx_ready:.unwrap()on RwLock reads gives opaque panic messages.Line 374 already uses a descriptive
.expect(...)for the wallet lookup; the two.unwrap()calls on the surrounding locks are inconsistent and would emit a cryptic "poisoned lock" message with no context if they ever fail.♻️ Proposed fix
- let wallets = app_ctx.wallets().read().unwrap(); + let wallets = app_ctx + .wallets() + .read() + .expect("wallets RwLock poisoned in ensure_spv_tx_ready"); let wallet = wallets .get(ctx.seed_hash()) .expect("Test wallet must exist in AppContext during tx phases"); - let w = wallet.read().unwrap(); + let w = wallet.read().expect("wallet RwLock poisoned in ensure_spv_tx_ready");Based on learnings: "Error handling refactoring is needed across the Dash-EVO-Tool codebase, particularly to avoid panics with
.expect()and instead propagate errors properly" — while this is test code where panicking is acceptable, using.expect()with descriptive messages is still preferable over.unwrap()for diagnostic clarity.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/e2e/helpers/harness.rs` around lines 372 - 376, Replace the cryptic .unwrap() calls on the RwLock reads in ensure_spv_tx_ready with descriptive .expect(...) messages: when reading app_ctx.wallets() replace .read().unwrap() with .read().expect("failed to acquire read lock on AppContext wallets RwLock in ensure_spv_tx_ready"), and when reading the returned wallet replace .read().unwrap() with .read().expect("failed to acquire read lock on Wallet in ensure_spv_tx_ready"); keep the existing .expect(...) on wallets.get(ctx.seed_hash()) as-is so all lock failures produce clear diagnostic messages referencing ensure_spv_tx_ready, app_ctx.wallets() and wallet.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@tests/e2e/helpers/harness.rs`:
- Around line 325-343: Move the final-attempt panic check so it occurs before
wasting frames in harness.run_steps: after calling dismiss_if_present(harness)
and optionally popping the screen (harness.state_mut().screen_stack.pop()),
check if attempt == PLATFORM_MAX_RETRIES and panic with the same message if
true; only call harness.run_steps(SETTLE_STEPS * attempt as usize) when not on
the final retry. This keeps the existing dismiss/pop behavior but avoids running
extra frames before the final panic.
---
Nitpick comments:
In `@tests/e2e/helpers/harness.rs`:
- Around line 372-376: Replace the cryptic .unwrap() calls on the RwLock reads
in ensure_spv_tx_ready with descriptive .expect(...) messages: when reading
app_ctx.wallets() replace .read().unwrap() with .read().expect("failed to
acquire read lock on AppContext wallets RwLock in ensure_spv_tx_ready"), and
when reading the returned wallet replace .read().unwrap() with
.read().expect("failed to acquire read lock on Wallet in ensure_spv_tx_ready");
keep the existing .expect(...) on wallets.get(ctx.seed_hash()) as-is so all lock
failures produce clear diagnostic messages referencing ensure_spv_tx_ready,
app_ctx.wallets() and wallet.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
tests/kittest/interactions.rs (1)
29-33:enable_welcome_screenhardcodesmainnet_app_contextregardless of current network.If the app is configured for testnet/devnet, the welcome screen created here always gets mainnet context. For the current UI-text/click tests this is benign, but it's a subtle divergence. The
current_app_context()method already exists onAppStateand returns&Arc<AppContext>, respecting the configured network via thechosen_networkfield.♻️ Suggested alternative
fn enable_welcome_screen(harness: &mut Harness<'_, dash_evo_tool::app::AppState>) { - let ctx = harness.state().mainnet_app_context.clone(); + let ctx = harness.state().current_app_context().clone(); harness.state_mut().show_welcome_screen = true; harness.state_mut().welcome_screen = Some(WelcomeScreen::new(ctx)); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/kittest/interactions.rs` around lines 29 - 33, enable_welcome_screen currently always uses mainnet_app_context; change it to use AppState::current_app_context() so it respects chosen_network. In the function enable_welcome_screen (and where it calls WelcomeScreen::new(ctx)), replace harness.state().mainnet_app_context.clone() with harness.state().current_app_context().clone() (or obtain a &Arc via current_app_context() and clone that) and keep the existing assignments to show_welcome_screen and welcome_screen.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@tests/e2e/main.rs`:
- Line 9: Update the doc comment that shows the run command so it includes the
Cargo feature flag: change the existing example "E2E_WALLET_MNEMONIC=\"...\"
cargo test --test e2e -- --ignored --nocapture" to include --all-features before
the test-args delimiter (i.e. "cargo test --test e2e --all-features -- --ignored
--nocapture") so the e2e feature is enabled when running the test; edit the run
command string in the tests/e2e/main.rs doc comment accordingly.
---
Nitpick comments:
In `@tests/kittest/interactions.rs`:
- Around line 29-33: enable_welcome_screen currently always uses
mainnet_app_context; change it to use AppState::current_app_context() so it
respects chosen_network. In the function enable_welcome_screen (and where it
calls WelcomeScreen::new(ctx)), replace
harness.state().mainnet_app_context.clone() with
harness.state().current_app_context().clone() (or obtain a &Arc via
current_app_context() and clone that) and keep the existing assignments to
show_welcome_screen and welcome_screen.
There was a problem hiding this comment.
🧹 Nitpick comments (2)
src/ui/wallets/wallets_screen/dialogs.rs (1)
170-172: Consider usingDashColors::ERRORfor theme consistency.The
send_dialog.errorblock a few lines below (Lines 195–213) usesDashColors::ERRORfor the same semantic role. The address-error label here stays on a raw(255, 100, 100)with no dark-mode awareness, which is a minor inconsistency.🎨 Proposed alignment with the theme
+ let dark_mode = ctx.style().visuals.dark_mode; if let Some(error) = &self.send_dialog.address_error { - ui.colored_label(egui::Color32::from_rgb(255, 100, 100), error); + ui.colored_label(DashColors::error_color(dark_mode), error); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/ui/wallets/wallets_screen/dialogs.rs` around lines 170 - 172, Replace the hard-coded color in the address-error label with the themed color constant: where you call ui.colored_label(...) for self.send_dialog.address_error, use DashColors::ERROR (the same theme used by the send_dialog.error block) so the label respects dark/light modes and theme consistency; update the call around send_dialog.address_error to use DashColors::ERROR instead of Color32::from_rgb(255, 100, 100).tests/e2e/main.rs (1)
44-47: Consider a brief// TODOlinking Phase 6 to a tracking issue.The skip comment explains why Phase 6 is disabled, but there's no reference to a tracking issue or milestone for re-enabling it once SPV mempool support lands. A
// TODO(#issue)would make it discoverable and prevent it from going stale.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/e2e/main.rs` around lines 44 - 47, Add a short TODO comment next to the Phase 6 skip comment/println that references the issue or milestone that will track re-enabling DPNS name registration (e.g., // TODO(`#1234`): re-enable Phase 6 when SPV mempool support lands or include the issue URL); place it immediately above or on the same line as the println!("\n=== Phase 6: DPNS Name Registration — SKIPPED ===") so the skip is discoverable and linked to the tracking ticket.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/ui/wallets/wallets_screen/dialogs.rs`:
- Around line 170-172: Replace the hard-coded color in the address-error label
with the themed color constant: where you call ui.colored_label(...) for
self.send_dialog.address_error, use DashColors::ERROR (the same theme used by
the send_dialog.error block) so the label respects dark/light modes and theme
consistency; update the call around send_dialog.address_error to use
DashColors::ERROR instead of Color32::from_rgb(255, 100, 100).
In `@tests/e2e/main.rs`:
- Around line 44-47: Add a short TODO comment next to the Phase 6 skip
comment/println that references the issue or milestone that will track
re-enabling DPNS name registration (e.g., // TODO(`#1234`): re-enable Phase 6 when
SPV mempool support lands or include the issue URL); place it immediately above
or on the same line as the println!("\n=== Phase 6: DPNS Name Registration —
SKIPPED ===") so the skip is discoverable and linked to the tracking ticket.
|
Clippy failure is a stale cache issue — the /rerun |
Co-authored-by: PastaClaw <thepastaclaw@users.noreply.github.com>
# Conflicts: # Cargo.toml # tests/e2e/navigation.rs # tests/e2e/wallet_flows.rs # tests/kittest/main.rs
chore: merge v1.0-dev into e2e
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/ui/identities/add_new_identity_screen/mod.rs (1)
95-95: Keep test-only identity state encapsulated behinde2eaccessors.Line 95 widens
successful_qualified_identity_idtopub(crate)for all builds. Prefer keeping the field private and exposing a feature-gated getter so non-e2e code can’t start depending on internal state.Proposed change
- pub(crate) successful_qualified_identity_id: Option<Identifier>, + successful_qualified_identity_id: Option<Identifier>,#[cfg(feature = "e2e")] impl AddNewIdentityScreen { + pub fn successful_qualified_identity_id(&self) -> Option<&Identifier> { + self.successful_qualified_identity_id.as_ref() + } + pub fn step(&self) -> &Arc<RwLock<WalletFundedScreenStep>> { &self.step }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/ui/identities/add_new_identity_screen/mod.rs` at line 95, The field successful_qualified_identity_id is currently exposed pub(crate) but should be private; make it private (remove pub(crate)) and add a feature-gated accessor for e2e tests: add a getter method named successful_qualified_identity_id on the same struct annotated with #[cfg(feature = "e2e")] and make it pub(crate) (or public as needed for tests) that returns the field (either by cloning Option<Identifier> or returning Option<&Identifier> depending on Identifier's ownership). This keeps the field encapsulated while allowing only code compiled with the "e2e" feature to read it.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@Cargo.toml`:
- Line 90: The unexpected_cfgs whitelist currently only allows "testing" and
causes warnings for uses of #[cfg(feature = "e2e")]; update the unexpected_cfgs
configuration to include "e2e" in the whitelist array (i.e., add the string
"e2e" alongside "testing" in the whitelist entry referenced by the
unexpected_cfgs config in Cargo.toml) so the feature is allowed where used in
src/ui/... and src/context/mod.rs.
---
Nitpick comments:
In `@src/ui/identities/add_new_identity_screen/mod.rs`:
- Line 95: The field successful_qualified_identity_id is currently exposed
pub(crate) but should be private; make it private (remove pub(crate)) and add a
feature-gated accessor for e2e tests: add a getter method named
successful_qualified_identity_id on the same struct annotated with #[cfg(feature
= "e2e")] and make it pub(crate) (or public as needed for tests) that returns
the field (either by cloning Option<Identifier> or returning Option<&Identifier>
depending on Identifier's ownership). This keeps the field encapsulated while
allowing only code compiled with the "e2e" feature to read it.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
Cargo.tomlsrc/context/mod.rssrc/ui/contracts_documents/add_contracts_screen.rssrc/ui/identities/add_existing_identity_screen.rssrc/ui/identities/add_new_identity_screen/mod.rssrc/ui/identities/register_dpns_name_screen.rssrc/ui/mod.rstests/kittest/main.rs
🚧 Files skipped from review as they are similar to previous changes (4)
- src/ui/identities/register_dpns_name_screen.rs
- tests/kittest/main.rs
- src/ui/contracts_documents/add_contracts_screen.rs
- src/ui/mod.rs
|
|
||
| [features] | ||
| testing = [] | ||
| e2e = [] |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's look at the Cargo.toml file, specifically around the lines mentioned
cat -n Cargo.toml | sed -n '85,120p'Repository: dashpay/dash-evo-tool
Length of output: 1908
🏁 Script executed:
# Search for any usage of #[cfg(feature = "e2e")] in the codebase
rg '#\[cfg\(feature\s*=\s*"e2e"' -A 2Repository: dashpay/dash-evo-tool
Length of output: 979
🏁 Script executed:
# Also search for cfg! macro usage with e2e feature
rg 'cfg!\s*\(\s*feature\s*=\s*"e2e"' -A 2Repository: dashpay/dash-evo-tool
Length of output: 47
Whitelist the new e2e feature in unexpected_cfgs checks.
The codebase uses #[cfg(feature = "e2e")] in multiple source files (src/ui/wallets/import_mnemonic_screen.rs, src/ui/identities/register_dpns_name_screen.rs, src/ui/identities/add_new_identity_screen/mod.rs, src/context/mod.rs), but line 116 only whitelists "testing". This triggers unexpected_cfgs warnings and will fail stricter CI runs.
Proposed fix
[lints.rust.unexpected_cfgs]
level = "warn"
-check-cfg = ["cfg(tokio_unstable)", "cfg(feature, values(\"testing\"))"]
+check-cfg = ["cfg(tokio_unstable)", "cfg(feature, values(\"testing\", \"e2e\"))"]🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@Cargo.toml` at line 90, The unexpected_cfgs whitelist currently only allows
"testing" and causes warnings for uses of #[cfg(feature = "e2e")]; update the
unexpected_cfgs configuration to include "e2e" in the whitelist array (i.e., add
the string "e2e" alongside "testing" in the whitelist entry referenced by the
unexpected_cfgs config in Cargo.toml) so the feature is allowed where used in
src/ui/... and src/context/mod.rs.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/e2e.yml:
- Line 67: Replace the direct cargo invocation with the repository-safe wrapper:
instead of running the command string 'cargo test --features="e2e" --test e2e --
--ignored --nocapture | tee /tmp/e2e.log', invoke the wrapper script
'scripts/safe-cargo.sh' to execute the exact same cargo arguments (e.g. run
'scripts/safe-cargo.sh cargo test --features="e2e" --test e2e -- --ignored
--nocapture | tee /tmp/e2e.log'); update the workflow step that currently runs
the 'cargo test ...' command so all E2E tests use the safe-cargo.sh wrapper.
- Line 34: Replace the deprecated GitHub Action usage by updating the workflow
step that references actions-rs/toolchain@v1 to use
dtolnay/rust-toolchain@stable instead; locate the uses: entry for
actions-rs/toolchain@v1 in the e2e.yml workflow and swap it to
dtolnay/rust-toolchain@stable so the action runs on supported runners.
| ${{ runner.os }}-cargo-registry- | ||
|
|
||
| - name: Install Rust toolchain | ||
| uses: actions-rs/toolchain@v1 |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
actions-rs/toolchain@v1 deprecated incompatible GitHub Actions runners 2024 2025
💡 Result:
actions-rs/toolchain@v1is an archived/unmaintained action (repo archived Oct 13, 2023) so it has not been updated for runner-runtime changes. [1]- Its
action.ymldeclaresruns: using: 'node12', meaning it depends on the Node 12 JavaScript action runtime. [2] - GitHub Actions deprecated Node 12 and began enforcing Node 16 instead of Node 12 starting June 14, 2023 (with only a temporary opt-out via
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION). This is whyactions-rs/toolchain@v1started triggering deprecation warnings / breakage on newer runners. [3] - GitHub then moved from Node 16 → Node 20 (default switch June 30, 2024) and ultimately removed Node 16 from runners on Nov 12, 2024, further tightening compatibility for old JavaScript actions. [4] [5]
What to do instead: migrate off actions-rs/toolchain@v1 to a maintained Rust toolchain installer such as dtolnay/rust-toolchain. [6]
Sources: [1] [2] [3] [4] [5] [6]
🌐 Web query:
dtolnay rust-toolchain GitHub Actions recommended replacement for actions-rs
💡 Result:
The commonly recommended replacement for the deprecated actions-rs/toolchain action is dtolnay/rust-toolchain. (github.com)
Example:
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable # or `@nightly`, or `@1.89.0`, etc.
- run: cargo test --all-featuresdtolnay/rust-toolchain installs Rust via rustup, and you can add components / targets via inputs if needed. (github.com)
Citations:
- 1: https://github.com/dtolnay/rust-toolchain?utm_source=openai
- 2: https://github.com/dtolnay/rust-toolchain?utm_source=openai
Replace actions-rs/toolchain@v1 with dtolnay/rust-toolchain@stable.
The actions-rs/toolchain repository was archived on October 13, 2023 and relies on the Node 12 JavaScript action runtime. GitHub Actions removed support for Node 12 on November 12, 2024, causing this action to fail on current runners. Use the maintained dtolnay/rust-toolchain@stable action instead:
- uses: dtolnay/rust-toolchain@stable🧰 Tools
🪛 actionlint (1.7.11)
[error] 34-34: the runner of "actions-rs/toolchain@v1" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/e2e.yml at line 34, Replace the deprecated GitHub Action
usage by updating the workflow step that references actions-rs/toolchain@v1 to
use dtolnay/rust-toolchain@stable instead; locate the uses: entry for
actions-rs/toolchain@v1 in the e2e.yml workflow and swap it to
dtolnay/rust-toolchain@stable so the action runs on supported runners.
| exit 0 | ||
| fi | ||
|
|
||
| cargo test --features="e2e" --test e2e -- --ignored --nocapture | tee /tmp/e2e.log |
There was a problem hiding this comment.
Use scripts/safe-cargo.sh for the E2E test command.
Line 67 calls cargo directly, which violates the workflow security guideline and bypasses CI secret scrubbing.
🔧 Proposed fix
- cargo test --features="e2e" --test e2e -- --ignored --nocapture | tee /tmp/e2e.log
+ scripts/safe-cargo.sh test --test e2e --all-features -- --ignored --nocapture | tee /tmp/e2e.logAs per coding guidelines: "Use scripts/safe-cargo.sh in GitHub Actions instead of calling cargo directly to prevent build scripts from accessing CI credentials."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/e2e.yml at line 67, Replace the direct cargo invocation
with the repository-safe wrapper: instead of running the command string 'cargo
test --features="e2e" --test e2e -- --ignored --nocapture | tee /tmp/e2e.log',
invoke the wrapper script 'scripts/safe-cargo.sh' to execute the exact same
cargo arguments (e.g. run 'scripts/safe-cargo.sh cargo test --features="e2e"
--test e2e -- --ignored --nocapture | tee /tmp/e2e.log'); update the workflow
step that currently runs the 'cargo test ...' command so all E2E tests use the
safe-cargo.sh wrapper.
Comprehensive end-to-end testing infrastructure for DET. Adds a phased e2e test suite that exercises the full user journey (wallet import → SPV sync → balance verification → platform reads → token search → identity validation → teardown) and kittest interaction tests for welcome screen behavior and navigation. Continuation of dashpay#598, rebased onto current v1.0-dev. Co-authored-by: PastaPastaPasta <pasta@dashboost.org> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Review GateCommit:
|
Summary by CodeRabbit
New Features
Tests