diff --git a/packages/sdk-tizen/src/__tests__/deviceManager.test.ts b/packages/sdk-tizen/src/__tests__/deviceManager.test.ts index 5ad469dfc..29573b6ac 100644 --- a/packages/sdk-tizen/src/__tests__/deviceManager.test.ts +++ b/packages/sdk-tizen/src/__tests__/deviceManager.test.ts @@ -33,15 +33,16 @@ describe('listTizenTargets', () => { .mockImplementationOnce(() => Promise.resolve('emulatorTizen\nemulatorMobile')) .mockImplementationOnce(() => Promise.resolve('List of devices attached\ndeviceTizen\ndeviceMobile')) .mockImplementationOnce(() => Promise.resolve('Template: Tizen')) - .mockImplementationOnce(() => Promise.resolve('Template: Mobile')); + .mockImplementationOnce(() => Promise.resolve('Template: Mobile')) + .mockImplementationOnce(() => Promise.resolve('profile_name:tv')) + .mockImplementationOnce(() => Promise.resolve('profile_name: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 + const correctResultString = 'Tizen targets:\n[0]> emulatorTizen\n[1]> deviceTizen\n'; expect(logToSummary).toHaveBeenCalledWith(correctResultString); }); it('listTizenTargets when calling npx rnv target list -p tizenwatch', async () => { @@ -58,9 +59,7 @@ describe('listTizenTargets', () => { 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 + const correctResultString = 'Tizen targets:\n[0]> emulatorTizenwatch\n'; expect(logToSummary).toHaveBeenCalledWith(correctResultString); }); it('listTizenTargets when calling npx rnv target list -p tizenmobile', async () => { @@ -77,9 +76,7 @@ describe('listTizenTargets', () => { 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 + const correctResultString = 'Tizen targets:\n[0]> emulatorTizenmobile\n'; expect(logToSummary).toHaveBeenCalledWith(correctResultString); }); }); @@ -102,12 +99,22 @@ describe('launchTizenTarget', () => { expect(result).toBe(true); }); it('should prompt the user to choose an emulator if name is true', async () => { + // logic - 2 emulators(tizen and mobile type), 2 devices(tv and mobile type). Since platform: 'tizen' is passed to context, its same as if npx rnv run -p tizen was called. + // so it should show only tizen/tv type emulators and devices + + // GIVEN const mockContext = { cli: { [CLI_TIZEN_EMULATOR]: 'tizen-emulator' }, platform: 'tizen' }; const ctx = { ...getContext(), ...mockContext }; createRnvContext(ctx); + (execCLI as jest.Mock) + .mockResolvedValueOnce('emulatorTizen\nemulatorMobile') + .mockResolvedValueOnce('List of devices attached\n111.111.111:11111\n222.222.222:22222') + .mockResolvedValueOnce('Template: Tizen') + .mockResolvedValueOnce('Template: Mobile') + .mockResolvedValueOnce('profile_name:tv') + .mockResolvedValueOnce('profile_name:mobile'); - (execCLI as jest.Mock).mockResolvedValueOnce('emulator1\nemulator2').mockResolvedValueOnce('device1\ndevice2'); - (inquirerPrompt as jest.Mock).mockResolvedValue({ chosenEmulator: 'emulator1' }); + (inquirerPrompt as jest.Mock).mockResolvedValue({ chosenEmulator: 'emulatorTizen' }); (executeAsync as jest.Mock).mockResolvedValue(true); const result = await launchTizenTarget(true); expect(execCLI).toHaveBeenCalledWith(CLI_TIZEN_EMULATOR, 'list-vm'); @@ -116,64 +123,104 @@ describe('launchTizenTarget', () => { name: 'chosenEmulator', type: 'list', message: 'which emulator or device would you like to launch?', - choices: expect.any(Array), + choices: [ + { + key: 'emulatorTizen', + name: 'emulatorTizen', + value: 'emulatorTizen', + }, + { + key: '111.111.111:11111', + name: '111.111.111:11111', + value: '111.111.111:11111', + }, + ], }); expect(executeAsync).toHaveBeenCalledWith( - 'tizen-emulator launch --name emulator1', + 'tizen-emulator launch --name emulatorTizen', ExecOptionsPresets.SPINNER_FULL_ERROR_SUMMARY ); expect(result).toBe(true); }); - it('should hide real devices from prompt, if true is passed', async () => { + it('should hide real devices from prompt, if the second paramater of launchTizenTarget() 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('emulatorTizen\nemulatorMobile') .mockResolvedValueOnce( - 'firstTrashLineThatTizenDeviceCmdReturns\n111.111.0.111:26101 device UE43NU7192' - ); - (inquirerPrompt as jest.Mock).mockResolvedValue({ chosenEmulator: 'emulator1' }); + 'firstTrashLineThatTizenDeviceCmdReturns\n111.111.111.111:11111 device UE43NU7192' + ) + .mockResolvedValueOnce('Template: Tizen') + .mockResolvedValueOnce('Template: Mobile') + .mockResolvedValueOnce('profile_name:tv'); + + (inquirerPrompt as jest.Mock).mockResolvedValue({ chosenEmulator: 'emulatorTizen' }); (executeAsync as jest.Mock).mockResolvedValue(true); const result = await launchTizenTarget(true, true); expect(inquirerPrompt).toHaveBeenCalledWith({ name: 'chosenEmulator', type: 'list', - message: 'which emulator or device would you like to launch?', - choices: [], // not correct, because emulators are not mocked, but doesn't matter here, since its testing devices + message: 'which emulator would you like to launch?', + choices: [ + { + key: 'emulatorTizen', + name: 'emulatorTizen', + value: 'emulatorTizen', + }, + ], // there is a tizen emulator, and a tizen device(because of the profile_name:tv mock value return), but since hideDevices(2nd param) is true, only the emulator should be shown }); expect(result).toBe(true); }); it('should show real devices(same conditions as test above, just not passing 2nd param true to launchTizenTarget) ', async () => { + //GIVEN const mockContext = { cli: { [CLI_TIZEN_EMULATOR]: 'tizen-emulator' }, platform: 'tizen' }; const ctx = { ...getContext(), ...mockContext }; createRnvContext(ctx); (execCLI as jest.Mock) - .mockResolvedValueOnce('emulator1\nemulator2') + .mockResolvedValueOnce('emulatorTizen\nemulatorMobile') .mockResolvedValueOnce( - 'firstTrashLineThatTizenDeviceCmdReturns\n111.111.0.111:26101 device UE43NU7192' - ); + 'firstTrashLineThatTizenDeviceCmdReturns\n111.111.111.111:11111 device UE43NU7192' + ) + .mockResolvedValueOnce('Template: Tizen') + .mockResolvedValueOnce('Template: Mobile') + .mockResolvedValueOnce('profile_name:tv'); + (inquirerPrompt as jest.Mock).mockResolvedValue({ chosenEmulator: 'emulator1' }); (executeAsync as jest.Mock).mockResolvedValue(true); + //WHEN const result = await launchTizenTarget(true); + + //THEN expect(inquirerPrompt).toHaveBeenCalledWith({ name: 'chosenEmulator', type: 'list', message: 'which emulator or device would you like to launch?', - choices: [{ key: '111.111.0.111:26101', name: '111.111.0.111:26101', value: '111.111.0.111:26101' }], + choices: [ + { key: 'emulatorTizen', name: 'emulatorTizen', value: 'emulatorTizen' }, + { key: '111.111.111.111:11111', name: '111.111.111.111:11111', value: '111.111.111.111:11111' }, + ], }); expect(result).toBe(true); }); it('should handle unknown VM error and retry with prompt', async () => { + //GIVEN 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' }); + (execCLI as jest.Mock) + .mockResolvedValueOnce('emulatorTizen\nemulatorMobile') + .mockResolvedValueOnce( + 'firstTrashLineThatTizenDeviceCmdReturns\n111.111.111.111:11111 device UE43NU7192' + ) + .mockResolvedValueOnce('Template: Tizen') + .mockResolvedValueOnce('Template: Mobile') + .mockResolvedValueOnce('profile_name:tv'); + (inquirerPrompt as jest.Mock).mockResolvedValue({ chosenEmulator: 'emulatorTizen' }); (executeAsync as jest.Mock).mockResolvedValue(true); const result = await launchTizenTarget('unknownEmulator'); expect(logError).toHaveBeenCalledWith('The VM/device "unknownEmulator" does not exist.'); @@ -183,10 +230,21 @@ describe('launchTizenTarget', () => { name: 'chosenEmulator', type: 'list', message: 'which emulator or device would you like to launch?', - choices: expect.any(Array), + choices: [ + { + key: 'emulatorTizen', + name: 'emulatorTizen', + value: 'emulatorTizen', + }, + { + key: '111.111.111.111:11111', + name: '111.111.111.111:11111', + value: '111.111.111.111:11111', + }, + ], }); expect(executeAsync).toHaveBeenCalledWith( - 'tizen-emulator launch --name emulator1', + 'tizen-emulator launch --name emulatorTizen', ExecOptionsPresets.SPINNER_FULL_ERROR_SUMMARY ); expect(result).toBe(true); diff --git a/packages/sdk-tizen/src/deviceManager.ts b/packages/sdk-tizen/src/deviceManager.ts index aab807ae6..5d1e8061e 100644 --- a/packages/sdk-tizen/src/deviceManager.ts +++ b/packages/sdk-tizen/src/deviceManager.ts @@ -79,23 +79,30 @@ export const launchTizenTarget = async (name: string | true, hideDevices?: boole const emulators = await execCLI(CLI_TIZEN_EMULATOR, 'list-vm'); const devices = await execCLI(CLI_SDB_TIZEN, 'devices'); const devices_lines = devices.split('\n'); + const devicesArr = devices_lines.slice(1).map((line: string) => line.split(' ')[0]); // devices array with only their ip const allDownloadedEmulators = emulators.split('\n'); // all tizen, tizenwatch and tizenmobile emulators - const specificEmulators = await getSubplatformDevices(allDownloadedEmulators, c.platform as string); - const devicesArr = devices_lines.slice(1).map((line: string) => line.split(' ')[0]); // devices array with only their ip - const lines = specificEmulators.concat(devicesArr); + const specificEmulators = await getEmulatorType(allDownloadedEmulators, c.platform as string); + const specificDevices = await getDeviceType(devicesArr, c.platform as string); + + const lines = specificEmulators.concat(specificDevices); const targetsArray = hideDevices ? specificEmulators.map((line) => ({ id: line, name: line })) : lines.map((line) => ({ id: line, name: line })); const choices = _composeDevicesString(targetsArray); - + if (!choices.length) { + logError(`No devices found for platform ${c.platform}`); + return Promise.reject('No devices found'); + } const { chosenEmulator } = await inquirerPrompt({ name: 'chosenEmulator', type: 'list', - message: 'which emulator or device would you like to launch?', + message: hideDevices + ? 'which emulator would you like to launch?' + : 'which emulator or device would you like to launch?', choices, }); @@ -136,12 +143,13 @@ export const launchTizenTarget = async (name: string | true, hideDevices?: boole return Promise.reject('No emulator -t target name specified!'); }; -const getSubplatformDevices = async (allTizenEmulators: string[], neededPlatform: string) => { +const getEmulatorType = 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 @@ -174,6 +182,31 @@ const getSubplatformDevices = async (allTizenEmulators: string[], neededPlatform return specificEmulators; }; +const getDeviceType = async (ipArr: string[], neededPlatform: string) => { + const returnArr = []; + + for (let i = 0; i < ipArr.length; i++) { + try { + const capabilityString = await execCLI(CLI_SDB_TIZEN, `-s ${ipArr[i]} capability`); + if ( + capabilityString.includes('profile_name:tv') && + (neededPlatform === 'tizen' || neededPlatform === 'tv') + ) { + returnArr.push(ipArr[i]); + } + if (capabilityString.includes('profile_name:wearable') && neededPlatform === 'tizenwatch') { + returnArr.push(ipArr[i]); + } + if (capabilityString.includes('profile_name:mobile') && neededPlatform === 'tizenmobile') { + returnArr.push(ipArr[i]); + } + } catch (err) { + logError(`Couldn't connect to ${ipArr[i]} device.`); + } + } + return returnArr; +}; + export const listTizenTargets = async (platform: string) => { const emulatorsString = await execCLI(CLI_TIZEN_EMULATOR, 'list-vm'); const devicesString = await execCLI(CLI_SDB_TIZEN, 'devices'); @@ -184,13 +217,19 @@ export const listTizenTargets = async (platform: string) => { // turns devices string: ' List of devices attached \n192.168.0.105:26101 device UE43NU7192' to only the '192.168.0.105:26101' 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 + const specificEmulators = await getEmulatorType(allDownloadedEmulators, platform); // tizen, tizenwatch, tizenmobile - only 1 of them + const specificDevices = await getDeviceType(devicesArr, platform); // tv, wearable, mobile + let targetStr = ''; - const finalTargetList = specificPlatformEmulators.concat(devicesArr); + const finalTargetList = specificEmulators.concat(specificDevices); finalTargetList.forEach((_, i) => { targetStr += `[${i}]> ${finalTargetList[i]}\n`; }); - logToSummary(`Tizen Targets:\n${targetStr}`); + if (!targetStr) { + logToSummary(`No targets for ${platform} found.`); + } else { + logToSummary(`Tizen targets:\n${targetStr}`); + } }; export const createDevelopTizenCertificate = (c: RnvContext) =>