1+ import migrate from './078' ;
2+ import { ensureValidState } from './util' ;
3+ import { captureException } from '@sentry/react-native' ;
4+
5+ jest . mock ( '@sentry/react-native' , ( ) => ( {
6+ captureException : jest . fn ( ) ,
7+ } ) ) ;
8+
9+ jest . mock ( './util' , ( ) => ( {
10+ ensureValidState : jest . fn ( ) ,
11+ } ) ) ;
12+
13+ const mockedCaptureException = jest . mocked ( captureException ) ;
14+ const mockedEnsureValidState = jest . mocked ( ensureValidState ) ;
15+
16+ describe ( 'Migration 078: Reset PhishingController phishingLists' , ( ) => {
17+ beforeEach ( ( ) => {
18+ jest . resetAllMocks ( ) ;
19+ } ) ;
20+
21+ it ( 'returns state unchanged if ensureValidState fails' , ( ) => {
22+ const state = { some : 'state' } ;
23+
24+ mockedEnsureValidState . mockReturnValue ( false ) ;
25+
26+ const migratedState = migrate ( state ) ;
27+
28+ expect ( migratedState ) . toBe ( state ) ;
29+ expect ( mockedCaptureException ) . not . toHaveBeenCalled ( ) ;
30+ } ) ;
31+
32+ it ( 'captures exception if PhishingController state is invalid' , ( ) => {
33+ const state = {
34+ engine : {
35+ backgroundState : {
36+ // PhishingController is missing
37+ } ,
38+ } ,
39+ } ;
40+
41+ mockedEnsureValidState . mockReturnValue ( true ) ;
42+
43+ const migratedState = migrate ( state ) ;
44+
45+ expect ( migratedState ) . toEqual ( state ) ;
46+ expect ( mockedCaptureException ) . toHaveBeenCalledWith ( expect . any ( Error ) ) ;
47+ expect ( mockedCaptureException . mock . calls [ 0 ] [ 0 ] . message ) . toContain (
48+ 'Migration 078: Invalid PhishingController state' ,
49+ ) ;
50+ } ) ;
51+
52+ it ( 'resets PhishingController phishingLists to empty array and stalelistLastFetched to 0 while preserving other fields' , ( ) => {
53+ interface TestState {
54+ engine : {
55+ backgroundState : {
56+ PhishingController : {
57+ c2DomainBlocklistLastFetched : number ;
58+ phishingLists : string [ ] ;
59+ whitelist : string [ ] ;
60+ hotlistLastFetched : number ;
61+ stalelistLastFetched : number ;
62+ extraProperty ?: string ;
63+ } ;
64+ OtherController : {
65+ shouldStayUntouched : boolean ;
66+ } ;
67+ } ;
68+ } ;
69+ }
70+
71+ const state : TestState = {
72+ engine : {
73+ backgroundState : {
74+ PhishingController : {
75+ c2DomainBlocklistLastFetched : 123456789 ,
76+ phishingLists : [ 'list1' , 'list2' ] ,
77+ whitelist : [ 'site1' , 'site2' ] ,
78+ hotlistLastFetched : 987654321 ,
79+ stalelistLastFetched : 123123123 ,
80+ extraProperty : 'should remain' ,
81+ } ,
82+ OtherController : {
83+ shouldStayUntouched : true ,
84+ } ,
85+ } ,
86+ } ,
87+ } ;
88+
89+ mockedEnsureValidState . mockReturnValue ( true ) ;
90+
91+ const migratedState = migrate ( state ) as typeof state ;
92+
93+ // PhishingLists should be reset to empty array and stalelistLastFetched to 0
94+ expect ( migratedState . engine . backgroundState . PhishingController . phishingLists ) . toEqual ( [ ] ) ;
95+ expect ( migratedState . engine . backgroundState . PhishingController . stalelistLastFetched ) . toBe ( 0 ) ;
96+
97+ // Other fields should remain unchanged
98+ expect ( migratedState . engine . backgroundState . PhishingController . c2DomainBlocklistLastFetched ) . toBe ( 123456789 ) ;
99+ expect ( migratedState . engine . backgroundState . PhishingController . whitelist ) . toEqual ( [ 'site1' , 'site2' ] ) ;
100+ expect ( migratedState . engine . backgroundState . PhishingController . hotlistLastFetched ) . toBe ( 987654321 ) ;
101+ expect ( migratedState . engine . backgroundState . PhishingController . extraProperty ) . toBe ( 'should remain' ) ;
102+
103+ // Other controllers should remain untouched
104+ expect ( migratedState . engine . backgroundState . OtherController ) . toEqual ( {
105+ shouldStayUntouched : true ,
106+ } ) ;
107+
108+ expect ( mockedCaptureException ) . not . toHaveBeenCalled ( ) ;
109+ } ) ;
110+
111+ it ( 'handles error during migration' , ( ) => {
112+ // Create state with a PhishingController that throws when phishingLists is accessed
113+ const state = {
114+ engine : {
115+ backgroundState : {
116+ PhishingController : Object . defineProperty ( { } , 'phishingLists' , {
117+ get : ( ) => {
118+ throw new Error ( 'Test error' ) ;
119+ } ,
120+ set : ( ) => {
121+ throw new Error ( 'Test error' ) ;
122+ } ,
123+ configurable : true ,
124+ enumerable : true ,
125+ } ) ,
126+ } ,
127+ } ,
128+ } ;
129+
130+ mockedEnsureValidState . mockReturnValue ( true ) ;
131+
132+ const migratedState = migrate ( state ) ;
133+
134+ expect ( migratedState ) . toEqual ( state ) ;
135+ expect ( mockedCaptureException ) . toHaveBeenCalledWith ( expect . any ( Error ) ) ;
136+ expect ( mockedCaptureException . mock . calls [ 0 ] [ 0 ] . message ) . toContain (
137+ 'Migration 078: cleaning PhishingController state failed with error' ,
138+ ) ;
139+ } ) ;
140+ } ) ;
0 commit comments