analytics-node
Advanced tools
Comparing version 1.1.1 to 1.2.0
1.2.0 / 2015-02-18 | ||
================== | ||
* add browserify support | ||
* Add installation instructions to readme | ||
1.1.1 / 2015-02-03 | ||
@@ -3,0 +9,0 @@ ================== |
@@ -36,3 +36,3 @@ var assert = require('assert'); | ||
if (!(this instanceof Analytics)) return new Analytics(writeKey, options); | ||
assert(writeKey, "You must pass your Segment project's write key."); | ||
assert(writeKey, 'You must pass your Segment project\'s write key.'); | ||
options = options || {}; | ||
@@ -39,0 +39,0 @@ this.queue = []; |
{ | ||
"name": "analytics-node", | ||
"repository": "git://github.com/segmentio/analytics-node", | ||
"version": "1.1.1", | ||
"version": "1.2.0", | ||
"description": "The hassle-free way to integrate analytics into any node application.", | ||
@@ -15,2 +15,7 @@ "keywords": [ | ||
"main": "lib/index.js", | ||
"browserify": { | ||
"transform": [ | ||
"brfs" | ||
] | ||
}, | ||
"dependencies": { | ||
@@ -28,6 +33,8 @@ "clone": "~0.1.17", | ||
"devDependencies": { | ||
"mocha": "1.8.1", | ||
"async": "~0.9.0", | ||
"browserify": "^8.1.3", | ||
"express": "~3.4.8", | ||
"http-proxy": "~1.3.0", | ||
"async": "~0.9.0" | ||
"mocha": "1.8.1", | ||
"brfs": "^1.3.0" | ||
}, | ||
@@ -34,0 +41,0 @@ "engines": { |
@@ -8,2 +8,8 @@ | ||
## Installation | ||
```bash | ||
$ npm install --save analytics-node | ||
``` | ||
## Documentation | ||
@@ -10,0 +16,0 @@ |
@@ -0,10 +1,362 @@ | ||
var assert = require('assert'); | ||
var Analytics = require('..'); | ||
var async = require('async'); | ||
var Browser = require('../analytics-node'); | ||
var server = require('./server'); | ||
var Mocha = require('mocha'); | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
var mocha = new Mocha({ reporter: 'spec' }); | ||
mocha.addFile(path.join(__dirname, 'tests.js')); | ||
mocha.run(function(failures){ | ||
process.exit(failures); | ||
var a; | ||
var noop = function(){}; | ||
var context = { | ||
library: { | ||
name: 'analytics-node', | ||
version: require('../package.json').version | ||
} | ||
}; | ||
describe('Analytics', function(){ | ||
before(function(done){ | ||
async.series([ | ||
function(cb){ | ||
server.proxy.listen(server.ports.proxy, cb); | ||
}, | ||
function(cb){ | ||
server.app | ||
.post('/v1/batch', server.fixture) | ||
.listen(server.ports.source, cb); | ||
} | ||
], done); | ||
}); | ||
beforeEach(function(){ | ||
a = Analytics('key', { | ||
host: 'http://localhost:4063', | ||
flushAt: Infinity, | ||
flushAfter: Infinity | ||
}); | ||
}); | ||
it('should expose a constructor', function(){ | ||
assert.equal('function', typeof Analytics); | ||
}); | ||
it('should require a write key', function(){ | ||
assert.throws(Analytics, error("You must pass your Segment project's write key.")); | ||
}); | ||
it('should not require the new keyword', function(){ | ||
assert(a instanceof Analytics); | ||
}); | ||
it('should create a queue', function(){ | ||
assert.deepEqual(a.queue, []); | ||
}); | ||
it('should set default options', function(){ | ||
var a = Analytics('key'); | ||
assert.equal(a.writeKey, 'key'); | ||
assert.equal(a.host, 'https://api.segment.io'); | ||
assert.equal(a.flushAt, 20); | ||
assert.equal(a.flushAfter, 10000); | ||
}); | ||
it('should take options', function(){ | ||
var a = Analytics('key', { | ||
host: 'a', | ||
flushAt: 1, | ||
flushAfter: 2, | ||
proxy: 'http://localhost:9001' | ||
}); | ||
assert.equal(a.host, 'a'); | ||
assert.equal(a.flushAt, 1); | ||
assert.equal(a.flushAfter, 2); | ||
assert.equal(a.proxy, 'http://localhost:9001'); | ||
}); | ||
it('should keep the flushAt option above zero', function(){ | ||
var a = Analytics('key', { flushAt: 0 }); | ||
assert.equal(a.flushAt, 1); | ||
}); | ||
describe('#enqueue', function(){ | ||
it('should add a message to the queue', function(){ | ||
var date = new Date(); | ||
a.enqueue('type', { timestamp: date }, noop); | ||
assert.deepEqual(a.queue[0], { | ||
message: { type: 'type', timestamp: date, context: context }, | ||
callback: noop | ||
}); | ||
}); | ||
it('should not modify the original message', function(){ | ||
var message = { event: 'test' }; | ||
a.enqueue('type', message, noop); | ||
assert(!message.hasOwnProperty('timestamp')); | ||
}); | ||
it('should flush the queue if it hits the max length', function(done){ | ||
a.flushAt = 1; | ||
a.flushAfter = null; | ||
a.flush = done; | ||
a.enqueue('type', {}); | ||
}); | ||
it('should flush after a period of time', function(done){ | ||
a.flushAt = Infinity; | ||
a.flushAfter = 1; | ||
a.flush = done; | ||
a.enqueue('type', {}); | ||
}); | ||
it('should reset an existing timer', function(done){ | ||
var i = 0; | ||
a.flushAt = Infinity; | ||
a.flushAfter = 1; | ||
a.flush = function(){ i++; }; | ||
a.enqueue('type', {}); | ||
a.enqueue('type', {}); | ||
setTimeout(function(){ | ||
assert.equal(1, i); | ||
done(); | ||
}, 1); | ||
}); | ||
it('should extend the given context', function(){ | ||
a.enqueue('type', { event: 'test', context: { name: 'travis' } }, noop); | ||
assert.deepEqual(a.queue[0].message.context, { | ||
library: { | ||
name:'analytics-node', | ||
version: require('../package.json').version | ||
}, | ||
name: 'travis' | ||
}); | ||
}); | ||
}); | ||
describe('#flush', function(){ | ||
it('should not fail when no items are in the queue', function(done){ | ||
a.flush(done); | ||
}); | ||
it('should send a batch of items', function(done){ | ||
a.flushAt = 2; | ||
enqueue(a, [1, 2, 3]); | ||
a.flush(function(err, data){ | ||
if (err) return done(err); | ||
assert.deepEqual(data.batch, [1, 2]); | ||
assert(data.timestamp instanceof Date); | ||
assert(data.sentAt instanceof Date); | ||
assert(data.messageId && /[a-zA-Z0-9]{8}/.test(data.messageId)); | ||
done(); | ||
}); | ||
}); | ||
it('should proxy', function(done) { | ||
a = Analytics('key', { | ||
host: 'http://localhost:4063', | ||
flushAt: Infinity, | ||
flushAfter: Infinity, | ||
proxy: 'http://localhost:4064' | ||
}); | ||
a.enqueue('type', { event: 'test' }, noop); | ||
a.flush(function(err, data){ | ||
// our proxy turns all responses into 408/errs | ||
assert(err); | ||
done(); | ||
}); | ||
}); | ||
it('should callback with an HTTP error', function(done){ | ||
enqueue(a, ['error']); | ||
a.flush(function(err, data){ | ||
assert(err); | ||
assert.equal(err.message, 'error'); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
describe('#identify', function(){ | ||
it('should enqueue a message', function(){ | ||
var date = new Date(); | ||
a.identify({ userId: 'id', timestamp: date }); | ||
assert.deepEqual(a.queue[0].message, { | ||
type: 'identify', | ||
userId: 'id', | ||
timestamp: date, | ||
context: context | ||
}); | ||
}); | ||
it('should validate a message', function(){ | ||
assert.throws(a.identify, error('You must pass a message object.')); | ||
}); | ||
it('should require a userId or anonymousId', function(){ | ||
assert.throws(function(){ | ||
a.identify({}); | ||
}, error('You must pass either an "anonymousId" or a "userId".')); | ||
}); | ||
}); | ||
describe('#group', function(){ | ||
it('should enqueue a message', function(){ | ||
var date = new Date(); | ||
a.group({ groupId: 'group', userId: 'user', timestamp: date }); | ||
assert.deepEqual(a.queue[0].message, { | ||
type: 'group', | ||
userId: 'user', | ||
groupId: 'group', | ||
timestamp: date, | ||
context: context | ||
}); | ||
}); | ||
it('should validate a message', function(){ | ||
assert.throws(a.group, error('You must pass a message object.')); | ||
}); | ||
it('should require a userId or anonymousId', function(){ | ||
assert.throws(function(){ | ||
a.group({}); | ||
}, error('You must pass either an "anonymousId" or a "userId".')); | ||
}); | ||
it('should require a groupId', function(){ | ||
assert.throws(function(){ | ||
a.group({ userId: 'id' }); | ||
}, error('You must pass a "groupId".')); | ||
}); | ||
}); | ||
describe('#track', function(){ | ||
it('should enqueue a message', function(){ | ||
var date = new Date(); | ||
a.track({ userId: 'id', event: 'event', timestamp: date }); | ||
assert.deepEqual(a.queue[0].message, { | ||
type: 'track', | ||
event: 'event', | ||
userId: 'id', | ||
timestamp: date, | ||
context: context | ||
}); | ||
}); | ||
it('should handle a user ids given as a number', function(){ | ||
var date = new Date(); | ||
a.track({ userId: 1, event: 'jumped the shark', timestamp: date }); | ||
assert.deepEqual(a.queue[0].message, { | ||
userId: 1, | ||
event: 'jumped the shark', | ||
type: 'track', | ||
timestamp: date, | ||
context: context | ||
}) | ||
}); | ||
it('should validate a message', function(){ | ||
assert.throws(a.track, error('You must pass a message object.')); | ||
}); | ||
it('should require a userId or anonymousId', function(){ | ||
assert.throws(function(){ | ||
a.track({}); | ||
}, error('You must pass either an "anonymousId" or a "userId".')); | ||
}); | ||
it('should require an event', function(){ | ||
assert.throws(function(){ | ||
a.track({ userId: 'id' }); | ||
}, error('You must pass an "event".')); | ||
}); | ||
}); | ||
describe('#page', function(){ | ||
it('should enqueue a message', function(){ | ||
var date = new Date(); | ||
a.page({ userId: 'id', timestamp: date }); | ||
assert.deepEqual(a.queue[0].message, { | ||
type: 'page', | ||
userId: 'id', | ||
timestamp: date, | ||
context: context | ||
}); | ||
}); | ||
it('should validate a message', function(){ | ||
assert.throws(a.page, error('You must pass a message object.')); | ||
}); | ||
it('should require a userId or anonymousId', function(){ | ||
assert.throws(function(){ | ||
a.page({}); | ||
}, error('You must pass either an "anonymousId" or a "userId".')); | ||
}); | ||
}); | ||
describe('#alias', function(){ | ||
it('should enqueue a message', function(){ | ||
var date = new Date(); | ||
a.alias({ previousId: 'previous', userId: 'id', timestamp: date }); | ||
assert.deepEqual(a.queue[0].message, { | ||
type: 'alias', | ||
previousId: 'previous', | ||
userId: 'id', | ||
timestamp: date, | ||
context: context | ||
}); | ||
}); | ||
it('should validate a message', function(){ | ||
assert.throws(a.alias, error('You must pass a message object.')); | ||
}); | ||
it('should require a userId', function(){ | ||
assert.throws(function(){ | ||
a.alias({}); | ||
}, error('You must pass a "userId".')); | ||
}); | ||
it('should require a previousId', function(){ | ||
assert.throws(function(){ | ||
a.alias({ userId: 'id' }); | ||
}, error('You must pass a "previousId".')); | ||
}); | ||
}); | ||
describe('browserify', function(){ | ||
it('should expose a browserified bundle', function(){ | ||
assert('function' == typeof Browser); | ||
}); | ||
}); | ||
}); | ||
/** | ||
* Create a queue with `messages`. | ||
* | ||
* @param {Analytics} a | ||
* @param {Array} messages | ||
* @return {Array} | ||
*/ | ||
function enqueue(a, messages){ | ||
a.queue = messages.map(function(msg){ | ||
return { | ||
message: msg, | ||
callback: noop | ||
}; | ||
}); | ||
} | ||
/** | ||
* Assert an error with `message` is thrown. | ||
* | ||
* @param {String} message | ||
* @return {Function} | ||
*/ | ||
function error(message){ | ||
return function(err){ | ||
return err.message == message; | ||
}; | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
372825
11216
38
6
5
4