0

Say I have a Nightwatch test with two steps that fill out a form. As part of the first step, I need to dynamically query some data from the page (using the Selenium api), then use that data to make additional selenium calls, and use the final result to make custom assertions. The reason I need to use the Selenium api is not that I do not know how to use the normal Nightwatch assertions, but rather that the normal assertions are not sufficient to test the types of things I want to test. Additionally, at the end of the first step a button is clicked that moves on to the next part of the form (in preparation for the second step).

(code version):

module.exports = {
  'Part 1': (client) => {

    // ... do cool stuff

    client.SOME_SELENIUM_COMMAND(...SOME_ARGS..., (result) => {

      client.SOME_OTHER_SELENIUM_COMMAND(...SOME_OTHER_ARGS..., (result2) => {
        // ... do more cool stuff with result2
      });
    });

    // moves the page onto part 2
    client.click(SOME_BUTTON);
  },

  'Part 2': (client) => {
    // ... part 2 stuff
  }
};

My problem is this: the test moves on to the second part before the selenium command result part resolves.

I am aware that internally Nightwatch uses some kind of event queue and EventEmitters to make sure that commands are executed in the correct order however it appears that the click command at the end of part one is being queued up before the commands in the callback can be.

dwoodwardgb
  • 163
  • 5
  • 10

1 Answers1

6

You can use the Nightwatch perform command to perform some other commands and call done() when you want the test to continue to Part 2. You would do something like this:

module.exports = {

    'Part 1': (client) => {

    // ... do cool stuff

    client
    .perform(function(client, done) {

         client.SOME_SELENIUM_COMMAND(...SOME_ARGS..., (result) => {

             client.SOME_OTHER_SELENIUM_COMMAND(...SOME_OTHER_ARGS..., (result2) => {
                 // ... do more cool stuff with result2
                 // Call done to continue to Part 2
                 done();
             });
        });
    })
    // moves the page onto part 2
    .click(SOME_BUTTON);
  },

  'Part 2': (client) => {
    // ... part 2 stuff
  }
};
Fredrik Salin
  • 1,450
  • 10
  • 19
  • Thanks for the answer! What exactly is the .perform command supposed to be used for? (the documentation doesn't seem too descriptive) – dwoodwardgb Jul 13 '16 at 15:28
  • I would say it's basically used when you want to do something that the API don't support by default or if you want to perform async operations. `Perform` could be used to run any javascript, or call the API since the first argument to this function is the browser object. The neat thing is that you can control what operation to run and then call the `done()` function when you want it to continuing to the next step. Did this solve your issue? – Fredrik Salin Jul 14 '16 at 08:54
  • Yeah. Currently I have a lot of abstraction built up (using promises and page objects). It will take some time to figure out how to work this new way of calling the api into that... – dwoodwardgb Jul 14 '16 at 14:57
  • Another way to go is to create [Custom commands](http://nightwatchjs.org/guide#writing-custom-commands) or [Custom assertions](http://nightwatchjs.org/guide#writing-custom-assertions). This is beneficial if you want to do more complex things and if you want to be able to reuse logics. – Fredrik Salin Jul 14 '16 at 15:08
  • I figured as much. – dwoodwardgb Jul 14 '16 at 15:41