Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tizen target list #1645

Merged
merged 10 commits into from
Aug 27, 2024
165 changes: 165 additions & 0 deletions packages/sdk-tizen/src/__tests__/deviceManager.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import {
createRnvContext,
fsExistsSync,
execCLI,
executeAsync,
logToSummary,
getContext,
logDefault,
logError,
inquirerPrompt,
ExecOptionsPresets,
} from '@rnv/core';
import { listTizenTargets, launchTizenSimulator } from '../deviceManager';
import { CLI_TIZEN_EMULATOR, CLI_SDB_TIZEN } from '../constants';

const ERROR_MSG = {
UNKNOWN_VM: 'does not match any VM',
ALREADY_RUNNING: 'is running now',
};

jest.mock('@rnv/core');

beforeEach(() => {
jest.clearAllMocks();
});

describe('listTizenTargets', () => {
it('listTizenTargets when calling npx rnv target list -p tizen', async () => {
//GIVEN
createRnvContext();
const execCLIMock = jest.mocked(execCLI);
execCLIMock
.mockImplementationOnce(() => Promise.resolve('emulatorTizen\nemulatorMobile'))
.mockImplementationOnce(() => Promise.resolve('List of devices attached\ndeviceTizen\ndeviceMobile'))
.mockImplementationOnce(() => Promise.resolve('Template: Tizen'))
.mockImplementationOnce(() => Promise.resolve('Template: Mobile'));
jest.mocked(fsExistsSync).mockReturnValueOnce(true);
//WHEN
await listTizenTargets('tizen');
//THEN

const correctResultString = 'Tizen Targets:\n[0]> emulatorTizen\n[1]> deviceTizen\n[2]> deviceMobile\n';
// right now all of the devices are added to the end, no matter if -p tizen, -p tizenwatch or -p tizenmobile was called
// when the function is updated, update the test as well, because it will fail
expect(logToSummary).toHaveBeenCalledWith(correctResultString);
});
it('listTizenTargets when calling npx rnv target list -p tizenwatch', async () => {
//GIVEN
const execCLIMock = jest.mocked(execCLI);
createRnvContext();
execCLIMock
.mockImplementationOnce(() => Promise.resolve('emulatorTizenmobile\nemulatorTizenwatch'))
.mockImplementationOnce(() => Promise.resolve('')) // the return for devices
.mockImplementationOnce(() => Promise.resolve('Template: Tizen'))
.mockImplementationOnce(() => Promise.resolve('Template: Wearable'));
jest.mocked(fsExistsSync).mockReturnValueOnce(true);
//WHEN
await listTizenTargets('tizenwatch');
//THEN

const correctResultString = 'Tizen Targets:\n[0]> emulatorTizenwatch\n';
// right now all of the devices are added to the end, no matter if -p tizen, -p tizenwatch or -p tizenmobile was called
// when the function is updated, update the test as well, because it will fail
expect(logToSummary).toHaveBeenCalledWith(correctResultString);
});
it('listTizenTargets when calling npx rnv target list -p tizenmobile', async () => {
//GIVEN
const execCLIMock = jest.mocked(execCLI);
createRnvContext();
execCLIMock
.mockImplementationOnce(() => Promise.resolve('emulatorTizenmobile\nemulatorTizenwatch'))
.mockImplementationOnce(() => Promise.resolve('')) // the return for devices
.mockImplementationOnce(() => Promise.resolve('Template: Mobile'))
.mockImplementationOnce(() => Promise.resolve('Template: Wearable'));
jest.mocked(fsExistsSync).mockReturnValueOnce(true);
//WHEN
await listTizenTargets('tizenmobile');
//THEN

const correctResultString = 'Tizen Targets:\n[0]> emulatorTizenmobile\n';
// right now all of the devices are added to the end, no matter if -p tizen, -p tizenwatch or -p tizenmobile was called
// when the function is updated, update the test as well, because it will fail
expect(logToSummary).toHaveBeenCalledWith(correctResultString);
});
});

