mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-19 15:48:04 +01:00
Refactore analytics service and tests
This commit is contained in:
@@ -1,6 +1,3 @@
|
|||||||
/**
|
|
||||||
* Created by Sabe on 6/11/2015.
|
|
||||||
*/
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
describe('Analytics Service', function () {
|
describe('Analytics Service', function () {
|
||||||
@@ -20,13 +17,100 @@ describe('Analytics Service', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
context('error handling', function() {
|
context('functions', function() {
|
||||||
|
|
||||||
|
describe('register', function() {
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
sandbox.stub(amplitude, 'setUserId');
|
||||||
|
sandbox.stub(window, 'ga');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets up user with amplitude', function() {
|
||||||
|
analytics.register();
|
||||||
|
expect(amplitude.setUserId).to.have.been.calledOnce;
|
||||||
|
expect(amplitude.setUserId).to.have.been.calledWith(user._id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets up user with google analytics', function() {
|
||||||
|
analytics.register();
|
||||||
|
expect(ga).to.have.been.calledOnce;
|
||||||
|
expect(ga).to.have.been.calledWith('set', {userId: user._id});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('login', function() {
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
sandbox.stub(amplitude, 'setUserId');
|
||||||
|
sandbox.stub(window, 'ga');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets up tracking for amplitude', function() {
|
||||||
|
analytics.login();
|
||||||
|
|
||||||
|
expect(amplitude.setUserId).to.have.been.calledOnce;
|
||||||
|
expect(amplitude.setUserId).to.have.been.calledWith(user._id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets up tracking for google analytics', function() {
|
||||||
|
analytics.login();
|
||||||
|
|
||||||
|
expect(ga).to.have.been.calledOnce;
|
||||||
|
expect(ga).to.have.been.calledWith('set', {userId: user._id});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('track', function() {
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
sandbox.stub(amplitude, 'logEvent');
|
||||||
|
sandbox.stub(window, 'ga');
|
||||||
|
});
|
||||||
|
|
||||||
|
context('succeful tracking', function() {
|
||||||
|
|
||||||
|
it('tracks a simple user action with amplitude', function() {
|
||||||
|
var properties = {'hitType':'event','eventCategory':'behavior','eventAction':'cron'};
|
||||||
|
analytics.track(properties);
|
||||||
|
|
||||||
|
expect(amplitude.logEvent).to.have.been.calledOnce;
|
||||||
|
expect(amplitude.logEvent).to.have.been.calledWith('cron', properties);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tracks a simple user action with google analytics', function() {
|
||||||
|
var properties = {'hitType':'event','eventCategory':'behavior','eventAction':'cron'};
|
||||||
|
analytics.track(properties);
|
||||||
|
|
||||||
|
expect(ga).to.have.been.calledOnce;
|
||||||
|
expect(ga).to.have.been.calledWith('send', properties);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tracks a user action with additional properties in amplitude', function() {
|
||||||
|
var properties = {'hitType':'event','eventCategory':'behavior','eventAction':'cron','booleanProperty':true,'numericProperty':17,'stringProperty':'bagel'};
|
||||||
|
analytics.track(properties);
|
||||||
|
|
||||||
|
expect(amplitude.logEvent).to.have.been.calledOnce;
|
||||||
|
expect(amplitude.logEvent).to.have.been.calledWith('cron', properties);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tracks a user action with additional properties in google analytics', function() {
|
||||||
|
var properties = {'hitType':'event','eventCategory':'behavior','eventAction':'cron','booleanProperty':true,'numericProperty':17,'stringProperty':'bagel'};
|
||||||
|
analytics.track(properties);
|
||||||
|
|
||||||
|
expect(ga).to.have.been.calledOnce;
|
||||||
|
expect(ga).to.have.been.calledWith('send', properties);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
context('unsuccesful tracking', function() {
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
sandbox.stub(console, 'log');
|
sandbox.stub(console, 'log');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not accept tracking events without required properties', function() {
|
context('events without requird properties', function() {
|
||||||
|
beforeEach(function(){
|
||||||
analytics.track('action');
|
analytics.track('action');
|
||||||
analytics.track({'hitType':'pageview','eventCategory':'green'});
|
analytics.track({'hitType':'pageview','eventCategory':'green'});
|
||||||
analytics.track({'hitType':'pageview','eventAction':'eat'});
|
analytics.track({'hitType':'pageview','eventAction':'eat'});
|
||||||
@@ -34,130 +118,96 @@ describe('Analytics Service', function () {
|
|||||||
analytics.track({'hitType':'pageview'});
|
analytics.track({'hitType':'pageview'});
|
||||||
analytics.track({'eventCategory':'green'});
|
analytics.track({'eventCategory':'green'});
|
||||||
analytics.track({'eventAction':'eat'});
|
analytics.track({'eventAction':'eat'});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('logs errors to console', function() {
|
||||||
expect(console.log.callCount).to.eql(7);
|
expect(console.log.callCount).to.eql(7);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not accept tracking events with incorrect hit type', function () {
|
it('does not call out to amplitude', function() {
|
||||||
|
expect(amplitude.logEvent).to.not.be.called;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not call out to google analytics', function() {
|
||||||
|
expect(ga).to.not.be.called;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
context('incorrect hit type', function() {
|
||||||
|
beforeEach(function() {
|
||||||
analytics.track({'hitType':'moogly','eventCategory':'green','eventAction':'eat'});
|
analytics.track({'hitType':'moogly','eventCategory':'green','eventAction':'eat'});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('logs error to console', function () {
|
||||||
expect(console.log).to.have.been.calledOnce;
|
expect(console.log).to.have.been.calledOnce;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does not call out to amplitude', function() {
|
||||||
|
expect(amplitude.logEvent).to.not.be.called;
|
||||||
});
|
});
|
||||||
|
|
||||||
context('Amplitude', function() {
|
it('does not call out to google analytics', function() {
|
||||||
|
expect(ga).to.not.be.called;
|
||||||
beforeEach(function() {
|
|
||||||
sandbox.stub(amplitude, 'setUserId');
|
|
||||||
sandbox.stub(amplitude, 'logEvent');
|
|
||||||
sandbox.stub(amplitude, 'setUserProperties');
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('register', function() {
|
|
||||||
it('sets up tracking when user registers', function() {
|
|
||||||
analytics.register();
|
|
||||||
expect(amplitude.setUserId).to.have.been.calledOnce;
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('login', function() {
|
|
||||||
it('sets up tracking when user logs in', function() {
|
|
||||||
analytics.login();
|
|
||||||
expect(amplitude.setUserId).to.have.been.calledOnce;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('track', function() {
|
|
||||||
it('tracks a simple user action', function() {
|
|
||||||
analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'cron'});
|
|
||||||
expect(amplitude.logEvent).to.have.been.calledOnce;
|
|
||||||
expect(amplitude.logEvent).to.have.been.calledWith('cron',{'hitType':'event','eventCategory':'behavior','eventAction':'cron'});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('tracks a user action with additional properties', function() {
|
|
||||||
analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'cron','booleanProperty':true,'numericProperty':17,'stringProperty':'bagel'});
|
|
||||||
expect(amplitude.logEvent).to.have.been.calledOnce;
|
|
||||||
expect(amplitude.logEvent).to.have.been.calledWith('cron',{'hitType':'event','eventCategory':'behavior','eventAction':'cron','booleanProperty':true,'numericProperty':17,'stringProperty':'bagel'});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('updateUser', function() {
|
describe('updateUser', function() {
|
||||||
it('updates user-level properties with values provided in properties', function() {
|
|
||||||
analytics.updateUser({'userBoolean': false, 'userNumber': -8, 'userString': 'Enlightened'});
|
|
||||||
expect(amplitude.setUserProperties).to.have.been.calledOnce;
|
|
||||||
expect(amplitude.setUserProperties).to.have.been.calledWith({'userBoolean': false, 'userNumber': -8, 'userString': 'Enlightened'});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('updates user-level properties with certain user values when no properties are provided', function() {
|
|
||||||
user._id = 'unique-user-id';
|
|
||||||
user.stats.class = 'wizard';
|
|
||||||
user.stats.exp = 35.7;
|
|
||||||
user.stats.gp = 43.2;
|
|
||||||
user.stats.hp = 47.8;
|
|
||||||
user.stats.lvl = 24;
|
|
||||||
user.stats.mp = 41;
|
|
||||||
user.contributor.level = 1;
|
|
||||||
user.purchased.plan.planId = 'unique-plan-id';
|
|
||||||
|
|
||||||
analytics.updateUser();
|
|
||||||
expect(amplitude.setUserProperties).to.have.been.calledOnce;
|
|
||||||
expect(amplitude.setUserProperties).to.have.been.calledWith({
|
|
||||||
UUID: 'unique-user-id',
|
|
||||||
Class: 'wizard',
|
|
||||||
Experience: 35,
|
|
||||||
Gold: 43,
|
|
||||||
Health: 48,
|
|
||||||
Level: 24,
|
|
||||||
Mana: 41,
|
|
||||||
contributorLevel: 1,
|
|
||||||
subscription: 'unique-plan-id'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
context('Google Analytics', function() {
|
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
|
sandbox.stub(amplitude, 'setUserProperties');
|
||||||
sandbox.stub(window, 'ga');
|
sandbox.stub(window, 'ga');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('register', function() {
|
context('properties argument provided', function(){
|
||||||
it('sets up tracking when user registers', function() {
|
var properties = {'userBoolean': false, 'userNumber': -8, 'userString': 'Enlightened'};
|
||||||
analytics.register();
|
var expectedProperties = _.cloneDeep(properties);
|
||||||
|
expectedProperties.UUID = 'unique-user-id';
|
||||||
|
expectedProperties.Class = 'wizard';
|
||||||
|
expectedProperties.Experience = 35;
|
||||||
|
expectedProperties.Gold = 43;
|
||||||
|
expectedProperties.Health = 48;
|
||||||
|
expectedProperties.Level = 24;
|
||||||
|
expectedProperties.Mana = 41;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
user._id = 'unique-user-id';
|
||||||
|
user.stats.class = 'wizard';
|
||||||
|
user.stats.exp = 35.7;
|
||||||
|
user.stats.gp = 43.2;
|
||||||
|
user.stats.hp = 47.8;
|
||||||
|
user.stats.lvl = 24;
|
||||||
|
user.stats.mp = 41;
|
||||||
|
|
||||||
|
analytics.updateUser(properties);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls amplitude with provided properties and select user info', function() {
|
||||||
|
expect(amplitude.setUserProperties).to.have.been.calledOnce;
|
||||||
|
expect(amplitude.setUserProperties).to.have.been.calledWith(expectedProperties);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls google analytics with provided properties and select user info', function() {
|
||||||
expect(ga).to.have.been.calledOnce;
|
expect(ga).to.have.been.calledOnce;
|
||||||
expect(ga).to.have.been.calledWith('set');
|
expect(ga).to.have.been.calledWith('set', expectedProperties);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('login', function() {
|
context('no properties argument provided', function() {
|
||||||
it('sets up tracking when user logs in', function() {
|
var expectedProperties = {
|
||||||
analytics.login();
|
UUID: 'unique-user-id',
|
||||||
expect(ga).to.have.been.calledOnce;
|
Class: 'wizard',
|
||||||
expect(ga).to.have.been.calledWith('set');
|
Experience: 35,
|
||||||
});
|
Gold: 43,
|
||||||
});
|
Health: 48,
|
||||||
|
Level: 24,
|
||||||
|
Mana: 41,
|
||||||
|
contributorLevel: 1,
|
||||||
|
subscription: 'unique-plan-id'
|
||||||
|
};
|
||||||
|
|
||||||
describe('track', function() {
|
beforeEach(function() {
|
||||||
it('tracks a simple user action', function() {
|
|
||||||
analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'cron'});
|
|
||||||
expect(ga).to.have.been.calledOnce;
|
|
||||||
expect(ga).to.have.been.calledWith('send',{'hitType':'event','eventCategory':'behavior','eventAction':'cron'});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('tracks a user action with additional properties', function() {
|
|
||||||
analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'cron','booleanProperty':true,'numericProperty':17,'stringProperty':'bagel'});
|
|
||||||
expect(ga).to.have.been.calledOnce;
|
|
||||||
expect(ga).to.have.been.calledWith('send',{'hitType':'event','eventCategory':'behavior','eventAction':'cron','booleanProperty':true,'numericProperty':17,'stringProperty':'bagel'});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('updateUser', function() {
|
|
||||||
it('updates user-level properties with values provided in properties', function() {
|
|
||||||
analytics.updateUser({'userBoolean': false, 'userNumber': -8, 'userString': 'Enlightened'});
|
|
||||||
expect(ga).to.have.been.calledOnce;
|
|
||||||
expect(ga).to.have.been.calledWith('set', {'userBoolean': false, 'userNumber': -8, 'userString': 'Enlightened'});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('updates user-level properties', function() {
|
|
||||||
user._id = 'unique-user-id';
|
user._id = 'unique-user-id';
|
||||||
user.stats.class = 'wizard';
|
user.stats.class = 'wizard';
|
||||||
user.stats.exp = 35.7;
|
user.stats.exp = 35.7;
|
||||||
@@ -169,57 +219,18 @@ describe('Analytics Service', function () {
|
|||||||
user.purchased.plan.planId = 'unique-plan-id';
|
user.purchased.plan.planId = 'unique-plan-id';
|
||||||
|
|
||||||
analytics.updateUser();
|
analytics.updateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls amplitude with select user info', function() {
|
||||||
|
expect(amplitude.setUserProperties).to.have.been.calledOnce;
|
||||||
|
expect(amplitude.setUserProperties).to.have.been.calledWith(expectedProperties);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls google analytics with select user info', function() {
|
||||||
expect(ga).to.have.been.calledOnce;
|
expect(ga).to.have.been.calledOnce;
|
||||||
expect(ga).to.have.been.calledWith('set',{
|
expect(ga).to.have.been.calledWith('set', expectedProperties);
|
||||||
UUID: 'unique-user-id',
|
|
||||||
Class: 'wizard',
|
|
||||||
Experience: 35,
|
|
||||||
Gold: 43,
|
|
||||||
Health: 48,
|
|
||||||
Level: 24,
|
|
||||||
Mana: 41,
|
|
||||||
contributorLevel: 1,
|
|
||||||
subscription: 'unique-plan-id'
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
context.skip('Mixpanel', function() { // Mixpanel not currently in use
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
sandbox.stub(mixpanel, 'alias');
|
|
||||||
sandbox.stub(mixpanel, 'identify');
|
|
||||||
sandbox.stub(mixpanel, 'track');
|
|
||||||
sandbox.stub(mixpanel, 'register');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('sets up tracking when user registers', function() {
|
|
||||||
analytics.register();
|
|
||||||
expect(mixpanel.alias).to.have.been.calledOnce;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('sets up tracking when user logs in', function() {
|
|
||||||
analytics.login();
|
|
||||||
expect(mixpanel.identify).to.have.been.calledOnce;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('tracks a simple user action', function() {
|
|
||||||
analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'cron'});
|
|
||||||
expect(mixpanel.track).to.have.been.calledOnce;
|
|
||||||
expect(mixpanel.track).to.have.been.calledWith('cron',{'hitType':'event','eventCategory':'behavior','eventAction':'cron'});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('tracks a user action with additional properties', function() {
|
|
||||||
analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'cron','booleanProperty':true,'numericProperty':17,'stringProperty':'bagel'});
|
|
||||||
expect(mixpanel.track).to.have.been.calledOnce;
|
|
||||||
expect(mixpanel.track).to.have.been.calledWith('cron',{'hitType':'event','eventCategory':'behavior','eventAction':'cron','booleanProperty':true,'numericProperty':17,'stringProperty':'bagel'});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('updates user-level properties', function() {
|
|
||||||
analytics.updateUser({'userBoolean': false, 'userNumber': -8, 'userString': 'Enlightened'});
|
|
||||||
expect(mixpanel.register).to.have.been.calledOnce;
|
|
||||||
expect(mixpanel.register).to.have.been.calledWith({'userBoolean': false, 'userNumber': -8, 'userString': 'Enlightened'});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
/**
|
|
||||||
* Created by Sabe on 6/15/2015.
|
|
||||||
*/
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular
|
angular
|
||||||
@@ -119,9 +116,16 @@ function analyticsFactory(User) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateUser(properties) {
|
function updateUser(properties) {
|
||||||
if (!properties) {
|
if (!properties) properties = {};
|
||||||
properties = {};
|
|
||||||
|
|
||||||
|
_gatherUserStats(user, properties);
|
||||||
|
|
||||||
|
amplitude.setUserProperties(properties);
|
||||||
|
ga('set',properties);
|
||||||
|
// mixpanel.register(properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _gatherUserStats(user, properties) {
|
||||||
if (user._id) properties.UUID = user._id;
|
if (user._id) properties.UUID = user._id;
|
||||||
if (user.stats.class) properties.Class = user.stats.class;
|
if (user.stats.class) properties.Class = user.stats.class;
|
||||||
if (user.stats.exp) properties.Experience = Math.floor(user.stats.exp);
|
if (user.stats.exp) properties.Experience = Math.floor(user.stats.exp);
|
||||||
@@ -133,11 +137,6 @@ function analyticsFactory(User) {
|
|||||||
if (user.purchased.plan.planId) properties.subscription = user.purchased.plan.planId;
|
if (user.purchased.plan.planId) properties.subscription = user.purchased.plan.planId;
|
||||||
}
|
}
|
||||||
|
|
||||||
amplitude.setUserProperties(properties);
|
|
||||||
ga('set',properties);
|
|
||||||
// mixpanel.register(properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
loadScripts: loadScripts,
|
loadScripts: loadScripts,
|
||||||
register: register,
|
register: register,
|
||||||
|
|||||||
Reference in New Issue
Block a user