Blog

Testing GTM Data Layer Loading with Cypress.io

PREREQUISITES

  1. Node and NPM setup on the machine you want to run Cypress.io

INTRODUCTION

Cypress.io is a next-generation front-end testing tool built for the modern web. It allows us to write End to End tests, Integration tests and Unit tests against anything that runs in a web browser, such as our awesome Open Source Brokers website and the GTM Data Layer that we have implemented on our site.

In this post, I will show how to setup Cypress.io to run as a standalone application that tests our website, for your GTM projects adjust this example to point at your website.
 

INSTALLING CYPRESS.IO

The first step to getting our Cypress.io tests running is to create a new npm project that will contain our tests and install Cypress.io as a dev dependency of our new project.

Let's get this started by opening a new console window, creating a directory to store our project and navigating into it.

mkdir site-tests
cd site-tests

To keep things simple we create a new directory named `site-tests`. This simple directory name will allow us to use the default values when initializing our npm project in the next step.

npm init

When prompted press enter to proceed with default values until the wizard is complete.

This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (site-tests)
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to D:\Repos\site-tests\package.json:

{
  "name": "site-tests",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}


Is this ok? (yes)

Now that we've created our site-tests project we need to install Cypress.io

npm install cypress --save-dev

Finally to make launching our test-project easy we want to edit package.json and update the test property listed under scripts to launch Cypress.io

{
  "name": "site-tests",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "cypress open"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "cypress": "^2.0.3"
  }
}

Our site-tests project is now set up with Cypress.io installed and we can now run it with the command.

npm run test

After some initial setup time that is required the first time you run Cypress.io, you should see the Cypress.io window. We're now ready to start writing tests.

Cypress Window


Our First Test

Open your favourite text editor and add the following code to it.

describe('Post Tests', function () {

    beforeEach(function () {
        cy.visit('http://opensourcebrokers.ca/blog/post/testing-gtm-data-layer-loading-with-cypress-io')
    });

    it('Data Layer Loaded', function () {
        cy.window().then((win) => {

            assert.isDefined(win.dataLayer, 'Data Layer is defined');
            assert.equal(win.dataLayer[0].page_type, 'Post', 'Page Type is correct');
            assert.equal(Cypress.$('.post-header').text().trim(), win.dataLayer[0].page_name, 'Page Name is correct');
           
        });             
    });
    
});

 We're going to want to save this file to:

./site-tests/cypress/integration/post_spec.js

After saving our new test specification file, we should automatically see it show up in the Cypress.io window.

Any javascript file we save to the Cypress.io integrations folder will automatically be displayed in this list.

post_spec.js added to Cypress.io


Clicking our new test specification in the list displayed will launch a new Chrome browser window and you can watch as the Cypress.io test runner opens our website and runs the tests we just saved.

Cypress.io Running

 

Understanding Post_spec.js

Now that we have Cypress.io running with our tests lets take a minute to understand what we just created.

In this example, post_spec.js represents a collection of tests that we want to run against an Open Source Brokers post page. We could name this file anything really and put anything we want in it but for our example post_spec.js makes sense.

There's a lot going on in this file if you haven't been writing tests already, so let's go through each piece to understand it better.

describe('Post Tests', function () { ... });

The very first line of our test file describes the tests that are about to be run, this is visual candy for the test runner and provides scoping for methods like beforeEach.

beforeEach(function () {
    cy.visit('http://opensourcebrokers.ca/blog/post/testing-gtm-data-layer-loading-with-cypress-io')
})

Next up we tell Cypress.io that before any test is executed that Cypress.io should navigate to this very blog post.

it('Data Layer Loaded', function () { ... });

It() method is our actual test, in this case, we are checking that the Data Layer has loaded correctly. If we added another it() method within Post Tests, beforeEach would run before it as well.

cy.window().then((win) => { ... });

cy.window() provides our test access to the current Global Window object of the page our tests are running against. With Cypress.io we cannot directly access the window object, instead, we call cy.window().then() with a callback that will have access to the Global Window object.

assert.isDefined(win.dataLayer, 'Data Layer is defined');

With access to the Global Window object, we can do our first check to ensure our Data Layer is loaded. This check simply ensures that window.dataLayer is defined on the page.

assert.equal(win.dataLayer[0].page_type, 'Post', 'Page Type is correct');

Our second check is used to ensure the integrity of our Data Layer and ensures that the page_type reported in the Data Layer is correct.

assert.equal(Cypress.$('.post-header').text().trim(), win.dataLayer[0].page_name, 'Page Name is correct');

The third check is a little more complicated but ensures that the Data Layer page_name variable is the same as the blog post title the user sees. To make this test work we use jQuery extension that is built into Cypress.io, this works just like regular jQuery and allows us to query the DOM and check that the value in the DOM is the same as the value in the Data Layer.

 
Next Steps

Write more tests!

The example in this post is just a starting point. It's important to test every property of your Data Layer that is coming from your backend. These properties can have long and complicated business processes feeding them and we want to know right away when one stops working.

For example, in our set of tests we check that the author is defined and correct as well, give it a try and see if you can create the same test.

The example_spec.js file provides an extensive list of example tests and the Cypress.io documentation provides in-depth detailed answers to any questions you might have.

https://docs.cypress.io/

Integrate with your workflow!

When should we run our tests? Cypress.io gives us a variety of options for when and how we want to run our tests.

If your team is already using a Continues Integration system, Cypress.io can be integrated directly with it. Continues Integration is ideal so that we can tell whenever a build occurs if any changes negatively impact our initial Data Layer loading.

Whatever way you decide to integrate Cypress.io into your workflow always keep in mind the more tests you have and the earlier in the process you run them the better chances you will have of catching bugs early before they become difficult to fix.

Read our Other GTM and Cypress.io testing posts!

This is just the first of many blog posts on GTM and testing with Cypress.io brought to you by Open Source Brokers. Check back often to see our latest GTM and Cypress.io testing guides.