Skip to content

Commit 56acddb

Browse files
committed
refactor: tighten Android timeout evidence cleanup
1 parent cf31953 commit 56acddb

2 files changed

Lines changed: 25 additions & 20 deletions

File tree

src/daemon/android-snapshot-timeout-evidence.ts

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,10 @@ export async function maybeBuildAndroidSnapshotTimeoutFailure(params: {
4646
}): Promise<Extract<DaemonResponse, { ok: false }> | undefined> {
4747
if (params.command !== 'snapshot') return undefined;
4848
if (params.device.platform !== 'android') return undefined;
49-
if (!isAndroidSnapshotTimeoutError(params.error)) return undefined;
5049

5150
const normalized = normalizeError(params.error);
51+
if (!isAndroidSnapshotTimeoutError(normalized)) return undefined;
52+
5253
return {
5354
ok: false,
5455
error: {
@@ -74,13 +75,16 @@ async function captureAndroidSnapshotTimeoutEvidence(params: {
7475
const data = await dispatchCommand(params.device, 'screenshot', [screenshotPath], undefined, {
7576
...contextFromFlags(
7677
params.logPath,
78+
// Use a fresh unstabilized screenshot context; inheriting snapshot flags could repeat the
79+
// accessibility stabilization timeout that this fallback is trying to avoid.
7780
{ screenshotNoStabilize: true },
7881
params.session?.appBundleId,
7982
params.session?.trace?.outPath,
8083
),
8184
surface: params.session?.surface,
8285
});
8386
const resolvedPath = resolveCapturedScreenshotPath(data, screenshotPath);
87+
await fs.access(resolvedPath);
8488
const evidence = await annotateAndroidSnapshotTimeoutEvidence(resolvedPath, params.session);
8589

8690
emitDiagnostic({
@@ -112,16 +116,14 @@ async function annotateAndroidSnapshotTimeoutEvidence(
112116
screenshotPath: string,
113117
session: SessionState | undefined,
114118
): Promise<AndroidSnapshotTimeoutEvidence> {
115-
const evidence: AndroidSnapshotTimeoutEvidence = {
116-
path: screenshotPath,
117-
overlayRefsRequested: true,
118-
overlayRefsAnnotated: false,
119-
overlayRefSource: 'unavailable',
120-
overlayRefCount: 0,
121-
};
122-
123119
if (!session?.snapshot) {
124-
return evidence;
120+
return {
121+
path: screenshotPath,
122+
overlayRefsRequested: true,
123+
overlayRefsAnnotated: false,
124+
overlayRefSource: 'unavailable',
125+
overlayRefCount: 0,
126+
};
125127
}
126128

127129
try {
@@ -130,7 +132,8 @@ async function annotateAndroidSnapshotTimeoutEvidence(
130132
snapshot: session.snapshot,
131133
});
132134
return {
133-
...evidence,
135+
path: screenshotPath,
136+
overlayRefsRequested: true,
134137
overlayRefsAnnotated: overlayRefs.length > 0,
135138
overlayRefCount: overlayRefs.length,
136139
overlayRefSource: 'session-snapshot',
@@ -144,8 +147,11 @@ async function annotateAndroidSnapshotTimeoutEvidence(
144147
data: { path: screenshotPath, error: normalized.message },
145148
});
146149
return {
147-
...evidence,
150+
path: screenshotPath,
151+
overlayRefsRequested: true,
152+
overlayRefsAnnotated: false,
148153
overlayRefSource: 'session-snapshot',
154+
overlayRefCount: 0,
149155
overlayAnnotationError: normalized.message,
150156
};
151157
}
@@ -161,13 +167,12 @@ function hasStringPath(value: unknown): value is { path: string } {
161167
);
162168
}
163169

164-
function isAndroidSnapshotTimeoutError(error: unknown): boolean {
165-
const normalized = normalizeError(error);
166-
if (normalized.code !== 'COMMAND_FAILED') return false;
170+
function isAndroidSnapshotTimeoutError(error: NormalizedError): boolean {
171+
if (error.code !== 'COMMAND_FAILED') return false;
167172
return (
168-
hasKnownAndroidSnapshotTimeoutMessage(normalized) ||
169-
hasHelperTimeoutDetails(normalized.details?.helper) ||
170-
hasUiAutomatorDumpTimeoutDetails(normalized.details)
173+
hasKnownAndroidSnapshotTimeoutMessage(error) ||
174+
hasHelperTimeoutDetails(error.details?.helper) ||
175+
hasUiAutomatorDumpTimeoutDetails(error.details)
171176
);
172177
}
173178

src/daemon/handlers/__tests__/snapshot-handler.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,10 @@ function expectAndroidTimeoutEvidence(
147147
if (response.ok) throw new Error('Expected snapshot timeout failure');
148148
expect(response.error.message).toMatch(/UI hierarchy dump timed out/i);
149149
expect(response.error.hint).toMatch(/Use screenshot as visual truth/i);
150-
expectAndroidTimeoutEvidencePayload(response.error.details?.androidSnapshotTimeoutScreenshot);
150+
assertAndroidTimeoutEvidencePayload(response.error.details?.androidSnapshotTimeoutScreenshot);
151151
}
152152

153-
function expectAndroidTimeoutEvidencePayload(evidence: unknown) {
153+
function assertAndroidTimeoutEvidencePayload(evidence: unknown) {
154154
if (!evidence || typeof evidence !== 'object') {
155155
throw new Error('Expected Android snapshot timeout screenshot evidence');
156156
}

0 commit comments

Comments
 (0)