End to end tests (E2E) with NodeJs, RethinkDB, and cypress.io

Cypress is an amazing relatively new tool to test everything that runs in a browser.

End to end, as I understand it, means all operations that any user of our site or app that runs in a browser can perform.

Example of operations are: Logging in, signing in, getting the needed information, creating new information, updating existing information, and deleting desired info.

All of the actions above are called CRUD operations. ( Create, Read, Update, Delete ) that users perform on our site or app that runs in tune ( gladly and hopefully responsively) with all industry most widely used browsers.

Did we miss something ? Well, I think yes and no. For example, our app can also send emails, call other programs, wait and listen for incoming notifications, and send push notifications on its own, with no user interference.

Not to mix things up, we can classify the above actions into further different tests, unit and integration tests.

Example: Sending an email will fall under unit tests, we can call this test “Send Email Test” and we will only and only test the “actual” sending of an email, without it being affiliated or associated in any way with any other action that a user,or our app performs.

When an email is sent upon completion of some user’s or app’s action, we will categorize this under Integration Tests, because the sending of an email is integrated, related, and based on another action, which in turn calls our “Send Email” functionality. So we can create a new integration test and call it “ Send email on log in”.

So as you can see, with this simple approach, we have identified already three different kinds of tests that we can courageously create in Cypress.io and thankfully cypress can do all that. It is very versatile, fast and easy to grasp, learn, and use.

I have written a small NodeJs-RethinkDB app for myself to write recipes. Cypress “recipes” is a philosophy around tests that you write. You can add a little bit of pepper, salt, make assertions for some actions to be true or false, and predict the future of your test a little bit, then run the test and check the results.

Personally I like writing basic recipes, that fit all tastes, more or less. Because they do fit all tastes, and everyone likes them.

You can find the app on GitHub here:

https://github.com/jinan-kordab/nodejs-rethinkdb-app

You can do whatever you want with this app, but please do not delete it because I need it, like I said before. :)))))

This app is pure NodeJs app and has a RethinkDb as a backend for storing organic foods information. The reason I chose RethinkDb is because it has something called “changefeeds”. When changefeeds are enabled in our app, with the help of socket.io, RethinkDb sends us notifications upon some changes in its table data that we specify.

Let’s say we want to receive a notification once a user updates a table in our database. RethinkDb will listen by itself for any changes that occur on that table, and send our app a notification. Inside our app, we will use socket.io to emit or push this notification to any of our front end pages written with EJS templates.

All this functionality is inside the app mentioned above, with Admin front end EJS page that accepts those notifications.

That being said, I think we can safely categorize the above changefeeds under End to End tests, because this functionality is a result of a user interfering with our tables. But, I am more inclined towards putting it under Integration Tests folder, because RethinkDb changefeeds functionality is integrated with user’s CRUD operation, and can not be tested separately as a unit test on its own. Why ? Because if we ask ourselves a question “How do we invoke a RethinkDB changefeed?” , The answer is : “We need to make some changes in our database”. Therefore we have a CRUD operation. But you may argue and say that what if the user does not invoke the CRUDE operation and it was invoked by another function call or another Promise in our app. Then and only then I would safely say that we need to put it under integration tests folder. Thus, for this example, I added it as E2E test.

Please find below the Admin cypress.io page that contains the E2E test for our changefeeds, relying on socket.io.

/// <reference types="cypress" />
import Chance from "Chance";
const chance = new Chance();
//Testing Changefeeds in RethinkDB
context("Admin page", () => {
beforeEach(() => {
cy.generalLogin();
});
it("navigate to admin page and add new sweet", () => {
//Navigate
cy.visit("http://localhost:3000/admin&quot;);
cy.contains("Welcome!");
//Generate random sweet ID
const randNum = chance.integer({ min: 2022, max: 9007199254740991 });
// Add new sweet manually using POST
cy.request({
method: "POST",
url: "/food/products/sweet/",
form: true,
body: {
color: "CYPRESS-Color",
property: "CYPRESS-Property",
id: "" + randNum + "",
name: "CYPRESS-Name",
},
}).as("sweet");
cy.get("@sweet").should((response) => {
cy.wait(500);
});
// // //Check if our newly added sweet is found
cy.contains("" + randNum + "");
});
});
view raw admin.spec.js hosted with ❤ by GitHub

After you start Cypress within this app, click on responsive.spec.js , and you will see tests executing as in the video below.

All dependencies for this NodeJs app are listed in Github readme file.

Thank you