DEV Community

Cover image for NightwatchJs and GitHub Actions
Kiran Parajuli
Kiran Parajuli

Posted on

NightwatchJs and GitHub Actions

NightwatchJs

Nightwatch.js is an integrated, easy to use End-to-End testing solution for web applications and websites, written in Node.js. It uses the W3C WebDriver API to drive browsers in order to perform commands and assertions on DOM elements.

GitHub Actions

GitHub Actions makes it easy to automate all your software workflows, now with world-class CI/CD. You can build, test and deploy your code right from GitHub.

GitHub Actions is available with GitHub Free, GitHub Pro, GitHub Free for organizations, GitHub Team, GitHub Enterprise Cloud, GitHub Enterprise Server, and GitHub AE. GitHub Actions is not available for private repositories owned by accounts using legacy per-repository plans. For more information, see "GitHub's products."

CI using GitHub Actions offers workflows that can build the code in your repository and run your tests. Workflows can run on GitHub-hosted virtual machines, or on machines that you host yourself.

Setup CI/CD

At this point, I assume that you've a working project to test and configure CI for. I'm using this project for demonstration Moving Todo. It is a Django application and tests are written in NightwatchJs.

Now, lets plat our CI configurations:

  • First, we've to choose an os for CI build
  • Second, we've to install dependencies inside the build
  • Next, we've to start server to test
  • At last, we've to run the tests and make it pass.

Webdriver

Personally I do not suggest using jar files for selenium. Rather use docker to start selenium as:

docker run --rm -d --network="host" --name selenium -p4444:4444 selenium/standalone-chrome
Enter fullscreen mode Exit fullscreen mode

Alternatively, you don't have to bother anything about starting and stopping selenium server. Using npm package manages all of that.

  • Have the following packages in your packages.json file:
  "dependencies": {
    "@cucumber/cucumber": "^7.3.0",
    "axios": "^0.21.1",
    "chromedriver": "^91.0.0",
    "cucumber": ">=6.0.5",
    "cucumber-pretty": "^6.0.0",
    "geckodriver": "^2.0.0",
    "iedriver": "^3.150.1",
    "nightwatch": "^1.3.4",
    "nightwatch-api": "^3.0.1",
    "selenium-server": "^3.141.59"
  },
Enter fullscreen mode Exit fullscreen mode
  • Configure nightwatch:
module.exports = {
  src_folders: ["tests"],
  // custom_commands_path: ["test/custom_commands"],
  page_objects_path: "./tests/acceptance/pageObjects",

  test_settings: {
    default: {
      launch_url: process.env.BASE_URL,
    },
    selenium: {
      selenium: {
        start_process: true,
        server_path: require("selenium-server").path,
        port: 4444,
        cli_args: {
          "webdriver.gecko.driver": require("geckodriver").path,
          "webdriver.chrome.driver": require("chromedriver").path,
        },
      },
      webdriver: {
        start_process: false,
      },
    },

    chrome: {
      extends: "selenium",
      desiredCapabilities: {
        browserName: "chrome",
        chromeOptions: {
          args: ["--headless", "--no-sandbox", "--disable-gpu"],
          w3c: false,
        },
      },
    },

    firefox: {
      extends: "selenium",
      desiredCapabilities: {
        browserName: "firefox",
        "moz:firefoxOptions": {
          args: ["--headless"],
        },
      },
    },
  },
};
Enter fullscreen mode Exit fullscreen mode
  • configure cucumber.conf.js
const { setDefaultTimeout, After, Before, BeforeAll, AfterAll } = require("cucumber");
const { createSession, closeSession, startWebDriver, stopWebDriver } = require("nightwatch-api");
const axios = require("axios").default;

setDefaultTimeout(60000);
const availableBrowsers = ["chrome", "firefox"];

const browser = process.env.BROWSER || "chrome";
if (!availableBrowsers.includes(browser)) {
    throw new Error(
    '\nInvalid browser selected.\n' +
    'Available browsers: ' +
    ${availableBrowsers.join(", ")} + '\n'
  );
}

BeforeAll(async () => {
  await startWebDriver({ env: browser });
});

Before(async () => {
  await createSession({ env: browser });
});

After(async () => {
  await closeSession();
});

AfterAll(async () => {
  await stopWebDriver();
});
Enter fullscreen mode Exit fullscreen mode
  • Assumed that tests files are inside tests directory, Now add script to run tests inside your package.json file:
"scripts": {
  "test:e2e": "cucumber-js --require cucumber.conf.js --require tests/acceptance/stepDefinitions --format node_modules/cucumber-pretty"
}
Enter fullscreen mode Exit fullscreen mode

Setup workflow

First, touch a file inside .github/workflows naming main.yml. GitHub uses this file as configuration file for CI build.

Now as our plan lets setup our CI:

name: CI

on:
  push:
    branches: [master]
  pull_request:
    branches: [master]

  workflow_dispatch:

jobs:
  build:
    name: webUi-${{ matrix.browser }}
    runs-on: ubuntu-latest

    strategy:
      matrix:
        browser: ["chrome", "firefox"]

    steps:
      - uses: actions/checkout@v2

      - name: yarn-install
        run: yarn install

      - name: pip-install
        run: pip install -r requirements.txt

      - name: setup-server
        run: |
          make migrate
          make create-admin
          make serve &

      - name: e2e-test
        env:
          BROWSER: ${{ matrix.browser }}
        run: |
          yarn test:e2e
Enter fullscreen mode Exit fullscreen mode

Check your builds

Push the changes adding the main.yml to your repository and navigate to Actions tab in your repository, you can see the started build.
Inspect it, fix it, its all yours.

What I love about GitHub CI

  • you can run sudo commands easily
  • you can easily use docker containers
  • you can pipeline your tests into multiple parallel builds

Top comments (0)