Giter VIP home page Giter VIP logo

gtm-datalayer-test's Introduction

gtm-datalayer-test

Automated functional testing for Google Tag Manager's Data Layer.

Requirements

To install and run gtm-datalayer-test, you need the following clients / libraries:

Installation

  1. Clone the repo with git clone https://github.com/sahava/gtm-datalayer-test.git
  2. Run cd gtm-datalayer-test
  3. Run npm install to install the dependencies (run as local user, not root)
  4. Run npm test to run the example script

Ubuntu 16.04 System Setup

First you need to install Node.js, Java, JRE, git, and build-essentials tools.

  1. sudo curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
  2. sudo apt-get install -y nodejs
  3. sudo apt-get install default-jre git
  4. sudo apt-get install -y build-essential

npm test

The npm test script does the following:

  1. Starts a simple HTTP server on http://localhost:8080, with the index.html from ./examples.
  2. Runs the ./examples/spec/basic_example.js spec against the mock dataLayer in index.html
  3. Stops the HTTP server

You can use this script to quickly see how the solution works. Be sure to check both basic_example.js and basic_example.conf.json to understand how the JSON validation works against the actual window.dataLayer object.

Technology

How it works

In examples/spec/basic_example.conf.json (see below), you specify both global key-value pairs as well as page-specific configurations. These dataLayer compositions will then be searched on every page (global configuration) as well as on specific pages (page-specific configurations).

You can enforce the schema in basic_example.conf.json using (a very slightly customized) JSON Schema (v4) to describe the objects in window.dataLayer, or you can use a simple subset check.

###JSON Schema You can describe the window.dataLayer objects using JSON Schema. Each object you add to the dataLayer property in the configuration (global or page-specific), will be compiled into its own schema, and this schema will then be checked against the global window.dataLayer structure. There are some slight modifications and hacks to accomodate for the fact that JSON Schema doesn't play that well with Arrays of indeterminate length and composition (such as window.dataLayer often is).

##Subset check You can also simply use a subset check, where you specify each dataLayer object (global or page-specific) with all the keys and values that you expect to find in dataLayer. Note that if you leave a key out, it is considered optional.

To enable the subset check, you will need to add the key-value pair

"@json" : false

to the root of each dataLayer object in the configuration file that you want to validate against.

Example:

{
    "baseUrl" : "https://www.yourdomain.com",
    "dataLayerName" : "dataLayer",
    "dataLayer" : [{
        "@json" : false,
        "someVariable" : "someValue"
    },{
        "someOtherVariable" : {
            "type" : "number",
            "enum" : [1,2,3,4,5]
        }
    }]
}

Here the first object uses the subset check, so it will validate if the global window.dataLayer structure has at least one object with that exact key-value pair ("someVariable" : "someValue") in the root.

The second object uses the modified JSON Schema. It will validate if at least one object in the global window.dataLayer structure has the root key someOtherVariable set to a number in the range of 1-5.

The JSON Schema used for the test configuration must follow the structure described in this README. When you run the tests, the JSON configuration is first validated against its own schema (/lib/validTestConfSchema.json). If validation fails, the test is aborted.

Customize tests

The test is currently contained in /examples/spec/. There are two files:

  • basic_example.conf.json - the JSON schema that controls on which pages the test visits and what assertations are run against dataLayer
  • basic_example.js - the actual test specification To customize the test, you should modify basic_example.conf.json. Here's what it might look like:
{
    "baseUrl" : "https://www.yourdomain.com",
    "dataLayerName" : "dataLayer",
    "dataLayer" : [{
        "someVariable" : {
            "@rootRequired" : false,
            "type" : "object",
            "properties" : {
                "someDeeperVariable" : {
                    "pattern" : "^deepValue$"
                }
            },
            "required" : ["someDeeperVariable"]
        }
    }],
    "page" : [{
        "path" : "/some-path/",
        "dataLayer" : [{
            "@expect" : "dataLayer to have Enhanced Ecommerce detail object",
            "ecommerce" : {
                "type" : "object",
                "properties" : {
                    "detail" : {
                        "$ref" : "/enhancedEcommerceSchema.json#/definitions/detail"
                    }
                },
                "required" : ["detail"]
            }
        }]
    }]
}

These are all the keys you can currently use:

Property Type Description
baseUrl (required) URI Base URL for tests, no trailing /.
multipleContainers Boolean If true then multiple instances of 'gtm.js' event are permitted in dataLayer.
dataLayerName String The name of the global window.dataLayer Array. Make sure this matches what you've configured in the Google Tag Manager container snippet. It defaults to dataLayer.
dataLayer Array Global dataLayer configuration. An Array of objects that you expect to find on every page of the site. The objects can be incomplete, as only the named key-value pairs will be searched for.
page Array Array of page-specific configurations, where each object corresponds to a page you want to test.
page.path (required) String Path of the page you want to test.
page.dataLayer (required) Array Array of objects, where each object is a single test run against dataLayer. Each object can have any number of key-value pairs, and only these key-value pairs are searched for (so the objects can be incomplete). The objects should correspond with what you expect to find in dataLayer.
page.dataLayer[].@expect (required) String A description of the test. It will be shown in the test reporter output.
(page.)dataLayer[].properties{}.key.@rootRequired Boolean If set to false will make this root-level property optional, meaning the test will pass even if the key is not found in the global dataLayer structure.

