NOTE: Laika is an archived project and there are some other alternatives you can use instead:

Features

It’s real

laika runs tests against your real running app. So It works everytime.

Isolated testing

each test runs on against a separate instance of your meteor app and a clean mongodb database.

Works with both meteor and meteorite

You can use meteor or meteorite as your development workflow. laika can work with both without any additional work for you.

evaluate codes on both server and client at once

You can evaluate codes at both the server and client on a single test. It helps to test unique meteor features like * permission * subscriptions * method calls

Example

test('using both client and the server', function(done, server, client) {
  server.eval(function() {
    Posts.find().observe({
      added: addedNewPost
    });

    function addedNewPost(post) {
      emit('post', post);
    }
  }).once('post', function(post) {
    assert.equal(post.title, 'hello title');
    done();
  });

  client.eval(function() {
    Posts.insert({title: 'hello title'});
  });
});

Tests with multiple clients

Meteor is all about realtime. So we need to test with multiple client. laika simply allows you to test with unlimited(theoretically) no of clients. See usage below.

test('using both client and the server', function(done, server, c1, c2, c3, c4) {
  
});

laika will inspect no of arguments you specified and inject client connector for each.

See example using multiple clients

EventEmitter like communication pattern between your test an evaluate code

Running a piece of code on the server or client and get the result is not ideal. It should be event based. So we’ve a event emitter like api pattern to communicate with the server and client.

Example

server.eval(function() {
  emit('return', 10);
  Meteor.setTimeout(function() {
    emit('after-2-secs');
  }, 2000);
});

server.once('return', function(value) {
  assert.equal(value, 10);
});

server.once('after-2-secs', function() {
  
});

Pass runtime values to evaluated code

We can pass runtime values to evaluated code via arguments.

Example

server.eval(function(a, b) {
  emit('sum', a + b);
}, 10, 20);

server.once('sum', function(value) {
  assert.equal(value, 30);
});

Waiting for templates to render

If you’re using Iron Router, and doing end-to-end or UI tests, you might run into the problem that the UI elements you want to interact with aren’t in the DOM yet at the time your test runs.

You can asynchronously wait for a given element to be present, and only then emit your events. If you’re using jQuery, you can pass in any jQuery selector; otherwise, an element ID as a string in the CSS/jQuery format (#id). Either way, you can also pass a test function that should return true once the element is detected.

Example

describe('Landing page', function() {
  it('Should load for unauthenticated users', function(done, server, client) {
    client.eval(function() {
      waitForDOM('h1', function() {
        emit('login-link-text', $('#login-sign-in-link').text());
        var h1 = $('h1');
        emit('h1-len', h1.length);
        emit('full-text', $('body').text());
        emit('return');
      });
    }).once('login-link-text', function(text) {
      return assert.equal(text, 'Sign in ▾');
    }).once('h1-len', function(len) {
      return assert.equal(len, 1);
    }).once('full-text', function(text) {
      return assert.equal(text.match(/my games/i), null);
    }).once('return', function() {
      return done();
    });
  });
});
Fork me on GitHub