Reusable custom commands.

4,404 views
Skip to first unread message

Diego Mejia

unread,
Jul 21, 2014, 6:11:46 PM7/21/14
to nightw...@googlegroups.com
I'm hoping to put together a clean test suite using custom commands. There are a common set of actions that need to be performed with each test session. I'd like to put together a set of reusable tests, that will be available as nightwatch commands. 

Basically I'm looking for a way to save a common set of tests so that I can use them in another nightwatch test. Ultimately I'd like to write nightwatch code that looks like this:

module.exports = {
 
"High level test" : function(browser){
   browser
     
.login('username','password')
     
.fillForms('data')
     
.logout()
     
.end()
   
}
}


I'm just not sure everything that is possible with custom commands. Is it possible to run nightwatch commands inside of custom commands?

For example:

module.exports = {
   
"Login, click around" : function (browser){
      browser
         
.login('username','password') <<<< Custom command that runs a set of common tests.
         
.click('#button')
         
.end();
   
}
}


login
.js:


exports
.command = function( username, password, callback ){


   
var self = this;
   
this.execute(
     
function(username, password){
      browser
//<<<<<<<<<<<  Is the nightwatch 'browser'/'client' context available here?
       
.setValue('input.username', username)  //<<<< Are nightwatch commands available in this context?
       
.setValue('input.password', password)
       
.click('button.submit');
     
return true;
   
}, [username, password],
   
function(result) {
       callback
.call(this, result)
   
});
   
return this;
}

I'd appreciate any help or guidance for this problem.
Thank you,
Diego

davidlinse

unread,
Jul 22, 2014, 2:11:42 PM7/22/14
to nightw...@googlegroups.com
You've outlined a (complete) sample .. Do you tried to run that ?
Wouldn't this answer all your questions then?

~david
Message has been deleted

Diego Mejia

unread,
Jul 22, 2014, 4:51:18 PM7/22/14
to nightw...@googlegroups.com
I've found the solution to my problem. The key was finding out that the 'this' pointer passed into the custom command is the same object as the browser object used to run nightwatch commands on.

This is what my test setup looks like now.

The customCommand file is able to fill out the login form, this is my reusable piece that I will invoke as a nightwatch command in a higher level test file.

login.js
---------

exports.command = function(username, password, callback) {
    var self = this;
    this
        .frame(null)
        .waitForElementPresent('input[name=username]', 10000)
        .setValue('input[name=title]', username)
        .waitForElementPresent('input[name=password]', 10000)
        .setValue('input[name=password]', password)
        .click('button.submit');

    if( typeof callback === "function"){
        callback.call(self);
    }
    return this; // allows the command to be chained.
};

test.js
----------------

module.exports = {
    "Log in, click around." : function (browser) {
        browser
                         .url("http://localhost/app.html")
            .login('USERNAME', 'PASSWORD')
            //At this point I've already logged in, with one command.
            .assert.containsText('#main', 'Welcome!')
            .end();
     }
}

This allows me to write very clean tests, I will note a possible downside though. The tests names get a little bit screwed up, because in this case the only test that will be visible is "Login, click around". The custom command isn't really named as a step in the test suite. And I could see a lot of tests being run under one 'nightwatch step'.

I'm comfortable with that limitation.

I hope this clears up what I was hoping to do.

Thank you,
Diego Mejia

Josh

unread,
Apr 5, 2016, 1:35:12 PM4/5/16
to NightwatchJs
I have had the same issue with several commands being wrapped into one custom command and the lack of info it causes in the console when running tests.
To remedy this I just use the callback function that's passed as the final argument to console.log() whatever I need it to print into the console.
Example: 
.setValue('input.username', username, function() {
  console.log('Some text I want printed out')
})

This also helps with debugging so I know where the test is at when issues arise or so I can watch what the browser is doing while the test is executing that command.

Now my next goal is to get the console.logs included in the reporting.....

Hope this helps!
Reply all
Reply to author
Forward
0 new messages