From 2c14dc4f6bb0e8439738a649485a793e418c356c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Sat, 11 Apr 2026 10:18:18 +0200 Subject: [PATCH] test: stabilize android emulator boot tests --- .../android/__tests__/devices.test.ts | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/platforms/android/__tests__/devices.test.ts b/src/platforms/android/__tests__/devices.test.ts index 65a5d531f..41040ed21 100644 --- a/src/platforms/android/__tests__/devices.test.ts +++ b/src/platforms/android/__tests__/devices.test.ts @@ -1,9 +1,18 @@ -import { test } from 'vitest'; +import { beforeEach, test, vi } from 'vitest'; import assert from 'node:assert/strict'; -import { promises as fs } from 'node:fs'; +import { appendFileSync, promises as fs, writeFileSync } from 'node:fs'; import os from 'node:os'; import path from 'node:path'; +vi.mock('../../../utils/exec.ts', async (importOriginal) => { + const actual = await importOriginal(); + return { ...actual, runCmdDetached: vi.fn(actual.runCmdDetached) }; +}); + +const execActual = + await vi.importActual('../../../utils/exec.ts'); + import { AppError } from '../../../utils/errors.ts'; +import { runCmdDetached } from '../../../utils/exec.ts'; import { ensureAndroidEmulatorBooted, listAndroidDevices, @@ -15,6 +24,8 @@ import { resolveAndroidEmulatorAvdName, } from '../devices.ts'; +const mockRunCmdDetached = vi.mocked(runCmdDetached); + const MOCK_ANDROID_ADB_SCRIPT = [ '#!/bin/sh', 'if [ "$1" = "devices" ] && [ "$2" = "-l" ]; then', @@ -86,11 +97,27 @@ const MOCK_ANDROID_EMULATOR_SCRIPT = [ '', ]; +beforeEach(() => { + mockRunCmdDetached.mockReset(); + mockRunCmdDetached.mockImplementation(execActual.runCmdDetached); +}); + async function writeExecutable(filePath: string, lines: readonly string[]): Promise { await fs.writeFile(filePath, lines.join('\n'), 'utf8'); await fs.chmod(filePath, 0o755); } +function mockDetachedEmulatorLaunch(emulatorLogPath: string, emulatorBootedPath: string): void { + mockRunCmdDetached.mockImplementation((cmd, args, options) => { + if (cmd === 'emulator' && args[0] === '-avd') { + appendFileSync(emulatorLogPath, `${args.join(' ')}\n`, 'utf8'); + writeFileSync(emulatorBootedPath, 'ready', 'utf8'); + return 1234; + } + return execActual.runCmdDetached(cmd, args, options); + }); +} + async function withEnv( overrides: Record, run: () => Promise, @@ -161,6 +188,7 @@ async function withMockedAndroidTools( await writeExecutable(emulatorPath, MOCK_ANDROID_EMULATOR_SCRIPT); try { + mockDetachedEmulatorLaunch(emulatorLogPath, emulatorBootedPath); await withEnv( { PATH: `${tmpDir}${path.delimiter}${process.env.PATH ?? ''}`, @@ -201,6 +229,7 @@ async function withMockedAndroidSdkRoot( await writeExecutable(emulatorPath, MOCK_ANDROID_EMULATOR_SCRIPT); try { + mockDetachedEmulatorLaunch(emulatorLogPath, emulatorBootedPath); await withEnv( { PATH: process.env.PATH ?? '',