In Azure pipelines, how do you set up X display for headless Chrome testing?

In our Azure Pipeline, we are attempting to run end-to-end tests in our Angular 9 application, using the following task ...

enter image description here

The package.json defines this ...

  "scripts": {
    "e2e": "npm run install-puppeteer && ng e2e"

but when the agent runs the above task, it dies with "Unable to open X display" error ...

> npm run install-puppeteer && ng test "--watch=false" "--codeCoverage=true" 

> [email protected] install-puppeteer /home/vsts/work/1/s 

> cd node_modules/puppeteer && npm run install 

> [email protected] install /home/vsts/work/1/s/node_modules/puppeteer 

> node install.js 

Chromium is already in /home/vsts/work/1/s/node_modules/puppeteer/.local-chromium/linux-818858; skipping download. 

08 12 2020 18:54:56.858:INFO [karma-server]: Karma v4.4.1 server started at 

08 12 2020 18:54:56.863:INFO [launcher]: Launching browsers Chrome with concurrency unlimited 

08 12 2020 18:54:56.866:INFO [launcher]: Starting browser Chrome 

08 12 2020 18:54:57.134:ERROR [launcher]: Cannot start Chrome 

[2099:2099:1208/] Unable to open X display. 

08 12 2020 18:54:57.134:ERROR [launcher]: Chrome stdout: 

08 12 2020 18:54:57.135:ERROR [launcher]: Chrome stderr: [2099:2099:1208/] Unable to open X display. 

08 12 2020 18:54:57.675:INFO [launcher]: Trying to start Chrome again (1/2). 

08 12 2020 18:54:59.035:ERROR [launcher]: Cannot start Chrome 

22 error Exit status 1 

23 error Failed at the [email protected] test script. 

23 error This is probably not a problem with npm. There is likely additional logging output above. 

24 verbose exit [ 1, true ]

Normally this kind of thing is dealt with by installing Xvfb. How do I do that using Azure pipelines?


  • Really this is @Hugh Lin's answer from the comments but for the benefit of posterity I created a bash task which ran a script in my repository. The script contained

    xvfb-run --auto-servernum --server-args='-screen 0, 1920x1080x24' npm run test -- --watch=false --codeCoverage=true

    Then the tests ran successfully.