cypress
cypress copied to clipboard
`after:run` task cwd changed after 9 -> 10
Current behavior
In after:run
task, Cypress 10 is using the location of configuration file as current working directory. In Cypress 9 it is the root of project, or where the actual cypress run
command is run.
After migrating from Cypress 9 to 10 some plugins I'm using started failing. They are relying on Cypress 9's functionality when it comes to current working directory, e.g. when reading files from disk.
I keep my cypress.config.ts
in a separate folder - not in the project root.
/workspaces/vite-everything
└── config
└── cypress
├── component-index.html
├── cypress.config.ts
├── support.component.ts
└── support.ts
cypress run --component --config-file config/cypress/cypress.config.ts
// config/cypress/cypress.config.ts
setupNodeEvents(on) {
on('after:run', () => {
console.log('[after:run] cwd is', process.cwd());
// > [after:run] cwd is /workspaces/vite-everything/config/cypress
});
},
Desired behavior
The current working directory should match with Cypress 9.
/workspaces/vite-everything
└── config
└── cypress
├── cypress.json
├── plugins.ts
└── support.ts
cypress run-ct --config-file config/cypress/cypress.json
// config/cypress/plugins.ts
on('after:run', () => {
console.log('[after:run] cwd is', process.cwd());
// [after:run] cwd is /workspaces/vite-everything
});
Test code to reproduce
I run into this error in separate closed source project but here is another project for reproducing the issue:
- https://github.com/AriPerkkio/vite-everything
- Branch
test/cypress-9-after-run-cwd
for previous functionality: https://github.com/AriPerkkio/vite-everything/commit/0e282c86eefa3766f25b374f5562518e6ecce3db - Branch
test/cypress-10-after-run-cwd
for current funcionality: https://github.com/AriPerkkio/vite-everything/commit/dbead4b1c90a107f2dbea6cbea454d3ccc89e5da
yarn # Install dependencies
yarn test:component # Run Cypress Component Test Runner
Cypress Version
10.3.0
Other
No response
I've noticed the same incorrect working directory in before:run
as well fwiw (in Cy 10).
I was able to reproduce this with the example repository provided
Seeing this as well. It is impacting the use of @cypress/code-coverage
, since it tries to read the nyc
config from package.json
, but is now looking for that within the Cypress config dir, rather than project root as before.
I ran with DEBUG=cypress:*
and here's what I see:
-
Initially, I see it passing the correct
cwd
:cypress:cli spawn args [ '--no-sandbox', '--', '--run-project', '/Users/pedemonte/projects/myproject/client', '--config-file', 'cypress/config/ci.config.ts', '--testing-type', 'e2e', '--cwd', '/Users/pedemonte/projects/myproject/client', '--userNodePath', '/Users/pedemonte/.nvm/versions/node/v16.13.1/bin/node', '--userNodeVersion', '16.13.1' ] { detached: false, stdio: [ 'inherit', 'inherit', 'pipe' ] } +7ms
-
Later, it switches to the config dir (although
--projectRoot
is correct):cypress:lifecycle:ProjectConfigIpc fork child process { CHILD_PROCESS_FILE_PATH: '/Users/pedemonte/Library/Caches/Cypress/10.4.0/Cypress.app/Contents/Resources/app/packages/server/lib/plugins/child/require_async_child.js', configProcessArgs: [ '--projectRoot', '/Users/pedemonte/projects/myproject/client', '--file', '/Users/pedemonte/projects/myproject/client/cypress/config/ci.config.ts' ], childOptions: { stdio: 'pipe', cwd: '/Users/pedemonte/projects/myproject/client/cypress/config', execPath: '/Users/pedemonte/.nvm/versions/node/v16.13.1/bin/node' } } +0ms
-
Finally, a custom
console.log
in a cypress plugin shows:processWorkingDirectory = /Users/pedemonte/projects/myproject/client/cypress/config
It appears that this is an intentional (but undocumented?) change in 10.0 (see app-lifecycle.md), wherein the config file is now run in a separate process, with cwd
changed to the config file's parent directory (rather than the project root). That would mean that plugins such as @cypress/code-coverage
which expect to run within the project root will need to be updated.
@jhpedemonte I also run into this issue when using @cypress/code-coverage
. But this also came up with cypress-sonarqube-reporter
. In both cases I was able to add work-arounds by prefixing all configurable paths with ../../
.
I'm not familiar with internals of Cypress but I think this is not intentional. A simple process.chdir()
on Cypress's side could fix this.
As per #23209 one of the issue in this ticket indicates that this behavior is probably not intended. ie. the default value for config component.indexHtmlFile
is broken as cypress will try to resolve cypress/cypress/support/component-index.html
rather than just cypress/support/component-index.html
(cypress
dir added twice in the path).
FYI, my current workaround (until this is fixed either here or by plugins) is the following:
function requirePluginWithProjectRoot(pluginPath, on, config) {
if (config.projectRoot) {
const cwd = process.cwd();
process.chdir(config.projectRoot);
require(pluginPath)(on, config);
// revert to previous cwd
process.chdir(cwd);
return;
}
throw Error("config.projectRoot doesn't exist");
}
I only invoke this for @cypress/code-coverage
, which is the only plugin I use that is affected by this:
requirePluginWithProjectRoot('@cypress/code-coverage/task', on, config);
@jhpedemonte maybe it is simpler to keep the config file at the root until this is fixed?
@gsouf that's best solution for now.
I really want to keep Cypress configuration file under a sub directory config/
since that's where I store configuration files for all sorts of tooling. So as a work-around I'm now using a separate configuration file in project root which simply imports the actual config. This way I don't need to apply any other work-arounds, e.g. prefixing all paths with .../../
or running process.chdir()
anywhere.
<project-root>
├── cypress.config.ts
└── config
└── cypress
└── cypress.config.ts
// TODO: Remove when https://github.com/cypress-io/cypress/issues/22689 is fixed
export { default } from './config/cypress/cypress.config';
any updates?
@MorisR nope, whole --config-file
is still broken in latest 13.3.0
release. I've found another work-around which does not require creating root level cypress config as in https://github.com/cypress-io/cypress/issues/22689#issuecomment-1211732120.
NPM adds INIT_CWD
environment variable which can be used to fix this bug:
// Work-around for https://github.com/cypress-io/cypress/issues/22689
if (!process.env.INIT_CWD) throw new Error('Missing INIT_CWD from npm');
process.chdir(process.env.INIT_CWD);
I've been adding these lines to every single cypress.config.ts
that are not in the root of the project:
<root>
├── package.json
├── src
└── test
|
├── component
| ├── component-index.html
| ├── cypress.config.ts # Work-around added here
| └── support.ts
|
├── end-to-end
| ├── cypress.config.ts # also here
| ├── some-tests-1
| └── some-tests-2
|
├── integration
| ├── cypress.config.ts # and here
| ├── some-tests-1
| └── some-tests-1
|
└── unit
└── vitest.setup.ts