e2e testing with Cypress, ReactJs and Firebase
Cypress is a e2e testing tool that interacts with chrome based browsers (and electron) to execute its test suite . E2e testing is known by its complexity, and often it is related to the top in the test pyramid .
The complexity comes from the amount of work and setup to do before performing the test itself. To put in context, unit test usually is the easiest in the spectrum, whereas the developer write test methods to cover a class behavior. The setup to be done is the smallest.
The havy setup is due the interaction between components, in a e2e testing, everything
is working the “production” way. Often this behavior is not desired, for that
Cypress provides a mock library. For example, the
cy.route is used to mock
network requests. Using the network mock, prevents the need to setup a entire
backend to interact with the web app .
Firebase is a library maintained by Google, which has many products inside it. In specific the real time database (or more recent firestore) is a Firebase product that allows developers to write real time applications.
Cypress and Firebase
Web applications that uses Firebase as a service to provide real time database
integration have a challenge beyond the
cy.route that Cypress provides.
Firebase uses a specific protocol to communicate with its server, which is not a
ajax requests. In this sense, using
cy.route is not effective, as it is
based on ajax requests only.
Proposed solution: redux and ReactJs
The first alternative is Redux . Redux provides a pattern to abstract the data of the application from the UI. In this sense, acting in the data part reflects the UI due its separation of concerns. Redux is a implementation of Flux a pattern, a one way flow to mutate data .
This solution, depend on the redux understanding. In other words, redux is a must. Applications that use Firebase and ReactJs only, can’t benefit. If that is the case there are solutions that try to tackle this case .
To follow on the ReactJs and the redux solution, the app must follow two basic rules:
- Calls to the firebase API must be inside reducers
- The app must depend on the redux state only
The next step is to expose the redux store through the
window object. This step
is required, so Cypress can access the store and commit actions to change the
state as needed .
This solution is interesting, as it isolates the dependency from Firebase. It
cy.route in this sense. Testable is a project that follows this approach
. To understand the big picture of the implementation is recommended
to check the
this file follows the first rule. In addition to the the file
index.js exposes the store to the
window object, as described before.
The second rule can be checked in the
components directory, as
all of them should’t dispatch Firebase interactions.
Interesting enough, exposing the store to the
window object might fit other
libraries/frameworks as well. This approach is not related to ReactJs + Redux only,
but to any Flux implementation. As an example, Vuex can also benefit from this approach.
Previous work have shown that the solution proposed in the previous sections is effective to remove the dependency from Firebase. Indeed,  has a step by step tutorial in how to achieve that.
 [Online]. Available: https://docs.cypress.io/guides/core-concepts/launching-browsers.html#Browsers
 Ham Vocke, ‘The Practical Test Pyramid’, 2018. [Online]. Available: https://martinfowler.com/articles/practical-test-pyramid.html
 [Online]. Available: https://docs.cypress.io/guides/guides/network-requests.html#Testing-Strategies. [Accessed: 31 - Oct - 2019]
 [Online]. Available: https://firebase.google.com/docs/ios/setup. [Accessed: 31 - Oct - 2019]
 [Online]. Available: https://firebase.google.com/docs/admin/setup#add_the_sdk. [Accessed: 31 - Oct - 2019]
 [Online]. Available: https://redux.js.org. [Accessed: 31 - Oct - 2019]
 [Online]. Available: https://facebook.github.io/flux/docs/in-depth-overview. [Accessed: 31 - Oct - 2019]
 [Online]. Available: https://github.com/prescottprue/cypress-firebase. [Accessed: 31 - Oct - 2019]
 [Online]. Available: https://github.com/cypress-io/cypress-example-recipes/issues/118. [Accessed: 31 - Oct - 2019]
 [Online]. Available: https://www.cypress.io/blog/2018/11/14/testing-redux-store/#drive-using-the-dom. [Accessed: 31 - Oct - 2019]
 [Online]. Available: https://github.com/marabesi/testable/tree/master/webapp. [Accessed: 31 - Oct - 2019]
 [Online]. Available: https://stackoverflow.com/a/52590453/2258921. [Accessed: 31 - Oct - 2019]