diff --git a/bin/start-session b/bin/start-session new file mode 100755 index 0000000..f00a36a --- /dev/null +++ b/bin/start-session @@ -0,0 +1,4 @@ +#!/usr/bin/env node + +"use strict"; +require("../lib/helpers/start-session.js"); \ No newline at end of file diff --git a/bin/start-session.cmd b/bin/start-session.cmd new file mode 100644 index 0000000..6d70619 --- /dev/null +++ b/bin/start-session.cmd @@ -0,0 +1 @@ +@node %~dp0\start-session %* \ No newline at end of file diff --git a/lib/appium-driver.d.ts b/lib/appium-driver.d.ts index cdd3d95..0d76742 100644 --- a/lib/appium-driver.d.ts +++ b/lib/appium-driver.d.ts @@ -85,7 +85,13 @@ export declare class AppiumDriver { * @param text * @param waitForElement */ - findElementByAutomationText(automationText: string, waitForElement?: number): Promise; + findElementByAutomationText(automationText: string, waitForElement?: number): Promise; + /** + * Search for element by given automationText. Searches only for exact string. + * @param text + * @param waitForElement + */ + findElementByAutomationTextIfExists(automationText: string, waitForElement?: number): Promise; /** * Search for element by given automationText and waits until the element is displayed. * @param text diff --git a/lib/appium-driver.ts b/lib/appium-driver.ts index e2d7c7b..3032e18 100644 --- a/lib/appium-driver.ts +++ b/lib/appium-driver.ts @@ -320,6 +320,18 @@ export class AppiumDriver { * @param waitForElement */ public async findElementByAutomationText(automationText: string, waitForElement: number = this.defaultWaitTime) { + if (this.isIOS) { + return await this.findElementByAccessibilityId(`${automationText}`, waitForElement); + } + return await this.findElementByXPath(this._elementHelper.getXPathByText(automationText, true), waitForElement); + } + + /** + * Search for element by given automationText. Searches only for exact string. + * @param text + * @param waitForElement + */ + public async findElementByAutomationTextIfExists(automationText: string, waitForElement: number = this.defaultWaitTime) { if (this.isIOS) { return await this.findElementByAccessibilityIdIfExists(`${automationText}`, waitForElement); } @@ -334,12 +346,12 @@ export class AppiumDriver { public async waitForElement(automationText: string, waitInMilliseconds: number = this.defaultWaitTime): Promise { let element; try { - element = await this.findElementByAutomationText(automationText, 100); + element = await this.findElementByAutomationTextIfExists(automationText, 100); } catch (error) { } const startTime = Date.now(); while ((!element || !(await element.isDisplayed())) && Date.now() - startTime <= waitInMilliseconds) { try { - element = await this.findElementByAutomationText(automationText, 100); + element = await this.findElementByAutomationTextIfExists(automationText, 100); } catch (error) { } } @@ -730,7 +742,7 @@ export class AppiumDriver { * @param time in minutes */ public async backgroundApp(minutes: number) { - console.log("Sending the currently active app to the background ..."); + logInfo("Sending the currently active app to the background ..."); await this._driver.backgroundApp(minutes); } @@ -756,20 +768,23 @@ export class AppiumDriver { } public async quit() { - console.log("Killing driver"); if (this._recordVideoInfo && this._recordVideoInfo['videoRecordingProcess']) { this._recordVideoInfo['videoRecordingProcess'].kill("SIGINT"); } try { if (!this._args.attachToDebug) { + console.log("Killing driver..."); await this._driver.quit(); + this._isAlive = false; + console.log("Driver is dead!"); } else { //await this._webio.detach(); } } catch (error) { + if (this._args.verbose) { + console.dir(error); + } } - this._isAlive = false; - console.log("Driver is dead"); } private static async applyAdditionalSettings(args) { @@ -817,13 +832,16 @@ export class AppiumDriver { private static configureLogging(driver, verbose) { driver.on("status", function (info) { - log(info.cyan, verbose); + log(info, verbose); + }); + driver.on("quit", function (info) { + console.log("QUIT: ", info); }); driver.on("command", function (meth, path, data) { - log(" > " + meth.yellow + path.grey + " " + (data || ""), verbose); + log(" > " + meth + " " + path + " " + (data || ""), verbose); }); driver.on("http", function (meth, path, data) { - log(" > " + meth.magenta + path + " " + (data || "").grey, verbose); + log(" > " + meth + " " + path + " " + (data || ""), verbose); }); }; @@ -945,4 +963,4 @@ export class AppiumDriver { return new UIElement(searchResult, this._driver, this._wd, this._webio, this._args, "elementByImage", imageAsBase64); } -} +} \ No newline at end of file diff --git a/lib/appium-server.ts b/lib/appium-server.ts index aaa5792..3cc93c6 100644 --- a/lib/appium-server.ts +++ b/lib/appium-server.ts @@ -1,4 +1,4 @@ -import { ChildProcess, spawn } from "child_process"; +import { ChildProcess, spawn, execSync } from "child_process"; import { log, resolvePath, @@ -9,7 +9,8 @@ import { logWarn, logInfo, prepareApp, - prepareDevice + prepareDevice, + stopServerCommand } from "./utils"; import { INsCapabilities } from "./interfaces/ns-capabilities"; import { IDeviceManager } from "./interfaces/device-manager"; diff --git a/lib/helpers/start-session.d.ts b/lib/helpers/start-session.d.ts new file mode 100644 index 0000000..4652015 --- /dev/null +++ b/lib/helpers/start-session.d.ts @@ -0,0 +1,2 @@ +import { INsCapabilities } from "../interfaces/ns-capabilities"; +export declare const nsCapabilities: INsCapabilities; diff --git a/lib/helpers/start-session.ts b/lib/helpers/start-session.ts new file mode 100644 index 0000000..6d52db6 --- /dev/null +++ b/lib/helpers/start-session.ts @@ -0,0 +1,42 @@ +import { execSync } from "child_process"; +import { NsCapabilities } from "../ns-capabilities"; +import { AppiumServer } from "../appium-server"; +import { AppiumDriver } from "../appium-driver"; +import { isWin, logInfo, logError, stopServerCommand } from "../utils"; +import * as parser from "../parser" +import { INsCapabilities } from "../interfaces/ns-capabilities"; + +export const nsCapabilities: INsCapabilities = new NsCapabilities(parser); +let server: AppiumServer; +const startSession = async () => { + if (!isWin()) { + execSync(stopServerCommand(nsCapabilities.port)); + console.log(stopServerCommand(nsCapabilities.port)); + } + + nsCapabilities.validateArgs(); + nsCapabilities.appiumCaps = nsCapabilities.appiumCaps || {}; + nsCapabilities.appiumCaps["newCommandTimeout"] = 300; + server = new AppiumServer(nsCapabilities); + await server.start(nsCapabilities.port); + const driver = await AppiumDriver.createAppiumDriver(nsCapabilities); + const session = await driver.sessionId(); + logInfo(`port: ${nsCapabilities.port}`); + logInfo(`session id: ${session}`); +} + +startSession().then(s => { + logInfo("session started") +}); + +process.once("uncaughtException", async () => { + logError(`uncaughtException!`) +}) + +process.once("SIGINT", async () => { + if (!isWin()) { + console.log(`stop server!`) + execSync(stopServerCommand(nsCapabilities.port)); + } + await server.stop(); +}) \ No newline at end of file diff --git a/lib/parser.d.ts b/lib/parser.d.ts index 2293fcf..c30215c 100644 --- a/lib/parser.d.ts +++ b/lib/parser.d.ts @@ -1 +1 @@ -export declare const projectDir: string, projectBinary: string, pluginRoot: string, pluginBinary: string, port: number, verbose: boolean, appiumCapsLocation: string, testFolder: string, runType: string, isSauceLab: boolean, appPath: string, storage: string, testReports: string, devMode: boolean, ignoreDeviceController: boolean, wdaLocalPort: number, path: string, relaxedSecurity: boolean, cleanApp: boolean, attachToDebug: boolean, sessionId: string, startSession: boolean, capabilitiesName: string, imagesPath: string, startDeviceOptions: string, deviceTypeOrPlatform: string, device: any, driverConfig: any; +export declare const projectDir: string, projectBinary: string, pluginRoot: string, pluginBinary: string, port: number, verbose: boolean, appiumCapsLocation: string, testFolder: string, runType: string, isSauceLab: boolean, appPath: string, storage: string, testReports: string, devMode: boolean, ignoreDeviceController: boolean, wdaLocalPort: number, path: string, relaxedSecurity: boolean, cleanApp: boolean, attachToDebug: boolean, sessionId: string, startSession: boolean, capabilitiesName: string, imagesPath: string, startDeviceOptions: string, deviceTypeOrPlatform: string, device: import("mobile-devices-controller/lib/device").IDevice, driverConfig: any; diff --git a/lib/parser.ts b/lib/parser.ts index c5d3b9d..fe4e288 100644 --- a/lib/parser.ts +++ b/lib/parser.ts @@ -1,6 +1,6 @@ import * as yargs from "yargs"; import { join } from "path"; -import { resolvePath, logError } from "./utils"; +import { resolvePath, logError, logWarn } from "./utils"; import { INsCapabilitiesArgs } from "./interfaces/ns-capabilities-args"; const config = (() => { @@ -105,8 +105,8 @@ const config = (() => { options.devMode = true; console.log(`Option attachToDebug is set to true. Option --devMode is set true as well !`) if (!options.port) { - logError("Provide appium server port started from desktop application!") - process.exit(1); + logWarn(`Default appium server port 4732!`); + logWarn(`In order to change it use --port option!`); } } diff --git a/lib/utils.d.ts b/lib/utils.d.ts index 22ddb23..393e5fb 100644 --- a/lib/utils.d.ts +++ b/lib/utils.d.ts @@ -39,6 +39,7 @@ export declare const prepareApp: (args: INsCapabilities) => Promise Promise; export declare function encodeImageToBase64(path: any): string; export declare const shouldUserMobileDevicesController: (args: INsCapabilities) => boolean; +export declare const stopServerCommand: (port: any) => string; export declare function logInfo(info: any, obj?: any): void; export declare function logWarn(info: any, obj?: any): void; export declare function logError(info: any, obj?: any): void; diff --git a/lib/utils.ts b/lib/utils.ts index 0c987cd..bb2f531 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -606,6 +606,9 @@ export const shouldUserMobileDevicesController = (args: INsCapabilities) => { return !args.isSauceLab && (new RegExp(`${useDsCS}`).test(`true`) || new RegExp(`${useMDsCS}`).test(`true`)); } +export const stopServerCommand = (port) => { + return `lsof -i tcp:${port} | grep -v grep | grep -v PID | awk '{print $2}' | xargs kill -9 || true`; +} export function logInfo(info, obj = undefined) { info += " " + convertObjToString(obj); diff --git a/package.json b/package.json index d19584e..b8e3248 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,8 @@ "bin": { "nativescript-dev-appium": "./bin/nativescript-dev-appium", "ns-dev-appium": "./bin/nativescript-dev-appium", - "ns-appium": "./bin/nativescript-dev-appium" + "ns-appium": "./bin/nativescript-dev-appium", + "ns-start-session": "./bin/start-session" }, "dependencies": { "app-root-path": "~2.1.0", diff --git a/test/device-manager.spec.ts b/test/device-manager.spec.ts index f0f0e95..f950d44 100644 --- a/test/device-manager.spec.ts +++ b/test/device-manager.spec.ts @@ -245,6 +245,7 @@ describe("Start device by apiLevel", async () => { describe("dev-mode-options", async () => { let appiumServer: AppiumServer; + const port = 8399; before("start devices", async () => { await DeviceController.startDevice({ platform: Platform.ANDROID, apiLevel: "23" }); @@ -263,6 +264,8 @@ describe("dev-mode-options", async () => { const nsCaps = new NsCapabilities({ deviceTypeOrPlatform: Platform.IOS, appPath: iosApp, + port: port, + verbose: true }); const appiumDriver = await AppiumDriver.createAppiumDriver(nsCaps); @@ -273,7 +276,8 @@ describe("dev-mode-options", async () => { it("test android", async () => { const nsCaps = new NsCapabilities({ deviceTypeOrPlatform: Platform.ANDROID, - appPath: androidApp + appPath: androidApp, + port: port, }); const appiumDriver = await AppiumDriver.createAppiumDriver(nsCaps); @@ -284,7 +288,8 @@ describe("dev-mode-options", async () => { it("test --device.platform=android", async () => { const nsCaps = new NsCapabilities({ device: { platform: Platform.ANDROID }, - appPath: androidApp + appPath: androidApp, + port: port }); const appiumDriver = await AppiumDriver.createAppiumDriver(nsCaps); @@ -295,7 +300,8 @@ describe("dev-mode-options", async () => { it("test --device.platform=ios", async () => { const nsCaps = new NsCapabilities({ device: { platform: Platform.IOS }, - appPath: iosApp + appPath: iosApp, + port: port }); const appiumDriver = await AppiumDriver.createAppiumDriver(nsCaps);