Files
safe-wallet/apps/mobile/docs/e2e-tests-guidelines.md
TimandGitHub 06a773ddf6 tests(mobile): e2e coverage for WalletConnectGate flows (#7760)
* tests(mobile): add e2e coverage for WalletConnectGate flows

Adds Maestro tests for the two non-signing gate states on the
review-and-execute screen:

- wc-gate-reconnect.yml: expired session renders "Reconnect wallet to
  continue"; tapping restores the session and reveals Execute transaction.
- wc-gate-switch-network.yml: wrong-network state renders "Switch network
  to continue"; tapping clears the flag and reveals Execute transaction.

Wires up the e2e control surface:

- WalletConnectContext.e2e.tsx: mock reconnect() and switchNetworkIfNeeded()
  now flip walletConnectE2eState so the gate transitions correctly.
- TestCtrls: e2eWcGateReconnect and e2eWcGateWrongNetwork buttons.
- connectSignerSetup: setupWcGateReconnect / setupWcGateWrongNetwork seed
  a pending-tx safe with a WC signer in the desired gate state.

Pin [email protected] in package.json resolutions.

Part of WA-1858.

* tests(mobile): extract shared review-and-execute nav for wc-gate tests

Both wc-gate YAML tests duplicated ~30 lines navigating from app start to
the Review-and-Execute screen of the first pending tx. Move that navigation
into apps/mobile/e2e/utils/setup/open-review-and-execute.yml, parameterised
by SETUP_BUTTON_ID, and have both gate tests `runFlow` it. The seeding
button id is now the only piece of per-test configuration.

* tests(mobile): assert wc-gate dismissal by id, not by neighbouring text

The gate-dismissed assertion used a regex matching either "Execute
transaction" or "Insufficient funds". Those are distinct semantic states
(funded vs unfunded signer); coupling them in one assertion lets a
funds-error regression silently pass the gate test.

Replace the text regex with `extendedWaitUntil: notVisible` on the gate
button id. That waits for re-render and asserts the gate is gone in one
step, decoupling the test from the underlying execute-button copy.

* tests(mobile): drop unread fields from WC e2e state overrides

WalletConnectGate and useWalletConnectStatus only read `address`,
`isWrongNetwork`, and `isWalletConnectSigner`. The setup helpers and the
`reconnect` mock were also setting `hasProvider` and `walletInfo` —
unobservable from any production code path, so they only added noise.

- setupWcGateReconnect: drop the override entirely; post-reset defaults
  already model an expired session.
- setupWcGateWrongNetwork: drop hasProvider and walletInfo.
- WalletConnectContext.e2e.tsx reconnect mock: drop hasProvider.

* tests(mobile): add `wc-gate` tag to connect-signer suite

The two child flows (wc-gate-reconnect.yml, wc-gate-switch-network.yml)
declare a `wc-gate` tag, but the parent __suite__.yml didn't surface it.
Tag-based runs (`maestro test --include-tags wc-gate`) now also pick up
the aggregated suite, matching repo convention.

* tests(mobile): annotate wcSigner literal with explicit Signer type

The literal relied on inference plus `as const` on `type`. With an explicit
Signer annotation, future widening or narrowing of the discriminated union
in signersSlice will surface here at compile time instead of failing
silently in the e2e flow. The `as const` workaround is no longer needed.

* tests(mobile): reuse setupPendingTxSafe from WC gate setup

setupWcGateBase duplicated the pending-tx safe scaffolding already in
setupHelpers.ts (base config, signer registration, active safe/signer).
The only delta was the signer's `type: 'walletconnect'` and the extra
setExecutionMethod dispatch.

Extend setupPendingTxSafe with an optional `options.signer` override.
Existing five private-key callers are unchanged. setupWcGateBase now
constructs the WC Signer literal and delegates everything else to the
shared helper.

* docs(mobile): document `e2e<PascalCase>` exception for TestCtrls triggers

The repo-wide testID convention is kebab-case, but every TestCtrls
scenario-trigger button uses `e2eConnectSignerOwner`-style camelCase.
That divergence was undocumented, so new contributors would either
churn the convention or get pushed to match it without context.

Codify the exception: product testIDs stay kebab-case; the hidden
e2e-build-only TestCtrls triggers use `e2e<PascalCase>`.

* docs: document `[email protected]` resolution and add resolutions log

The root package.json `resolutions` block had 12 entries with zero
recorded rationale, so each new reviewer has to investigate why a pin
exists. Add `docs/resolutions.md` as the canonical home for that
rationale and seed it with the `[email protected]` entry — a benign dedup
(no CVE) added to align the transitive version under viem.

Future contributors are asked to update the log alongside any new
resolutions entry.
2026-04-28 10:35:30 +02:00

2.0 KiB

E2E Testing Guidelines for React Native

This document outlines best practices for writing and maintaining end-to-end tests.


1. TestID Naming Convention

  • Format: Use kebab-case.
  • Suffixes: Append a suffix that indicates the element type:
    • Button: continue-button
    • Tab: home-tab
    • Input: address-input
    • Screen: settings-screen
  • Uniqueness: It's virtually impossible to have unique testIDs across the app. We should make sure that every screen has unique testIDs.
  • Exception — TestCtrls triggers: The hidden buttons in TestCtrls.e2e.tsx that seed Redux state for a scenario use the e2e<PascalCase> form (e.g. e2eConnectSignerOwner, e2eWcGateReconnect). These IDs only exist in e2e builds and are scoped to test setup, so they are kept visually distinct from product testIDs.

2. File Structure & Naming

  • Directory: Keep all e2e tests under the /e2e directory.
  • File Names: Name test files to clearly reflect the tested feature.

3. Selector Best Practices

  • Primary Selector: Rely on testIDs for selecting elements.
  • Fallbacks: Use accessibility labels only when testIDs are not available.
  • Avoid: Do not use dynamic selectors or indexes as they can lead to flaky tests.

4. Running & Debugging Tests

The easiest way to write tests is to use Maestro Studio:

  • build the app and start the the e2e metro server:
yarn workspace @safe-global/mobile e2e:metro-ios

to run Maestro Studio:

maestro studio
  • Cross-Platform: Ideally, tests should run on both iOS and Android devices. In practice though Android tests are more flaky than iOS tests. Strive to run tests on both platforms, but prioritize iOS if necessary.

5. General Considerations

  • Maintenance: Regularly update tests to reflect UI changes.
  • Readability: Keep test code clean and well-documented.
  • Consistency: Adhere to project-wide code style and linting rules.

Happy testing!