Noon
Published in

Noon

E2E testing with Cypress & Bitbucket Pipelines

A look into my experience with setting up cypress, writing assertion, running test, fixing issues, fixing test config, setting up pipeline and deploying successfully in production.

Cypress and bitbucket logo graphic

What is E2E testing, (feat. Cypress)?

As a refresher, let’s see what E2E testing does. Most basically, E2E test cases written with Cypress are,

  1. Select county (if the country code for the number test is going to enter does not match the default selected country)
  2. Enter phone number
  3. Enter OTP
  4. Select profile
  5. Should redirect to discovery page

Getting started with Cypress

Setting up cypress is as easy as just typing in the add command. I’ll be using yarn throughout this article, but you can do the same with npm,

yarn add cypress
yarn cypress:open
yarn cypress:run
yarn cypress run --record --key PRODUCT_KEY
  1. Integration — Cypress test cases hide in here
  2. Plugins — helps you run some operations when cypress loads. Plugins run on load
  3. Support — is for helper commands and helper events
{
chromeWebSecurity: false,
baseUrl: '<http://localhost:2020>',
userAgent: 'testing',
blockHosts: ['*.google.com'],
projectId: '',
}

Writing test cases

Now it’s time to start adding test cases. But I am not going to focus on that here. Instead, here is a helpful link to Cypress’s list of examples that are posted on Github. They are comprehensive and very helpful, do check them out.

Challenges I faced, and Solutions

What I am going to focus on are the problems/issues that I faced while working with Cypress and how I resolved them. Starting with the config,

1. Separate environment config (local dev, qa, dev remote)

  1. Create config file for each environment
  2. Add plugin to read config file
  3. Update cypress environment config with value in config file Use this plugin to update config
module.exports = (on, config) => {
const file = config.env.configFile || 'development';
return readConfigFile(file);
};

2. Testing third party iFrames

To validate element inside third party iframe is a security issue, but if you want to write E2E tests, then you can do it in chromium based browsers. To do that,

  1. Install cypress-iframe — has method to check iframeLoaded and find element inside iframe
  2. If you are writing test case for multiple browsers(Firefox, chrome, IE), then use skipOn method to not run test case in non chromium browser
cy.iframe('#cardNumber').find('#checkout-frames-card-number').type('1234567890123456').should('have.value', '1234 5678 9012 3456');

3. Testing multiple flow on same page

To validate multiple features on the same page, you will have to write separate assertions. For instance, to validate cash and credit card payments, you will have to write two assertions.

beforeEach(() => {
cy.restoreLocalStorage();
}); afterEach(() => {
cy.saveLocalStorage();
});

4. Login details, page input value repeated in multiple test files

Fixtures are a really helpful way to avoid this kind of duplication. For our use case, we are just using basic fixtures function.

  1. Read fixtures json file content inside assertion
  2. Open cypress/fixtures/phone-number.json
cy.fixture(‘phone-number’).then((phoneNumber) => {
console.log(phoneNumber);
});

5. Registering service worker

Service worker registration and code exec throwing error and breaking app when running cypress. At Noon, as we are simply testing major feature flows as of now, we don’t need service worker in End to End testing.

  1. Use navigator.userAgent to not execute service worker code
if (navigator.userAgent.indexOf('testing-mode') > -1) {
console.log('execute me');
} else {
console.log("i don't like e2e testing");
}

6. Handling exceptions

To avoid app crashes in case of any exceptions, this event in cypress is quite helpful. It returns false if there is any exception when you run the tests,

Cypress.on('uncaught:exception', (err, runnable) =>
false,
);

7. Validate Audio Input With Cypress

Noon Academy is all about classroom experience, and classroom is driven by audio, it’s very important for us that classroom feature run successfully.
But how to simulate audio in your tests? Well, there is a browser flag which can trigger a fake audio input.

on('before:browser:launch', (browser = {}, launchOptions) => {
if (browser.family === 'chromium') {
launchOptions.args.push('--use-fake-device-for-media-stream');
launchOptions.args.push('--use-fake-ui-for-media-stream');
launchOptions.args.push('--no-sandbox');
launchOptions.args.push('--use-file-for-fake-audio-capture=cypress/fixtures/classroom-audio.wav');
}
return launchOptions;
});

How to setup bitbucket pipeline for cypress

This is super easy and very useful. Once up and running

  1. Add config for caches (do not miss out cypress cache folder)
    caches:
    - yarn
    - cypress
    - node
  2. Cache is added but this cache config doesn’t know where to find cache, so to define cache folder, add
    definitions:
    caches:
    yarn: $HOME/.cache
    cypress: $HOME/.cache/Cypress
  3. Do not forgot to add yarn install --frozen-lockfile, this config does not update yarn.lock
  1. Finally, command to start server, run cypress and upload test result to cypress dashboard
    yarn start-server-and-test start [<http://localhost:2020>](<http://localhost:2020/>) cypress run --record --key PRODUCT_KEY
image: cypress/base:10pipelines:
pull-requests:
'**':
- step:
name: "E2E (Cypress) test"
caches:
- yarn
- cypress
- node
script:
- yarn install --frozen-lockfile
- yarn start-server-and-test start [<http://localhost:2020>](<http://localhost:2020/>) cypress run --record --key PRODUCT_KEY
definitions:
caches:
yarn: $HOME/.cache
cypress: $HOME/.cache/Cypress

End notes

We have just recently started working on E2E testing within our team at Noon Academy, but we can already see the benefits and the time it saves us in debugging issues. Time we can use to create interesting and cool features.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store