From c82a7b4d8c49cfb68f0110e3d489eff68c1e618b Mon Sep 17 00:00:00 2001 From: Sylvester Menawar Date: Sat, 30 May 2026 06:17:00 +0100 Subject: [PATCH] test: add component interaction tests for buttons, forms, navigation Adds @testing-library/react-native interaction tests that simulate real user behaviour (issue #53). Until now the suite only had logic/store/ service tests and no component rendering or interaction tests. New suites (24 tests): - Button: onPress called once, not called when disabled/loading, busy/disabled accessibility state - FloatingActionButton: onPress, icon/title rendering, accessibility label - FilterBar: search changeText, clear button, filter press, active count - SubscriptionCard: onPress receives the subscription, confirm-then-toggle flow, conditional toggle rendering/labelling - AddSubscriptionScreen: empty-name and invalid/missing-price validation, valid submit calls addSubscription with the entered data, cancel navigates back, dirty-form cancel prompts to discard Shared infrastructure: - src/test-utils.tsx: provider-wrapped render (SafeAreaProvider + NavigationContainer); supplies concrete safe-area metrics so children render under Jest where initialWindowMetrics is null - src/__fixtures__/subscriptions.ts: typed Subscription fixtures Tooling notes (required to run RN component tests, were not present): - devDeps: @testing-library/react-native@13.3.3, react-test-renderer@19.2.5 - overrides: hermes-parser / babel-plugin-syntax-hermes-parser pinned to 0.33.3 so babel-preset-expo can parse react-native 0.85 Flow source (the Expo 53 toolchain shipped 0.25.1, which fails on RN 0.85's `const` type parameters) No source/config files were modified beyond package.json. The 9 pre-existing failing suites (date-dependent business logic / network) are unchanged. Closes #53 Co-Authored-By: Claude Opus 4.8 (1M context) --- package-lock.json | 262 ++++++++++++++---- package.json | 6 + src/__fixtures__/subscriptions.ts | 57 ++++ src/components/common/Button.test.tsx | 57 ++++ .../common/FloatingActionButton.test.tsx | 34 +++ src/components/home/FilterBar.test.tsx | 63 +++++ .../subscription/SubscriptionCard.test.tsx | 84 ++++++ src/screens/AddSubscriptionScreen.test.tsx | 129 +++++++++ src/test-utils.tsx | 40 +++ 9 files changed, 682 insertions(+), 50 deletions(-) create mode 100644 src/__fixtures__/subscriptions.ts create mode 100644 src/components/common/Button.test.tsx create mode 100644 src/components/common/FloatingActionButton.test.tsx create mode 100644 src/components/home/FilterBar.test.tsx create mode 100644 src/components/subscription/SubscriptionCard.test.tsx create mode 100644 src/screens/AddSubscriptionScreen.test.tsx create mode 100644 src/test-utils.tsx diff --git a/package-lock.json b/package-lock.json index 3e952a6..a893833 100644 --- a/package-lock.json +++ b/package-lock.json @@ -57,6 +57,7 @@ "@semantic-release/npm": "^12.0.2", "@semantic-release/release-notes-generator": "^14.1.0", "@size-limit/file": "^11.1.4", + "@testing-library/react-native": "13.3.3", "@typechain/ethers-v5": "^11.1.2", "@types/detox": "^17.14.3", "@types/jest": "^29.5.14", @@ -75,6 +76,7 @@ "jest-expo": "~53.0.5", "lint-staged": "^16.4.0", "prettier": "^3.8.3", + "react-test-renderer": "19.2.5", "semantic-release": "^24.2.9", "size-limit": "^11.1.4", "ts-jest": "^29.4.11", @@ -5839,21 +5841,6 @@ "@babel/core": "*" } }, - "node_modules/@react-native/codegen/node_modules/hermes-estree": { - "version": "0.33.3", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.33.3.tgz", - "integrity": "sha512-6kzYZHCk8Fy1Uc+t3HGYyJn3OL4aeqKLTyina4UFtWl8I0kSL7OmKThaiX+Uh2f8nGw3mo4Ifxg0M5Zk3/Oeqg==", - "license": "MIT" - }, - "node_modules/@react-native/codegen/node_modules/hermes-parser": { - "version": "0.33.3", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.33.3.tgz", - "integrity": "sha512-Yg3HgaG4CqgyowtYjX/FsnPAuZdHOqSMtnbpylbptsQ9nwwSKsy6uRWcGO5RK0EqiX12q8HvDWKgeAVajRO5DA==", - "license": "MIT", - "dependencies": { - "hermes-estree": "0.33.3" - } - }, "node_modules/@react-native/community-cli-plugin": { "version": "0.85.2", "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.85.2.tgz", @@ -8437,6 +8424,124 @@ } } }, + "node_modules/@testing-library/react-native": { + "version": "13.3.3", + "resolved": "https://registry.npmjs.org/@testing-library/react-native/-/react-native-13.3.3.tgz", + "integrity": "sha512-k6Mjsd9dbZgvY4Bl7P1NIpePQNi+dfYtlJ5voi9KQlynxSyQkfOgJmYGCYmw/aSgH/rUcFvG8u5gd4npzgRDyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-matcher-utils": "^30.0.5", + "picocolors": "^1.1.1", + "pretty-format": "^30.0.5", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "jest": ">=29.0.0", + "react": ">=18.2.0", + "react-native": ">=0.71", + "react-test-renderer": ">=18.2.0" + }, + "peerDependenciesMeta": { + "jest": { + "optional": true + } + } + }, + "node_modules/@testing-library/react-native/node_modules/@jest/diff-sequences": { + "version": "30.4.0", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.4.0.tgz", + "integrity": "sha512-zOpzlfUs45l6u7jm39qr87JCHUDsaeCtvL+kQe/Vn9jSnRB4/5IPXISm0h9I1vZW/o00Kn4UTJ2MOlhnUGwv3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@testing-library/react-native/node_modules/@jest/schemas": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.4.1.tgz", + "integrity": "sha512-i6b4qw5qnP8c5FEeBJg/uZQ4ddrkN6Ca8qISJh0pr7a5hfn3h3v5x60BEbOC7OYAGZNMs1LfFLwnW2CuK8F57Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@testing-library/react-native/node_modules/@sinclair/typebox": { + "version": "0.34.49", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.49.tgz", + "integrity": "sha512-brySQQs7Jtn0joV8Xh9ZV/hZb9Ozb0pmazDIASBkYKCjXrXU3mpcFahmK/z4YDhGkQvP9mWJbVyahdtU5wQA+A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@testing-library/react-native/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/react-native/node_modules/jest-diff": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.4.1.tgz", + "integrity": "sha512-CRpFK0RtLriVDGcPPAnR6HMVI8bSR2jnUIgralhauzYQZIb4RH9AtEInTuQr65LmmGggGcRT6HIASxwqsVsmlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/diff-sequences": "30.4.0", + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "pretty-format": "30.4.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@testing-library/react-native/node_modules/jest-matcher-utils": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.4.1.tgz", + "integrity": "sha512-zvYfX5CaeEkFrrLS9suWe9rvJrm9J1Iv3ua8kIBv9GEPzcnsfBf0bob37la7s67fs0nlBC3EuvkOLnXQKxtx4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "jest-diff": "30.4.1", + "pretty-format": "30.4.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@testing-library/react-native/node_modules/pretty-format": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.4.1.tgz", + "integrity": "sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "30.4.1", + "ansi-styles": "^5.2.0", + "react-is-18": "npm:react-is@^18.3.1", + "react-is-19": "npm:react-is@^19.2.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -11795,12 +11900,12 @@ "integrity": "sha512-4hHoto6xaN23LCyZgL9LJZc3olmAxd7b6jDzlZnKXAh4rRAbZRKNBJoOOdp46OBqgy+K0t0guTj5/mhA8inymQ==" }, "node_modules/babel-plugin-syntax-hermes-parser": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.25.1.tgz", - "integrity": "sha512-IVNpGzboFLfXZUAwkLFcI/bnqVbwky0jP3eBno4HKtqvQJAHBLdgxiG6lQ4to0+Q/YCN3PO0od5NZwIKyY4REQ==", + "version": "0.33.3", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.33.3.tgz", + "integrity": "sha512-/Z9xYdaJ1lC0pT9do6TqCqhOSLfZ5Ot8D5za1p+feEfWYupCOfGbhhEXN9r2ZgJtDNUNRw/Z+T2CvAGKBqtqWA==", "license": "MIT", "dependencies": { - "hermes-parser": "0.25.1" + "hermes-parser": "0.33.3" } }, "node_modules/babel-plugin-transform-flow-enums": { @@ -18938,18 +19043,18 @@ "license": "MIT" }, "node_modules/hermes-estree": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", - "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "version": "0.33.3", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.33.3.tgz", + "integrity": "sha512-6kzYZHCk8Fy1Uc+t3HGYyJn3OL4aeqKLTyina4UFtWl8I0kSL7OmKThaiX+Uh2f8nGw3mo4Ifxg0M5Zk3/Oeqg==", "license": "MIT" }, "node_modules/hermes-parser": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", - "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "version": "0.33.3", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.33.3.tgz", + "integrity": "sha512-Yg3HgaG4CqgyowtYjX/FsnPAuZdHOqSMtnbpylbptsQ9nwwSKsy6uRWcGO5RK0EqiX12q8HvDWKgeAVajRO5DA==", "license": "MIT", "dependencies": { - "hermes-estree": "0.25.1" + "hermes-estree": "0.33.3" } }, "node_modules/highlight.js": { @@ -24554,6 +24659,16 @@ "dom-walk": "^0.1.0" } }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -29984,6 +30099,22 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "license": "MIT" }, + "node_modules/react-is-18": { + "name": "react-is", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/react-is-19": { + "name": "react-is", + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.6.tgz", + "integrity": "sha512-XjBR15BhXuylgWGuslhDKqlSayuqvqBX91BP8pauG8kd1zY8kotkNWbXksTCNRarse4kuGbe2kIY05ARtwNIvw==", + "dev": true, + "license": "MIT" + }, "node_modules/react-native": { "version": "0.85.2", "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.85.2.tgz", @@ -30354,15 +30485,6 @@ "react-native": "*" } }, - "node_modules/react-native/node_modules/babel-plugin-syntax-hermes-parser": { - "version": "0.33.3", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.33.3.tgz", - "integrity": "sha512-/Z9xYdaJ1lC0pT9do6TqCqhOSLfZ5Ot8D5za1p+feEfWYupCOfGbhhEXN9r2ZgJtDNUNRw/Z+T2CvAGKBqtqWA==", - "license": "MIT", - "dependencies": { - "hermes-parser": "0.33.3" - } - }, "node_modules/react-native/node_modules/commander": { "version": "12.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", @@ -30372,21 +30494,6 @@ "node": ">=18" } }, - "node_modules/react-native/node_modules/hermes-estree": { - "version": "0.33.3", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.33.3.tgz", - "integrity": "sha512-6kzYZHCk8Fy1Uc+t3HGYyJn3OL4aeqKLTyina4UFtWl8I0kSL7OmKThaiX+Uh2f8nGw3mo4Ifxg0M5Zk3/Oeqg==", - "license": "MIT" - }, - "node_modules/react-native/node_modules/hermes-parser": { - "version": "0.33.3", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.33.3.tgz", - "integrity": "sha512-Yg3HgaG4CqgyowtYjX/FsnPAuZdHOqSMtnbpylbptsQ9nwwSKsy6uRWcGO5RK0EqiX12q8HvDWKgeAVajRO5DA==", - "license": "MIT", - "dependencies": { - "hermes-estree": "0.33.3" - } - }, "node_modules/react-native/node_modules/scheduler": { "version": "0.27.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", @@ -30435,6 +30542,34 @@ "node": ">=0.10.0" } }, + "node_modules/react-test-renderer": { + "version": "19.2.5", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-19.2.5.tgz", + "integrity": "sha512-kwViRpdISMTpcpy5B6TSewfJzRjnajihRaj57ZmOWKD+SPN6k9LUM13O0pfOuW8ir6B6OOiAXwCRqOoVxRNykA==", + "dev": true, + "license": "MIT", + "dependencies": { + "react-is": "^19.2.5", + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.5" + } + }, + "node_modules/react-test-renderer/node_modules/react-is": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.6.tgz", + "integrity": "sha512-XjBR15BhXuylgWGuslhDKqlSayuqvqBX91BP8pauG8kd1zY8kotkNWbXksTCNRarse4kuGbe2kIY05ARtwNIvw==", + "dev": true, + "license": "MIT" + }, + "node_modules/react-test-renderer/node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "dev": true, + "license": "MIT" + }, "node_modules/read-package-up": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/read-package-up/-/read-package-up-11.0.0.tgz", @@ -30643,6 +30778,33 @@ "node": ">= 12.13.0" } }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/redent/node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/reduce-flatten": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", diff --git a/package.json b/package.json index fb96d7a..1ac5c93 100644 --- a/package.json +++ b/package.json @@ -95,6 +95,7 @@ "@semantic-release/npm": "^12.0.2", "@semantic-release/release-notes-generator": "^14.1.0", "@size-limit/file": "^11.1.4", + "@testing-library/react-native": "13.3.3", "@typechain/ethers-v5": "^11.1.2", "@types/detox": "^17.14.3", "@types/jest": "^29.5.14", @@ -113,6 +114,7 @@ "jest-expo": "~53.0.5", "lint-staged": "^16.4.0", "prettier": "^3.8.3", + "react-test-renderer": "19.2.5", "semantic-release": "^24.2.9", "size-limit": "^11.1.4", "ts-jest": "^29.4.11", @@ -120,6 +122,10 @@ "typescript": "~5.8.3" }, "private": false, + "overrides": { + "hermes-parser": "0.33.3", + "babel-plugin-syntax-hermes-parser": "0.33.3" + }, "repository": { "type": "git", "url": "https://github.com/Smartdevs17/SubTrackr.git" diff --git a/src/__fixtures__/subscriptions.ts b/src/__fixtures__/subscriptions.ts new file mode 100644 index 0000000..45fc6dd --- /dev/null +++ b/src/__fixtures__/subscriptions.ts @@ -0,0 +1,57 @@ +import { Subscription, SubscriptionCategory, BillingCycle } from '../types/subscription'; + +/** + * Shared test data for component interaction tests. + * + * Use these fixtures instead of inlining subscription objects in individual + * test cases so that the shape stays consistent with the real `Subscription` + * type across every suite. + */ +export const mockSubscription: Subscription = { + id: 'test-id-001', + name: 'Netflix', + description: 'Streaming service', + category: SubscriptionCategory.STREAMING, + price: 15.99, + currency: 'USD', + billingCycle: BillingCycle.MONTHLY, + nextBillingDate: new Date('2026-06-30T00:00:00.000Z'), + isActive: true, + isCryptoEnabled: false, + createdAt: new Date('2026-01-01T00:00:00.000Z'), + updatedAt: new Date('2026-01-01T00:00:00.000Z'), +}; + +export const mockPausedSubscription: Subscription = { + id: 'test-id-002', + name: 'Spotify', + description: 'Music streaming', + category: SubscriptionCategory.STREAMING, + price: 9.99, + currency: 'USD', + billingCycle: BillingCycle.MONTHLY, + nextBillingDate: new Date('2026-06-15T00:00:00.000Z'), + isActive: false, + isCryptoEnabled: false, + createdAt: new Date('2026-01-01T00:00:00.000Z'), + updatedAt: new Date('2026-01-01T00:00:00.000Z'), +}; + +export const mockSubscriptions: Subscription[] = [ + mockSubscription, + mockPausedSubscription, + { + id: 'test-id-003', + name: 'iCloud', + description: 'Cloud storage', + category: SubscriptionCategory.PRODUCTIVITY, + price: 2.99, + currency: 'USD', + billingCycle: BillingCycle.YEARLY, + nextBillingDate: new Date('2026-07-01T00:00:00.000Z'), + isActive: true, + isCryptoEnabled: false, + createdAt: new Date('2026-01-01T00:00:00.000Z'), + updatedAt: new Date('2026-01-01T00:00:00.000Z'), + }, +]; diff --git a/src/components/common/Button.test.tsx b/src/components/common/Button.test.tsx new file mode 100644 index 0000000..1cab517 --- /dev/null +++ b/src/components/common/Button.test.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import { render, screen, fireEvent } from '@testing-library/react-native'; +import { Button } from './Button'; + +describe('Button', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('press interactions', () => { + it('calls the onPress callback once when the button is pressed', () => { + const onPress = jest.fn(); + render(