cypress-io / cypress

Fast, easy and reliable testing for anything that runs in a browser.
https://cypress.io
MIT License
46.43k stars 3.14k forks source link

Error: EINVAL: invalid argument, mkdir on windows for cypress + windows + Angular project #8599

Open pavandixit93 opened 3 years ago

pavandixit93 commented 3 years ago

Current behavior:

When cypres@3.8.3 is run on windows in Angular project, i am getting this type of error when i click on any test specs and try to run and capture image snapshot: Error: EINVAL: invalid argument, mkdir 'C:\Users\rocks\AppData\Roaming\Cypress\cy\production\projects\styleguide-e2e-a8ba09f50d81ec188e3b12528503dca9\bundles\C:\Users\rocks\project\torque\styleguide\cypress\support

Cypress cache folder is: C:\Users\rocks\AppData\Roaming\Cypress\cy\production\projects for windows.

Error1 Error2

Desired behavior:

It should not throw any error on windows system.

Test code to reproduce

Package.json

{
"cypress": "3.8.3",

"cypress-axe": "^0.8.1",

"cypress-cucumber-preprocessor": "^2.0.1",

"cypress-image-snapshot": "^3.1.1",
}

NPM command to open cypress:

npm run nx-high-memory -- e2e styleguide-e2e --watch

cypress.josn config file

{
  "video": false,

  "testFiles": "**/*.{feature,features}",

  "fixturesFolder": "../../cypress/fixtures",

  "integrationFolder": "../../cypress/integration",

  "pluginsFile": "../../cypress/plugins/index",

  "supportFile": "../../cypress/support/index",

  "screenshotsFolder": "../../cypress/screenshots"
}

Versions

"cypress": "3.8.3",

"cypress-axe": "^0.8.1",

"cypress-cucumber-preprocessor": "^2.0.1",

"cypress-image-snapshot": "^3.1.1",

"chrome": "Version 85.0.4183.102 (Official Build) (64-bit)"

"windows": 10
bahmutov commented 3 years ago

Can you please try the latest Cypress version v5.2.0, Cypress v3 is a really old version.

andreilaptev1 commented 3 years ago

Having the same issue using version 5.0.0

andreilaptev1 commented 3 years ago

Tested version 5.2.0, issue not resolved

pavandixit93 commented 3 years ago

@andreilaptev1 Thank you for confirmation, I was going to test using mentioned version EOD, I will skip then. It looks like issue is due to mkdir or mkdirp library used inside Cypress.

andreilaptev1 commented 3 years ago

@pavandixit93 probably yes. The weird thing is Mac users do not face this issue in our app. Furthermore, once I create new Cypress project outside of main app, it works

bahmutov commented 3 years ago

Please could you create an example repo showing this problem that we can look at?

andreilaptev1 commented 3 years ago

Once I create an example repo, it works fine. The issue is Cypress does not work on our company app, and I may not share code. Thinking it might has something to do with internal setup, but not sure

From: Gleb Bahmutov notifications@github.com Sent: September 22, 2020 10:15 AM To: cypress-io/cypress cypress@noreply.github.com Cc: Andrei Laptev1 Andrei.Laptev1@rci.rogers.com; Mention mention@noreply.github.com Subject: Re: [cypress-io/cypress] Error: EINVAL: invalid argument, mkdir on windows for cypress + windows + Angular project (#8599)

Please could you create an example repo showing this problem that we can look at?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/cypress-io/cypress/issues/8599#issuecomment-696749969, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AN6H33FR3QZSPSWI6I3UIRLSHCWNVANCNFSM4RP4KLWA.


This communication is confidential. We only send and receive email on the basis of the terms set out at www.rogers.com/web/content/emailnoticehttp://www.rogers.com/web/content/emailnotice

Ce message est confidentiel. Notre transmission et réception de courriels se fait strictement suivant les modalités énoncées dans l’avis publié à www.rogers.com/aviscourriel http://www.rogers.com/aviscourriel


andreilaptev1 commented 3 years ago

Solution found: in cypress.json I set up supportFile as "false" and magic happened

pavandixit93 commented 3 years ago

@andreilaptev1 Thanks for the workaround, its working now. But is there any side effect if i set supportFile : false in json file. Any idea about that? Did you get any error?

When i tried by setting supportFile: false, test ran successfully but i got one error, PFA. TypeError: cy.get(...).matchImageSnapshot is not a function

image

andreilaptev1 commented 3 years ago

@pavandixit93 yep, I've seen that. In this case, code doesn't recognize functions from imported modules. So far having no answer, will continue investigation. Should you find a solution first, please share

jennifer-shehane commented 3 years ago

Could you include the code from your support.js file? Seems like the issue may be coming from something inside that. Thanks!

pavandixit93 commented 3 years ago

@jennifer-shehane We dont have support.js, but we have index.js file inside /support folder which has below lines of code. Let me know if you need anything else.

import 'cypress-axe';
import './commands';

And in ./commands we have written like this...

import * as axe from 'axe-core';
import { addMatchImageSnapshotCommand } from 'cypress-image-snapshot/command';

Cypress.Commands.add('injectAxe', () => {
  cy.window({ log: false }).then(window => {
    window.axe = axe;
  });
});

addMatchImageSnapshotCommand({
  failureThreshold: 0.05,
  failureThresholdType: 'percent',
  customDiffConfig: { threshold: 0.05 },
  capture: 'viewport'
});

Cypress.Commands.overwrite('matchImageSnapshot', (originalFn, subject, name, options) => {
  if (Cypress.browser.isHeadless) {
    return originalFn(subject, name, options);
  }
  return cy.log('No screenshot taken when headed');
});
andreilaptev1 commented 3 years ago

We even do not have this code, just

import './commands'; import '@cypress/code-coverage/support';

Later this .ts file is being recompiled to .js and put into /dist folder

Esskla commented 3 years ago

Currently we are facing the same issue on windows. The problem is fixed if we set supportFile: false but in this case we need our support file. It is executing some beforEach commands to clear our wiremock scenarios and requests.

We are using cypress 5.0.0 and node 12.18.3

artkoselev commented 3 years ago

I am able to reproduce this by setting a relative supportFile path in config

Setup Reproduction project: https://github.com/artkoselev/cypress8599 OS: Windows Cypress package version: 6.2.1 Cypress binary version: 6.2.1 Electron version: 11.1.1 Bundled Node version: 12.18.3

Reproduction steps

  1. Clone repository
  2. call 'npm install'
  3. call 'npm test'

Expected: Cypress visits cypress.io page Actual: Error thrown - Error: EINVAL: invalid argument, mkdir 'C:\Users\{user}\AppData\Roaming\Cypress\cy\production\projects\nested-0b20f090537cddae1cfb3da2204e4eae\bundles\C:\Users\{user}\cypress8599\support

Notes: npm test calls npx cypress run --project nested and nested project contains entry "supportFile": "../support/index.js". From the error message it seems that the path gets converted to absolute which results in an invalid argument for 'mkdir' - ... bundles\C:\Users\{user}\ ...

akselil commented 3 years ago

I am able to reproduce this by setting a relative supportFile path in config

We found a workaround for this issue:

Create nested/cypressSupportForWindows.js file with content:

import '../support/index';

and then change nested/cypress.json to point that file

“supportFile”: “cypressSupportForWindows.js”,
adkr commented 3 years ago

I have the same issue. My project configuration requires to point supportFile as relative path (../../someFolder/index.js) and this causes an error Error: EINVAL: invalid argument, mkdir 'C:\ (...) D:\ (...). When I remove functionality from test which reqires code from supportFile and set supportFIle to false then everything works fine.

SoftwareDesign-Solution commented 2 years ago

I have the same problem.

plugins\index.js ` /// // // This example plugins/index.js can be used to load plugins // // You can change the location of this file or turn off loading // the plugins file with the 'pluginsFile' configuration option. // // You can read more here: // https://on.cypress.io/plugins-guide //

// This function is called when a project is opened or re-opened (e.g. due to // the project's config changing)

/**

module.exports = (on, config) => { on("file:preprocessor", webpack(options)); return Object.assign({}, config, { fixturesFolder: "cypress/fixtures", integrationFolder: "cypress/integration", screenshotsFolder: "cypress/screenshots", videosFolder: "cypress/videos", supportFile: false }); }; `

cypress.json { }

package.json

{ "name": "uitesting_cypress", "version": "0.1.0", "private": true, "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "test:unit": "vue-cli-service test:unit", "lint": "vue-cli-service lint", "test:components": "vue-cli-service test:components", "uitest": "vue-cli-service serve & cypress open" }, "dependencies": { "@types/uuid": "^8.3.1", "axios": "^0.24.0", "core-js": "^3.6.5", "open": "^8.4.0", "uuid": "^8.3.2", "vue": "^2.6.11", "vue-class-component": "^7.2.3", "vue-property-decorator": "^9.1.2", "vue-router": "^3.2.0", "vuetify": "^2.4.0" }, "devDependencies": { "@cypress/vue": "*", "@cypress/webpack-dev-server": "^1.7.0", "@cypress/webpack-preprocessor": "^5.10.0", "@types/jest": "^24.0.19", "@typescript-eslint/eslint-plugin": "^4.18.0", "@typescript-eslint/parser": "^4.18.0", "@vue/cli-plugin-babel": "~4.5.0", "@vue/cli-plugin-eslint": "~4.5.0", "@vue/cli-plugin-router": "~4.5.0", "@vue/cli-plugin-typescript": "~4.5.0", "@vue/cli-plugin-unit-jest": "~4.5.0", "@vue/cli-service": "~4.5.0", "@vue/eslint-config-typescript": "^7.0.0", "@vue/test-utils": "^1.0.3", "cypress": "^9.1.0", "eslint": "^6.7.2", "eslint-plugin-vue": "^6.2.2", "sass": "~1.32.0", "sass-loader": "^10.0.0", "typescript": "~4.1.5", "vue-cli-plugin-cypress-experimental": "~1.2.0", "vue-cli-plugin-vuetify": "~2.4.3", "vue-loader": "^15.9.8", "vue-template-compiler": "^2.6.11", "vuetify-loader": "^1.7.0" } }

roldengarm commented 2 years ago

I had the same problem with a NX mono repo. In our case, it was caused by having cypress.json inside a subfolder; by default it's at the root level of the e2e project.

Leif-Frederiksen commented 2 years ago

I had the same problem. In my case I could fix it by renaming the root folder of my project. It had spaces in the folder name represented at %20. When I changed the %20 to actual spaces in the fole name, it started to work.

prantlf commented 1 year ago

I got the same error for a project with the root at C:\Users\ferdipr\Sources\ot-web-components and the structure:

src/...      sources and e2e tests
cypress/...  cypress config, support, plugins

┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Cypress:        10.8.0                                                                         │
│ Browser:        Electron 102 (headless)                                                        │
│ Node Version:   v16.13.1 (C:\Program Files\nodejs\node.exe)                                    │
│ Specs:          13 found (button.e2e.js, checkboxgroup.e2e.js, inline-edit-container.e2e.js, i │
│                 nput.e2e.js, link.e2e.js, menu.e2e.js, multivalue.e2e.js, radiogroup.e2e.js, s │
│                 earchfield.e2e.js, select.e2e.js, textarea.e2e.js, toggle.e2e.js, example.e2e. │
│                 js)                                                                            │
│ Searched:       ../src/**/*.e2e.js                                                             │
└────────────────────────────────────────────────────────────────────────────────────────────────┘

Oops...we found an error preparing this test file:

  > ..\src\components\button\e2e\button.e2e.js

The error was:

Error: EINVAL: invalid argument, mkdir 'C:\Users\ferdipr\AppData\Roaming\Cypress\cy\production\projects\cypress-f5ab6fa9dd720ce21f40904142e2a66b\bundles\C:\Users\ferdipr\Sources\ot-web-components\src\components\button\e2e'

This occurred while Cypress was compiling and bundling your test code. This is usually caused by:

- A missing file or dependency
- A syntax error in the file or one of its dependencies

Fix the error in your code and re-run your tests.

  (Results)

  ┌────────────────────────────────────────────────────────────────────────────────────────────────┐
  │ Tests:        0                                                                                │
  │ Passing:      0                                                                                │
  │ Failing:      1                                                                                │
  │ Pending:      0                                                                                │
  │ Skipped:      0                                                                                │
  │ Screenshots:  0                                                                                │
  │ Video:        false                                                                            │
  │ Duration:     0 seconds                                                                        │
  │ Spec Ran:     button.e2e.js                                                                    │
  └────────────────────────────────────────────────────────────────────────────────────────────────┘

I suspect that Cypress or Webpack concatenates paths in a wrong way - two absolute paths were joined according to the error message.

Is it possible to print a stacktrace to find out who calls the mkdir with an invalid path? It's probably something in webpack - is it possible to print the complete webpack configuration?

This information isn't available even after setting the environment variable DEBUG=cypress:*.

cypress:webpack webpackOptions: { mode: 'development', node: { global: true, __filename: true, __dirname: true }, module: { rules: [ [Object], [Object], [Object], [Object] ] }, resolve: { extensions: [ '.js',     '.json', '.jsx',    '.mjs', '.coffee', '.ts', '.tsx' ], alias: { child_process: 'C:\\Users\\ferdipr\\AppData\\Local\\Cypress\\Cache\\10.8.0\\Cypress\\resources\\app\\node_modules\\@packages\\server\\node_modules\\@cypress\\webpack-batteries-included-preprocessor\\empty.js', cluster: 'C:\\Users\\ferdipr\\AppData\\Local\\Cypress\\Cache\\10.8.0\\Cypress\\resources\\app\\node_modules\\@packages\\server\\node_modules\\@cypress\\webpack-batteries-included-preprocessor\\empty.js', console: 'C:\\Users\\ferdipr\\AppData\\Local\\Cypress\\Cache\\10.8.0\\Cypress\\resources\\app\\node_modules\\@packages\\server\\node_modules\\@cypress\\webpack-batteries-included-preprocessor\\empty.js', dgram: 'C:\\Users\\ferdipr\\AppData\\Local\\Cypress\\Cache\\10.8.0\\Cypress\\resources\\app\\node_modules\\@packages\\server\\node_modules\\@cypress\\webpack-batteries-included-preprocessor\\empty.js', dns: 'C:\\Users\\ferdipr\\AppData\\Local\\Cypress\\Cache\\10.8.0\\Cypress\\resources\\app\\node_modules\\@packages\\server\\node_modules\\@cypress\\webpack-batteries-included-preprocessor\\empty.js', fs: 'C:\\Users\\ferdipr\\AppData\\Local\\Cypress\\Cache\\10.8.0\\Cypress\\resources\\app\\node_modules\\@packages\\server\\node_modules\\@cypress\\webpack-batteries-included-preprocessor\\empty.js', http2: 'C:\\Users\\ferdipr\\AppData\\Local\\Cypress\\Cache\\10.8.0\\Cypress\\resources\\app\\node_modules\\@packages\\server\\node_modules\\@cypress\\webpack-batteries-included-preprocessor\\empty.js', inspector: 'C:\\Users\\ferdipr\\AppData\\Local\\Cypress\\Cache\\10.8.0\\Cypress\\resources\\app\\node_modules\\@packages\\server\\node_modules\\@cypress\\webpack-batteries-included-preprocessor\\empty.js', module: 'C:\\Users\\ferdipr\\AppData\\Local\\Cypress\\Cache\\10.8.0\\Cypress\\resources\\app\\node_modules\\@packages\\server\\node_modules\\@cypress\\webpack-batteries-included-preprocessor\\empty.js', net: 'C:\\Users\\ferdipr\\AppData\\Local\\Cypress\\Cache\\10.8.0\\Cypress\\resources\\app\\node_modules\\@packages\\server\\node_modules\\@cypress\\webpack-batteries-included-preprocessor\\empty.js', perf_hooks: 'C:\\Users\\ferdipr\\AppData\\Local\\Cypress\\Cache\\10.8.0\\Cypress\\resources\\app\\node_modules\\@packages\\server\\node_modules\\@cypress\\webpack-batteries-included-preprocessor\\empty.js', readline: 'C:\\Users\\ferdipr\\AppData\\Local\\Cypress\\Cache\\10.8.0\\Cypress\\resources\\app\\node_modules\\@packages\\server\\node_modules\\@cypress\\webpack-batteries-included-preprocessor\\empty.js', repl: 'C:\\Users\\ferdipr\\AppData\\Local\\Cypress\\Cache\\10.8.0\\Cypress\\resources\\app\\node_modules\\@packages\\server\\node_modules\\@cypress\\webpack-batteries-included-preprocessor\\empty.js', tls: 'C:\\Users\\ferdipr\\AppData\\Local\\Cypress\\Cache\\10.8.0\\Cypress\\resources\\app\\node_modules\\@packages\\server\\node_modules\\@cypress\\webpack-batteries-included-preprocessor\\empty.js' }, plugins: [ [TsconfigPathsPlugin] ] }, entry: [ 'C:\\Users\\ferdipr\\Sources\\ot-web-components\\cypress\\support\\index.js' ], output: { path: 'C:\\Users\\ferdipr\\AppData\\Roaming\\Cypress\\cy\\production\\projects\\cypress-f5ab6fa9dd720ce21f40904142e2a66b\\bundles\\support', filename: 'index.js' }, devtool: 'inline-source-map' } +0ms
cypress:webpack watchOptions: {} +7ms
cypress:webpack typescript: C:\Users\ferdipr\Sources\ot-web-components\node_modules\typescript\lib\typescript.js +0ms
cypress:webpack input: C:\Users\ferdipr\Sources\ot-web-components\cypress\support\index.js +0ms
cypress:webpack output: C:\Users\ferdipr\AppData\Roaming\Cypress\cy\production\projects\cypress-f5ab6fa9dd720ce21f40904142e2a66b\bundles\support\index.js +0ms
cypress:webpack handle - had error EINVAL: invalid argument, mkdir 'C:\Users\ferdipr\AppData\Roaming\Cypress\cy\production\projects\cypress-f5ab6fa9dd720ce21f40904142e2a66b\bundles\C:\Users\ferdipr\Sources\ot-web-components\src\components\button\e2e' +2s
cypress:webpack errored bundling C:\Users\ferdipr\AppData\Roaming\Cypress\cy\production\projects\cypress-f5ab6fa9dd720ce21f40904142e2a66b\bundles\C:\Users\ferdipr\Sources\ot-web-components\src\components\button\e2e\button.e2e.js EINVAL: invalid argument, mkdir 'C:\Users\ferdipr\AppData\Roaming\Cypress\cy\production\projects\cypress-f5ab6fa9dd720ce21f40904142e2a66b\bundles\C:\Users\ferdipr\Sources\ot-web-components\src\components\button\e2e' +1ms
ocombe commented 1 year ago

I managed to track the issue to this part of the code: https://github.com/cypress-io/cypress/blob/a5ec234005fead97f6cfdf611abf8d9f4ad0565d/packages/server/lib/plugins/preprocessor.js#L72-L78

If for some reason the test file is not part of the project root, then this code will fail to remove the base path of the spec file (when it is bundled by webpack and copied to cypress work folder), I think that by default the project root is based on the location of the cypress config file, or based on where you ran the cli command to start it.

To fix that, just set the config option project to the root folder where your spec is and it works just fine !

ausi commented 12 months ago

This issue still occurs on Windows. It can be reproduced by putting support files or spec files outside of the project root directory.

prantlf commented 12 months ago

I think that this problem can be reproduced on any platform. I reproduced it on ~Linux, Mac and~ Windows, as I wrote above.

If you decide to maintain dependencies and configuration of your E2E tests separate from your build directory, you will face the bug described by this issue.

A workaround: create a symlink to the test and source files inside the Cypress directory, and use the symlink in the Cypress configuration. Cypress will see everything apparently inside its directory and will work well.

src/...      sources and e2e tests
cypress/...  cypress config, support, plugins

cypress/src --> ../src symbolic link

EDITED: The problem occurs only on Windows.

lmiller1990 commented 12 months ago

@prantlf I tried to reproduce on MacOS and Linux using your information:

https://github.com/lmiller1990/cypress-test-tiny/compare/master...lmiller1990:cypress-test-tiny:issue-8599?expand=1

Specifically: https://github.com/lmiller1990/cypress-test-tiny/compare/master...lmiller1990:cypress-test-tiny:issue-8599?expand=1#diff-7ae45ad102eab3b6d7e7896acd08c427a9b25b346470d7bc6507b6481575d519R7

I put my support file outside my project directory, but it still loads. I did not try windows yet. Am I understanding this correctly?

ausi commented 12 months ago

I put my support file outside my project directory, but it still loads. I did not try windows yet.

The same happend with us. The identical setup (support file outside project) worked on linux and macOS, but it did not work on Windows.

prantlf commented 12 months ago

Oh, I'm sorry, @lmiller1990. The problem occurred on Windows only. I tried the workaround @ocombe pointed out, but it didn't help me. It's been some time and I can't remember the details any more.

The Cypress configuration is in the project root in cypress-test-tiny:

/cypress/e2e
/cypress/support
cypress.config.js
package.json

My project has Cypress completely separated from the build:

/src/some-component/e2e
package.json for build
/cypress/support
/cypress/cypress.config.js
/cypress/package.json for Cypress
lmiller1990 commented 11 months ago

I will help you fix this but trying to reproduce the issue based on snippets and comments is a bit time consuming, can you please upload a repo I can clone and reproduce the issue? That will let me spend more time finding a fix. Thanks!

ausi commented 11 months ago

Can be reproduced with the following repo: https://github.com/ausi/cypress-issue-8599

git clone git@github.com:ausi/cypress-issue-8599.git
cd cypress-issue-8599
cd subdirectory
npm install
npx cypress run

This results in the following output (only on Windows):

Oops...we found an error preparing this test file:

  > ..\support.js

The error was:

Error: EINVAL: invalid argument, mkdir 'C:\Users\████\AppData\Roaming\Cypress\cy\production\projects\subdirectory-8d97a5303e393e4931bd1dd983377a82\bundles\C:\Users\████\Desktop\cypress-issue-8599'
lmiller1990 commented 11 months ago

Thank you!

niekvandael commented 10 months ago

We are experiencing the same issue on Windows. Is there any follow-up planned?

lmiller1990 commented 10 months ago

I am not able to allocate bandwidth to fix this one right now. I'd recommend using a work around in the meantime, unless you are able to contribute a fix.

briangleeson commented 1 month ago

Ran into this problem yesterday after splitting up our codebase into two repos. After much experimentation with projectRoot and other suggestions above, the only one that I could get working was to create a symlink as suggested by @prantlf: https://github.com/cypress-io/cypress/issues/8599#issuecomment-1634777106

Structure:

our-tests/cypress/tests/...   // test spec files
common/cypress/...            // cypress config, support, plugins

common/cypress/tests --> our-tests/cypress/tests   // symbolic link

Example symlink command:

mklink /D "C:/Snaps/common/cypress/tests" "C:/Snaps/our-tests/cypress/tests"
gustavo-almeida commented 1 month ago

Has anyone tried using Windows WSL?

prantlf commented 1 month ago

I suspect that you'd have to use the headless mode only. You wouldn't be able to use Cypress in the windows mode.

I tried configuring X.Org once and using an X-Server on Windows. Not with Cypress, but with Chrome and VS Code. The convenience of the work was a lot worse than with the native Windows applications.

Since WSL2 was released, the performance of the filesystem has improved and the remote features too. But not UI. WSL wasn't designed for running UI applications.

gustavo-almeida commented 1 month ago

Never mind, it should work well since it's a cross-platform tool.

In my case, I have a project with two NPM workspaces, like a monorepo. Both have their own configuration file and plugins, but point to the same support and spec files on the project root (../cypress/e2e/*, ../cypress/support/*).

It works flawlessly on Mac and Linux, but this week a colleague found this error on Windows. I'm trying the symlink approach, but I don't have a Windows computer to test. I have to keep in contact with this colleague, which is not working well.

gustavo-almeida commented 1 month ago

Ok, the symlink worked for me. But since I have to keep the project working on Mac and Linux, I've decided to do some more work.

This is my project structure today using npm workspaces:

├── cypress │ ├── e2e │ │ ├── spec1.cy.js │ │ ├── spec2.cy.js │ │ └── ... │ ├── support │ ├── videos │ └── ... │ ├── cypress-one │ └── cypress.config.js │ ├── cypress-two │ └── cypress.config.js └── ...

I added a file called setup-symlinks.js on root to create the symlinks:

const fs = require("fs");
const path = require("path");

function createSymlink(target, path) {
  try {
    if (!fs.existsSync(path)) {
      fs.symlinkSync(target, path, "junction");
      console.log(`Created symlink: ${path} -> ${target}`);
    } else {
      console.log(`Symlink already exists: ${path}`);
    }
  } catch (err) {
    console.error(`Error creating symlink: ${err.message}`);
  }
}

if (process.platform === "win32") {
  const projectRoot = path.resolve(__dirname);
  const e2ePath = path.join(projectRoot, "cypress");
  const cypressOneLink = path.join(projectRoot, "cypress-one", "cypress");
  const cypressTwoLink = path.join(projectRoot, "cypress-two", "cypress");

  createSymlink(e2ePath, cypressOneLink);
  createSymlink(e2ePath, cypressTwoLink);
} else {
  console.log("No symlinks needed on this OS.");
}

Added a script to package-json (also on root):

  "scripts": {
    "postinstall": "node setup-symlinks.js"
  },

Updated both config files with dynamic configuration of specs and support folders (for cross-platform compatibility):

  ...
  e2e: {
    specPattern:
      process.platform === "win32"
        ? "cypress/e2e/**/*.cy.js"
        : "../cypress/e2e/**/*.cy.js",
    supportFile:
      process.platform === "win32"
        ? "cypress/support/index.js"
        : "../cypress/support/index.js",
        ...

And (I didn't know that), but the symlink folders should be added to .gitignore:

cypress-one/cypress
cypress-two/cypress

Updated readme for Windows users

npm install
npm run postinstall

I hate this solution, but is better than using a Windows WSL, Docker, or any virtual machine approach. And I feel bad this problem occurs since always (or Cypress version 3).