boomcatch
Version:
A standalone, node.js-based beacon receiver for boomerang.
631 lines (543 loc) • 27.5 kB
JavaScript
// Copyright © 2014, 2015, 2016 Springer Nature
//
// This file is part of boomcatch.
//
// Boomcatch is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Boomcatch is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with boomcatch. If not, see <http://www.gnu.org/licenses/>.
;
var mockery, assert, spooks, modulePath;
mockery = require('mockery');
assert = require('chai').assert;
spooks = require('spooks');
modulePath = '../../src/mappers/har';
mockery.registerAllowable(modulePath);
mockery.registerAllowable('../../package.json');
mockery.registerAllowable('../normalise');
mockery.registerAllowable('check-types');
mockery.registerAllowable('url');
mockery.registerAllowable('querystring');
suite('mappers/har:', function () {
var log, useragent, browser;
setup(function () {
log = {};
useragent = spooks.fn({
name: 'useragent',
log: log
});
useragent.lookup = spooks.fn({
name: 'lookup',
log: log,
results: [
{
toJSON: function () {
log.counts.toJSON += 1;
log.these.toJSON.push(this);
log.args.toJSON.push(arguments);
return browser;
}
}
]
});
log.counts.toJSON = 0;
log.these.toJSON = [];
log.args.toJSON = [];
mockery.enable({ useCleanCache: true });
mockery.registerMock('useragent', useragent);
});
teardown(function () {
mockery.deregisterMock('useragent');
mockery.disable();
log = useragent = undefined;
});
test('require does not throw', function () {
assert.doesNotThrow(function () {
require(modulePath);
});
});
test('require returns object', function () {
assert.isObject(require(modulePath));
});
suite('require:', function () {
var har;
setup(function () {
har = require(modulePath);
});
teardown(function () {
har = undefined;
});
test('initialise function is exported', function () {
assert.isFunction(har.initialise);
});
test('initialise does not throw without options', function () {
assert.doesNotThrow(function () {
har.initialise();
});
});
test('useragent was not called', function () {
assert.strictEqual(log.counts.useragent, 0);
});
suite('call initialise without options:', function () {
var mapper;
setup(function () {
mapper = har.initialise();
});
teardown(function () {
mapper = undefined;
});
test('useragent was called once', function () {
assert.strictEqual(log.counts.useragent, 1);
});
test('useragent was called correctly', function () {
assert.isUndefined(log.these.useragent[0]);
assert.lengthOf(log.args.useragent[0], 1);
assert.isTrue(log.args.useragent[0][0]);
});
test('initialise returned function', function () {
assert.isFunction(mapper);
});
test('mapper throws without data', function () {
assert.throws(function () {
mapper(undefined, 'foo', 'bar');
});
});
test('mapper does not throw with empty data', function () {
assert.doesNotThrow(function () {
mapper({}, 'foo', 'bar');
});
});
suite('call mapper without restiming data:', function () {
var result;
setup(function () {
result = mapper({
nt_nav_type: '0',
nt_nav_st: '1',
nt_fet_st: '2',
nt_ssl_st: '3',
nt_req_st: '4',
nt_domint: '5',
nt_unload_st: '6',
nt_unload_end: '7',
nt_red_st: '8',
nt_red_end: '9',
nt_dns_st: '10',
nt_dns_end: '11',
nt_con_st: '12',
nt_con_end: '13',
nt_res_st: '14',
nt_res_end: '15',
nt_domloading: '16',
nt_domcomp: '17',
nt_domcontloaded_st: '18',
nt_domcontloaded_end: '19',
nt_load_st: '20',
nt_load_end: '21'
}, 'foo', 'bar');
});
teardown(function () {
result = undefined;
});
test('result was empty string', function () {
assert.strictEqual(result, '');
});
test('useragent.lookup was not called', function () {
assert.strictEqual(log.counts.lookup, 0);
});
test('useragent.toJSON was not called', function () {
assert.strictEqual(log.counts.toJSON, 0);
});
});
suite('call mapper without navtiming data:', function () {
var result;
setup(function () {
result = mapper({
restiming: {
0: {
rt_name: 'http://www.example.com/foo?bar=baz#qux',
rt_in_type: 'css',
rt_st: '1',
rt_fet_st: '2',
rt_scon_st: '3',
rt_req_st: '4',
rt_red_st: '5',
rt_red_end: '6',
rt_dns_st: '7',
rt_dns_end: '8',
rt_con_st: '10',
rt_con_end: '11',
rt_res_st: '12',
rt_res_end: '13'
},
1: {
rt_name: 'https://nature.com/wibble?k=v&l=w',
rt_in_type: 'img',
rt_st: '14',
rt_fet_st: '15',
rt_scon_st: '16',
rt_req_st: '17',
rt_red_st: '18',
rt_red_end: '19',
rt_dns_st: '20',
rt_dns_end: '21',
rt_con_st: '22',
rt_con_end: '23',
rt_res_st: '24',
rt_res_end: '25'
}
}
}, 'foo', 'bar');
});
teardown(function () {
result = undefined;
});
test('result was empty string', function () {
assert.strictEqual(result, '');
});
test('useragent.lookup was not called', function () {
assert.strictEqual(log.counts.lookup, 0);
});
test('useragent.toJSON was not called', function () {
assert.strictEqual(log.counts.toJSON, 0);
});
});
suite('call mapper with valid data:', function () {
var result;
setup(function () {
browser = {
family: 'foo',
major: 'bar'
};
result = mapper({
nt_nav_type: '0',
nt_nav_st: '1',
nt_fet_st: '2',
nt_ssl_st: '3',
nt_req_st: '4',
nt_domint: '5',
nt_unload_st: '6',
nt_unload_end: '12',
nt_red_st: '7',
nt_red_end: '14',
nt_dns_st: '8',
nt_dns_end: '16',
nt_con_st: '9',
nt_con_end: '18',
nt_res_st: '10',
nt_res_end: '20',
nt_domloading: '11',
nt_domcomp: '22',
nt_domcontloaded_st: '12',
nt_domcontloaded_end: '24',
nt_load_st: '13',
nt_load_end: '26',
restiming: {
0: {
rt_name: 'http://www.example.com/foo?bar=baz#qux',
rt_in_type: 'img',
rt_st: '14',
rt_fet_st: '15',
rt_scon_st: '16',
rt_req_st: '17',
rt_red_st: '18',
rt_red_end: '36',
rt_dns_st: '19',
rt_dns_end: '38',
rt_con_st: '20',
rt_con_end: '40',
rt_res_st: '21',
rt_res_end: '42'
},
1: {
rt_name: 'https://nature.com/wibble?k=v&l=w',
rt_in_type: 'css',
rt_st: '220',
rt_fet_st: '230',
rt_scon_st: '240',
rt_req_st: '250',
rt_red_st: '280',
rt_red_end: '560',
rt_dns_st: '290',
rt_dns_end: '580',
rt_con_st: '300',
rt_con_end: '600',
rt_res_st: '310',
rt_res_end: '620'
}
}
}, 'baz', 'qux');
});
teardown(function () {
browser = result = undefined;
});
test('useragent.lookup was called once', function () {
assert.strictEqual(log.counts.lookup, 1);
});
test('useragent.lookup was called correctly', function () {
assert.strictEqual(log.these.lookup[0], useragent);
assert.lengthOf(log.args.lookup[0], 1);
assert.strictEqual(log.args.lookup[0][0], 'qux');
});
test('useragent.toJSON was called once', function () {
assert.strictEqual(log.counts.toJSON, 1);
});
test('useragent.toJSON was called correctly', function () {
assert.strictEqual(log.these.toJSON[0], useragent.lookup());
assert.lengthOf(log.args.toJSON[0], 0);
});
test('result was not empty string', function () {
assert.notEqual(result, '');
});
test('result was valid JSON', function () {
assert.doesNotThrow(function () {
JSON.parse(result);
});
});
suite('parse result:', function () {
var data;
setup(function () {
data = JSON.parse(result);
});
teardown(function () {
data = undefined;
});
test('data is object', function () {
assert.isObject(data);
assert.lengthOf(Object.keys(data), 1);
});
test('data.log is object', function () {
assert.isObject(data.log);
assert.lengthOf(Object.keys(data.log), 5);
});
test('data.log.version is correct', function () {
assert.strictEqual(data.log.version, '1.2');
});
test('data.log.creator is object', function () {
assert.isObject(data.log.creator);
assert.lengthOf(Object.keys(data.log.creator), 2);
});
test('data.log.creator is correct', function () {
assert.strictEqual(data.log.creator.name, 'boomcatch');
assert.strictEqual(data.log.creator.version, require('../../package.json').version);
});
test('data.log.browser is object', function () {
assert.isObject(data.log.browser);
assert.lengthOf(Object.keys(data.log.browser), 2);
});
test('data.log.browser is correct', function () {
assert.strictEqual(data.log.browser.name, 'foo');
assert.strictEqual(data.log.browser.version, 'bar');
});
test('data.log.pages is array', function () {
assert.isArray(data.log.pages);
assert.lengthOf(data.log.pages, 1);
});
test('data.log.pages[0] is object', function () {
assert.isObject(data.log.pages[0]);
assert.lengthOf(Object.keys(data.log.pages[0]), 4);
});
test('data.log.pages[0] is correct', function () {
assert.strictEqual(data.log.pages[0].startedDateTime, '1970-01-01T00:00:00.001Z');
assert.strictEqual(data.log.pages[0].id, '0');
assert.strictEqual(data.log.pages[0].title, 'baz');
assert.isObject(data.log.pages[0].pageTimings);
assert.lengthOf(Object.keys(data.log.pages[0].pageTimings), 2);
assert.strictEqual(data.log.pages[0].pageTimings.onContentLoad, 12);
assert.strictEqual(data.log.pages[0].pageTimings.onLoad, 13);
});
test('data.log.entries is array', function () {
assert.isArray(data.log.entries);
assert.lengthOf(data.log.entries, 2);
});
test('data.log.entries[0] is object', function () {
assert.isObject(data.log.entries[0]);
assert.lengthOf(Object.keys(data.log.entries[0]), 7);
});
test('data.log.entries[0] is correct', function () {
assert.strictEqual(data.log.entries[0].pageref, '0');
assert.strictEqual(data.log.entries[0].startedDateTime, '1970-01-01T00:00:00.014Z');
assert.strictEqual(data.log.entries[0].time, 65);
assert.isObject(data.log.entries[0].request);
assert.lengthOf(Object.keys(data.log.entries[0].request), 8);
assert.isObject(data.log.entries[0].response);
assert.lengthOf(Object.keys(data.log.entries[0].response), 9);
assert.isObject(data.log.entries[0].cache);
assert.lengthOf(Object.keys(data.log.entries[0].cache), 0);
assert.isObject(data.log.entries[0].timings);
assert.lengthOf(Object.keys(data.log.entries[0].timings), 7);
});
test('data.log.entries[0].request is correct', function () {
assert.strictEqual(data.log.entries[0].request.method, '');
assert.strictEqual(data.log.entries[0].request.url, 'http://www.example.com/foo?bar=baz#qux');
assert.strictEqual(data.log.entries[0].request.httpVersion, '');
assert.isArray(data.log.entries[0].request.cookies);
assert.lengthOf(data.log.entries[0].request.cookies, 0);
assert.isArray(data.log.entries[0].request.headers);
assert.lengthOf(data.log.entries[0].request.headers, 0);
assert.isArray(data.log.entries[0].request.queryString);
assert.lengthOf(data.log.entries[0].request.queryString, 1);
assert.isObject(data.log.entries[0].request.queryString[0]);
assert.lengthOf(Object.keys(data.log.entries[0].request.queryString[0]), 2);
assert.strictEqual(data.log.entries[0].request.queryString[0].name, 'bar');
assert.strictEqual(data.log.entries[0].request.queryString[0].value, 'baz');
assert.strictEqual(data.log.entries[0].request.headerSize, -1);
assert.strictEqual(data.log.entries[0].request.bodySize, -1);
});
test('data.log.entries[0].response is correct', function () {
assert.strictEqual(data.log.entries[0].response.status, -1);
assert.strictEqual(data.log.entries[0].response.statusText, '');
assert.strictEqual(data.log.entries[0].response.httpVersion, '');
assert.isArray(data.log.entries[0].response.cookies);
assert.lengthOf(data.log.entries[0].response.cookies, 0);
assert.isArray(data.log.entries[0].response.headers);
assert.lengthOf(data.log.entries[0].response.headers, 0);
assert.isObject(data.log.entries[0].response.content);
assert.lengthOf(Object.keys(data.log.entries[0].response.content), 2);
assert.strictEqual(data.log.entries[0].response.content.size, -1);
assert.strictEqual(data.log.entries[0].response.content.mimeType, '');
assert.strictEqual(data.log.entries[0].response.redirectURL, '');
assert.strictEqual(data.log.entries[0].response.headerSize, -1);
assert.strictEqual(data.log.entries[0].response.bodySize, -1);
});
test('data.log.entries[0].timings is correct', function () {
assert.strictEqual(data.log.entries[0].timings.blocked, 1);
assert.strictEqual(data.log.entries[0].timings.dns, 19);
assert.strictEqual(data.log.entries[0].timings.connect, 20);
assert.strictEqual(data.log.entries[0].timings.send, 4);
assert.strictEqual(data.log.entries[0].timings.wait, 0);
assert.strictEqual(data.log.entries[0].timings.receive, 21);
assert.strictEqual(data.log.entries[0].timings.ssl, 24);
});
test('data.log.entries[1] is correct', function () {
assert.strictEqual(data.log.entries[1].pageref, '0');
assert.strictEqual(data.log.entries[1].startedDateTime, '1970-01-01T00:00:00.220Z');
assert.strictEqual(data.log.entries[1].time, 970);
});
test('data.log.entries[1].request is correct', function () {
assert.strictEqual(data.log.entries[1].request.url, 'https://nature.com/wibble?k=v&l=w');
assert.lengthOf(data.log.entries[1].request.queryString, 2);
assert.strictEqual(data.log.entries[1].request.queryString[0].name, 'k');
assert.strictEqual(data.log.entries[1].request.queryString[0].value, 'v');
assert.strictEqual(data.log.entries[1].request.queryString[1].name, 'l');
assert.strictEqual(data.log.entries[1].request.queryString[1].value, 'w');
});
test('data.log.entries[1].timings is correct', function () {
assert.strictEqual(data.log.entries[1].timings.blocked, 10);
assert.strictEqual(data.log.entries[1].timings.dns, 290);
assert.strictEqual(data.log.entries[1].timings.connect, 300);
assert.strictEqual(data.log.entries[1].timings.send, 60);
assert.strictEqual(data.log.entries[1].timings.wait, 0);
assert.strictEqual(data.log.entries[1].timings.receive, 310);
assert.strictEqual(data.log.entries[1].timings.ssl, 360);
});
});
});
suite('call mapper with minimal data:', function () {
var result;
setup(function () {
browser = {
family: 'browser name',
major: 'browser version'
};
result = mapper({
nt_nav_type: '0',
nt_nav_st: '100',
nt_fet_st: '200',
nt_ssl_st: '300',
nt_req_st: '400',
nt_domint: '500',
nt_unload_st: '600',
nt_unload_end: '1200',
nt_red_st: '700',
nt_red_end: '1400',
nt_dns_st: '800',
nt_dns_end: '1600',
nt_con_st: '900',
nt_con_end: '1800',
nt_res_st: '1000',
nt_res_end: '2000',
nt_domloading: '1100',
nt_domcomp: '2200',
nt_domcontloaded_st: '1200',
nt_domcontloaded_end: '2400',
nt_load_st: '1300',
nt_load_end: '2600',
restiming: [
{
rt_name: 'http://example.com/?a=b&c=d',
rt_in_type: 'css',
rt_st: '1400',
rt_fet_st: '1500'
}
]
}, 'referer', 'user agent');
});
teardown(function () {
browser = result = undefined;
});
test('useragent.lookup was called correctly', function () {
assert.strictEqual(log.args.lookup[0][0], 'user agent');
});
test('result was not empty string', function () {
assert.notEqual(result, '');
});
test('result was valid JSON', function () {
assert.doesNotThrow(function () {
JSON.parse(result);
});
});
suite('parse result:', function () {
var data;
setup(function () {
data = JSON.parse(result);
});
teardown(function () {
data = undefined;
});
test('data.log.browser is correct', function () {
assert.strictEqual(data.log.browser.name, 'browser name');
assert.strictEqual(data.log.browser.version, 'browser version');
});
test('data.log.pages[0] is correct', function () {
assert.strictEqual(data.log.pages[0].startedDateTime, '1970-01-01T00:00:00.100Z');
assert.strictEqual(data.log.pages[0].title, 'referer');
assert.strictEqual(data.log.pages[0].pageTimings.onContentLoad, 1200);
assert.strictEqual(data.log.pages[0].pageTimings.onLoad, 1300);
});
test('data.log.entries has one item', function () {
assert.lengthOf(data.log.entries, 1);
});
test('data.log.entries[0] is correct', function () {
assert.strictEqual(data.log.entries[0].startedDateTime, '1970-01-01T00:00:01.400Z');
assert.strictEqual(data.log.entries[0].time, 100);
});
test('data.log.entries[0].request is correct', function () {
assert.strictEqual(data.log.entries[0].request.url, 'http://example.com/?a=b&c=d');
assert.lengthOf(data.log.entries[0].request.queryString, 2);
assert.strictEqual(data.log.entries[0].request.queryString[0].name, 'a');
assert.strictEqual(data.log.entries[0].request.queryString[0].value, 'b');
assert.strictEqual(data.log.entries[0].request.queryString[1].name, 'c');
assert.strictEqual(data.log.entries[0].request.queryString[1].value, 'd');
});
test('data.log.entries[0].timings is correct', function () {
assert.strictEqual(data.log.entries[0].timings.blocked, 100);
assert.strictEqual(data.log.entries[0].timings.dns, -1);
assert.strictEqual(data.log.entries[0].timings.connect, -1);
assert.strictEqual(data.log.entries[0].timings.send, -1);
assert.strictEqual(data.log.entries[0].timings.wait, 0);
assert.strictEqual(data.log.entries[0].timings.receive, -1);
assert.strictEqual(data.log.entries[0].timings.ssl, -1);
});
});
});
});
});
});