From 2a1b42c226573ef2107b880a6a33c6be432dcfea Mon Sep 17 00:00:00 2001 From: Nikolay Feldman Date: Fri, 4 May 2018 19:37:46 -0700 Subject: [PATCH 1/4] improve code coverage Also testing out that codecov and travis ci run on PRs --- index.js | 5 ++++- test/unit/simple-tracker.js | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 9e45742..541b7a6 100644 --- a/index.js +++ b/index.js @@ -148,7 +148,9 @@ startTimer: function(metric) { var performance = window.performance + /* istanbul ignore else */ if (performance.now) { + /* istanbul ignore if */ if (timer[metric]) { console.warn("Timing metric '" + metric + "' already started") } @@ -164,6 +166,7 @@ if (performance.now) { var stopTime = performance.now() var startTime = timer[metric] + /* istanbul ignore else */ if (startTime !== undefined) { var diff = Math.round(stopTime - startTime) timer[metric] = undefined @@ -248,8 +251,8 @@ return tracker } - var isModule = typeof module !== 'undefined' && module.exports + /* istanbul ignore else */ if (typeof window !== 'undefined') { var tracker = simpleTracker(window, window.document) // sets window.tracker if (isModule) { diff --git a/test/unit/simple-tracker.js b/test/unit/simple-tracker.js index 9e59cf9..a582388 100644 --- a/test/unit/simple-tracker.js +++ b/test/unit/simple-tracker.js @@ -2,6 +2,7 @@ const assert = require('chai').assert const sinon = require('sinon') +const rewire = require('rewire') const simpleTracker = require('../../index.js') @@ -443,4 +444,31 @@ describe('simple-tracker', function() { done() }) + it('should auto initialize with window object if one exists', function(done) { + delete window.tracker // ensure no instance of tracker loaded + delete window.SimpleTracker + global.window = window + + assert.isUndefined(window.tracker) + assert.isUndefined(window.SimpleTracker) + + // window object is now in global, so should be picked up automatically + const rTracker = rewire('../../index.js') // rewire loads fresh instance of module + + assert.isDefined(window.SimpleTracker) + assert.instanceOf(window.tracker, window.SimpleTracker) + assert.instanceOf(rTracker, window.SimpleTracker) + + delete global.window // cleanup + + done() + }) + + it('dont do anything if data pushed is not an object or string', function(done) { + tracker.push(() => {}) + assert.isTrue(mockRequest.open.notCalled) + assert.isTrue(mockRequest.send.notCalled) + done() + }) + }) From a57391b5780424801a835971237640017f781cc7 Mon Sep 17 00:00:00 2001 From: Nikolay Feldman Date: Fri, 4 May 2018 19:57:33 -0700 Subject: [PATCH 2/4] log to console only in devMode --- dist/simple-tracker.min.js | 2 +- dist/simple-tracker.min.map | 2 +- index.js | 18 +++++------------- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/dist/simple-tracker.min.js b/dist/simple-tracker.min.js index 39b5127..18557b9 100644 --- a/dist/simple-tracker.min.js +++ b/dist/simple-tracker.min.js @@ -1,2 +1,2 @@ -!function(){"use strict";function e(e,t){function n(e){return e?(e^16*Math.random()>>e/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,n)}function o(t){var n=e.onerror;e.onerror=function(){t.apply(f,arguments),"function"==typeof n&&n.apply(e,arguments)}}function i(){return p||(p={url:e.location.href,userAgent:e.navigator.userAgent||null,platform:e.navigator.platform||null}),p}function r(){var e=t.cookie,n=e.indexOf(g);if(n>=0){var o=e.indexOf(";",n+1);return o=o<0?e.length:o,e.slice(n+v,o)}}function s(e){t.cookie=g+"="+e}function a(e){s(u=e||u||r()||n())}function c(t){if(d&&Object.keys(t).length>0)if(t.sessionId=u,m&&(t.context=i()),w)console.debug("SimpleTracker: POST "+d,t);else try{var n=new e.XMLHttpRequest;n.open("POST",d,!0),n.setRequestHeader("Content-Type","application/json"),n.send(JSON.stringify(t))}catch(n){e.console&&"function"==typeof e.console.log&&(console.log("Failed to send tracking request because of this exception:\n"+n),console.log("Failed tracking data:",t))}}function l(){}var d,u,f,p,g="trcksesh",v=g.length+1,h=!0,m=!0,w=!1,x={};l.prototype={onerror:function(e,t,n,o,i){var r={message:e,lineno:n,colno:o,stack:i?i.stack:"n/a"};this.logException(r)},logEvent:function(e){this.push({type:"event",event:e})},logException:function(e){this.push({level:"error",type:"exception",exception:e})},logMessage:function(e,t){var n={type:"message",message:e};t&&(n.level=t),this.push(n)},logMetric:function(e,t){this.push({type:"metric",metric:e,value:t})},startTimer:function(t){var n=e.performance;n.now?(x[t]&&console.warn("Timing metric '"+t+"' already started"),console.debug("timer started for:",t),x[t]=n.now()):console.warn("window.performance is not defined")},stopTimer:function(t){var n=e.performance;if(n.now){var o=n.now(),i=x[t];if(void 0!==i){var r=Math.round(o-i);x[t]=void 0,console.debug("timer stopped for:",t,"time="+r),this.logMetric(t,r)}else console.warn("Timing metric '"+t+"' wasn't started")}},push:function(e){var t=typeof e;if("object"===t||"string"===t){if("string"===t)e={text:e};else if(void 0!==e.devMode&&(w=!!e.devMode,delete e.devMode),void 0!==e.attachClientContext&&(m=!!e.attachClientContext,delete e.attachClientContext),e.sessionId&&(a(e.sessionId),delete e.sessionId),e.endpoint&&(u||a(),d=e.endpoint,delete e.endpoint),void 0!==e.sendCaughtExceptions){var n=!!e.sendCaughtExceptions;h=n,n&&o(this.onerror),delete e.sendCaughtExceptions}c(e)}}};var y=e.tracker;if(y&&y instanceof l)f=y;else if(y&&y.length){f=new l;var k=0,C=y.length;for(k=0;k>e/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,n)}function o(t){var n=e.onerror;e.onerror=function(){t.apply(f,arguments),"function"==typeof n&&n.apply(e,arguments)}}function i(){return p||(p={url:e.location.href,userAgent:e.navigator.userAgent||null,platform:e.navigator.platform||null}),p}function r(){var e=t.cookie,n=e.indexOf(v);if(n>=0){var o=e.indexOf(";",n+1);return o=o<0?e.length:o,e.slice(n+g,o)}}function s(e){t.cookie=v+"="+e}function a(e){s(d=e||d||r()||n())}function c(t){if(u&&Object.keys(t).length>0)if(t.sessionId=d,m&&(t.context=i()),w)console.debug("SimpleTracker: POST "+u,t);else try{var n=new e.XMLHttpRequest;n.open("POST",u,!0),n.setRequestHeader("Content-Type","application/json"),n.send(JSON.stringify(t))}catch(e){}}function l(){}var u,d,f,p,v="trcksesh",g=v.length+1,h=!0,m=!0,w=!1,x={};l.prototype={onerror:function(e,t,n,o,i){var r={message:e,lineno:n,colno:o,stack:i?i.stack:"n/a"};this.logException(r)},logEvent:function(e){this.push({type:"event",event:e})},logException:function(e){this.push({level:"error",type:"exception",exception:e})},logMessage:function(e,t){var n={type:"message",message:e};t&&(n.level=t),this.push(n)},logMetric:function(e,t){this.push({type:"metric",metric:e,value:t})},startTimer:function(t){var n=e.performance;n.now&&(x[t]&&w&&console.warn("Timing metric '"+t+"' already started"),w&&console.debug("timer started for:",t),x[t]=n.now())},stopTimer:function(t){var n=e.performance;if(n.now){var o=n.now(),i=x[t];if(void 0!==i){var r=Math.round(o-i);x[t]=void 0,w&&console.debug("timer stopped for:",t,"time="+r),this.logMetric(t,r)}else w&&console.warn("Timing metric '"+t+"' wasn't started")}},push:function(e){var t=typeof e;if("object"===t||"string"===t){if("string"===t)e={text:e};else if(void 0!==e.devMode&&(w=!!e.devMode,delete e.devMode),void 0!==e.attachClientContext&&(m=!!e.attachClientContext,delete e.attachClientContext),e.sessionId&&(a(e.sessionId),delete e.sessionId),e.endpoint&&(d||a(),u=e.endpoint,delete e.endpoint),void 0!==e.sendCaughtExceptions){var n=!!e.sendCaughtExceptions;h=n,n&&o(this.onerror),delete e.sendCaughtExceptions}c(e)}}};var y=e.tracker;if(y&&y instanceof l)f=y;else if(y&&y.length){f=new l;var k=0,C=y.length;for(k=0;k Date: Fri, 4 May 2018 21:01:00 -0700 Subject: [PATCH 3/4] remove unnecessary instanceof check --- dist/simple-tracker.min.js | 2 +- dist/simple-tracker.min.map | 2 +- index.js | 5 +---- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/dist/simple-tracker.min.js b/dist/simple-tracker.min.js index 18557b9..d8df601 100644 --- a/dist/simple-tracker.min.js +++ b/dist/simple-tracker.min.js @@ -1,2 +1,2 @@ -!function(){"use strict";function e(e,t){function n(e){return e?(e^16*Math.random()>>e/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,n)}function o(t){var n=e.onerror;e.onerror=function(){t.apply(f,arguments),"function"==typeof n&&n.apply(e,arguments)}}function i(){return p||(p={url:e.location.href,userAgent:e.navigator.userAgent||null,platform:e.navigator.platform||null}),p}function r(){var e=t.cookie,n=e.indexOf(v);if(n>=0){var o=e.indexOf(";",n+1);return o=o<0?e.length:o,e.slice(n+g,o)}}function s(e){t.cookie=v+"="+e}function a(e){s(d=e||d||r()||n())}function c(t){if(u&&Object.keys(t).length>0)if(t.sessionId=d,m&&(t.context=i()),w)console.debug("SimpleTracker: POST "+u,t);else try{var n=new e.XMLHttpRequest;n.open("POST",u,!0),n.setRequestHeader("Content-Type","application/json"),n.send(JSON.stringify(t))}catch(e){}}function l(){}var u,d,f,p,v="trcksesh",g=v.length+1,h=!0,m=!0,w=!1,x={};l.prototype={onerror:function(e,t,n,o,i){var r={message:e,lineno:n,colno:o,stack:i?i.stack:"n/a"};this.logException(r)},logEvent:function(e){this.push({type:"event",event:e})},logException:function(e){this.push({level:"error",type:"exception",exception:e})},logMessage:function(e,t){var n={type:"message",message:e};t&&(n.level=t),this.push(n)},logMetric:function(e,t){this.push({type:"metric",metric:e,value:t})},startTimer:function(t){var n=e.performance;n.now&&(x[t]&&w&&console.warn("Timing metric '"+t+"' already started"),w&&console.debug("timer started for:",t),x[t]=n.now())},stopTimer:function(t){var n=e.performance;if(n.now){var o=n.now(),i=x[t];if(void 0!==i){var r=Math.round(o-i);x[t]=void 0,w&&console.debug("timer stopped for:",t,"time="+r),this.logMetric(t,r)}else w&&console.warn("Timing metric '"+t+"' wasn't started")}},push:function(e){var t=typeof e;if("object"===t||"string"===t){if("string"===t)e={text:e};else if(void 0!==e.devMode&&(w=!!e.devMode,delete e.devMode),void 0!==e.attachClientContext&&(m=!!e.attachClientContext,delete e.attachClientContext),e.sessionId&&(a(e.sessionId),delete e.sessionId),e.endpoint&&(d||a(),u=e.endpoint,delete e.endpoint),void 0!==e.sendCaughtExceptions){var n=!!e.sendCaughtExceptions;h=n,n&&o(this.onerror),delete e.sendCaughtExceptions}c(e)}}};var y=e.tracker;if(y&&y instanceof l)f=y;else if(y&&y.length){f=new l;var k=0,C=y.length;for(k=0;k>e/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,n)}function o(t){var n=e.onerror;e.onerror=function(){t.apply(f,arguments),"function"==typeof n&&n.apply(e,arguments)}}function i(){return p||(p={url:e.location.href,userAgent:e.navigator.userAgent||null,platform:e.navigator.platform||null}),p}function r(){var e=t.cookie,n=e.indexOf(v);if(n>=0){var o=e.indexOf(";",n+1);return o=o<0?e.length:o,e.slice(n+g,o)}}function s(e){t.cookie=v+"="+e}function a(e){s(d=e||d||r()||n())}function c(t){if(u&&Object.keys(t).length>0)if(t.sessionId=d,m&&(t.context=i()),w)console.debug("SimpleTracker: POST "+u,t);else try{var n=new e.XMLHttpRequest;n.open("POST",u,!0),n.setRequestHeader("Content-Type","application/json"),n.send(JSON.stringify(t))}catch(e){}}function l(){}var u,d,f,p,v="trcksesh",g=v.length+1,h=!0,m=!0,w=!1,x={};l.prototype={onerror:function(e,t,n,o,i){var r={message:e,lineno:n,colno:o,stack:i?i.stack:"n/a"};this.logException(r)},logEvent:function(e){this.push({type:"event",event:e})},logException:function(e){this.push({level:"error",type:"exception",exception:e})},logMessage:function(e,t){var n={type:"message",message:e};t&&(n.level=t),this.push(n)},logMetric:function(e,t){this.push({type:"metric",metric:e,value:t})},startTimer:function(t){var n=e.performance;n.now&&(x[t]&&w&&console.warn("Timing metric '"+t+"' already started"),w&&console.debug("timer started for:",t),x[t]=n.now())},stopTimer:function(t){var n=e.performance;if(n.now){var o=n.now(),i=x[t];if(void 0!==i){var r=Math.round(o-i);x[t]=void 0,w&&console.debug("timer stopped for:",t,"time="+r),this.logMetric(t,r)}else w&&console.warn("Timing metric '"+t+"' wasn't started")}},push:function(e){var t=typeof e;if("object"===t||"string"===t){if("string"===t)e={text:e};else if(void 0!==e.devMode&&(w=!!e.devMode,delete e.devMode),void 0!==e.attachClientContext&&(m=!!e.attachClientContext,delete e.attachClientContext),e.sessionId&&(a(e.sessionId),delete e.sessionId),e.endpoint&&(d||a(),u=e.endpoint,delete e.endpoint),void 0!==e.sendCaughtExceptions){var n=!!e.sendCaughtExceptions;h=n,n&&o(this.onerror),delete e.sendCaughtExceptions}c(e)}}};var y=e.tracker;if(y&&y.length){f=new l;var k=0,C=y.length;for(k=0;k Date: Fri, 4 May 2018 21:04:52 -0700 Subject: [PATCH 4/4] only pass window object --- README.md | 12 ++++++------ dist/simple-tracker.min.js | 2 +- dist/simple-tracker.min.map | 2 +- index.js | 5 +++-- test/unit/simple-tracker.js | 13 +++++++------ 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 5726f26..99ad66f 100644 --- a/README.md +++ b/README.md @@ -96,11 +96,11 @@ All Configurations ----- ```javascript tracker.push({ - endpoint: '/ENDPOINT', // endpoint to send tracking data to - sendCaughtExceptions: true/false, // send exceptions caught by browser. DEFAULT: true - attachClientContext: true/false, // attach various client context, such as useragent, platform, and page url. DEFAULT: true - sessionId: 'SESSION_ID', // explicitly set a session id - devMode: true/false // toggle dev mode. If enabled, outgoing requests are blocked and logged for debugging instead. DEFAULT: false + endpoint: '/ENDPOINT', // Endpoint to send tracking data to + sendCaughtExceptions: true/false, // Send exceptions caught by browser. DEFAULT: true + attachClientContext: true/false, // Attach various client context, such as useragent, platform, and page url. DEFAULT: true + sessionId: 'SESSION_ID', // Explicitly set a session id + devMode: true/false // Toggle dev mode. If enabled, outgoing requests are blocked and logged for debugging instead. DEFAULT: false }); ``` @@ -203,7 +203,7 @@ tracker.push({ Bugs, feature requests, & contributing ----- -If you found a bug or want to request a feature, [create a new issue](https://github.com/codeniko/simple-tracker/issues). Contributions are more than welcome :) +If you found a bug or want to request a feature, [create a new issue](https://github.com/codeniko/simple-tracker/issues). Contributions via pull requests are more than welcome :) Running unit tests and code coverage ---------- diff --git a/dist/simple-tracker.min.js b/dist/simple-tracker.min.js index d8df601..d9b81d3 100644 --- a/dist/simple-tracker.min.js +++ b/dist/simple-tracker.min.js @@ -1,2 +1,2 @@ -!function(){"use strict";function e(e,t){function n(e){return e?(e^16*Math.random()>>e/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,n)}function o(t){var n=e.onerror;e.onerror=function(){t.apply(f,arguments),"function"==typeof n&&n.apply(e,arguments)}}function i(){return p||(p={url:e.location.href,userAgent:e.navigator.userAgent||null,platform:e.navigator.platform||null}),p}function r(){var e=t.cookie,n=e.indexOf(v);if(n>=0){var o=e.indexOf(";",n+1);return o=o<0?e.length:o,e.slice(n+g,o)}}function s(e){t.cookie=v+"="+e}function a(e){s(d=e||d||r()||n())}function c(t){if(u&&Object.keys(t).length>0)if(t.sessionId=d,m&&(t.context=i()),w)console.debug("SimpleTracker: POST "+u,t);else try{var n=new e.XMLHttpRequest;n.open("POST",u,!0),n.setRequestHeader("Content-Type","application/json"),n.send(JSON.stringify(t))}catch(e){}}function l(){}var u,d,f,p,v="trcksesh",g=v.length+1,h=!0,m=!0,w=!1,x={};l.prototype={onerror:function(e,t,n,o,i){var r={message:e,lineno:n,colno:o,stack:i?i.stack:"n/a"};this.logException(r)},logEvent:function(e){this.push({type:"event",event:e})},logException:function(e){this.push({level:"error",type:"exception",exception:e})},logMessage:function(e,t){var n={type:"message",message:e};t&&(n.level=t),this.push(n)},logMetric:function(e,t){this.push({type:"metric",metric:e,value:t})},startTimer:function(t){var n=e.performance;n.now&&(x[t]&&w&&console.warn("Timing metric '"+t+"' already started"),w&&console.debug("timer started for:",t),x[t]=n.now())},stopTimer:function(t){var n=e.performance;if(n.now){var o=n.now(),i=x[t];if(void 0!==i){var r=Math.round(o-i);x[t]=void 0,w&&console.debug("timer stopped for:",t,"time="+r),this.logMetric(t,r)}else w&&console.warn("Timing metric '"+t+"' wasn't started")}},push:function(e){var t=typeof e;if("object"===t||"string"===t){if("string"===t)e={text:e};else if(void 0!==e.devMode&&(w=!!e.devMode,delete e.devMode),void 0!==e.attachClientContext&&(m=!!e.attachClientContext,delete e.attachClientContext),e.sessionId&&(a(e.sessionId),delete e.sessionId),e.endpoint&&(d||a(),u=e.endpoint,delete e.endpoint),void 0!==e.sendCaughtExceptions){var n=!!e.sendCaughtExceptions;h=n,n&&o(this.onerror),delete e.sendCaughtExceptions}c(e)}}};var y=e.tracker;if(y&&y.length){f=new l;var k=0,C=y.length;for(k=0;k>e/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,t)}function n(t){var n=e.onerror;e.onerror=function(){t.apply(d,arguments),"function"==typeof n&&n.apply(e,arguments)}}function o(){return f||(f={url:e.location.href,userAgent:e.navigator.userAgent||null,platform:e.navigator.platform||null}),f}function r(){var e=g.cookie,t=e.indexOf(p);if(t>=0){var n=e.indexOf(";",t+1);return n=n<0?e.length:n,e.slice(t+v,n)}}function i(e){g.cookie=p+"="+e}function s(e){i(u=e||u||r()||t())}function a(t){if(l&&Object.keys(t).length>0)if(t.sessionId=u,m&&(t.context=o()),x)console.debug("SimpleTracker: POST "+l,t);else try{var n=new e.XMLHttpRequest;n.open("POST",l,!0),n.setRequestHeader("Content-Type","application/json"),n.send(JSON.stringify(t))}catch(e){}}function c(){}var l,u,d,f,p="trcksesh",v=p.length+1,g=e.document,h=!0,m=!0,x=!1,w={};c.prototype={onerror:function(e,t,n,o,r){var i={message:e,lineno:n,colno:o,stack:r?r.stack:"n/a"};this.logException(i)},logEvent:function(e){this.push({type:"event",event:e})},logException:function(e){this.push({level:"error",type:"exception",exception:e})},logMessage:function(e,t){var n={type:"message",message:e};t&&(n.level=t),this.push(n)},logMetric:function(e,t){this.push({type:"metric",metric:e,value:t})},startTimer:function(t){var n=e.performance;n.now&&(w[t]&&x&&console.warn("Timing metric '"+t+"' already started"),x&&console.debug("timer started for:",t),w[t]=n.now())},stopTimer:function(t){var n=e.performance;if(n.now){var o=n.now(),r=w[t];if(void 0!==r){var i=Math.round(o-r);w[t]=void 0,x&&console.debug("timer stopped for:",t,"time="+i),this.logMetric(t,i)}else x&&console.warn("Timing metric '"+t+"' wasn't started")}},push:function(e){var t=typeof e;if("object"===t||"string"===t){if("string"===t)e={text:e};else if(void 0!==e.devMode&&(x=!!e.devMode,delete e.devMode),void 0!==e.attachClientContext&&(m=!!e.attachClientContext,delete e.attachClientContext),e.sessionId&&(s(e.sessionId),delete e.sessionId),e.endpoint&&(u||s(),l=e.endpoint,delete e.endpoint),void 0!==e.sendCaughtExceptions){var o=!!e.sendCaughtExceptions;h=o,o&&n(this.onerror),delete e.sendCaughtExceptions}a(e)}}};var y=e.tracker;if(y&&y.length){d=new c;var k=0,C=y.length;for(k=0;k