Basic Generators in JavaScript

I have been watching a movie last night when my mind spun on a different thread and remembered a JavaScript language feature that have existed for some time now, but I have never had the chance to use. At least, directly.

We do bleeding edge JavaScript at the office. That means we have all these new language features at our disposal as early as possible through the use of Babel. We write JavaScript code using the newest language specification (ECMAScript 6/7) and our code gets transpiled into ECMAScript 5. We have been using all the nifty features such as importasync/awaitspread/rest operators and destructuring as early as last year. These are just the new ES6 features that I can think of off the top, maybe because they are the most practical ones.

There is one feature, however, that can be really powerful but I have not really been able to leverage. They are generators. Prior to V8 v5.5 and Node v7.6.0, Babel's async/await and other asynchronous libraries around has been using generatorsunder the hood to implement this feature.

But what are generators? According to the venerable MDN page:

A generator is a special type of function that works as a factory for iterators. A function becomes a generator if it contains one or more yield expressions and if it uses the function* syntax.

MDN's definition is clear and straightforward, but let me rephrase it from what I have understood. Aside from producing iterables, think of a generator as a function that you can play and pause. This characteristic enables it to implement asynchronous programming, and when used with promises, you can come up with all sorts of things- including your own async library if you want to make one for learning purposes.

Let's dig into some basic code examples to solidify our understanding of generators:

function* counter() {
  for (let i = 0; i < 5; i++) {
    yield i
  }
}

This function was declared using function* and has a yield inside the function body, so this must be a generator. When we invoke it and assign the result to a variable like so, let c = counter(), we get back an iterable object that we can use to iterate over the values of i. An iterable object in JavaScript must have a next()method. This method returns an object that contains a value and a done property. Let's see that in action:

/***************************************************
  Using next() to step through the values explicitly
****************************************************/
let c1 = counter();

console.log(c1.next().value);
// 1
console.log(c1.next().value);
// 2
console.log(c1.next().value);
// 3
console.log(c1.next().value);
// 4
console.log(c1.next().value);
// 5

/***************************************************
  Using a for-of loop
****************************************************/
let c2 = counter();

for (const num of c) {
  console.log(c);
}

// 1
// 2
// 3
// 4
// 5

/***************************************************
  Using the done property explicitly
****************************************************/
let c3 = counter();

let i = c3.next();

while (!i.done) {
  console.log(i.value);
  i = c3.next();
}

// 1
// 2
// 3
// 4
// 5

We went through three different ways on how to iterate over the iterable that was returned by our counter generator. On the first example, we manually stepped through the iterator by using next(). We know that next() returns an object with a valueand a done property, and so we were able to chain .value every time we log the iteration to the console. This shows us one of the concepts that we have discussed earlier: we were able to play and pause the generator's execution by using the next() method. Another interesting thing is that it remembers its internal statethrough its iterations.

It works this way: the generator function stops immediately at every yield statement, and passes the value on its right to the object being returned by next(). We used a loop on our example, and by doing so, the loop gets suspended every time it encounters a yield statement.

Another thing worth knowing is that we can alter the generator's internal state from outside the generator by passing in an argument to next():

function* counter (limit) {
  for (let i = 1; i <= limit; i++) {
    let j = yield i;
    if (j) limit = j;
  }
}

/***************************************************
  Passing a value to next() to alter internal state
****************************************************/
const c1 = counter(2)

console.log(c1.next().value); // 1
console.log(c1.next().value); // 2
console.log(c1.next().value); // undefined

/***************************************************
  Passing a value to next() to alter internal state
****************************************************/
const a2 = counter(2)

console.log(c2.next().value); // 1
console.log(c2.next().value); // 2
console.log(c2.next(5).value); // 3
console.log(c2.next().value); // 4
console.log(c2.next().value); // 5

The example above is yet another contrived modification to our earlier example. This counter generator accepts an argument as the limit to the number of values it can generate. It has the same loop as the above example, except that the control is now dependent on the limit parameter that was passed to it.

Inside the loop body, we have declared a variable j that is being assigned to the value of yield. This expression is being followed by another control structure: an if statement that checks the value of j. The value of j will replace the value of limit if it has a truthy value.

