/**
* Unit tests for environment tools
* Tests manage_env, clean_project, and list_devices
*/
import { describe, it, expect, vi, beforeEach } from 'vitest';
import {
Device,
DeviceStatus,
CleanResult,
EnvironmentResult,
fromAndroidDevice,
fromIOSDevice,
filterDevicesByStatus,
findDevice,
getBootedDevice,
createDeviceSummary,
} from '../../../src/models/device.js';
// Mock shell execution
vi.mock('../../../src/utils/shell.js', () => ({
executeShell: vi.fn(),
executeShellOrThrow: vi.fn(),
}));
describe('Device Models', () => {
describe('fromAndroidDevice', () => {
it('should convert Android device to unified format', () => {
const android = {
id: 'emulator-5554',
name: 'Pixel_6_API_33',
status: 'device',
model: 'sdk_gphone64_x86_64',
type: 'emulator',
};
const device = fromAndroidDevice(android);
expect(device.id).toBe('emulator-5554');
expect(device.name).toBe('Pixel_6_API_33');
expect(device.platform).toBe('android');
expect(device.type).toBe('emulator');
expect(device.status).toBe('booted');
expect(device.model).toBe('sdk_gphone64_x86_64');
});
it('should handle physical device', () => {
const android = {
id: 'R5CT12345',
name: 'Samsung Galaxy S23',
status: 'device',
type: 'physical',
};
const device = fromAndroidDevice(android);
expect(device.type).toBe('physical');
expect(device.status).toBe('booted');
});
it('should map offline status to shutdown', () => {
const android = {
id: 'emulator-5554',
name: 'Pixel_6_API_33',
status: 'offline',
};
const device = fromAndroidDevice(android);
expect(device.status).toBe('shutdown');
});
});
describe('fromIOSDevice', () => {
it('should convert iOS device to unified format', () => {
const ios = {
id: 'ABCD1234-5678-90EF-GHIJ-KLMNOPQRSTUV',
name: 'iPhone 15 Pro',
status: 'Booted',
runtime: 'com.apple.CoreSimulator.SimRuntime.iOS-17-0',
isAvailable: true,
};
const device = fromIOSDevice(ios);
expect(device.id).toBe('ABCD1234-5678-90EF-GHIJ-KLMNOPQRSTUV');
expect(device.name).toBe('iPhone 15 Pro');
expect(device.platform).toBe('ios');
expect(device.type).toBe('simulator');
expect(device.status).toBe('booted');
expect(device.osVersion).toBe('17.0');
});
it('should parse iOS version with patch number', () => {
const ios = {
id: 'UUID-123',
name: 'iPad Pro',
status: 'Shutdown',
runtime: 'com.apple.CoreSimulator.SimRuntime.iOS-16-4-1',
};
const device = fromIOSDevice(ios);
expect(device.osVersion).toBe('16.4.1');
expect(device.status).toBe('shutdown');
});
});
describe('filterDevicesByStatus', () => {
const devices: Device[] = [
{ id: '1', name: 'Device 1', platform: 'android', type: 'emulator', status: 'booted' },
{ id: '2', name: 'Device 2', platform: 'android', type: 'emulator', status: 'shutdown' },
{ id: '3', name: 'Device 3', platform: 'ios', type: 'simulator', status: 'booted' },
{ id: '4', name: 'Device 4', platform: 'ios', type: 'simulator', status: 'shutdown' },
];
it('should filter booted devices', () => {
const booted = filterDevicesByStatus(devices, 'booted');
expect(booted).toHaveLength(2);
expect(booted.every((d) => d.status === 'booted')).toBe(true);
});
it('should filter shutdown devices', () => {
const shutdown = filterDevicesByStatus(devices, 'shutdown');
expect(shutdown).toHaveLength(2);
expect(shutdown.every((d) => d.status === 'shutdown')).toBe(true);
});
});
describe('findDevice', () => {
const devices: Device[] = [
{ id: 'emulator-5554', name: 'Pixel 6 API 33', platform: 'android', type: 'emulator', status: 'booted' },
{ id: 'UUID-iPhone15', name: 'iPhone 15 Pro', platform: 'ios', type: 'simulator', status: 'booted' },
];
it('should find device by exact ID', () => {
const device = findDevice(devices, 'emulator-5554');
expect(device?.name).toBe('Pixel 6 API 33');
});
it('should find device by exact name', () => {
const device = findDevice(devices, 'iPhone 15 Pro');
expect(device?.id).toBe('UUID-iPhone15');
});
it('should find device by partial name (case insensitive)', () => {
const device = findDevice(devices, 'pixel');
expect(device?.id).toBe('emulator-5554');
});
it('should return undefined for non-existent device', () => {
const device = findDevice(devices, 'NonExistent');
expect(device).toBeUndefined();
});
});
describe('getBootedDevice', () => {
const devices: Device[] = [
{ id: '1', name: 'Android Booted', platform: 'android', type: 'emulator', status: 'booted' },
{ id: '2', name: 'Android Shutdown', platform: 'android', type: 'emulator', status: 'shutdown' },
{ id: '3', name: 'iOS Booted', platform: 'ios', type: 'simulator', status: 'booted' },
];
it('should get first booted device', () => {
const device = getBootedDevice(devices);
expect(device?.status).toBe('booted');
});
it('should get first booted device for specific platform', () => {
const device = getBootedDevice(devices, 'ios');
expect(device?.name).toBe('iOS Booted');
});
it('should return undefined if no booted device for platform', () => {
const shutdownDevices: Device[] = [
{ id: '1', name: 'Shutdown', platform: 'android', type: 'emulator', status: 'shutdown' },
];
const device = getBootedDevice(shutdownDevices, 'android');
expect(device).toBeUndefined();
});
});
describe('createDeviceSummary', () => {
it('should create summary for empty device list', () => {
const summary = createDeviceSummary([]);
expect(summary).toBe('No devices found');
});
it('should create summary with device counts', () => {
const devices: Device[] = [
{ id: '1', name: 'Pixel 6', platform: 'android', type: 'emulator', status: 'booted' },
{ id: '2', name: 'Pixel 7', platform: 'android', type: 'emulator', status: 'shutdown' },
{ id: '3', name: 'iPhone 15', platform: 'ios', type: 'simulator', status: 'booted' },
];
const summary = createDeviceSummary(devices);
expect(summary).toContain('Total: 3 devices');
expect(summary).toContain('Android: 2 (1 running)');
expect(summary).toContain('iOS: 1 (1 running)');
expect(summary).toContain('Pixel 6');
expect(summary).toContain('iPhone 15');
});
});
});
describe('manage_env tool', () => {
describe('boot action', () => {
it('should validate platform argument', async () => {
// Placeholder - will be tested with actual handler
expect(true).toBe(true);
});
it('should boot Android emulator', async () => {
expect(true).toBe(true);
});
it('should boot iOS simulator', async () => {
expect(true).toBe(true);
});
});
describe('shutdown action', () => {
it('should shutdown running device', async () => {
expect(true).toBe(true);
});
it('should handle already shutdown device', async () => {
expect(true).toBe(true);
});
});
describe('restart action', () => {
it('should restart running device', async () => {
expect(true).toBe(true);
});
});
});
describe('clean_project tool', () => {
describe('Gradle clean', () => {
it('should run gradlew clean', async () => {
expect(true).toBe(true);
});
it('should clean specific module', async () => {
expect(true).toBe(true);
});
});
describe('Xcode clean', () => {
it('should clean DerivedData', async () => {
expect(true).toBe(true);
});
});
describe('combined clean', () => {
it('should clean multiple targets', async () => {
expect(true).toBe(true);
});
it('should report partial failures', async () => {
expect(true).toBe(true);
});
});
});
describe('list_devices tool', () => {
describe('Android devices', () => {
it('should list connected Android devices', async () => {
expect(true).toBe(true);
});
it('should list available AVDs', async () => {
expect(true).toBe(true);
});
});
describe('iOS devices', () => {
it('should list iOS simulators', async () => {
expect(true).toBe(true);
});
it('should filter by runtime', async () => {
expect(true).toBe(true);
});
});
describe('all platforms', () => {
it('should list devices from both platforms', async () => {
expect(true).toBe(true);
});
it('should filter by status', async () => {
expect(true).toBe(true);
});
});
});