Notes:
- The aim of this serie of articles is to help my future me to remember how to setup a Docker container with Jenkins to run all the tests (unit + acceptance) against a Meteor app with build progress displayed in Slack.
- Cypress is not suitable for IE tests right now (but Edge is on the road map)
- I'm pretty new to all these tools, so do not hesitate to comment if you see any mistakes.
- I use Ubuntu and the command lines and file structures may not work as is on another OS, but it is possible to adapt them since every tools used here also work on windows and mac platforms.
Prerequisite
Meteor is a free and open-source JavaScript web framework written on top of Node.js js with many cool features such as reactivity, hot code push, client side database, client/server code reuse capabilities
In this article I assume that you already have a working Meteor development environment and a working Meteor app with source code hosted on a git repo. If not you can create an example app in no time with the guides.
I still use Blaze as front end rendering system, but this guide will work no matter what rendering library you use.
NodeJs and NPM should also be installed on your machine and available from the command line.
Part 1 : Write some acceptance-tests with Cypress
Cypress is a really cool end to end test framework. You can watch this presentation if you don't know it yet and want to learn more about it.
Installation
Using npm :
cd /your/project/path
npm install cypress --save-dev
(or you can download it from the website)
Configuration
You now have a new directory (cypress/) in the root of your project + a new cypress.json config file.
Meteor which is designed to load every .js file it founds in your project directory (except for special directories like imports/) will try to do the same with our new tests files and fail resulting in the infamous => Your application is crashing. Waiting for file change error.
To prevent this, you have to move the cypress/ directory to tests/cypress/ so Meteor will ignore it.
mkdir tests
mv cypress/ tests/cypress
Last part of the setup is to update the cypress.json file (root of your project) to tell Cypress where the files are now located:
cypress.json
:
{
"fixturesFolder": "tests/cypress/fixtures",
"integrationFolder": "tests/cypress/integration",
"pluginsFile": "tests/cypress/plugins/index.js",
"screenshotsFolder": "tests/cypress/screenshots",
"supportFile": "tests/cypress/support/index.js",
"videosFolder": "tests/cypress/videos"
}
Thanks @mitar for updated/improved configuration and the tests/ directory trick!
Running Cypress
The default command line to open Cypress is the following :
./node_modules/.bin/cypress open
But I suggest you to edit your package.json
file :
package.json
:
[...]
"scripts": {
"cypress:gui": "cypress open",
"cypress:headless": "cypress run"
},
"dependencies": {
[...]
Now you can easily start Cypress GUI like this :
meteor npm run cypress:gui
This should display Cypress Gui from which you can find a default test suite called example_spec.js (and launch it if you want to see Cypress in action)
A simple test
It's now finally the time to test our Meteor application.
First of all you have to start your Meteor application as you are used to :
meteor
or (if you have some configuration script to initialize your app) :
meteor --settings path/to/your/settings.json
I will not enter in detail in how to write a Cypress test since everything is in the official documentation. But I will just give you a quick example to show the syntax.
The following test will demonstrate how to test a simple signup form in a Meteor application.
With your favorite IDE, start by adding a new file called signup_tests.js
in the tests/cypress/integration/
directory.
Here is the structure of a simple Cypress test :
signup_tests.js
:
describe('Test signup', function () {
beforeEach(function () {
cy.visit('http://localhost:3000/signup')
})
it('.should() - assert that signup panel has every input field needed', function () {
cy.get('div.jumbotron').within(function () {
// Some assertions using a custom helper
isEnabledAndVisible('input#userName')
isEnabledAndVisible('input#email')
isEnabledAndVisible('input#password')
isEnabledAndVisible('#signupBtn')
// Enter some data
cy.get('input#userName').type("Jean-Denis")
cy.get('input#email').type("me@dev.to")
cy.get('input#password').type("my secret password")
// Click the button
cy.get('#signupBtn').click()
// Validate the new url
cy.url().should('eq', 'http://localhost:3000/logged-in')
})
})
})
// Helpers
function isEnabledAndVisible(element) {
cy.get(element).should('exist').and('be.visible').and('be.enabled')
}
Once you save the file, just switch to Cypress GUI and you should see your test available :
Click on it and Cypress will open a new instance of Chrome and start running the test.
Cool Cypress features
- You can edit the signup_tests.js and see how fast Cypress re-run your test suite each time you save the file.
- Try the selector playground to pick elements easily.
- Hover each step of your test in the left side panel to see screenshots of your app
- Try to open the chrome dev tools to discover helpfull information about events, Ajax requests, ...
Cypress headless
The GUI is pretty cool when you write and debug tests, but when it comes to CI you need a command line to run tests and get results.
If you've edited your package.json scripts section as I suggested you now only have to :
meteor npm run cypress:headless
Otherwise, it is more like ./node_modules/.bin/cypress run
You should quickly get a result like below :
(Tests Starting)
Test signup
✓ .should() - assert that signup panel is well designed (46ms)
1 passing (46ms)
(Tests Finished)
- Tests: 1
- Passes: 1
- Failures: 0
- Pending: 0
- Duration: 46ms
- Screenshots: 0
- Video Recorded: false
- Cypress Version: 2.1.0
(All Done)
Conclusion
We have now a working Cypress installation which we can use to write and run end-to-end tests on a Meteor application.
In the next article, we will setup a Docker image to have a working Jenkins+Cypress+Meteor container and go into the details of how to setup Jenkins to build our Meteor application and run our tests.
Top comments (9)
I think it would be better to put tests under
tests
directory, which is also not compiled by Meteor. Moreover, some paths should point to a file not a directory. I use the followingcypress.json
configuration:Thanks for the input ! I've edited the post.
I also tried to make a custom command to call Meteor methods but I didn't get as far as I would like.
So, where is Part 2?
Me too!
Hi, I followed your tutorial plus the one found at learntdd.in/vue/ and I'm getting errors when trying to do unit tests. Full problem is described here: forums.meteor.com/t/error-message-...
Can you please help?
I'm having trouble finding Part 2. Would you be able to direct me?
Thanks for the article. Have you had any experience with Chimp? I was just wondering how it compares with Cypress.
I haven't tested Chimp but since it rely on Selenium I think you can have a look at articles that compares Selenium and Cypress. I do have tested Selenium (with nightwatchjs) and I really prefer the simplicity of setup and use of Cypress. Especially the fact that since Cypress runs into the browser (not remote controlling it like Selenium) it have a better understanding of events and all javascript stuff and you need way less hacks (wait till render complete, etc...).
It is also really easy (trivial) to debug your application while the tests are running since it is not running in a black box but in a browser right in front of you (just open the chrome dev tools and put some breakpoints).