diff --git a/src/commands/android/constants.ts b/src/commands/android/constants.ts index 513b174..761c04f 100644 --- a/src/commands/android/constants.ts +++ b/src/commands/android/constants.ts @@ -24,6 +24,14 @@ export const AVAILABLE_OPTIONS: AvailableOptions = { appium: { alias: [], description: 'Make sure the final setup works with Appium out-of-the-box.' + }, + standalone: { + alias: [], + description: 'Do standalone setup for Android Emulator (no Nightwatch-related requirements will be downloaded).' + }, + wireless: { + alias: [], + description: 'Connect ADB with wireless connection.' } }; diff --git a/src/commands/android/index.ts b/src/commands/android/index.ts index f1d5327..23d3e21 100644 --- a/src/commands/android/index.ts +++ b/src/commands/android/index.ts @@ -26,6 +26,7 @@ import { } from './utils/sdk'; import DOWNLOADS from './downloads.json'; +import {connectAdbWirelessly} from './utils/adbWirelessConnect'; export class AndroidSetup { @@ -107,6 +108,12 @@ export class AndroidSetup { this.sdkRoot = sdkRootEnv || await this.getSdkRootFromUser(); process.env.ANDROID_HOME = this.sdkRoot; + if (this.options.wireless) { + const adbLocation = getBinaryLocation(this.sdkRoot, this.platform, 'adb', true); + + return await connectAdbWirelessly(adbLocation, this.platform); + } + let result = true; const setupConfigs: SetupConfigs = await this.getSetupConfigs(this.options); @@ -415,6 +422,18 @@ export class AndroidSetup { } } + // For standalone mode, don't ask the browser question (set `configs.browsers` to 'none'). + // But if a user explicitly provides a browser using the `--browsers` flag, use it. + if (options.standalone && !configs.browsers) { + configs.browsers = 'none'; + + // if just the `--browsers` flag is passed with no argument, + // ask the browser question even in the case of standalone. + if (options.browsers === true) { + delete configs.browsers; + } + } + return configs; } @@ -858,12 +877,14 @@ export class AndroidSetup { // TODO: add major version of Chrome as suffix to chromedriver. // Or, check the version of existing chromedriver using --version. - Logger.log('Checking if chromedriver is already downloaded...'); - if (fs.existsSync(chromedriverDownloadPath)) { - Logger.log(` ${colors.green(symbols().ok)} chromedriver already present at '${chromedriverDownloadPath}'\n`); - } else { - Logger.log(` ${colors.red(symbols().fail)} chromedriver not found at '${chromedriverDownloadPath}'\n`); - downloadChromedriver = true; + if (!this.options.standalone) { + Logger.log('Checking if chromedriver is already downloaded...'); + if (fs.existsSync(chromedriverDownloadPath)) { + Logger.log(` ${colors.green(symbols().ok)} chromedriver already present at '${chromedriverDownloadPath}'\n`); + } else { + Logger.log(` ${colors.red(symbols().fail)} chromedriver not found at '${chromedriverDownloadPath}'\n`); + downloadChromedriver = true; + } } } else if (stdout !== null) { Logger.log(` ${colors.red(symbols().fail)} Chrome browser not found in the AVD.\n`); diff --git a/src/commands/android/utils/adbWirelessConnect.ts b/src/commands/android/utils/adbWirelessConnect.ts new file mode 100644 index 0000000..e680e8c --- /dev/null +++ b/src/commands/android/utils/adbWirelessConnect.ts @@ -0,0 +1,72 @@ +import {Platform} from '../interfaces'; +import {execBinarySync} from './sdk'; +import Logger from '../../../logger'; +import inquirer from 'inquirer'; +import colors from 'ansi-colors'; + +export async function connectAdbWirelessly(adbLocation: string, platform: Platform): Promise { + try { + + Logger.log(`${colors.bold('Follow the below steps to connect to your device wirelessly:\n')} + 1.Connect your device to the same network as your computer ${colors.grey('(you may connect your device to your computer\'s hotspot)')}. + 2.Enable wireless debugging on your device. + 3.Find the IP address and port number of your device by going to: + ${colors.cyan('Settings > Wireless Debugging')} + ${colors.grey('IP address and port number are separated by \':\' in the format \n '+ + 'where IP address comes before \':\' and port number comes after \':\'')}\n`); + + const deviceIPAnswer = await inquirer.prompt({ + type: 'input', + name: 'deviceIP', + message: 'Enter the IP address of your device:' + }); + const deviceIP = deviceIPAnswer.deviceIP; + + const portAnswer = await inquirer.prompt({ + type: 'input', + name: 'port', + message: 'Enter the port number:' + }); + const port = portAnswer.port; + + Logger.log(`\n 4.Now find your device's pairing code and pairing port number by going to: + ${colors.cyan('Settings > Wireless Debugging > Pair device with pairing code')} + ${colors.grey('Here you will find the pairing code and an IP address with a port number.\n '+ + 'The port number associated with this IP address is the requird pairing port number.')}\n`); + + const pairingCodeAnswer = await inquirer.prompt({ + type: 'input', + name: 'pairingCode', + message: 'Enter the pairing code displayed on your device:' + }); + const pairingCode = pairingCodeAnswer.pairingCode; + + const pairingPortAnswer = await inquirer.prompt({ + type: 'input', + name: 'pairingPort', + message: 'Enter the pairing port number displayed on your device:' + }); + const pairingPort = pairingPortAnswer.pairingPort; + + Logger.log('\nPairing your device with your computer...\n'); + + const pairing = execBinarySync(adbLocation, 'adb', platform, `pair ${deviceIP}:${pairingPort} ${pairingCode}`); + if (pairing) { + Logger.log(`${colors.green('\nPairing successful!')} Now connecting to device wirelessly...`); + } else { + Logger.log(`${colors.red('\nPairing failed!')} Please try again.`); + + return false; + } + + execBinarySync(adbLocation, 'adb', platform, `connect ${deviceIP}:${port}`); + Logger.log(colors.green('\nConnected to device wirelessly.')); + + return true; + } catch (error) { + Logger.log('Error connecting to wifi ADB'); + console.error('Error:', error); + + return false; + } +} diff --git a/src/index.ts b/src/index.ts index c15ec74..ff5abd7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,7 +9,7 @@ export const run = () => { try { const argv = process.argv.slice(2); const {_: args, ...options} = minimist(argv, { - boolean: ['install', 'setup', 'help', 'appium'], + boolean: ['install', 'setup', 'help', 'appium', 'standalone', 'wireless'], alias: { help: 'h', mode: 'm', diff --git a/tests/unit_tests/commands/android/testIndex.js b/tests/unit_tests/commands/android/testIndex.js index 55cbdc6..d72adbf 100644 --- a/tests/unit_tests/commands/android/testIndex.js +++ b/tests/unit_tests/commands/android/testIndex.js @@ -440,6 +440,25 @@ describe('test getConfigFromOptions', function() { configs = androidSetup.getConfigFromOptions({mode: true, browsers: []}); assert.deepStrictEqual(configs, {}); + + configs = androidSetup.getConfigFromOptions({standalone: true}); + assert.deepStrictEqual(configs, {browsers: 'none'}); + + configs = androidSetup.getConfigFromOptions({standalone: true, browsers: false}); + assert.deepStrictEqual(configs, {browsers: 'none'}); + + // if just `--browsers` option is passed with no argument, ask the browsers question. + configs = androidSetup.getConfigFromOptions({standalone: true, browsers: true}); + assert.deepStrictEqual(configs, {}); + + configs = androidSetup.getConfigFromOptions({standalone: true, browsers: 'chrome'}); + assert.deepStrictEqual(configs, {browsers: 'chrome'}); + + configs = androidSetup.getConfigFromOptions({standalone: true, browsers: 'chrome,firefox'}); + assert.deepStrictEqual(configs, {browsers: 'both'}); + + configs = androidSetup.getConfigFromOptions({standalone: true, browsers: 'brave'}); + assert.deepStrictEqual(configs, {browsers: 'none'}); }); });