Repository: TheBrainFamily/cypress-cucumber-preprocessor
Pull request #279 (2019-12-03 05:37:33)

feature (get-cypress-config): allow check if cypress were run using --config-file option and use the configured path for get cypress config
When Cypress it's running when the `--config-file` flag, the preprocessor cannot find the path configured by this flag because in `lib/stepDefinitionPath.js` the `cypress.json` always loaded from the appRoot.


lgandecki: Cool stuff, I will play around with it a little and leave a review or merge :) Thanks!
gpincheiraa: @lgandecki I will push the test suite for the file `stepDefinitionPath` in a few hours.
lgandecki: nice! I was wondering whether I should be pushing you to add tests - I'd definitely be more comfortable with keeping the high test coverage, but I realize that part is not the easiest to test and will require mocking (so not very high confidence after all). But if you are comfortable writing tests around that area that would definitely be appreciated. 
gpincheiraa: > nice! I was wondering whether I should be pushing you to add tests - I'd definitely be more comfortable with keeping the high test coverage, but I realize that part is not the easiest to test and will require mocking (so not very high confidence after all). But if you are comfortable writing tests around that area that would definitely be appreciated.

it's ready!!!! https://github.com/TheBrainFamily/cypress-cucumber-preprocessor/blob/e8fee51d1c2e35fe2ba715c1ac1abccc593b7daf/lib/stepDefinitionPath.test.js
gpincheiraa: @lgandecki Hi! any news about this PR?

Patch:
diff --git a/lib/cypressExecutionInstance.js b/lib/cypressExecutionInstance.js
new file mode 100644
index 0000000..3f411a4
--- /dev/null
+++ b/lib/cypressExecutionInstance.js
@@ -0,0 +1,31 @@
+const ps = require("ps-node");
+const minimist = require("minimist");
+
+let cypressExecArgs;
+const lookupCypressQuery = {
+  command: "cypress",
+  arguments: "--config-file"
+};
+
+module.exports = {
+  load: async () =>
+    new Promise(resolve => {
+      ps.lookup(lookupCypressQuery, (err, resultList) => {
+        if (err) {
+          resolve();
+        }
+        cypressExecArgs = resultList
+          .filter(process => process && process.arguments.length)
+          .map(process => minimist(process.arguments))
+          .reduce(
+            (processArgs, finalProcessArgs) => ({
+              ...finalProcessArgs,
+              ...processArgs
+            }),
+            {}
+          );
+        resolve();
+      });
+    }),
+  getArguments: () => cypressExecArgs
+};
diff --git a/lib/index.js b/lib/index.js
index f82a779..93b8ca6 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -7,6 +7,7 @@ const chokidar = require("chokidar");
 const compile = require("./loader.js");
 const compileFeatures = require("./featuresLoader.js");
 const stepDefinitionPath = require("./stepDefinitionPath.js");
