microsoft / playwright

Playwright is a framework for Web Testing and Automation. It allows testing Chromium, Firefox and WebKit with a single API.
https://playwright.dev
Apache License 2.0
66.53k stars 3.64k forks source link

[Question] Is it possible to run playwright for Electron in headless mode ? #2609

Closed atali closed 4 years ago

atali commented 4 years ago

There is 2 flavours of my project, one running on windows and another one running on linux.

Until now for Linux, we use a docker image to run our e2e with Spectron, we switched recently to Playwright but I am wondering if it's possible to run then on Linux.

Our Docker image uses xvfb, do we need something in particular to run electron with playwright in headless mode inside a docker image ?

pavelfeldman commented 4 years ago

You don't need anything, Docker + xvfb should work just fine. If you already ran Electron in that docker, it means you have all the dependencies in place.

pavelfeldman commented 4 years ago

To clarify, playwright-electron will run it headfully. xvfb-run node test is what makes it headless.

atali commented 4 years ago

Ok thanks a lot @pavelfeldman , let me try and let you know if I have any issue

pavelfeldman commented 4 years ago

Lets us know if it worked please! If it all went fine, we will close the issue!

atali commented 4 years ago

Yes I will, I have some issue but I trying to investigate what is the real issue.

atali commented 4 years ago

inside my docker , when running the following command to run my application directly

xvfb-run /home/pwuser/workspace/node_modules/electron/dist/electron --no-sandbox dist/apps/myapp/main.js

I got the following output:

Showing window...

I suppose my electron application is running correctly .

Then I stopped the previous command and then I am trying to run my e2e tests with playwright and I got the following error :

 console.log application-wrapper.ts:30
    browser:   <launching> /home/pwuser/workspace/node_modules/electron/dist/electron --inspect=0 --remote-debugging-port=0 --require /home/pwuser/workspace/node_modules/playwright-core/lib/server/electronLoader.js --no-sandbox dist/apps/ev-electron/main.js

  console.log application-wrapper.ts:30
    browser:   <launched> pid=1934

  console.log application-wrapper.ts:30
    browser:err:   Debugger listening on ws://127.0.0.1:35581/ad97929e-238a-4e72-a406-80a97a3b3cb3

  console.log application-wrapper.ts:30
    browser:   <ws connecting> ws://127.0.0.1:35581/ad97929e-238a-4e72-a406-80a97a3b3cb3

  console.log application-wrapper.ts:30
    browser:err:   For help, see: https://nodejs.org/en/docs/inspector

  console.log application-wrapper.ts:30
    browser:   <ws connected> ws://127.0.0.1:35581/ad97929e-238a-4e72-a406-80a97a3b3cb3

  console.log application-wrapper.ts:30
    browser:err:   Debugger attached.

  **console.log application-wrapper.ts:30
    browser:   <process did exit: exitCode=null, signal=SIGSEGV>**

 FAIL  my-test.spec.ts
  Address setting
    ✕ Should load the URL provided by the user (417ms)

  ●  Should load the URL provided by the user

    TypeError: Cannot read property 'message' of null

      at ProgressController.run (../../node_modules/playwright-core/lib/progress.js:85:51)

As you can see, it seems that the debugger is connected correctly but the browser crash .

My docker file is :

FROM ubuntu:bionic

ENV NODE_VERSION 12.16.3

# 0. Install curl
RUN apt-get update && apt-get install -y curl vim

# 1. Install node12
# this package is used for snapcraft and we should not clear apt list - to avoid apt-get update during snap build
RUN curl -L https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz | tar xz -C /usr/local --strip-components=1 && \
  unlink /usr/local/CHANGELOG.md && unlink /usr/local/LICENSE && unlink /usr/local/README.md && \
  # https://github.com/npm/npm/issues/4531
  npm config set unsafe-perm true

# 2. Install WebKit dependencies
RUN apt-get install -y libwoff1 \
                       libopus0 \
                       libwebp6 \
                       libwebpdemux2 \
                       libenchant1c2a \
                       libgudev-1.0-0 \
                       libsecret-1-0 \
                       libhyphen0 \
                       libgdk-pixbuf2.0-0 \
                       libegl1 \
                       libnotify4 \
                       libxslt1.1 \
                       libevent-2.1-6 \
                       libgles2 \
                       libvpx5

# 3. Install Chromium dependencies

RUN apt-get install -y libnss3 \
                       libxss1 \
                       libasound2 \
                       fonts-noto-color-emoji

# 4. Install Firefox dependencies

RUN apt-get install -y libdbus-glib-1-2 \
                       libxt6

# 5. Install ffmpeg to bring in audio and video codecs necessary for playing videos in Firefox.

RUN apt-get install -y ffmpeg

# 6. Add user so we don't need --no-sandbox in Chromium
RUN groupadd -r pwuser && useradd -r -g pwuser -G audio,video pwuser \
    && mkdir -p /home/pwuser/workspace \
    && mkdir -p /home/pwuser/Downloads \
    && chown -R pwuser:pwuser /home/pwuser