As I have mentioned prior to showing the examples, we can control the internal state of generators by passing an argument to the next() method. This argument will become the value of yield inside the generator, and as such we can assign it to control its behavior.

This can be seen above where we both declared a generator with an initial limit of 2 values. On the first one, we did not pass an argument to next() and so we were only able to iterate through two values. On the second example, we did the same thing, but we passed in a value of 5 as an argument to next(). This altered the generator's internal limit from two to five values, enabling us to get three more values out of it.



On this post, we have learned about the basics of ES6's generators. We went through the basic implementation and usage through some simple examples. We found out that generator functions are declared using the function* keyword, and contains at least one yield statement/expression. We also found out that a generator produces and iterable with a next() method. Since this post is getting long, I have decided to split this post into two. On my next post, we will explore how to implement basic async/await functionality through the use of generators and promises.

Introducing Cheers Alerts


Cheer Alerts Demo GIF

This week, a friend decided to create his own JavaScript library. It was a small and simple in-browser notification library called 'Cheers Alert'. The library was inspired by Toastr, and as of this writing, depends on jQuery and FontAwesome.

The library is already available on npm. I have submitted a pull request that added [Grunt] to this project. This enabled the library to be bundled as a standalone browser library through the use of Browserify and other Grunt plugins such as Uglify and mincss. This automation allowed him to easily maintain and develop future versions of the library. Aside from npm, the library can also be installed through Bower.

As this is his first open source package, he will be actively developing this library. It's open for feedback and contributions, so please check the source out at Github.

You can try the library out by visiting the demo page.

Using Gagarin’s DDP Client to test Meteor methods, publications and subscriptions

On my previous post, we briefly went over unit testing in Meteor and Mantra by using Sinon’s spy and stub. We have discussed the difference between the two functions and determined when to use them for our unit tests.

Today, we are going to go through basic integration testing with methods and publications/subscriptions using Gagarin’s DDP client. Gagarin is the Mantra spec’s recommended testing framework for doing integration testing. It is versatile and can do a lot more that what we are going to cover here, like using chromedriver and Selenium for end to end testing, for example.

About Gagarin

According to the project’s documentation,

Gagarin is a mocha based testing framework designed to be used with Meteor. It can spawn multiple instances of your meteor application and run the tests by executing commands on both server and client in realtime. In other words, Gagarin allows you to automate everything you could achieve manually with meteor shell, browser console and a lot of free time. There’s no magic. It just works.

Gagarin is based on Laika, another testing framework created by Arunoda. According to the documentation, it can be thought of as Laika 2.0, though it is not backward compatible. The main differences between Gagarin, Laika and Velocity can also be found on the documentation above.

Installation

We can simply install Gagarin by running

npm install -g gagarin

Once we have written some tests, we can just run this command at the root of our app directory:

gagarin

By default, it will look for files that are in the tests/gagarin/ directory. It will build our app inside .gagarin/local/ along with the database that it will use for the duration of the test, which can be found at .gagarin/db/.
Now that we have a basic understanding of how to install and run Gagarin, let’s proceed and look at the code snippets that we are going to test.

Meteor code snippets (for testing)

In order for us to understand what we are testing, the code snippets will be included here so we can easily reference the functions and how they are being tested. I have simplified these code snippets so that we can focus more on testing.

Collection

const Categories = new Mongo.Collection(‘categories’);

Publications

Meteor.publish(‘categoriesList’, () => {
  return Categories.find()
});
Meteor.publish(‘categoriesOwnedBy’, (owner) => {
  check(owner, String);
  
  return Categories.find({owner: owner});
});

Methods

Meteor.methods({
  ‘categoriesAdd’(data) {
     check(data, Object);
 
     Categories.insert({
       name : data.name,
       owner: data.owner,
       createdAt : new Date(),
     });
   },
   ‘categoriesUpdate’(data) {
     check(data, Object);
     
     Categories.update({_id:data._id},{$set:{
       name : data.name, 
       owner: data.owner,
       modifiedAt : new Date(),
     }});
   },
});

Writing Gagarin Tests

Now that we have seen the code that we are going to test, we can now start writing basic tests in a single JavaScript file inside tests/gagarin/. Because Gagarin is based on Mocha, it has the same describe — it structure. Chai’s expect is also exposed for doing more semantic assertions.

Testing the categoriesAdd method

