@segment/analytics.js-integration-segmentio
Advanced tools
Comparing version 4.0.0 to 4.1.1
@@ -36,19 +36,7 @@ /* eslint-env node */ | ||
}, | ||
// FIXME(ndhoule): Bad IE7/8 support in testing packages make these fail | ||
// sl_ie_7: { | ||
// base: 'SauceLabs', | ||
// browserName: 'internet explorer', | ||
// version: '7' | ||
// }, | ||
// sl_ie_8: { | ||
// base: 'SauceLabs', | ||
// browserName: 'internet explorer', | ||
// version: '8' | ||
// }, | ||
// FIXME(): IE9 tests are failing pre-Browserification | ||
// sl_ie_9: { | ||
// base: 'SauceLabs', | ||
// browserName: 'internet explorer', | ||
// version: '9' | ||
// }, | ||
sl_ie_9: { | ||
base: 'SauceLabs', | ||
browserName: 'internet explorer', | ||
version: '9' | ||
}, | ||
sl_ie_10: { | ||
@@ -74,33 +62,39 @@ base: 'SauceLabs', | ||
if (!process.env.SAUCE_USERNAME || !process.env.SAUCE_ACCESS_KEY) { | ||
throw new Error('SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables are required but are missing'); | ||
throw new Error( | ||
'SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables are required but are missing' | ||
); | ||
} | ||
config.set({ | ||
browserDisconnectTolerance: 2, | ||
browserDisconnectTimeout: 30000, | ||
browserNoActivityTimeout: 30000, | ||
browserDisconnectTolerance: 1, | ||
browserDisconnectTimeout: 60000, | ||
browserNoActivityTimeout: 60000, | ||
singleRun: true, | ||
reporters: ['progress', 'junit', 'coverage'], | ||
concurrency: 2, | ||
browsers: ['PhantomJS'].concat(Object.keys(customLaunchers)), | ||
retryLimit: 5, | ||
customLaunchers: customLaunchers, | ||
reporters: ['spec', 'summary', 'junit'], | ||
specReporter: { | ||
suppressPassed: true | ||
}, | ||
junitReporter: { | ||
outputDir: process.env.TEST_REPORTS_DIR, | ||
outputDir: 'junit-reports', | ||
suite: require('./package.json').name | ||
}, | ||
browsers: ['PhantomJS'].concat(Object.keys(customLaunchers)), | ||
customLaunchers: customLaunchers, | ||
sauceLabs: { | ||
testName: require('./package.json').name | ||
}, | ||
coverageReporter: { | ||
reporters: [ | ||
{ type: 'lcov' } | ||
] | ||
} | ||
}); | ||
}; | ||
}; |
/* eslint-env node */ | ||
/* eslint-disable no-restricted-globals */ | ||
'use strict'; | ||
// 10 minutes | ||
var TEST_TIMEOUT = 10 * 60 * 1000; | ||
module.exports = function(config) { | ||
@@ -10,5 +12,7 @@ config.set({ | ||
], | ||
browsers: ['PhantomJS'], | ||
singleRun: true, | ||
middleware: ['server'], | ||
@@ -51,3 +55,3 @@ | ||
reporters: ['spec', 'coverage'], | ||
reporters: ['spec'], | ||
@@ -58,7 +62,8 @@ preprocessors: { | ||
browserNoActivityTimeout: TEST_TIMEOUT, | ||
client: { | ||
mocha: { | ||
grep: process.env.GREP, | ||
reporter: 'html', | ||
timeout: 10000 | ||
timeout: TEST_TIMEOUT | ||
} | ||
@@ -68,23 +73,5 @@ }, | ||
browserify: { | ||
debug: true, | ||
transform: [ | ||
[ | ||
'browserify-istanbul', | ||
{ | ||
instrumenterConfig: { | ||
embedSource: true | ||
} | ||
} | ||
] | ||
] | ||
}, | ||
coverageReporter: { | ||
reporters: [ | ||
{ type: 'text' }, | ||
{ type: 'html' }, | ||
{ type: 'json' } | ||
] | ||
debug: true | ||
} | ||
}); | ||
}; | ||
}; |
190
lib/index.js
@@ -64,2 +64,3 @@ 'use strict'; | ||
.option('deleteCrossDomainId', false) | ||
.option('saveCrossDomainIdInLocalStorage', false) | ||
.option('retryQueue', true) | ||
@@ -173,12 +174,2 @@ .option('addBundledMetadata', false) | ||
// Migrate from old cross domain id cookie names | ||
if (this.cookie('segment_cross_domain_id')) { | ||
this.cookie('seg_xid', this.cookie('segment_cross_domain_id')); | ||
this.cookie('seg_xid_fd', this.cookie('segment_cross_domain_id_from_domain')); | ||
this.cookie('seg_xid_ts', this.cookie('segment_cross_domain_id_timestamp')); | ||
this.cookie('segment_cross_domain_id', null); | ||
this.cookie('segment_cross_domain_id_from_domain', null); | ||
this.cookie('segment_cross_domain_id_timestamp', null); | ||
} | ||
// Delete cross domain identifiers. | ||
@@ -289,3 +280,3 @@ this.deleteCrossDomainIdIfNeeded(); | ||
if (!ctx.library) ctx.library = { name: 'analytics.js', version: this.analytics.VERSION }; | ||
var crossDomainId = this.cookie('seg_xid'); | ||
var crossDomainId = this.getCachedCrossDomainId(); | ||
if (crossDomainId && this.isCrossDomainAnalyticsEnabled()) { | ||
@@ -446,2 +437,3 @@ if (!ctx.traits) { | ||
if (!this.isCrossDomainAnalyticsEnabled()) { | ||
// Callback is only provided in tests. | ||
if (callback) { | ||
@@ -452,60 +444,122 @@ callback('crossDomainId not enabled', null); | ||
} | ||
if (!this.cookie('seg_xid')) { | ||
var self = this; | ||
var writeKey = this.options.apiKey; | ||
// Exclude the current domain from the list of servers we're querying | ||
var currentTld = getTld(window.location.hostname); | ||
var domains = []; | ||
for (var i=0; i<this.options.crossDomainIdServers.length; i++) { | ||
var domain = this.options.crossDomainIdServers[i]; | ||
if (getTld(domain) !== currentTld) { | ||
domains.push(domain); | ||
} | ||
var cachedCrossDomainId = this.getCachedCrossDomainId(); | ||
if (cachedCrossDomainId) { | ||
// Callback is only provided in tests. | ||
if (callback) { | ||
callback(null, { | ||
crossDomainId: cachedCrossDomainId | ||
}); | ||
} | ||
return; | ||
} | ||
getCrossDomainIdFromServerList(domains, writeKey, function(err, res) { | ||
if (err) { | ||
// We optimize for no conflicting xid as much as possible. So bail out if there is an | ||
// error and we cannot be sure that xid does not exist on any other domains | ||
if (callback) { | ||
callback(err, null); | ||
} | ||
return; | ||
} | ||
var crossDomainId = null; | ||
var fromDomain = null; | ||
if (res) { | ||
crossDomainId = res.id; | ||
fromDomain = res.domain; | ||
} else { | ||
crossDomainId = uuid(); | ||
fromDomain = window.location.hostname; | ||
} | ||
var currentTimeMillis = (new Date()).getTime(); | ||
self.cookie('seg_xid', crossDomainId); | ||
// Not actively used. Saving for future conflict resolution purposes | ||
self.cookie('seg_xid_fd', fromDomain); | ||
self.cookie('seg_xid_ts', currentTimeMillis); | ||
self.analytics.identify({ | ||
crossDomainId: crossDomainId | ||
}); | ||
var self = this; | ||
var writeKey = this.options.apiKey; | ||
// Exclude the current domain from the list of servers we're querying | ||
var currentTld = getTld(window.location.hostname); | ||
var domains = []; | ||
for (var i = 0; i < this.options.crossDomainIdServers.length; i++) { | ||
var domain = this.options.crossDomainIdServers[i]; | ||
if (getTld(domain) !== currentTld) { | ||
domains.push(domain); | ||
} | ||
} | ||
getCrossDomainIdFromServerList(domains, writeKey, function(err, res) { | ||
if (err) { | ||
// Callback is only provided in tests. | ||
if (callback) { | ||
callback(null, { | ||
crossDomainId: crossDomainId, | ||
fromDomain: fromDomain, | ||
timestamp: currentTimeMillis | ||
}); | ||
callback(err, null); | ||
} | ||
// We optimize for no conflicting xid as much as possible. So bail out if there is an | ||
// error and we cannot be sure that xid does not exist on any other domains. | ||
return; | ||
} | ||
var crossDomainId = null; | ||
var fromDomain = null; | ||
if (res) { | ||
crossDomainId = res.id; | ||
fromDomain = res.domain; | ||
} else { | ||
crossDomainId = uuid(); | ||
fromDomain = window.location.hostname; | ||
} | ||
self.saveCrossDomainId(crossDomainId); | ||
self.analytics.identify({ | ||
crossDomainId: crossDomainId | ||
}); | ||
// Callback is only provided in tests. | ||
if (callback) { | ||
callback(null, { | ||
crossDomainId: crossDomainId, | ||
fromDomain: fromDomain | ||
}); | ||
} | ||
}); | ||
}; | ||
/** | ||
* getCachedCrossDomainId returns the cross domain identifier stored on the client based on the `saveCrossDomainIdInLocalStorage` flag. | ||
* If `saveCrossDomainIdInLocalStorage` is false, it reads it from the `seg_xid` cookie. | ||
* If `saveCrossDomainIdInLocalStorage` is true, it reads it from the `seg_xid` key in localStorage. | ||
* | ||
* @return {string} crossDomainId | ||
*/ | ||
Segment.prototype.getCachedCrossDomainId = function() { | ||
if (this.options.saveCrossDomainIdInLocalStorage) { | ||
return localstorage('seg_xid'); | ||
} | ||
return this.cookie('seg_xid'); | ||
}; | ||
/** | ||
* saveCrossDomainId saves the cross domain identifier. The implementation differs based on the `saveCrossDomainIdInLocalStorage` flag. | ||
* If `saveCrossDomainIdInLocalStorage` is false, it saves it as the `seg_xid` cookie. | ||
* If `saveCrossDomainIdInLocalStorage` is true, it saves it to localStorage (so that it can be accessed on the current domain) | ||
* and as a httpOnly cookie (so that can it can be provided to other domains). | ||
* | ||
* @api private | ||
*/ | ||
Segment.prototype.saveCrossDomainId = function(crossDomainId) { | ||
if (!this.options.saveCrossDomainIdInLocalStorage) { | ||
this.cookie('seg_xid', crossDomainId); | ||
return; | ||
} | ||
var self = this; | ||
// Save the cookie by making a request to the xid server for the current domain. | ||
var currentTld = getTld(window.location.hostname); | ||
for (var i = 0; i < this.options.crossDomainIdServers.length; i++) { | ||
var domain = this.options.crossDomainIdServers[i]; | ||
if (getTld(domain) === currentTld) { | ||
var writeKey = this.options.apiKey; | ||
var url = 'https://' + domain + '/v1/saveId?writeKey=' + writeKey + '&xid=' + crossDomainId; | ||
httpGet(url, function(err, res) { | ||
if (err) { | ||
self.debug('could not save id on %O, received %O', url, [err, res]); | ||
return; | ||
} | ||
localstorage('seg_xid', crossDomainId); | ||
}); | ||
return; | ||
} | ||
} | ||
}; | ||
/** | ||
* Deletes any state persisted by cross domain analytics. | ||
* * seg_xid (and metadata) from cookies | ||
* * seg_xid from localStorage | ||
* * crossDomainId from traits in localStorage | ||
* | ||
* The deletion logic is run only if deletion is enabled for this project, and | ||
* when either the seg_xid cookie or crossDomainId localStorage trait exists. | ||
* The deletion logic is run only if deletion is enabled for this project, and only | ||
* deletes the data that actually exists. | ||
* | ||
@@ -527,2 +581,7 @@ * @api private | ||
// Delete the xid from localStorage if it exists. | ||
if (localstorage('seg_xid')) { | ||
localstorage('seg_xid', null); | ||
} | ||
// Delete the crossDomainId trait in localStorage if it exists. | ||
@@ -619,2 +678,23 @@ if (this.analytics.user().traits().crossDomainId) { | ||
/** | ||
* get makes a get request to the given URL. | ||
* @param {string} url | ||
* @param {function} callback => err, response | ||
*/ | ||
function httpGet(url, callback) { | ||
var xhr = new XMLHttpRequest(); | ||
xhr.open('GET', url, true); | ||
xhr.withCredentials = true; | ||
xhr.onreadystatechange = function() { | ||
if (xhr.readyState === XMLHttpRequest.DONE) { | ||
if (xhr.status >= 200 && xhr.status < 300) { | ||
callback(null, xhr.responseText); | ||
} else { | ||
callback(xhr.statusText || xhr.responseText || 'Unknown Error', null); | ||
} | ||
} | ||
}; | ||
xhr.send(); | ||
} | ||
/** | ||
* getTld | ||
@@ -621,0 +701,0 @@ * Get domain.com from subdomain.domain.com, etc. |
{ | ||
"name": "@segment/analytics.js-integration-segmentio", | ||
"description": "The Segmentio analytics.js integration.", | ||
"version": "4.0.0", | ||
"version": "4.1.1", | ||
"keywords": [ | ||
@@ -13,3 +13,6 @@ "analytics.js", | ||
"scripts": { | ||
"test": "make test" | ||
"test": "make test", | ||
"np": "np --no-publish", | ||
"cz": "git-cz", | ||
"commitmsg": "commitlint -E GIT_PARAMS" | ||
}, | ||
@@ -44,2 +47,4 @@ "repository": { | ||
"devDependencies": { | ||
"@commitlint/cli": "^8.0.0", | ||
"@commitlint/config-conventional": "^8.0.0", | ||
"@segment/analytics.js-core": "^3.8.0", | ||
@@ -51,2 +56,6 @@ "@segment/analytics.js-integration-tester": "^2.0.0", | ||
"browserify-istanbul": "^2.0.0", | ||
"codecov": "^3.5.0", | ||
"commitizen": "^3.1.1", | ||
"commitlint-circle": "^1.0.0", | ||
"cz-conventional-changelog": "^2.1.0", | ||
"eslint": "^2.9.0", | ||
@@ -67,2 +76,3 @@ "eslint-plugin-mocha": "^2.2.0", | ||
"mocha": "^2.2.5", | ||
"np": "^3.0.4", | ||
"npm-check": "^5.2.1", | ||
@@ -72,4 +82,23 @@ "phantomjs-prebuilt": "^2.1.7", | ||
"sinon": "^1.17.4", | ||
"snyk": "^1.177.0", | ||
"watchify": "^3.7.0" | ||
}, | ||
"commitlint": { | ||
"extends": [ | ||
"@commitlint/config-conventional" | ||
] | ||
}, | ||
"lint-staged": { | ||
"linters": { | ||
"*.{js,json,md}": [ | ||
"prettier-eslint --write", | ||
"git add" | ||
] | ||
} | ||
}, | ||
"config": { | ||
"commitizen": { | ||
"path": "cz-conventional-changelog" | ||
} | ||
} | ||
} |
@@ -47,2 +47,5 @@ 'use strict'; | ||
resetCookies(); | ||
if (window.localStorage) { | ||
window.localStorage.clear(); | ||
} | ||
}); | ||
@@ -54,2 +57,5 @@ | ||
resetCookies(); | ||
if (window.localStorage) { | ||
window.localStorage.clear(); | ||
} | ||
segment.reset(); | ||
@@ -888,10 +894,2 @@ sandbox(); | ||
it('should migrate cookies from old to new name', function() { | ||
segment.cookie('segment_cross_domain_id', 'xid-test-1'); | ||
segment.initialize(); | ||
analytics.assert(segment.cookie('segment_cross_domain_id') == null); | ||
analytics.assert(segment.cookie('seg_xid') === 'xid-test-1'); | ||
}); | ||
it('should not crash with invalid config', function() { | ||
@@ -911,145 +909,233 @@ segment.options.crossDomainIdServers = undefined; | ||
it('should generate xid locally if there is only one (current hostname) server', function() { | ||
it('should use cached cross domain identifier from LS when saveCrossDomainIdInLocalStorage is true', function() { | ||
segment.options.crossDomainIdServers = [ | ||
'localhost' | ||
]; | ||
segment.options.saveCrossDomainIdInLocalStorage = true; | ||
store('seg_xid', 'test_xid_cache_ls'); | ||
var res = null; | ||
segment.retrieveCrossDomainId(function(err, response) { | ||
var err = null; | ||
segment.retrieveCrossDomainId(function(error, response) { | ||
res = response; | ||
err = error; | ||
}); | ||
var identify = segment.onidentify.args[0]; | ||
var crossDomainId = identify[0].traits().crossDomainId; | ||
analytics.assert(crossDomainId); | ||
analytics.assert(res.crossDomainId === crossDomainId); | ||
analytics.assert(res.fromDomain === 'localhost'); | ||
assert.isNull(err); | ||
assert.deepEqual(res, { | ||
crossDomainId: 'test_xid_cache_ls' | ||
}); | ||
}); | ||
it('should obtain crossDomainId', function() { | ||
it('should use cached cross domain identifier from cookies when saveCrossDomainIdInLocalStorage is false', function() { | ||
segment.options.crossDomainIdServers = [ | ||
'localhost' | ||
]; | ||
segment.options.saveCrossDomainIdInLocalStorage = false; | ||
segment.cookie('seg_xid', 'test_xid_cache_cookie'); | ||
var res = null; | ||
segment.retrieveCrossDomainId(function(err, response) { | ||
var err = null; | ||
segment.retrieveCrossDomainId(function(error, response) { | ||
res = response; | ||
err = error; | ||
}); | ||
server.respondWith('GET', 'https://xid.domain2.com/v1/id/' + segment.options.apiKey, [ | ||
200, | ||
{ 'Content-Type': 'application/json' }, | ||
'{ "id": "xdomain-id-1" }' | ||
]); | ||
server.respond(); | ||
var identify = segment.onidentify.args[0]; | ||
analytics.assert(identify[0].traits().crossDomainId === 'xdomain-id-1'); | ||
analytics.assert(res.crossDomainId === 'xdomain-id-1'); | ||
analytics.assert(res.fromDomain === 'xid.domain2.com'); | ||
assert.isNull(err); | ||
assert.deepEqual(res, { | ||
crossDomainId: 'test_xid_cache_cookie' | ||
}); | ||
}); | ||
it('should generate crossDomainId if no server has it', function() { | ||
var res = null; | ||
segment.retrieveCrossDomainId(function(err, response) { | ||
res = response; | ||
describe('getCachedCrossDomainId', function() { | ||
it('should return identifiers from localstorage when saveCrossDomainIdInLocalStorage is true', function() { | ||
store('seg_xid', 'test_xid_cache_ls'); | ||
segment.cookie('seg_xid', 'test_xid_cache_cookie'); | ||
segment.options.saveCrossDomainIdInLocalStorage = true; | ||
assert.equal(segment.getCachedCrossDomainId(), 'test_xid_cache_ls'); | ||
}); | ||
server.respondWith('GET', 'https://xid.domain2.com/v1/id/' + segment.options.apiKey, [ | ||
200, | ||
{ 'Content-Type': 'application/json' }, | ||
'{ "id": null }' | ||
]); | ||
server.respondWith('GET', 'https://userdata.example1.com/v1/id/' + segment.options.apiKey, [ | ||
200, | ||
{ 'Content-Type': 'application/json' }, | ||
'{ "id": null }' | ||
]); | ||
server.respond(); | ||
it('should return identifiers from localstorage when saveCrossDomainIdInLocalStorage is true', function() { | ||
store('seg_xid', 'test_xid_cache_ls'); | ||
segment.cookie('seg_xid', 'test_xid_cache_cookie'); | ||
var identify = segment.onidentify.args[0]; | ||
var crossDomainId = identify[0].traits().crossDomainId; | ||
analytics.assert(crossDomainId); | ||
segment.options.saveCrossDomainIdInLocalStorage = false; | ||
analytics.assert(res.crossDomainId === crossDomainId); | ||
analytics.assert(res.fromDomain === 'localhost'); | ||
assert.equal(segment.getCachedCrossDomainId(), 'test_xid_cache_cookie'); | ||
}); | ||
}); | ||
it('should bail if all servers error', function() { | ||
var err = null; | ||
var res = null; | ||
segment.retrieveCrossDomainId(function(error, response) { | ||
err = error; | ||
res = response; | ||
}); | ||
var cases = { | ||
'saveCrossDomainIdInLocalStorage true': true, | ||
'saveCrossDomainIdInLocalStorage false': false | ||
}; | ||
server.respondWith('GET', 'https://xid.domain2.com/v1/id/' + segment.options.apiKey, [ | ||
500, | ||
{ 'Content-Type': 'application/json' }, | ||
'' | ||
]); | ||
server.respondWith('GET', 'https://userdata.example1.com/v1/id/' + segment.options.apiKey, [ | ||
500, | ||
{ 'Content-Type': 'application/json' }, | ||
'' | ||
]); | ||
server.respond(); | ||
for (var scenario in cases) { | ||
if (!cases.hasOwnProperty(scenario)) { | ||
continue; | ||
} | ||
var identify = segment.onidentify.args[0]; | ||
analytics.assert(!identify); | ||
analytics.assert(!res); | ||
analytics.assert(err === 'Internal Server Error'); | ||
}); | ||
describe('with ' + scenario, function() { | ||
it('should generate xid locally if there is only one (current hostname) server', function() { | ||
segment.options.crossDomainIdServers = [ | ||
'localhost' | ||
]; | ||
segment.options.saveCrossDomainIdInLocalStorage = cases[scenario]; | ||
it('should bail if some servers fail and others have no xid', function() { | ||
var err = null; | ||
var res = null; | ||
segment.retrieveCrossDomainId(function(error, response) { | ||
err = error; | ||
res = response; | ||
}); | ||
var res = null; | ||
segment.retrieveCrossDomainId(function(err, response) { | ||
res = response; | ||
}); | ||
server.respondWith('GET', 'https://xid.domain2.com/v1/id/' + segment.options.apiKey, [ | ||
400, | ||
{ 'Content-Type': 'application/json' }, | ||
'' | ||
]); | ||
server.respondWith('GET', 'https://userdata.example1.com/v1/id/' + segment.options.apiKey, [ | ||
200, | ||
{ 'Content-Type': 'application/json' }, | ||
'{ "id": null }' | ||
]); | ||
server.respond(); | ||
var identify = segment.onidentify.args[0]; | ||
var crossDomainId = identify[0].traits().crossDomainId; | ||
analytics.assert(crossDomainId); | ||
var identify = segment.onidentify.args[0]; | ||
analytics.assert(!identify); | ||
analytics.assert(!res); | ||
analytics.assert(err === 'Bad Request'); | ||
}); | ||
analytics.assert(res.crossDomainId === crossDomainId); | ||
analytics.assert(res.fromDomain === 'localhost'); | ||
it('should succeed even if one server fails', function() { | ||
var err = null; | ||
var res = null; | ||
segment.retrieveCrossDomainId(function(error, response) { | ||
err = error; | ||
res = response; | ||
}); | ||
assert.equal(segment.getCachedCrossDomainId(), crossDomainId); | ||
}); | ||
server.respondWith('GET', 'https://xid.domain2.com/v1/id/' + segment.options.apiKey, [ | ||
500, | ||
{ 'Content-Type': 'application/json' }, | ||
'' | ||
]); | ||
server.respondWith('GET', 'https://userdata.example1.com/v1/id/' + segment.options.apiKey, [ | ||
200, | ||
{ 'Content-Type': 'application/json' }, | ||
'{ "id": "xidxid" }' | ||
]); | ||
server.respond(); | ||
it('should obtain crossDomainId', function() { | ||
var res = null; | ||
segment.retrieveCrossDomainId(function(err, response) { | ||
res = response; | ||
}); | ||
server.respondWith('GET', 'https://xid.domain2.com/v1/id/' + segment.options.apiKey, [ | ||
200, | ||
{ 'Content-Type': 'application/json' }, | ||
'{ "id": "xdomain-id-1" }' | ||
]); | ||
server.respond(); | ||
var identify = segment.onidentify.args[0]; | ||
analytics.assert(identify[0].traits().crossDomainId === 'xidxid'); | ||
var identify = segment.onidentify.args[0]; | ||
analytics.assert(identify[0].traits().crossDomainId === 'xdomain-id-1'); | ||
analytics.assert(res.crossDomainId === 'xidxid'); | ||
analytics.assert(res.fromDomain === 'userdata.example1.com'); | ||
analytics.assert(!err); | ||
}); | ||
analytics.assert(res.crossDomainId === 'xdomain-id-1'); | ||
analytics.assert(res.fromDomain === 'xid.domain2.com'); | ||
assert.equal(segment.getCachedCrossDomainId(), 'xdomain-id-1'); | ||
}); | ||
it('should generate crossDomainId if no server has it', function() { | ||
var res = null; | ||
segment.retrieveCrossDomainId(function(err, response) { | ||
res = response; | ||
}); | ||
server.respondWith('GET', 'https://xid.domain2.com/v1/id/' + segment.options.apiKey, [ | ||
200, | ||
{ 'Content-Type': 'application/json' }, | ||
'{ "id": null }' | ||
]); | ||
server.respondWith('GET', 'https://userdata.example1.com/v1/id/' + segment.options.apiKey, [ | ||
200, | ||
{ 'Content-Type': 'application/json' }, | ||
'{ "id": null }' | ||
]); | ||
server.respond(); | ||
var identify = segment.onidentify.args[0]; | ||
var crossDomainId = identify[0].traits().crossDomainId; | ||
analytics.assert(crossDomainId); | ||
analytics.assert(res.crossDomainId === crossDomainId); | ||
analytics.assert(res.fromDomain === 'localhost'); | ||
assert.equal(segment.getCachedCrossDomainId(), crossDomainId); | ||
}); | ||
it('should bail if all servers error', function() { | ||
var err = null; | ||
var res = null; | ||
segment.retrieveCrossDomainId(function(error, response) { | ||
err = error; | ||
res = response; | ||
}); | ||
server.respondWith('GET', 'https://xid.domain2.com/v1/id/' + segment.options.apiKey, [ | ||
500, | ||
{ 'Content-Type': 'application/json' }, | ||
'' | ||
]); | ||
server.respondWith('GET', 'https://userdata.example1.com/v1/id/' + segment.options.apiKey, [ | ||
500, | ||
{ 'Content-Type': 'application/json' }, | ||
'' | ||
]); | ||
server.respond(); | ||
var identify = segment.onidentify.args[0]; | ||
analytics.assert(!identify); | ||
analytics.assert(!res); | ||
analytics.assert(err === 'Internal Server Error'); | ||
assert.equal(segment.getCachedCrossDomainId(), null); | ||
}); | ||
it('should bail if some servers fail and others have no xid', function() { | ||
var err = null; | ||
var res = null; | ||
segment.retrieveCrossDomainId(function(error, response) { | ||
err = error; | ||
res = response; | ||
}); | ||
server.respondWith('GET', 'https://xid.domain2.com/v1/id/' + segment.options.apiKey, [ | ||
400, | ||
{ 'Content-Type': 'application/json' }, | ||
'' | ||
]); | ||
server.respondWith('GET', 'https://userdata.example1.com/v1/id/' + segment.options.apiKey, [ | ||
200, | ||
{ 'Content-Type': 'application/json' }, | ||
'{ "id": null }' | ||
]); | ||
server.respond(); | ||
var identify = segment.onidentify.args[0]; | ||
analytics.assert(!identify); | ||
analytics.assert(!res); | ||
analytics.assert(err === 'Bad Request'); | ||
assert.equal(segment.getCachedCrossDomainId(), null); | ||
}); | ||
it('should succeed even if one server fails', function() { | ||
var err = null; | ||
var res = null; | ||
segment.retrieveCrossDomainId(function(error, response) { | ||
err = error; | ||
res = response; | ||
}); | ||
server.respondWith('GET', 'https://xid.domain2.com/v1/id/' + segment.options.apiKey, [ | ||
500, | ||
{ 'Content-Type': 'application/json' }, | ||
'' | ||
]); | ||
server.respondWith('GET', 'https://userdata.example1.com/v1/id/' + segment.options.apiKey, [ | ||
200, | ||
{ 'Content-Type': 'application/json' }, | ||
'{ "id": "xidxid" }' | ||
]); | ||
server.respond(); | ||
var identify = segment.onidentify.args[0]; | ||
analytics.assert(identify[0].traits().crossDomainId === 'xidxid'); | ||
analytics.assert(res.crossDomainId === 'xidxid'); | ||
analytics.assert(res.fromDomain === 'userdata.example1.com'); | ||
analytics.assert(!err); | ||
assert.equal(segment.getCachedCrossDomainId(), 'xidxid'); | ||
}); | ||
}); | ||
} | ||
describe('isCrossDomainAnalyticsEnabled', function() { | ||
@@ -1128,2 +1214,4 @@ it('should return false when crossDomainIdServers is undefined', function() { | ||
segment.cookie('seg_xid_fd', 'test_xid_fd'); | ||
store('seg_xid', 'test_xid'); | ||
analytics.identify({ | ||
@@ -1138,2 +1226,3 @@ crossDomainId: 'test_xid' | ||
assert.equal(segment.cookie('seg_xid_fd'), null); | ||
assert.equal(store('seg_xid'), null); | ||
assert.equal(analytics.user().traits().crossDomainId, null); | ||
@@ -1193,5 +1282,2 @@ }); | ||
xhr = sinon.useFakeXMLHttpRequest(); | ||
if (window.localStorage) { | ||
window.localStorage.clear(); | ||
} | ||
analytics.once('ready', done); | ||
@@ -1198,0 +1284,0 @@ segment.options.retryQueue = true; |
Sorry, the diff of this file is not supported yet
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
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 1 instance in 1 package
440683
16
1942
2
0
34