Testing Meteor with CucumberJS
Introduction
Now that velocity has been elected the official Meteor testing platform it is worth spending some time to learn the thing.
This is an example about how to test a Meteor app on the client side with CucumberJS and the Zombie headless browser.
Setup
We need a Meteor app to test and the testing framework to execute our tests. Let us set it all up
Creating the app
this is a normal Meteor app created with meteor create myApp
once the app folder exists, we need a tests
folder in it with the following structure
+ tests
++ features
+++ step_definitions
+++ support
the cucumber world
the testing environment is setup in a file called world.coffee
or world.js
which goes into the support
folder. Our setup is world.coffee
and looks like this:
module.exports = ->
@World = class MultiWorld extends Cucumber.World
constructor: ->
@zombie = new Cucumber.World.Zombie
@selenium = new Cucumber.World.Selenium if Package.selenium?
@protractor = new Cucumber.World.Protractor if Package.selenium?
super
mrt packages
these packages can be installed with mrt add
* velocity
* cucumber
* velocity-html-reporter
The application
The application is the default Meteor one with just a little tweak: we add an input field and handle the change
event on it to have something to test.
HTML
<head>
<link rel="icon" sizes="16x16 32x32" href="/favicon.png?v=2">
<title>app</title>
</head>
<body>
{{> hello}}
</body>
<template name="hello">
<h1 id="greeting">Hello {{name}}!</h1>
<input id="name"/><br>
{{greeting}}
<input type="button" value="Click"/>
</template>
Template JavaScript
if (Meteor.isClient) {
Template.hello.helpers(
{
greeting: function () {
console.log("retunring greeting text")
return "Welcome to app.";
},
name: function() {
return Session.get("name");
}
})
Template.hello.events(
{
'change #name': function () {
console.log("changing the name");
Session.set("name", $("#name").val());
},
'click input': function () {
// template data, if any, is available in 'this'
if (typeof console !== 'undefined')
console.log("You pressed the button");
}
});
}
Tests
Now we need a test. In Cucumber this is a Feature
which gets implemented in JavaScript or CoffeeScript.
Feature file
the file containing the description is hello.feature
and must be placed in the tests/features
folder of the application. The name of the file is meaningful and must be used in the definition and the implementation of the test scenarios. You can read all about it in the CucumberJs documentation.
@zombie
Feature: Display hello world on the home page
Scenario: Go to the home page and see the hello world message
Given the application has been created
When I go to the home page and enter "Micha" in the name field
Then I should see "Hello Micha!" on the page
Test implementation
In order to have something to execute we need to implement the feature in a javascript file. The file must be called hello.js
in our case. The name must be the same as the feature
module.exports = function () {
this.Given(/^the application has been created$/, function (callback) {
callback();
});
this.When(/^I go to the home page and enter "([^"]*)" in the name field$/, function (name, callback) {
var z = this.zombie
z.home(function(){
z.browser.fill("#name", name)
z.browser.evaluate("$('#name').change()");
z.browser.wait(1000, callback);
})
});
this.Then(/^I should see "([^"]*)" on the page$/, function (greeting, callback) {
var browser = this.zombie.browser;
var actualGreeting = browser.text("#greeting");
if(greeting == actualGreeting) {
callback();
} else {
callback.fail(actualGreeting + " not equal to expected " + greeting);
}
});
}
If you are familiar with zombieJs, you might have noticed that the change event was not triggered in the usual zombie manner with browser.fire
but with the evaluation of some javascript z.browser.evaluate("$('#name').change()")
this was necessary as the normal way did not work with meteor. This is probably linked to issue 181 in zombie
Execution
you can clone the repository with all the files from github with clone git@github.com:drgorb/meteor-cucumber-example.git
change to the application's directory and launch with mrt
you should see the tests pass