Migrating from Protractor to Nightwatch

Introduction

Protractor was a popular end-to-end test framework for Angular and AngularJS applications. However, Protractor will no longer be shipped with the new Angular Projects as of Angular 12. This migration guide to help make the transition from Protractor on your team to Nightwatch easier.

Getting Started

Install the Nightwatch Angular schematic to add Nightwatch to your Angular project.

bash
ng add @nightwatch/schematics

This will install Nightwatch, add different scripts to run Nightwatch, scaffold Nightwatch config, and test files. It also prompts you to remove Protractor from your project and reconfigure your default ng e2e command to use Nightwatch.

You can now run Nightwatch with the following command:

bash
ng e2e

You can also use the following command to run Nightwatch alternatively.

bash
ng run {your-project-name}:nightwatch-run

Next Steps

Your existing e2e tests will be migrated to a new location i.e. Protractor. Sample tests will be added to the Nightwatch folder to get you started with your first test in Nightwatch.

You will see these changes in your project, after you had run schematics on your project.

Folder changes

  1. Now, You need to modify your existing tests to Nightwatch. To being with you can start with Assertions, Expect, Page Objects and API commands.

  2. We had added few examples in this guide, but if you need more information please visit: /api/

Check out our Nightwatch Schematic documentation for more details like running tests in a specific browser, etc.

Working with the DOM

Getting the DOM Elements

Getting a single element

In e2e tests, one of the most common things to do in a webpage is to get one or more HTML elements. In Nightwatch, you don't need to make any changes here, as everything works as before.

Before: Protractor

javascript
// Find an element using a css selector.
element(by.css('.myclass'))

After: Nightwatch v2

javascript
// Find an element using a css selector.
element(by.css('.myclass'))
Getting multiple elements

If you need to access more than one element on the page, you must chain the .all() method. However, in Nightwatch, you can use browser.findElements.

Before: Protractor

javascript
// Find elements using a css selector.
element.all(by.css('.myclass'))

After: Nightwatch v2

javascript
// Find mulltiple elements using a css selector.
browser.findElements(by.css('.myclass'))

// or simply:
browser.findElements('.myclass')
Interaction with DOM Elements

Before: Protractor

javascript
// Click on the element
element(by.css('button')).click()

// Clear the text in an element (usually an input).
element(by.css('input')).clear()

// Check the first checkbox on a page
element.all(by.css('[type="checkbox"]')).first().click()

// Scroll an element into view
browser
  .actions()
  .mouseMove(element(by.id('my-id')))
  .perform()

After: Nightwatch v2

javascript
// Click on the element
browser.click(element(by.css('button')))

// or with default css selector as locate strategy:
browser.click('button')

// Clear the text in an element (usually an input).
browser.clearValue('input')

// Check the first checkbox on a page
// Nightwatch by default search for first element, and perform click event if there are multiple element present
browser.click('[type="checkbox"]')

// Scroll an element into view
browser.moveToElement(element(by.id('my-id'), 0, 0))

// or, using the actions api:
browser
  .perform(function() {
    return this.actions().mouseMove(element(by.id('my-id')))
  })

You can learn more about working with DOM elements in our official documentation

Assertions

Length

Before: Protractor

javascript
const list = element.all(by.css('.custom-class'))
expect(list.count()).toBe(3)

After: Nightwatch v2

javascript
expect.elements('.custom-class').count.to.equal(3);

Value

Before: Protractor

javascript
expect(element(by.css('input[name="first_name"]'))).getAttribute('value').toBe('foo')

After: Nightwatch v2

javascript
expect(element('input[name="first_name"]')).attribute('value').toEqual('foo');

Text Content

Before: Protractor

javascript
// assert the element\'s text content is exactly the given text
expect(element(by.id('user-name')).getText()).toBe('John Doe')

After: Nightwatch v2

javascript
expect.element(by.id('user-name')).text.toEqual('John Doe');

Visibility

Before: Protractor

javascript
// assert button is visible
expect(element(by.css('#main ul li a.first')).isDisplayed()).toBe(true)

After: Nightwatch v2

javascript
expect('#main ul li a.first').to.be.visible;

// The following will end the test:
browser.assert.visible('#main ul li a.first');

// However this will just log the failure and continue:
browser.verify.visible('#main ul li a.first');

Existence

Before: Protractor

javascript
// assert the spinner no longer exists
expect(element(by.id('loading')).isPresent()).toBe(false)

After: Nightwatch v2

javascript
browser.assert.not.elementPresent(by.id('loading'))

CSS

Before: Protractor

javascript
// assert #main ul li a.first has css style "block" for "display" property
expect(element(by.css('#main ul li a.first')).getCssValue('display')).toBe('block')

After: Nightwatch v2

javascript
browser.assert.cssProperty(by.css('#main ul li a.first'), 'display', 'block');

Navigating websites

When you need to visit a page in your test, you can use following code:

Before: Protractor

javascript
it('visits a page', () => {
  browser.get('/about')
  browser.navigate().forward()
  browser.navigate().back()
})

After: Nightwatch v2

javascript
it('visits a page', () => {
  browser
    .navigateTo('/about')
    .forward()
    .back()
})

Questions or having issues?

The best way to ask for questions or report issues related to Nightwatch Angular Schematic is to open an issue.