Skip to content

Instantly share code, notes, and snippets.

@awatson1978
Last active November 19, 2019 21:45
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save awatson1978/e9fd118781e68c5e851e to your computer and use it in GitHub Desktop.
Save awatson1978/e9fd118781e68c5e851e to your computer and use it in GitHub Desktop.
Nightwatch Unit Testing for Meteor

Nightwatch Unit Testing Functions for Meteor

Unit Testing Client-Side Javascript from the Client

Meteor has a fairly extensive API, and places various objects on the global scope of the browser's Javascript environment, such as Session, Template, Collection, and of course Meteor. Here is how to test methods on such objects using Nightwatch and the Selenium .execute() API.

exports.command = function(sessionVarName, expectedValue) {
  var client = this;
  this
    .execute(function(data){
      return Session.get(data);
    }, [sessionVarName], function(result){
      client.assert.ok(result.value);
      if(expectedValue){
        client.assert.equal(result.value, expectedValue);
      }
    })
    return this;
};

Unit Testing Server-Side Meteor-Methods from the Client

Meteor provides remote procedure calls (RPC) using the Meteor.methods() and Meteor.call API. This doesn't let us test all the code on the server; but it does allow us to test anything that's within the Meteor.method({}) scope.

//
exports.command = function(methodName, arguments, callback) {

    var self = this;
    this
      .timeoutsAsyncScript(5000)
      .executeAsync(function (meteorMethodNameAndArguments, meteorCallback) {
          var meteorMethodName = meteorMethodNameAndArguments[0];
          var meteorArguments = meteorMethodNameAndArguments[1];
          Meteor.call(meteorMethodName, meteorArguments, function (meteorError, meteorResult) {
              var response = (meteorError ? { error: meteorError } : { result: meteorResult });
              meteorCallback(response);
          });
      }, [[methodName, arguments]], function (response) { // you need to pass an ARRAY of ONE argument, must be a bug          
          if (response && response.value && response.value.error) {
              throw 'Meteor apply (call) returned an error: ' + response.value.error;
          } else if (typeof callback === 'function') {
              callback(null, response.value.result)
          }
      });

    return this;
};

Example Meteor App

So, lets see how this works in practice. A simple HelloWorld app written with Meteor might look like the following:

if(Meteor.isClient()){
  Session.setDefault("loggedInUser", "Jane Doe")
}
if(Meteor.isServer()){
  Meteor.methods({
    testMethod:function(){
       return "abc";
    },
    testMethodWithInput:function(value){
       return value * 2;
    }
  });
}

And the Nightwatch unit-test walkthrough of the above code would like the following:

module.exports = {
  "Check Client Session" : function (client) {

    var sessionBar = false;
    client
      .url("http://localhost:3000/list/users")
      .checkSession("loggedInUser", "Jane Doe")
      .end();
  },
  "Check Server Methods" : function (client) {

    var sessionBar = false;
    client
      .url("http://localhost:3000/list/users")
      .meteorCall("testMethod", false, function(error, result){
        client.assert.equal(result, "abc");
      })
      .meteorCall("testMethodWithInput", 3, function(error, result){
        client.assert.equal(result, 6);
      })
      .end();
  }
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment