Emulate GeoLocation for Automated Testing with webdriverIO
Tags: webdriverio, testing, javascript
Published: 2020-05-01 02:57:02

As exposed on the [first post](https://dev.to/coffeestain/emulate-geolocation-for-manual-testing-311k) of this series, Google Chrome DevTools includes a series of features that facilitate the emulation of customers *Experience Profiles*, such as device, resolution and of course geographical location.

### Chrome DevTools Protocol
Once you have mastered the art of manual testing and want to try some automated geoLocation testing, you don't have to look away looking for new tools. **Chrome DevTools** exposes its own Protocol which allow us to programmatically use the same tools you know how to use on the browser.


# Let's automate it
For the sake of this post I decided to use [webdriverIO] (https://webdriver.io/docs/gettingstarted.html) to write the automated tests. The reason to use this framework is that there is 3rd party service already developed and ready to use that allow us to seamlessly use the devTools without adding any extra code.

## Getting started
### Setup the project
We need to create a folder, and start a nodeJs project. (Recommended: Make sure the latest version of node is installed).
```bash
$ mkdir webdriverio-test && cd webdriverio-test
$ npm init -y
```

### Install webdriverIO CLI
Now let's install the wdio CLI, which provide us with tools to setup and run a basic webdriverIO project.
```bash
$ npm i --save-dev @wdio/cli
```

### Generate a wdio config file and create a test folder
WebdriverIO uses a configuration file (by default `wdio.conf.js`) that contains the basic information of the framework. Once the basic setup is complete webdriverIO will look into `./test/specs` for the test files.
```bash
$ npx wdio config -y
$ mkdir -p ./test/specs
```

### Setup devTools service
So far we have only setup the basic default configuration for webdriverIO. On this next step we are going to include the devTools service which will provide us with capabilities to interact with the devTools protocol.

```bash
$ npm install @wdio/devtools-service --save-dev
```
Then go to the `wdio.conf.js` and add the `devtools` service to the webdriverIO configuration.

```js
...
// Services take over a specific job you don't want to take care of. They enhance
// your test setup with almost no effort. Unlike plugins, they don't add new
// commands. Instead, they hook themselves up into the test process.
    services: ["devtools"],
..
```

**This is basically all the necessary configuration**

### Now let's create some tests
Create a file under the folder above and name it `geo.js`. This file will contain our testing code.

**Test Scenario**
1. Navigate to `https://www.where-am-i.net/` and verify the current position.
2. Use devTools to emulate a different location. (London)
3. Verify that the user is on a new location.
4. Again use devTools to emulate another location. (Tokyo)
5. Repeat the verification.

*Read the comments in the code*

```js
const assert = require('assert')

describe('Check Location overriding the timezone', () => {
    it('Check the default timezone', () => {
        browser.url('https://www.where-am-i.net/')
        // this validation depends on where are you!
        // assert.equal(location.getText(), '19.075984, 72.877656')
        // you might get 0.0 and 0.0 the first time because of authorization issues
    })

    it('Check that London should be the timezone', () => {
        // change to london location and timezone
        // cdp is the command to use a devTools command
        // we are going to use the Emulation module
        // and the setGeoLocationOverride method
        // info: https://chromedevtools.github.io/devtools-protocol/tot/Emulation/
        // note: the location and timezone must match or you will get an unavailable position    

        browser.cdp('Emulation', 'setGeolocationOverride' , {
            latitude:51.507351,
            longitude:-0.127758,
            accuracy: 1
        })
        browser.cdp('Emulation', 'setTimezoneOverride', {
            timezoneId: 'Europe/London'
        })       
        browser.pause(3000) // wait so you can notice the map changing
        let location = $('#location') // get a location reference for validation
        assert.equal(location.getText(), '51.507351, -0.127758')

    })

    it('Check that Tokyo should be the timezone', () => {
        // change to lo Tokyo location and timezone
        browser.cdp('Emulation', 'setGeolocationOverride' , {
            latitude:35.689487,
            longitude:139.691706,
            accuracy: 1
        })

        browser.cdp('Emulation', 'setTimezoneOverride', {
            timezoneId: 'Asia/Tokyo'
        })
        browser.pause(3000) // wait so you can notice the map changing
        assert.equal($('#location').getText(), '35.689487, 139.691706')
    })
});
```

### Let's execute the tests
Just run on your terminal
```bash
$ npx wdio wdio.conf.js
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/d4a91y9d2y3tunzb5gws.png)

Just like that!! We just emulated different user locations with no need to add complicated code or any extra tooling. 

### Now what?
Well... this example is just a very small fragment of what you actually accomplish with devTools and webdriverIO. I encourage you to explore more the documentation for both tools and discover new capabilities that can be added to your tests.

[webdriverIO devTools Service](https://webdriver.io/docs/devtools-service.html)
[Chrome devTools Protocol](https://chromedevtools.github.io/devtools-protocol/tot/Emulation/)


Share your thoughts and comments on how you test geolocation within your automated tests!!