Search code examples
seleniumdockermocha.jsselenium-chromedriverwebdriver-io

WebdriverIO tests don't run accordingly against dockerized Selenium server


I have a simple WebdriverIO project with a few test cases. I run everything "locally" (no CI variable declared according my wdio.conf.js settings) with browserName: "chrome" in headless mode, and Mocha test runner.

Now, I'm trying to run exactly the same test cases against a Selenium server (started via Docker), but all tests cases fail with this little error message: Timeout of 15000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.

If I go to the Selenium Web console I can see the sessions being created and deleted, so the configuration should be OK.

// wdio.conf.js
const cfg = require("config");
const fs = require("fs");
const path = require("path");

const source = { };

if (process.env.CI) { // ...if running on a CI/CD environment
  source.hostname = "localhost";
  source.maxInstances = 5;
  source.path = "/wd/hub";
  source.port = 4444;

  source.services = ["selenium-standalone"];
} else {
  source.filesToWatch = [];
}

exports.config = Object.assign({}, {
  runner: "local",

  bail: 0,
  baseUrl: cfg.get("baseUrl"),
  coloredLogs: true,
  exclude: [
    // "test/spec/**.spec.ts",
  ],
  filesToWatch: [],
  hostname: "localhost",
  logLevel: "warn", // trace | debug | info | warn | error | silent
  maxInstances: 1,
  outputDir: `${__dirname}/logs/`,
  path: "/",
  port: 9515,
  specs: ["./test/**/*",],
  sync: true,
  waitforTimeout: 25000,

  framework: "mocha",
  specFileRetries: 0,
  mochaOpts: {
    require: ["tsconfig-paths/register"],
    timeout: 15000,
    ui: "bdd",
  },

  capabilities: [
    {
      browserName: "chrome",
      maxInstances: 5,
      "goog:chromeOptions": {
        args: [
          "--disable-gpu",
          "--headless",
          "--no-sandbox",
          "--test-type",
        ],
      },
    },
  ],

  reporters: ["spec",],
  services: ["chromedriver",],

  before: function (capabilities, specs) {
    require("ts-node").register({ files: true, transpileOnly: true });
  },

  // ...Cucumber specific hooks
}, source);

Moreover, I disabled all test cases and put something simple like this:

browser.url(`https://duckduckgo.com/`);
$("#search_form_input_homepage").setValue("webdriverio");
$("#search_button_homepage").click();
const expected: string = "WebdriverIO · Next-gen WebDriver test framework for Node.js";
expect($("div#r1-0 h2.result__title a.result__a").getText()).to.contain(expected);

...and still, the same error message >:(

Any clues?


Solution

  • TL;DR — define/set proxy settings at the container level.


    OK, it was a silly detail: we use a corporate proxy.

    My initial thoughts was to try setting the proxy info (at the browser level) in wdio.conf.js:

    capabilities: [
      {
        browserName: "chrome",
        maxInstances: 5,
        "goog:chromeOptions": {
          args: [
            "--disable-gpu",
            "--headless",
            // "--no-sandbox",
            "--test-type",
            // "--window-size=1024x768",
          ],
        },
        proxy: {
          httpProxy: "http://corporate.proxy:9080",
          noProxy: ["127.0.0.1", "localhost", ".domain.tld",],
          proxyType: "manual",
          sslProxy: "http://corporate.proxy:9080",
        },
      },
    ],
    

    ...but that didn't work, so I ended up setting that at container level (in the Docker Compose file):

    version: "3.7"
    
    services:
      chrome:
        container_name: standalone-chrome
        environment:
          - CHROME_VERSION=76.0.3809   # ...make sure this is in sync with the chromedriver version in package.json
          - HTTPS_PROXY=http://corporate.proxy:9080
          - HTTP_PROXY=http://corporate.proxy:9080
          - NO_PROXY=127.0.0.1,localhost,.domain.tld
          - START_XVFB=false
        healthcheck:
          interval: 15s
          retries: 3
          timeout: 30s
          test: "/opt/bin/check-grid.sh --host chrome --port 4444"
        image: selenium/standalone-chrome:3.141.59-selenium
        networks:
          - global-network
        ports:
          - "4444:4444"
    
    networks:
      global-network:
        driver: bridge
        name: selenium-network
    

    Then I can run the tests against that dockerized "standalone" Chrome instance, or in the CI/CD pipeline via: CI=docker npm run test (mapped in package.json like: "scripts": { "test": "wdio" }).

    Hope this helps somebody in the future...