Skip to content
This repository was archived by the owner on Oct 11, 2022. It is now read-only.

Commit b5be6de

Browse files
committed
Added integration tests (closes snowplow#154)
1 parent b22517e commit b5be6de

8 files changed

Lines changed: 348 additions & 5 deletions

File tree

.travis.yml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,22 @@ node_js:
22
- "0.10"
33
script: node node_modules/intern/runner.js config=tests/intern
44
language: node_js
5-
before_script:
5+
install:
6+
- npm install
67
- npm install -g grunt-cli
7-
script: grunt travis
8+
- wget https://api.equinox.io/1/Applications/ap_pJSFC5wQYkAyI0FIVwKYs9h1hW/Updates/Asset/ngrok.zip\?os\=linux\&arch\=386\&channel\=stable
9+
- unzip ./ngrok.zip\?os=linux\&arch=386\&channel=stable
10+
before_script:
11+
- node tests/integration/request_recorder.js &
12+
- ./ngrok -authtoken $NGROK_AUTH -subdomain=snowplow -log=stdout 8500 > /dev/null &
13+
script:
14+
- grunt travis
15+
after_script:
16+
- cat ./tracker.log
817
env:
918
global:
1019
- secure: "Ort7jy0HpYi0EGfuRYGW4tawmVJzfUUNXhtJEOWR09FYL28XUyxvjUnpS1WZlD0/rBZiuDPBep1Tc81F88pSns4ZAg1lxlM/zheWrCKvYudeAia2g06OqOA1JfeVWX7TjemJ5s1lY66b5VQrDG1QLIO1RPjgWWea0MpSQzv00Ms="
1120
- secure: "JFprkMXxrQZhRlYvJb+ZOr540QuzMU2jQtf39oPzg8uqcV5TDDWTuUZ6D3ogyNJnzH0mYDRzHZQEAqxkyjfndpIgN+a+dBM1l4WoKrTR9BpA3ZZD6zFEG7UrHBcvZgvopbY1wMPXbn4JL7J7SPPOjvvrjjIk/QIsTUYft/UOyXI="
21+
22+
# NGROK_AUTH token
23+
- secure: "aLAryygcpImMFo2ZrDhcrE5IFGrt300BfCXu4r2mChoGUMUU6fJltfKktwv9OKsfWFhhJ44fpJX2nSmGmOyGDljC8eegXUjB0vToQ0/NGvtibE+ug/T4fbMgVMA842Y1MB9MvIK10/cD2/2bLKGYHrNq8196YxBVptvVLu+aphY="

Gruntfile.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ module.exports = function(grunt) {
9797
test: {
9898
files: {
9999
'tests/pages/helpers.js': ['tests/scripts/helpers.js'],
100-
'tests/pages/detectors.js': ['tests/scripts/detectors.js']
100+
'tests/pages/detectors.js': ['tests/scripts/detectors.js'],
101+
'tests/pages/snowplow.js': ['src/js/init.js']
101102
}
102103
}
103104
},

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"grunt-yui-compressor": "git://github.com/snowplow/grunt-yui-compressor.git#feature/issue-8",
1515
"intern": "~1.5.0",
1616
"jstimezonedetect": "~1.0.5",
17+
"lodash": "^3.1.0",
1718
"lodash-cli": "^2.4.2",
1819
"murmurhash": "0.0.2",
1920
"semver": "~2.2.1",

tests/integration/integration.js

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
* JavaScript tracker for Snowplow: tests/functional/helpers.js
3+
*
4+
* Significant portions copyright 2010 Anthon Pang. Remainder copyright
5+
* 2012-2014 Snowplow Analytics Ltd. All rights reserved.
6+
*
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions are
9+
* met:
10+
*
11+
* * Redistributions of source code must retain the above copyright
12+
* notice, this list of conditions and the following disclaimer.
13+
*
14+
* * Redistributions in binary form must reproduce the above copyright
15+
* notice, this list of conditions and the following disclaimer in the
16+
* documentation and/or other materials provided with the distribution.
17+
*
18+
* * Neither the name of Anthon Pang nor Snowplow Analytics Ltd nor the
19+
* names of their contributors may be used to endorse or promote products
20+
* derived from this software without specific prior written permission.
21+
*
22+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33+
*/
34+
35+
define([
36+
'intern!object',
37+
'intern/chai!assert',
38+
'intern/dojo/node!fs',
39+
'intern/dojo/node!querystring',
40+
'intern/dojo/node!lodash'
41+
], function(registerSuite, assert, fs, querystring, lodash) {
42+
43+
function parseLog () {
44+
return fs.readFileSync('./tracker.log', 'utf8').split('\n');
45+
}
46+
47+
function querystringFromLine(line) {
48+
return line ? JSON.parse(line) : {};
49+
}
50+
51+
function requestMatchesExpectedQuerystring(actual, expected) {
52+
if (!actual) {
53+
return false;
54+
}
55+
return !lodash.any(lodash.keys(expected), function (key) {
56+
if (expected[key] !== actual[key]) {
57+
return true;
58+
}
59+
return false;
60+
});
61+
}
62+
63+
function checkExistenceOfExpectedQuerystring(expected) {
64+
var lines = parseLog();
65+
66+
return lodash.any(lines, function (line) {
67+
if (requestMatchesExpectedQuerystring(querystringFromLine(line), expected)) {
68+
return true;
69+
}
70+
return false;
71+
});
72+
}
73+
74+
registerSuite({
75+
76+
name: 'Test that request_recorder logs meet expectations',
77+
78+
'Check existence of page view in log': function() {
79+
assert.isTrue(checkExistenceOfExpectedQuerystring({
80+
e: 'pv',
81+
p: 'mob',
82+
aid: 'CFe23a',
83+
uid: 'Malcolm',
84+
page: 'My Title',
85+
cx: 'eyJzY2hlbWEiOiJpZ2x1OmNvbS5zbm93cGxvd2FuYWx5dGljcy5zbm93cGxvdy9jb250ZXh0cy9qc29uc2NoZW1hLzEtMC0wIiwiZGF0YSI6W3sic2NoZW1hIjoiaWdsdTpjb20uZXhhbXBsZV9jb21wYW55L3VzZXIvanNvbnNjaGVtYS8yLTAtMCIsImRhdGEiOnsidXNlclR5cGUiOiJ0ZXN0ZXIifX1dfQ'
86+
}), 'A page view should be detected');
87+
},
88+
89+
'Check nonexistence of nonexistent event types in log': function() {
90+
assert.isFalse(checkExistenceOfExpectedQuerystring({
91+
e: 'ad'
92+
}), 'No nonexistent event type should be detected');
93+
},
94+
95+
'Check a structured event was sent': function () {
96+
assert.isTrue(checkExistenceOfExpectedQuerystring({
97+
e: 'se',
98+
se_ca: 'Mixes',
99+
se_ac: 'Play',
100+
se_la: 'MRC/fabric-0503-mix',
101+
se_va: '0.0'
102+
}), 'A structured event should be detected');
103+
},
104+
105+
'Check an unstructured event was sent': function () {
106+
assert.isTrue(checkExistenceOfExpectedQuerystring({
107+
e: 'ue',
108+
ue_px: 'eyJzY2hlbWEiOiJpZ2x1OmNvbS5zbm93cGxvd2FuYWx5dGljcy5zbm93cGxvdy91bnN0cnVjdF9ldmVudC9qc29uc2NoZW1hLzEtMC0wIiwiZGF0YSI6eyJzY2hlbWEiOiJpZ2x1OmNvbS5hY21lX2NvbXBhbnkvdmlld2VkX3Byb2R1Y3QvanNvbnNjaGVtYS81LTAtMCIsImRhdGEiOnsicHJvZHVjdElkIjoiQVNPMDEwNDMifX19'
109+
}), 'An unstructured event should be detected');
110+
},
111+
112+
'Check a transaction event was sent': function () {
113+
assert.isTrue(checkExistenceOfExpectedQuerystring({
114+
e: 'tr',
115+
tr_id: 'order-123',
116+
tr_af: 'acme',
117+
tr_tt: '8000',
118+
tr_tx: '100',
119+
tr_ci: 'phoenix',
120+
tr_st: 'arizona',
121+
tr_co: 'USA',
122+
tr_cu: 'JPY'
123+
}), 'A transaction event should be detected');
124+
},
125+
126+
'Check a transaction item event was sent': function () {
127+
assert.isTrue(checkExistenceOfExpectedQuerystring({
128+
e: 'ti',
129+
ti_id: 'order-123',
130+
ti_sk: '1001',
131+
ti_nm: 'Blue t-shirt',
132+
ti_ca: 'clothing',
133+
ti_pr: '2000',
134+
ti_qu: '2',
135+
ti_cu: 'JPY'
136+
}), 'A transaction item event should be detected');
137+
}
138+
});
139+
});
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* JavaScript tracker for Snowplow: tests/request_recorder.js
3+
*
4+
* Significant portions copyright 2010 Anthon Pang. Remainder copyright
5+
* 2012-2014 Snowplow Analytics Ltd. All rights reserved.
6+
*
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions are
9+
* met:
10+
*
11+
* * Redistributions of source code must retain the above copyright
12+
* notice, this list of conditions and the following disclaimer.
13+
*
14+
* * Redistributions in binary form must reproduce the above copyright
15+
* notice, this list of conditions and the following disclaimer in the
16+
* documentation and/or other materials provided with the distribution.
17+
*
18+
* * Neither the name of Anthon Pang nor Snowplow Analytics Ltd nor the
19+
* names of their contributors may be used to endorse or promote products
20+
* derived from this software without specific prior written permission.
21+
*
22+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33+
*/
34+
35+
var url = require('url');
36+
var http = require('http');
37+
var fs = require('fs');
38+
39+
http.createServer(function (request, response) {
40+
response.writeHead(200, {'Content-Type': 'image/gif'});
41+
42+
if (request.method === 'GET') {
43+
var payload = url.parse(request.url, true).query;
44+
console.log(JSON.stringify(payload));
45+
fs.appendFile('tracker.log', JSON.stringify(payload) + '\n');
46+
}
47+
48+
var img = new Buffer('47494638396101000100800000dbdfef00000021f90401000000002c00000000010001000002024401003b', 'hex');
49+
response.end(img, 'binary');
50+
51+
}).listen(8500);
52+
console.log('Server running at http://127.0.0.1:8500/');

tests/integration/setup.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* JavaScript tracker for Snowplow: tests/functional/detectors.js
3+
*
4+
* Significant portions copyright 2010 Anthon Pang. Remainder copyright
5+
* 2012-2014 Snowplow Analytics Ltd. All rights reserved.
6+
*
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions are
9+
* met:
10+
*
11+
* * Redistributions of source code must retain the above copyright
12+
* notice, this list of conditions and the following disclaimer.
13+
*
14+
* * Redistributions in binary form must reproduce the above copyright
15+
* notice, this list of conditions and the following disclaimer in the
16+
* documentation and/or other materials provided with the distribution.
17+
*
18+
* * Neither the name of Anthon Pang nor Snowplow Analytics Ltd nor the
19+
* names of their contributors may be used to endorse or promote products
20+
* derived from this software without specific prior written permission.
21+
*
22+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33+
*/
34+
35+
define([
36+
'intern!object'
37+
], function(registerSuite) {
38+
39+
registerSuite({
40+
41+
name: 'Integration setup',
42+
43+
'Set up the page and send some events to request_recorder': function() {
44+
45+
return this.remote
46+
.get(require.toUrl('tests/pages/integration.html'))
47+
.waitForElementByCssSelector('body.loaded', 5000)
48+
.sleep(1000);
49+
}
50+
});
51+
});

tests/intern.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ define({
5252
{ browserName: 'safari', version: '7', platform: 'OS X 10.9' }
5353
],
5454

55-
maxConcurrency: 3,
55+
maxConcurrency: 1,
5656
useSauceConnect: true,
5757

5858
// Connection information for the remote WebDriver service.
@@ -66,7 +66,7 @@ define({
6666
loader: {},
6767

6868
// Functional test suite(s) to run in each browser once non-functional tests are completed
69-
functionalSuites: ['tests/functional/helpers','tests/functional/detectors'],
69+
functionalSuites: ['tests/integration/setup', 'tests/integration/integration', 'tests/functional/helpers','tests/functional/detectors'],
7070

7171
// A regular expression matching URLs to files that should not be included in code coverage analysis
7272
excludeInstrumentation: /^tests\//

tests/pages/integration.html

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>Integration test page</title>
5+
</head>
6+
<body>
7+
<p id="title">Page for sending requests to request_recorder</p>
8+
9+
<script>
10+
document.body.className += ' loaded';
11+
</script>
12+
13+
<script>
14+
15+
16+
;(function(p,l,o,w,i,n,g){if(!p[i]){p.GlobalSnowplowNamespace=p.GlobalSnowplowNamespace||[];
17+
p.GlobalSnowplowNamespace.push(i);p[i]=function(){(p[i].q=p[i].q||[]).push(arguments)
18+
};p[i].q=p[i].q||[];n=l.createElement(o);g=l.getElementsByTagName(o)[0];n.async=1;
19+
n.src=w;g.parentNode.insertBefore(n,g)}}(window,document,"script","./snowplow.js","snowplow"));
20+
21+
window.snowplow('newTracker', 'cf', 'snowplow.ngrok.com', {
22+
encodeBase64: true,
23+
appId: 'CFe23a',
24+
platform: 'mob'
25+
});
26+
27+
window.snowplow('setUserId', 'Malcolm');
28+
window.snowplow('trackPageView', 'My Title', [ // Auto-set page title; add page context
29+
{
30+
schema: "iglu:com.example_company/user/jsonschema/2-0-0",
31+
data: {
32+
userType: 'tester'
33+
}
34+
}
35+
]);
36+
37+
window.snowplow('trackStructEvent', 'Mixes', 'Play', 'MRC/fabric-0503-mix', '', '0.0');
38+
window.snowplow('trackUnstructEvent', {
39+
schema: 'iglu:com.acme_company/viewed_product/jsonschema/5-0-0',
40+
data: {
41+
productId: 'ASO01043'
42+
}
43+
});
44+
45+
var orderId = 'order-123';
46+
47+
window.snowplow('addTrans',
48+
orderId,
49+
'acme',
50+
'8000',
51+
'100',
52+
'50',
53+
'phoenix',
54+
'arizona',
55+
'USA',
56+
'JPY'
57+
);
58+
59+
// addItem might be called for each item in the shopping cart,
60+
// or not at all.
61+
window.snowplow('addItem',
62+
orderId,
63+
'1001',
64+
'Blue t-shirt',
65+
'clothing',
66+
'2000',
67+
'2',
68+
'JPY'
69+
);
70+
71+
window.snowplow('addItem',
72+
orderId,
73+
'1002',
74+
'Red shoes',
75+
'clothing',
76+
'4000',
77+
'1',
78+
'JPY'
79+
);
80+
81+
// trackTrans sends the transaction to Snowplow tracking servers.
82+
// Must be called last to commit the transaction.
83+
window.snowplow('trackTrans');
84+
</script>
85+
86+
</body>
87+
</html>

0 commit comments

Comments
 (0)