Skip to content

Commit 9ca4e07

Browse files
committed
chore: tighten ios screenshot fallback diagnostics
1 parent 1d875ba commit 9ca4e07

2 files changed

Lines changed: 35 additions & 5 deletions

File tree

src/platforms/ios/__tests__/index.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,11 @@ test('captureSimulatorScreenshotWithFallback emits fallback diagnostic before us
250250

251251
const log = await waitForFileText(logPath);
252252
assert.match(log, /"phase":"ios_screenshot_fallback"/);
253+
assert.match(log, /"deviceId":"sim-1"/);
254+
assert.match(log, /"errorCode":"COMMAND_FAILED"/);
253255
assert.match(log, /"from":"simctl_screenshot"/);
254256
assert.match(log, /"to":"runner"/);
257+
assert.match(log, /"commandArgs":"simctl io sim-1 screenshot \/tmp\/out\.png"/);
255258
} finally {
256259
await fs.rm(tmpDir, { recursive: true, force: true });
257260
}

src/platforms/ios/screenshot.ts

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export async function screenshotIos(device: DeviceInfo, outPath: string, appBund
6060
if (!shouldFallbackToRunnerForIosScreenshot(error)) {
6161
throw error;
6262
}
63-
emitScreenshotFallbackDiagnostic(device, 'devicectl_screenshot', 'runner', error);
63+
emitScreenshotFallbackDiagnostic(device, 'devicectl_screenshot', error);
6464
}
6565

6666
await captureScreenshotViaRunner(device, outPath, appBundleId);
@@ -84,7 +84,7 @@ export async function captureSimulatorScreenshotWithFallback(
8484
if (!deps.shouldFallbackToRunner(error)) {
8585
throw error;
8686
}
87-
emitScreenshotFallbackDiagnostic(device, 'simctl_screenshot', 'runner', error);
87+
emitScreenshotFallbackDiagnostic(device, 'simctl_screenshot', error);
8888
}
8989
await deps.captureWithRunner(device, outPath, appBundleId);
9090
}
@@ -220,22 +220,49 @@ function resolveDeadlineTimeoutMs(deadline: Deadline, timeoutMs: number, step: s
220220
function emitScreenshotFallbackDiagnostic(
221221
device: DeviceInfo,
222222
from: 'simctl_screenshot' | 'devicectl_screenshot',
223-
to: 'runner',
224223
error: unknown,
225224
): void {
225+
const errorMeta = extractScreenshotFallbackErrorMeta(error);
226226
emitDiagnostic({
227227
level: 'warn',
228228
phase: 'ios_screenshot_fallback',
229229
data: {
230230
platform: device.platform,
231231
deviceKind: device.kind,
232+
deviceId: device.id,
232233
from,
233-
to,
234-
reason: error instanceof Error ? error.message : String(error),
234+
to: 'runner',
235+
...errorMeta,
235236
},
236237
});
237238
}
238239

240+
function extractScreenshotFallbackErrorMeta(error: unknown): Record<string, unknown> {
241+
if (!(error instanceof AppError)) {
242+
return { reason: error instanceof Error ? error.message : String(error) };
243+
}
244+
const details = (error.details ?? {}) as {
245+
args?: unknown;
246+
exitCode?: unknown;
247+
stderr?: unknown;
248+
stdout?: unknown;
249+
timeoutMs?: unknown;
250+
};
251+
const args = Array.isArray(details.args)
252+
? details.args.filter((value): value is string => typeof value === 'string').join(' ')
253+
: undefined;
254+
255+
return {
256+
errorCode: error.code,
257+
reason: error.message,
258+
timeoutMs: typeof details.timeoutMs === 'number' ? details.timeoutMs : undefined,
259+
exitCode: typeof details.exitCode === 'number' ? details.exitCode : undefined,
260+
stderr: typeof details.stderr === 'string' && details.stderr.trim() ? details.stderr : undefined,
261+
stdout: typeof details.stdout === 'string' && details.stdout.trim() ? details.stdout : undefined,
262+
commandArgs: args,
263+
};
264+
}
265+
239266
export function resolveSimulatorRunnerScreenshotCandidatePaths(containerPath: string, remoteFileName: string): string[] {
240267
const normalizedContainerPath = path.resolve(containerPath);
241268
const rawRemotePath = remoteFileName.trim();

0 commit comments

Comments
 (0)