Skip to content

chore: ban new snapshot assertions in lint#27226

Closed
georgewrmarshall wants to merge 2 commits into
mainfrom
chore/ban-new-snapshot-lint
Closed

chore: ban new snapshot assertions in lint#27226
georgewrmarshall wants to merge 2 commits into
mainfrom
chore/ban-new-snapshot-lint

Conversation

@georgewrmarshall

@georgewrmarshall georgewrmarshall commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

Description

This PR adds an ESLint guard that rejects new snapshot assertions in *.test.* files.

The motivation is that mobile currently relies heavily on snapshot testing, and in many cases snapshots appear to be used for coverage rather than to validate the specific behavior described in the test. That creates a lot of churn for broad UI or token updates and makes it harder to review what actually changed.

A good example is the recent grey palette update:

That delta reflects a real difference in test strategy. Extension does not rely on UI snapshots nearly as much, while mobile absorbs large snapshot diffs for changes that are often unrelated to the behavior the test claims to cover.

Representative examples from mobile:

This PR is intentionally small. It does not remove, deprecate, or migrate the repository's existing snapshot tests. It only prevents new snapshot-based assertions from being added, so we can stop growing the problem while any broader migration is discussed separately.

Scope of enforcement:

  • Bans new uses of toMatchSnapshot
  • Bans new uses of toMatchInlineSnapshot
  • Bans new uses of toThrowErrorMatchingSnapshot
  • Bans new uses of toThrowErrorMatchingInlineSnapshot

The lint rule is also applied in overlapping ESLint overrides, including confirmation tests and view tests, so it is not silently dropped in those paths.

Changelog

CHANGELOG entry: null

Related issues

Fixes:

Manual testing steps

Feature: lint enforcement for snapshot assertions

  Scenario: developer adds a snapshot matcher to a test
    Given a test file contains expect(...).toMatchSnapshot()

    When eslint runs on that file
    Then lint fails with a message telling the author to use explicit behavioral assertions instead

Verified with:

./node_modules/.bin/eslint app/component-library/components/Badges/Badge/Badge.test.tsx --format unix
./node_modules/.bin/eslint app/components/Views/confirmations/__snapshot-ban-proof__.test.tsx --format unix
./node_modules/.bin/eslint app/util/test/__snapshot-ban-proof__.view.test.tsx --format unix

The two __snapshot-ban-proof__ files were temporary local proof files used to verify the overlapping override paths, and were removed afterward.

Screenshots/Recordings

Before

Not applicable.

After

Not applicable.

Pre-merge author checklist

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.

Note

Medium Risk
Low code risk (dev-only tooling), but it changes CI enforcement and can block merges if the base ref detection or snapshot matcher detection behaves unexpectedly.

Overview
Adds a new CI job, new-snapshot-assertions, that runs yarn lint:snapshots:new on PRs to prevent introducing additional snapshot-based assertions.

Introduces scripts/check-new-snapshot-assertions.js and the lint:snapshots:new package script, which compares changed test files against the PR base revision and fails the build if new snapshot matcher calls (e.g., toMatchSnapshot, inline snapshot, and snapshot-throw variants) are added.

Written by Cursor Bugbot for commit ee04356. This will update automatically on new commits. Configure here.

@github-actions

github-actions Bot commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Snapshot ban silently overridden by later no-restricted-syntax overrides
    • Duplicated the snapshot-ban selectors into the confirmations and view-test no-restricted-syntax overrides so they are not replaced by later overrides.

Create PR

Or push these changes by commenting:

