Cypress: cy.exec fails on windows

Created on 23 Oct 2017  Â·  23Comments  Â·  Source: cypress-io/cypress

Current behavior:

image

From the bug, the path seems mangled:

  1. first part is UNIXy /c/Program
  2. There's a : inserted into the (Program Files) folder name for some reason
  3. 2nd half is in windows format (backslashes)

How to reproduce:

cy.exec('echo 42');

Additional Info (images, stack traces, etc)

On my machine is installed (and in env variables) the git-for-windows bash, which is the bash the cypress is trying to invoke.

  • Operating System: Windows 7/x64
  • Cypress Version: 1.0.2
  • Browser Version: canary 64
windows ready for work bug

Most helpful comment

execa has decided to not offer support for cmd.exe-incompatible shells, so this looks like something we would have to manually support.

All 23 comments

Hmm, I wonder if the git-for-windows is confusing shell read from Cypress. Will need to install and test it.

Hello,

I am also having an issue running exec in Windows 10. My git bash install path is C:\dev-tools\Git\usr\bin. When I exec cypress logs:
cypress:server shell C:\dev-tools\Git\usr\bin\bash.exe profile undefined +4ms cypress:server cy.exec found shell C:\dev-tools\Git\usr\bin\bash.exe +1ms cypress:server and is running command: echo +1ms

The command fails with Stderr: /usr/bin/bash: /s: No such file or directory

I'm not sure if this is an issue with my git-bash install or the way cypress is calling it. Any help would be greatly appreciated.

I haven't got a solution for this (yet) but I do know what the problem is.

image
(https://github.com/sindresorhus/execa/blob/master/index.js)

Basically the above section in the dependency "execa" is the problem. If your platform is windows it makes the assumption that your shell is cmd and it structures the resulting command as follows:

C:\\ProgramFiles\\Git\\usr\\bin\\bash.exe /s /c "source undefined > /dev/null 2>&1; echo foo"
(Yes, that is ProgramFiles with no spaces. I was trying to work around the original issue.)

As you can see the flags /s /c make sense in cmd, but bash sees them as file paths and we get the error we are all seeing. In line 89 you can see what the args variable should actually be set to when you shell is bash.

@GuyBransgrove Thanks for looking into this and opening the issue with execa - hopefully they get a fix in and we can update the package.

execa has decided to not offer support for cmd.exe-incompatible shells, so this looks like something we would have to manually support.

execa has decided to not offer support for cmd.exe-incompatible shells, so this looks like something we would have to manually support.

That's great news. Is there a solution as of yet to have this working at all on windows at all? I seem to be getting this error regardless of the shell used being on windows

How about using ShellJS?

This same issue: #1034

Found a solution that does the trick for now.
I'm using cypress.task to start a task which I define in the plugins file. There, I import shell-exec, a npm package that also supports windows. Since I only need a single command for now, this works fine.

Sharing full example for clearness.
cypress/plugins/index.js

// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
require('dotenv').config();
const shell = require('shell-exec');
module.exports = (on, config) => {
  // `on` is used to hook into various events Cypress emits
  // `config` is the resolved Cypress config
  on('task', {
    'env': () => {
      return new Promise(resolve => {
        resolve(process.env);
      });
    },
    // relevant part
    'db:clean': () => {
      return shell('npx gulp db:clean');
    }
  })
};

And in a test:

it('can register a new account', () => {
      cy.task('db:clean');

      cy.visit('/register');
});

It returns a promise, so it is then-able. However cypress waits for the completion out-of-the-box.

Hope that helps.

execa has decided to not offer support for cmd.exe-incompatible shells, so this looks like something we would have to manually support.

The reason this issue occurs is because Git Bash sets the SHELL environment variable, which Cypress then tries to use with execa.

Since the docs don't say anything about what shell should be used in cy.exec, and there's no option to supply a custom shell, I think we should just short-circuit the shell detection code to always use cmd.exe on Windows until people ask for support for other shells.

That would mean moving lines 88-92 of this getShell function to the top:

https://github.com/cypress-io/cypress/blob/029ed01793ba0af0e9b210d818de61d0f6806e9e/packages/server/lib/util/shell.js#L75-L95

Tested and this fixes the issue on Windows 10. Don't believe it would change existing behavior, since the current behavior is "use cmd.exe or fail".

That would mean we won't be able to use UNIX shell programs, which means that cross-platform tests written for UNIX target would stop working.

Is this issue still outstanding though? It works for me at the moment (I've also tried using execa directly, and it works, too). Though, some things changed, such as my SHELL path not containing spaces as it did in OP --- but weren't the main issue that execa passed cmd.exe switches even to the bash shell? It seems that's no longer an issue.

That would mean we won't be able to use UNIX shell programs, which means that cross-platform tests written for UNIX target would stop working.

Would it though? I only say that because AFAIK, currently, you cannot launch Cypress from a non-cmd.exe shell and then successfully use cy.exec, at all, in any way. Any command will give you the error from the OP. So tests that would break in the way you're describing are already broken today, and I'd assume that tests that pass today are most likely being launched through cmd.exe.

The change I'm proposing would make cy.exec behave as if Cypress is always launched from cmd.exe on Windows, which will make cy.exec work in non-cmd.exe shells.

Let me know if this is mistaken or you see a breaking change with this.

Is this issue still outstanding though? It works for me at the moment (I've also tried using execa directly, and it works, too). Though, some things changed, such as my SHELL path not containing spaces as it did in OP --- but weren't the main issue that execa passed cmd.exe switches even to the bash shell? It seems that's no longer an issue .

I just experienced the issue in CI using bash.exe, and switching the CI step to use cmd.exe with SHELL empty fixed it:

Would it though? I only say that because AFAIK, currently, you cannot launch Cypress from a non-cmd.exe shell and then successfully use cy.exec, at all, in any way.

Interesting. You're right, I've just tested. Previously it worked for me because I've run the test from the vscode terminal (which I have configured to use bash.exe, though) --- but running the test directly from cmd.exe or bash.exe results in the error.

Weirdly enough, it seems that I have two bash.exe executables on my system:

  1. C:\Windows\System32\cmd.exe --- this is used by vscode terminal (and since it contains no spaces, it works).
  2. C:\Program Files\Git\usr\bin\bash.exe --- this is the default shell (weirdly, echo $SHELL shows /usr/bin/bash, which isn't a valid absolute path. It seems the path is relative to C:\Program Files\Git\).

That being said, it seems this error comes down to improperly handling the path (not sure whose fault that is, but I believe it's Cypress').

cy.exec seems to use (2), but handles it in such a way that it results in the OP error of /c/Program: Files\Git\usr\bin\bash.exe: No such file or directory. I believe if we solve that, this issue would be resolved (since the upstream issue in execa seems to no longer exist).

Agreed, that's probably the preferred approach if execa will indeed work with bash.exe.


Weirdly enough, it seems that I have two bash.exe executables on my system:

1. `C:\Windows\System32\cmd.exe` --- this is used by vscode terminal (and since it contains no spaces, it works).

Is this supposed to be a path to a bash.exe executable? :stuck_out_tongue:

Wha..

It's not, I misread it :). But I'm indeed using bash.exe, it's just configured via settings.json (and isn't reflected in the vscode settings view, from which I blindly copied it). WTBS, the path again points to the Git path:

"terminal.integrated.shell.windows": "C:\\Program Files\\Git\\bin\\bash.exe",

Thus, it still contains the space. Why does Cypress handle it correctly, when invoked from vscode terminal, though?

What is the value of the SHELL environment variable in each environment?

Not sure how to figure that out on windows (maybe looking it up in registry?) except echo $SHELL, which feels not very authoritative. But it reports /usr/bin/bash when executed both from vscode terminal, and bash.exe.

Googling, it seems that echo %SHELL% should work in cmd.exe, but it seems this env variable is only set within the bash.exe process, because echoing it from cmd.exe shows nothing (which suggests it doesn't exist).

Cool, that sounds right. Strange, in that case I have no idea why it works in VScode but not outside it. There's a lot of logic in the shell.js file that needs to be unpacked...

For intelliJ
https://www.jetbrains.com/help/idea/settings-tools-terminal.html
choose your terminal as cmd for windows .

For VS Code :
Check the settings -
Terminal › External: Windows Exec
Customizes which terminal to run on Windows.
C:\windows\System32cmd.exe

Hope this helps

I was using git bash to run cypress, when i changed to windows powershell it worked for me

Is there any update to this issue or any workaround? I can't seem to get cy.exec to work on Windows at all, even via VSCode or cmd. Makes it pretty difficult to use Cypress at the moment sadly.

EDIT: @selvex's solution does work for me as well, I did something wrong when I tried it the first time. This is a reasonable workaround for the moment, but obviously it would be great for cy.exec to work on Windows too.

I am running into the same situation and was wondering if cy.exec works on Windows....

Was this page helpful?
0 / 5 - 0 ratings