Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Viewing The Interactive Cypress Test Runner In Docker On Linux

I'm trying to see Cypress in interactive mode when the Cypress tests are running in a docker container. This article explains how do it on Mac - https://www.cypress.io/blog/2019/05/02/run-cypress-with-a-single-docker-command/#Interactive-mode. I cannot get it to work however on my new linux mint OS install.

Following the article, I have set -

$ IP=172.17.0.1
$ xhost + $IP
$ export DISPLAY=172.17.0.1:0

Which is the IP address on my local host machine on the Docker default bridge network.

This is my only set up. Next is the docker command for running the container -

docker container run -it \
  -v $PWD:/e2e \
  -v /tmp/.X11-unix:/tmp/.X11-unix \
  -w /e2e \
  -e DISPLAY \
  --entrypoint cypress \
  cypress/included:3.8.1 open --project .

The only difference is the latest image and 'docker container run' instead of the deprecated 'docker run ...'

It elicits -

(Cypress:16): Gtk-WARNING **: cannot open display: 172.17.0.1:0

Now the article does warn this may come up -

Debugging tip: if Cypress shows an error Gtk-WARNING **: cannot open display:... make sure X11 server allows connections over the network from the Docker container. Run xhost command in the terminal to see if it has the IP address you have added previous with xhost + $IP.

When I run -

$ xhost

It gives -

INET:ross-Aspire-TC-780

SI:localuser:ross

I'm a hobby web dev with not much sys admin knowledge so I was totally relying on the article working. Does anybody know how to get this working?

like image 992
user1849962 Avatar asked Dec 28 '19 19:12

user1849962


People also ask

Can Docker run Cypress?

Docker enables more efficient use of system resources. You create your image once and run it anywhere on your local, inside ci/cd, or any other setups. With Cypress, you can use Docker in your Continuous Testing setups achieving better results.

What is the command to launch the Cypress tests through terminal?

cypress open --project <project-path>

How do you run Cypress tests with Cypress test runner?

Cypress provides two ways to test cases. Either using the Cypress UI Test Runner or from the CLI using the "cypress run" command. A specific test case can be executed on the CLI using the "--spec" option. We can change the browser for a specific test run on CLI using the "--browser" option.


2 Answers

tl;dr

docker run -it --rm \
    --network host \
    -v ~/.Xauthority:/root/.Xauthority:ro \
    -e DISPLAY \
    -v $PWD:/e2e \
    -w /e2e \
    --entrypoint '' \
    cypress/included \
    npx cypress open

To run any GUI application in a docker container you've got to understand how X Window System works. X uses client-server model. An X server program runs on a computer with a graphical display and communicates with various client programs (X clients). The X server acts as a go-between for the user and the client programs, accepting requests for graphical output from the client programs and displaying them to the user (display), and receiving user input (keyboard, mouse) and transmitting it to the client programs.

In X, the server runs on the user's computer, while the clients may run on remote machines. This terminology reverses the common notion of client–server systems, where the client normally runs on the user's local computer and the server runs on the remote computer. The X Window terminology takes the perspective that the X Window program is at the centre of all activity, i.e. the X Window program accepts and responds to requests from applications, and from the user's mouse and keyboard input. Therefore, applications (on remote computers) are viewed as clients of the X Window server program.

So, to run a GUI application in a docker container, you've got to provide a way for it to communicate to the X server running on the host. One way to go about it is to use host networking (--network host). In this case the container shares the host's networking namespace. I.e. container’s network stack is not isolated from the Docker host. Particularly, the container can connect to any servers running on the host.

Also, you've got to let the container authenticate to the X server. Again, one way to achieve this is to use cookie-based authentication. For that you've got to share the ~/.Xauthority file with the container (--volume ~/.Xauthority:/root/.Xauthority:ro).

And you've got to tell the container where the X server is running. For that the DISPLAY variable is used. Since the container is going to have access to the host's network namespace, you can simply pass the DISPLAY variable from the host into the container (--env DISPLAY).

Then you need to make sure the tests are available for cypress (--volume $PWD:/e2e + --workdir /e2e).

Additionally, cypress/included sets the entrypoint to cypress run, so to open cypress you've got to reset the entrypoint (--entrypoint ''), and use npx (npx cypress open), or else it won't find your project files. Usually, you run cypress located at ./node_modules/.bin/cypress, but cypress in the image resolves to /usr/local/bin/cypress. npx makes it run cypress from the ./node_modules dir.

That is not needed in case of cypress run because the latter defaults to the current dir. For one reason or another cypress open doesn't do that if installed globally.

As such,

docker run -it --rm \
    --network host \
    -v ~/.Xauthority:/root/.Xauthority:ro \
    -e DISPLAY \
    -v $PWD:/e2e \
    -w /e2e \
    --entrypoint '' \
    cypress/included \
    npx cypress open

More on it here.

P.S. If you do anything memory intensive, cypress (or rather chrome) might occasionally crash. That happens because by default docker allocates 64 MB for shared memory (/dev/shm). One way to remedy this is to give the container access to the host's shared memory. In other words, to unisolate the IPC namespace. That is achieved by passing --ipc=host. That's not something specific to cypress. What crashes is basically chrome.

like image 110
x-yuri Avatar answered Oct 17 '22 19:10

x-yuri


Great answer provided by @x-yuri and it pointed me in the right direction to solve my problem.

For people struggling to get this running with Docker compose and Ubuntu, here is the stripped off version of my docker-compose.yml.

The key property is network_mode: host.

Run xhost +local: first to ensure correct permissions are set.

version: '3'
services:
  back-office-web-app:
    build:
      context: .
    volumes:
      - ../build:/usr/share/nginx/html
    ports:
      - 3000:80
  e2e-tests:
    image: cypress/included:4.8.0
    working_dir: /e2e
    entrypoint: cypress open --project /e2e
    depends_on:
      - back-office-web-app
    network_mode: host
    environment:
      CYPRESS_VIDEO: 'false'
      CYPRESS_BASE_URL: 'http://localhost:3000'
      DISPLAY:
    volumes:
    - ./test/:/e2e
    - ~/.Xauthority:/root/.Xauthority:rw
like image 42
Wizard Avatar answered Oct 17 '22 19:10

Wizard