Skip to content

docs(testing): ban nested findBy inside waitFor in CV skill - #132

Merged
racitores merged 1 commit into
mainfrom
docs/cv-do-not-nest-findby-in-waitfor
Aug 19, 2026
Merged

docs(testing): ban nested findBy inside waitFor in CV skill#132
racitores merged 1 commit into
mainfrom
docs/cv-do-not-nest-findby-in-waitfor

Conversation

@racitores

Copy link
Copy Markdown
Contributor

Description

Component view tests that wrap findBy* in waitFor double-poll with the same 1s default timeout. Under CI load the outer waiter expires first and the log is only Timed out in waitFor. with no assertion detail (seen on WatchlistFullScreenView.view.test.tsx).

The mobile-testing CV skill still taught that nested shape in the data-completeness and nock examples. This change:

  • Adds golden rule 14: do not nest find* inside waitFor
  • Adds self-review item 15 and a diagnosing-failures row for the bare timeout
  • Replaces the nested examples with await findBy* (or waitFor + getBy* + { timeout })
  • Documents the antipattern in What NOT to Do

Type of Change

  • Skill improvement/update
  • New skill
  • Bug fix
  • Documentation update
  • Other (please describe):

Skill Details (if adding a new skill)

Provider Name:
Skill Name:
Brief Description:

Checklist

  • I have read the CONTRIBUTING.md guidelines
  • My skill follows the SKILL_TEMPLATE.md format
  • I have tested this skill with an AI agent
  • My skill does not contain any secrets, private keys, or sensitive data
  • I have added appropriate documentation
  • My changes don't break existing skills

Testing

N/A — documentation-only. Verified remaining waitFor(async () => findBy*) occurrences in the CV skill are the new ❌ examples.

Additional Context

Canonical skill: testing/mobile-testingreferences/component-view.md (and component-view/writing-tests.md, reference.md, navigation-mocking.md).

After merge, run yarn skills in metamask-mobile so local agents pick this up. The in-repo copy at docs/testing/component-view-tests.md is separate and still has the old example until that file is synced.

Made with Cursor

findBy already polls via waitFor with the same 1s default, so nesting them flakes in CI with a bare timeout and no assertion detail.

Co-authored-by: Cursor <cursoragent@cursor.com>
@racitores racitores self-assigned this Aug 19, 2026
@racitores
racitores marked this pull request as ready for review August 19, 2026 15:50
@racitores
racitores enabled auto-merge (squash) August 19, 2026 15:52
@racitores
racitores merged commit cce2ee1 into main Aug 19, 2026
28 checks passed
@racitores
racitores deleted the docs/cv-do-not-nest-findby-in-waitfor branch August 19, 2026 15:52
pull Bot pushed a commit to Reality2byte/metamask-mobile that referenced this pull request Aug 20, 2026
MetaMask#35032)

## **Description**

<!-- mms-check: type=text required=true -->

Fixes two flaky component-view waits that surfaced as CI failures. Both
are the same class of defect: the assertion does not actually wait for
the value being asserted.

**1. `WatchlistFullScreenView.view.test.tsx` — nested waiters**

The test `loads and displays all token fields for each editable row
(newest first)` failed with `Timed out in waitFor.` and no assertion
detail. It nested `findAllByTestId` inside `waitFor`. `findBy*` already
polls via `waitFor` (default 1000 ms), so both waiters share that budget
and the outer one expires before the inner query can surface a real
assertion error. Locally the nock + React Query path resolves in time;
on a loaded CI runner it does not.

It now uses a single `waitFor` with a synchronous `getAllByTestId`
callback and an explicit `{ timeout: 5000 }`, matching the search test
in the same file. A failure now reports the actual row count instead of
a bare timeout.

**2. `ActivityDetails.view.test.tsx` — awaiting the container, not the
content**

The Solana total row asserted a converted fiat amount (`$4.00` /
`$8.00`) synchronously. The row renders before the multichain conversion
rate resolves, so CI intermittently read `Total amount$0.00`. This
blocked an earlier run of this PR.

Both assertions are now wrapped in `waitFor` so they poll until the rate
settles. The awaited condition is the fiat text itself rather than the
row that contains it.

The nested-waiter antipattern was also present in the canonical
component-view testing guidance, fixed in
[MetaMask/skills#132](MetaMask/skills#132).

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

CHANGELOG entry: null

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Refs: failing CI runs
[93933344701](https://github.com/MetaMask/metamask-mobile/actions/runs/31537555318/job/93933344701)
(watchlist) and
[96133976774](https://github.com/MetaMask/metamask-mobile/actions/runs/32272692323/job/96133976774)
(activity details)

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

N/A — component view tests only, no runtime code touched. Verified
locally on the merged branch, both platforms:

```
TEST_OS=ios     yarn jest -c jest.config.view.js app/components/UI/Assets/watchlist/Views/WatchlistFullScreenView/WatchlistFullScreenView.view.test.tsx
TEST_OS=ios     yarn jest -c jest.config.view.js app/components/Views/ActivityDetails/ActivityDetails.view.test.tsx
TEST_OS=android yarn jest -c jest.config.view.js app/components/Views/ActivityDetails/ActivityDetails.view.test.tsx
```

All green (4 and 19 tests respectively).

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

### **Before**

N/A — no user-facing change.

### **After**

N/A — no user-facing change.

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

Not applicable — test-only change, no runtime code touched.

- [ ] I've tested on Android
- [ ] I've tested with a power user scenario
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants