Problems with Cypress and workarounds

I have a hard time making Cypress work. If you use Cypress under NixOS, I would really appreciate some help.

Here is what I did and some workarounds:

rm -rf ~/.cache/Cypress
rm -rf ~/.config/Cypress
rm -rf /tmp/test-cypress

mkdir /tmp/test-cypress
cd /tmp/test-cypress

cat > shell.nix <<EOF
with import <nixpkgs> { };

{ }:

stdenv.mkDerivation {
  name = "node";

  buildInputs = [ pkgs."nodejs" yarn cypress ];

  shellHook = ''

nix-shell --run 'yarn init --yes'
nix-shell --run 'yarn add --dev cypress'
nix-shell --run 'yarn add --dev cypress@4.3.0'

Now you can execute:

nix-shell --run 'npx cypress open'

Instead of tacking the NixOS Cypress binary from the PATH, it will download Cypress and try to run it from $HOME/.cache/Cypress. We can try to force the Cypress binary we want:

nix-shell --run 'CYPRESS_INSTALL_BINARY=0 CYPRESS_RUN_BINARY=$(which Cypress) npx cypress open'

This opens Cypress and generates a few example tests. Click on one and you get a new error:

EACCES: permission denied, open '~/.config/Cypress/cy/production/browsers/chromium-stable/interactive/CypressExtension/background.js'

This file was just created but it only got the read permission:

$ ls -l '~/.config/Cypress/cy/production/browsers/chromium-stable/interactive/CypressExtension/background.js'
-r--r--r-- 1 cassou users 579142 Apr 23 09:03 ~/.config/Cypress/cy/production/browsers/chromium-stable/interactive/CypressExtension/background.js

Cypress requires write acess to this file though. What happens is that
Cypress copies files from /nix/store to $HOME/.config/Cypress. Because the store is read-only, the copied files are read-only by default. There was a PR trying to fix this for Cypress but the author never finished it.

We can try to first copy the Cypress binary from the store and then let Cypress copy that instead:

cp --recursive --no-preserve=mode /nix/store/mcsh4x07gp365chyzhsdq4z17shisf1s-cypress-4.3.0 Cypress-store
sed --in-place 's,^exec -a .*$,exec -a "$0" "'$PWD'/Cypress-store/bin/.Cypress-wrapped" "$@",' Cypress-store/bin/Cypress 
chmod +x Cypress-store/bin/Cypress
chmod +x Cypress-store/opt/cypress/Cypress

The sed expression adapts the NixOS shell wrapper so it calls the
right Cypress binary instead of the one on the nix store. At this
point, the $HOME/.config/Cypress/ probably contains files owned by
root so you have to get rid of it:

sudo rm -rf ~/.config/Cypress/

Now you can try again:

nix-shell --run 'CYPRESS_INSTALL_BINARY=0 CYPRESS_RUN_BINARY=$PWD/Cypress-store/bin/Cypress npx cypress open'

This works.

Is there a way to do better than all that?


/cc @ero-sennin @thorstenweber83 @mmahut @rasendubi @kalbasit @gomain

The error only happens when testing with external browsers; running tests with Electron works fine, so that’s what I ended up doing.

If you need to run real browsers, I would suggest picking up my PR that you mentioned, testing, and going through the Cypress review process. I remember it working well for me, but there might be a couple of files that I have missed. I’ve abandoned the PR because (1) Electron worked fine for me, and (2) it took more than one and a half months to get a review.

1 Like

Here’s an overlay for Cypress 6.0.0 that applies rasendubi’s idea to the generated js of chrome.js between extracting it from the zip and copying it to the store:

final: prev: {
  cypress = prev.cypress.overrideAttrs (oldAttrs: {
    installPhase = let
      old = "copyExtension(pathToExtension, extensionDest)";
      # This has only been tested against Cypress 6.0.0!
      new =
        "copyExtension(pathToExtension, extensionDest).then(() => fs_1.default.chmodAsync(extensionBg, 0o0644))";
    in ''
      sed -i 's/${old}/${new}/' \
    '' + oldAttrs.installPhase;

I’ve combined that and DamienCassou’s very helpful example env vars tip into an example shell.nix as a gist, here.

(I’m not sure it’s robust enough to submit as a PR to nixpkgs though… Maybe if Cypress could be built from source?)