+const cypressExecutionInstance = require("./cypressExecutionInstance");
 
 const transform = file => {
   let data = "";
@@ -36,10 +37,13 @@ const touch = filename => {
 };
 
 let watcher;
-const preprocessor = (options = browserify.defaultOptions) => file => {
+
+const preprocessor = (options = browserify.defaultOptions) => async file => {
   if (options.browserifyOptions.transform.indexOf(transform) === -1) {
     options.browserifyOptions.transform.unshift(transform);
   }
+  // load arguments from running Cypress instance
+  await cypressExecutionInstance.load();
 
   if (file.shouldWatch) {
     if (watcher) {
diff --git a/lib/stepDefinitionPath.js b/lib/stepDefinitionPath.js
index b6e37da..d855882 100644
--- a/lib/stepDefinitionPath.js
+++ b/lib/stepDefinitionPath.js
@@ -1,12 +1,17 @@
 const fs = require("fs");
 const path = require("path");
 const cosmiconfig = require("cosmiconfig");
+const cypressExecutionInstance = require("./cypressExecutionInstance");
 
 module.exports = () => {
   const appRoot = process.cwd();
-
+  const cypressExecutionArguments = cypressExecutionInstance.getArguments();
+  const cypressConfigPath =
+    cypressExecutionArguments && cypressExecutionArguments["config-file"]
+      ? path.resolve(appRoot, cypressExecutionArguments["config-file"])
+      : `${appRoot}/cypress.json`;
   const cypressOptions = JSON.parse(
-    fs.readFileSync(`${appRoot}/cypress.json`, "utf-8")
+    fs.readFileSync(cypressConfigPath, "utf-8")
   );
 
   const explorer = cosmiconfig("cypress-cucumber-preprocessor", { sync: true });
diff --git a/package-lock.json b/package-lock.json
index 6841195..6e555c4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4975,6 +4975,11 @@
         "typedarray": "^0.0.6"
       }
     },
+    "connected-domain": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/connected-domain/-/connected-domain-1.0.0.tgz",
+      "integrity": "sha1-v+dyOMdL5FOnnwy2BY3utPI1jpM="
+    },
     "console-browserify": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
@@ -13536,9 +13541,9 @@
       }
     },
     "minimist": {
-      "version": "0.0.8",
-      "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
-      "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+      "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
     },
     "minimist-options": {
       "version": "3.0.2",
@@ -13575,6 +13580,13 @@
       "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
       "requires": {
         "minimist": "0.0.8"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "0.0.8",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+          "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
+        }
       }
     },
     "modify-values": {
@@ -17402,6 +17414,12 @@
         "wordwrap": "~0.0.2"
       },
       "dependencies": {
+        "minimist": {
+          "version": "0.0.10",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
+          "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=",
+          "dev": true
+        },
         "wordwrap": {
           "version": "0.0.3",
           "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
@@ -17896,6 +17914,14 @@
         "sisteransi": "^1.0.3"
       }
     },
+    "ps-node": {
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/ps-node/-/ps-node-0.1.6.tgz",
+      "integrity": "sha1-mvZ6mdex0BMuUaUDCZ04qNKs4sM=",
+      "requires": {
+        "table-parser": "^0.1.3"
+      }
+    },
     "pseudomap": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
@@ -19993,6 +20019,14 @@
         }
       }
     },
