Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/platforms/android/__tests__/adb-executor.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
import assert from 'node:assert/strict';
import { test, vi } from 'vitest';

const { spawnMock } = vi.hoisted(() => ({
spawnMock: vi.fn(() => ({})),
}));

vi.mock('node:child_process', async (importOriginal) => {
const actual = await importOriginal<typeof import('node:child_process')>();
return {
...actual,
spawn: spawnMock,
};
});

vi.mock('../../../utils/exec.ts', async (importOriginal) => {
const actual = await importOriginal<typeof import('../../../utils/exec.ts')>();
return {
Expand Down Expand Up @@ -114,9 +126,17 @@ test('createLocalAndroidAdbProvider exposes exec, spawn, and reverse over local
});

await provider.exec(['shell', 'echo', 'ok']);
provider.spawn?.(['logcat'], { stdio: ['ignore', 'pipe', 'pipe'] });
await provider.reverse?.ensure({ local: 'tcp:8081', remote: 'tcp:8081', ownerId: 'session-a' });
await provider.reverse?.removeAllOwned('session-a');

assert.deepEqual(spawnMock.mock.calls, [
[
'adb',
['-s', 'emulator-5554', 'logcat'],
{ stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true },
],
]);
assert.deepEqual(
mockRunCmd.mock.calls.map((call) => call[1]),
[
Expand Down
3 changes: 2 additions & 1 deletion src/platforms/android/adb-executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ function createSerialAdbExecutor(serial: string): AndroidAdbExecutor {
}

function createSerialAdbSpawner(serial: string): AndroidAdbSpawner {
return (args, options) => spawn('adb', ['-s', serial, ...args], options ?? {});
return (args, options) =>
spawn('adb', ['-s', serial, ...args], { ...options, windowsHide: true });
}

export function createLocalAndroidAdbProvider(device: DeviceInfo): AndroidAdbProvider {
Expand Down
61 changes: 61 additions & 0 deletions src/utils/__tests__/exec-windows-hide.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import assert from 'node:assert/strict';
import { EventEmitter } from 'node:events';
import { PassThrough } from 'node:stream';
import { beforeEach, test, vi } from 'vitest';

type MockChildProcess = EventEmitter & {
stdin: PassThrough;
stdout: PassThrough;
stderr: PassThrough;
kill: ReturnType<typeof vi.fn>;
unref: ReturnType<typeof vi.fn>;
};

const { spawnMock, spawnSyncMock } = vi.hoisted(() => ({
spawnMock: vi.fn(),
spawnSyncMock: vi.fn(),
}));

vi.mock('node:child_process', () => ({
spawn: spawnMock,
spawnSync: spawnSyncMock,
}));

import { runCmd, runCmdBackground, runCmdDetached, runCmdSync } from '../exec.ts';

beforeEach(() => {
spawnMock.mockReset();
spawnSyncMock.mockReset();
});

test('process helpers hide Windows console windows for spawned commands', async () => {
spawnMock.mockImplementation(() => makeMockChild());
spawnSyncMock.mockReturnValue({ stdout: '', stderr: '', status: 0 });

await runCmd('node', ['--version']);
runCmdSync('node', ['--version']);
runCmdDetached('node', ['--version']);
runCmdBackground('node', ['--version']);

for (const call of spawnMock.mock.calls) {
assert.equal(call[2]?.windowsHide, true);
}
assert.equal(spawnSyncMock.mock.calls[0]?.[2]?.windowsHide, true);
});

function makeMockChild(): ReturnType<typeof import('node:child_process').spawn> {
const child = new EventEmitter() as MockChildProcess;
child.stdin = new PassThrough();
child.stdout = new PassThrough();
child.stderr = new PassThrough();
child.kill = vi.fn(() => true);
child.unref = vi.fn();

queueMicrotask(() => {
child.stdout?.end();
child.stderr?.end();
child.emit('close', 0, null);
});

return child as unknown as ReturnType<typeof import('node:child_process').spawn>;
}
4 changes: 4 additions & 0 deletions src/utils/exec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ function runSpawnedCommand(
env: options.env,
stdio: ['pipe', 'pipe', 'pipe'],
detached: options.detached,
windowsHide: true,
shell: false,
});
options.onSpawn?.(child);
Expand Down Expand Up @@ -248,6 +249,7 @@ export function runCmdSync(cmd: string, args: string[], options: ExecOptions = {
encoding: options.binaryStdout ? undefined : 'utf8',
input: options.stdin,
timeout: normalizeTimeoutMs(options.timeoutMs),
windowsHide: true,
shell: false,
});

Expand Down Expand Up @@ -303,6 +305,7 @@ export function runCmdDetached(
env: options.env,
stdio: options.stdio ?? 'ignore',
detached: true,
windowsHide: true,
shell: false,
});
child.unref();
Expand All @@ -320,6 +323,7 @@ export function runCmdBackground(
env: options.env,
stdio: ['ignore', 'pipe', 'pipe'],
detached: options.detached,
windowsHide: true,
shell: false,
});

Expand Down
Loading