Repository: nightwatchjs/nightwatch (js)

Issue:
Xpath locators stopped working for .waitForElementVisible() and .waitForElementPresent()

I started getting the following error with all waitForElementVisible() or waitForElementPresent() functions in my test suits today:

Error: Error while running "waitForElementVisible" command: "Error: Provided locating strategy "//span[contains(text(),'Element')]" is not supported for .waitForElementVisible(). It must be one of the following: id, css selector, link text, partial link text, tag name, xpath

All xPath locators are valid (worked before for over a year, checked in a browser console). If I replace .waitForElementVisible() with .verify.elementPresent() or just .click() - it works


## Sample test
<!-- 
Include a sample test which reproduces the problem you're experiencing. If possible, the test should be against a public url.

Please add the test and other info inline, not as attachments or screenshots.
-->

<details><summary>sampleTest.js</summary><p>
<!-- browsers demand the next line be empty -->

```js
// Please add the sample test here

module.exports = {
  sampleTest: function(browser) {
browser
.url(pageUrl + "deployments")
      .pause(1000)
      .click(testDeployment)
      .verify.elementPresent(
        `//span[contains(text(), "Total Runs")]`,
        "Deployment package page is loaded"
      )
      .url(pageUrl + "deployments")
      .pause(1000)
      .click(assetDeployments)
      .waitForElementVisible(
        `//th[contains(text(),'Scheduled Time')]`,
        "Asset deployments page is loaded"
      )
      .url(pageUrl + "custom-scripts")
      .verify.urlContains(
        "scripts",
        "admin users have access to scripts page"
      )
      .verify.elementPresent(
        refreshButton,
        "Refresh button is present on scripts page"
      )
  }
}
```
</p></details>

**Run with command**
<!-- Include the command used to run the test, if applicable. -->

```sh
npm test -- --tag sample
```

### Verbose output
<details><summary>debug.log</summary><p>
<!-- browsers demand the next line be empty -->

```txt
 → Completed command: url ('http://localhost:3001/deployments') (194ms)
 
 → Running command: pause (1000)
  → Completed command: pause (1000) (1004ms)
 
 → Running command: click ('//span[contains(text(),'Asset Deployments')]')
   Request POST  /session/0cb2b964016173a366b899c3f93e9674/elements  
   {
     using: 'xpath',
     value: "//span[contains(text(),'Asset Deployments')]"
}
   Response 200 POST /session/0cb2b964016173a366b899c3f93e9674/elements (15ms)
   {
     sessionId: '0cb2b964016173a366b899c3f93e9674',
     status: 0,
     value: [ { ELEMENT: '0.4085434465794966-1' } ]
}
   Request POST  /session/0cb2b964016173a366b899c3f93e9674/element/0.4085434465794966-1/click  
{}
   Response 200 POST /session/0cb2b964016173a366b899c3f93e9674/element/0.4085434465794966-1/click (199ms)
   {
     sessionId: '0cb2b964016173a366b899c3f93e9674',
     status: 0,
     value: null
}
  → Completed command: click ('//span[contains(text(),'Asset Deployments')]') (215ms)
 
 → Running command: waitForElementVisible ('//th[contains(text(),'Scheduled Time')]', 'Asset deployments page is loaded')
  → Completed command: waitForElementVisible ('//th[contains(text(),'Scheduled Time')]', 'Asset deployments page is loaded') (0ms)
 → Running [afterEach]:
 → Completed [afterEach].

FAILED: 1 errors and  36 passed (28.165s)
   Error: Error while running "waitForElementVisible" command: "Error: Provided locating strategy "//th[contains(text(),'Scheduled Time')]" is not supported for .waitForElementVisible(). It must be one of the following: id, css selector, link text, partial link text, tag name, xpath.
  "
```
</p></details>


## Configuration
<details><summary>nightwatch.conf.js</summary><p>
<!-- browsers demand the next line be empty -->

<!-- Please paste your nightwatch.json or nightwatch.conf.js here; make sure to leave out any sensitive details -->

```js
module.exports = {
  src_folders: ["e2e-test/tests"],
  page_objects_path: ["e2e-test/page-objects"],
  log_screenshot_data: true,
  test_workers: {
    "enabled": true,
    "workers": "auto"
  },

  webdriver: {
    start_process: true,
    timeout_options: { timeout: 15000, retry_attempts: 6 },
    status_poll_interval: 100,
    max_status_poll_tries: 6,
    server_path: "node_modules/.bin/chromedriver",
    port: 9515,
  },

  test_settings: {
    default: {
      screenshots: {
        enabled: false,
      },
      desiredCapabilities: {
        browserName: "chrome",
        javascriptEnabled: true,
        chromeOptions: {
          args: [
            "--window-size=1920,1080",
            "--start-maximized",
            "--headless",
            "--disable-gpu",
            "no-sandbox",
          ],
        },
        binary: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
      },
    },
  },
};

