Repository: Codeception/CodeceptJS
Pull request #2313 (2020-04-02 23:44:23)

update waitForElement to support waitUntil in webdriverio^6.0
## Motivation/Description of the PR
- When using WebDriver helper with webdriverio@^6.0, the `waitForElement` function is not applying the optional second argument to override the default timeout length. 
- WebDriverIO v6 updates `waitUntil` method which is used by all of the `wait*` functions. Many of these function were updated, such as `waitForVisible` and `waitInUrl` however `waitForElement` appears to still use the webdriverio@^5.0 code.
- This updates the `waitForElement` function by the same convention used to update `waitForVisible` and `waitInUrl` to be compatible with both WebDriverIO v5 & v6.

Applicable helpers:

- [x] WebDriver

## Type of change

- [x] :bug: Bug fix
- [ ] :hotsprings: Hot fix

## Notes

- I was unable to configure the repo to run the tests in examples directory. I implemented tests for this fix on a branch I use myself, so any guidance in implementing a test for this would be appreciated. 😄 


DavertMik: 
![Codacy](https://app.codacy.com/assets/images/favicon.png) Here is an overview of what got changed by this pull request:


```diff

Clones added
============
- lib/helper/WebDriver.js  5
         
```


See the complete overview on [Codacy](https://app.codacy.com/manual/DavertMik/CodeceptJS/pullRequest?prid=5297039&bid=17338795)
        
PeterNgTr: @Mooksc what prevents you from running tests locally?
Mooksc: > @Mooksc what prevents you from running tests locally?

Hey @PeterNgTr - I was running into errors like `Cannot read 'name' of undefined` when following the instructions in the contributing guidelines for running tests locally in the fork - when trying to run `node bin/codecept.js run -c examples` for example.
PeterNgTr: https://github.com/Codeception/CodeceptJS/blob/master/.github/CONTRIBUTING.md have you followed this guide?
Mooksc: > https://github.com/Codeception/CodeceptJS/blob/master/.github/CONTRIBUTING.md#testing have you followed this guide?

Oh wow - I was using that guide but it looks like I didn't read far enough 😛 The docker-compose solution worked 👍 running the unit tests now. Thanks!

Patch:
diff --git a/lib/command/gherkin/snippets.js b/lib/command/gherkin/snippets.js
index 4739bff8..8c7b90c3 100644
--- a/lib/command/gherkin/snippets.js
+++ b/lib/command/gherkin/snippets.js
@@ -49,7 +49,7 @@ module.exports = function (genPath, options) {
   });
   output.print(`Loaded ${files.length} files`);
 
-  let newSteps = [];
+  const newSteps = new Map();
 
   const parseSteps = (steps) => {
     const newSteps = [];
@@ -88,9 +88,9 @@ module.exports = function (genPath, options) {
     const ast = parser.parse(fs.readFileSync(file).toString());
     for (const child of ast.feature.children) {
       if (child.type === 'ScenarioOutline') continue; // skip scenario outline
-      newSteps = newSteps.concat(parseSteps(child.steps).map((step) => {
+      parseSteps(child.steps).map((step) => {
         return Object.assign(step, { file: file.replace(global.codecept_dir, '').slice(1) });
-      }));
+      }).map((step) => newSteps.set(`${step.type}(${step})`, step));
     }
   };
 
@@ -106,7 +106,7 @@ module.exports = function (genPath, options) {
     stepFile = fsPath.join(global.codecept_dir, stepFile);
   }
 
-  const snippets = newSteps
+  const snippets = [...newSteps.values()]
     .filter((value, index, self) => self.indexOf(value) === index)
     .map((step) => {
       return `
diff --git a/lib/helper/WebDriver.js b/lib/helper/WebDriver.js
index a8e6b673..52bf9772 100644
--- a/lib/helper/WebDriver.js
+++ b/lib/helper/WebDriver.js
@@ -1876,10 +1876,16 @@ class WebDriver extends Helper {
    */
   async waitForElement(locator, sec = null) {
     const aSec = sec || this.options.waitForTimeout;
+    if (isWebDriver5()) {
+      return this.browser.waitUntil(async () => {
+        const res = await this.$$(withStrictLocator(locator));
+        return res && res.length;
+      }, aSec * 1000, `element (${locator}) still not present on page after ${aSec} sec`);
+    }
     return this.browser.waitUntil(async () => {
       const res = await this.$$(withStrictLocator(locator));
       return res && res.length;
-    }, aSec * 1000, `element (${locator}) still not present on page after ${aSec} sec`);
+    }, { timeout: aSec * 1000, timeoutMsg: `element (${locator}) still not present on page after ${aSec} sec` });
   }
 
   /**


Test patch:
diff --git a/test/data/sandbox/codecept.dummy.bdd.json b/test/data/sandbox/codecept.dummy.bdd.json
index c9d053b4..77a50748 100644
--- a/test/data/sandbox/codecept.dummy.bdd.json
+++ b/test/data/sandbox/codecept.dummy.bdd.json
@@ -8,7 +8,7 @@
     }
   },
   "gherkin": {
-    "features": "./support/*.feature",
+    "features": "./support/dummy.feature",
     "steps": [
       "./features/step_definitions/my_steps.js",
       "./features/step_definitions/my_other_steps.js"
@@ -18,4 +18,4 @@
   "bootstrap": false,
   "mocha": {},
   "name": "sandbox"
-}
\ No newline at end of file
+}
diff --git a/test/data/sandbox/codecept.duplicate.bdd.json b/test/data/sandbox/codecept.duplicate.bdd.json
new file mode 100644
index 00000000..ef9b9bbf
--- /dev/null
+++ b/test/data/sandbox/codecept.duplicate.bdd.json
@@ -0,0 +1,21 @@
+{
+  "tests": "./*_no_test.js",
+  "timeout": 10000,
+  "output": "./output",
+  "helpers": {
+    "BDD": {
+      "require": "./support/bdd_helper.js"
+    }
+  },
+  "gherkin": {
+    "features": "./support/duplicate.feature",
+    "steps": [
+      "./features/step_definitions/my_steps.js",
+      "./features/step_definitions/my_other_steps.js"
+    ]
+  },
+  "include": {},
+  "bootstrap": false,
+  "mocha": {},
+  "name": "sandbox"
+}
diff --git a/test/data/sandbox/support/duplicate.feature b/test/data/sandbox/support/duplicate.feature
new file mode 100644
index 00000000..56ae6998
--- /dev/null
+++ b/test/data/sandbox/support/duplicate.feature
@@ -0,0 +1,13 @@
+Feature: Auth
+
+  Scenario: Login to website
+    Given I open a browser on a site
+    When I click login button at 1.2
+    Then I see welcome message
+
+  Scenario: Logout from website
+    Given I open a browser on a site
+    And I click login button at 1.2
+    And I see welcome message
+    When I click logout
+    Then I see goodbye message
diff --git a/test/runner/bdd_test.js b/test/runner/bdd_test.js
index 4cde1e4a..9ae4e744 100644
--- a/test/runner/bdd_test.js
+++ b/test/runner/bdd_test.js
@@ -278,4 +278,12 @@ When(/^I define a step with a \\( paren and a "(.*?)" string$/, () => {
       done();
     });
   });
+
+  it('should not generate duplicated steps', (done) => {
+    exec(`${runner} gherkin:snippets --dry-run --config ${codecept_dir}/codecept.duplicate.bdd.json`, (err, stdout, stderr) => { //eslint-disable-line
+      assert.equal(stdout.match(/I open a browser on a site/g).length, 1);
+      assert(!err);
+      done();
+    });
+  });
 });