Search code examples
angulardockerprotractore2e

Issue with running e2e Angular tests in docker and setting up Chromium


I am setting up a docker container to run my Angular E2E tests. It seems that I am missing something when I set up Chromium. I am using Angular 11 with Protractor.

My Dockerfile is

FROM node:15.6.0

RUN apt-get update && \
    DEBIAN_FRONTEND="nointeractive" \
    apt-get install -y --no-install-recommends \
    chromium \
    libgconf-2-4 \
    openjdk-8-jre-headless \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /opt/frontend/angular
COPY . .

RUN rm -r node_modules
RUN npm install -g @angular/cli
RUN npm install

CMD ng e2e --baseUrl="http://something.com/"

and the error I am getting in docker is

Connected.
Your global Angular CLI version (11.1.1) is greater than your local version (11.0.0). The local Angular CLI version is used.

To disable this warning use "ng config -g cli.warnings.versionMismatch false".
[20:43:25] I/file_manager - creating folder /opt/frontend/angular/node_modules/protractor/node_modules/webdriver-manager/selenium
[20:43:25] I/config_source - curl -o/opt/frontend/angular/node_modules/protractor/node_modules/webdriver-manager/selenium/chrome-response.xml https://chromedriver.storage.googleapis.com/
[20:43:27] I/downloader - curl -o/opt/frontend/angular/node_modules/protractor/node_modules/webdriver-manager/selenium/chromedriver_88.0.4324.96.zip https://chromedriver.storage.googleapis.com/88.0.4324.96/chromedriver_linux64.zip
[20:43:29] I/update - chromedriver: unzipping chromedriver_88.0.4324.96.zip
[20:43:29] I/update - chromedriver: setting permissions to 0755 for /opt/frontend/angular/node_modules/protractor/node_modules/webdriver-manager/selenium/chromedriver_88.0.4324.96
[20:43:30] I/launcher - Running 1 instances of WebDriver
[20:43:30] I/direct - Using ChromeDriver directly...
[20:43:32] E/runner - Unable to start a WebDriver session.
[20:43:32] E/launcher - Error: WebDriverError: unknown error: Chrome failed to start: exited abnormally.
  (unknown error: DevToolsActivePort file doesn't exist)
  (The process started from chrome location /usr/bin/chromium is no longer running, so ChromeDriver is assuming that Chrome has crashed.)
  (Driver info: chromedriver=88.0.4324.96 (68dba2d8a0b149a1d3afac56fa74648032bcf46b-refs/branch-heads/4324@{#1784}),platform=Linux 4.19.121-linuxkit x86_64)
    at Object.checkLegacyResponse (/opt/frontend/angular/node_modules/selenium-webdriver/lib/error.js:546:15)
    at parseHttpResponse (/opt/frontend/angular/node_modules/selenium-webdriver/lib/http.js:509:13)
    at /opt/frontend/angular/node_modules/selenium-webdriver/lib/http.js:441:30
    at processTicksAndRejections (node:internal/process/task_queues:94:5)
[20:43:32] E/launcher - Process exited with error code 100
Disconnected from container.

Is there anything that I am missing for setting up Chromium for Angular e2e tests in docker?


Solution

  • The main issues were in the Dockerfile and the protractor config file.

    The first issue with the protractor config file is that you should pass the right chromeOptions. These args are necessary to have. the final protractor file:

    const { SpecReporter } = require('jasmine-spec-reporter');
    const PrettyReporter = require('protractor-pretty-html-reporter').Reporter;
    const path = require('path');
    const fs = require('fs');
    const now = new Date();
    exports.report_name = 'Report-' + now.getFullYear() + "-" + (now.getMonth() + 1) + "-" + now.getDate() + "-" + now.getHours() + "-" + now.getMinutes() + "-" + now.getSeconds();
    exports.logfile_name = 'results-' + now.getFullYear() + "-" + (now.getMonth() + 1) + "-" + now.getDate() + "-" + now.getHours() + "-" + now.getMinutes() + "-" + now.getSeconds();
    const Reporter = path.resolve("./target/");
    const report = `${Reporter}` + '/' + exports.report_name;
    
    const mkdirSync = function (report) {
      try {
        fs.mkdirSync(report);
      }
      catch (err) {
        if (err.code !== 'EEXIST')
          throw err;
      }
    };
    // @ts-ignore
    var prettyReporter = new PrettyReporter({
      path: report,
      screenshotOnPassed: true
    });
    
    /**
     * @type { import("protractor").Config }
     */
    exports.config = {
      allScriptsTimeout: 11000,
      specs: [
        './src/**/*.e2e-spec.ts'
      ],
      capabilities: {
        browserName: 'chrome',
        'directConnect': true,
        chromeOptions: {
          args: [
            'window-size=1280,710',
            'no-sandbox',
            'headless',
            'disable-gpu',
            'disable-dev-shm-usage'
          ]
        },
        sharedTestFiles: true,
        maxInstances: 1
      },
      directConnect: true,
      baseUrl: 'http://localhost:4200/',
      framework: 'jasmine',
      jasmineNodeOpts: {
        showColors: true,
        defaultTimeoutInterval: 30000,
        print: function() {}
      },
      beforeLaunch() {
        mkdirSync("target")
        prettyReporter.startReporter();
      },
      onPrepare() {
        require('ts-node').register({
          project: require('path').join(__dirname, './tsconfig.json')
        });
        jasmine.getEnv().addReporter(prettyReporter);
        jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
      }
    };
    

    Another issue is that the specific version of Chrome could not be found, and it is easy to get this issue with every build since the versions could change. The solution is to make sure you know which version of Chrome you are installing. Then you need to update the expected Chrome version using the webdriver-manager in the node-modules (Note that this step should be done after installing node packages). This is an edited version of the Dockerfile that worked successfully. The final Dockerfile:

    FROM node:15.6.0
    ENV chrome_version=88.0.4324.104
    ENV testurl default_test_base_url
    
    # Google Chrome
    RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
        && echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list \
        && apt-get update -qqy \
        && apt-get -qqy install google-chrome-stable \
        && rm /etc/apt/sources.list.d/google-chrome.list \
        && rm -rf /var/lib/apt/lists/* /var/cache/apt/* \
        && sed -i 's/"$HERE\/chrome"/"$HERE\/chrome" --no-sandbox/g' /opt/google/chrome/google-chrome
        
    WORKDIR /opt/frontend/angular
    COPY ./frontend/angular .
    
    RUN rm -rf node_modules || true
    RUN npm install -g @angular/cli@11
    RUN npm install
    RUN ./node_modules/.bin/webdriver-manager update --versions.chrome ${chrome_version}
    
    CMD ng e2e --baseUrl=$testurl