diff --git a/detox/src/devices/allocation/drivers/android/genycloud/exec/GenyCloudExec.js b/detox/src/devices/allocation/drivers/android/genycloud/exec/GenyCloudExec.js index 3a13ad91e3..85f9895586 100644 --- a/detox/src/devices/allocation/drivers/android/genycloud/exec/GenyCloudExec.js +++ b/detox/src/devices/allocation/drivers/android/genycloud/exec/GenyCloudExec.js @@ -1,8 +1,6 @@ // @ts-nocheck const exec = require('../../../../../../utils/childProcess').execWithRetriesAndLogs; -const defaultFlags = '--format compactjson'; - class GenyCloudExec { constructor(binaryPath) { this.binaryExec = binaryPath; @@ -14,7 +12,7 @@ class GenyCloudExec { } doctor() { - return this._exec('doctor', { retries: 0 }, '--format text'); + return this._exec('doctor', { retries: 0 }, 'text'); } getRecipe(name) { @@ -44,23 +42,25 @@ class GenyCloudExec { return this._exec(`instances stop ${instanceUUID}`, options); } - async _exec(args, options, flags = defaultFlags) { + async _exec(args, options, format = 'compactjson') { try { - const rawResult = await this.__exec(flags, args, options); - return JSON.parse(rawResult); + const rawResult = await this.__exec(args, options, format); + return ( + format === 'compactjson' ? JSON.parse(rawResult) : rawResult + ); } catch (error) { throw new Error(error.stderr); } } - async __exec(flags, args, _options) { - const options = { - ..._options, + async __exec(args, options, format) { + const _options = { + ...options, statusLogs: { retrying: true, }, }; - return (await exec(`"${this.binaryExec}" ${flags} ${args}`, options )).stdout; + return (await exec(`"${this.binaryExec}" --format ${format} ${args}`, _options )).stdout; } } diff --git a/detox/src/devices/allocation/drivers/android/genycloud/exec/GenyCloudExec.test.js b/detox/src/devices/allocation/drivers/android/genycloud/exec/GenyCloudExec.test.js index 37eadefee4..80c9595476 100644 --- a/detox/src/devices/allocation/drivers/android/genycloud/exec/GenyCloudExec.test.js +++ b/detox/src/devices/allocation/drivers/android/genycloud/exec/GenyCloudExec.test.js @@ -19,12 +19,18 @@ describe('Genymotion-cloud executable', () => { const instanceUUID = 'mock-uuid'; const instanceName = 'detox-instance1'; - const givenSuccessResult = () => exec.mockResolvedValue({ + const givenSuccessJSONResult = () => exec.mockResolvedValue({ stdout: JSON.stringify(successResponse), }); - const givenErrorResult = () => exec.mockRejectedValue({ + const givenSuccessTextResult = () => exec.mockResolvedValue({ + stdout: successResponse, + }); + const givenErrorJSONResult = () => exec.mockRejectedValue({ stderr: JSON.stringify(failResponse), }); + const givenErrorResult = (errorMessage) => exec.mockRejectedValue({ + stderr: errorMessage, + }); let exec; let uut; @@ -40,44 +46,82 @@ describe('Genymotion-cloud executable', () => { delete process.env.GMSAAS_USER_AGENT_EXTRA_DATA; }); - describe.each([ - ['version', () => uut.getVersion(), `"mock/path/to/gmsaas" --format compactjson --version`], - ['Doctor', () => uut.doctor(), `"mock/path/to/gmsaas" --format text doctor`, { retries: 0 }], - ['Get Recipe', () => uut.getRecipe(recipeName), `"mock/path/to/gmsaas" --format compactjson recipes list --name "${recipeName}"`], - ['Get Instance', () => uut.getInstance(instanceUUID), `"mock/path/to/gmsaas" --format compactjson instances get ${instanceUUID}`], - ['Get Instances', () => uut.getInstances(), `"mock/path/to/gmsaas" --format compactjson instances list -q`], - ['Start Instance', () => uut.startInstance(recipeUUID, instanceName), `"mock/path/to/gmsaas" --format compactjson instances start --no-wait ${recipeUUID} "${instanceName}"`, { retries: 0 }], - ['ADB Connect', () => uut.adbConnect(instanceUUID), `"mock/path/to/gmsaas" --format compactjson instances adbconnect ${instanceUUID}`, { retries: 0 }], - ['Stop Instance', () => uut.stopInstance(instanceUUID), `"mock/path/to/gmsaas" --format compactjson instances stop ${instanceUUID}`, { retries: 3 }], - ])(`%s command`, (commandName, commandExecFn, expectedExec, expectedExecOptions) => { - it('should execute command by name', async () => { - givenSuccessResult(); - - const expectedOptions = { - ...expectedExecOptions, - statusLogs: { - retrying: true, - } - }; - - await commandExecFn(); - expect(exec).toHaveBeenCalledWith( - expectedExec, - expectedOptions, - ); + describe('JSON command', () => { + describe.each([ + ['version', () => uut.getVersion(), `"mock/path/to/gmsaas" --format compactjson --version`], + ['Get Recipe', () => uut.getRecipe(recipeName), `"mock/path/to/gmsaas" --format compactjson recipes list --name "${recipeName}"`], + ['Get Instance', () => uut.getInstance(instanceUUID), `"mock/path/to/gmsaas" --format compactjson instances get ${instanceUUID}`], + ['Get Instances', () => uut.getInstances(), `"mock/path/to/gmsaas" --format compactjson instances list -q`], + ['Start Instance', () => uut.startInstance(recipeUUID, instanceName), `"mock/path/to/gmsaas" --format compactjson instances start --no-wait ${recipeUUID} "${instanceName}"`, { retries: 0 }], + ['ADB Connect', () => uut.adbConnect(instanceUUID), `"mock/path/to/gmsaas" --format compactjson instances adbconnect ${instanceUUID}`, { retries: 0 }], + ['Stop Instance', () => uut.stopInstance(instanceUUID), `"mock/path/to/gmsaas" --format compactjson instances stop ${instanceUUID}`, { retries: 3 }], + ])(`%s`, (commandName, commandExecFn, expectedExec, expectedExecOptions) => { + it('should execute command by name', async () => { + givenSuccessJSONResult(); + + const expectedOptions = { + ...expectedExecOptions, + statusLogs: { + retrying: true, + } + }; + + await commandExecFn(); + expect(exec).toHaveBeenCalledWith( + expectedExec, + expectedOptions, + ); + }); + + it('should return the result', async () => { + givenSuccessJSONResult(); + + const result = await commandExecFn(); + expect(result).toEqual(successResponse); + }); + + it('should fail upon an error result', async () => { + givenErrorJSONResult(); + + await expect(commandExecFn()).rejects.toThrowError(JSON.stringify(failResponse)); + }); }); + }); - it('should return the result', async () => { - givenSuccessResult(); - - const result = await commandExecFn(); - expect(result).toEqual(successResponse); - }); - - it('should fail upon an error result', async () => { - givenErrorResult(); - - await expect(commandExecFn()).rejects.toThrowError(JSON.stringify(failResponse)); + describe('Text command', () => { + describe.each([ + ['Doctor', () => uut.doctor(), `"mock/path/to/gmsaas" --format text doctor`, { retries: 0 }], + ])(`%s`, (commandName, commandExecFn, expectedExec, expectedExecOptions) => { + it('should execute command by name', async () => { + givenSuccessTextResult(); + + const expectedOptions = { + ...expectedExecOptions, + statusLogs: { + retrying: true, + } + }; + + await commandExecFn(); + expect(exec).toHaveBeenCalledWith( + expectedExec, + expectedOptions, + ); + }); + + it('should return the result', async () => { + givenSuccessTextResult(); + + const result = await commandExecFn(); + expect(result).toEqual(successResponse); + }); + + it('should fail upon an error result', async () => { + const errorMessage = 'Oh no, mocked error has occurred!'; + givenErrorResult(errorMessage); + + await expect(commandExecFn()).rejects.toThrowError(errorMessage); + }); }); });