# E2E Testing with Nightwatch and Nuxt

*The Nuxt team provides some  [great documentation](https://nuxtjs.org/examples/testing)  on getting started with e2e testing using  [Ava](https://github.com/avajs/ava) . But if you’re looking for a little more power, Nightwatch is worth a try.*

## Getting Started
I’m going to skip over the  [installation details](https://nightwatchjs.org/gettingstarted/installation/)  and assume that we’re working on a project that contains the latest version of Nightwatch and an appropriate webdriver, like  [Chrome](https://nightwatchjs.org/gettingstarted/installation/#install-chromedriver) .

## Basic Configuration
In the root directory of your project, Nightwatch will look for `nightwatch.json` or `nightwatch.conf.js`. In my example, I used a single `nightwatch.json` file to configure my webdriver. (I’m using Chrome in this instance.)

The  [nightwatch docs do a good job of explaining most of these settings](https://nightwatchjs.org/gettingstarted/configuration/#base-settings), so I’ll just highlight a couple that are relevant to our task.

### nightwatch.json

```json
{
    "src_folders": [
        "tests"
    ],
    "exclude": [
        "tests/globals.js"
    ],
    "webdriver": {
        "start_process": true,
        "server_path": "node_modules/.bin/chromedriver",
        "cli_args": [
            "--verbose"
        ],
        "port": 9515
    },
    "test_settings": {
        "default": {
            "desiredCapabilities": {
                "browserName": "chrome"
            },
            "globals": {
                "asyncHookTimeout": 60000
            }
        }
    },
    "globals_path": "tests/globals.js"
}
``` 

## exclude
I have a global configuration file that I decided to store in the same directory as my tests. I suspect this isn’t considered best practice, but my root directory is already crowded enough. However, by placing this file in the `tests` directory, nightwatch tries to open the file and run tests. To avoid this, I’ve added the `tests/globals.js` file to the exclude array.

## globals_path
As I mentioned above, I have a file that contains global configuration and hooks for all of my tests. This option lets you instruct nightwatch where to find your global settings and hooks.

## globals.asyncHookTimeout
In our `before` hook, which prepares our environment for testing, I’m building the app and running the server. However, nightwatch was timing out before Nuxt was finished building our app. So I set this value to 60 seconds. This gives our `before` and `after` hooks enough time to build and serve our app before moving on to running the tests.

<em>**Note**: Technically you should be able to set this value in the tests/globals.js that was created, but doing so caused the chromedriver to crash, so I just set the value here instead. 🤷‍♂️</em>

## Global Configuration and Hooks
As mentioned above, the global settings and hooks are stored in a javascript module, `tests/globals.js`.  [Check out the source code for a complete set of properties](https://github.com/nightwatchjs/nightwatch/blob/master/examples/globalsModule.js) .

<em>**Note**: The example below is using Nuxt 2.8.1. There’s a good chance that the process for programmatically building and serving the app may have changed in recent versions.</em>

### tests/globals.js
```javascript
const resolve = require('path').resolve;
const Nuxt = require('nuxt').Nuxt;
const Builder = require('nuxt').Builder;
 
/**
 * Nightwatch
 * @url https://nightwatchjs.org/guide/
 */
 
// Used to store the nuxt server instance
let nuxtInstance = null;
 
module.exports = {
 
  // The host for nuxt server
  serverHost: 'localhost',
 
  // Which port to run nuxt on
  serverPort: 5555,
 
  before : async function(browser, done) {
    console.log("Starting Nuxt Server")
    const rootDir = resolve(__dirname, '../')
    let config = {}
    try { config = require(resolve(rootDir, 'nuxt.config.js')) } catch (e) {}
    config.rootDir = rootDir // project folder
    const nuxt = new Nuxt(config)
    nuxtInstance = nuxt // We keep a reference to Nuxt so we can close the server at the end of the test
    await new Builder(nuxt).build()
    await nuxt.server.listen(this.serverPort, this.serverHost)
    done();
  },
 
  after : async function(browser, done) {
    console.log('Shutting Down Nuxt');
    await nuxtInstance.close();
    done();
  },
}
```

The `before` method runs before our tests and fires up the Nuxt server to run locally on port 5555.

Once all of the tests are complete, the `after` method shuts down the Nuxt server instance.

## Finally, writing and running the tests:
Just to make sure things were working properly, I created a simple test that loads the app, waits for the body to load, and asserts that the title is correct.

### tests/index.test.js
```javascript
// Needed to get the serverHost and serverPort
const globals = require("./globals");
 
/**
 * Nightwatch
 * @url Setup Guide https://nightwatchjs.org/guide/
 * @url API Reference https://nightwatchjs.org/api/commands/
 */
module.exports = {
 
  // Set true to disable this test
  disabled: false,
 
  'Page: /' : function (browser) {
    browser
      .url(`http://${globals.serverHost}:${globals.serverPort}`)
      .waitForElementVisible('body')
      .assert.titleContains('Name of App')
      .end();
  }
}
```

I used my `globals.js` module to determine the host and port of our Nuxt server. The rest of the code is part of the  [Nightwatch API](https://nightwatchjs.org/guide/#writing-tests), which is super-readable.

Running
The last step is to add the nightwatch command to our `package.json`, so that we can easily run the tests with `yarn` or `npm`.

package.json
```json
{
  "name": "my-cool-app",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "build": "nuxt build --spa",
    "test": "nightwatch"
  },
  ...
}
```

Now we can run our tests from the command line:

```bash
$ yarn run test
```