If you use the JSON Schema option (by default), everything within the dataLayer objects (global and page-specific) must conform to the latest draft of JSON Schema (http://json-schema.org/). The only exceptions are:

  • The root level of each dataLayer object is translated directly into properties of respective root level window.dataLayer objects. So instead of specifying the root level dataLayer objects in the configuration as complete JSON Schema objects, just list the properties as keys. Everything else (except for the other exceptions listed below) should be described using the regular JSON Schema specification.
  • @expect used in the page-specific configurations to describe the current test for the test reporter. This is required also when using the subset check method.
  • @rootRequired used in root-level properties to indicate whether or not they are optional in the global dataLayer structure.

To do

  • Add support for navigation (e.g. validate dataLayer after user interactions).
  • Improve the configuration to make it easier to use different browser drivers.

gtm-datalayer-test's People

Contributors

sahava avatar thyngster avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gtm-datalayer-test's Issues

Add more examples

More examples are needed, each with their own test spec and configuration JSON.

  • Failing test
  • Multiple browsers
  • Multiple pages
  • Complex structure using subset check only
  • Complex JSON validation

connect econnrefused 127.0.0.1:4444

After errorless npm install stops npm test after http-server ./examples -s. On hard break appears an error

ERROR: connect ECONNREFUSED 127.0.0.1:4444 phantomjs at new RuntimeError (C:\gtm-datalayer-test\node_modules\webdriverio\build\li b\utils\ErrorHandler.js:143:12) at Request._callback (C:\gtm-datalayer-test\node_modules\webdriverio\build\l ib\utils\RequestHandler.js:330:43) at self.callback (C:\gtm-datalayer-test\node_modules\webdriverio\node_module s\request\request.js:185:22) at emitOne (events.js:116:13) at Request.emit (events.js:211:7) at Request.onRequestError (C:\gtm-datalayer-test\node_modules\webdriverio\no de_modules\request\request.js:877:8) at emitOne (events.js:121:20) at ClientRequest.emit (events.js:211:7) at Socket.socketErrorListener (_http_client.js:387:9) at emitOne (events.js:116:13).

Error: reporter "wdio-spec-reporter" is not installed

Current master throws an error when installing from scratch:

/home/work/gtm-datalayer-test/node_modules/webdriverio/build/lib/launcher.js:162
throw _iteratorError;
^

Error: reporter "wdio-spec-reporter" is not installed. Error: Error: Cannot find module 'wdio-spec-reporter'
at Function.Module._resolveFilename (module.js:469:15)
at Function.Module._load (module.js:417:25)
at Module.require (module.js:497:17)
at require (internal/module.js:20:19)
at Launcher.initReporters (/home/work/gtm-datalayer-test/node_modules/webdriverio/build/lib/launcher.js:137:41)
at new Launcher (/home/work/gtm-datalayer-test/node_modules/webdriverio/build/lib/launcher.js:73:31)
at Object. (/home/work/gtm-datalayer-test/node_modules/webdriverio/build/lib/cli.js:426:20)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at Launcher.initReporters (/home/work/gtm-datalayer-test/node_modules/webdriverio/build/lib/launcher.js:139:35)
at new Launcher (/home/work/gtm-datalayer-test/node_modules/webdriverio/build/lib/launcher.js:73:31)
at Object. (/home/work/gtm-datalayer-test/node_modules/webdriverio/build/lib/cli.js:426:20)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
at Module.require (module.js:497:17)
at require (internal/module.js:20:19)

Add support for reporting results to a GSheet

Hi Simo,

If you find it to be a good fit, I'd like to include some functionality we've been working on here at Napkyn Inc. We're a heavy user of gsheets for documenting QA results. As we begin rolling out our internal testing tools, we're looking for tools in the community that we could contribute some functionality to. Our contribution would be the gsheet scripts we use to munge the incoming data as well as the code we use to send the data to the sheets (integrated into your framework). I look forward to hearing your thoughts.

All the best,
Adam

Get rid of wdio

Let's start thinking of getting rid of wdio. The only reason I chose wdio was because I wanted a test runner up as fast as possible.

Without wdio, we could setup Selenium, phantomjs, mocha, chai using e.g. Grunt to do the package and script handling.

Then, we could have more freedom to incorporate more complex interactions between the client and the server, such as adding https://github.com/google/data-layer-helper and run assertions when dataLayer.push() commands are registered. This way we could test each dataLayer.push() against the JSON as they come in, rather than the pretty complex method currently used to test the dataLayer as one big JSON lump.

Add support for navigation

Navigation support needs to be added. Basically anything that triggers a dataLayer.push() should be something you can write a test to.

Will need to figure out how to represent navigation in the JSON configuration, though.

Come up with a better alternative to the "not" : { "items" : { "not" pattern

Currently the only way (I have found) to test if an array (window.dataLayer) simply contains an object is to use the

"type" : "array
"not" : {
    "items" : {
        "not" : {
            "type" : "object",
            "properties" : ...

pattern as used in /lib/testUtils.js. However, this is not only really ugly, but it also lacks proper validation error messages. If the test fails, the only thing the reporter knows is that the spec validated against a "not" condition. The reporter doesn't know what part of the spec failed. That's why there's the "FAILED ON: " workaround, where I expose the object on which the test failed in the error message.

As far as I know, there's not much to do about this yet. There's the "contains" keyword coming up (hopefully) in a future JSON Schema draft, but even then I'm not certain if it's descriptive enough.

So we need to figure out how to properly do an "array contains..." so that the validation error is still expressive enough to be informative.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.