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

Commit 9c05c8d

Browse files
King Long Tsejuliofarah
andauthored
Adds basic end to end test (#154)
* Added basic end to end test that uses a test website to load analytics.js, clicks around, and captures the network traffic and compares cookies / local storage values. Saves captured network traffic to a staging directory for comparison against a reference later. Co-authored-by: Julio <[email protected]>
1 parent f7fc216 commit 9c05c8d

File tree

12 files changed

+2061
-34
lines changed

12 files changed

+2061
-34
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,7 @@ package-lock.json
44
junit-reports
55

66
build/
7-
.DS_Store
7+
.DS_Store
8+
9+
test-e2e/output
10+
test-e2e/staging

.npmignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
node_modules
44
test/**/*
55
lib/**/*
6+
test-e2e/**/*
7+
steps_file.ts
8+
steps.d.ts
69
.eslintrc
710
.gitignore
811
.nvmrc

HISTORY.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 3.13.6 / 2020-06-15
2+
3+
- test: test analytics.js from a test website
4+
15
# 3.13.5 / 2020-06-08
26

37
- refactor: improve typescript support

Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,14 @@ test-browser: build
8080
test: lint test-browser
8181
.PHONY: test
8282

83+
# Run e2e tests
84+
test-e2e:
85+
rm -rf ./test-e2e/output
86+
rm -rf ./test-e2e/staging
87+
mkdir ./test-e2e/staging
88+
npx codeceptjs run --steps
89+
.PHONY: test-e2e
90+
8391
release-test:
8492
sh .circleci/changelog-check.sh
8593
.PHONY: release-test

codecept.conf.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
const { setHeadlessWhen } = require('@codeceptjs/configure');
2+
3+
// turn on headless mode when running with HEADLESS=true environment variable
4+
// HEADLESS=true npx codecept run
5+
setHeadlessWhen(process.env.HEADLESS);
6+
7+
exports.config = {
8+
tests: './test-e2e/*.test.ts',
9+
output: './test-e2e/output',
10+
helpers: {
11+
Puppeteer: {
12+
url: 'http://www.library-test-site.com/',
13+
show: false,
14+
windowSize: '1200x900',
15+
args: ['--disable-web-security']
16+
},
17+
MockRequestHelper: {
18+
require: '@codeceptjs/mock-request',
19+
mode: 'record',
20+
recordIfMissing: true,
21+
recordFailedRequests: false,
22+
expiresIn: null,
23+
persisterOptions: {
24+
keepUnusedRequests: false,
25+
fs: {
26+
recordingsDir: './test-e2e/output'
27+
}
28+
}
29+
}
30+
},
31+
include: {
32+
I: './test-e2e/steps_file.ts'
33+
},
34+
bootstrap: null,
35+
mocha: {},
36+
name: 'analytics.js-core',
37+
plugins: {
38+
retryFailedStep: {
39+
enabled: true
40+
},
41+
screenshotOnFail: {
42+
enabled: true
43+
}
44+
}
45+
};

jsconfig.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"compilerOptions": {
3+
"allowJs": true
4+
}
5+
}

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@segment/analytics.js-core",
33
"author": "Segment <[email protected]>",
4-
"version": "3.13.5",
4+
"version": "3.13.6",
55
"description": "The hassle-free way to integrate analytics into any web application.",
66
"keywords": [
77
"analytics",
@@ -62,11 +62,13 @@
6262
"uuid": "^3.4.0"
6363
},
6464
"devDependencies": {
65+
"@codeceptjs/mock-request": "^0.3.0",
6566
"@segment/analytics.js-integration": "^3.2.1",
6667
"@segment/eslint-config": "^4.0.0",
6768
"@types/node": "^14.0.6",
6869
"browserify": "13.0.0",
6970
"browserify-istanbul": "^2.0.0",
71+
"codeceptjs": "^2.6.5",
7072
"codecov": "^3.0.2",
7173
"compat-trigger-event": "^1.0.0",
7274
"component-each": "^0.2.6",
@@ -95,6 +97,7 @@
9597
"phantomjs-prebuilt": "^2.1.7",
9698
"prettier-eslint-cli": "^4.7.1",
9799
"proclaim": "^3.4.1",
100+
"puppeteer": "^3.3.0",
98101
"sinon": "^1.7.3",
99102
"snyk": "^1.83.0",
100103
"ts-node": "^8.10.2",

test-e2e/ajs.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
Feature('AJS Bundle');
2+
3+
const assert = require('assert');
4+
const testSite = 'https://www.library-test-site.com';
5+
const testWriteKey = 'TEWEu8XrcMVejk8GOulbEx7rHGyuuijV';
6+
7+
Scenario(
8+
'User id is stored in cookies and local storage',
9+
async (I, testID) => {
10+
I.amOnPage(testSite);
11+
I.loadAJS(testWriteKey);
12+
13+
I.startRecording(testID);
14+
I.click('#page-home');
15+
I.click('#track-checkout-started');
16+
I.click('#identify-fathy');
17+
18+
await I.stopRecording(testID);
19+
20+
const userId = await I.grabCookie('ajs_user_id');
21+
assert.equal(userId.value, '%22fathy%22');
22+
23+
const lsUserId = await I.executeScript(() => {
24+
return localStorage.getItem('ajs_user_id');
25+
});
26+
assert.equal(lsUserId, `"fathy"`);
27+
}
28+
).injectDependencies({ testID: 'cookies-and-local-storage' });

test-e2e/steps.d.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/// <reference types='codeceptjs' />
2+
type steps_file = typeof import('./steps_file');
3+
4+
declare namespace CodeceptJS {
5+
interface SupportObject {
6+
I: CodeceptJS.I;
7+
}
8+
interface CallbackOrder {
9+
[0]: CodeceptJS.I;
10+
}
11+
interface Methods extends CodeceptJS.Puppeteer {}
12+
interface I extends ReturnType<steps_file> {}
13+
namespace Translation {
14+
interface Actions {}
15+
}
16+
}

test-e2e/steps_file.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
const fs = require('fs');
2+
// in this file you can append custom step methods to 'I' object
3+
4+
module.exports = function() {
5+
return actor({
6+
loadAJS: async function(testWriteKey) {
7+
this.fillField('writeKey', testWriteKey);
8+
this.click('Load');
9+
10+
// Wait for AJS to load
11+
this.waitForText(`loaded`, 5, '#status-msg');
12+
},
13+
14+
startRecording: function(testID) {
15+
this.startMocking();
16+
this.mockServer(server => {
17+
server.any('https://api.segment.io/*').recordingName(testID);
18+
});
19+
},
20+
21+
stopRecording: async function(testID) {
22+
await this.stopMocking();
23+
const dirs = fs.readdirSync('./test-e2e/output', { encoding: 'utf8' });
24+
let outputFilePath = '';
25+
dirs.forEach(dir => {
26+
if (dir.includes(testID)) {
27+
outputFilePath = `./test-e2e/output/${dir}/recording.har`;
28+
}
29+
});
30+
31+
if (outputFilePath.length == 0)
32+
throw new Error(`cannot find directory for ${testID}`);
33+
if (!fs.existsSync(outputFilePath)) {
34+
throw new Error(`cannot find HAR file for ${testID}`);
35+
}
36+
37+
const stagingFilePath = `./test-e2e/staging/${testID}.har`;
38+
39+
fs.renameSync(outputFilePath, stagingFilePath);
40+
41+
return stagingFilePath;
42+
}
43+
});
44+
};

0 commit comments

Comments
 (0)