Skip to content

Doesn't work with non-root project folder on Windows #18

New issue

Have a question about this project? No Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “No Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? No Sign in to your account

Closed
ericorruption opened this issue Jun 21, 2019 · 18 comments · Fixed by #162
Closed

Doesn't work with non-root project folder on Windows #18

ericorruption opened this issue Jun 21, 2019 · 18 comments · Fixed by #162
Labels

Comments

@ericorruption
Copy link

First of all, really awesome initiative with this plugin.

My cypress test suite is inside a test folder.
With this plugin, my specs fail with the following message:

CypressError: cy.task('coverageReport') failed with the following error:

> Error: Command failed: nyc report --reporter=html
    at makeError (/Users/xxx/projectname/node_modules/execa/index.js:174:9)
    at Promise.all.then.arr (/Users/xxx/projectname/node_modules/execa/index.js:278:16)
    at <anonymous>

Moving the cypress folder and cypress.json to the root of the project, outside of /test, makes the whole thing work again.

@schl3ck
Copy link

schl3ck commented Aug 1, 2019

I've the same issue, but I can't fix it like @ericorruption suggested, because my client (gui) and server (backend) are seperate repositories and there is currently no way into merging them.

The error I get in the after all section:

CypressError: cy.task('coverageReport') failed with the following error:

> Error: spawn nyc ENOENT
    at notFoundError (C:\Users\xxx\projectname\gui\node_modules\cross-spawn\lib\enoent.js:6:26)
    at verifyENOENT (C:\Users\xxx\projectname\gui\node_modules\cross-spawn\lib\enoent.js:40:16)
    at ChildProcess.cp.emit (C:\Users\xxx\projectname\gui\node_modules\cross-spawn\lib\enoent.js:27:25)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:198:12)

Because this error occurred during a 'after all' hook we are skipping all of the remaining tests.

My guess is that nyc gets executed in the folder where cypress.json resides and therfore hasn't direct access to the source files.
Running the nyc report command in a shell doesn't fail, but ignores the missing source files, so I don't know if that is really the problem...

A little off-topic: The last line in the error message is a little missleading. It looks like it is a generic error for all hooks (before, beforeEach, afterEach, after), but it doesn't make much sense that after the after hook the remaining tests are skipped, because there never won't be any tests remaining.

@schl3ck
Copy link

schl3ck commented Aug 1, 2019

Looks like my error wasn't the same as from @ericorruption. The problem was that nyc wasn't found in my %PATH% variable on my Windows machine.
Since running the command manually missed the files from my server, I decided to rewrite the coverageReport task.

on('task', {
        coverageReport() {
            let commonParentDir = process.cwd();
            const rawCoverageDir = path.join(process.cwd(), '.nyc_output');
            const nycOutput = require(path.join(rawCoverageDir, 'out.json'));
            const allFiles = Object.keys(nycOutput);
            for (const file of allFiles) {
                let p = path.relative(commonParentDir, file);
                if (p.startsWith('..')) {
                    commonParentDir = path.join(commonParentDir, p.match(/^(\.\.[\/\\])+/)[0] + '.');
                }
            }

            let nycOptions = require(path.join(process.cwd(), 'package.json')) || {};
            nycOptions = nycOptions.nyc;

            const reportDir = path.join(process.cwd(), nycOptions['report-dir'] || './coverage')
            const reporter = nycOptions['reporter'] || ['lcov', 'clover', 'json']
            const reporters = Array.isArray(reporter)
                ? reporter.map(name => `--reporter=${name}`)
                : `--reporter=${reporter}`

            let command = path.join(process.cwd(), 'node_modules', '.bin', 'nyc');
            const args = ['report', '--cwd', commonParentDir, '-t', rawCoverageDir, '--report-dir', reportDir].concat(reporters).map((arg) => arg.replace(/ /g, '\\ '));

            command = command + ' ' + args.join(' ');
            // console.log(`executing command for coverageReport: ${command}`);

            return new Promise((resolve, reject) => {
                exec(command, (err, stdout, stderr) => {
                    if (err) reject(err);
                    resolve({stdout, stderr});
                });
            });
        }
    });

It should use the topmost folder as working directory so that all files referenced by .nyc_output/out.json are included. It also respects the nyc settings in package.json like the original coverageReport function.

As execa still made some problems, I dropped it and used the native approach with exec.

Maybe this also fixes @ericorruption's issue? If so, I can make a PR with this change. If not, how does your folder structure look like? Where resides the folder .nyc_output, where is your source code, ...? Maybe like this (with a few things left out)?