```
</p></details>

## Your Environment
<!--- Include the relevant details your environment -->

| Executable | Version |
| ---: | :--- |
| `nightwatch --version` | 1.3.6 |
| `npm --version`  | 6.14.4 |
| `yarn --version` | 1.22.4 |
| `node --version` | v12.16.2 |

| Browser driver | Version |
| --- | --- |
| chromedriver | 89.0.0 |

| OS | Version |
| --- | --- |
| macOS Mojave | 10.14.6 |



Pull request description:
use locate strategy from args when valid strategy is found
Thanks in advance for your contribution. Please follow the below steps in submitting a pull request, as it will help us with reviewing it quicker.

- [x] Create a new branch from master (e.g. `features/my-new-feature` or `issue/123-my-bugfix`);
- [x] If you're fixing a bug also create an issue if one doesn't exist yet;
- [x] If it's a new feature explain why do you think it's necessary. Please check with the maintainers beforehand to make sure it is something that we will accept. Usually we only accept new features if we feel that they will benefit the entire community;
- [x] Please avoid sending PRs which contain drastic or low level changes. If you are certain that the changes are needed, please discuss them beforehand and indicate what the impact will be;
- [x] If your change is based on existing functionality please consider refactoring first. Pull requests that duplicate code will most likely be ignored;
- [x] Do not include changes that are not related to the issue at hand;
- [x] Follow the same coding style with regards to spaces, semicolons, variable naming etc.;
- [x] Always add unit tests - PRs without tests are most of the times ignored.

### Related Issues
- Fixes #2695 


Patch:
diff --git a/lib/api/element-commands/_waitFor.js b/lib/api/element-commands/_waitFor.js
index fb046547..4ac4dff5 100644
--- a/lib/api/element-commands/_waitFor.js
+++ b/lib/api/element-commands/_waitFor.js
@@ -1,6 +1,7 @@
 const Utils = require('../../utils');
 const {AssertionRunner} = require('../../assertion');
-const ElementCommand = require('../../element').Command;
+const {LocateStrategy, Command: ElementCommand} = require('../../element');
+
 
 /*!
  * Base class for waitForElement commands. It provides a command
@@ -24,7 +25,7 @@ class WaitForElement extends ElementCommand {
   }
 
   validateArgsCount() {
-    if (Utils.isString(this.args[0]) && (Utils.isString(this.args[1]) || ElementCommand.isSelectorObject(this.args[1]))) {
+    if (LocateStrategy.isValid(this.args[0]) && (Utils.isString(this.args[1]) || ElementCommand.isSelectorObject(this.args[1]))) {
       this.setStrategyFromArgs();
     }
   }


Test patch:
diff --git a/test/src/api/commands/testWaitForElementVisible.js b/test/src/api/commands/testWaitForElementVisible.js
index 82331a11..c6968089 100644
--- a/test/src/api/commands/testWaitForElementVisible.js
+++ b/test/src/api/commands/testWaitForElementVisible.js
@@ -293,4 +293,39 @@ describe('waitForElementVisible', function() {
       }
     });
   });
+
+  it('client.waitForElementVisible() success with selector and test message only', function () {
+    MockServer
+      .addMock({
+        url: '/wd/hub/session/1352110219202/elements',
+        postdata: {
+          using: 'css selector',
+          value: '#web-login'
+        },
+        method: 'POST',
+        response: JSON.stringify({
+          status: 0,
+          state: 'success',
+          value: [{ELEMENT: '99'}]
+        })
+      }, true)
+      .addMock({
+        url: '/wd/hub/session/1352110219202/element/99/displayed',
+        method: 'GET',
+        response: JSON.stringify({
+          state: 'success',
+          status: 0,
+          value: true
+        })
+      }, true);
+
+    this.client.api.waitForElementVisible('#web-login', 'Test message');
+
+    return this.client.start(function(err) {
+      if (err) {
+        throw err;
+      }
+    });
+  });
+
 });