@@ -3,6 +3,30 @@ import { screen, fireEvent } from '@testing-library/react-native';
33import renderWithProvider from '../../../../../../util/test/renderWithProvider' ;
44import WhatsHappeningCard from './WhatsHappeningCard' ;
55import type { WhatsHappeningItem } from '../types' ;
6+ import { MetaMetricsEvents } from '../../../../../../core/Analytics/MetaMetrics.events' ;
7+
8+ const mockTrackEvent = jest . fn ( ) ;
9+ const mockCreateEventBuilder = jest . fn ( ( eventName : string ) => ( {
10+ addProperties : jest . fn ( ( properties : Record < string , unknown > ) => ( {
11+ build : jest . fn ( ( ) => ( { category : eventName , properties } ) ) ,
12+ } ) ) ,
13+ build : jest . fn ( ( ) => ( { category : eventName } ) ) ,
14+ } ) ) ;
15+
16+ let capturedOnVisible : ( ( ) => void ) | null = null ;
17+ jest . mock ( '../../../../../UI/MarketInsights/hooks/useViewportTracking' , ( ) => ( {
18+ useViewportTracking : ( onVisible : ( ) => void ) => {
19+ capturedOnVisible = onVisible ;
20+ return { ref : { current : null } , onLayout : jest . fn ( ) } ;
21+ } ,
22+ } ) ) ;
23+
24+ jest . mock ( '../../../../../hooks/useAnalytics/useAnalytics' , ( ) => ( {
25+ useAnalytics : ( ) => ( {
26+ trackEvent : mockTrackEvent ,
27+ createEventBuilder : mockCreateEventBuilder ,
28+ } ) ,
29+ } ) ) ;
630
731const mockRelatedAsset = {
832 sourceAssetId : 'btc-mainnet' ,
@@ -23,63 +47,68 @@ const baseItem: WhatsHappeningItem = {
2347} ;
2448
2549describe ( 'WhatsHappeningCard' , ( ) => {
50+ beforeEach ( ( ) => {
51+ jest . clearAllMocks ( ) ;
52+ capturedOnVisible = null ;
53+ } ) ;
54+
2655 it ( 'renders title and description' , ( ) => {
27- renderWithProvider ( < WhatsHappeningCard item = { baseItem } /> ) ;
56+ renderWithProvider ( < WhatsHappeningCard item = { baseItem } cardIndex = { 0 } /> ) ;
2857 expect ( screen . getByText ( baseItem . title ) ) . toBeOnTheScreen ( ) ;
2958 expect ( screen . getByText ( baseItem . description ) ) . toBeOnTheScreen ( ) ;
3059 } ) ;
3160
3261 it ( 'renders category badge when category is provided' , ( ) => {
33- renderWithProvider ( < WhatsHappeningCard item = { baseItem } /> ) ;
62+ renderWithProvider ( < WhatsHappeningCard item = { baseItem } cardIndex = { 0 } /> ) ;
3463 expect ( screen . getByText ( 'Macro' ) ) . toBeOnTheScreen ( ) ;
3564 } ) ;
3665
3766 it ( 'does not render category badge when category is absent' , ( ) => {
3867 const item = { ...baseItem , category : undefined } ;
39- renderWithProvider ( < WhatsHappeningCard item = { item } /> ) ;
68+ renderWithProvider ( < WhatsHappeningCard item = { item } cardIndex = { 0 } /> ) ;
4069 expect ( screen . queryByText ( 'Macro' ) ) . toBeNull ( ) ;
4170 } ) ;
4271
4372 it ( 'renders Bullish impact badge for positive impact' , ( ) => {
4473 const item = { ...baseItem , impact : 'positive' as const } ;
45- renderWithProvider ( < WhatsHappeningCard item = { item } /> ) ;
74+ renderWithProvider ( < WhatsHappeningCard item = { item } cardIndex = { 0 } /> ) ;
4675 expect ( screen . getByText ( 'Bullish' ) ) . toBeOnTheScreen ( ) ;
4776 } ) ;
4877
4978 it ( 'renders Bearish impact badge for negative impact' , ( ) => {
5079 const item = { ...baseItem , impact : 'negative' as const } ;
51- renderWithProvider ( < WhatsHappeningCard item = { item } /> ) ;
80+ renderWithProvider ( < WhatsHappeningCard item = { item } cardIndex = { 0 } /> ) ;
5281 expect ( screen . getByText ( 'Bearish' ) ) . toBeOnTheScreen ( ) ;
5382 } ) ;
5483
5584 it ( 'renders Neutral impact badge for neutral impact' , ( ) => {
5685 const item = { ...baseItem , impact : 'neutral' as const } ;
57- renderWithProvider ( < WhatsHappeningCard item = { item } /> ) ;
86+ renderWithProvider ( < WhatsHappeningCard item = { item } cardIndex = { 0 } /> ) ;
5887 expect ( screen . getByText ( 'Neutral' ) ) . toBeOnTheScreen ( ) ;
5988 } ) ;
6089
6190 it ( 'does not render impact badge when impact is absent' , ( ) => {
6291 const item = { ...baseItem , impact : undefined } ;
63- renderWithProvider ( < WhatsHappeningCard item = { item } /> ) ;
92+ renderWithProvider ( < WhatsHappeningCard item = { item } cardIndex = { 0 } /> ) ;
6493 expect ( screen . queryByText ( 'Bullish' ) ) . toBeNull ( ) ;
6594 expect ( screen . queryByText ( 'Bearish' ) ) . toBeNull ( ) ;
6695 expect ( screen . queryByText ( 'Neutral' ) ) . toBeNull ( ) ;
6796 } ) ;
6897
6998 it ( 'renders impact badge alongside category badge' , ( ) => {
70- renderWithProvider ( < WhatsHappeningCard item = { baseItem } /> ) ;
99+ renderWithProvider ( < WhatsHappeningCard item = { baseItem } cardIndex = { 0 } /> ) ;
71100 expect ( screen . getByText ( 'Bullish' ) ) . toBeOnTheScreen ( ) ;
72101 expect ( screen . getByText ( 'Macro' ) ) . toBeOnTheScreen ( ) ;
73102 } ) ;
74103
75104 it ( 'renders related asset symbol pills' , ( ) => {
76- renderWithProvider ( < WhatsHappeningCard item = { baseItem } /> ) ;
105+ renderWithProvider ( < WhatsHappeningCard item = { baseItem } cardIndex = { 0 } /> ) ;
77106 expect ( screen . getByText ( 'BTC' ) ) . toBeOnTheScreen ( ) ;
78107 } ) ;
79108
80109 it ( 'does not render asset pills when relatedAssets is empty' , ( ) => {
81110 const item = { ...baseItem , relatedAssets : [ ] } ;
82- renderWithProvider ( < WhatsHappeningCard item = { item } /> ) ;
111+ renderWithProvider ( < WhatsHappeningCard item = { item } cardIndex = { 0 } /> ) ;
83112 expect ( screen . queryByText ( 'BTC' ) ) . toBeNull ( ) ;
84113 } ) ;
85114
@@ -91,36 +120,57 @@ describe('WhatsHappeningCard', () => {
91120 caip19 : [ 'eip155:1/slip44:60' ] ,
92121 } ;
93122 const item = { ...baseItem , relatedAssets : [ mockRelatedAsset , ethAsset ] } ;
94- renderWithProvider ( < WhatsHappeningCard item = { item } /> ) ;
123+ renderWithProvider ( < WhatsHappeningCard item = { item } cardIndex = { 0 } /> ) ;
95124 expect ( screen . getByText ( 'BTC' ) ) . toBeOnTheScreen ( ) ;
96125 expect ( screen . getByText ( 'ETH' ) ) . toBeOnTheScreen ( ) ;
97126 } ) ;
98127
99128 it ( 'renders formatted date when date is valid' , ( ) => {
100- renderWithProvider ( < WhatsHappeningCard item = { baseItem } /> ) ;
129+ renderWithProvider ( < WhatsHappeningCard item = { baseItem } cardIndex = { 0 } /> ) ;
101130 expect ( screen . getByText ( 'Mar 15, 2026' ) ) . toBeOnTheScreen ( ) ;
102131 } ) ;
103132
104133 it ( 'does not render date when date string is invalid' , ( ) => {
105134 const item = { ...baseItem , date : 'not-a-date' } ;
106- renderWithProvider ( < WhatsHappeningCard item = { item } /> ) ;
135+ renderWithProvider ( < WhatsHappeningCard item = { item } cardIndex = { 0 } /> ) ;
107136 expect ( screen . queryByText ( 'not-a-date' ) ) . toBeNull ( ) ;
108137 } ) ;
109138
110139 it ( 'calls onPress with the item when tapped' , ( ) => {
111140 const onPress = jest . fn ( ) ;
112141 renderWithProvider (
113- < WhatsHappeningCard item = { baseItem } onPress = { onPress } /> ,
142+ < WhatsHappeningCard item = { baseItem } cardIndex = { 0 } onPress = { onPress } /> ,
114143 ) ;
115144 fireEvent . press ( screen . getByText ( baseItem . title ) ) ;
116145 expect ( onPress ) . toHaveBeenCalledTimes ( 1 ) ;
117146 expect ( onPress ) . toHaveBeenCalledWith ( baseItem ) ;
118147 } ) ;
119148
120149 it ( 'does not throw when onPress is not provided' , ( ) => {
121- renderWithProvider ( < WhatsHappeningCard item = { baseItem } /> ) ;
150+ renderWithProvider ( < WhatsHappeningCard item = { baseItem } cardIndex = { 0 } /> ) ;
122151 expect ( ( ) =>
123152 fireEvent . press ( screen . getByText ( baseItem . title ) ) ,
124153 ) . not . toThrow ( ) ;
125154 } ) ;
155+
156+ it ( 'tracks Whats Happening Card Scrolled to View when card becomes visible' , ( ) => {
157+ renderWithProvider ( < WhatsHappeningCard item = { baseItem } cardIndex = { 2 } /> ) ;
158+ expect ( capturedOnVisible ) . not . toBeNull ( ) ;
159+ capturedOnVisible ?.( ) ;
160+ expect ( mockCreateEventBuilder ) . toHaveBeenCalledWith (
161+ MetaMetricsEvents . WHATS_HAPPENING_CARD_SCROLLED_TO_VIEW ,
162+ ) ;
163+ expect ( mockTrackEvent ) . toHaveBeenCalledWith (
164+ expect . objectContaining ( {
165+ category : MetaMetricsEvents . WHATS_HAPPENING_CARD_SCROLLED_TO_VIEW ,
166+ properties : expect . objectContaining ( {
167+ event_id : 'trend-0' ,
168+ card_index : 2 ,
169+ category : 'macro' ,
170+ impact : 'positive' ,
171+ asset_symbols : [ 'BTC' ] ,
172+ } ) ,
173+ } ) ,
174+ ) ;
175+ } ) ;
126176} ) ;
0 commit comments