@@ -37,6 +37,8 @@ type SnapshotData = {
3737 analysis ?: AndroidSnapshotAnalysis ;
3838} ;
3939
40+ type AndroidFreshnessReason = 'empty-interactive' | 'sharp-drop' | 'stuck-route' ;
41+
4042export async function captureSnapshot ( params : CaptureSnapshotParams ) : Promise < {
4143 snapshot : SnapshotState ;
4244 analysis ?: AndroidSnapshotAnalysis ;
@@ -49,7 +51,7 @@ export async function captureSnapshot(params: CaptureSnapshotParams): Promise<{
4951 const data = await captureSnapshotData ( params ) ;
5052 clearAndroidSnapshotFreshness ( params . session ) ;
5153 return {
52- snapshot : buildSnapshotState ( data , params . flags ?. snapshotRaw ) ,
54+ snapshot : buildSnapshotState ( data , params . flags ) ,
5355 analysis : data . analysis ,
5456 } ;
5557}
@@ -85,30 +87,31 @@ async function captureAndroidFreshnessAwareSnapshot(
8587 freshness ?: AndroidFreshnessCaptureMeta ;
8688} > {
8789 let latest = await captureSnapshotAttempt ( params ) ;
88- let suspicious = isSuspiciousAndroidFreshnessCapture ( latest , freshness , params . flags ) ;
90+ let suspiciousReason = getAndroidFreshnessReason ( latest , freshness , params . flags ) ;
8991 let retryCount = 0 ;
9092
9193 for ( const delayMs of ANDROID_FRESHNESS_RETRY_DELAYS_MS ) {
92- if ( ! suspicious ) break ;
94+ if ( ! suspiciousReason ) break ;
9395 await new Promise ( ( resolve ) => setTimeout ( resolve , delayMs ) ) ;
9496 latest = await captureSnapshotAttempt ( params ) ;
9597 retryCount += 1 ;
96- suspicious = isSuspiciousAndroidFreshnessCapture ( latest , freshness , params . flags ) ;
98+ suspiciousReason = getAndroidFreshnessReason ( latest , freshness , params . flags ) ;
9799 }
98100
99- if ( ! suspicious ) {
101+ if ( ! suspiciousReason ) {
100102 clearAndroidSnapshotFreshness ( params . session ) ;
101103 }
102104
103105 return {
104106 snapshot : latest . snapshot ,
105107 analysis : latest . data . analysis ,
106108 freshness :
107- retryCount > 0 || suspicious
109+ retryCount > 0 || Boolean ( suspiciousReason )
108110 ? {
109111 action : freshness . action ,
110112 retryCount,
111- staleAfterRetries : suspicious ,
113+ staleAfterRetries : Boolean ( suspiciousReason ) ,
114+ reason : suspiciousReason ?? undefined ,
112115 }
113116 : undefined ,
114117 } ;
@@ -120,15 +123,15 @@ async function captureSnapshotAttempt(
120123 const data = await captureSnapshotData ( params ) ;
121124 return {
122125 data,
123- snapshot : buildSnapshotState ( data , params . flags ?. snapshotRaw ) ,
126+ snapshot : buildSnapshotState ( data , params . flags ) ,
124127 } ;
125128}
126129
127- function isSuspiciousAndroidFreshnessCapture (
130+ function getAndroidFreshnessReason (
128131 attempt : { data : SnapshotData ; snapshot : SnapshotState } ,
129132 freshness : NonNullable < SessionState [ 'androidSnapshotFreshness' ] > ,
130133 flags : CommandFlags | undefined ,
131- ) : boolean {
134+ ) : AndroidFreshnessReason | null {
132135 const interactiveOnly = flags ?. snapshotInteractiveOnly === true ;
133136 const analysis = attempt . data . analysis ;
134137
@@ -138,17 +141,18 @@ function isSuspiciousAndroidFreshnessCapture(
138141 analysis &&
139142 analysis . rawNodeCount >= 12
140143 ) {
141- return true ;
144+ return 'empty-interactive' ;
142145 }
143146
144147 if ( isLikelyStaleSnapshotDrop ( freshness . baselineCount , attempt . snapshot . nodes . length ) ) {
145- return ! hasMeaningfulSnapshotContent ( attempt . snapshot ) ;
148+ return ! hasMeaningfulSnapshotContent ( attempt . snapshot ) ? 'sharp-drop' : null ;
146149 }
147150
148- return (
151+ return freshness . routeComparable &&
149152 isNavigationSensitiveAction ( freshness . action ) &&
150153 isLikelySnapshotStuckOnPreviousRoute ( freshness . baselineSignatures , attempt . snapshot . nodes )
151- ) ;
154+ ? 'stuck-route'
155+ : null ;
152156}
153157
154158function hasMeaningfulSnapshotContent ( snapshot : SnapshotState ) : boolean {
@@ -167,15 +171,28 @@ export function buildSnapshotState(
167171 truncated ?: boolean ;
168172 backend ?: 'xctest' | 'android' | 'macos-helper' ;
169173 } ,
170- snapshotRaw : boolean | undefined ,
174+ flags :
175+ | ( Pick <
176+ CommandFlags ,
177+ 'snapshotCompact' | 'snapshotDepth' | 'snapshotInteractiveOnly' | 'snapshotRaw'
178+ > &
179+ Partial < Pick < CommandFlags , 'snapshotScope' > > )
180+ | undefined ,
171181) : SnapshotState {
172182 const rawNodes = data ?. nodes ?? [ ] ;
183+ const snapshotRaw = flags ?. snapshotRaw ;
173184 const nodes = attachRefs ( snapshotRaw ? rawNodes : pruneGroupNodes ( rawNodes ) ) ;
174185 return {
175186 nodes,
176187 truncated : data ?. truncated ,
177188 createdAt : Date . now ( ) ,
178189 backend : data ?. backend ,
190+ comparisonSafe :
191+ data ?. backend === 'android' &&
192+ flags ?. snapshotInteractiveOnly !== true &&
193+ flags ?. snapshotCompact !== true &&
194+ typeof flags ?. snapshotDepth !== 'number' &&
195+ ! flags ?. snapshotScope ,
179196 } ;
180197}
181198
0 commit comments