debian-mirror-gitlab/snowplow-javascript-tracker/tests/integration/integration.js

321 lines
10 KiB
JavaScript
Executable File

/*
* JavaScript tracker for Snowplow: tests/functional/helpers.js
*
* Significant portions copyright 2010 Anthon Pang. Remainder copyright
* 2012-2016 Snowplow Analytics Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Anthon Pang nor Snowplow Analytics Ltd nor the
* names of their contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
define([
'intern!object',
'intern/chai!assert',
'intern/dojo/node!lodash',
'intern/dojo/node!http',
'intern/dojo/node!url',
"intern/dojo/node!js-base64"
], function(registerSuite, assert, lodash, http, url, jsBase64) {
var decodeBase64 = jsBase64.Base64.fromBase64;
/**
* Expected amount of request for each browser
* This must be increased when new tracking call added to
* pages/integration-template.html
*/
var log = [];
function pageViewsHaveDifferentIds () {
var pageViews = lodash.filter(log, function (logLine) {
return logLine.e === 'pv';
});
var contexts = lodash.map(pageViews, function (logLine) {
var data = JSON.parse(decodeBase64(logLine.cx)).data;
return lodash.find(data, function (context) {
return context.schema === 'iglu:com.snowplowanalytics.snowplow/web_page/jsonschema/1-0-0';
});
});
var ids = lodash.map(contexts, function (wpContext) {
return wpContext.data.id;
});
return lodash.uniq(ids).length >= 2;
}
/**
* Check if expected payload exists in `log`
*/
function checkExistenceOfExpectedQuerystring(expected) {
function compare(e, other) { // e === expected
var result = lodash.map(e, function (v, k) {
if (lodash.isFunction(v)) { return v(other[k]); }
else { return lodash.isEqual(v, other[k]); }
});
return lodash.every(result);
}
function strip(logLine) {
var expectedKeys = lodash.keys(expected);
var stripped = lodash.pickBy(logLine, function (v, k) { return lodash.includes(expectedKeys, k); });
if (lodash.keys(stripped).length !== expectedKeys.length) { return null; }
else { return stripped; }
}
return lodash.some(log, function (logLine) {
var stripped = strip(logLine);
if (stripped == null) { return false; }
else { return lodash.isEqualWith(expected, stripped, compare); }
});
}
function someTestsFailed(suite) {
return lodash.some(suite.tests, function (test) { return test.error !== null; });
}
// Ngrok must be running to forward requests to localhost
http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'image/gif'});
if (request.method === 'GET') {
var payload = url.parse(request.url, true).query;
log.push(payload);
}
var img = new Buffer('47494638396101000100800000dbdfef00000021f90401000000002c00000000010001000002024401003b', 'hex');
response.end(img, 'binary');
}).listen(8500, function () { console.log("Collector mock running...\n"); });
registerSuite({
teardown: function () {
if (someTestsFailed(this)) {
console.log("Tests failed with following log:");
lodash.forEach(log, function (l) { console.log(l); });
}
console.log("Cleaning log");
log = [];
},
name: 'Test that request_recorder logs meet expectations',
'Check existence of page view in log': function () {
assert.isTrue(checkExistenceOfExpectedQuerystring({
e: 'pv',
p: 'mob',
aid: 'CFe23a',
uid: 'Malcolm',
page: 'My Title',
cx: function (cx) {
var contexts = JSON.parse(decodeBase64(cx)).data;
return lodash.some(contexts,
lodash.matches({
schema:"iglu:com.example_company/user/jsonschema/2-0-0",
data:{
userType:'tester'
}
})
);
}
}), 'A page view should be detected');
},
'Check nonexistence of nonexistent event types in log': function () {
assert.isFalse(checkExistenceOfExpectedQuerystring({
e: 'ad'
}), 'No nonexistent event type should be detected');
},
'Check a structured event was sent': function () {
assert.isTrue(checkExistenceOfExpectedQuerystring({
e: 'se',
se_ca: 'Mixes',
se_ac: 'Play',
se_la: 'MRC/fabric-0503-mix',
se_va: '0.0'
}), 'A structured event should be detected');
},
'Check an unstructured event with true timestamp was sent': function () {
assert.isTrue(checkExistenceOfExpectedQuerystring({
e: 'ue',
ue_px: 'eyJzY2hlbWEiOiJpZ2x1OmNvbS5zbm93cGxvd2FuYWx5dGljcy5zbm93cGxvdy91bnN0cnVjdF9ldmVudC9qc29uc2NoZW1hLzEtMC0wIiwiZGF0YSI6eyJzY2hlbWEiOiJpZ2x1OmNvbS5hY21lX2NvbXBhbnkvdmlld2VkX3Byb2R1Y3QvanNvbnNjaGVtYS81LTAtMCIsImRhdGEiOnsicHJvZHVjdElkIjoiQVNPMDEwNDMifX19',
ttm: '1477401868'
}), 'An unstructured event should be detected');
},
'Check a transaction event was sent': function () {
assert.isTrue(checkExistenceOfExpectedQuerystring({
e: 'tr',
tr_id: 'order-123',
tr_af: 'acme',
tr_tt: '8000',
tr_tx: '100',
tr_ci: 'phoenix',
tr_st: 'arizona',
tr_co: 'USA',
tr_cu: 'JPY'
}), 'A transaction event should be detected');
},
'Check a transaction item event was sent': function () {
assert.isTrue(checkExistenceOfExpectedQuerystring({
e: 'ti',
ti_id: 'order-123',
ti_sk: '1001',
ti_nm: 'Blue t-shirt',
ti_ca: 'clothing',
ti_pr: '2000',
ti_qu: '2',
ti_cu: 'JPY'
}), 'A transaction item event should be detected');
},
'Check an unhandled exception was sent': function () {
assert.isTrue(checkExistenceOfExpectedQuerystring({
ue_px: function (ue) {
var event = JSON.parse(decodeBase64(ue)).data;
// We cannot test more because implementations vary much in old browsers (FF27,IE9)
return (event.schema === 'iglu:com.snowplowanalytics.snowplow/application_error/jsonschema/1-0-1') &&
(event.data.programmingLanguage === 'JAVASCRIPT') &&
(event.data.message != null);
}
}));
},
'Check pageViewId is regenerated for each trackPageView': function () {
assert.isTrue(pageViewsHaveDifferentIds());
},
'Check global contexts are for structured events': function () {
assert.isTrue(checkExistenceOfExpectedQuerystring({
e: 'se',
cx: function (cx) {
var contexts = JSON.parse(decodeBase64(cx)).data;
return 2 === lodash.size(
lodash.filter(contexts,
lodash.overSome(
lodash.matches({
schema: "iglu:com.snowplowanalytics.snowplow/mobile_context/jsonschema/1-0-1",
data: {
osType: 'ubuntu'
}
}),
lodash.matches({
schema: 'iglu:com.snowplowanalytics.snowplow/geolocation_context/jsonschema/1-1-0',
data: {
'latitude': 40.0,
'longitude': 55.1
}
})
)
)
);
}
}));
},
'Check an unstructured event with global context from accept ruleset': function () {
assert.isTrue(checkExistenceOfExpectedQuerystring({
e: 'ue',
ue_px: function (ue_px) {
var event = JSON.parse(decodeBase64(ue_px)).data;
return lodash.isMatch(event,
{
schema:"iglu:com.acme_company/viewed_product/jsonschema/5-0-0",
data:{
productId: 'ASO01042'
}
}
);
},
cx: function (cx) {
var contexts = JSON.parse(decodeBase64(cx)).data;
return 2 === lodash.size(
lodash.filter(contexts,
lodash.overSome(
lodash.matches({
schema: "iglu:com.snowplowanalytics.snowplow/mobile_context/jsonschema/1-0-1",
data: {
osType: 'ubuntu'
}
}),
lodash.matches({
schema: 'iglu:com.snowplowanalytics.snowplow/geolocation_context/jsonschema/1-1-0',
data: {
'latitude': 40.0,
'longitude': 55.1
}
})
)
)
);
}
}), 'An unstructured event with global contexts should be detected');
},
'Check an unstructured event missing global context from reject ruleset': function () {
assert.isTrue(checkExistenceOfExpectedQuerystring({
e: 'ue',
ue_px: function (ue_px) {
var event = JSON.parse(decodeBase64(ue_px)).data;
return lodash.isMatch(event,
{
schema:"iglu:com.acme_company/viewed_product/jsonschema/5-0-0",
data:{
productId: 'ASO01041'
}
}
);
},
cx: function (cx) {
var contexts = JSON.parse(decodeBase64(cx)).data;
return 0 === lodash.size(
lodash.filter(contexts,
lodash.overSome(
lodash.matches({
schema: "iglu:com.snowplowanalytics.snowplow/mobile_context/jsonschema/1-0-1",
data: {
osType: 'ubuntu'
}
}),
lodash.matches({
schema: 'iglu:com.snowplowanalytics.snowplow/geolocation_context/jsonschema/1-1-0',
data: {
'latitude': 40.0,
'longitude': 55.1
}
})
)
)
);
}
}), 'An unstructured event without global contexts should be detected');
}
});
});