Integration testing with Cypress 101

Integration testing your application can be very hard, especially when u are still using selenium based tools. Luckily for us there’s a new player on the market, Cypress. It makes creating tests easy, stable and most of all very good fun to work with.

Create your first test
After setting it up, you can start adding your test files inside the cypress/integration folder. Good practice should be that you create a file for each page or section (like header, footer) that you what to test. Don’t put all tests into one large file.

Let’s start with creating a simple test for the homepage which checks wether the html title is rendered correctly. With the visit() call you can give the url to visit and title() returns a string on which you can match your expectation. You could also chain the calls, but that’s up to you.

describe('Homepage', () => {
it('should have to correct title', () => {
cy.visit('/');
cy.title().should('eq', 'Welcome on the homepage');
});
});

Viewport based testing
But what if our homepage title returns different values for mobile, tablet and desktop? You can easily upgrade your test by adding the viewport() call. Cypress has some built in Apple device presets like ‘iphone-6’, ‘ipad-2’, ‘macbook-13’ but you could also provide width and height to the call. When using one of the presets, you could also change the orientation from landscape to portrait.

describe('Homepage', () => {
it('should have to correct title on mobile', () => {
cy.viewport('iphone-6');
cy.visit('/');
cy.title().should('eq', 'Welcome on the mobile homepage');
});
  it('should have to correct title on tablet', () => {
cy.viewport('ipad-2', 'portait');
cy.visit('/');
cy.title().should('eq', 'Welcome on the tablet homepage');
});
  it('should have to correct title on tablet', () => {
cy.viewport('macbook-13');
cy.visit('/');
cy.title().should('eq', 'Welcome on the desktop homepage');
});
});

Generic setUp function
As you can see in our previous test, is that we’re using a lot of the same code to initiate the tests. A good practice could be to write a generic setUp() function in where we can define viewport and possible other properties on which we base our tests. In this case the visited url stays the same.

function setUp({ viewport }) {
cy.viewport(viewport);
cy.visit('/');
}
...
it('should have to correct title on mobile', () => {
setUp('iphone-6');
cy.title().should('eq', 'Welcome on the mobile homepage');
});

Basic functionalities
With the finishing of the first test and a setUp() function complete, it’s time to add some more basic testing functionality to our test. Let’s say we want to test a newsletter subscribe functionality. In our test we will find the elements by using get() and provide it with the id or classname of the element (just like in jQuery). We fill in our email address and then submit the AJAX form by clicking on the button. After submitting we will wait a few seconds to see the correct message.

describe('Subscibe Newsletter', () => {
it('should show error label if wrong email is typed', () => {
cy.get('.input-email').type('info@domain.com');
cy.get('.form-submit').click().then({ timeout: 2000 }, () => {
cy.get('.form-success').should('have.length', 1);
cy.get('.form-success').should('contain',
'You have succesfully subscribed to our newsletter'
);
});
});
});

You could also do a submit of the form where the user will be redirected to another page. In that case you could check if the url is correct.

cy.get('.form-submit').click();
cy.location('pathname').should('eq', '/newsletter/subscribed');
cy.get('h2').should('contain',
'You have succesfully subscribed to our newsletter'
);

Adding cookies
For some cases like showing a cookiebar, logged in status or other user settings you’ll need to set some cookies. This can be easily done by using the setCookie() function.

describe('Cookiebar', () => {
it('should be visible', () => {
cy.get('.cookiebar').should('be.visible');
});
it('should not be visible', () => {
cy.setCookie('cookiebarCookie', 'accept');
cy.get('.cookiebar').should('not.be.visible');
});
});

XHR calls
You can easily stub and test your AJAX/XHR calls. You can start the server and add a route which stubs the response of your call. When you run the test, Cypress will match the route and returns the mocked data.

cy.server().route('GET', '/api/1', {id: 1, title: 'Mock Title'});

Fetch call
When using the new fetch api and its returning a Promise we can’t really test if we get the correct data. The only way to test these calls is to add a fetch spy on window in your script. This way we can check wether the correct call has been made.

cy.visit(url, {
onBeforeLoad: (win) => {
cy.spy(win, 'fetch');
}
});

In your test you can then call the spy and check wether the correct url has been called.

it('should do the fetch call', () => {
cy.window().its('fetch').should('be.calledWith', '/mock-service');
});

Overrule errors
When running your tests, you only want them to fail if one of your assumptions is failing right? Not because when a third party library throws a console error or something like that. Luckily there’s a simple solution for that. Add the following script to your generic setUp function. This will suppress uncaught exceptions and will define the onerror property on window. This way your tests only fail if one of your expectations is failing.

function setUp({ viewport }) {
Cypress.Cy.prototype.onUncaughtException = () => {};
cy.viewport(viewport);
cy.visit(testUrl, {
onBeforeLoad: (win) => {
win.onerror = null;
}});
};

Roundup
With these basic functionalities you will get a long way testing your application. The cypress.io websites provides excellent documentation and if you can’t find the answer to your problem you can always check the Cypress Gitter channel and ask the community or Brian Mann himself for help.

While Cypress is still in beta all plans are free of charge. When out of beta public plans will be free, but private plans should pay as they go. For more information visit the website.


Thank you for taking the time to reading this story! If you enjoyed reading this story, click the 👏🏻 below so other people will see this here on Medium.

Also, I work at wehkamp.nl one of the biggest e-commerce companies of the Netherlands. We do have a tech blog, check it out and subscribe if you want to read more stories like this one. Or look at our job offers if you are looking for a great job!