@@ -4,6 +4,26 @@ import { LOCAL_UPDATE_HASHES, LOCAL_UPDATE_LABELS } from './localUpdateConfig.ts
44const RELOAD_TIMEOUT = 180000 ;
55const MARK_SUCCESS_TIMEOUT = 30000 ;
66const MARK_SUCCESS_SETTLE_MS = 1500 ;
7+ const DOWNLOAD_SUCCESS_TIMEOUT = 120000 ;
8+
9+ function getDetoxLaunchArgs ( ) {
10+ if ( device . getPlatform ( ) !== 'android' ) {
11+ return { } ;
12+ }
13+
14+ return {
15+ launchArgs : {
16+ detoxEnableSynchronization : '0' ,
17+ } ,
18+ } ;
19+ }
20+
21+ async function relaunchAppPreservingData ( ) {
22+ await device . launchApp ( {
23+ newInstance : true ,
24+ ...getDetoxLaunchArgs ( ) ,
25+ } ) ;
26+ }
727
828async function tapCheckUpdate ( ) {
929 await waitFor ( element ( by . id ( 'check-update' ) ) ) . toBeVisible ( ) . withTimeout ( 30000 ) ;
@@ -17,8 +37,9 @@ async function waitForBundleLabel(expectedLabel: string) {
1737}
1838
1939async function waitForHash ( expectedHash : string ) {
40+ const visibleHash = expectedHash || '(empty)' ;
2041 await waitFor ( element ( by . id ( 'current-hash' ) ) )
21- . toHaveText ( `currentHash: ${ expectedHash } ` )
42+ . toHaveText ( `currentHash: ${ visibleHash } ` )
2243 . withTimeout ( RELOAD_TIMEOUT ) ;
2344}
2445
@@ -29,27 +50,51 @@ async function waitForMarkSuccess() {
2950 await new Promise ( resolve => setTimeout ( resolve , MARK_SUCCESS_SETTLE_MS ) ) ;
3051}
3152
53+ async function waitForDownloadSuccess ( expectedHash : string ) {
54+ await waitFor ( element ( by . id ( 'last-event' ) ) )
55+ . toHaveText ( 'lastEvent: downloadSuccess' )
56+ . withTimeout ( DOWNLOAD_SUCCESS_TIMEOUT ) ;
57+ await waitFor ( element ( by . id ( 'last-event-version' ) ) )
58+ . toHaveText ( `lastEventVersion: ${ expectedHash } ` )
59+ . withTimeout ( DOWNLOAD_SUCCESS_TIMEOUT ) ;
60+ }
61+
3262async function waitForReady ( ) {
3363 await waitFor ( element ( by . id ( 'check-update' ) ) ) . toBeVisible ( ) . withTimeout ( 30000 ) ;
3464}
3565
66+ async function waitForCheckState ( expectedStatus : string , expectedResult : string ) {
67+ await waitFor ( element ( by . id ( 'last-check-status' ) ) )
68+ . toHaveText ( `lastCheckStatus: ${ expectedStatus } ` )
69+ . withTimeout ( RELOAD_TIMEOUT ) ;
70+ await waitFor ( element ( by . id ( 'last-check-result' ) ) )
71+ . toHaveText ( `lastCheckResult: ${ expectedResult } ` )
72+ . withTimeout ( RELOAD_TIMEOUT ) ;
73+ }
74+
75+ async function waitForStrategy ( expectedStrategy : 'silentAndNow' | 'silentAndLater' ) {
76+ await waitFor ( element ( by . id ( 'update-strategy' ) ) )
77+ . toHaveText ( `updateStrategy: ${ expectedStrategy } ` )
78+ . withTimeout ( 10000 ) ;
79+ }
80+
81+ async function selectStrategy ( testId : 'strategy-silent-now' | 'strategy-silent-later' ) {
82+ await waitFor ( element ( by . id ( testId ) ) ) . toBeVisible ( ) . withTimeout ( 10000 ) ;
83+ await element ( by . id ( testId ) ) . tap ( ) ;
84+ }
85+
3686describe ( 'Local Update Merge E2E' , ( ) => {
37- beforeAll ( async ( ) => {
87+ beforeEach ( async ( ) => {
3888 await device . launchApp ( {
3989 newInstance : true ,
4090 delete : true ,
41- ...( device . getPlatform ( ) === 'android'
42- ? {
43- launchArgs : {
44- detoxEnableSynchronization : '0' ,
45- } ,
46- }
47- : { } ) ,
91+ ...getDetoxLaunchArgs ( ) ,
4892 } ) ;
4993 } ) ;
5094
5195 it ( 'covers local full update, diff merge, and package diff through checkUpdate + silentAndNow' , async ( ) => {
5296 await waitForReady ( ) ;
97+ await waitForStrategy ( 'silentAndNow' ) ;
5398 await waitForBundleLabel ( LOCAL_UPDATE_LABELS . base ) ;
5499
55100 await tapCheckUpdate ( ) ;
@@ -68,5 +113,91 @@ describe('Local Update Merge E2E', () => {
68113 await waitForHash ( LOCAL_UPDATE_HASHES . packagePatch ) ;
69114 await waitForMarkSuccess ( ) ;
70115 }
116+
117+ const finalLabel =
118+ device . getPlatform ( ) === 'android'
119+ ? LOCAL_UPDATE_LABELS . packagePatch
120+ : LOCAL_UPDATE_LABELS . ppkPatch ;
121+ const finalHash =
122+ device . getPlatform ( ) === 'android'
123+ ? LOCAL_UPDATE_HASHES . packagePatch
124+ : LOCAL_UPDATE_HASHES . ppkPatch ;
125+
126+ await relaunchAppPreservingData ( ) ;
127+ await waitForReady ( ) ;
128+ await waitForBundleLabel ( finalLabel ) ;
129+ await waitForHash ( finalHash ) ;
130+
131+ await tapCheckUpdate ( ) ;
132+ await waitForCheckState ( 'completed' , 'upToDate' ) ;
133+ await waitForBundleLabel ( finalLabel ) ;
134+ await waitForHash ( finalHash ) ;
135+ } ) ;
136+
137+ it ( 'covers local full update, deferred install, and follow-up deferred patches through silentAndLater' , async ( ) => {
138+ await waitForReady ( ) ;
139+ await waitForBundleLabel ( LOCAL_UPDATE_LABELS . base ) ;
140+
141+ await selectStrategy ( 'strategy-silent-later' ) ;
142+ await waitForStrategy ( 'silentAndLater' ) ;
143+
144+ await tapCheckUpdate ( ) ;
145+ await waitForCheckState ( 'completed' , `update:${ LOCAL_UPDATE_HASHES . full } ` ) ;
146+ await waitForDownloadSuccess ( LOCAL_UPDATE_HASHES . full ) ;
147+ await waitForBundleLabel ( LOCAL_UPDATE_LABELS . base ) ;
148+ await waitForHash ( '' ) ;
149+
150+ await relaunchAppPreservingData ( ) ;
151+ await waitForReady ( ) ;
152+ await waitForBundleLabel ( LOCAL_UPDATE_LABELS . full ) ;
153+ await waitForHash ( LOCAL_UPDATE_HASHES . full ) ;
154+ await waitForMarkSuccess ( ) ;
155+
156+ await selectStrategy ( 'strategy-silent-later' ) ;
157+ await waitForStrategy ( 'silentAndLater' ) ;
158+ await tapCheckUpdate ( ) ;
159+ await waitForCheckState ( 'completed' , `update:${ LOCAL_UPDATE_HASHES . ppkPatch } ` ) ;
160+ await waitForDownloadSuccess ( LOCAL_UPDATE_HASHES . ppkPatch ) ;
161+ await waitForBundleLabel ( LOCAL_UPDATE_LABELS . full ) ;
162+ await waitForHash ( LOCAL_UPDATE_HASHES . full ) ;
163+
164+ await relaunchAppPreservingData ( ) ;
165+ await waitForReady ( ) ;
166+ await waitForBundleLabel ( LOCAL_UPDATE_LABELS . ppkPatch ) ;
167+ await waitForHash ( LOCAL_UPDATE_HASHES . ppkPatch ) ;
168+ await waitForMarkSuccess ( ) ;
169+
170+ if ( device . getPlatform ( ) === 'android' ) {
171+ await selectStrategy ( 'strategy-silent-later' ) ;
172+ await waitForStrategy ( 'silentAndLater' ) ;
173+ await tapCheckUpdate ( ) ;
174+ await waitForCheckState (
175+ 'completed' ,
176+ `update:${ LOCAL_UPDATE_HASHES . packagePatch } ` ,
177+ ) ;
178+ await waitForDownloadSuccess ( LOCAL_UPDATE_HASHES . packagePatch ) ;
179+ await waitForBundleLabel ( LOCAL_UPDATE_LABELS . ppkPatch ) ;
180+ await waitForHash ( LOCAL_UPDATE_HASHES . ppkPatch ) ;
181+
182+ await relaunchAppPreservingData ( ) ;
183+ await waitForReady ( ) ;
184+ await waitForBundleLabel ( LOCAL_UPDATE_LABELS . packagePatch ) ;
185+ await waitForHash ( LOCAL_UPDATE_HASHES . packagePatch ) ;
186+ await waitForMarkSuccess ( ) ;
187+ }
188+
189+ const finalLabel =
190+ device . getPlatform ( ) === 'android'
191+ ? LOCAL_UPDATE_LABELS . packagePatch
192+ : LOCAL_UPDATE_LABELS . ppkPatch ;
193+ const finalHash =
194+ device . getPlatform ( ) === 'android'
195+ ? LOCAL_UPDATE_HASHES . packagePatch
196+ : LOCAL_UPDATE_HASHES . ppkPatch ;
197+
198+ await tapCheckUpdate ( ) ;
199+ await waitForCheckState ( 'completed' , 'upToDate' ) ;
200+ await waitForBundleLabel ( finalLabel ) ;
201+ await waitForHash ( finalHash ) ;
71202 } ) ;
72203} ) ;
0 commit comments