describe('launchTizenSimulator', () => {
it('should launch the specified emulator by name', async () => {
const mockContext = { cli: { [CLI_TIZEN_EMULATOR]: 'tizen-emulator' }, platform: 'tizen' };
const ctx = { ...getContext(), ...mockContext };
createRnvContext(ctx);

(executeAsync as jest.Mock).mockResolvedValue(true);

const result = await launchTizenSimulator('emulatorName');

expect(logDefault).toHaveBeenCalledWith('launchTizenSimulator:emulatorName');
expect(executeAsync).toHaveBeenCalledWith(
'tizen-emulator launch --name emulatorName',
ExecOptionsPresets.SPINNER_FULL_ERROR_SUMMARY
);
expect(result).toBe(true);
});
it('should prompt the user to choose an emulator if name is true', async () => {
const mockContext = { cli: { [CLI_TIZEN_EMULATOR]: 'tizen-emulator' }, platform: 'tizen' };
const ctx = { ...getContext(), ...mockContext };
createRnvContext(ctx);

(execCLI as jest.Mock).mockResolvedValueOnce('emulator1\nemulator2').mockResolvedValueOnce('device1\ndevice2');
(inquirerPrompt as jest.Mock).mockResolvedValue({ chosenEmulator: 'emulator1' });
(executeAsync as jest.Mock).mockResolvedValue(true);
const result = await launchTizenSimulator(true);
expect(execCLI).toHaveBeenCalledWith(CLI_TIZEN_EMULATOR, 'list-vm');
expect(execCLI).toHaveBeenCalledWith(CLI_SDB_TIZEN, 'devices');
expect(inquirerPrompt).toHaveBeenCalledWith({
name: 'chosenEmulator',
type: 'list',
message: 'What emulator would you like to launch?',
choices: expect.any(Array),
});
expect(executeAsync).toHaveBeenCalledWith(
'tizen-emulator launch --name emulator1',
ExecOptionsPresets.SPINNER_FULL_ERROR_SUMMARY
);
expect(result).toBe(true);
});
it('should handle unknown VM error and retry with prompt', async () => {
const mockContext = { cli: { [CLI_TIZEN_EMULATOR]: 'tizen-emulator' }, platform: 'tizen' };
const ctx = { ...getContext(), ...mockContext };
createRnvContext(ctx);

(executeAsync as jest.Mock).mockRejectedValueOnce(ERROR_MSG.UNKNOWN_VM);
(execCLI as jest.Mock).mockResolvedValueOnce('emulator1\nemulator2').mockResolvedValueOnce('device1\ndevice2');
(inquirerPrompt as jest.Mock).mockResolvedValue({ chosenEmulator: 'emulator1' });
(executeAsync as jest.Mock).mockResolvedValue(true);
const result = await launchTizenSimulator('unknownEmulator');
expect(logError).toHaveBeenCalledWith('The VM "unknownEmulator" does not exist.');
expect(execCLI).toHaveBeenCalledWith(CLI_TIZEN_EMULATOR, 'list-vm');
expect(execCLI).toHaveBeenCalledWith(CLI_SDB_TIZEN, 'devices');
expect(inquirerPrompt).toHaveBeenCalledWith({
name: 'chosenEmulator',
type: 'list',
message: 'What emulator would you like to launch?',
choices: expect.any(Array),
});
expect(executeAsync).toHaveBeenCalledWith(
'tizen-emulator launch --name emulator1',
ExecOptionsPresets.SPINNER_FULL_ERROR_SUMMARY
);
expect(result).toBe(true);
});
it('should handle already running VM error and return true', async () => {
const mockContext = { cli: { [CLI_TIZEN_EMULATOR]: 'tizen-emulator' }, platform: 'tizen' };
const ctx = { ...getContext(), ...mockContext };
createRnvContext(ctx);

(executeAsync as jest.Mock).mockRejectedValueOnce(ERROR_MSG.ALREADY_RUNNING);
const result = await launchTizenSimulator('runningEmulator');
expect(logError).toHaveBeenCalledWith('The VM "runningEmulator" is already running.');
expect(result).toBe(true);
});
it('should reject if no name is specified', async () => {
await expect(launchTizenSimulator('')).rejects.toEqual('No simulator -t target name specified!');
});
});
61 changes: 52 additions & 9 deletions packages/sdk-tizen/src/deviceManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,16 @@ export const launchTizenSimulator = async (name: string | true): Promise<boolean
if (name === true) {
const emulators = await execCLI(CLI_TIZEN_EMULATOR, 'list-vm');
const devices = await execCLI(CLI_SDB_TIZEN, 'devices');
const emulators_lines = emulators.split('\n');
const devices_lines = devices.split('\n');
const lines = emulators_lines.concat(devices_lines.slice(1));

const allDownloadedEmulators = emulators.split('\n'); // all tizen, tizenwatch and tizenmobile emulators
const specificEmulators = await getSubplatformDevices(allDownloadedEmulators, c.platform as string);

const lines = specificEmulators.concat(devices_lines.slice(1));

const targetsArray = lines.map((line) => ({ id: line, name: line }));
const choices = _composeDevicesString(targetsArray);

const { chosenEmulator } = await inquirerPrompt({
name: 'chosenEmulator',
type: 'list',
Expand Down Expand Up @@ -117,16 +122,54 @@ export const launchTizenSimulator = async (name: string | true): Promise<boolean
return Promise.reject('No simulator -t target name specified!');
};

export const listTizenTargets = async () => {
const getSubplatformDevices = async (allTizenEmulators: string[], neededPlatform: string) => {
// subplatform meaning tizen, tizenwatch or tizenmobile
const specificEmulators = [];
for (let i = 0; i < allTizenEmulators.length; i++) {
try {
const detailString = await execCLI(CLI_TIZEN_EMULATOR, 'detail -n ' + allTizenEmulators[i]);
if (detailString === undefined) continue;

const detailLines = detailString // turn the command return into array
.split('\n')
.map((line: string) => line.trim())
.filter((line: string) => line !== '');

const detailObj = detailLines.reduce<{ [key: string]: string }>((acc: any, line: string) => {
// make it into a readable object
const [key, ...value] = line.split(':');
if (key && value) {
acc[key.trim()] = value.join(':').trim();
}
return acc;
}, {});

const TizenEmulatorTemplate = detailObj.Template.toLowerCase();
if (
(neededPlatform === 'tizen' &&
(TizenEmulatorTemplate.includes('tizen') || TizenEmulatorTemplate.includes('tv'))) ||
(neededPlatform === 'tizenwatch' && TizenEmulatorTemplate.includes('wearable')) ||
(neededPlatform === 'tizenmobile' && TizenEmulatorTemplate.includes('mobile'))
) {
specificEmulators.push(allTizenEmulators[i]);
}
} catch (err) {
console.log(err);
}
}
return specificEmulators;
};

export const listTizenTargets = async (platform: string) => {
const emulatorsString = await execCLI(CLI_TIZEN_EMULATOR, 'list-vm');
const devicesString = await execCLI(CLI_SDB_TIZEN, 'devices');
const emulatorArr = emulatorsString.split('\n');
// Removed first line because cli gives header ("List of devices attached") before devices list
const deviceArr = devicesString.split('\n').slice(1);
const devicesArr = devicesString.split('\n').slice(1);
const allDownloadedEmulators = emulatorsString.split('\n'); // all tizen, tizenwatch and tizenmobile emulators
const specificPlatformEmulators = await getSubplatformDevices(allDownloadedEmulators.concat(devicesArr), platform); // tizen, tizenwatch, tizenmobile - only 1 of them
let targetStr = '';
const targetArr = emulatorArr.concat(deviceArr);
targetArr.forEach((_, i) => {
targetStr += `[${i}]> ${targetArr[i]}\n`;
const finalTargetList = specificPlatformEmulators.concat(devicesArr);
finalTargetList.forEach((_, i) => {
targetStr += `[${i}]> ${finalTargetList[i]}\n`;
});
logToSummary(`Tizen Targets:\n${targetStr}`);
};
Expand Down
4 changes: 2 additions & 2 deletions packages/sdk-tizen/src/tasks/taskTargetList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import { SdkPlatforms } from '../constants';
export default createTask({
description: 'List all available targets for specific platform',
dependsOn: [RnvTaskName.workspaceConfigure],
fn: async () => {
fn: async ({ ctx }) => {
await checkAndConfigureTizenSdks();
await checkTizenSdk();
return listTizenTargets();
return listTizenTargets(ctx.platform || '');
},
task: RnvTaskName.targetList,
options: [RnvTaskOptions.target],
Expand Down
Loading