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?
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