# 7. (Optional) Install XVFB if there's a need to run browsers in headful mode
RUN apt-get install -y xvfb

COPY . /home/pwuser/workspace

I am running the following docker command line : docker run -t -i --rm --shm-size=2gb -m 2gb --cap-add=SYS_ADMIN microsoft/playwright:bionic /bin/bash

atali commented 4 years ago

I added --enable-logging as a new parameter

    this.app = await electron.launch(electronPath, {
      args: ['--no-sandbox', '--enable-logging', applicationPath],
      env: this.envs
      logger: {
        isEnabled: (name, severity) => true,
        log: (name, severity, message, args) => console.log(`${name}: ${message}`)
      }
    })
  }

and I got the following error

  console.log application-wrapper.ts:30
    browser:err:   [2128:0618/204237.452921:ERROR:browser_main_loop.cc(1473)] Unable to open X display.
atali commented 4 years ago

I am wondering if it's not related to the functionasync function launchProcess(options) from the lib/server/processLauncher.js. Maybe there is a side effect with the spawn function.

pavelfeldman commented 4 years ago

I would try a couple of things:

atali commented 4 years ago

Hey @pavelfeldman ,

I can't use xvfb-run first because of the order of parameters :

xvfb-run  --inspect=0 --remote-debugging-port=0 --require /home/pwuser/workspace/node_modules/playwright-core/lib/server/electronLoader.js /home/pwuser/workspace/node_modules/electron/dist/electron main.js

instead of

xvfb-run /home/pwuser/workspace/node_modules/electron/dist/electron --inspect=0 --remote-debugging-port=0 --require /home/pwuser/workspace/node_modules/playwright-core/lib/server/electronLoader.js main.js

The second option helps (expose DISPLAY via this.envs) but was not enough. We noticed xvfb-run quit before the test start maybe because of our layer of launchers :

gradle -> npx -> typescript -> playwright-electron -> electron launcher.

we end up using :

export DISPLAY=:99
Xvfb $DISPLAY -screen 0 1920x1080x24 &

and then start the e2e tests. it works well.

That's being said, xvfb-run was running well with Spectron. I don't know exactly why xvfb-run behave differently with Playwright.

Thanks again for your help. We now run our e2e tests on Linux in docker (headless) and on Windows (headfully).

zhex900 commented 3 years ago

@atali can you show the Dockerfile you use to run Playwright tests headless?

zhex900 commented 3 years ago

I can't get the playwright tests to run in docker.

I tried

export DISPLAY=:99
Xvfb $DISPLAY -screen 0 1920x1080x24 &

xvfb-run playwright test this does work either

this is my error log

  pw:browser <launching> /app/packages/kiosk-app/node_modules/electron/dist/electron --inspect=0 --remote-debugging-port=0 .webpack/main/index.js --enable-logging --ignore-certificate-errors --ignore-ssl-errors --disable-dev-shm-usage --mockDeviceId test_fd485024-fa36-481e-a252-c16b611a837d --no-sandbox +0ms
  pw:browser <launched> pid=1621 +6ms
  pw:browser [pid=1621][err] Debugger listening on ws://127.0.0.1:34211/c3b19f4d-c66b-4833-ad20-d238ab48c623 +194ms
  pw:browser [pid=1621][err] For help, see: https://nodejs.org/en/docs/inspector +0ms
  pw:browser <ws connecting> ws://127.0.0.1:34211/c3b19f4d-c66b-4833-ad20-d238ab48c623 +1ms
  pw:browser <ws connected> ws://127.0.0.1:34211/c3b19f4d-c66b-4833-ad20-d238ab48c623 +6ms
  pw:browser [pid=1621][err] Debugger attached. +1ms
  pw:browser [pid=1605][err] [1605:0813/131926.008991:ERROR:browser_main_loop.cc(1402)] Unable to open X display. +
JoCa96 commented 3 years ago

Hi, we are running xvfb-run --auto-servernum --server-args='-screen 0, 1920x1080x24' npm run jest:ci in the docker image mcr.microsoft.com/playwright:focal. We are always getting an electron.launch: Process failed to launch!electron.launch: Process failed to launch! error. But we only have this issue when trying to run it headless on Azure Pipelines, locally it works.

Our code looks like this:

beforeAll(async () => {
  electronApp = await _electron.launch({
    args: [
      "--disable_splash_screen",
      "--no-sandbox",
      "--enable-logging",
      path.join(__dirname, ".."),
    ],
  });
});

afterAll(async () => {
  if (electronApp) {
    return electronApp.close();
  }
});

Any suggestions on how to fix this issue or how to get a more extensive error message?

gilles-yvetot commented 3 years ago

@pavelfeldman I tried both things:

I would try a couple of things:

  • use xvfb-run as an electronPath and pass actual electron path as a first argument

I got electron.launch: Process failed to launch!

  • check to see if environment was indeed inherited and you are passing the DISPLAY via this.envs into the spawned process.

I tried checking if process.env.DISPLAY was set (it was) and then passing it down through env but I still have Unable to open X display