+    "table-parser": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/table-parser/-/table-parser-0.1.3.tgz",
+      "integrity": "sha1-BEHPzhallIFoTCfRtaZ/8VpDx7A=",
+      "requires": {
+        "connected-domain": "^1.0.0"
+      }
+    },
     "test-exclude": {
       "version": "5.2.3",
       "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz",
diff --git a/package.json b/package.json
index 84737eb..0e77349 100644
--- a/package.json
+++ b/package.json
@@ -54,6 +54,8 @@
     "gherkin": "^5.1.0",
     "glob": "^7.1.2",
     "js-string-escape": "^1.0.1",
+    "minimist": "^1.2.0",
+    "ps-node": "^0.1.6",
     "through": "^2.3.8"
   },
   "devDependencies": {
@@ -75,6 +77,14 @@
   "jest": {
     "setupFilesAfterEnv": [
       "<rootDir>/lib/testHelpers/setupTestFramework.js"
+    ],
+    "collectCoverage": true,
+    "collectCoverageFrom": [
+      "lib/**/*.js"
+    ],
+    "coveragePathIgnorePatterns": [
+      "node_modules",
+      "<rootDir>/lib/*.test.js"
     ]
   },
   "config": {


Test patch:
diff --git a/lib/stepDefinitionPath.test.js b/lib/stepDefinitionPath.test.js
new file mode 100644
index 0000000..0fcf4fc
--- /dev/null
+++ b/lib/stepDefinitionPath.test.js
@@ -0,0 +1,130 @@
+const fs = require("fs");
+const cosmiconfig = require("cosmiconfig");
+const stepDefinitionPath = require("./stepDefinitionPath.js");
+const cypressExecutionInstance = require("./cypressExecutionInstance");
+
+jest.mock("./cypressExecutionInstance", () => ({
+  getArguments: jest.fn()
+}));
+
+jest.mock("fs", () => ({
+  readFileSync: jest.fn()
+}));
+
+jest.mock("cosmiconfig");
+
+describe("load path from step definitions", () => {
+  beforeEach(() => {
+    cosmiconfig.mockReset();
+    fs.readFileSync.mockReset();
+    cypressExecutionInstance.getArguments.mockReset();
+  });
+
+  test("Should throw error if both nonGlobalStepDefinitions and step_definitions are set in cosmic config", () => {
+    const loadMock = jest.fn().mockReturnValue({
+      config: {
+        nonGlobalStepDefinitions: true,
+        step_definitions: "e2e/step_definitions"
+      }
+    });
+    cosmiconfig.mockReturnValue({
+      load: loadMock
+    });
+    fs.readFileSync.mockReturnValue("{}");
+
+    const errorMessage =
+      "Error! You can't have both step_definitions folder and nonGlobalStepDefinitions setup in cypress-cucumber-preprocessor configuration";
+    expect(stepDefinitionPath).throw(errorMessage);
+  });
+
+  test("should return default path if coscmicconfig and cypress.json has not config properties", () => {
+    const appRoot = process.cwd();
+    cosmiconfig.mockReturnValue({
+      load: jest.fn()
+    });
+    fs.readFileSync.mockReturnValue("{}");
+
+    expect(stepDefinitionPath()).to.equal(
+      `${appRoot}/cypress/support/step_definitions`
+    );
+    expect(fs.readFileSync.mock.calls[0][0]).to.equal(
+      `${appRoot}/cypress.json`
+    );
+  });
+
+  test("should use fileServerFolder from cypress options for backward compability", () => {
+    const appRoot = process.cwd();
+    const loadMock = jest.fn().mockReturnValue({
+      config: {
+        commonPath: "./e2e/step-definitions/common"
+      }
+    });
+    cosmiconfig.mockReturnValue({
+      load: loadMock
+    });
+    fs.readFileSync.mockReturnValue(`{
+      "fileServerFolder": "./e2e"
+    }`);
+
+    expect(stepDefinitionPath()).to.equal(`./e2e/support/step_definitions`);
+    expect(fs.readFileSync.mock.calls[0][0]).to.equal(
+      `${appRoot}/cypress.json`
+    );
+  });
+
+  test("should use config file for cypress when cypress is running with option --config-file", () => {
+    const appRoot = process.cwd();
+    cosmiconfig.mockReturnValue({
+      load: jest.fn()
+    });
+    fs.readFileSync.mockReturnValue(`{
+      "fileServerFolder": "./e2e"
+    }`);
+    cypressExecutionInstance.getArguments.mockReturnValue({
+      "config-file": "./e2e/cypress.json"
+    });
+
+    expect(stepDefinitionPath()).to.equal(`./e2e/support/step_definitions`);
+    expect(fs.readFileSync.mock.calls[0][0]).to.equal(
+      `${appRoot}/e2e/cypress.json`
+    );
+  });
+
+  test("should use nonGlobalStepDefinitions from cosmiconfig", () => {
+    const appRoot = process.cwd();
+    const loadMock = jest.fn().mockReturnValue({
+      config: {
+        nonGlobalStepDefinitions: true
+      }
+    });
+    cosmiconfig.mockReturnValue({
+      load: loadMock
+    });
+    fs.readFileSync.mockReturnValue(`{}`);
+
+    expect(stepDefinitionPath()).to.equal(`${appRoot}/cypress/integration`);
+    expect(fs.readFileSync.mock.calls[0][0]).to.equal(
+      `${appRoot}/cypress.json`
+    );
+  });
+
+  test("should use step_definitions from cosmiconfig", () => {
+    const appRoot = process.cwd();
+    const loadMock = jest.fn().mockReturnValue({
+      config: {
+        step_definitions: "./e2e/support/step-definitions"
+      }
+    });
+    cosmiconfig.mockReturnValue({
+      load: loadMock
+    });
+    fs.readFileSync.mockReturnValue(`{}`);
+
+    expect(stepDefinitionPath()).to.equal(
+      `${appRoot}/e2e/support/step-definitions`
+    );
+    expect(fs.readFileSync.mock.calls[0][0]).to.equal(
+      `${appRoot}/cypress.json`
+    );
+  });
+});