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.

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:

ng e2e

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

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: https://nightwatchjs.org/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

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

After: Nightwatch 2

// 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

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

After: Nightwatch 2

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

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

Before: Protractor

// 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 2

// 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

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

After: Nightwatch 2

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

Value

Before: Protractor

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

After: Nightwatch 2

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

Text Content

Before: Protractor

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

After: Nightwatch 2

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

Visibility

Before: Protractor

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

After: Nightwatch 2

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

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

After: Nightwatch 2

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

CSS

Before: Protractor

// 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 2

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

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

Before: Protractor

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

After: Nightwatch

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.

Improve this article