From d3d473170fedcf8af008e6a64deb62820bbc0a34 Mon Sep 17 00:00:00 2001 From: Matthew Callis Date: Mon, 5 Dec 2016 17:21:28 -0800 Subject: [PATCH 1/2] Updated tests, remove static methods that can't be easily tested. --- .babelrc | 9 + .eslintrc | 30 + .gitignore | 8 +- .npmignore | 12 +- .travis.yml | 21 +- LICENSE | 3 +- README.md | 116 +-- build/wildberry_princess.js | 236 ------ coffeelint.json | 140 ---- dist/wildberry-princess.js | 344 +++++++++ dist/wildberry-princess.min.js | 1 - package.json | 86 ++- phantom_hooks.js | 15 - rollup.config.js | 34 + src/wildberry_princess.coffee | 145 ---- src/wildberry_princess.js | 185 +++++ test/helpers/setup-browser-env.js | 3 + test/index.html | 37 +- test/mocha.css | 270 ------- test/wildberry_princess.clickHandler.test.js | 174 +++++ test/wildberry_princess.constructor.test.js | 56 ++ test/wildberry_princess.identify.test.js | 81 +++ test/wildberry_princess.sendPayload.test.js | 77 ++ test/wildberry_princess.set.test.js | 85 +++ .../wildberry_princess.trackEcommerce.test.js | 59 ++ test/wildberry_princess.trackEvent.test.js | 127 ++++ test/wildberry_princess.trackPageView.test.js | 65 ++ ...ildberry_princess.trackUserActions.test.js | 45 ++ test/wildberry_princess_spec.coffee | 651 ----------------- test/wildberry_princess_spec.js | 672 ------------------ 30 files changed, 1537 insertions(+), 2250 deletions(-) create mode 100644 .babelrc create mode 100644 .eslintrc delete mode 100644 build/wildberry_princess.js delete mode 100644 coffeelint.json create mode 100644 dist/wildberry-princess.js delete mode 100644 dist/wildberry-princess.min.js delete mode 100755 phantom_hooks.js create mode 100644 rollup.config.js delete mode 100644 src/wildberry_princess.coffee create mode 100644 src/wildberry_princess.js create mode 100644 test/helpers/setup-browser-env.js delete mode 100644 test/mocha.css create mode 100644 test/wildberry_princess.clickHandler.test.js create mode 100644 test/wildberry_princess.constructor.test.js create mode 100644 test/wildberry_princess.identify.test.js create mode 100644 test/wildberry_princess.sendPayload.test.js create mode 100644 test/wildberry_princess.set.test.js create mode 100644 test/wildberry_princess.trackEcommerce.test.js create mode 100644 test/wildberry_princess.trackEvent.test.js create mode 100644 test/wildberry_princess.trackPageView.test.js create mode 100644 test/wildberry_princess.trackUserActions.test.js delete mode 100644 test/wildberry_princess_spec.coffee delete mode 100644 test/wildberry_princess_spec.js diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..04898d4 --- /dev/null +++ b/.babelrc @@ -0,0 +1,9 @@ +{ + "presets": [ + ["es2015"], + ], + "plugins": [ + "babel-plugin-espower", + "transform-object-rest-spread" + ] +} diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..1ef09f0 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,30 @@ +{ + "extends": "airbnb", + "plugins": [ + "ava", + "no-inferred-method-name", + "xss", + ], + "env": { + "es6": true, + "browser": true, + }, + "globals": { + "sinon": false, + "expect": true, + }, + # Custom Disabled Rules + rules: { + camelcase: 0, + max-len: 0, + no-param-reassign: 0, + no-unused-vars: ["error", { "varsIgnorePattern": "^(_|Apptentive)", "argsIgnorePattern": "^_", "caughtErrors": "none" }], + no-plusplus: 0, # Meaningless as other rules prevent the errors that could happens. + # Rules dependent on external APIs that would otherwise break rules or be needlessly complex: + no-underscore-dangle: 0, + no-restricted-syntax: 0, + no-empty: ["error", { "allowEmptyCatch": true }], + "import/no-extraneous-dependencies": 0, + "class-methods-use-this": 0 # Breaks Ava testing when using static method due to transpiled code. + } +} diff --git a/.gitignore b/.gitignore index cf14c63..ac19b6d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ -.DS_Store -node_modules/ .coveralls.yml +.DS_Store +.nyc_output/ +build-coverage/ coverage/ lib-cov -build-coverage/ +node_modules/ +npm-debug.log diff --git a/.npmignore b/.npmignore index 482871b..acd504e 100644 --- a/.npmignore +++ b/.npmignore @@ -1,7 +1,13 @@ -support +.coveralls.yml +.DS_Store +.nyc_output/ assets assets_source -tmp -.DS_Store +build-coverage/ config.json +coverage/ +lib-cov +node_modules/ npm-debug.log +support +tmp diff --git a/.travis.yml b/.travis.yml index 9769b7a..3d8f245 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,25 +1,22 @@ language: node_js node_js: - "stable" +cache: + directories: + - node_modules env: - CODECLIMATE_REPO_TOKEN=9ffe8abc7638fd859bf081174225ff9846ee5a476c8793bd4e8cc3ec90dae358 before_install: - npm conf set strict-ssl false -after_install: - - sudo npm install -g phantomjs -before_script: - - phantomjs --version - - npm install -g mocha-phantomjs - - npm install -g istanbul - - npm install -g codeclimate-test-reporter script: - npm run make - - npm run instrument - - npm run test-phantomjs - - npm run coverage-report + - npm run test after_script: - - cat coverage/lcov.info | codeclimate - - cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js + - './node_modules/.bin/nyc report --reporter=text-lcov | ./node_modules/.bin/coveralls' + - './node_modules/.bin/nyc report --reporter=text-lcov | ./node_modules/.bin/codeclimate-test-reporter' +branches: + only: + - master addons: code_climate: repo_token: 9ffe8abc7638fd859bf081174225ff9846ee5a476c8793bd4e8cc3ec90dae358 diff --git a/LICENSE b/LICENSE index 7bf0118..7344b8a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014 Matthew Callis +Copyright (c) 2016 Matthew Callis Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -19,4 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - diff --git a/README.md b/README.md index 3a8568a..e675af8 100644 --- a/README.md +++ b/README.md @@ -14,61 +14,64 @@ Wildberry Princess is a JavaScript library for abstracting out Google Analytics ## Usage -```coffeescript -# Google Analytics initialized somewhere... -# Kissmetrics initialized somewhere... - -# Setup -analytics = new WildberryPrincess( - useGoogleAnalytics: true - useKissMetrics: true -) - -# Set dimensions and users. -analytics.identify(current_user_id) if current_user_id? -analytics.set('dimension1', app_id) if app_id? - -# Or more specifically: -analytics.setGA('dimension1', app_id) if app_id? -analytics.setKM('app_id', app_id) if app_id? - -# Track user actions, specifically clicks, where the label is the text content (button, div, tab, etc.) or form input name (input, select, textarea). -# analytics.trackUserActions(selector, category, action, label, value) -analytics.trackUserActions('button', 'Button') -analytics.trackUserActions('input, select, textarea', 'Form Input') -analytics.trackUserActions('tab', 'Tab') - -# Send events anywhere, like Backbone model actions. -# analytics.trackEvent(category, action, label, value) -# analytics.trackEventGA(category, action, label, value) -# analytics.trackEventKM(label, payload) -analytics.trackEvent('Model', 'Destroy', @constructorName) - -# Track page views. Currently, KissMetrics is not included here to avoid event bloat. -Apptentive.analytics.trackPageView('/fake-page', 'A Cool Fake Title') - -# Send eCommerce data. -transaction_id = "#{@model.id}_#{Date.now()}" -transaction = - id: transaction_id - affiliation: "Candy Kingdom" - revenue: price - shipping: '0' - tax: '0' - -item = - id: transaction_id - name: name - category: category - price: price - quantity: 1 - -analytics.trackEcommerce('clear') -analytics.trackEcommerce('addTransaction', transaction) -analytics.trackEcommerce('addItem', item) -analytics.trackEcommerce('send') +```javascript +// Google Analytics initialized somewhere... +// Kissmetrics initialized somewhere... + +// Setup +const analytics = new WildberryPrincess({ + useGoogleAnalytics: true, + useKissMetrics: false, +}); + +// Set dimensions and users. +if (current_user_id != null) { + analytics.identify(current_user_id); +} + +if (app_id != null) { + analytics.set('dimension1', app_id); +} + +// Track user actions, specifically clicks, where the label is the text content (button, div, tab, etc.) or form input name (input, select, textarea). +// analytics.trackUserActions(selector, category, action, label, value) +analytics.trackUserActions('button', 'Button'); +analytics.trackUserActions('input, select, textarea', 'Form Input'); +analytics.trackUserActions('tab', 'Tab'); + +// Send events anywhere, like Backbone model actions. +// analytics.trackEvent(category, action, label, value) +analytics.trackEvent('Model', 'Destroy', this.constructorName); + +// Track page views. Currently +// NOTE: KissMetrics is not included here to avoid event bloat 🤑 +Apptentive.analytics.trackPageView('/fake-page', 'A Cool Fake Title'); + +// Send eCommerce data. +const transaction_id = `${this.model.id}_${Date.now()}`; +const transaction = { + id: transaction_id, + affiliation: 'Candy Kingdom', + revenue: price, + shipping: '0', + tax: '0', +}; +const item = { + id: transaction_id, + name, + category, + price, + quantity: 1, +}; + +analytics.trackEcommerce('clear'); +analytics.trackEcommerce('addTransaction', transaction); +analytics.trackEcommerce('addItem', item); +analytics.trackEcommerce('send'); ``` +For more advanced use, please refer to the source. + ### Testing ```shell @@ -82,6 +85,13 @@ npm run make-dist-min npm run lint && npm run make && npm run instrument && npm run test-phantomjs && npm run coverage-report && npm run make-dist-min ``` +## Useful Reading + +- [Analytics.js Field Reference](https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference) +- [Cookies and User Identification](https://developers.google.com/analytics/devguides/collection/analyticsjs/cookies-user-id) +- [Custom Dimensions and Metrics](https://developers.google.com/analytics/devguides/collection/analyticsjs/custom-dims-mets) +- [Event Tracking](https://developers.google.com/analytics/devguides/collection/analyticsjs/events) + ## Contributing 1. Fork it diff --git a/build/wildberry_princess.js b/build/wildberry_princess.js deleted file mode 100644 index b8d4a1b..0000000 --- a/build/wildberry_princess.js +++ /dev/null @@ -1,236 +0,0 @@ -// Generated by CoffeeScript 1.9.3 -(function() { - var WildberryPrincess, - bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; - - WildberryPrincess = (function() { - var defaults; - - defaults = { - useGoogleAnalytics: true, - useKissMetrics: true - }; - - function WildberryPrincess(options) { - if (options == null) { - options = {}; - } - this.clearIdentity = bind(this.clearIdentity, this); - this.identify = bind(this.identify, this); - this.setKM = bind(this.setKM, this); - this.set = bind(this.set, this); - this.trackEcommerce = bind(this.trackEcommerce, this); - this.trackPageView = bind(this.trackPageView, this); - this.trackEventKM = bind(this.trackEventKM, this); - this.trackEventGA = bind(this.trackEventGA, this); - this.trackEvent = bind(this.trackEvent, this); - this.clickHandler = bind(this.clickHandler, this); - this.trackUserActions = bind(this.trackUserActions, this); - this.settings = this.merge(defaults, options); - } - - WildberryPrincess.prototype.getLabel = function(element) { - return element.getAttribute('data-event-label'); - }; - - WildberryPrincess.prototype.trackUserActions = function(selector, category, action, label, value) { - var elements, i, params, results; - params = { - category: category, - action: action || 'Click' - }; - if (label) { - params.label = label; - } - if (value) { - params.value = value; - } - elements = document.querySelectorAll(selector); - i = 0; - results = []; - while (i < elements.length) { - elements[i].data = { - eventParams: params - }; - elements[i].removeEventListener('click', this.clickHandler); - elements[i].addEventListener('click', this.clickHandler, false); - results.push(i++); - } - return results; - }; - - WildberryPrincess.prototype.clickHandler = function(event) { - var element, eventParams, label, payload; - if (!event) { - return; - } - element = event.target; - if (!element) { - return; - } - eventParams = element.data.eventParams; - label = eventParams.label ? eventParams.label : this.getLabel(element); - if (this.settings.useGoogleAnalytics) { - payload = { - hitType: 'event', - eventCategory: eventParams.category, - eventAction: eventParams.action - }; - if (label) { - payload.eventLabel = label; - } - if (eventParams.value) { - payload.eventValue = eventParams.value; - } - this.sendPayloadGA(payload); - } - if (this.settings.useKissMetrics) { - payload = { - category: eventParams.category, - action: eventParams.action - }; - if (label) { - payload.label = label; - } - if (eventParams.value) { - payload.value = eventParams.value; - } - this.trackEventKM(eventParams.category + ": " + label + " (" + eventParams.action + ")", payload); - } - }; - - WildberryPrincess.prototype.trackEvent = function(category, action, label, value) { - var payload; - if (this.settings.useGoogleAnalytics) { - this.trackEventGA(category, action, label, value); - } - if (this.settings.useKissMetrics) { - payload = { - category: category, - action: action - }; - if (label) { - payload.label = label; - } - if (value) { - payload.value = value; - } - return this.trackEventKM(category + ": " + label + " (" + action + ")", payload); - } - }; - - WildberryPrincess.prototype.trackEventGA = function(category, action, label, value) { - var payload; - payload = { - hitType: 'event', - eventCategory: category, - eventAction: action - }; - if (label) { - payload.eventLabel = label; - } - if (value) { - payload.eventValue = value; - } - return this.sendPayloadGA(payload); - }; - - WildberryPrincess.prototype.trackEventKM = function(label, payload) { - return this.sendPayloadKM('record', label, payload); - }; - - WildberryPrincess.prototype.trackPageView = function(page, title) { - var payload; - page || (page = window.location.pathname); - title || (title = document.title); - payload = { - hitType: 'pageview', - page: page, - title: title - }; - return this.sendPayloadGA(payload); - }; - - WildberryPrincess.prototype.trackEcommerce = function(action, payload) { - if ((window.ga != null) && this.settings.useGoogleAnalytics) { - return window.ga("ecommerce:" + action, payload); - } - }; - - WildberryPrincess.prototype.set = function(key, value) { - if (this.settings.useGoogleAnalytics) { - this.setGA(key, value); - } - if (this.settings.useKissMetrics) { - return this.setKM(key, value); - } - }; - - WildberryPrincess.prototype.setGA = function(key, value) { - if (window.ga != null) { - return window.ga('set', key, value); - } - }; - - WildberryPrincess.prototype.setKM = function(key, value) { - var data; - data = {}; - data[key] = value; - return this.sendPayloadKM('set', data, null); - }; - - WildberryPrincess.prototype.identify = function(user_id) { - if (user_id == null) { - user_id = 'anonymous'; - } - if (this.settings.useGoogleAnalytics && user_id !== 'anonymous') { - this.setGA('userId', user_id); - } - if (this.settings.useKissMetrics) { - return this.sendPayloadKM('identify', user_id); - } - }; - - WildberryPrincess.prototype.clearIdentity = function() { - if (this.settings.useKissMetrics) { - return this.sendPayloadKM('clearIdentity'); - } - }; - - WildberryPrincess.prototype.sendPayloadGA = function(payload) { - if (window.ga != null) { - return window.ga('send', payload); - } - }; - - WildberryPrincess.prototype.sendPayloadKM = function(action, payload, data) { - var output; - if (window._kmq != null) { - output = [action]; - if (payload) { - output.push(payload); - } - if (data) { - output.push(data); - } - return window._kmq.push(output); - } - }; - - WildberryPrincess.prototype.merge = function(input, options) { - var k, output, v; - output = JSON.parse(JSON.stringify(input)); - for (k in options) { - v = options[k]; - output[k] = v; - } - return output; - }; - - return WildberryPrincess; - - })(); - - (typeof exports !== "undefined" && exports !== null ? exports : this).WildberryPrincess = WildberryPrincess; - -}).call(this); diff --git a/coffeelint.json b/coffeelint.json deleted file mode 100644 index c805dc5..0000000 --- a/coffeelint.json +++ /dev/null @@ -1,140 +0,0 @@ -{ - "arrow_spacing": { - "name": "arrow_spacing", - "level": "warn" - }, - "coffeescript_error": { - "level": "error" - }, - "camel_case_classes": { - "name": "camel_case_classes", - "level": "error" - }, - "colon_assignment_spacing": { - "name": "colon_assignment_spacing", - "level": "ignore", - "spacing": { - "left": 0, - "right": 0 - } - }, - "cyclomatic_complexity": { - "name": "cyclomatic_complexity", - "value": 10, - "level": "ignore" - }, - "duplicate_key": { - "name": "duplicate_key", - "level": "error" - }, - "empty_constructor_needs_parens": { - "name": "empty_constructor_needs_parens", - "level": "warn" - }, - "ensure_comprehensions": { - "level": "warn" - }, - "indentation": { - "name": "indentation", - "value": 2, - "level": "error" - }, - "line_endings": { - "name": "line_endings", - "level": "warn", - "value": "unix" - }, - "max_line_length": { - "name": "max_line_length", - "value": 280, - "level": "ignore", - "limitComments": true - }, - "missing_fat_arrows": { - "name": "missing_fat_arrows", - "level": "ignore" - }, - "newlines_after_classes": { - "name": "newlines_after_classes", - "value": 3, - "level": "warn" - }, - "no_backticks": { - "name": "no_backticks", - "level": "error" - }, - "no_debugger": { - "name": "no_debugger", - "level": "warn" - }, - "no_empty_functions": { - "name": "no_empty_functions", - "level": "ignore" - }, - "no_empty_param_list": { - "name": "no_empty_param_list", - "level": "warn" - }, - "no_implicit_braces": { - "name": "no_implicit_braces", - "level": "ignore", - "strict": false - }, - "no_implicit_parens": { - "name": "no_implicit_parens", - "level": "ignore" - }, - "no_interpolation_in_single_quotes": { - "name": "no_interpolation_in_single_quotes", - "level": "warn" - }, - "no_plusplus": { - "name": "no_plusplus", - "level": "ignore" - }, - "no_stand_alone_at": { - "name": "no_stand_alone_at", - "level": "warn" - }, - "no_tabs": { - "name": "no_tabs", - "level": "error" - }, - "no_throwing_strings": { - "name": "no_throwing_strings", - "level": "error" - }, - "no_trailing_semicolons": { - "name": "no_trailing_semicolons", - "level": "error" - }, - "no_trailing_whitespace": { - "name": "no_trailing_whitespace", - "level": "error", - "allowed_in_comments": false, - "allowed_in_empty_lines": true - }, - "no_unnecessary_double_quotes": { - "name": "no_unnecessary_double_quotes", - "level": "ignore" - }, - "no_unnecessary_fat_arrows": { - "name": "no_unnecessary_fat_arrows", - "level": "warn" - }, - "non_empty_constructor_needs_parens": { - "name": "non_empty_constructor_needs_parens", - "level": "warn" - }, - "prefer_english_operator": { - "name": "prefer_english_operator", - "level": "warn" - }, - "space_operators": { - "name": "space_operators", - "level": "warn" - }, - "transform_messes_up_line_numbers": { - "level": "warn" - } -} diff --git a/dist/wildberry-princess.js b/dist/wildberry-princess.js new file mode 100644 index 0000000..d20db34 --- /dev/null +++ b/dist/wildberry-princess.js @@ -0,0 +1,344 @@ +var WildberryPrincess = (function () { +'use strict'; + +var classCallCheck = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +}; + +var createClass = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; +}(); + + + + + + + +var get = function get(object, property, receiver) { + if (object === null) object = Function.prototype; + var desc = Object.getOwnPropertyDescriptor(object, property); + + if (desc === undefined) { + var parent = Object.getPrototypeOf(object); + + if (parent === null) { + return undefined; + } else { + return get(parent, property, receiver); + } + } else if ("value" in desc) { + return desc.value; + } else { + var getter = desc.get; + + if (getter === undefined) { + return undefined; + } + + return getter.call(receiver); + } +}; + + + + + + + + + + + + + + + + + +var set$1 = function set$1(object, property, value, receiver) { + var desc = Object.getOwnPropertyDescriptor(object, property); + + if (desc === undefined) { + var parent = Object.getPrototypeOf(object); + + if (parent !== null) { + set$1(parent, property, value, receiver); + } + } else if ("value" in desc && desc.writable) { + desc.value = value; + } else { + var setter = desc.set; + + if (setter !== undefined) { + setter.call(receiver, value); + } + } + + return value; +}; + +var WildberryPrincess = function () { + function WildberryPrincess() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + classCallCheck(this, WildberryPrincess); + + this.trackUserActions = this.trackUserActions.bind(this); + this.clickHandler = this.clickHandler.bind(this); + this.trackEvent = this.trackEvent.bind(this); + this.trackPageView = this.trackPageView.bind(this); + this.trackEcommerce = this.trackEcommerce.bind(this); + this.set = this.set.bind(this); + this.identify = this.identify.bind(this); + this.clearIdentity = this.clearIdentity.bind(this); + + var defaults$$1 = { + useGoogleAnalytics: true, + useKissMetrics: true + }; + this.settings = Object.assign({}, defaults$$1, options); + } + + createClass(WildberryPrincess, [{ + key: 'trackUserActions', + value: function trackUserActions(selector, category, action, label, value) { + var params = { + category: category, + action: action || 'Click' + }; + if (label) { + params.label = label; + } + if (value) { + params.value = value; + } + + var elements = document.querySelectorAll(selector); + var i = 0; + + var result = []; + while (i < elements.length) { + elements[i].data = { eventParams: params }; + elements[i].removeEventListener('click', this.clickHandler); + elements[i].addEventListener('click', this.clickHandler, false); + result.push(i++); + } + } + }, { + key: 'clickHandler', + value: function clickHandler(event) { + if (event == null) { + return; + } + var element = event.target; + if (element == null) { + return; + } + + var eventParams = element.data.eventParams; + + var label = eventParams.label ? eventParams.label : this.getLabel(element); + + if (this.settings.useGoogleAnalytics) { + var payload = { + hitType: 'event', + eventCategory: eventParams.category, + eventAction: eventParams.action + }; + if (label) { + payload.eventLabel = label; + } + if (eventParams.value) { + payload.eventValue = eventParams.value; + } + + this.sendPayloadGA(payload); + } + + if (this.settings.useKissMetrics) { + var _payload = { + category: eventParams.category, + action: eventParams.action + }; + if (label) { + _payload.label = label; + } + if (eventParams.value) { + _payload.value = eventParams.value; + } + + this.trackEventKM(eventParams.category + ': ' + label + ' (' + eventParams.action + ')', _payload); + } + } + }, { + key: 'trackEvent', + value: function trackEvent(category, action, label, value) { + if (this.settings.useGoogleAnalytics) { + this.trackEventGA(category, action, label, value); + } + + if (this.settings.useKissMetrics) { + var payload = { + category: category, + action: action + }; + if (label) { + payload.label = label; + } + if (value) { + payload.value = value; + } + + this.trackEventKM(category + ': ' + label + ' (' + action + ')', payload); + } + } + }, { + key: 'trackPageView', + value: function trackPageView(page, title) { + if (!page) { + page = window.location.pathname; + } + if (!title) { + var _document = document; + title = _document.title; + } + var payload = { + hitType: 'pageview', + page: page, + title: title + }; + + if (this.settings.useGoogleAnalytics) { + this.sendPayloadGA(payload); + } + } + }, { + key: 'trackEcommerce', + value: function trackEcommerce(action, payload) { + if (window.ga != null && this.settings.useGoogleAnalytics) { + window.ga('ecommerce:' + action, payload); + } + } + }, { + key: 'set', + value: function set(key, value) { + if (this.settings.useGoogleAnalytics) { + this.setGA(key, value); + } + if (this.settings.useKissMetrics) { + this.setKM(key, value); + } + } + }, { + key: 'identify', + value: function identify() { + var user_id = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'anonymous'; + + // https://developers.google.com/analytics/devguides/collection/analyticsjs/user-id + // https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#userId + // http://support.kissmetrics.com/apis/common-methods#identify + if (this.settings.useGoogleAnalytics && user_id !== 'anonymous') { + this.setGA('userId', user_id); + } + if (this.settings.useKissMetrics) { + this.sendPayloadKM('identify', user_id); + } + } + }, { + key: 'clearIdentity', + value: function clearIdentity() { + // http://support.kissmetrics.com/advanced/multiple-people-same-browser/ + if (this.settings.useKissMetrics) { + this.sendPayloadKM('clearIdentity'); + } + } + + // Static / Class Methods + + }, { + key: 'getLabel', + value: function getLabel(element) { + return element.getAttribute('data-event-label'); + } + }, { + key: 'trackEventGA', + value: function trackEventGA(category, action, label, value) { + var payload = { + hitType: 'event', + eventCategory: category, + eventAction: action + }; + if (label) { + payload.eventLabel = label; + } + if (value) { + payload.eventValue = value; + } + + this.sendPayloadGA(payload); + } + }, { + key: 'trackEventKM', + value: function trackEventKM(label, payload) { + this.sendPayloadKM('record', label, payload); + } + }, { + key: 'setGA', + value: function setGA(key, value) { + if (window.ga != null) { + window.ga('set', key, value); + } + } + }, { + key: 'setKM', + value: function setKM(key, value) { + var data = {}; + data[key] = value; + this.sendPayloadKM('set', data, null); + } + }, { + key: 'sendPayloadGA', + value: function sendPayloadGA(payload) { + if (window.ga != null) { + window.ga('send', payload); + } + } + }, { + key: 'sendPayloadKM', + value: function sendPayloadKM(action, payload, data) { + // http://support.kissmetrics.com/apis/common-methods + if (window._kmq != null) { + var output = [action]; + if (payload) { + output.push(payload); + } + if (data) { + output.push(data); + } + + window._kmq.push(output); + } + } + }]); + return WildberryPrincess; +}(); + +return WildberryPrincess; + +}()); diff --git a/dist/wildberry-princess.min.js b/dist/wildberry-princess.min.js deleted file mode 100644 index a7db512..0000000 --- a/dist/wildberry-princess.min.js +++ /dev/null @@ -1 +0,0 @@ -(function(){var t,e=function(t,e){return function(){return t.apply(e,arguments)}};t=function(){function t(t){null==t&&(t={}),this.clearIdentity=e(this.clearIdentity,this),this.identify=e(this.identify,this),this.setKM=e(this.setKM,this),this.set=e(this.set,this),this.trackEcommerce=e(this.trackEcommerce,this),this.trackPageView=e(this.trackPageView,this),this.trackEventKM=e(this.trackEventKM,this),this.trackEventGA=e(this.trackEventGA,this),this.trackEvent=e(this.trackEvent,this),this.clickHandler=e(this.clickHandler,this),this.trackUserActions=e(this.trackUserActions,this),this.settings=this.merge(i,t)}var i;return i={useGoogleAnalytics:!0,useKissMetrics:!0},t.prototype.getLabel=function(t){return t.getAttribute("data-event-label")},t.prototype.trackUserActions=function(t,e,i,n,s){var r,o,a,c;for(a={category:e,action:i||"Click"},n&&(a.label=n),s&&(a.value=s),r=document.querySelectorAll(t),o=0,c=[];o ( + bundle.write({ + format: 'iife', // amd, cjs, es, iife, umd + moduleName: 'WildberryPrincess', + dest: 'dist/wildberry-princess.js', + }) +)) +.then(() => { + console.log('Bundle Created'); +}) +.catch((e) => { + console.error('Rollup Error:', e); +}); diff --git a/src/wildberry_princess.coffee b/src/wildberry_princess.coffee deleted file mode 100644 index ae842f8..0000000 --- a/src/wildberry_princess.coffee +++ /dev/null @@ -1,145 +0,0 @@ -# https://developers.google.com/analytics/devguides/collection/analyticsjs/advanced -# https://developers.google.com/analytics/devguides/collection/analyticsjs/events -# https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference -# https://developers.google.com/analytics/devguides/collection/analyticsjs/custom-dims-mets -class WildberryPrincess - defaults = - useGoogleAnalytics: true - useKissMetrics: true - - constructor: (options = {}) -> - @settings = @merge(defaults, options) - - getLabel: (element) -> - element.getAttribute('data-event-label') - - trackUserActions: (selector, category, action, label, value) => - params = - category: category - action: action or 'Click' - params.label = label if label - params.value = value if value - - elements = document.querySelectorAll(selector) - i = 0 - while i < elements.length - elements[i].data = - eventParams: params - elements[i].removeEventListener 'click', @clickHandler - elements[i].addEventListener 'click', @clickHandler, false - i++ - - clickHandler: (event) => - return unless event - element = event.target - return unless element - - eventParams = element.data.eventParams - - label = if eventParams.label then eventParams.label else @getLabel(element) - - if @settings.useGoogleAnalytics - payload = - hitType: 'event' - eventCategory: eventParams.category - eventAction: eventParams.action - payload.eventLabel = label if label - payload.eventValue = eventParams.value if eventParams.value - - @sendPayloadGA payload - - if @settings.useKissMetrics - payload = - category: eventParams.category - action: eventParams.action - payload.label = label if label - payload.value = eventParams.value if eventParams.value - - @trackEventKM "#{eventParams.category}: #{label} (#{eventParams.action})", payload - - return - - trackEvent: (category, action, label, value) => - if @settings.useGoogleAnalytics - @trackEventGA(category, action, label, value) - - if @settings.useKissMetrics - payload = - category: category - action: action - payload.label = label if label - payload.value = value if value - - @trackEventKM "#{category}: #{label} (#{action})", payload - - trackEventGA: (category, action, label, value) => - payload = - hitType: 'event' - eventCategory: category - eventAction: action - payload.eventLabel = label if label - payload.eventValue = value if value - - @sendPayloadGA payload - - trackEventKM: (label, payload) => - @sendPayloadKM 'record', label, payload - - trackPageView: (page, title) => - page or= window.location.pathname - title or= document.title - payload = - hitType: 'pageview' - page: page - title: title - - @sendPayloadGA payload - - trackEcommerce: (action, payload) => - if window.ga? and @settings.useGoogleAnalytics - window.ga "ecommerce:#{action}", payload - - set: (key, value) => - @setGA(key, value) if @settings.useGoogleAnalytics - if @settings.useKissMetrics - @setKM(key, value) - - setGA: (key, value) -> - if window.ga? - window.ga 'set', key, value - - setKM: (key, value) => - data = {} - data[key] = value - @sendPayloadKM('set', data, null) - - identify: (user_id = 'anonymous') => - # https://developers.google.com/analytics/devguides/collection/analyticsjs/user-id - # https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#userId - # http://support.kissmetrics.com/apis/common-methods#identify - @setGA('userId', user_id) if @settings.useGoogleAnalytics and user_id isnt 'anonymous' - @sendPayloadKM('identify', user_id) if @settings.useKissMetrics - - clearIdentity: => - # http://support.kissmetrics.com/advanced/multiple-people-same-browser/ - @sendPayloadKM('clearIdentity') if @settings.useKissMetrics - - sendPayloadGA: (payload) -> - if window.ga? - window.ga 'send', payload - - sendPayloadKM: (action, payload, data) -> - # http://support.kissmetrics.com/apis/common-methods - if window._kmq? - output = [action] - output.push payload if payload - output.push data if data - - window._kmq.push output - - merge: (input, options) -> - output = JSON.parse(JSON.stringify(input)) - output[k] = v for k, v of options - output - -(exports ? this).WildberryPrincess = WildberryPrincess diff --git a/src/wildberry_princess.js b/src/wildberry_princess.js new file mode 100644 index 0000000..b702580 --- /dev/null +++ b/src/wildberry_princess.js @@ -0,0 +1,185 @@ +export default class WildberryPrincess { + constructor(options = {}) { + this.trackUserActions = this.trackUserActions.bind(this); + this.clickHandler = this.clickHandler.bind(this); + this.trackEvent = this.trackEvent.bind(this); + this.trackPageView = this.trackPageView.bind(this); + this.trackEcommerce = this.trackEcommerce.bind(this); + this.set = this.set.bind(this); + this.identify = this.identify.bind(this); + this.clearIdentity = this.clearIdentity.bind(this); + + const defaults = { + useGoogleAnalytics: true, + useKissMetrics: true, + }; + this.settings = Object.assign({}, defaults, options); + } + + trackUserActions(selector, category, action, label, value) { + const params = { + category, + action: action || 'Click', + }; + if (label) { params.label = label; } + if (value) { params.value = value; } + + const elements = document.querySelectorAll(selector); + let i = 0; + + const result = []; + while (i < elements.length) { + elements[i].data = { eventParams: params }; + elements[i].removeEventListener('click', this.clickHandler); + elements[i].addEventListener('click', this.clickHandler, false); + result.push(i++); + } + } + + clickHandler(event) { + if (event == null) { return; } + const element = event.target; + if (element == null) { return; } + + const { eventParams } = element.data; + const label = eventParams.label ? eventParams.label : this.getLabel(element); + + if (this.settings.useGoogleAnalytics) { + const payload = { + hitType: 'event', + eventCategory: eventParams.category, + eventAction: eventParams.action, + }; + if (label) { payload.eventLabel = label; } + if (eventParams.value) { payload.eventValue = eventParams.value; } + + this.sendPayloadGA(payload); + } + + if (this.settings.useKissMetrics) { + const payload = { + category: eventParams.category, + action: eventParams.action, + }; + if (label) { payload.label = label; } + if (eventParams.value) { payload.value = eventParams.value; } + + this.trackEventKM(`${eventParams.category}: ${label} (${eventParams.action})`, payload); + } + } + + trackEvent(category, action, label, value) { + if (this.settings.useGoogleAnalytics) { + this.trackEventGA(category, action, label, value); + } + + if (this.settings.useKissMetrics) { + const payload = { + category, + action, + }; + if (label) { payload.label = label; } + if (value) { payload.value = value; } + + this.trackEventKM(`${category}: ${label} (${action})`, payload); + } + } + + trackPageView(page, title) { + if (!page) { page = window.location.pathname; } + if (!title) { ({ title } = document); } + const payload = { + hitType: 'pageview', + page, + title, + }; + + if (this.settings.useGoogleAnalytics) { + this.sendPayloadGA(payload); + } + } + + trackEcommerce(action, payload) { + if ((window.ga != null) && this.settings.useGoogleAnalytics) { + window.ga(`ecommerce:${action}`, payload); + } + } + + set(key, value) { + if (this.settings.useGoogleAnalytics) { + this.setGA(key, value); + } + if (this.settings.useKissMetrics) { + this.setKM(key, value); + } + } + + identify(user_id = 'anonymous') { + // https://developers.google.com/analytics/devguides/collection/analyticsjs/user-id + // https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#userId + // http://support.kissmetrics.com/apis/common-methods#identify + if (this.settings.useGoogleAnalytics && user_id !== 'anonymous') { + this.setGA('userId', user_id); + } + if (this.settings.useKissMetrics) { + this.sendPayloadKM('identify', user_id); + } + } + + clearIdentity() { + // http://support.kissmetrics.com/advanced/multiple-people-same-browser/ + if (this.settings.useKissMetrics) { + this.sendPayloadKM('clearIdentity'); + } + } + + // Static / Class Methods + getLabel(element) { + return element.getAttribute('data-event-label'); + } + + trackEventGA(category, action, label, value) { + const payload = { + hitType: 'event', + eventCategory: category, + eventAction: action, + }; + if (label) { payload.eventLabel = label; } + if (value) { payload.eventValue = value; } + + this.sendPayloadGA(payload); + } + + trackEventKM(label, payload) { + this.sendPayloadKM('record', label, payload); + } + + setGA(key, value) { + if (window.ga != null) { + window.ga('set', key, value); + } + } + + setKM(key, value) { + const data = {}; + data[key] = value; + this.sendPayloadKM('set', data, null); + } + + sendPayloadGA(payload) { + if (window.ga != null) { + window.ga('send', payload); + } + } + + sendPayloadKM(action, payload, data) { + // http://support.kissmetrics.com/apis/common-methods + if (window._kmq != null) { + const output = [action]; + if (payload) { output.push(payload); } + if (data) { output.push(data); } + + window._kmq.push(output); + } + } +} diff --git a/test/helpers/setup-browser-env.js b/test/helpers/setup-browser-env.js new file mode 100644 index 0000000..dee5cbd --- /dev/null +++ b/test/helpers/setup-browser-env.js @@ -0,0 +1,3 @@ +const browserEnv = require('browser-env'); + +browserEnv(); diff --git a/test/index.html b/test/index.html index 8cf8602..fbbefc0 100644 --- a/test/index.html +++ b/test/index.html @@ -1,34 +1,19 @@ - + -Mocha - - - + + + +WBP Test Area + -
- - - - - - - - - +
+ +
+ diff --git a/test/mocha.css b/test/mocha.css deleted file mode 100644 index 42b9798..0000000 --- a/test/mocha.css +++ /dev/null @@ -1,270 +0,0 @@ -@charset "utf-8"; - -body { - margin:0; -} - -#mocha { - font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif; - margin: 60px 50px; -} - -#mocha ul, -#mocha li { - margin: 0; - padding: 0; -} - -#mocha ul { - list-style: none; -} - -#mocha h1, -#mocha h2 { - margin: 0; -} - -#mocha h1 { - margin-top: 15px; - font-size: 1em; - font-weight: 200; -} - -#mocha h1 a { - text-decoration: none; - color: inherit; -} - -#mocha h1 a:hover { - text-decoration: underline; -} - -#mocha .suite .suite h1 { - margin-top: 0; - font-size: .8em; -} - -#mocha .hidden { - display: none; -} - -#mocha h2 { - font-size: 12px; - font-weight: normal; - cursor: pointer; -} - -#mocha .suite { - margin-left: 15px; -} - -#mocha .test { - margin-left: 15px; - overflow: hidden; -} - -#mocha .test.pending:hover h2::after { - content: '(pending)'; - font-family: arial, sans-serif; -} - -#mocha .test.pass.medium .duration { - background: #c09853; -} - -#mocha .test.pass.slow .duration { - background: #b94a48; -} - -#mocha .test.pass::before { - content: '✓'; - font-size: 12px; - display: block; - float: left; - margin-right: 5px; - color: #00d6b2; -} - -#mocha .test.pass .duration { - font-size: 9px; - margin-left: 5px; - padding: 2px 5px; - color: #fff; - -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); - -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); - box-shadow: inset 0 1px 1px rgba(0,0,0,.2); - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - -ms-border-radius: 5px; - -o-border-radius: 5px; - border-radius: 5px; -} - -#mocha .test.pass.fast .duration { - display: none; -} - -#mocha .test.pending { - color: #0b97c4; -} - -#mocha .test.pending::before { - content: '◦'; - color: #0b97c4; -} - -#mocha .test.fail { - color: #c00; -} - -#mocha .test.fail pre { - color: black; -} - -#mocha .test.fail::before { - content: '✖'; - font-size: 12px; - display: block; - float: left; - margin-right: 5px; - color: #c00; -} - -#mocha .test pre.error { - color: #c00; - max-height: 300px; - overflow: auto; -} - -/** - * (1): approximate for browsers not supporting calc - * (2): 42 = 2*15 + 2*10 + 2*1 (padding + margin + border) - * ^^ seriously - */ -#mocha .test pre { - display: block; - float: left; - clear: left; - font: 12px/1.5 monaco, monospace; - margin: 5px; - padding: 15px; - border: 1px solid #eee; - max-width: 85%; /*(1)*/ - max-width: calc(100% - 42px); /*(2)*/ - word-wrap: break-word; - border-bottom-color: #ddd; - -webkit-border-radius: 3px; - -webkit-box-shadow: 0 1px 3px #eee; - -moz-border-radius: 3px; - -moz-box-shadow: 0 1px 3px #eee; - border-radius: 3px; -} - -#mocha .test h2 { - position: relative; -} - -#mocha .test a.replay { - position: absolute; - top: 3px; - right: 0; - text-decoration: none; - vertical-align: middle; - display: block; - width: 15px; - height: 15px; - line-height: 15px; - text-align: center; - background: #eee; - font-size: 15px; - -moz-border-radius: 15px; - border-radius: 15px; - -webkit-transition: opacity 200ms; - -moz-transition: opacity 200ms; - transition: opacity 200ms; - opacity: 0.3; - color: #888; -} - -#mocha .test:hover a.replay { - opacity: 1; -} - -#mocha-report.pass .test.fail { - display: none; -} - -#mocha-report.fail .test.pass { - display: none; -} - -#mocha-report.pending .test.pass, -#mocha-report.pending .test.fail { - display: none; -} -#mocha-report.pending .test.pass.pending { - display: block; -} - -#mocha-error { - color: #c00; - font-size: 1.5em; - font-weight: 100; - letter-spacing: 1px; -} - -#mocha-stats { - position: fixed; - top: 15px; - right: 10px; - font-size: 12px; - margin: 0; - color: #888; - z-index: 1; -} - -#mocha-stats .progress { - float: right; - padding-top: 0; -} - -#mocha-stats em { - color: black; -} - -#mocha-stats a { - text-decoration: none; - color: inherit; -} - -#mocha-stats a:hover { - border-bottom: 1px solid #eee; -} - -#mocha-stats li { - display: inline-block; - margin: 0 5px; - list-style: none; - padding-top: 11px; -} - -#mocha-stats canvas { - width: 40px; - height: 40px; -} - -#mocha code .comment { color: #ddd; } -#mocha code .init { color: #2f6fad; } -#mocha code .string { color: #5890ad; } -#mocha code .keyword { color: #8a6343; } -#mocha code .number { color: #2f6fad; } - -@media screen and (max-device-width: 480px) { - #mocha { - margin: 60px 0px; - } - - #mocha #stats { - position: absolute; - } -} diff --git a/test/wildberry_princess.clickHandler.test.js b/test/wildberry_princess.clickHandler.test.js new file mode 100644 index 0000000..307601f --- /dev/null +++ b/test/wildberry_princess.clickHandler.test.js @@ -0,0 +1,174 @@ +import test from 'ava'; +import sinon from 'sinon'; +import WildberryPrincess from '../src/wildberry_princess'; + +let wbp; +let button; +let wbp_click_spy; +let ga_send_spy; +let km_send_spy; +let ga_spy; +let kmq_spy; + +test.beforeEach((_t) => { + button = document.createElement('button'); + button.textConent = 'First Button'; + button.setAttribute('data-event-label', 'First Button'); + document.body.appendChild(button); + + window.ga = () => {}; + window._kmq = {}; + window._kmq.push = () => {}; + ga_spy = sinon.spy(window, 'ga'); + kmq_spy = sinon.spy(window._kmq, 'push'); + + wbp = new WildberryPrincess(); + wbp_click_spy = sinon.spy(wbp, 'clickHandler'); + ga_send_spy = sinon.spy(wbp, 'sendPayloadGA'); + km_send_spy = sinon.spy(wbp, 'sendPayloadKM'); +}); + +test.afterEach((_t) => { + button.parentNode.removeChild(button); + + window.ga.restore(); + window._kmq.push.restore(); + wbp.clickHandler.restore(); + wbp.sendPayloadGA.restore(); + wbp.sendPayloadKM.restore(); +}); + +test('#clickHandler: should track clicks on elements', (t) => { + wbp.trackUserActions('button', 'Buttons'); + const click_event = document.createEvent('HTMLEvents'); + click_event.initEvent('click', true, false); + button.dispatchEvent(click_event); + + t.is(wbp_click_spy.callCount, 1); + t.is(ga_send_spy.callCount, 1); + t.is(km_send_spy.callCount, 1); + t.is(ga_spy.callCount, 1); + t.is(kmq_spy.callCount, 1); + + t.true(ga_spy.calledWith('send', { + eventCategory: 'Buttons', + eventAction: 'Click', + eventLabel: 'First Button', + hitType: 'event', + })); + + t.true(kmq_spy.calledWith([ + 'record', 'Buttons: First Button (Click)', { + action: 'Click', + category: 'Buttons', + label: 'First Button', + }, + ])); +}); + +test('#clickHandler: should not set a label unless it is provided', (t) => { + button.removeAttribute('data-event-label'); + wbp.trackUserActions('button', 'Buttons'); + const click_event = document.createEvent('HTMLEvents'); + click_event.initEvent('click', true, false); + button.dispatchEvent(click_event); + + t.is(wbp_click_spy.callCount, 1); + t.is(ga_send_spy.callCount, 1); + t.is(km_send_spy.callCount, 1); + t.is(ga_spy.callCount, 1); + t.is(kmq_spy.callCount, 1); + + t.true(ga_spy.calledWith('send', { + eventCategory: 'Buttons', + eventAction: 'Click', + hitType: 'event', + })); + + t.true(kmq_spy.calledWith([ + 'record', 'Buttons: null (Click)', { + action: 'Click', + category: 'Buttons', + }, + ])); +}); + +test('#clickHandler: should track clicks on elements with optional value', (t) => { + wbp.trackUserActions('button', 'Buttons', 'Click', null, 1); + const click_event = document.createEvent('HTMLEvents'); + click_event.initEvent('click', true, false); + button.dispatchEvent(click_event); + + t.is(wbp_click_spy.callCount, 1); + t.is(ga_send_spy.callCount, 1); + t.is(km_send_spy.callCount, 1); + t.is(ga_spy.callCount, 1); + t.is(kmq_spy.callCount, 1); + + t.true(ga_spy.calledWith('send', { + eventCategory: 'Buttons', + eventAction: 'Click', + eventLabel: 'First Button', + eventValue: 1, + hitType: 'event', + })); + + t.true(kmq_spy.calledWith([ + 'record', 'Buttons: First Button (Click)', { + action: 'Click', + category: 'Buttons', + label: 'First Button', + value: 1, + }, + ])); +}); + +test('#clickHandler: should return when there is no event', (t) => { + wbp.clickHandler(); + + t.is(wbp_click_spy.callCount, 1); + t.is(ga_send_spy.callCount, 0); + t.is(km_send_spy.callCount, 0); + t.is(ga_spy.callCount, 0); + t.is(kmq_spy.callCount, 0); +}); + +test('#clickHandler: should return when there is no eventParams', (t) => { + const click_event = document.createEvent('HTMLEvents'); + click_event.initEvent('click', true, false); + wbp.clickHandler(click_event); + + t.is(wbp_click_spy.callCount, 1); + t.is(ga_send_spy.callCount, 0); + t.is(km_send_spy.callCount, 0); + t.is(ga_spy.callCount, 0); + t.is(kmq_spy.callCount, 0); +}); + +test('#clickHandler: should not call GA when useGoogleAnalytics is false', (t) => { + wbp.settings.useGoogleAnalytics = false; + wbp.trackUserActions('button', 'Buttons'); + const click_event = document.createEvent('HTMLEvents'); + click_event.initEvent('click', true, false); + button.dispatchEvent(click_event); + + t.is(wbp_click_spy.callCount, 1); + t.is(ga_send_spy.callCount, 0); + t.is(km_send_spy.callCount, 1); + t.is(ga_spy.callCount, 0); + t.is(kmq_spy.callCount, 1); +}); + +test('#clickHandler: should not call KM when useGoogleAnalytics is false', (t) => { + wbp.settings.useKissMetrics = false; + wbp.trackUserActions('button', 'Buttons'); + const click_event = document.createEvent('HTMLEvents'); + click_event.initEvent('click', true, false); + button.dispatchEvent(click_event); + + t.is(wbp_click_spy.callCount, 1); + t.is(ga_send_spy.callCount, 1); + t.is(km_send_spy.callCount, 0); + t.is(ga_spy.callCount, 1); + t.is(kmq_spy.callCount, 0); +}); diff --git a/test/wildberry_princess.constructor.test.js b/test/wildberry_princess.constructor.test.js new file mode 100644 index 0000000..895de24 --- /dev/null +++ b/test/wildberry_princess.constructor.test.js @@ -0,0 +1,56 @@ +import test from 'ava'; +import WildberryPrincess from '../src/wildberry_princess'; + +let wbp; + +test.beforeEach((_t) => { + window.ga = () => {}; + window._kmq = {}; + window._kmq.push = () => {}; + wbp = new WildberryPrincess(); +}); + +test('#constructor: should contruct without issue', (t) => { + t.true(wbp instanceof WildberryPrincess); +}); + +test('#constructor: should have known functions', (t) => { + t.true(typeof wbp.trackUserActions === 'function'); + t.true(typeof wbp.clickHandler === 'function'); + t.true(typeof wbp.trackEvent === 'function'); + t.true(typeof wbp.trackPageView === 'function'); + t.true(typeof wbp.trackEcommerce === 'function'); + t.true(typeof wbp.set === 'function'); + t.true(typeof wbp.identify === 'function'); + t.true(typeof wbp.clearIdentity === 'function'); + + t.true(typeof wbp.trackEventGA === 'function'); + t.true(typeof wbp.trackEventKM === 'function'); + t.true(typeof wbp.setGA === 'function'); + t.true(typeof wbp.setKM === 'function'); + t.true(typeof wbp.sendPayloadGA === 'function'); + t.true(typeof wbp.sendPayloadKM === 'function'); +}); + +test('#constructor: should have default setting', (t) => { + t.deepEqual(Object.keys(wbp.settings), ['useGoogleAnalytics', 'useKissMetrics']); + t.true(wbp.settings.useGoogleAnalytics); + t.true(wbp.settings.useKissMetrics); +}); + +test('#constructor: should set the settings based on passed in configuration', (t) => { + wbp = new WildberryPrincess({ useGoogleAnalytics: false }); + t.false(wbp.settings.useGoogleAnalytics); + t.true(wbp.settings.useKissMetrics); + + wbp = new WildberryPrincess({ useKissMetrics: false }); + t.true(wbp.settings.useGoogleAnalytics); + t.false(wbp.settings.useKissMetrics); + + wbp = new WildberryPrincess({ + useGoogleAnalytics: false, + useKissMetrics: false, + }); + t.false(wbp.settings.useGoogleAnalytics); + t.false(wbp.settings.useKissMetrics); +}); diff --git a/test/wildberry_princess.identify.test.js b/test/wildberry_princess.identify.test.js new file mode 100644 index 0000000..6dadba2 --- /dev/null +++ b/test/wildberry_princess.identify.test.js @@ -0,0 +1,81 @@ +import test from 'ava'; +import sinon from 'sinon'; +import WildberryPrincess from '../src/wildberry_princess'; + +let wbp; +let key; +let value; +let kmq_spy; +let setga_spy; + +test.beforeEach((_t) => { + window.ga = () => {}; + window._kmq = {}; + window._kmq.push = () => {}; + kmq_spy = sinon.spy(window._kmq, 'push'); + + wbp = new WildberryPrincess(); + setga_spy = sinon.spy(wbp, 'setGA'); + key = 'my-key'; + value = 'my-value'; +}); + +test.afterEach((_t) => { + window._kmq.push.restore(); +}); + +test('#identify: should not call setGA when GA is enabled without a user_ID', (t) => { + t.is(setga_spy.callCount, 0); + wbp.identify(); + t.is(setga_spy.callCount, 0); +}); + +test('#identify: should call setGA when GA is enabled with an user_id', (t) => { + t.is(setga_spy.callCount, 0); + wbp.identify('1234'); + t.is(setga_spy.callCount, 1); + t.true(setga_spy.calledWith('userId', '1234')); +}); + +test('#identify: should not call setGA when GA is disabled', (t) => { + wbp = new WildberryPrincess({ useGoogleAnalytics: false }); + t.is(setga_spy.callCount, 0); + wbp.identify(key, value); + t.is(setga_spy.callCount, 0); +}); + +test('#identify: should call setKM when KM is enabled', (t) => { + t.is(kmq_spy.callCount, 0); + wbp.identify(); + t.is(kmq_spy.callCount, 1); + t.true(kmq_spy.calledWith(['identify', 'anonymous'])); +}); + +test('#identify: should call setKM when KM is enabled with an user_id', (t) => { + t.is(kmq_spy.callCount, 0); + wbp.identify('1234'); + t.is(kmq_spy.callCount, 1); + t.true(kmq_spy.calledWith(['identify', '1234'])); +}); + +test('#identify: should not call setKM when KM is disabled', (t) => { + wbp = new WildberryPrincess({ useKissMetrics: false }); + t.is(kmq_spy.callCount, 0); + wbp.identify(key, value); + t.is(kmq_spy.callCount, 0); +}); + +// #clearIdentity +test('#clearIdentity: should call sendPayloadKM when KM is enabled', (t) => { + t.is(kmq_spy.callCount, 0); + wbp.clearIdentity(); + t.is(kmq_spy.callCount, 1); + t.true(kmq_spy.calledWith(['clearIdentity'])); +}); + +test('#clearIdentity: should not call sendPayloadKM when KM is disabled', (t) => { + wbp = new WildberryPrincess({ useKissMetrics: false }); + t.is(kmq_spy.callCount, 0); + wbp.clearIdentity(key, value); + t.is(kmq_spy.callCount, 0); +}); diff --git a/test/wildberry_princess.sendPayload.test.js b/test/wildberry_princess.sendPayload.test.js new file mode 100644 index 0000000..57c2a96 --- /dev/null +++ b/test/wildberry_princess.sendPayload.test.js @@ -0,0 +1,77 @@ +import test from 'ava'; +import sinon from 'sinon'; +import WildberryPrincess from '../src/wildberry_princess'; + +let wbp; +let ga_spy; +let kmq_spy; + +test.beforeEach((_t) => { + window.ga = () => {}; + window._kmq = {}; + window._kmq.push = () => {}; + ga_spy = sinon.spy(window, 'ga'); + kmq_spy = sinon.spy(window._kmq, 'push'); + + wbp = new WildberryPrincess(); +}); + +// #sendPayloadGA +test('#sendPayloadGA: should send the payload when there is GA', (t) => { + const payload = { + hitType: 'event', + eventCategory: 'my-category', + eventAction: 'my-action', + eventLabel: 'my-label', + eventValue: 'my-value', + }; + + t.is(ga_spy.callCount, 0); + wbp.sendPayloadGA(payload); + t.is(ga_spy.callCount, 1); + t.true(ga_spy.calledWith('send', payload)); +}); + +test('#sendPayloadGA: should not send the payload when there is no GA', (t) => { + const payload = { + hitType: 'event', + eventCategory: 'my-category', + eventAction: 'my-action', + eventLabel: 'my-label', + eventValue: 'my-value', + }; + + window.ga = null; + t.is(ga_spy.callCount, 0); + wbp.sendPayloadGA(payload); + t.is(ga_spy.callCount, 0); +}); + +// #sendPayloadKM +test('#sendPayloadKM: should send the full payload when there is KM', (t) => { + t.is(kmq_spy.callCount, 0); + wbp.sendPayloadKM('record', 'event', { 'event-data': '1' }); + t.is(kmq_spy.callCount, 1); + t.true(kmq_spy.calledWith(['record', 'event', { 'event-data': '1' }])); +}); + +test('#sendPayloadKM: should send the partial payload when there is KM', (t) => { + t.is(kmq_spy.callCount, 0); + wbp.sendPayloadKM('record', 'event'); + t.is(kmq_spy.callCount, 1); + t.true(kmq_spy.calledWith(['record', 'event'])); +}); + +test('#sendPayloadKM: should send the action-only payload when there is KM', (t) => { + t.is(kmq_spy.callCount, 0); + wbp.sendPayloadKM('record'); + t.is(kmq_spy.callCount, 1); + t.true(kmq_spy.calledWith(['record'])); +}); + +test('#sendPayloadKM: should not send the payload when there is no KM', (t) => { + window._kmq = null; + t.is(kmq_spy.callCount, 0); + wbp.sendPayloadKM('record'); + t.is(kmq_spy.callCount, 0); +}); diff --git a/test/wildberry_princess.set.test.js b/test/wildberry_princess.set.test.js new file mode 100644 index 0000000..7c38f26 --- /dev/null +++ b/test/wildberry_princess.set.test.js @@ -0,0 +1,85 @@ +import test from 'ava'; +import sinon from 'sinon'; +import WildberryPrincess from '../src/wildberry_princess'; + +let wbp; +let ga_spy; +let kmq_spy; +let key; +let value; +let setga_spy; +let setkm_spy; + +test.beforeEach((_t) => { + window.ga = () => {}; + window._kmq = {}; + window._kmq.push = () => {}; + ga_spy = sinon.spy(window, 'ga'); + kmq_spy = sinon.spy(window._kmq, 'push'); + + wbp = new WildberryPrincess(); + + setga_spy = sinon.spy(wbp, 'setGA'); + setkm_spy = sinon.spy(wbp, 'setKM'); + + key = 'my-key'; + value = 'my-value'; +}); + +test('#set: should call setGA when GA is enabled', (t) => { + t.is(setga_spy.callCount, 0); + wbp.set(key, value); + t.is(setga_spy.callCount, 1); +}); + +test('#set: should not call setGA when GA is disabled', (t) => { + wbp = new WildberryPrincess({ useGoogleAnalytics: false }); + t.is(setga_spy.callCount, 0); + wbp.set(key, value); + t.is(setga_spy.callCount, 0); +}); + +test('#set: should call setKM when KM is enabled', (t) => { + t.is(setkm_spy.callCount, 0); + wbp.set(key, value); + t.is(setkm_spy.callCount, 1); +}); + +test('#set: should not call setKM when KM is disabled', (t) => { + wbp = new WildberryPrincess({ useKissMetrics: false }); + t.is(setkm_spy.callCount, 0); + wbp.set(key, value); + t.is(setkm_spy.callCount, 0); +}); + +// #setGA +test('#setGA: should set the key to the value when there is GA', (t) => { + t.is(ga_spy.callCount, 0); + wbp.setGA(key, value); + t.is(ga_spy.callCount, 1); + t.true(ga_spy.calledWith('set', key, value)); +}); + +test('#setGA: should not set the key to the value when there is no GA', (t) => { + window.ga = null; + t.is(ga_spy.callCount, 0); + wbp.setGA(key, value); + t.is(ga_spy.callCount, 0); +}); + +// #setKM +test('#setKM: should set the key to the value when there is KM', (t) => { + t.is(kmq_spy.callCount, 0); + wbp.setKM(key, value); + t.is(kmq_spy.callCount, 1); + const output = {}; + output[key] = value; + t.true(kmq_spy.calledWith(['set', output])); +}); + +test('#setKM: should not set the key to the value when there is no MK', (t) => { + window._kmq = null; + t.is(kmq_spy.callCount, 0); + wbp.setKM(key, value); + t.is(kmq_spy.callCount, 0); +}); diff --git a/test/wildberry_princess.trackEcommerce.test.js b/test/wildberry_princess.trackEcommerce.test.js new file mode 100644 index 0000000..e2951d1 --- /dev/null +++ b/test/wildberry_princess.trackEcommerce.test.js @@ -0,0 +1,59 @@ +import test from 'ava'; +import sinon from 'sinon'; +import WildberryPrincess from '../src/wildberry_princess'; + +let ga_spy; +let wbp; +let transaction; +let transaction_id; +let item; + +test.beforeEach((_t) => { + window.ga = () => {}; + window._kmq = {}; + window._kmq.push = () => {}; + ga_spy = sinon.spy(window, 'ga'); + + wbp = new WildberryPrincess(); + + transaction_id = `${Date.now()}`; + transaction = { + id: transaction_id, + affiliation: 'Candy Kingdom', + revenue: 123, + shipping: '0', + tax: '0', + }; + item = { + id: transaction_id, + name: 'b', + category: 'a', + price: 123, + quantity: 1, + }; +}); + +test('#trackEcommerce: should send the payload when there is GA', (t) => { + t.is(ga_spy.callCount, 0); + wbp.trackEcommerce('clear'); + t.true(ga_spy.calledWith('ecommerce:clear')); + wbp.trackEcommerce('addTransaction', transaction); + t.true(ga_spy.calledWith('ecommerce:addTransaction', transaction)); + wbp.trackEcommerce('addItem', item); + t.true(ga_spy.calledWith('ecommerce:addItem', item)); + wbp.trackEcommerce('send'); + t.true(ga_spy.calledWith('ecommerce:send')); +}); + +test('#trackEcommerce: should not send the payload when there is no GA', (t) => { + window.ga = null; + t.is(ga_spy.callCount, 0); + wbp.trackEcommerce('clear'); + t.is(ga_spy.callCount, 0); + wbp.trackEcommerce('addTransaction', transaction); + t.is(ga_spy.callCount, 0); + wbp.trackEcommerce('addItem', item); + t.is(ga_spy.callCount, 0); + wbp.trackEcommerce('send'); + t.is(ga_spy.callCount, 0); +}); diff --git a/test/wildberry_princess.trackEvent.test.js b/test/wildberry_princess.trackEvent.test.js new file mode 100644 index 0000000..1dea26a --- /dev/null +++ b/test/wildberry_princess.trackEvent.test.js @@ -0,0 +1,127 @@ +import test from 'ava'; +import sinon from 'sinon'; +import WildberryPrincess from '../src/wildberry_princess'; + +let wbp; +let ga_spy; +let kmq_spy; +let ga_send_spy; +let km_send_spy; + +let track_event_ga_spy; +let track_event_km_spy; + +test.beforeEach((_t) => { + window.ga = () => {}; + window._kmq = {}; + window._kmq.push = () => {}; + ga_spy = sinon.spy(window, 'ga'); + kmq_spy = sinon.spy(window._kmq, 'push'); + + wbp = new WildberryPrincess(); + track_event_ga_spy = sinon.spy(wbp, 'trackEventGA'); + track_event_km_spy = sinon.spy(wbp, 'trackEventKM'); + ga_send_spy = sinon.spy(wbp, 'sendPayloadGA'); + km_send_spy = sinon.spy(wbp, 'sendPayloadKM'); +}); + +test('#trackEvent: should call trackEventGA when GA is enabled', (t) => { + t.is(track_event_ga_spy.callCount, 0); + wbp.trackEvent('a', 'b', 'c', 'd'); + t.is(track_event_ga_spy.callCount, 1); +}); + +test('#trackEvent: should not call trackEventGA when GA is disabled', (t) => { + wbp = new WildberryPrincess({ useGoogleAnalytics: false }); + t.is(track_event_ga_spy.callCount, 0); + wbp.trackEvent('a', 'b', 'c', 'd'); + t.is(track_event_ga_spy.callCount, 0); +}); + +test('#trackEvent: should call trackEventKM when KM is enabled', (t) => { + t.is(track_event_km_spy.callCount, 0); + wbp.trackEvent('a', 'b', 'c', 'd'); + t.is(track_event_km_spy.callCount, 1); +}); + +test('#trackEvent: should call trackEventKM with the correct params', (t) => { + t.is(track_event_km_spy.callCount, 0); + wbp.trackEvent('a', 'b', 'c', 'd'); + t.true(track_event_km_spy.calledWith('a: c (b)', { + action: 'b', + category: 'a', + label: 'c', + value: 'd', + })); +}); + +test('#trackEvent: should not call trackEventKM when KM is disabled', (t) => { + wbp = new WildberryPrincess({ useKissMetrics: false }); + t.is(track_event_km_spy.callCount, 0); + wbp.trackEvent('a', 'b', 'c', 'd'); + t.is(track_event_km_spy.callCount, 0); +}); + +test('#trackEvent: should exclude label and value when not set', (t) => { + t.is(track_event_km_spy.callCount, 0); + wbp.trackEvent('a', 'b'); + t.true(track_event_km_spy.calledWith('a: undefined (b)', { action: 'b', category: 'a' })); +}); + +// trackEventGA +test('#trackEventGA: should track the event', (t) => { + wbp.trackEventGA('a', 'b', 'c', 'd'); + + const payload = { + eventCategory: 'a', + eventAction: 'b', + eventLabel: 'c', + eventValue: 'd', + hitType: 'event', + }; + + t.is(ga_send_spy.callCount, 1); + t.true(ga_send_spy.calledWith(payload)); + t.is(ga_spy.callCount, 1); + t.true(ga_spy.calledWith('send', payload)); +}); + +test('#trackEventGA: should track the event without a label', (t) => { + wbp.trackEventGA('a', 'b', null, 'd'); + + const payload = { + eventCategory: 'a', + eventAction: 'b', + eventValue: 'd', + hitType: 'event', + }; + + t.is(ga_send_spy.callCount, 1); + t.true(ga_send_spy.calledWith(payload)); + t.is(ga_spy.callCount, 1); + t.true(ga_spy.calledWith('send', payload)); +}); + +test('#trackEventGA: should track the event without a value', (t) => { + wbp.trackEventGA('a', 'b', 'c'); + + const payload = { + eventCategory: 'a', + eventAction: 'b', + eventLabel: 'c', + hitType: 'event', + }; + + t.is(ga_send_spy.callCount, 1); + t.true(ga_send_spy.calledWith(payload)); + t.is(ga_spy.callCount, 1); + t.true(ga_spy.calledWith('send', payload)); +}); + +// trackEventKM +test('#trackEventKM: should track the event using sendPayloadKM', (t) => { + wbp.trackEventKM('!label', { '!key': '!value' }); + t.is(km_send_spy.callCount, 1); + t.true(km_send_spy.calledWith('record', '!label', { '!key': '!value' })); + t.is(kmq_spy.callCount, 1); +}); diff --git a/test/wildberry_princess.trackPageView.test.js b/test/wildberry_princess.trackPageView.test.js new file mode 100644 index 0000000..4f35e54 --- /dev/null +++ b/test/wildberry_princess.trackPageView.test.js @@ -0,0 +1,65 @@ +import test from 'ava'; +import sinon from 'sinon'; +import WildberryPrincess from '../src/wildberry_princess'; + +let wbp; +let ga_spy; +let ga_send_spy; + +test.beforeEach((_t) => { + window.ga = () => {}; + ga_spy = sinon.spy(window, 'ga'); + + wbp = new WildberryPrincess(); + ga_send_spy = sinon.spy(wbp, 'sendPayloadGA'); +}); + +test('#trackPageView: should track the page view', (t) => { + wbp.trackPageView('a', 'b'); + + const payload = { + page: 'a', + title: 'b', + hitType: 'pageview', + }; + + t.is(ga_send_spy.callCount, 1); + t.true(ga_send_spy.calledWith(payload)); + t.is(ga_spy.callCount, 1); + t.true(ga_spy.calledWith('send', payload)); +}); + +test('#trackPageView: should not track the page view if GA is not enabled', (t) => { + wbp = new WildberryPrincess({ useGoogleAnalytics: false }); + t.is(ga_send_spy.callCount, 0); + wbp.trackPageView('a', 'b'); + t.is(ga_send_spy.callCount, 0); +}); + +test('#trackPageView: should track the page view without a page provided', (t) => { + wbp.trackPageView(null, 'b'); + const payload = { + page: window.location.pathname, + title: 'b', + hitType: 'pageview', + }; + + t.is(ga_send_spy.callCount, 1); + t.true(ga_send_spy.calledWith(payload)); + t.is(ga_spy.callCount, 1); + t.true(ga_spy.calledWith('send', payload)); +}); + +test('#trackPageView: should track the page view without a title', (t) => { + wbp.trackPageView('a', null); + const payload = { + page: 'a', + title: document.title, + hitType: 'pageview', + }; + + t.is(ga_send_spy.callCount, 1); + t.true(ga_send_spy.calledWith(payload)); + t.is(ga_spy.callCount, 1); + t.true(ga_spy.calledWith('send', payload)); +}); diff --git a/test/wildberry_princess.trackUserActions.test.js b/test/wildberry_princess.trackUserActions.test.js new file mode 100644 index 0000000..ef4be7a --- /dev/null +++ b/test/wildberry_princess.trackUserActions.test.js @@ -0,0 +1,45 @@ +import test from 'ava'; +import sinon from 'sinon'; +import WildberryPrincess from '../src/wildberry_princess'; + +let wbp; +let button; + +test.beforeEach((_t) => { + button = document.createElement('button'); + button.textConent = 'First Button'; + button.setAttribute('data-event-label', 'First Button'); + document.body.appendChild(button); + + window.ga = () => {}; + window._kmq = {}; + window._kmq.push = () => {}; + sinon.spy(window, 'ga'); + sinon.spy(window._kmq, 'push'); + wbp = new WildberryPrincess(); +}); + +test.afterEach((_t) => { + button.parentNode.removeChild(button); + + window.ga.restore(); + window._kmq.push.restore(); +}); + +test('#trackUserActions: should add data and click handlers to the elements', (t) => { + const wbp_spy = sinon.spy(wbp, 'trackUserActions'); + wbp.trackUserActions('button', 'Buttons'); + t.is(wbp_spy.callCount, 1); + const event_data = document.querySelector('button').data; + t.true({}.hasOwnProperty.call(event_data, 'eventParams')); + t.deepEqual(Object.keys(event_data.eventParams), ['category', 'action']); +}); + +test('#trackUserActions: should add label and value data when supplied', (t) => { + const wbp_spy = sinon.spy(wbp, 'trackUserActions'); + wbp.trackUserActions('button', 'Buttons', 'Click', 'Label', 1); + t.is(wbp_spy.callCount, 1); + const event_data = document.querySelector('button').data; + t.true({}.hasOwnProperty.call(event_data, 'eventParams')); + t.deepEqual(Object.keys(event_data.eventParams), ['category', 'action', 'label', 'value']); +}); diff --git a/test/wildberry_princess_spec.coffee b/test/wildberry_princess_spec.coffee deleted file mode 100644 index 53fbb64..0000000 --- a/test/wildberry_princess_spec.coffee +++ /dev/null @@ -1,651 +0,0 @@ -# Are we in iojs? -if require? - sinon = require('sinon') - sinonChai = require('sinon-chai') - chai = require('chai') - global.should = chai.should() - global.expect = chai.expect - - chai.should() - chai.use(sinonChai) - - WildberryPrincess = require('../build/wildberry_princess').WildberryPrincess -else - WildberryPrincess = window.WildberryPrincess - sinon = window.sinon - -describe 'WildberryPrincess', -> - # Globals - jQuery = jQuery or null - wbp = ga_spy = kmq_spy = null - transaction_id = transaction = item = key = value = payload = null - - beforeEach -> - window.ga = -> - window._kmq = {} - window._kmq.push = (a) -> - ga_spy = sinon.spy(window, 'ga') - kmq_spy = sinon.spy(window._kmq, 'push') - wbp = new WildberryPrincess() - - it 'should contruct without issue', -> - wbp.should.be.an.instanceof(WildberryPrincess) - - it 'should have known functions', -> - wbp.should.itself.to.respondTo('getLabel') - wbp.should.itself.to.respondTo('trackUserActions') - wbp.should.itself.to.respondTo('clickHandler') - wbp.should.itself.to.respondTo('trackEvent') - wbp.should.itself.to.respondTo('trackEventGA') - wbp.should.itself.to.respondTo('trackEventKM') - wbp.should.itself.to.respondTo('trackPageView') - wbp.should.itself.to.respondTo('trackEcommerce') - wbp.should.itself.to.respondTo('set') - wbp.should.itself.to.respondTo('setGA') - wbp.should.itself.to.respondTo('setKM') - wbp.should.itself.to.respondTo('identify') - wbp.should.itself.to.respondTo('clearIdentity') - wbp.should.itself.to.respondTo('sendPayloadGA') - wbp.should.itself.to.respondTo('sendPayloadKM') - wbp.should.itself.to.respondTo('merge') - - it 'should have default setting', -> - wbp.settings.should.have.any.keys('useGoogleAnalytics', 'useKissMetrics') - wbp.settings.useGoogleAnalytics.should.be.true - wbp.settings.useKissMetrics.should.be.true - - it 'should set the settings based on passed in configuration', -> - wbp = new WildberryPrincess(useGoogleAnalytics: false) - wbp.settings.useGoogleAnalytics.should.be.false - wbp.settings.useKissMetrics.should.be.true - - wbp = new WildberryPrincess(useKissMetrics: false) - wbp.settings.useGoogleAnalytics.should.be.true - wbp.settings.useKissMetrics.should.be.false - - wbp = new WildberryPrincess(useGoogleAnalytics: false, useKissMetrics: false) - wbp.settings.useGoogleAnalytics.should.be.false - wbp.settings.useKissMetrics.should.be.false - - describe '#trackUserActions', -> - wbp_spy = null - - beforeEach -> - wbp_spy = sinon.spy(wbp, 'trackUserActions') - - button = document.createElement('button') - button.textConent = 'First Button' - button.setAttribute('data-event-label', 'First Button') - document.body.appendChild button - - it 'should add data and click handlers to the elements', -> - wbp.trackUserActions('button', 'Buttons') - - wbp_spy.should.have.been.calledOnce - - event_data = document.querySelector('button').data - event_data.should.have.property('eventParams') - event_data.eventParams.should.have.keys('category', 'action') - - it 'should add label and value data when supplied', -> - wbp.trackUserActions('button', 'Buttons', 'Click', 'Label', 1) - - wbp_spy.should.have.been.calledOnce - - event_data = document.querySelector('button').data - event_data.should.have.property('eventParams') - event_data.eventParams.should.have.keys('category', 'action', 'label', 'value') - - describe '#clickHandler', -> - wbp_click_spy = ga_send_spy = km_send_spy = button = null - - beforeEach -> - wbp_click_spy = sinon.spy(wbp, 'clickHandler') - ga_send_spy = sinon.spy(wbp, 'sendPayloadGA') - km_send_spy = sinon.spy(wbp, 'sendPayloadKM') - - button = document.createElement('button') - button.innerText = 'First Button' - button.setAttribute('data-event-label', 'First Button') - document.body.appendChild button - - afterEach -> - button.parentNode.removeChild(button) - - it 'should track clicks on elements', -> - wbp.trackUserActions('button', 'Buttons') - - # Trigger Click - click_event = document.createEvent('HTMLEvents') - click_event.initEvent('click', true, false) - button.dispatchEvent(click_event) - - wbp_click_spy.should.have.been.calledOnce - ga_send_spy.should.have.been.calledOnce - km_send_spy.should.have.been.calledOnce - ga_spy.should.have.been.calledOnce - payload = - eventCategory: 'Buttons' - eventAction: 'Click' - eventLabel: 'First Button' - hitType: 'event' - ga_spy.should.have.been.calledWith 'send', payload - payload = [ - "record", - "Buttons: First Button (Click)", - { - action: "Click" - category: "Buttons" - label: "First Button" - } - ] - kmq_spy.should.have.been.calledWith payload - - it 'should not set a label unless it is provided', -> - button.removeAttribute('data-event-label') - wbp.trackUserActions('button', 'Buttons') - - # Trigger Click - click_event = document.createEvent('HTMLEvents') - click_event.initEvent('click', true, false) - button.dispatchEvent(click_event) - - wbp_click_spy.should.have.been.calledOnce - ga_send_spy.should.have.been.calledOnce - km_send_spy.should.have.been.calledOnce - ga_spy.should.have.been.calledOnce - payload = - eventCategory: 'Buttons' - eventAction: 'Click' - hitType: 'event' - ga_spy.should.have.been.calledWith 'send', payload - payload = [ - "record" - "Buttons: null (Click)" - { - action: "Click" - category: "Buttons" - } - ] - kmq_spy.should.have.been.calledWith payload - - it 'should track clicks on elements with optional value', -> - wbp.trackUserActions('button', 'Buttons', 'Click', null, 1) - - # Trigger Click - click_event = document.createEvent('HTMLEvents') - click_event.initEvent('click', true, false) - button.dispatchEvent(click_event) - - wbp_click_spy.should.have.been.calledOnce - ga_send_spy.should.have.been.calledOnce - km_send_spy.should.have.been.calledOnce - ga_spy.should.have.been.calledOnce - payload = - eventCategory: 'Buttons' - eventAction: 'Click' - eventLabel: 'First Button' - eventValue: 1 - hitType: 'event' - ga_spy.should.have.been.calledWith 'send', payload - kmq_spy.should.have.been.calledOnce - payload = [ - "record" - "Buttons: First Button (Click)" - { - action: "Click" - category: "Buttons" - label: "First Button" - value: 1 - } - ] - kmq_spy.should.have.been.calledWith payload - - it 'should return when there is no event', -> - wbp.clickHandler() - - wbp_click_spy.should.have.been.calledOnce - ga_send_spy.should.not.have.been.calledOnce - km_send_spy.should.not.have.been.calledOnce - ga_spy.should.not.have.been.calledOnce - kmq_spy.should.not.have.been.calledOnce - - it 'should return when there is no eventParams', -> - click_event = document.createEvent('HTMLEvents') - click_event.initEvent('click', true, false) - wbp.clickHandler(click_event) - - wbp_click_spy.should.have.been.calledOnce - ga_send_spy.should.not.have.been.calledOnce - km_send_spy.should.not.have.been.calledOnce - ga_spy.should.not.have.been.calledOnce - kmq_spy.should.not.have.been.calledOnce - - it 'should not call GA when useGoogleAnalytics is false', -> - wbp.settings.useGoogleAnalytics = false - wbp.trackUserActions('button', 'Buttons') - - # Trigger Click - click_event = document.createEvent('HTMLEvents') - click_event.initEvent('click', true, false) - button.dispatchEvent(click_event) - - wbp_click_spy.should.have.been.calledOnce - ga_send_spy.should.not.have.been.calledOnce - km_send_spy.should.have.been.calledOnce - ga_spy.should.not.have.been.calledOnce - kmq_spy.should.have.been.calledOnce - - it 'should not call KM when useGoogleAnalytics is false', -> - wbp.settings.useKissMetrics = false - wbp.trackUserActions('button', 'Buttons') - - # Trigger Click - click_event = document.createEvent('HTMLEvents') - click_event.initEvent('click', true, false) - button.dispatchEvent(click_event) - - wbp_click_spy.should.have.been.calledOnce - ga_send_spy.should.have.been.calledOnce - km_send_spy.should.not.have.been.calledOnce - kmq_spy.should.not.have.been.calledOnce - - describe '#trackEvent', -> - track_event_ga_spy = null - track_event_km_spy = null - - beforeEach -> - track_event_ga_spy = sinon.spy(wbp, 'trackEventGA') - track_event_km_spy = sinon.spy(wbp, 'trackEventKM') - - it 'should call trackEventGA when GA is enabled', -> - track_event_ga_spy.callCount.should.equal 0 - wbp.trackEvent 'a', 'b', 'c', 'd' - track_event_ga_spy.should.have.been.calledOnce - - it 'should not call trackEventGA when GA is disabled', -> - wbp = new WildberryPrincess(useGoogleAnalytics: false) - track_event_ga_spy.callCount.should.equal 0 - wbp.trackEvent 'a', 'b', 'c', 'd' - track_event_ga_spy.callCount.should.equal 0 - - it 'should call trackEventKM when KM is enabled', -> - track_event_km_spy.callCount.should.equal 0 - wbp.trackEvent 'a', 'b', 'c', 'd' - track_event_km_spy.should.have.been.calledOnce - - it 'should call trackEventKM with the correct params', -> - track_event_km_spy.callCount.should.equal 0 - wbp.trackEvent 'a', 'b', 'c', 'd' - track_event_km_spy.should.have.been.calledWith 'a: c (b)', { action: "b", category: "a", label: "c", value: "d" } - - it 'should not call trackEventKM when KM is disabled', -> - wbp = new WildberryPrincess(useKissMetrics: false) - track_event_km_spy.callCount.should.equal 0 - wbp.trackEvent 'a', 'b', 'c', 'd' - track_event_km_spy.callCount.should.equal 0 - - it 'should exclude label and value when not set', -> - track_event_km_spy.callCount.should.equal 0 - wbp.trackEvent 'a', 'b' - track_event_km_spy.should.have.been.calledWith 'a: undefined (b)', { action: "b", category: "a" } - - describe '#trackEventGA', -> - wbp_spy = null - - beforeEach -> - wbp_spy = sinon.spy(wbp, 'sendPayloadGA') - - it 'should track the event', -> - wbp.trackEventGA 'a', 'b', 'c', 'd' - - payload = - eventCategory: 'a' - eventAction: 'b' - eventLabel: 'c' - eventValue: 'd' - hitType: 'event' - - wbp_spy.should.have.been.calledOnce - wbp_spy.should.have.been.calledWith payload - - ga_spy.should.have.been.calledOnce - ga_spy.should.have.been.calledWith 'send', payload - - it 'should track the event without a label', -> - wbp.trackEventGA 'a', 'b', null, 'd' - - payload = - eventCategory: 'a' - eventAction: 'b' - eventValue: 'd' - hitType: 'event' - - wbp_spy.should.have.been.calledOnce - wbp_spy.should.have.been.calledWith payload - - ga_spy.should.have.been.calledOnce - ga_spy.should.have.been.calledWith 'send', payload - - it 'should track the event without a value', -> - wbp.trackEventGA 'a', 'b', 'c' - - payload = - eventCategory: 'a' - eventAction: 'b' - eventLabel: 'c' - hitType: 'event' - - wbp_spy.should.have.been.calledOnce - wbp_spy.should.have.been.calledWith payload - - ga_spy.should.have.been.calledOnce - ga_spy.should.have.been.calledWith 'send', payload - - describe '#trackEventKM', -> - wbp_spy = null - - beforeEach -> - wbp_spy = sinon.spy(wbp, 'sendPayloadKM') - - it 'should track the event using sendPayloadKM', -> - wbp.trackEventKM '!label', { '!key': '!value' } - - wbp_spy.should.have.been.calledOnce - wbp_spy.should.have.been.calledWith 'record', '!label', { '!key': '!value' } - - it 'should send the event to KissMetrics', -> - wbp.trackEventKM '!label', { '!key': '!value' } - - payload = {} - - kmq_spy.should.have.been.calledOnce - kmq_spy.should.have.been.calledWith ['record', '!label', { '!key': '!value' }] - - describe '#trackPageView', -> - wbp_spy = null - - beforeEach -> - wbp_spy = sinon.spy(wbp, 'sendPayloadGA') - - it 'should track the page view', -> - wbp.trackPageView 'a', 'b' - - payload = - page: 'a' - title: 'b' - hitType: 'pageview' - - wbp_spy.should.have.been.calledOnce - wbp_spy.should.have.been.calledWith payload - - ga_spy.should.have.been.calledOnce - ga_spy.should.have.been.calledWith 'send', payload - - it 'should track the page view without a page provided', -> - wbp.trackPageView null, 'b' - - payload = - page: window.location.pathname - title: 'b' - hitType: 'pageview' - - wbp_spy.should.have.been.calledOnce - wbp_spy.should.have.been.calledWith payload - - ga_spy.should.have.been.calledOnce - ga_spy.should.have.been.calledWith 'send', payload - - it 'should track the page view without a title', -> - wbp.trackPageView 'a', null - - payload = - page: 'a' - title: 'Mocha' - hitType: 'pageview' - - wbp_spy.should.have.been.calledOnce - wbp_spy.should.have.been.calledWith payload - - ga_spy.should.have.been.calledOnce - ga_spy.should.have.been.calledWith 'send', payload - - describe '#trackEcommerce', -> - beforeEach -> - transaction_id = "#{Date.now()}" - transaction = - id: transaction_id - affiliation: "Candy Kingdom" - revenue: 123 - shipping: '0' - tax: '0' - - item = - id: transaction_id - name: 'b' - category: 'a' - price: 123 - quantity: 1 - - it 'should send the payload when there is GA', -> - ga_spy.callCount.should.equal 0 - - wbp.trackEcommerce('clear') - ga_spy.should.have.been.calledWith 'ecommerce:clear' - - wbp.trackEcommerce('addTransaction', transaction) - ga_spy.should.have.been.calledWith 'ecommerce:addTransaction', transaction - - wbp.trackEcommerce('addItem', item) - ga_spy.should.have.been.calledWith 'ecommerce:addItem', item - - wbp.trackEcommerce('send') - ga_spy.should.have.been.calledWith 'ecommerce:send' - - it 'should not send the payload when there is no GA', -> - window.ga = null - - ga_spy.callCount.should.equal 0 - - wbp.trackEcommerce('clear') - ga_spy.should.not.have.been.calledOnce - - wbp.trackEcommerce('addTransaction', transaction) - ga_spy.should.not.have.been.calledOnce - - wbp.trackEcommerce('addItem', item) - ga_spy.should.not.have.been.calledOnce - - wbp.trackEcommerce('send') - ga_spy.should.not.have.been.calledOnce - - describe '#set', -> - setga_spy = null - setkm_spy = null - - beforeEach -> - setga_spy = sinon.spy(wbp, 'setGA') - setkm_spy = sinon.spy(wbp, 'setKM') - - key = 'my-key' - value = 'my-value' - - it 'should call setGA when GA is enabled', -> - setga_spy.callCount.should.equal 0 - wbp.set key, value - setga_spy.should.have.been.calledOnce - - it 'should not call setGA when GA is disabled', -> - wbp = new WildberryPrincess(useGoogleAnalytics: false) - setga_spy.callCount.should.equal 0 - wbp.set key, value - setga_spy.callCount.should.equal 0 - - it 'should call setKM when KM is enabled', -> - setkm_spy.callCount.should.equal 0 - wbp.set key, value - setkm_spy.should.have.been.calledOnce - - it 'should not call setKM when KM is disabled', -> - wbp = new WildberryPrincess(useKissMetrics: false) - setkm_spy.callCount.should.equal 0 - wbp.set key, value - setkm_spy.callCount.should.equal 0 - - describe '#setGA', -> - beforeEach -> - key = 'my-key' - value = 'my-value' - - it 'should set the key to the value when there is GA', -> - ga_spy.callCount.should.equal 0 - wbp.setGA key, value - ga_spy.should.have.been.calledOnce - ga_spy.should.have.been.calledWith 'set', key, value - - it 'should not set the key to the value when there is no GA', -> - window.ga = null - ga_spy.callCount.should.equal 0 - wbp.setGA key, value - ga_spy.should.not.have.been.calledOnce - - describe '#setKM', -> - beforeEach -> - key = 'my-key' - value = 'my-value' - - it 'should set the key to the value when there is KM', -> - kmq_spy.callCount.should.equal 0 - wbp.setKM key, value - kmq_spy.should.have.been.calledOnce - output = {} - output[key] = value - kmq_spy.should.have.been.calledWith ['set', output] - - it 'should not set the key to the value when there is no MK', -> - window._kmq = null - kmq_spy.callCount.should.equal 0 - wbp.setKM key, value - kmq_spy.should.not.have.been.calledOnce - - describe '#identify', -> - setga_spy = null - - beforeEach -> - setga_spy = sinon.spy(wbp, 'setGA') - - it 'should not call setGA when GA is enabled without a user_ID', -> - setga_spy.callCount.should.equal 0 - wbp.identify() - setga_spy.callCount.should.equal 0 - - it 'should call setGA when GA is enabled with an user_id', -> - setga_spy.callCount.should.equal 0 - wbp.identify('1234') - setga_spy.should.have.been.calledOnce - setga_spy.should.have.been.calledWith 'userId', '1234' - - it 'should not call setGA when GA is disabled', -> - wbp = new WildberryPrincess(useGoogleAnalytics: false) - setga_spy.callCount.should.equal 0 - wbp.identify key, value - setga_spy.callCount.should.equal 0 - - it 'should call setKM when KM is enabled', -> - kmq_spy.callCount.should.equal 0 - wbp.identify() - kmq_spy.should.have.been.calledOnce - kmq_spy.should.have.been.calledWith ['identify', 'anonymous'] - - it 'should call setKM when KM is enabled with an user_id', -> - kmq_spy.callCount.should.equal 0 - wbp.identify('1234') - kmq_spy.should.have.been.calledOnce - kmq_spy.should.have.been.calledWith ['identify', '1234'] - - it 'should not call setKM when KM is disabled', -> - wbp = new WildberryPrincess(useKissMetrics: false) - kmq_spy.callCount.should.equal 0 - wbp.identify key, value - kmq_spy.callCount.should.equal 0 - - describe '#clearIdentity', -> - it 'should call sendPayloadKM when KM is enabled', -> - kmq_spy.callCount.should.equal 0 - wbp.clearIdentity() - kmq_spy.should.have.been.calledOnce - kmq_spy.should.have.been.calledWith ['clearIdentity'] - - it 'should not call sendPayloadKM when KM is disabled', -> - wbp = new WildberryPrincess(useKissMetrics: false) - kmq_spy.callCount.should.equal 0 - wbp.clearIdentity key, value - kmq_spy.callCount.should.equal 0 - - describe '#sendPayloadGA', -> - beforeEach -> - payload = - hitType: 'event' - eventCategory: 'my-category' - eventAction: 'my-action' - eventLabel: 'my-label' - eventValue: 'my-value' - - it 'should send the payload when there is GA', -> - ga_spy.callCount.should.equal 0 - wbp.sendPayloadGA payload - ga_spy.should.have.been.calledOnce - ga_spy.should.have.been.calledWith 'send', payload - - it 'should not send the payload when there is no GA', -> - window.ga = null - ga_spy.callCount.should.equal 0 - wbp.sendPayloadGA payload - ga_spy.should.not.have.been.calledOnce - - describe '#sendPayloadKM', -> - it 'should send the full payload when there is KM', -> - payload = ['record', 'event', { 'event-data': '1' }] - - kmq_spy.callCount.should.equal 0 - wbp.sendPayloadKM('record', 'event', { 'event-data': '1' }) - kmq_spy.should.have.been.calledOnce - kmq_spy.should.have.been.calledWith payload - - it 'should send the partial payload when there is KM', -> - payload = ['record', 'event'] - - kmq_spy.callCount.should.equal 0 - wbp.sendPayloadKM('record', 'event') - kmq_spy.should.have.been.calledOnce - kmq_spy.should.have.been.calledWith payload - - it 'should send the action-only payload when there is KM', -> - payload = ['record'] - - kmq_spy.callCount.should.equal 0 - wbp.sendPayloadKM('record') - kmq_spy.should.have.been.calledOnce - kmq_spy.should.have.been.calledWith payload - - it 'should not send the payload when there is no KM', -> - payload = ['record'] - - window._kmq = null - kmq_spy.callCount.should.equal 0 - wbp.sendPayloadKM payload - kmq_spy.should.not.have.been.calledOnce - - describe '#merge', -> - it 'should merge objects', -> - defaults = - useGoogleAnalytics: true - useKissMetrics: true - - options = - useGoogleAnalytics: false - useKissMetrics: false - useOther: true - - output = wbp.merge(defaults, options) - output.should.deep.equal options diff --git a/test/wildberry_princess_spec.js b/test/wildberry_princess_spec.js deleted file mode 100644 index 2f9d9c6..0000000 --- a/test/wildberry_princess_spec.js +++ /dev/null @@ -1,672 +0,0 @@ -// Generated by CoffeeScript 1.9.3 -(function() { - var WildberryPrincess, chai, sinon, sinonChai; - - if (typeof require !== "undefined" && require !== null) { - sinon = require('sinon'); - sinonChai = require('sinon-chai'); - chai = require('chai'); - global.should = chai.should(); - global.expect = chai.expect; - chai.should(); - chai.use(sinonChai); - WildberryPrincess = require('../build/wildberry_princess').WildberryPrincess; - } else { - WildberryPrincess = window.WildberryPrincess; - sinon = window.sinon; - } - - describe('WildberryPrincess', function() { - var ga_spy, item, jQuery, key, kmq_spy, payload, transaction, transaction_id, value, wbp; - jQuery = jQuery || null; - wbp = ga_spy = kmq_spy = null; - transaction_id = transaction = item = key = value = payload = null; - beforeEach(function() { - window.ga = function() {}; - window._kmq = {}; - window._kmq.push = function(a) {}; - ga_spy = sinon.spy(window, 'ga'); - kmq_spy = sinon.spy(window._kmq, 'push'); - return wbp = new WildberryPrincess(); - }); - it('should contruct without issue', function() { - return wbp.should.be.an["instanceof"](WildberryPrincess); - }); - it('should have known functions', function() { - wbp.should.itself.to.respondTo('getLabel'); - wbp.should.itself.to.respondTo('trackUserActions'); - wbp.should.itself.to.respondTo('clickHandler'); - wbp.should.itself.to.respondTo('trackEvent'); - wbp.should.itself.to.respondTo('trackEventGA'); - wbp.should.itself.to.respondTo('trackEventKM'); - wbp.should.itself.to.respondTo('trackPageView'); - wbp.should.itself.to.respondTo('trackEcommerce'); - wbp.should.itself.to.respondTo('set'); - wbp.should.itself.to.respondTo('setGA'); - wbp.should.itself.to.respondTo('setKM'); - wbp.should.itself.to.respondTo('identify'); - wbp.should.itself.to.respondTo('clearIdentity'); - wbp.should.itself.to.respondTo('sendPayloadGA'); - wbp.should.itself.to.respondTo('sendPayloadKM'); - return wbp.should.itself.to.respondTo('merge'); - }); - it('should have default setting', function() { - wbp.settings.should.have.any.keys('useGoogleAnalytics', 'useKissMetrics'); - wbp.settings.useGoogleAnalytics.should.be["true"]; - return wbp.settings.useKissMetrics.should.be["true"]; - }); - it('should set the settings based on passed in configuration', function() { - wbp = new WildberryPrincess({ - useGoogleAnalytics: false - }); - wbp.settings.useGoogleAnalytics.should.be["false"]; - wbp.settings.useKissMetrics.should.be["true"]; - wbp = new WildberryPrincess({ - useKissMetrics: false - }); - wbp.settings.useGoogleAnalytics.should.be["true"]; - wbp.settings.useKissMetrics.should.be["false"]; - wbp = new WildberryPrincess({ - useGoogleAnalytics: false, - useKissMetrics: false - }); - wbp.settings.useGoogleAnalytics.should.be["false"]; - return wbp.settings.useKissMetrics.should.be["false"]; - }); - describe('#trackUserActions', function() { - var wbp_spy; - wbp_spy = null; - beforeEach(function() { - var button; - wbp_spy = sinon.spy(wbp, 'trackUserActions'); - button = document.createElement('button'); - button.textConent = 'First Button'; - button.setAttribute('data-event-label', 'First Button'); - return document.body.appendChild(button); - }); - it('should add data and click handlers to the elements', function() { - var event_data; - wbp.trackUserActions('button', 'Buttons'); - wbp_spy.should.have.been.calledOnce; - event_data = document.querySelector('button').data; - event_data.should.have.property('eventParams'); - return event_data.eventParams.should.have.keys('category', 'action'); - }); - return it('should add label and value data when supplied', function() { - var event_data; - wbp.trackUserActions('button', 'Buttons', 'Click', 'Label', 1); - wbp_spy.should.have.been.calledOnce; - event_data = document.querySelector('button').data; - event_data.should.have.property('eventParams'); - return event_data.eventParams.should.have.keys('category', 'action', 'label', 'value'); - }); - }); - describe('#clickHandler', function() { - var button, ga_send_spy, km_send_spy, wbp_click_spy; - wbp_click_spy = ga_send_spy = km_send_spy = button = null; - beforeEach(function() { - wbp_click_spy = sinon.spy(wbp, 'clickHandler'); - ga_send_spy = sinon.spy(wbp, 'sendPayloadGA'); - km_send_spy = sinon.spy(wbp, 'sendPayloadKM'); - button = document.createElement('button'); - button.innerText = 'First Button'; - button.setAttribute('data-event-label', 'First Button'); - return document.body.appendChild(button); - }); - afterEach(function() { - return button.parentNode.removeChild(button); - }); - it('should track clicks on elements', function() { - var click_event; - wbp.trackUserActions('button', 'Buttons'); - click_event = document.createEvent('HTMLEvents'); - click_event.initEvent('click', true, false); - button.dispatchEvent(click_event); - wbp_click_spy.should.have.been.calledOnce; - ga_send_spy.should.have.been.calledOnce; - km_send_spy.should.have.been.calledOnce; - ga_spy.should.have.been.calledOnce; - payload = { - eventCategory: 'Buttons', - eventAction: 'Click', - eventLabel: 'First Button', - hitType: 'event' - }; - ga_spy.should.have.been.calledWith('send', payload); - payload = [ - "record", "Buttons: First Button (Click)", { - action: "Click", - category: "Buttons", - label: "First Button" - } - ]; - return kmq_spy.should.have.been.calledWith(payload); - }); - it('should not set a label unless it is provided', function() { - var click_event; - button.removeAttribute('data-event-label'); - wbp.trackUserActions('button', 'Buttons'); - click_event = document.createEvent('HTMLEvents'); - click_event.initEvent('click', true, false); - button.dispatchEvent(click_event); - wbp_click_spy.should.have.been.calledOnce; - ga_send_spy.should.have.been.calledOnce; - km_send_spy.should.have.been.calledOnce; - ga_spy.should.have.been.calledOnce; - payload = { - eventCategory: 'Buttons', - eventAction: 'Click', - hitType: 'event' - }; - ga_spy.should.have.been.calledWith('send', payload); - payload = [ - "record", "Buttons: null (Click)", { - action: "Click", - category: "Buttons" - } - ]; - return kmq_spy.should.have.been.calledWith(payload); - }); - it('should track clicks on elements with optional value', function() { - var click_event; - wbp.trackUserActions('button', 'Buttons', 'Click', null, 1); - click_event = document.createEvent('HTMLEvents'); - click_event.initEvent('click', true, false); - button.dispatchEvent(click_event); - wbp_click_spy.should.have.been.calledOnce; - ga_send_spy.should.have.been.calledOnce; - km_send_spy.should.have.been.calledOnce; - ga_spy.should.have.been.calledOnce; - payload = { - eventCategory: 'Buttons', - eventAction: 'Click', - eventLabel: 'First Button', - eventValue: 1, - hitType: 'event' - }; - ga_spy.should.have.been.calledWith('send', payload); - kmq_spy.should.have.been.calledOnce; - payload = [ - "record", "Buttons: First Button (Click)", { - action: "Click", - category: "Buttons", - label: "First Button", - value: 1 - } - ]; - return kmq_spy.should.have.been.calledWith(payload); - }); - it('should return when there is no event', function() { - wbp.clickHandler(); - wbp_click_spy.should.have.been.calledOnce; - ga_send_spy.should.not.have.been.calledOnce; - km_send_spy.should.not.have.been.calledOnce; - ga_spy.should.not.have.been.calledOnce; - return kmq_spy.should.not.have.been.calledOnce; - }); - it('should return when there is no eventParams', function() { - var click_event; - click_event = document.createEvent('HTMLEvents'); - click_event.initEvent('click', true, false); - wbp.clickHandler(click_event); - wbp_click_spy.should.have.been.calledOnce; - ga_send_spy.should.not.have.been.calledOnce; - km_send_spy.should.not.have.been.calledOnce; - ga_spy.should.not.have.been.calledOnce; - return kmq_spy.should.not.have.been.calledOnce; - }); - it('should not call GA when useGoogleAnalytics is false', function() { - var click_event; - wbp.settings.useGoogleAnalytics = false; - wbp.trackUserActions('button', 'Buttons'); - click_event = document.createEvent('HTMLEvents'); - click_event.initEvent('click', true, false); - button.dispatchEvent(click_event); - wbp_click_spy.should.have.been.calledOnce; - ga_send_spy.should.not.have.been.calledOnce; - km_send_spy.should.have.been.calledOnce; - ga_spy.should.not.have.been.calledOnce; - return kmq_spy.should.have.been.calledOnce; - }); - return it('should not call KM when useGoogleAnalytics is false', function() { - var click_event; - wbp.settings.useKissMetrics = false; - wbp.trackUserActions('button', 'Buttons'); - click_event = document.createEvent('HTMLEvents'); - click_event.initEvent('click', true, false); - button.dispatchEvent(click_event); - wbp_click_spy.should.have.been.calledOnce; - ga_send_spy.should.have.been.calledOnce; - km_send_spy.should.not.have.been.calledOnce; - return kmq_spy.should.not.have.been.calledOnce; - }); - }); - describe('#trackEvent', function() { - var track_event_ga_spy, track_event_km_spy; - track_event_ga_spy = null; - track_event_km_spy = null; - beforeEach(function() { - track_event_ga_spy = sinon.spy(wbp, 'trackEventGA'); - return track_event_km_spy = sinon.spy(wbp, 'trackEventKM'); - }); - it('should call trackEventGA when GA is enabled', function() { - track_event_ga_spy.callCount.should.equal(0); - wbp.trackEvent('a', 'b', 'c', 'd'); - return track_event_ga_spy.should.have.been.calledOnce; - }); - it('should not call trackEventGA when GA is disabled', function() { - wbp = new WildberryPrincess({ - useGoogleAnalytics: false - }); - track_event_ga_spy.callCount.should.equal(0); - wbp.trackEvent('a', 'b', 'c', 'd'); - return track_event_ga_spy.callCount.should.equal(0); - }); - it('should call trackEventKM when KM is enabled', function() { - track_event_km_spy.callCount.should.equal(0); - wbp.trackEvent('a', 'b', 'c', 'd'); - return track_event_km_spy.should.have.been.calledOnce; - }); - it('should call trackEventKM with the correct params', function() { - track_event_km_spy.callCount.should.equal(0); - wbp.trackEvent('a', 'b', 'c', 'd'); - return track_event_km_spy.should.have.been.calledWith('a: c (b)', { - action: "b", - category: "a", - label: "c", - value: "d" - }); - }); - it('should not call trackEventKM when KM is disabled', function() { - wbp = new WildberryPrincess({ - useKissMetrics: false - }); - track_event_km_spy.callCount.should.equal(0); - wbp.trackEvent('a', 'b', 'c', 'd'); - return track_event_km_spy.callCount.should.equal(0); - }); - return it('should exclude label and value when not set', function() { - track_event_km_spy.callCount.should.equal(0); - wbp.trackEvent('a', 'b'); - return track_event_km_spy.should.have.been.calledWith('a: undefined (b)', { - action: "b", - category: "a" - }); - }); - }); - describe('#trackEventGA', function() { - var wbp_spy; - wbp_spy = null; - beforeEach(function() { - return wbp_spy = sinon.spy(wbp, 'sendPayloadGA'); - }); - it('should track the event', function() { - wbp.trackEventGA('a', 'b', 'c', 'd'); - payload = { - eventCategory: 'a', - eventAction: 'b', - eventLabel: 'c', - eventValue: 'd', - hitType: 'event' - }; - wbp_spy.should.have.been.calledOnce; - wbp_spy.should.have.been.calledWith(payload); - ga_spy.should.have.been.calledOnce; - return ga_spy.should.have.been.calledWith('send', payload); - }); - it('should track the event without a label', function() { - wbp.trackEventGA('a', 'b', null, 'd'); - payload = { - eventCategory: 'a', - eventAction: 'b', - eventValue: 'd', - hitType: 'event' - }; - wbp_spy.should.have.been.calledOnce; - wbp_spy.should.have.been.calledWith(payload); - ga_spy.should.have.been.calledOnce; - return ga_spy.should.have.been.calledWith('send', payload); - }); - return it('should track the event without a value', function() { - wbp.trackEventGA('a', 'b', 'c'); - payload = { - eventCategory: 'a', - eventAction: 'b', - eventLabel: 'c', - hitType: 'event' - }; - wbp_spy.should.have.been.calledOnce; - wbp_spy.should.have.been.calledWith(payload); - ga_spy.should.have.been.calledOnce; - return ga_spy.should.have.been.calledWith('send', payload); - }); - }); - describe('#trackEventKM', function() { - var wbp_spy; - wbp_spy = null; - beforeEach(function() { - return wbp_spy = sinon.spy(wbp, 'sendPayloadKM'); - }); - it('should track the event using sendPayloadKM', function() { - wbp.trackEventKM('!label', { - '!key': '!value' - }); - wbp_spy.should.have.been.calledOnce; - return wbp_spy.should.have.been.calledWith('record', '!label', { - '!key': '!value' - }); - }); - return it('should send the event to KissMetrics', function() { - wbp.trackEventKM('!label', { - '!key': '!value' - }); - payload = {}; - kmq_spy.should.have.been.calledOnce; - return kmq_spy.should.have.been.calledWith([ - 'record', '!label', { - '!key': '!value' - } - ]); - }); - }); - describe('#trackPageView', function() { - var wbp_spy; - wbp_spy = null; - beforeEach(function() { - return wbp_spy = sinon.spy(wbp, 'sendPayloadGA'); - }); - it('should track the page view', function() { - wbp.trackPageView('a', 'b'); - payload = { - page: 'a', - title: 'b', - hitType: 'pageview' - }; - wbp_spy.should.have.been.calledOnce; - wbp_spy.should.have.been.calledWith(payload); - ga_spy.should.have.been.calledOnce; - return ga_spy.should.have.been.calledWith('send', payload); - }); - it('should track the page view without a page provided', function() { - wbp.trackPageView(null, 'b'); - payload = { - page: window.location.pathname, - title: 'b', - hitType: 'pageview' - }; - wbp_spy.should.have.been.calledOnce; - wbp_spy.should.have.been.calledWith(payload); - ga_spy.should.have.been.calledOnce; - return ga_spy.should.have.been.calledWith('send', payload); - }); - return it('should track the page view without a title', function() { - wbp.trackPageView('a', null); - payload = { - page: 'a', - title: 'Mocha', - hitType: 'pageview' - }; - wbp_spy.should.have.been.calledOnce; - wbp_spy.should.have.been.calledWith(payload); - ga_spy.should.have.been.calledOnce; - return ga_spy.should.have.been.calledWith('send', payload); - }); - }); - describe('#trackEcommerce', function() { - beforeEach(function() { - transaction_id = "" + (Date.now()); - transaction = { - id: transaction_id, - affiliation: "Candy Kingdom", - revenue: 123, - shipping: '0', - tax: '0' - }; - return item = { - id: transaction_id, - name: 'b', - category: 'a', - price: 123, - quantity: 1 - }; - }); - it('should send the payload when there is GA', function() { - ga_spy.callCount.should.equal(0); - wbp.trackEcommerce('clear'); - ga_spy.should.have.been.calledWith('ecommerce:clear'); - wbp.trackEcommerce('addTransaction', transaction); - ga_spy.should.have.been.calledWith('ecommerce:addTransaction', transaction); - wbp.trackEcommerce('addItem', item); - ga_spy.should.have.been.calledWith('ecommerce:addItem', item); - wbp.trackEcommerce('send'); - return ga_spy.should.have.been.calledWith('ecommerce:send'); - }); - return it('should not send the payload when there is no GA', function() { - window.ga = null; - ga_spy.callCount.should.equal(0); - wbp.trackEcommerce('clear'); - ga_spy.should.not.have.been.calledOnce; - wbp.trackEcommerce('addTransaction', transaction); - ga_spy.should.not.have.been.calledOnce; - wbp.trackEcommerce('addItem', item); - ga_spy.should.not.have.been.calledOnce; - wbp.trackEcommerce('send'); - return ga_spy.should.not.have.been.calledOnce; - }); - }); - describe('#set', function() { - var setga_spy, setkm_spy; - setga_spy = null; - setkm_spy = null; - beforeEach(function() { - setga_spy = sinon.spy(wbp, 'setGA'); - setkm_spy = sinon.spy(wbp, 'setKM'); - key = 'my-key'; - return value = 'my-value'; - }); - it('should call setGA when GA is enabled', function() { - setga_spy.callCount.should.equal(0); - wbp.set(key, value); - return setga_spy.should.have.been.calledOnce; - }); - it('should not call setGA when GA is disabled', function() { - wbp = new WildberryPrincess({ - useGoogleAnalytics: false - }); - setga_spy.callCount.should.equal(0); - wbp.set(key, value); - return setga_spy.callCount.should.equal(0); - }); - it('should call setKM when KM is enabled', function() { - setkm_spy.callCount.should.equal(0); - wbp.set(key, value); - return setkm_spy.should.have.been.calledOnce; - }); - return it('should not call setKM when KM is disabled', function() { - wbp = new WildberryPrincess({ - useKissMetrics: false - }); - setkm_spy.callCount.should.equal(0); - wbp.set(key, value); - return setkm_spy.callCount.should.equal(0); - }); - }); - describe('#setGA', function() { - beforeEach(function() { - key = 'my-key'; - return value = 'my-value'; - }); - it('should set the key to the value when there is GA', function() { - ga_spy.callCount.should.equal(0); - wbp.setGA(key, value); - ga_spy.should.have.been.calledOnce; - return ga_spy.should.have.been.calledWith('set', key, value); - }); - return it('should not set the key to the value when there is no GA', function() { - window.ga = null; - ga_spy.callCount.should.equal(0); - wbp.setGA(key, value); - return ga_spy.should.not.have.been.calledOnce; - }); - }); - describe('#setKM', function() { - beforeEach(function() { - key = 'my-key'; - return value = 'my-value'; - }); - it('should set the key to the value when there is KM', function() { - var output; - kmq_spy.callCount.should.equal(0); - wbp.setKM(key, value); - kmq_spy.should.have.been.calledOnce; - output = {}; - output[key] = value; - return kmq_spy.should.have.been.calledWith(['set', output]); - }); - return it('should not set the key to the value when there is no MK', function() { - window._kmq = null; - kmq_spy.callCount.should.equal(0); - wbp.setKM(key, value); - return kmq_spy.should.not.have.been.calledOnce; - }); - }); - describe('#identify', function() { - var setga_spy; - setga_spy = null; - beforeEach(function() { - return setga_spy = sinon.spy(wbp, 'setGA'); - }); - it('should not call setGA when GA is enabled without a user_ID', function() { - setga_spy.callCount.should.equal(0); - wbp.identify(); - return setga_spy.callCount.should.equal(0); - }); - it('should call setGA when GA is enabled with an user_id', function() { - setga_spy.callCount.should.equal(0); - wbp.identify('1234'); - setga_spy.should.have.been.calledOnce; - return setga_spy.should.have.been.calledWith('userId', '1234'); - }); - it('should not call setGA when GA is disabled', function() { - wbp = new WildberryPrincess({ - useGoogleAnalytics: false - }); - setga_spy.callCount.should.equal(0); - wbp.identify(key, value); - return setga_spy.callCount.should.equal(0); - }); - it('should call setKM when KM is enabled', function() { - kmq_spy.callCount.should.equal(0); - wbp.identify(); - kmq_spy.should.have.been.calledOnce; - return kmq_spy.should.have.been.calledWith(['identify', 'anonymous']); - }); - it('should call setKM when KM is enabled with an user_id', function() { - kmq_spy.callCount.should.equal(0); - wbp.identify('1234'); - kmq_spy.should.have.been.calledOnce; - return kmq_spy.should.have.been.calledWith(['identify', '1234']); - }); - return it('should not call setKM when KM is disabled', function() { - wbp = new WildberryPrincess({ - useKissMetrics: false - }); - kmq_spy.callCount.should.equal(0); - wbp.identify(key, value); - return kmq_spy.callCount.should.equal(0); - }); - }); - describe('#clearIdentity', function() { - it('should call sendPayloadKM when KM is enabled', function() { - kmq_spy.callCount.should.equal(0); - wbp.clearIdentity(); - kmq_spy.should.have.been.calledOnce; - return kmq_spy.should.have.been.calledWith(['clearIdentity']); - }); - return it('should not call sendPayloadKM when KM is disabled', function() { - wbp = new WildberryPrincess({ - useKissMetrics: false - }); - kmq_spy.callCount.should.equal(0); - wbp.clearIdentity(key, value); - return kmq_spy.callCount.should.equal(0); - }); - }); - describe('#sendPayloadGA', function() { - beforeEach(function() { - return payload = { - hitType: 'event', - eventCategory: 'my-category', - eventAction: 'my-action', - eventLabel: 'my-label', - eventValue: 'my-value' - }; - }); - it('should send the payload when there is GA', function() { - ga_spy.callCount.should.equal(0); - wbp.sendPayloadGA(payload); - ga_spy.should.have.been.calledOnce; - return ga_spy.should.have.been.calledWith('send', payload); - }); - return it('should not send the payload when there is no GA', function() { - window.ga = null; - ga_spy.callCount.should.equal(0); - wbp.sendPayloadGA(payload); - return ga_spy.should.not.have.been.calledOnce; - }); - }); - describe('#sendPayloadKM', function() { - it('should send the full payload when there is KM', function() { - payload = [ - 'record', 'event', { - 'event-data': '1' - } - ]; - kmq_spy.callCount.should.equal(0); - wbp.sendPayloadKM('record', 'event', { - 'event-data': '1' - }); - kmq_spy.should.have.been.calledOnce; - return kmq_spy.should.have.been.calledWith(payload); - }); - it('should send the partial payload when there is KM', function() { - payload = ['record', 'event']; - kmq_spy.callCount.should.equal(0); - wbp.sendPayloadKM('record', 'event'); - kmq_spy.should.have.been.calledOnce; - return kmq_spy.should.have.been.calledWith(payload); - }); - it('should send the action-only payload when there is KM', function() { - payload = ['record']; - kmq_spy.callCount.should.equal(0); - wbp.sendPayloadKM('record'); - kmq_spy.should.have.been.calledOnce; - return kmq_spy.should.have.been.calledWith(payload); - }); - return it('should not send the payload when there is no KM', function() { - payload = ['record']; - window._kmq = null; - kmq_spy.callCount.should.equal(0); - wbp.sendPayloadKM(payload); - return kmq_spy.should.not.have.been.calledOnce; - }); - }); - return describe('#merge', function() { - return it('should merge objects', function() { - var defaults, options, output; - defaults = { - useGoogleAnalytics: true, - useKissMetrics: true - }; - options = { - useGoogleAnalytics: false, - useKissMetrics: false, - useOther: true - }; - output = wbp.merge(defaults, options); - return output.should.deep.equal(options); - }); - }); - }); - -}).call(this); From b902bf78972c97cecf0d06d0b2a9a36112fe2ff0 Mon Sep 17 00:00:00 2001 From: Matthew Callis Date: Tue, 6 Dec 2016 10:44:00 -0800 Subject: [PATCH 2/2] Spruce up package.json --- package.json | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 195905a..a62619f 100644 --- a/package.json +++ b/package.json @@ -10,14 +10,33 @@ "email": "matthew.callis@gmail.com" } ], - "main": "dist/wildberry-princess.min.js", + "maintainers": [ + { + "name": "Matthew Callis", + "email": "matthew.callis@gmail.com", + "web": "https://eludevisibility.org" + } + ], + "main": "dist/wildberry-princess.js", "files": [ - "dist/wildberry-princess.min.js" + "dist/wildberry-princess.js" ], + "directories": { + "lib": "dist", + "src": "src", + "test": "test" + }, "repository": { "type": "git", "url": "https://github.com/MatthewCallis/wildberry-princess" }, + "repositories": [ + { + "type": "git", + "url": "https://github.com/MatthewCallis/wildberry-princess.git", + "path": "MatthewCallis/wildberry-princess" + } + ], "bugs": { "url": "https://github.com/MatthewCallis/wildberry-princess/issues" }, @@ -60,6 +79,12 @@ "preferGlobal": false, "private": false, "license": "MIT", + "licenses": [ + { + "type": "MIT", + "url": "https://raw.githubusercontent.com/MatthewCallis/wildberry-princess/master/LICENSE" + } + ], "jam": { "dependencies": {} },