The test we are going to do first is to check whether or not we can add something to the categories collection.

describe(‘Categories’, function() {
  var app = meteor({flavor: “fiber”});
  var client = ddp(app, {flavor: “fiber”});
  it(‘should be able to add’, function() {
    client.call(‘categoriesAdd’, [{name: ‘First category’}]);
    client.sleep(200);
    client.subscribe(‘categoriesList’);
    var categories = client.collection(“categories”);
    expect(Object.keys(categories).length).to.equal(1);
 }); 
}

We are defining the initial describe block that we are going to use for this example. Gagarin gives us two useful global functions that are essential for running tests: meteor and ddp.

meteor is used to spawn a new Meteor instance that we have assigned to the app variable. Meteor uses fibers by default, so we need to specify it as the flavor. ddp allows a client to connect to the Meteor instance that we have just created by passing the reference of the instance and the flavor as its arguments.

Since we now have our Meteor app and our client configured, we are ready to proceed with our first test case: making sure that we can successfully add a new category.

Inside our it block, we are calling the Meteor method categoriesAdd. Gagarin provides our client with a handy call function that works exactly the same way as Meteor.call. The only difference is that the arguments need to be inside an array, regardless of its number.

We then use the sleep function to add a little delay so that we can make sure that the new document comes to the client. We are subscribing to our categoriesList publication through the handy subscribe function of our client. Just like the call function, this is similar to Meteor.subscribe, which makes it very straightforward.

After subscribing to our publication, we now check if the document has been inserted by our Meteor method to the collection. We do that by calling the collection function of our client, passing the name of the MongoDB collection as an argument. It returns an object that looks like this:

{ Hpu6Z4h7ZFtC6Q77m: 
 { _id: ‘Hpu6Z4h7ZFtC6Q77m’,
 name: ‘First category’,
 owner: null,
 modifiedAt: 2016–06–07T08:29:06.026Z,
 createdAt: 2016–06–07T08:29:06.026Z } }

It looks similar to something that we would get if we query our collection using find, aside from the fact that instead of getting back an array or a cursor, we are getting an object which has the _id field as a key.

We then use Chai’s expect function to do a simple assertion and that completes our first test. Object.keys has been used on the object that was returned by the collection function, so we can just expect the resulting array to have a length of 1. This test makes us sure that the client can call our method, and can receive the the document through our publication.

Testing the categoriesUpdate method

We now have a basic test that checks if we can insert and retrieve documents, what we want to do next is to check if we can update a certain category from our collection. The process is similar to what we did on the last section (still goes inside the same describe block):

it(‘should be able to update’, function() {
  client.subscribe(‘categoriesList’);
  var categories = client.collection(“categories”);
  var id = Object.keys(categories)[0];
  client.call(‘categoriesUpdate’, [{_id:id, name: ‘updated    category’}]);
 client.sleep(200);
 
  categories = client.collection(“categories”);
  expect(categories[id].name).to.equal(‘updated category’);
});

The only thing that is new here is that we are storing the id of the category that we want to update so we can use it when we call categoriesUpdate. We can then check if the name has been updated by using expect.

Testing categoriesOwnedBy publication

The next thing that we will test is the categoriesOwnedBy publication. Since we did not use the owner field in our previous examples, we will put this test on a separate describe block. That will allow us to spawn a new Meteor and database instances that has nothing to do with the previous one.

describe(‘categoriesOwnedBy publication’, function() {
  var app = meteor({flavor: “fiber”});
  var client = ddp(app, {flavor: “fiber”});
  it(‘should only publish a specific users category’, function() {
    app.execute(function() {
      var categories = [
        { name: ‘Category 1’, owner: ‘John’ },
        { name: ‘Category 2’, owner: ‘Jessica’ },
        { name: ‘Category 3’, owner: ‘John’ }
      ];
      Meteor.call(‘categoriesAdd’, categories[0]);
      Meteor.call(‘categoriesAdd’, categories[1]);
      Meteor.call(‘categoriesAdd’, categories[2]);
   });
  client.subscribe(‘categoriesOwnedBy’, [‘John’]);
  
  var johnsCategories = client.collection(‘categories’);
  
  expect(Object.keys(johnsCategories).length).to.equal(2);
});

This looks similar to our two previous examples, but this time I am using the execute function of our Meteor instance. It accepts a callback function as an argument, and the contents of that function will be executed in the server context. Notice how we have access to Meteor.call inside this function?

We then go back to the client context and subscribe to our categoriesOwnedBypublication, passing ‘John’ as our argument. After fetching the contents of the collection, we are checking if we are getting the expected number of documents that was published by our collection.

Running our test

If we run gagarin on the root folder of our application, we will get something similar to this:

Conclusion

Using the examples above, we have seen how to create simple integration tests using Gagarin on Meteor. These test cases might seem contrived, but the idea here is to get an overview of how to use Gagarin’s DDP client to perform basic integration tests that deals with Meteor methods, publications and subscriptions.


Using Sinon’s Spy and Stub in Mantra (Unit Testing)

With the release of Meteor 1.3, unit testing has never been easier in Meteor. Our team recently decided to adopt Arunoda’s Mantra spec for developing Meteor applications. It is an application architecture which allows for a more modular approach with clear separation of concerns with the client and the server side. It has been a rough month for us since the spec is new and there are limited learning resources available. There were also a lot of things to learn since adopting the Mantra spec meant that we have to learn React for the presentation logic, instead of sticking with Blaze.


Unit testing is something that can be easily accomplished with the Mantra spec. Since it is modular and it clearly separates the presentation logic from the business logic through containers, components and actions, everything can be unit tested. Meteor 1.3 also introduced native NPM support, which means that using familiar tools such as Mocha, Chai and Sinon can be imported in a straightforward manner. This is going to be my first blog post and so I am only going to explain Sinon’s spy and stub methods as they were used in Arunoda’s mantra-sample-blog application.

Spies

People who are new to unit testing tools in JavaScript (with me included) were initially confused about the difference between Sinon’s spy and stub. It turns out that a spy is a basic function that you can use in Sinon, and that stubs and mocks were built on top of it.

According to the Sinon.JS documentation, a spy is

a function that records arguments, return value, the value of this and exception thrown (if any) for all its calls. A test spy can be an anonymous function or it can wrap an existing function

What this means is that a spy can be used as a replacement for an anonymous callback function or you can wrap an existing function into it so that you can spy on its behavior. For example, if you have a function that accepts another function as an argument to be called back later after a certain condition, you can instead pass Sinon’s spy() function as the callback. You can then assert or use Chai’s expect() to see if that function was called by using spy()’s calledOnce(). Additionally, you can check if the correct arguments were passed to it by using its calledWith(). You can check the different spy functions that are available here.

Now let’s look at how spies are used in the Mantra sample blog application. We are going to use the tests that were written for the posts action. Let’s check this code snippet out:

it('should call Meteor.call to save the post', () => {
  const Meteor = {uuid: () => 'id', call: spy()};
  const LocalState = {set: spy()};
  const FlowRouter = {go: spy()};
  
  actions.create({LocalState, Meteor, FlowRouter}, 't', 'c');
  
  const methodArgs = Meteor.call.args[0];
  
  expect(methodArgs.slice(0, 4)).to.deep.equal([
    'posts.create', 'id', 't', 'c'
  ]);
  expect(methodArgs[4]).to.be.a('function');
});

In the test block above, we are testing if our action will correctly invoke a Meteor Method in the server through Meteor.call(). The first three lines are creating local objects for MeteorLocalState and FlowRouter to be used exclusively in this test case. In the Mantra spec, these are exported as the application context inside client/configs/context.js.

Actions in Mantra receive this application context as the first parameter. We are creating local objects in lieu of the real app context and by doing so, we can trick the action into thinking that it is receiving its first expected argument (which is the app context).

Next, we spy on how these objects are used inside the action that we are testing. See how the Meteor object that we have passed contains a call property, which is a Sinon’s spy() function? When the action gets invoked on Line 6, it will go ahead and invoke Meteor.call() inside it. The Meteor object that it will receive is something that we have just created for spying purposes, so we have access to the arguments that were passed into it when it was invoked (Lines 7 — 12). We used the arguments that we have obtained through spying to verify that our function is invoking Meteor.call() with the correct arguments.

This is what the create action looks like, for reference:

  create({Meteor, LocalState, FlowRouter}, title, content) {
    if (!title || !content) {
      return LocalState.set('SAVING_ERROR', 'Title & Content are required!');
    }

    LocalState.set('SAVING_ERROR', null);

    const id = Meteor.uuid();
    Meteor.call('posts.create', id, title, content, (err) => {
      if (err) {
        return LocalState.set('SAVING_ERROR', err.message);
      }
    });
    FlowRouter.go(`/post/${id}`);
  }

Stubs

Now that we are done with spies, and have a basic understanding on how they work, let’s work with stubs. Stubs are just like spies, and in fact they have the entire spy() API inside them, but they can do more than just observe a function’s behavior. According to the Sinon API, stubs are:

functions (spies) with pre-programmed behavior. They support the full test spy API in addition to methods which can be used to alter the stub’s behavior.

and they should be used when you want to:

Control a method’s behavior from a test to force the code down a specific path. Examples include forcing a method to throw an error in order to test error handling.

or

When you want to prevent a specific method from being called directly (possibly because it triggers undesired behavior, such as a XMLHttpRequest or similar).

Okay, so where spies can observe and spy on how a function is going to be called, the number of times it’s going to be called and the arguments that were sent with it, stubs can do all these, plus you can also programmatically control its behavior.

Let’s check how it is used on the post action test inside the sample blog application:


    it('should call Meteor.call to save the post', () => {
      const Meteor = {uuid: () => 'id', call: spy()};
      const LocalState = {set: spy()};
      const FlowRouter = {go: spy()};

      actions.create({LocalState, Meteor, FlowRouter}, 't', 'c');
      const methodArgs = Meteor.call.args[0];

      expect(methodArgs.slice(0, 4)).to.deep.equal([
        'posts.create', 'id', 't', 'c'
      ]);
      expect(methodArgs[4]).to.be.a('function');
    });

This particular test will check if our action will set an error message if something goes wrong after the Meteor Method call. Just like what we did with the spy example, we are setting local objects to be used as the context for our action function.

In Mantra, the LocalState is a Meteor reactive-dict data structure (a reactive dictionary) which is mainly used to handle the client side state of the app, although it is mostly used to store temporary error messages. We are creating a LocalState object here to mimic the app context’s LocalState. We are setting its set property as a spy function, so we can later see if our action will set the appropriate error message by checking the arguments that were passed into it.

Notice that this time, we are using a stub() instead of a spy() for our local Meteor object. The reason for this is that we are no longer just observing how it is going to be called, but we are also forcing it to respond in a specific way.

We are checking our action’s behavior once the call to a remote Meteor method returns an error and if that error will be stored in the LocalState accordingly. In order to do that, we need to reproduce that behavior, or make the call() function in our local Meteor object return an error. That is something that a spy() will not be able to do since it can only observe. For this scenario, we will use the stub’s callsArgWith()* function to set our desired behavior (Line 6).

We will give callsArgWith() two arguments: 4 and the err object that we have defined in Line 5. This function will make our stub invoke the argument at index 4, passing the err as an argument to whatever function is at that position. If you are going to look at our create action above, Meteor.call() is invoked with five arguments, the last or the one in the fourth index is a callback function:

Meteor.call(‘posts.create’, id, title, content, (err) => { 
  if (err) { 
    return LocalState.set(‘SAVING_ERROR’, err.message); 
  } 
});

We have to remember that this Meteor.call() that is being invoked here is the local object that we have created and passed explicitly into our create action for testing purposes. As such, this is the stub in action, and it doesn’t know that the last argument when it is invoked is going to be a callback function, so we have to use the callsArgWith() with the err object. Inside this callback, the create action will then store the error message in the LocalState object that we have passed in. Since the set() function of that LocalState object is a spy, we can conclude our test by checking if the arguments that were passed to this spy function matches the error message that we are expecting (Line 9).

This wraps up our discussion of how Sinon’s Spy and Stubs methods are being used in Mantra Unit Testing. As a recap, a spy just observes a certain function, or can take the place of a anonymous callback function so we can observe its behavior. A stub does more than that, by allowing us to pre-program a function’s behavior. If I have provided any wrong information, please feel free to correct me in the comments. :)

*The callsArg and yields family of methods have been removed as of Sinon 1.8. They were replaced with the onCall API.