Testing with Protractor on Recent Chrome Versions

A comprehensive guide explaining how to resolve ChromeDriver compatibility issues when using Protractor with recent versions of Google Chrome, including detailed solutions and technical background.

The Error

If you are using Protractor to test your web application against the Google Chrome browser, you might have come across the following error message:

E/runner - Unable to start a WebDriver session.
E/launcher - Error: SessionNotCreatedError: session not created:
    This version of ChromeDriver only supports Chrome version 114
    Current browser version is <SOME_VERSION> with binary path <SOME_PATH>

So, why is this error happening and how to avoid it, while still being able to test against a recent version of Chrome?

Overview of Key Components

To understand why this is happening, let's first get an overview of the key components involved in running end-to-end tests with Protractor.

On one end is the browser that the tests are going to run on. On the other end is Protractor, which needs to read the test files, translate them to browser operations, send them to the browser and get back the test results. In order for Protractor to be able to communicate with a browser, an intermediary "driver" is needed. There are drivers for each of the supported browsers, all following the W3C WebDriver Standard. For Chrome specifically, there is ChromeDriver.

Now, there are a couple of different routes that Protractor can take to communicate with the browser, but all involve the use of an appropriate WebDriver:

  • Communicate with the browser directly. This is what happens when you use directConnect: true in your Protractor configuration.
    (NOTE: This only works for Chrome and Firefox.)
  • Communicate with the browser through a local Selenium Server instance. This is what happens when you use the seleniumServerJar option in your Protractor configuration or use the seleniumAddress option to bind to a locally running instance.
  • Communicate with the browser through a remote Selenium Server instance. This is what happens when you use the seleniumAddress option in your Protractor configuration to bind to a remotely running instance or use a cloud-based testing platform, such as BrowserStack or SauceLabs.

Also, keep in mind that each browser version is only compatible with specific versions of the corresponding WebDriver.

To deal with the complexity of getting the necessary WebDrivers at appropriate versions and optionally getting and running a Selenium Server, Protractor uses another library, webdriver-manager.

Understanding the Error

At some point, the process and APIs involved in identifying and downloading a ChromeDriver binary version for a version of Chrome changed. This change affects Chrome/ChromeDriver versions 115 and newer. You can find more details about the changes here.

As a result, webdriver-manager is no longer able to locate and download any ChromeDriver version newer than v114. Consequently, when Protractor relies on webdriver-manager, it can only communicate with Chrome versions around v114. This is problematic since, as of the time of writing, the stable Chrome version is 134.

There are also some discussions about the issue on the webdriver-manager repository on GitHub, for example here and here.

Resolving the Issue

Installing ChromeDriver

If you are affected by this issue, the easiest way to resolve it is by taking charge of providing the ChromeDriver binary to Protractor/Selenium, instead of relying on webdriver-manager for that. Fortunately, there is another npm package that can greatly help with that: chromedriver

  1. Add chromedriver to your devDependencies in package.json. The version of the chromedriver package directly matches the version of ChromeDriver that it will download by default, which correlates to the version of Chrome you can "drive". In most cases, you should install the latest available version.
    package.json
    {
      // ...
      "devDependencies": {
        // ...
        "chromedriver": "134.0.0"
      }
    }
    
  2. Optionally, you can configure chromedriver to auto-detect the installed version of Chrome and download an appropriate version of ChromeDriver. This is useful when the tests are going to run on different environments, with different versions of Chrome.
    One way to do this, is to add detect_chromedriver_version=true to your .npmrc file. See the chromedriver package documentation for more information on available configuration options.
    .npmrc
    # ...
    detect_chromedriver_version=true
    
  3. Run npm install to install the newly added chromedriver package. As part of the installation process, chromedriver will also download a version of the ChromeDriver binary.
    npm install
    

Using ChromeDriver

By following the above steps, you will end up with an appropriate version of ChromeDriver. Now, you need to instruct Protractor/Selenium to use it. This involves different steps depending on how Protractor is communicating with the browser.

Case 1: directConnect or seleniumServerJar

If you are using directConnect: true or the seleniumServerJar option in your Protractor configuration, you need to let Protractor know where to find the ChromeDriver binary by using the chromeDriver configuration option:

protractor.conf.js
exports.config = {
  // ...
  chromeDriver: require('chromedriver').path,
};

Case 2: seleniumAddress and webdriver-manager

If you are using the seleniumAddress option in your Protractor configuration to bind to an already running Selenium Server instance (typically started with webdriver-manager start), then you need to make the following changes:

  1. Configure webdriver-manager to not download a ChromeDriver binary (which it does by default), so that the Selenium Server will instead find and use our version. For example, if you run the command npx webdriver-manager update, change it to npx webdriver-manager update --no-chrome.
  2. Ensure that the node_modules/.bin/ directory is on the PATH environment variable when starting the Selenium Server. This will allow the server to find and use the ChromeDriver binary downloaded by the chromedriver package.
    A straightforward way to achieve this is to run the start command from an npm script, which, by default, augments the PATH with package executables. For example, add a script in your package.json to start the Selenium Server:
    package.json
    {
      // ...
      "scripts": {
        // ...
        "start-selenium": "webdriver-manager start"
      }
    }
    
  3. On Windows, the Selenium Server gets confused by the node_modules/.bin/chromedriver executable, which is intended for UNIX-based systems, and fails to use the correct executable: node_modules/.bin/chromedriver.cmd
    If your tests are going to be run on Windows as well, one way to fix this is to add a postinstall npm script to your package.json to remove the unneeded executable on Windows machines. For example:
    package.json
    {
      // ...
      "scripts": {
        // ...
        "postinstall": "node --eval \"os.platform().startsWith('win') && fs.unlinkSync('node_modules/.bin/chromedriver')\""
      }
    }
    

    Don't forget to run npm install once again after you define the script, so that it runs on the already installed executables.

Conclusion

By making these changes, you can circumvent webdriver-manager's inability to download newer versions of ChromeDriver and will again be able to run your end-to-end tests with Protractor against the most recent versions of the Google Chrome browser.