Comparing version 0.6.0 to 0.6.1
{ | ||
"extends": "standard", | ||
"parser": "babel-eslint", | ||
"plugins": [ | ||
@@ -4,0 +5,0 @@ "standard" |
@@ -24,6 +24,10 @@ 'use strict'; | ||
console.log('Pushing "'+packageName+'" version '+packageVersion+' to S3') | ||
push(packageName,packageVersion,86400) | ||
push(packageName,semver.major(packageVersion)+'.'+semver.minor(packageVersion),3600) | ||
push(packageName,semver.major(packageVersion),3600) | ||
if(process.env.PUSH_CDN === "true"){ | ||
console.log('Pushing "'+packageName+'" version '+packageVersion+' to S3') | ||
push(packageName,packageVersion,86400) | ||
push(packageName,semver.major(packageVersion)+'.'+semver.minor(packageVersion),3600) | ||
push(packageName,semver.major(packageVersion),3600) | ||
} | ||
else { | ||
console.log('PUSH_CDN is not set to "true" will do nothing. To fix: export PUSH_CDN=true') | ||
} |
@@ -6,2 +6,4 @@ 'use strict'; | ||
}); | ||
exports.fetch = fetch; | ||
exports.createFetch = createFetch; | ||
// function createXHR() { | ||
@@ -18,3 +20,3 @@ // var xhr = new XMLHttpRequest(); | ||
var fetch = exports.fetch = function fetch(token, url, endpoint, context) { | ||
function fetch(token, url, endpoint, context) { | ||
var _ref = arguments.length <= 4 || arguments[4] === undefined ? { method: 'GET', body: null } : arguments[4]; | ||
@@ -28,3 +30,3 @@ | ||
req.onerror = function (event) { | ||
req.onerror = function () { | ||
reject({ | ||
@@ -42,3 +44,3 @@ code: 'AJAX_ERROR', | ||
req.ontimeout = function (event) { | ||
req.ontimeout = function () { | ||
reject({ | ||
@@ -133,2 +135,5 @@ code: 'AJAX_ERROR', | ||
if (context) { | ||
if (context.locale) { | ||
req.setRequestHeader('Accept-Language', context.locale); | ||
} | ||
req.setRequestHeader('Context', window.btoa(JSON.stringify(context))); | ||
@@ -144,5 +149,5 @@ } | ||
}); | ||
}; | ||
} | ||
var createFetch = exports.createFetch = function createFetch(token, url, endpoint, context) { | ||
function createFetch(token, url, endpoint, context) { | ||
var _ref2 = arguments.length <= 4 || arguments[4] === undefined ? { method: 'GET', body: null } : arguments[4]; | ||
@@ -156,2 +161,2 @@ | ||
}; | ||
}; | ||
} |
@@ -11,2 +11,3 @@ 'use strict'; | ||
/* eslint no-console: 0 */ | ||
exports.default = { | ||
@@ -13,0 +14,0 @@ authenticateWithCredentials: function authenticateWithCredentials(client_id, client_secret, callback) { |
@@ -7,8 +7,8 @@ "use strict"; | ||
exports.default = { | ||
"version": "0.6.0", | ||
"version": "0.6.1", | ||
"git": { | ||
"short": "882ac0e", | ||
"long": "882ac0e8359efc79596588aada40514b6663d23c", | ||
"short": "f554ec1", | ||
"long": "f554ec165f462668954cf9fb6a3baaa0898ebdd6", | ||
"branch": "master" | ||
} | ||
}; |
@@ -5,10 +5,2 @@ 'use strict'; | ||
// This module contains polyfills installed in the global scope. | ||
// Polyfills are not final, we may, or may not remove them from the global scope, | ||
// and we may use a more complete polyfill, such as core.js | ||
// install Promise polyfill globally | ||
// String polyfills | ||
@@ -25,4 +17,10 @@ if (!String.prototype.endsWith) { | ||
}; | ||
} | ||
} // This module contains polyfills installed in the global scope. | ||
// Polyfills are not final, we may, or may not remove them from the global scope, | ||
// and we may use a more complete polyfill, such as core.js | ||
// install Promise polyfill globally | ||
if (!String.prototype.startsWith) { | ||
@@ -29,0 +27,0 @@ String.prototype.startsWith = function (searchString, position) { |
@@ -7,6 +7,6 @@ 'use strict'; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; | ||
exports.default = function (token, endpoint) { | ||
@@ -40,28 +40,44 @@ var currentToken = token; | ||
// handle paginated data | ||
if (data && data.items) { | ||
// merge items into entityCache | ||
data.items = data.items.map(function (item) { | ||
if (item.url) { | ||
item = deepMerge(entityCache[item.url], item); | ||
entityCache[item.url] = item; | ||
entityToResource[item.url] = mergeIntoArray(entityToResource[item.url], resource); | ||
} | ||
return item; | ||
}); | ||
} else { | ||
// merge into entityCache | ||
if (data && data.url) { | ||
cached = deepMerge(entityCache[data.url], data); | ||
entityCache[data.url] = cached; | ||
entityToResource[data.url] = mergeIntoArray(entityToResource[data.url], resource); | ||
// merge items into entityCache | ||
Object.keys(data).forEach(function (key) { | ||
if (Array.isArray(data[key])) { | ||
data[key] = data[key].map(function (item) { | ||
if (item && item.url) { | ||
item = deepMerge(entityCache[item.url], item); | ||
// resolve connections with related domain objects | ||
item = mergeRelations(item); | ||
// domain specific merge (bid/ask) | ||
item = mergeDomain(item); | ||
entityCache[item.url] = item; | ||
entityToResource[item.url] = mergeIntoArray(entityToResource[item.url], resource); | ||
} | ||
return item; | ||
}); | ||
} else if (data[key] && data[key].url) { | ||
var item = data[key]; | ||
item = deepMerge(entityCache[item.url], item); | ||
// resolve connections with related domain objects | ||
item = mergeRelations(item); | ||
// domain specific merge (bid/ask) | ||
item = mergeDomain(item); | ||
entityCache[item.url] = item; | ||
entityToResource[item.url] = mergeIntoArray(entityToResource[item.url], resource); | ||
} | ||
}); | ||
// merge into entityCache | ||
if (data && data.url) { | ||
cached = deepMerge(entityCache[data.url], data); | ||
entityCache[data.url] = cached; | ||
entityToResource[data.url] = mergeIntoArray(entityToResource[data.url], resource); | ||
} | ||
// TODO: below must be done also for items in paginated responses | ||
// TODO: below must be done also for items in paginated responses | ||
// resolve connections with related domain objects | ||
cached = mergeRelations(cached); | ||
// resolve connections with related domain objects | ||
cached = mergeRelations(cached); | ||
// domain specific merge (bid/ask) | ||
cached = mergeDomain(cached); | ||
} | ||
// domain specific merge (bid/ask) | ||
cached = mergeDomain(cached); | ||
@@ -87,2 +103,4 @@ // merge into resourceCache | ||
entityCache[obj[field].url] = obj[field]; | ||
} else { | ||
entityCache[obj[field].url] = deepMerge(entityCache[obj[field].url], obj[field]); | ||
} | ||
@@ -95,2 +113,4 @@ obj[field] = cached || obj[field]; | ||
} | ||
} else if (_typeof(obj[field]) === 'object') { | ||
mergeRelations(obj[field]); | ||
} | ||
@@ -100,2 +120,17 @@ } | ||
// example /listings/848/quotes -> /listing/848 | ||
var parentUrl = obj && (obj._parent || obj.url); | ||
if (parentUrl) { | ||
(function () { | ||
var root = entityCache[parentUrl]; | ||
if (root && root.url) { | ||
Object.keys(root).forEach(function (key) { | ||
if (root[key].url === obj.url) { | ||
root[key] = obj; | ||
} | ||
}); | ||
} | ||
})(); | ||
} | ||
return obj; | ||
@@ -185,3 +220,49 @@ }; | ||
notifySubscribers: function notifySubscribers(url, called, err) { | ||
var root = entityCache[url]; | ||
if (root && root.url) { | ||
// notify all subscribers for the root entity itself | ||
var resources = entityToResource[root.url]; | ||
if (resources) { | ||
resources.forEach(function (r) { | ||
var response = resourceCache[r]; | ||
var subscriptions = resourceToSubscription[r]; | ||
if (subscriptions) { | ||
subscriptions.forEach(function (s) { | ||
if (!called[s.id]) { | ||
s.callback(err, response, s.unsubscribeFn); | ||
called[s.id] = true; | ||
} | ||
}); | ||
} | ||
}); | ||
} | ||
// next we traverse the root object looking for references to entities | ||
// (fields containing object with .url fields) | ||
// for each reference found we notify any subscribers | ||
Object.keys(root).forEach(function (field) { | ||
if (root[field] && root[field].url) { | ||
var _resources = entityToResource[root[field].url]; | ||
if (_resources) { | ||
_resources.forEach(function (resource) { | ||
var subscriptions = resourceToSubscription[resource]; | ||
if (subscriptions) { | ||
subscriptions.forEach(function (subscription) { | ||
if (!called[subscription.id]) { | ||
subscription.callback(err, resourceCache[resource], subscription.unsubscribeFn); | ||
called[subscription.id] = true; | ||
} | ||
}); | ||
} | ||
}); | ||
} | ||
} | ||
}); | ||
} | ||
}, | ||
publish: function publish(resource, data, err) { | ||
var _this = this; | ||
// on errors, notify all subscriptions *only* for original resource | ||
@@ -225,45 +306,3 @@ if (err) { | ||
if (rootEntity) { | ||
(function () { | ||
var root = entityCache[rootEntity]; | ||
if (root && root.url) { | ||
// notify all subscribers for the root entity itself | ||
var resources = entityToResource[root.url]; | ||
if (resources) { | ||
resources.forEach(function (r) { | ||
var response = resourceCache[r]; | ||
var subscriptions = resourceToSubscription[r]; | ||
if (subscriptions) { | ||
subscriptions.forEach(function (s) { | ||
if (!called[s.id]) { | ||
s.callback(err, response, s.unsubscribeFn); | ||
called[s.id] = true; | ||
} | ||
}); | ||
} | ||
}); | ||
} | ||
// next we traverse the root object looking for references to entities | ||
// (fields containing object with .url fields) | ||
// for each reference found we notify any subscribers | ||
Object.keys(root).forEach(function (field) { | ||
if (root[field].url) { | ||
var _resources = entityToResource[root[field].url]; | ||
if (_resources) { | ||
_resources.forEach(function (resource) { | ||
var subscriptions = resourceToSubscription[resource]; | ||
if (subscriptions) { | ||
subscriptions.forEach(function (subscription) { | ||
if (!called[subscription.id]) { | ||
subscription.callback(err, resourceCache[resource], subscription.unsubscribeFn); | ||
called[subscription.id] = true; | ||
} | ||
}); | ||
} | ||
}); | ||
} | ||
} | ||
}); | ||
} | ||
})(); | ||
this.notifySubscribers(rootEntity, called, err); | ||
} | ||
@@ -277,16 +316,4 @@ | ||
entities.forEach(function (entity) { | ||
var resources = entityToResource[entity.url]; | ||
if (resources) { | ||
resources.forEach(function (r) { | ||
var response = resourceCache[r]; | ||
var subscriptions = resourceToSubscription[r]; | ||
if (subscriptions) { | ||
subscriptions.forEach(function (s) { | ||
if (!called[s.id]) { | ||
s.callback(err, response, s.unsubscribeFn); | ||
called[s.id] = true; | ||
} | ||
}); | ||
} | ||
}); | ||
if (entity) { | ||
_this.notifySubscribers(entity.url, called, err); | ||
} | ||
@@ -298,9 +325,11 @@ }); | ||
fetch: function fetch(resource, callback) { | ||
var _this = this; | ||
var _this2 = this; | ||
this.debug && console.log('fetch', resource); | ||
var errFunc = function errFunc(err) { | ||
_this._internal.publishError(resource, null, err); | ||
_this2._internal.publishError(resource, null, err); | ||
}; | ||
var promise = retry((0, _fetch.createFetch)(currentToken, resource, endpoint, this._context), errFunc); | ||
var promise = retry((0, _fetch.createFetch)(currentToken, resource, endpoint, this._context), errFunc, function () { | ||
return !_this2.hasSubscriptions(resource); | ||
}); | ||
promise.catch(errFunc); | ||
@@ -311,2 +340,7 @@ return promise; | ||
hasSubscriptions: function hasSubscriptions(resource) { | ||
var subscriptions = resourceToSubscription[resource]; | ||
return subscriptions && subscriptions.length > 0; | ||
}, | ||
subscribe: function subscribe(resource, callback) { | ||
@@ -347,11 +381,13 @@ this.debug && console.log('subscribe', currentToken, resource, endpoint); | ||
refresh: function refresh(resource) { | ||
var _this2 = this; | ||
var _this3 = this; | ||
this.debug && console.log('refresh', resource); | ||
var errFunc = function errFunc(err) { | ||
_this2._internal.publishError(resource, null, err); | ||
_this3._internal.publishError(resource, null, err); | ||
}; | ||
retry((0, _fetch.createFetch)(currentToken, resource, endpoint, this._internal._context), errFunc).then(function (response) { | ||
retry((0, _fetch.createFetch)(currentToken, resource, endpoint, this._internal._context), errFunc, function () { | ||
return !_this3.hasSubscriptions(resource); | ||
}).then(function (response) { | ||
return setTimeout(function () { | ||
return _this2._internal.publish(resource, response, null); | ||
return _this3._internal.publish(resource, response, null); | ||
}, 0); | ||
@@ -362,13 +398,15 @@ }).catch(errFunc); | ||
create: function create(resource, content) { | ||
var _this3 = this; | ||
var _this4 = this; | ||
this.debug && console.log('refresh', resource, content); | ||
var errFunc = function errFunc(err) { | ||
_this3._internal.publishError(resource, null, err); | ||
_this4._internal.publishError(resource, null, err); | ||
}; | ||
var promise = retry((0, _fetch.createFetch)(currentToken, resource, endpoint, this._internal._context, { method: 'POST', body: content }), errFunc); | ||
var promise = retry((0, _fetch.createFetch)(currentToken, resource, endpoint, this._internal._context, { method: 'POST', body: content }), errFunc, function () { | ||
return !_this4.hasSubscriptions(resource); | ||
}); | ||
promise.then(function (response) { | ||
return setTimeout(function () { | ||
if (response && response.url) { | ||
_this3._internal.publish(response.url, response, null); | ||
_this4._internal.publish(response.url, response, null); | ||
} | ||
@@ -382,12 +420,14 @@ }, 0); | ||
update: function update(resource, content) { | ||
var _this4 = this; | ||
var _this5 = this; | ||
this.debug && console.log('update', resource, content); | ||
var errFunc = function errFunc(err) { | ||
_this4._internal.publishError(resource, null, err); | ||
_this5._internal.publishError(resource, null, err); | ||
}; | ||
var promise = retry((0, _fetch.createFetch)(currentToken, resource, endpoint, this._internal._context, { method: 'PUT', body: content }), errFunc); | ||
var promise = retry((0, _fetch.createFetch)(currentToken, resource, endpoint, this._internal._context, { method: 'PUT', body: content }), errFunc, function () { | ||
return !_this5.hasSubscriptions(resource); | ||
}); | ||
promise.then(function (response) { | ||
return setTimeout(function () { | ||
return _this4._internal.publish(resource, response, null); | ||
return _this5._internal.publish(resource, response, null); | ||
}, 0); | ||
@@ -400,9 +440,11 @@ }); | ||
remove: function remove(resource) { | ||
var _this5 = this; | ||
var _this6 = this; | ||
this.debug && console.log('remove', resource); | ||
var errFunc = function errFunc(err) { | ||
_this5._internal.publishError(resource, null, err); | ||
_this6._internal.publishError(resource, null, err); | ||
}; | ||
var promise = retry((0, _fetch.createFetch)(currentToken, resource, endpoint, this._internal._context, { method: 'DELETE', body: null }), errFunc); | ||
var promise = retry((0, _fetch.createFetch)(currentToken, resource, endpoint, this._internal._context, { method: 'DELETE', body: null }), errFunc, function () { | ||
return !_this6.hasSubscriptions(resource); | ||
}); | ||
@@ -412,3 +454,3 @@ promise.then(function (response) { | ||
delete resourceCache[resource]; | ||
_this5._internal.publish(resource, null, null); | ||
_this6._internal.publish(resource, null, null); | ||
}, 0); | ||
@@ -466,20 +508,28 @@ }); | ||
var retry = function retry(fetchFunc, failFunc) { | ||
var retryTimeout = global.RETRY_START_TIMEOUT || RETRY_START_TIMEOUT; | ||
var retry = function retry(fetchFunc, failFunc, abortFunc) { | ||
var retryTimeout = window.RETRY_START_TIMEOUT || RETRY_START_TIMEOUT; | ||
var retries = 0; | ||
return new Promise(function (resolve, reject) { | ||
function doRetry(err) { | ||
var status = err.details.status; | ||
// status 0 should be transport errors and 5xx server errors | ||
if ((status === 0 || status >= 500 && status < 600) && retries < (global.MAX_RETRIES || MAX_RETRIES)) { | ||
failFunc(err); | ||
setTimeout(function () { | ||
retries++; | ||
if (retryTimeout < (global.MAX_RETRY_TIMEOUT || MAX_RETRY_TIMEOUT)) { | ||
retryTimeout = retryTimeout + (global.RETRY_TIMEOUT_INCREMENT || RETRY_TIMEOUT_INCREMENT); | ||
} | ||
fetchFunc().then(resolve).catch(doRetry); | ||
}, retryTimeout); | ||
if (abortFunc && abortFunc()) { | ||
reject(_extends({}, err, { | ||
code: 'ABORTED', | ||
title: 'Request was aborted', | ||
description: 'The request was aborted' | ||
})); | ||
} else { | ||
reject(err); | ||
var status = err.details.status; | ||
// status 0 should be transport errors and 5xx server errors | ||
if ((status === 0 || status >= 500 && status < 600) && retries < (window.MAX_RETRIES || MAX_RETRIES)) { | ||
failFunc(err); | ||
setTimeout(function () { | ||
retries++; | ||
if (retryTimeout < (window.MAX_RETRY_TIMEOUT || MAX_RETRY_TIMEOUT)) { | ||
retryTimeout = retryTimeout + (window.RETRY_TIMEOUT_INCREMENT || RETRY_TIMEOUT_INCREMENT); | ||
} | ||
fetchFunc().then(resolve).catch(doRetry); | ||
}, retryTimeout); | ||
} else { | ||
reject(err); | ||
} | ||
} | ||
@@ -486,0 +536,0 @@ } |
{ | ||
"name": "six-sdk", | ||
"version": "0.6.0", | ||
"version": "0.6.1", | ||
"description": "SIX Javascript SDK", | ||
@@ -11,2 +11,3 @@ "main": "lib", | ||
"test": "npm run prepare && mocha --compilers js:babel-register --recursive ./tests", | ||
"get-stage": "get-stage", | ||
"push:npm": "npm run prepare && npm run compile && npm publish", | ||
@@ -39,2 +40,3 @@ "push:cdn": "npm run dist && node ./bin/push-cdn", | ||
"babel-core": "^6.3.17", | ||
"babel-eslint": "^6.1.2", | ||
"babel-loader": "^6.2.0", | ||
@@ -48,5 +50,2 @@ "babel-plugin-transform-class-properties": "^6.4.0", | ||
"eslint": "^1.10.3", | ||
"eslint-config-standard": "^4.4.0", | ||
"eslint-plugin-react": "^3.14.0", | ||
"eslint-plugin-standard": "^1.3.2", | ||
"jsdom": "^8.0.2", | ||
@@ -57,2 +56,3 @@ "mocha": "^2.4.5", | ||
"sinon": "^1.17.3", | ||
"six-widget-release-support": "0.0.1-0", | ||
"webpack": "^1.12.9", | ||
@@ -59,0 +59,0 @@ "webpack-dev-server": "^1.14.1" |
@@ -124,2 +124,100 @@ import { expect } from 'chai'; | ||
describe("should give same object to subscribers for favorites + entity resource", () => { | ||
it('favorites then entity', (done) => { | ||
const LISTING = {url: '/listings/848', foo: 'bar'} | ||
const FAVORITES = { | ||
url: '/pop', | ||
favorites:[ {url: '/listings/848'}, {url: '/listings/847'}] | ||
} | ||
// queue up some responses | ||
XMLHttpRequest.respondWith(FAVORITES) | ||
XMLHttpRequest.respondWith(LISTING) | ||
let called = 0 | ||
session.subscribe('/pop',(e,favorites) => { | ||
session.subscribe('/listings/848',(e,listing2) => { | ||
if (called++) return // ignore second call | ||
expect(favorites).to.exist | ||
expect(listing2).to.exist | ||
expect(favorites.favorites[0] === listing2).to.be.true | ||
done() | ||
}) | ||
}) | ||
}) | ||
it('entity then resource', (done) => { | ||
const LISTING = {url: '/listings/848', foo: 'bar'} | ||
const FAVORITES = { | ||
url: '/pop', | ||
favorites:[ {url: '/listings/848'}, {url: '/listings/847'}] | ||
} | ||
// queue up some responses | ||
XMLHttpRequest.respondWith(LISTING) | ||
XMLHttpRequest.respondWith(FAVORITES) | ||
let called = 0 | ||
session.subscribe('/listings/848',(e,listing2) => { | ||
session.subscribe('/pop',(e,favorites) => { | ||
if (called++) return // ignore second call | ||
expect(favorites).to.exist | ||
expect(listing2).to.exist | ||
expect(favorites.favorites[0] === listing2).to.be.true | ||
done() | ||
}) | ||
}) | ||
}) | ||
}) | ||
describe("should give same object to subscribers for search + entity resource", () => { | ||
it('favorites then entity', (done) => { | ||
const LISTING = {url: '/listings/848', foo: 'bar'} | ||
const SEARCH = { | ||
url: '/pop', | ||
search: { EQUITY: [ {url: '/listings/848'}, {url: '/listings/847'}] }, | ||
} | ||
// queue up some responses | ||
XMLHttpRequest.respondWith(SEARCH) | ||
XMLHttpRequest.respondWith(LISTING) | ||
let called = 0 | ||
session.subscribe('/pop',(e,search) => { | ||
session.subscribe('/listings/848',(e,listing2) => { | ||
if (called++) return // ignore second call | ||
expect(search).to.exist | ||
expect(listing2).to.exist | ||
expect(search.search.EQUITY[0] === listing2).to.be.true | ||
done() | ||
}) | ||
}) | ||
}) | ||
it('entity then resource', (done) => { | ||
const LISTING = {url: '/listings/848', foo: 'bar'} | ||
const SEARCH = { | ||
url: '/pop', | ||
search: { EQUITY: [ {url: '/listings/848'}, {url: '/listings/847'}] }, | ||
} | ||
// queue up some responses | ||
XMLHttpRequest.respondWith(LISTING) | ||
XMLHttpRequest.respondWith(SEARCH) | ||
let called = 0 | ||
session.subscribe('/listings/848',(e,listing2) => { | ||
session.subscribe('/pop',(e,search) => { | ||
if (called++) return // ignore second call | ||
expect(search).to.exist | ||
expect(listing2).to.exist | ||
expect(search.search.EQUITY[0] === listing2).to.be.true | ||
done() | ||
}) | ||
}) | ||
}) | ||
}) | ||
it('should give same object to subscriber for entity and entity/relation', (done) => { | ||
@@ -126,0 +224,0 @@ const QUOTES = {url: '/listings/848/quotes'} |
@@ -137,2 +137,34 @@ import { expect } from 'chai'; | ||
it('should abort retry on unsubscribe',(done) => { | ||
global.MAX_RETRIES = 10 | ||
global.RETRY_START_TIMEOUT = 1 | ||
global.RETRY_TIMEOUT_INCREMENT = 1 | ||
let errorCalls = 0; | ||
const errorSpy = sinon.spy((error) => { | ||
errorCalls++ | ||
expect(error).to.exist | ||
if (errorCalls === 1) { | ||
expect(error.code).to.equal('GENERAL_INTERNAL_ERROR') | ||
} else if (errorCalls === 2) { | ||
expect(error.code).to.equal('ABORTED') | ||
} else { | ||
assert.fail(error, null, 'Too many error calls') | ||
} | ||
}) | ||
session.subscribe('error', errorSpy) | ||
const callback = sinon.spy() | ||
const unsub = session.subscribe('/listings/848', callback) | ||
XMLHttpRequest.respondWith('{ "requestId" : "5d269742-8311-4065-84dd-6493b287fad6", "httpStatusCode" : 500, "code" : "GENERAL_INTERNAL_ERROR", "title" : "General error", "description" : "A general internal server error occured. "}', 500) | ||
setTimeout(() => { | ||
unsub() | ||
XMLHttpRequest.respondWith('{ "requestId" : "5d269742-8311-4065-84dd-6493b287fad6", "httpStatusCode" : 500, "code" : "GENERAL_INTERNAL_ERROR", "title" : "General error", "description" : "A general internal server error occured. "}', 500) | ||
}, 0) | ||
setTimeout(() => { | ||
expect(callback.called).to.be.true | ||
expect(errorSpy.calledOnce).to.be.false | ||
done() | ||
}, 15) | ||
}) | ||
it('should not retry on user error',(done) => { | ||
@@ -139,0 +171,0 @@ global.MAX_RETRIES = 1 |
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
76026
19
28
1789
8
5