`-- project_root
  +-- .nyc_output
  | `-- out.json
  +-- source
  +-- test
  | +-- cypress
  | | `-- ...
  | `-- cypress.json
  `-- package.json

@jrnail23
Copy link

I've got a similar problem, where I've got more than one cypress test suite that need to run separately (integration tests, post-deploy smoke tests, etc.), and my integration tests (and cypress.json file) are at project_root/tests/client/integration, so I run those tests with cypress run --project ./test/client/integration.

I also have the following in my package.json:

  "nyc": {
    "report-dir": "./coverage/cypress"
  }

When I run them, the .nyc_output folder ends up at project_root/tests/client/integration/.nyc_output, and the coverage files end up getting written at project_root/coverage instead of project_root/coverage/cypress.

I also tried adding temp_dir to that config to control where the .nyc_output gets written, but it doesn't seem to respect that.

@jrnail23
Copy link

Just a suggestion to better deal with the issue of multiple cypress projects and/or those which have cypress.json files in nested locations (not in project root):
Would it make sense to just add nyc config options to the cypress config (cypress.json), like what already exists for collecting server-side coverage (env.codeCoverage.url)?

@bahmutov
Copy link
Contributor

bahmutov commented Sep 4, 2019

@ericorruption can you try plugin v1.10.1 with your situation? I think I have recreated it in bahmutov/cy-nested-code-coverage#1

For other issues, where it cannot find nyc for example, I would need accurate reproduction, because at least on Mac terminal, it finds the nyc in parent folders just fine.

@schl3ck
Copy link

schl3ck commented Sep 4, 2019

For other issues, where it cannot find nyc for example, I would need accurate reproduction, because at least on Mac terminal, it finds the nyc in parent folders just fine.

It can't find nyc because I'm on Windows and have installed it locally in the project. It places the executable in node_modules/.bin/nyc but it doesn't add that path to the system PATH variable and therfore Windows can't find it if I just type nyc in the console.

To reproduce, (not tested, but I think it should behave the same) clone your repo cypress-io/cypress-example-todomvc-redux on a Windows PC and make sure that nyc is not installed globally, but only locally in the project.
Open the command prompt cmd.exe in the project root folder and type nyc. If it writes something like The command "nyc" is either missspelled or could not be found, then you have the right setup.
Now, when running the tests in the test runner interface, the after hook should fail with my error message from here.
If you tell the plugin to search the executable in node_modules/.bin/ then it works again.

@bahmutov
Copy link
Contributor

bahmutov commented Sep 4, 2019

@schl3ck since I don't have access to a Windows machine, I wonder why execa would find nyc in the higher folder on Mac, but not on Windows. Might be NPM path difference between the platforms?

So, since I never install tools globally (bad practice), can I ask something:

When you clone and install cypress-io/cypress-example-todomvc-redux on Windows, then nyc is linked inside node_modules/.bin right? And you can things like npx nyc --help without installing it again?

@schl3ck
Copy link

schl3ck commented Sep 9, 2019

When you clone and install cypress-io/cypress-example-todomvc-redux on Windows, then nyc is linked inside node_modules/.bin right? And you can things like npx nyc --help without installing it again?

@bahmutov Yes, that's right (I had to install npx seperatly, because I use node v6).

I've not tested it now, because I need node v6 for my work (the example needs node v12) and on Windows there is not an official nvm... There is one, but I already had some problems with it...

@bahmutov bahmutov changed the title Doesn't work with non-root project folder Doesn't work with non-root project folder on Windows Sep 10, 2019
@davojta
Copy link

davojta commented Nov 15, 2019

I have the same error on Mac OS. But yesterday the code was working. I think it might be connected with my tests in /integration-tests/<cypress_folders path

@cellog
Copy link

cellog commented Jan 3, 2020

EDIT: in my case, nyc had been accidentally removed, so this can be a cause - it actually wasn't there :)

The same issue happens with yarn workspaces, where nyc is installed in a higher folder.

This is on Mac OS X

@jrnail23
Copy link

Just dropping by to bump this issue again, as I'm finally having to deal with it again #18 (comment). It would be great if the plugin allowed for configurable folder structures and config locations, etc.

@bahmutov
Copy link
Contributor

Can you try using version https://github.com/cypress-io/code-coverage/releases/tag/v1.14.0 of this plugin - it now should discover nyc even if it was installed somewhere up the folder chain.

@jrnail23
Copy link

it's not that it can't find nyc, it's that when your cypress.json is in a nested location, the working directory ends up being that same nested location. The task file assumes your package.json file is in the working directory, so as a result, it can't find the package.json file (and thus ignores any configuration you've set in there).
TBH, it would be great to be able to set up separate nyc configurations per project (nested location) -- right now, the package.json-based config ends up being global, so it's tricky if you want to write your coverage output files to different report dirs for each project.

@jrnail23
Copy link

jrnail23 commented Mar 13, 2020

FYI, as a workaround, I've had to extract project-specific cypress config files in my project root (although I'd really prefer to have those co-located with their respective cypress projects), as cypress.my-nested-project.json, and I'm invoking via cypress run --config-file cypress.my-nested-project.json.

I was previously using cypress run --project tests/my-nested-project, with a cypress.json located in tests/my-nested-project, and that's when the code-coverage plugin can't find the package.json file.

@bahmutov
Copy link
Contributor

Hmm @jrnail23 this seems like a separate issue from the original (nyc location). Please open a new issue with folder structure described in enough detail so I can understand it - or better a public repo available that shows the problem

@bahmutov
Copy link
Contributor

Hi everyone,

I have a beta release of Cypress that uses nyc as its own dependency and does not call it via bin folder. Could you try @cypress/code-coverage@2.0.0-beta.1 and comment if it solves your problem?

@schl3ck
Copy link

schl3ck commented Mar 30, 2020

@bahmutov Worked for me!

@bahmutov
Copy link
Contributor

🎉 This issue has been resolved in version 2.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

No Sign up for free to join this conversation on GitHub. Already have an account? No Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants