Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run Angular6 E2E tests on Alpine Linux

While trying to run E2E tests using Alpine Linux we have the following mysterious error:

E/launcher - spawn (...)/selenium/chromedriver_2.40 ENOENT

How to reproduce

docker run -it --name my-alpine --rm alpine:latest /bin/ash
apk add --update nodejs nodejs-npm chromium \
    && export CHROME_BIN=/usr/bin/chromium-browser

npm install -g @angular/cli
ng new testAlpine
cd testAlpine
ng e2e

The results

[14:10:54] I/file_manager - creating folder /testAlpine/node_modules/protractor/node_modules/webdriver-manager/selenium
ℹ 「wdm」: Compiled successfully.
[14:10:54] I/update - chromedriver: unzipping chromedriver_2.40.zip
[14:10:55] I/update - chromedriver: setting permissions to 0755 for /testAlpine/node_modules/protractor/node_modules/webdriver-manager/selenium/chromedriver_2.40
(node:121) [DEP0022] DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead.
[14:10:55] I/launcher - Running 1 instances of WebDriver
[14:10:55] I/direct - Using ChromeDriver directly...
[14:10:55] E/launcher - spawn /testAlpine/node_modules/protractor/node_modules/webdriver-manager/selenium/chromedriver_2.40 ENOENT
[14:10:55] E/launcher - Error: spawn /testAlpine/node_modules/protractor/node_modules/webdriver-manager/selenium/chromedriver_2.40 ENOENT
    at _errnoException (util.js:1024:11)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:190:19)
    at onErrorNT (internal/child_process.js:372:16)
    at _combinedTickCallback (internal/process/next_tick.js:138:11)
    at process._tickCallback (internal/process/next_tick.js:180:9)
[14:10:55] E/launcher - Process exited with error code 199
An unexpected error occured: undefined

Some investigation details

Assuming that protractor uses Nodejs spawn function, we tried to run the command from ash, and the result was a "not found" message! digging a little bit about it found that this could be related to a missing dynamic linked library.

In order to validate the assumption, we installed binutils to check for the dynamic link dependency.

apk add --update binutils
readelf -l /testAlpine/node_modules/protractor/node_modules/webdriver-manager/selenium/chromedriver_2.40

And the results show the dependency that is not present in Alpine Linux,

/lib64/ld-linux-x86-64.so.2

Elf file type is EXEC (Executable file)
Entry point 0x490000
There are 11 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000200040 0x0000000000200040
                 0x0000000000000268 0x0000000000000268  R      0x8
  INTERP         0x00000000000002a8 0x00000000002002a8 0x00000000002002a8
                 0x000000000000001c 0x000000000000001c  R      0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000200000 0x0000000000200000
                 0x000000000028f27c 0x000000000028f27c  R      0x1000
  LOAD           0x0000000000290000 0x0000000000490000 0x0000000000490000

Trying to get an updated chrome driver version using webdriver-manager didn't work as well. the downloaded version has the same issue.

npm install -g webdriver-manager

webdriver-manager update
webdriver-manager: using global installed version 12.0.6
[14:30:20] I/file_manager - creating folder /usr/lib/node_modules/webdriver-manager/selenium
[14:30:21] I/update - chromedriver: unzipping chromedriver_2.40.zip
[14:30:21] I/update - chromedriver: setting permissions to 0755 for /usr/lib/node_modules/webdriver-manager/selenium/chromedriver_2.40

/testAlpine # /usr/lib/node_modules/webdriver-manager/selenium/chromedriver_2.40
/bin/ash: /usr/lib/node_modules/webdriver-manager/selenium/chromedriver_2.40: not found

Random toughts

  • As Alpine Linux moved to musl libc is it necessary to rebuild chromeDriver to use it?
like image 714
hamilton.lima Avatar asked Jun 08 '18 14:06

hamilton.lima


2 Answers

It is necessary to rebuild chromedriver with musl libc or to use the chromedriver package from alpine repos, you can install it with apk add --no-cache chromium-chromedriver.

You also need to tell protractor to use the correct binary with chromeDriver: '/usr/bin/chromedriver' in your protractor config.

like image 135
sdumont Avatar answered Sep 25 '22 14:09

sdumont


For people that have this issue in the future, I was totally unable to get the combination of alpine + angular + protractor + webdriver-manager to co-operate in any out-of-the-box supported way.

After much tinkering around, I managed to get it to work by

  1. using webdriver-manager to generate configs
  2. overriding the webdriver-manager driver with one from the alpine registry

Dockerfile:

FROM node:12-alpine

RUN \
  echo "http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories \
  && echo "http://dl-cdn.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories \
  && echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \
  && apk --no-cache update \
  && apk --no-cache upgrade \
  && apk add --no-cache --virtual .build-deps chromium chromium-chromedriver \
  && rm -rf /var/cache/apk/* /tmp/*

ENV CHROME_BIN /usr/bin/chromium-browser

protractor.conf.js

capabilities: {
    browserName: 'chrome',
    chromeOptions: {
        args: ['--headless', '--disable-gpu', '--no-sandbox'],
    },
},
directConnect: true,

The script looks somewhat like this:

  before_script:
    - yarn install --frozen-lockfile --cache-folder "$CI_PROJECT_DIR/.yarn"
  script:
    - npx webdriver-manager update --versions.chrome="$(chromium-browser --version | cut -d ' ' -f 2)"
    - mv "$CI_PROJECT_DIR/node_modules/webdriver-manager/selenium/chromedriver_$(chromium-browser --version | cut -d ' ' -f 2)" "$CI_PROJECT_DIR/node_modules/webdriver-manager/selenium/chromedriver.bak"
    - ln -s "/usr/bin/chromedriver" "$CI_PROJECT_DIR/node_modules/webdriver-manager/selenium/chromedriver_$(chromium-browser --version | cut -d ' ' -f 2)"
    - yarn run e2e --webdriverUpdate=false

Note that the code mentioned above is code for a Gitlab CI configuration: based on your needs you will probably have to:

  • Convert it into a script usable for your environment
  • Remove/replace some environment variables
like image 43
JohannesB Avatar answered Sep 25 '22 14:09

JohannesB