Repository: codeceptjs/CodeceptJS (JavaScript)

Issue:
Gherkin: duplicated steps generated with `gherkin:snippets`
#### What are you trying to achieve?
When I generate steps with `gherkin:snippets` command I do not want to have duplicated steps.
Problem appears when we have more than one scenario in feature, e.g.
```
  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
```

#### What do you get instead?
Step `I open a browser on a site` appears twice in `steps.js` file
### Details

* CodeceptJS version: 2.6
* NodeJS Version: 13.11.0



Discussion:

Patch:
diff --git a/lib/command/gherkin/snippets.js b/lib/command/gherkin/snippets.js
index 4739bff87..8c7b90c3f 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 `


Test patch:
diff --git a/test/data/sandbox/codecept.dummy.bdd.json b/test/data/sandbox/codecept.dummy.bdd.json
index c9d053b41..77a507486 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 000000000..ef9b9bbfb
--- /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 000000000..56ae69981
--- /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 4cde1e4a4..9ae4e7442 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();
+    });
+  });
 });