@cursor push 2aad551ba1
Preview (2aad551ba1)
diff --git a/.eslintrc.js b/.eslintrc.js
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -190,6 +190,29 @@
               .join('|')}/]`,
             message: 'Avoid using global network selectors in confirmations',
           },
+          {
+            selector: "CallExpression[callee.property.name='toMatchSnapshot']",
+            message:
+              'Snapshot tests are banned. Use explicit behavioral assertions instead.',
+          },
+          {
+            selector:
+              "CallExpression[callee.property.name='toMatchInlineSnapshot']",
+            message:
+              'Inline snapshot tests are banned. Use explicit behavioral assertions instead.',
+          },
+          {
+            selector:
+              "CallExpression[callee.property.name='toThrowErrorMatchingSnapshot']",
+            message:
+              'Snapshot-based error assertions are banned. Assert on the error explicitly instead.',
+          },
+          {
+            selector:
+              "CallExpression[callee.property.name='toThrowErrorMatchingInlineSnapshot']",
+            message:
+              'Inline snapshot-based error assertions are banned. Assert on the error explicitly instead.',
+          },
         ],
       },
     },
@@ -227,6 +250,29 @@
             message:
               'Only Engine and react-native-device-info can be mocked in component-view tests.',
           },
+          {
+            selector: "CallExpression[callee.property.name='toMatchSnapshot']",
+            message:
+              'Snapshot tests are banned. Use explicit behavioral assertions instead.',
+          },
+          {
+            selector:
+              "CallExpression[callee.property.name='toMatchInlineSnapshot']",
+            message:
+              'Inline snapshot tests are banned. Use explicit behavioral assertions instead.',
+          },
+          {
+            selector:
+              "CallExpression[callee.property.name='toThrowErrorMatchingSnapshot']",
+            message:
+              'Snapshot-based error assertions are banned. Assert on the error explicitly instead.',
+          },
+          {
+            selector:
+              "CallExpression[callee.property.name='toThrowErrorMatchingInlineSnapshot']",
+            message:
+              'Inline snapshot-based error assertions are banned. Assert on the error explicitly instead.',
+          },
         ],
       },
     },

Comment thread .eslintrc.js Outdated
@georgewrmarshall georgewrmarshall self-assigned this Mar 9, 2026
@georgewrmarshall georgewrmarshall added the team-design-system All issues relating to design system in Mobile label Mar 9, 2026
@georgewrmarshall georgewrmarshall force-pushed the chore/ban-new-snapshot-lint branch from 9e4fb71 to b2461d4 Compare March 9, 2026 21:47
@github-actions github-actions Bot added the size-S label Mar 9, 2026
@github-actions

github-actions Bot commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

E2E Fixture Validation — Schema is up to date
9 value mismatches detected (expected — fixture represents an existing user).
View details

@github-actions github-actions Bot added size-M and removed size-S labels Mar 10, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: None (no tests recommended)
  • Selected Performance tags: None (no tests recommended)
  • Risk Level: low
  • AI Confidence: 96%
click to see 🤖 AI reasoning details

E2E Test Selection:
All changes are limited to CI and repository tooling:

  1. .github/workflows/ci.yml – Adds a new CI job (new-snapshot-assertions) that runs a custom lint script.
  2. package.json – Adds a new npm script (lint:snapshots:new) invoking a Node script.
  3. scripts/check-new-snapshot-assertions.js – New Node-based utility that inspects git diffs to prevent adding new Jest snapshot matchers in changed test files.

There are no changes to:

  • app/ source code
  • Controllers or Engine
  • UI components or navigation
  • Detox test specs or page objects
  • Performance-sensitive logic

The new script only analyzes test files during CI and does not affect runtime behavior, build output, app initialization, wallet flows, confirmations, network logic, or any user-facing functionality.

Therefore, no E2E test tags are required to validate this PR. Running Detox suites would not provide additional safety for this CI-only change.

Risk assessment: Low – Infrastructure/lint-only change with no impact on application runtime or E2E flows.

Performance Test Selection:
No application code, rendering logic, controllers, state management, or startup paths were modified. This change cannot impact runtime performance, so no performance tests are needed.

View GitHub Actions results

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Snapshot check job not wired into merge gate
    • Added new-snapshot-assertions to all-jobs-pass.needs so the merge gate enforces it.

Create PR

Or push these changes by commenting:

@cursor push 487624b5ac
Preview (487624b5ac)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -726,6 +726,7 @@
         check-workflows,
         js-bundle-size-check,
         sonar-cloud-quality-gate-status,
+        new-snapshot-assertions,
       ]
     outputs:
       ALL_JOBS_PASSED: ${{ steps.jobs-passed-status.outputs.ALL_JOBS_PASSED }}

Comment thread .github/workflows/ci.yml
if: ${{ github.event_name == 'pull_request' && github.base_ref != '' }}
run: git fetch origin ${{ github.base_ref }} --depth=1
- run: yarn lint:snapshots:new

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Snapshot check job not wired into merge gate

High Severity

The new new-snapshot-assertions job is not listed in the needs array of the all-jobs-pass gate job. Since all-jobs-pass is the sole input to check-all-jobs-pass (the merge gate), a failure in new-snapshot-assertions is silently ignored. PRs that add new snapshot assertions will pass CI and can still be merged, completely defeating the purpose of this PR.

Additional Locations (1)
Fix in Cursor Fix in Web

@sonarqubecloud

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

This PR has been automatically marked as stale because it has not had recent activity in the last 90 days. It will be closed in 7 days. Thank you for your contributions.

@github-actions github-actions Bot added the stale Issues that have not had activity in the last 90 days label Jun 9, 2026
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 9, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

size-M stale Issues that have not had activity in the last 90 days team-design-system All issues relating to design system in Mobile

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant