Repository: nightwatchjs/nightwatch
Pull request #3634 (2023-03-08 19:03:30)

Allow to use any browser with BrowserStack and Appium.
This PR allows users to use any browser with BrowserStack, as well as while creating a session with Appium server.

This is because with BrowserStack, we can send any browser name and instead of returning an error it creates a session with Chrome browser as default. And with Appium server, accepted values of `browserName` depends on the driver being used and hence cannot be pre-defined.

With selenium server, because we use Selenium's `Builder` class which supports only a few browsers, it will throw an appropriate error for other unsupported browsers instead of just some random error.

swrdfish: Can you add a test for this. 

Patch:
diff --git a/.github/workflows/build-node.yaml b/.github/workflows/build-node.yaml
index 49ef4368..1b69b96d 100644
--- a/.github/workflows/build-node.yaml
+++ b/.github/workflows/build-node.yaml
@@ -15,6 +15,7 @@ jobs:
     runs-on: ubuntu-latest
 
     strategy:
+      fail-fast: false
       matrix:
         node-version: [12.x, 14.x, 16.x, 18.x]
         # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
@@ -33,6 +34,7 @@ jobs:
     runs-on: windows-latest
 
     strategy:
+      fail-fast: false
       matrix:
         node-version: [16.x, 18.x]
     steps:
diff --git a/lib/transport/factory.js b/lib/transport/factory.js
index 0f77bc0a..638a6e33 100644
--- a/lib/transport/factory.js
+++ b/lib/transport/factory.js
@@ -61,10 +61,15 @@ module.exports = class TransportFactory {
 
     let {browserName} = settings.desiredCapabilities;
 
-    // Better support for app-testing, if the browserName is not present we can skip all further checks
+    // Allow to use any browserName with Appium and BrowserStack.
+    // Not supporting '--browserName' cli flag for both of these.
     const usingAppium = TransportFactory.usingSeleniumServer(settings) && settings.selenium.use_appium;
     const usingBrowserStack = TransportFactory.usingBrowserstack(settings);
-    if ((usingAppium || usingBrowserStack) && !browserName) {
+    if (usingAppium || usingBrowserStack) {
+      if (BrowsersLowerCase[browserName && browserName.toLowerCase()]) {
+        browserName = BrowsersLowerCase[browserName.toLowerCase()];
+      }
+
       return browserName;
     }
 
@@ -94,7 +99,7 @@ module.exports = class TransportFactory {
       const didYouMean = require('didyoumean');
       const browsersList = Object.values(Browser);
       const resultMeant = didYouMean(browserName, browsersList);
-  
+
       throw new Error(`Unknown browser: "${browserName}"${resultMeant ? ('; did you mean "' + resultMeant + '"?') : ''}`);
     }
 
diff --git a/lib/transport/selenium-webdriver/selenium.js b/lib/transport/selenium-webdriver/selenium.js
index cc24a2e6..c789aeee 100644
--- a/lib/transport/selenium-webdriver/selenium.js
+++ b/lib/transport/selenium-webdriver/selenium.js
@@ -74,8 +74,6 @@ module.exports = class SeleniumServer extends DefaultSeleniumDriver {
 
     return super.setBuilderOptions({builder, options});
   }
-
-
 };
 
 


Test patch:
diff --git a/test/src/cli/testServiceCreationFromCli.js b/test/src/cli/testServiceCreationFromCli.js
index b23c9ab0..14a3e1d4 100644
--- a/test/src/cli/testServiceCreationFromCli.js
+++ b/test/src/cli/testServiceCreationFromCli.js
@@ -3,7 +3,9 @@ const mockery = require('mockery');
 const assert = require('assert');
 const origPath = require('path');
 
-describe('Service creation from cli.js', function() {
+const IS_WINDOWS = process.platform === 'win32';
+
+(IS_WINDOWS ? describe.skip : describe)('Service creation from cli.js', function() {
   this.timeout(15000);
 
   beforeEach(function() {
@@ -54,7 +56,7 @@ describe('Service creation from cli.js', function() {
     mockery.registerMock('./options.js', MockOptions);
   }
 
-  xit('test appium server startup', function() {
+  it('test appium server startup', function() {
     let appiumPathQueried = false;
     mockOptions({
       onAppiumPathQuery() {
diff --git a/test/src/core/testCreateSession.js b/test/src/core/testCreateSession.js
index a29573e4..3ac36f63 100644
--- a/test/src/core/testCreateSession.js
+++ b/test/src/core/testCreateSession.js
@@ -433,18 +433,32 @@ describe('test Request With Credentials', function () {
     });
   });
 
-  it('Test create session with use_appium property - Appium support', async function () {
+  it('Test create session with use_appium property and random browser - Appium support', async function () {
     nock('http://somewhere:9999')
       .post('/wd/hub/session')
-      .reply(201, {
-        value: {
+      .reply(201, function (uri, requestBody) {
+        assert.deepEqual(requestBody, {
           capabilities: {
-            platformName: 'android',
-            platformVersion: '12.0',
-            name: 'sample test goes here'
-          },
-          sessionId: '1352110219202'
-        }
+            firstMatch: [{}],
+            alwaysMatch: {
+              browserName: 'acmeBrowser',
+              platformName: 'android',
+              'appium:platformVersion': '12.0'
+            }
+          }
+        });
+
+        return {
+          value: {
+            capabilities: {
+              browserName: 'acmeBrowser',
+              platformName: 'android',
+              platformVersion: '12.0',
+              name: 'sample test goes here'
+            },
+            sessionId: '1352110219202'
+          }
+        };
       });
 
     const client = Nightwatch.createClient({
@@ -458,15 +472,16 @@ describe('test Request With Credentials', function () {
         port: 9999
       },
       desiredCapabilities: {
-        browserName: '',
+        browserName: 'acmeBrowser',
         platformName: 'android',
-        platformVersion: '12.0'
+        'appium:platformVersion': '12.0'
       }
     });
 
     const result = await client.createSession();
     assert.deepStrictEqual(result, {
       capabilities: {
+        browserName: 'acmeBrowser',
         platformName: 'android',
         platformVersion: '12.0',
         name: 'sample test goes here'
@@ -929,16 +944,15 @@ describe('test Request With Credentials', function () {
     });
   });
 
-  it('Test create session with browserstack and update buildName', async function () {
+  it('Test create session with browserstack with random browser and update buildName', async function () {
     nock('https://hub.browserstack.com')
       .post('/wd/hub/session')
       .reply(201, function (uri, requestBody) {
-
         assert.deepEqual(requestBody, {
           capabilities: {
             firstMatch: [{}],
             alwaysMatch: {
-              browserName: 'chrome',
+              browserName: 'acmeBrowser',
               'bstack:options': {
                 local: 'false',
                 sessionName: 'Try 1',
@@ -947,8 +961,7 @@ describe('test Request With Credentials', function () {
                 os: 'OS X',
                 osVersion: 'Monterey',
                 buildName: 'Nightwatch Programmatic Api Demo'
-              },
-              'goog:chromeOptions': {w3c: false}
+              }
             }
           }
         });
@@ -1000,12 +1013,8 @@ describe('test Request With Credentials', function () {
           os: 'OS X',
           osVersion: 'Monterey'
         },
-        browserName: 'chrome',
-        chromeOptions: {
-          w3c: false
-        }
+        browserName: 'acmeBrowser'
       },
-
       parallel: false
     });
 
@@ -1020,7 +1029,7 @@ describe('test Request With Credentials', function () {
       capabilities: {
         firstMatch: [{}],
         alwaysMatch: {
-          browserName: 'chrome',
+          browserName: 'acmeBrowser',
           'bstack:options': {
             local: 'false',
             sessionName: 'Try 1',
@@ -1029,8 +1038,7 @@ describe('test Request With Credentials', function () {
             os: 'OS X',
             osVersion: 'Monterey',
             buildName: 'Nightwatch Programmatic Api Demo'
-          },
-          'goog:chromeOptions': {w3c: false}
+          }
         }
       }
     });