nightwatchjs / nightwatch

Integrated end-to-end testing framework written in Node.js and using W3C Webdriver API. Developed at @browserstack
https://nightwatchjs.org
MIT License
11.79k stars 1.31k forks source link

Support Native Mobile App #3289

Closed CadeHowarth closed 2 years ago

CadeHowarth commented 2 years ago

Describe the bug

I am trying to use Appium and Nightwatch together to test a native app on an Android Studio emulator. Appium does not allow appPackage and browserName in the same desiredCapabilities, and the official Nightwatch/Appium setup wiki article (https://github.com/nightwatchjs/nightwatch/wiki/Testing-Android-native-application-and-mobile-browsers-with-Appium) indicates that placing a blank string into the browserName capability should be possible. Instead, I receive the following error when attempting to run my test:

Error: Unknown browser: ""

I believe that this field should allow a blank string, if the Appium wiki article is correct.

Furthermore, if browserName is not provided in the configuration file at all, Nightwatch will automatically default to firefox as the browserName, even though the configuration file does not list the capability at all.

Sample test

sampleTest.js

```js module.exports = { tags: ['androidNative'], '@disabled': false, 'Add two numbers' : function (client) { client .useXpath() .click('//android.widget.Button[@resource-id="com.google.android.calculator:id/digit_5"]') .click('//android.widget.Button[@resource-id="com.google.android.calculator:id/op_add"]') .click('//android.widget.Button[@resource-id="com.google.android.calculator:id/digit_5"]') .click('//android.widget.Button[@resource-id="com.google.android.calculator:id/eq"]') .assert.containsText('//android.widget.TextView[@resource-id="com.google.android.calculator:id/result"]', '10') client.end(); } }; ```

Run with command

 npx nightwatch --tag androidNative -e androidNative

Verbose output

debug.log

Error: Unknown browser: ""

Configuration

nightwatch.json

default: { desiredCapabilities: { browserName: "" }, }, androidNative: { selenium_start_process: false, selenium_port: 4723, selenium_host: "127.0.0.1", selenium_path: "/wd/hub", desiredCapabilities: { appiumVersion: "1.22.3", automationName: "Appium", platformName: "Android", platformVersion: "11.0", avd: "Samsung_Galaxy_Tab_S7_API_32", deviceName: "Samsung Galaxy Tab S7", appActivity: "", appPackage: "", autoGrantPermissions: true, noReset: true, fullReset: false }, appium: { start_process: true } }

Your Environment

Executable Version
nightwatch --version 2.2.2
npm --version 8.3.1
yarn --version N/A
node --version 16.14.0
Browser driver Version
N/A N/A
OS Version
Windows 11 10.0.22000 Build 22000
beatfactor commented 2 years ago

try setting it to null.

CadeHowarth commented 2 years ago

It looks like adding in null into the browserName field returns this error from Nightwatch verbose logs.

TypeError: An error occurred while creating a new Selenium Server session: [TypeError] Cannot read properties of undefined (reading 'getBrowserName')

beatfactor commented 2 years ago

Could you maybe suggest how we can update this unit test to reproduce the issue?

CadeHowarth commented 2 years ago

The unit test looks correct to me, though you might try adding in the selenium port, and see if that has an effect? I say that only because of the TypeError received when passing null. It indicates that when starting a selenium server session, it receives the error.

I also feel that it is prudent to note that, since I am running version 2 of Nightwatch, I never took the time to explicitly install selenium server in any capacity; though I did not think that would be an issue given that the configuration sets the start process to false.

Additionally, it could be possible that the assert in the unit test is not adequate to test its validity. From what I understand, strictEqual is passing the variable laid out in the desiredCapabilities, and testing that it === null. I believe that would pass as true regardless if the runner does not accept it or not. I am not the most knowledgable on these subjects, I'm stilling learning, but would it be better to replace assert.strictEquals with something like assert.doesNotReject?

gravityvi commented 2 years ago

@CadeHowarth I think the error over here is Nightwatch is trying to create a process. Can you try using this config:

 androidNative: {
      selenium: {
        host: '127.0.0.1',
        port: 4723
      },
      webdriver: {
        start_process: false
      },

      desiredCapabilities: {
        appiumVersion: '1.22.3',
        automationName: 'Appium',
        platformName: 'Android',
        platformVersion: '11.0',
        avd: 'Samsung_Galaxy_Tab_S7_API_32',
        deviceName: 'Samsung Galaxy Tab S7',
        appActivity: '<activityString>',
        appPackage: '<packageString>',
        autoGrantPermissions: true,
        noReset: true,
        fullReset: false
      },
      appium: {
        start_process: true
      }
    }
CadeHowarth commented 2 years ago

Hey @gravityvi I just attempted running that config both with and without browserName set, and it looks like Nightwatch still attempts to set the browserName with or without; still not allowing me to pass in an empty string or null into the field.

Editing to provide more information:

This config: `test_settings: {

default: {
  desiredCapabilities: {
    browserName: null
  },
},

androidNative: {
  selenium: {
    port: 4723,
    shost: "127.0.0.1",
    path: "/wd/hub",
  },

  webdriver: {
    start_process: false
  },

  desiredCapabilities: {
      appiumVersion: "1.22.3",
      automationName: "Appium",
      platformName: "Android",
      platformVersion: "11.0",
      avd: "Samsung_Galaxy_Tab_S7_API_32",
      deviceName: "Samsung Galaxy Tab S7",
      appActivity: '<activityString>',
      appPackage: '<packageString>',
      autoGrantPermissions: true,
      noReset: true,
      fullReset: false
  },
    appium: {
      start_process: true
  }
}`

results in this verbose log: Error: Unrecognized browser: null.

This config: ` test_settings: {

androidNative: {
  selenium: {
    port: 4723,
    shost: "127.0.0.1",
    path: "/wd/hub",
  },

  webdriver: {
    start_process: false
  },

  desiredCapabilities: {
      appiumVersion: "1.22.3",
      automationName: "Appium",
      platformName: "Android",
      platformVersion: "11.0",
      avd: "Samsung_Galaxy_Tab_S7_API_32",
      deviceName: "Samsung Galaxy Tab S7",
      appActivity: '<activityString>',
      appPackage: '<packageString>',
      autoGrantPermissions: true,
      noReset: true,
      fullReset: false
  },
    appium: {
      start_process: true
  }
}`

results in this verbose log: UnsupportedOperationError: An error occurred while creating a new GeckoDriver session: [UnsupportedOperationError] The requested resource could not be found, or a request was received using an HTTP method that is not supported by the mapped resource

This config: ` test_settings: {

default: {
  desiredCapabilities: {
    browserName: ""
  },
},

androidNative: {
  selenium: {
    port: 4723,
    shost: "127.0.0.1",
    path: "/wd/hub",
  },

  webdriver: {
    start_process: false
  },

  desiredCapabilities: {
      appiumVersion: "1.22.3",
      automationName: "Appium",
      platformName: "Android",
      platformVersion: "11.0",
      avd: "Samsung_Galaxy_Tab_S7_API_32",
      deviceName: "Samsung Galaxy Tab S7",
      appActivity: '<activityString>',
      appPackage: '<packageString>',
      autoGrantPermissions: true,
      noReset: true,
      fullReset: false
  },
    appium: {
      start_process: true
  }
}`

results in this verbose log: Error: Unknown browser: ""