From 30c5c05910a2f774dfd3f46d9c2de2abd1738235 Mon Sep 17 00:00:00 2001 From: Joe Goggins Date: Fri, 10 Jun 2022 18:51:24 -0500 Subject: [PATCH 01/14] Introduce setDefaultAuth(auth) top level method --- src/Particle.js | 9 +++++++++ test/Particle.spec.js | 12 ++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/Particle.js b/src/Particle.js index ce17ca83..fbe3b08e 100644 --- a/src/Particle.js +++ b/src/Particle.js @@ -2099,6 +2099,15 @@ class Particle { }); } + /** + * Set default auth token that will be used in each method if `auth` is not provided + * @param {String} auth A Particle access token + * @returns {undefined} + */ + setDefaultAuth(auth){ + this._defaultAuth = auth; + } + /** * API URI to access a device * @param {Object} options Options for this API call diff --git a/test/Particle.spec.js b/test/Particle.spec.js index c3cb6bff..a38bde39 100644 --- a/test/Particle.spec.js +++ b/test/Particle.spec.js @@ -2716,4 +2716,16 @@ describe('ParticleAPI', () => { expect(api.agent.setBaseUrl.firstCall.args[0]).to.eql(baseUrl); }); }); + + describe('setDefaultAuth(auth)', () => { + afterEach(() => { + sinon.restore(); + }); + + it('sets ._defaultAuth', () => { + const auth = 'foo'; + api.setDefaultAuth(auth); + expect(api._defaultAuth).to.eql(auth); + }); + }); }); From cb1c5a330adc7e7196d45ab851e8f43c5e1002b8 Mon Sep 17 00:00:00 2001 From: Joe Goggins Date: Tue, 14 Jun 2022 11:59:57 -0500 Subject: [PATCH 02/14] Introduce api._getEffectiveAuth and use it on listDevices({}) --- src/Particle.js | 17 ++++++++++++++++- test/Particle.spec.js | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/Particle.js b/src/Particle.js index fbe3b08e..b0549831 100644 --- a/src/Particle.js +++ b/src/Particle.js @@ -407,6 +407,7 @@ class Particle { uri = '/v1/devices'; } + auth = this._getEffectiveAuth(auth); return this.get({ uri, auth, headers, query, context }); } @@ -2107,7 +2108,21 @@ class Particle { setDefaultAuth(auth){ this._defaultAuth = auth; } - + /** + * Return provided token if truthy else use default auth if truthy else undefined + * @param {*} auth Optional auth token or undefined + * @private + * @returns {String|undefined} a Particle auth token or undefined + */ + _getEffectiveAuth(auth) { + if (auth) { + return auth; + } else if (this._defaultAuth) { + return this._defaultAuth; + } else { + return undefined; + } + } /** * API URI to access a device * @param {Object} options Options for this API call diff --git a/test/Particle.spec.js b/test/Particle.spec.js index a38bde39..daa4f3c6 100644 --- a/test/Particle.spec.js +++ b/test/Particle.spec.js @@ -370,6 +370,18 @@ describe('ParticleAPI', () => { }); describe('.listDevices', () => { + describe('uses effective auth', () => { + afterEach(() => { + sinon.restore(); + }); + it('calls this._getEffectiveAuth', async () => { + sinon.stub(api, '_getEffectiveAuth'); + sinon.stub(api, 'get'); // don't actually call the real method + await api.listDevices(props); + expect(api._getEffectiveAuth).to.have.property('callCount', 1); + }); + }); + describe('user scope', () => { it('generates request', () => { return api.listDevices(props).then((results) => { @@ -2728,4 +2740,29 @@ describe('ParticleAPI', () => { expect(api._defaultAuth).to.eql(auth); }); }); + + describe('_getEffectiveAuth(auth)', () => { + afterEach(() => { + sinon.restore(); + }); + + it('returns provided value when provided value is truthy', () => { + const expectedReturnValue = 'pass through'; + expect(api._getEffectiveAuth(expectedReturnValue)).to.eql(expectedReturnValue); + }); + + it('returns value of _defaultAuth when provided value is NOT truthy', () => { + const providedValue = undefined; + const expectedReturnValue = 'default auth value'; + api.setDefaultAuth(expectedReturnValue); + expect(api._getEffectiveAuth(providedValue)).to.eql(expectedReturnValue); + }); + + it('returns undefined when both provided value and _defaultAuth are NOT truthy', () => { + const providedValue = undefined; + const expectedReturnValue = undefined; + api.setDefaultAuth(undefined); + expect(api._getEffectiveAuth(providedValue)).to.eql(expectedReturnValue); + }); + }); }); From fd35d3d5bed04a62df1383499c0efbcb7bb85074 Mon Sep 17 00:00:00 2001 From: Joe Goggins Date: Tue, 14 Jun 2022 13:17:42 -0500 Subject: [PATCH 03/14] Reword constructor test to use expect instead of should This is done because things will fail if a property has a value of undefined (like we are about to with the defaultAuth prop) --- test/Particle.spec.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/Particle.spec.js b/test/Particle.spec.js index daa4f3c6..4cd66194 100644 --- a/test/Particle.spec.js +++ b/test/Particle.spec.js @@ -124,11 +124,12 @@ describe('ParticleAPI', () => { }); describe('constructor', () => { - it('sets the defaults', () => { + it('sets maps defaults to instance properties', () => { Object.keys(Defaults).forEach((setting) => { - api[setting].should.equal(Defaults[setting]); + expect(api[setting]).to.eql(Defaults[setting]); }); }); + }); describe('trackingIdentity', () => { From 72c15e18c45dcaa136acf3872a05fe638b406fa6 Mon Sep 17 00:00:00 2001 From: Joe Goggins Date: Tue, 14 Jun 2022 13:19:11 -0500 Subject: [PATCH 04/14] Adds defaultAuth constructor property and test coverage for expected defaults --- src/Defaults.js | 3 ++- test/Defaults.spec.js | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 test/Defaults.spec.js diff --git a/src/Defaults.js b/src/Defaults.js index 7a2e8a55..95d7205d 100644 --- a/src/Defaults.js +++ b/src/Defaults.js @@ -2,5 +2,6 @@ export default { baseUrl: 'https://api.particle.io', clientSecret: 'particle-api', clientId: 'particle-api', - tokenDuration: 7776000 // 90 days + tokenDuration: 7776000, // 90 days + defaultAuth: undefined }; diff --git a/test/Defaults.spec.js b/test/Defaults.spec.js new file mode 100644 index 00000000..3a69823d --- /dev/null +++ b/test/Defaults.spec.js @@ -0,0 +1,29 @@ +import { expect } from './test-setup'; +import Defaults from '../src/Defaults'; + +describe('Default Particle constructor options', () => { + it('includes baseUrl', () => { + expect(Defaults).to.have.property('baseUrl'); + expect(Defaults.baseUrl).to.eql('https://api.particle.io'); + }); + + it('includes clientSecret', () => { + expect(Defaults).to.have.property('clientSecret'); + expect(Defaults.clientSecret).to.eql('particle-api'); + }); + + it('includes clientId', () => { + expect(Defaults).to.have.property('clientId'); + expect(Defaults.clientId).to.eql('particle-api'); + }); + + it('includes tokenDuration', () => { + expect(Defaults).to.have.property('tokenDuration'); + expect(Defaults.tokenDuration).to.eql(7776000); + }); + + it('includes defaultAuth', () => { + expect(Defaults).to.have.property('defaultAuth'); + expect(Defaults.defaultAuth).to.eql(undefined); + }); +}); From 1a73735a71d815d427b467f99386076fb1d7bc75 Mon Sep 17 00:00:00 2001 From: Joe Goggins Date: Tue, 14 Jun 2022 13:19:40 -0500 Subject: [PATCH 05/14] Particle constructor calls setDefaultAuth when defaultAuth option is truthy --- src/Particle.js | 4 ++++ test/Particle.spec.js | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/Particle.js b/src/Particle.js index b0549831..29826fbf 100644 --- a/src/Particle.js +++ b/src/Particle.js @@ -23,6 +23,10 @@ class Particle { * @param {Object} options Options for this API call Options to be used for all requests (see [Defaults](../src/Defaults.js)) */ constructor(options = {}){ + if (options.defaultAuth) { + this.setDefaultAuth(options.defaultAuth); + } + // todo - this seems a bit dangerous - would be better to put all options/context in a contained object Object.assign(this, Defaults, options); this.context = {}; diff --git a/test/Particle.spec.js b/test/Particle.spec.js index 4cd66194..c5ea5e3a 100644 --- a/test/Particle.spec.js +++ b/test/Particle.spec.js @@ -130,6 +130,20 @@ describe('ParticleAPI', () => { }); }); + describe('without defaultAuth', () => { + it('does NOT call .setDefaultAuth(defaultAuth) unless provided value is truthy', () => { + sinon.stub(api, 'setDefaultAuth'); + expect(api.setDefaultAuth).to.have.property('callCount', 0); + }); + }); + + describe('with defaultAuth', () => { + it('calls .setDefaultAuth(defaultAuth) when provided defaultAuth value is truthy', () => { + sinon.stub(Particle.prototype, 'setDefaultAuth'); + api = new Particle({ defaultAuth: 'foo' }); + expect(api.setDefaultAuth).to.have.property('callCount', 1); + }); + }); }); describe('trackingIdentity', () => { From 7ba3dec56b150f387dbec0cab41723597f54a398 Mon Sep 17 00:00:00 2001 From: Joe Goggins Date: Tue, 14 Jun 2022 13:20:11 -0500 Subject: [PATCH 06/14] Increase minimum code coverage from 50 to 91% of lines --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c8286380..07fc4e4e 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "test:unit:silent": "npm run test:unit > tmp/test-unit-log.txt 2>&1", "test:browser": "karma start --single-run", "test:watch": "npm run test:unit -- --watch", - "coverage": "nyc --reporter=text --include='src/**/*.js' --temp-dir=./tmp/ --check-coverage --lines 50 npm run test:unit:silent", + "coverage": "nyc --reporter=text --include='src/**/*.js' --temp-dir=./tmp/ --check-coverage --lines 91 npm run test:unit:silent", "lint": "eslint . --ext .js --format unix --ignore-path .gitignore --ignore-pattern \"dist/*\"", "lint:fix": "npm run lint -- --fix", "docs": "documentation build src/Particle.js --shallow -g -f md -o docs/api.md", From fc701701e69085f482cff0d4aaeaaf5ed0e32c00 Mon Sep 17 00:00:00 2001 From: Joe Goggins Date: Tue, 14 Jun 2022 13:26:08 -0500 Subject: [PATCH 07/14] Changes constructor option name from defaultAuth to auth --- src/Defaults.js | 2 +- src/Particle.js | 4 ++-- test/Defaults.spec.js | 4 ++-- test/Particle.spec.js | 5 ++++- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Defaults.js b/src/Defaults.js index 95d7205d..990ffae9 100644 --- a/src/Defaults.js +++ b/src/Defaults.js @@ -3,5 +3,5 @@ export default { clientSecret: 'particle-api', clientId: 'particle-api', tokenDuration: 7776000, // 90 days - defaultAuth: undefined + auth: undefined }; diff --git a/src/Particle.js b/src/Particle.js index 29826fbf..841964e2 100644 --- a/src/Particle.js +++ b/src/Particle.js @@ -23,8 +23,8 @@ class Particle { * @param {Object} options Options for this API call Options to be used for all requests (see [Defaults](../src/Defaults.js)) */ constructor(options = {}){ - if (options.defaultAuth) { - this.setDefaultAuth(options.defaultAuth); + if (options.auth) { + this.setDefaultAuth(options.auth); } // todo - this seems a bit dangerous - would be better to put all options/context in a contained object diff --git a/test/Defaults.spec.js b/test/Defaults.spec.js index 3a69823d..d33a062d 100644 --- a/test/Defaults.spec.js +++ b/test/Defaults.spec.js @@ -23,7 +23,7 @@ describe('Default Particle constructor options', () => { }); it('includes defaultAuth', () => { - expect(Defaults).to.have.property('defaultAuth'); - expect(Defaults.defaultAuth).to.eql(undefined); + expect(Defaults).to.have.property('auth'); + expect(Defaults.auth).to.eql(undefined); }); }); diff --git a/test/Particle.spec.js b/test/Particle.spec.js index c5ea5e3a..c88ecbed 100644 --- a/test/Particle.spec.js +++ b/test/Particle.spec.js @@ -139,9 +139,12 @@ describe('ParticleAPI', () => { describe('with defaultAuth', () => { it('calls .setDefaultAuth(defaultAuth) when provided defaultAuth value is truthy', () => { + const fakeAuthToken = 'foo'; sinon.stub(Particle.prototype, 'setDefaultAuth'); - api = new Particle({ defaultAuth: 'foo' }); + api = new Particle({ auth: fakeAuthToken }); expect(api.setDefaultAuth).to.have.property('callCount', 1); + expect(api.setDefaultAuth.firstCall.args).to.have.lengthOf(1); + expect(api.setDefaultAuth.firstCall.args[0]).to.eql(fakeAuthToken); }); }); }); From f7e7ddce1305ff0de74206bc9461d7ade52eb067 Mon Sep 17 00:00:00 2001 From: Joe Goggins Date: Tue, 14 Jun 2022 14:49:12 -0500 Subject: [PATCH 08/14] Move call to _getEffectiveAuth to agent forwarders This should be exhaustive; any API method that includes an http auth parameter should pass it through to the agent --- src/Particle.js | 7 ++++++- test/Particle.spec.js | 30 ++++++++++-------------------- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/src/Particle.js b/src/Particle.js index 841964e2..d6bccb43 100644 --- a/src/Particle.js +++ b/src/Particle.js @@ -411,7 +411,6 @@ class Particle { uri = '/v1/devices'; } - auth = this._getEffectiveAuth(auth); return this.get({ uri, auth, headers, query, context }); } @@ -2141,31 +2140,37 @@ class Particle { get({ uri, auth, headers, query, context }){ context = this._buildContext(context); + auth = this._getEffectiveAuth(auth); return this.agent.get({ uri, auth, headers, query, context }); } head({ uri, auth, headers, query, context }){ context = this._buildContext(context); + auth = this._getEffectiveAuth(auth); return this.agent.head({ uri, auth, headers, query, context }); } post({ uri, auth, headers, data, context }){ context = this._buildContext(context); + auth = this._getEffectiveAuth(auth); return this.agent.post({ uri, auth, headers, data, context }); } put({ uri, auth, headers, data, context }){ context = this._buildContext(context); + auth = this._getEffectiveAuth(auth); return this.agent.put({ uri, auth, headers, data, context }); } delete({ uri, auth, headers, data, context }){ context = this._buildContext(context); + auth = this._getEffectiveAuth(auth); return this.agent.delete({ uri, auth, headers, data, context }); } request(args){ args.context = this._buildContext(args.context); + args.auth = this._getEffectiveAuth(args.auth); return this.agent.request(args); } diff --git a/test/Particle.spec.js b/test/Particle.spec.js index c88ecbed..de4a42ef 100644 --- a/test/Particle.spec.js +++ b/test/Particle.spec.js @@ -388,18 +388,6 @@ describe('ParticleAPI', () => { }); describe('.listDevices', () => { - describe('uses effective auth', () => { - afterEach(() => { - sinon.restore(); - }); - it('calls this._getEffectiveAuth', async () => { - sinon.stub(api, '_getEffectiveAuth'); - sinon.stub(api, 'get'); // don't actually call the real method - await api.listDevices(props); - expect(api._getEffectiveAuth).to.have.property('callCount', 1); - }); - }); - describe('user scope', () => { it('generates request', () => { return api.listDevices(props).then((results) => { @@ -2648,13 +2636,15 @@ describe('ParticleAPI', () => { contextResult = { def: 456 }; result = 'fake-result'; api._buildContext = sinon.stub().returns(contextResult); + api._getEffectiveAuth = sinon.stub().returns(auth); }); afterEach(() => { expect(api._buildContext).to.have.been.calledWith(context); + expect(api._getEffectiveAuth).to.have.been.calledWith(auth); }); - it('calls _buildContext from get', () => { + it('calls _buildContext and _getEffectiveAuth from get', () => { api.agent.get = sinon.stub().returns(result); const options = { uri, auth, headers, query, context }; const res = api.get(options); @@ -2668,7 +2658,7 @@ describe('ParticleAPI', () => { }); }); - it('calls _buildContext from head', () => { + it('calls _buildContext and _getEffectiveAuth from head', () => { api.agent.head = sinon.stub().returns(result); const options = { uri, auth, headers, query, context }; const res = api.head(options); @@ -2682,7 +2672,7 @@ describe('ParticleAPI', () => { }); }); - it('calls _buildContext from post', () => { + it('calls _buildContext and _getEffectiveAuth from post', () => { api.agent.post = sinon.stub().returns(result); const options = { uri, auth, headers, data, context }; const res = api.post(options); @@ -2696,7 +2686,7 @@ describe('ParticleAPI', () => { }); }); - it('calls _buildContext from put', () => { + it('calls _buildContext and _getEffectiveAuth from put', () => { api.agent.put = sinon.stub().returns(result); const options = { uri, auth, headers, data, context }; const res = api.put(options); @@ -2710,7 +2700,7 @@ describe('ParticleAPI', () => { }); }); - it('calls _buildContext from delete', () => { + it('calls _buildContext and _getEffectiveAuth from delete', () => { api.agent.delete = sinon.stub().returns(result); const options = { uri, auth, headers, data, context }; const res = api.delete(options); @@ -2724,10 +2714,10 @@ describe('ParticleAPI', () => { }); }); - it('calls _buildContext from request', () => { + it('calls _buildContext and _getEffectiveAuth from request', () => { api.agent.request = sinon.stub().returns(result); - api.request({ context }).should.eql(result); - expect(api.agent.request).to.have.been.calledWith({ context:contextResult }); + api.request({ context, auth }).should.eql(result); + expect(api.agent.request).to.have.been.calledWith({ context:contextResult, auth }); }); }); }); From e2e3f7f7eb0dab2eba804dc419d84499dc975f7e Mon Sep 17 00:00:00 2001 From: Joe Goggins Date: Tue, 14 Jun 2022 16:06:22 -0500 Subject: [PATCH 09/14] Rewrite _getEffectiveAuth() concisely Co-authored-by: Matthew Mirande --- src/Particle.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Particle.js b/src/Particle.js index d6bccb43..4a493a57 100644 --- a/src/Particle.js +++ b/src/Particle.js @@ -2118,13 +2118,7 @@ class Particle { * @returns {String|undefined} a Particle auth token or undefined */ _getEffectiveAuth(auth) { - if (auth) { - return auth; - } else if (this._defaultAuth) { - return this._defaultAuth; - } else { - return undefined; - } + return auth || this._defaultAuth } /** * API URI to access a device From 0305f4f2ae22138e4d701970a078e1de1a819657 Mon Sep 17 00:00:00 2001 From: Joe Goggins Date: Tue, 14 Jun 2022 16:13:09 -0500 Subject: [PATCH 10/14] Renames _getEffectiveAuth to _getActiveAuthToken for clarity --- src/Particle.js | 16 ++++++++-------- test/Particle.spec.js | 24 ++++++++++++------------ 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/Particle.js b/src/Particle.js index 4a493a57..fc8fe4ff 100644 --- a/src/Particle.js +++ b/src/Particle.js @@ -2117,8 +2117,8 @@ class Particle { * @private * @returns {String|undefined} a Particle auth token or undefined */ - _getEffectiveAuth(auth) { - return auth || this._defaultAuth + _getActiveAuthToken(auth) { + return auth || this._defaultAuth; } /** * API URI to access a device @@ -2134,37 +2134,37 @@ class Particle { get({ uri, auth, headers, query, context }){ context = this._buildContext(context); - auth = this._getEffectiveAuth(auth); + auth = this._getActiveAuthToken(auth); return this.agent.get({ uri, auth, headers, query, context }); } head({ uri, auth, headers, query, context }){ context = this._buildContext(context); - auth = this._getEffectiveAuth(auth); + auth = this._getActiveAuthToken(auth); return this.agent.head({ uri, auth, headers, query, context }); } post({ uri, auth, headers, data, context }){ context = this._buildContext(context); - auth = this._getEffectiveAuth(auth); + auth = this._getActiveAuthToken(auth); return this.agent.post({ uri, auth, headers, data, context }); } put({ uri, auth, headers, data, context }){ context = this._buildContext(context); - auth = this._getEffectiveAuth(auth); + auth = this._getActiveAuthToken(auth); return this.agent.put({ uri, auth, headers, data, context }); } delete({ uri, auth, headers, data, context }){ context = this._buildContext(context); - auth = this._getEffectiveAuth(auth); + auth = this._getActiveAuthToken(auth); return this.agent.delete({ uri, auth, headers, data, context }); } request(args){ args.context = this._buildContext(args.context); - args.auth = this._getEffectiveAuth(args.auth); + args.auth = this._getActiveAuthToken(args.auth); return this.agent.request(args); } diff --git a/test/Particle.spec.js b/test/Particle.spec.js index de4a42ef..654c0119 100644 --- a/test/Particle.spec.js +++ b/test/Particle.spec.js @@ -2636,15 +2636,15 @@ describe('ParticleAPI', () => { contextResult = { def: 456 }; result = 'fake-result'; api._buildContext = sinon.stub().returns(contextResult); - api._getEffectiveAuth = sinon.stub().returns(auth); + api._getActiveAuthToken = sinon.stub().returns(auth); }); afterEach(() => { expect(api._buildContext).to.have.been.calledWith(context); - expect(api._getEffectiveAuth).to.have.been.calledWith(auth); + expect(api._getActiveAuthToken).to.have.been.calledWith(auth); }); - it('calls _buildContext and _getEffectiveAuth from get', () => { + it('calls _buildContext and _getActiveAuthToken from get', () => { api.agent.get = sinon.stub().returns(result); const options = { uri, auth, headers, query, context }; const res = api.get(options); @@ -2658,7 +2658,7 @@ describe('ParticleAPI', () => { }); }); - it('calls _buildContext and _getEffectiveAuth from head', () => { + it('calls _buildContext and _getActiveAuthToken from head', () => { api.agent.head = sinon.stub().returns(result); const options = { uri, auth, headers, query, context }; const res = api.head(options); @@ -2672,7 +2672,7 @@ describe('ParticleAPI', () => { }); }); - it('calls _buildContext and _getEffectiveAuth from post', () => { + it('calls _buildContext and _getActiveAuthToken from post', () => { api.agent.post = sinon.stub().returns(result); const options = { uri, auth, headers, data, context }; const res = api.post(options); @@ -2686,7 +2686,7 @@ describe('ParticleAPI', () => { }); }); - it('calls _buildContext and _getEffectiveAuth from put', () => { + it('calls _buildContext and _getActiveAuthToken from put', () => { api.agent.put = sinon.stub().returns(result); const options = { uri, auth, headers, data, context }; const res = api.put(options); @@ -2700,7 +2700,7 @@ describe('ParticleAPI', () => { }); }); - it('calls _buildContext and _getEffectiveAuth from delete', () => { + it('calls _buildContext and _getActiveAuthToken from delete', () => { api.agent.delete = sinon.stub().returns(result); const options = { uri, auth, headers, data, context }; const res = api.delete(options); @@ -2714,7 +2714,7 @@ describe('ParticleAPI', () => { }); }); - it('calls _buildContext and _getEffectiveAuth from request', () => { + it('calls _buildContext and _getActiveAuthToken from request', () => { api.agent.request = sinon.stub().returns(result); api.request({ context, auth }).should.eql(result); expect(api.agent.request).to.have.been.calledWith({ context:contextResult, auth }); @@ -2749,28 +2749,28 @@ describe('ParticleAPI', () => { }); }); - describe('_getEffectiveAuth(auth)', () => { + describe('_getActiveAuthToken(auth)', () => { afterEach(() => { sinon.restore(); }); it('returns provided value when provided value is truthy', () => { const expectedReturnValue = 'pass through'; - expect(api._getEffectiveAuth(expectedReturnValue)).to.eql(expectedReturnValue); + expect(api._getActiveAuthToken(expectedReturnValue)).to.eql(expectedReturnValue); }); it('returns value of _defaultAuth when provided value is NOT truthy', () => { const providedValue = undefined; const expectedReturnValue = 'default auth value'; api.setDefaultAuth(expectedReturnValue); - expect(api._getEffectiveAuth(providedValue)).to.eql(expectedReturnValue); + expect(api._getActiveAuthToken(providedValue)).to.eql(expectedReturnValue); }); it('returns undefined when both provided value and _defaultAuth are NOT truthy', () => { const providedValue = undefined; const expectedReturnValue = undefined; api.setDefaultAuth(undefined); - expect(api._getEffectiveAuth(providedValue)).to.eql(expectedReturnValue); + expect(api._getActiveAuthToken(providedValue)).to.eql(expectedReturnValue); }); }); }); From bc940ab6d22998c60d9fc3de3d061b1138327167 Mon Sep 17 00:00:00 2001 From: Joe Goggins Date: Tue, 14 Jun 2022 16:29:41 -0500 Subject: [PATCH 11/14] setDefaultAuth throws error when auth is not a non-empty string --- src/Particle.js | 6 +++++- test/Particle.spec.js | 13 ++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Particle.js b/src/Particle.js index fc8fe4ff..70ab771a 100644 --- a/src/Particle.js +++ b/src/Particle.js @@ -2109,7 +2109,11 @@ class Particle { * @returns {undefined} */ setDefaultAuth(auth){ - this._defaultAuth = auth; + if (typeof auth === 'string' && auth.length !== 0) { + this._defaultAuth = auth; + } else { + throw new Error('Must pass a non-empty string'); + } } /** * Return provided token if truthy else use default auth if truthy else undefined diff --git a/test/Particle.spec.js b/test/Particle.spec.js index 654c0119..ee8c38bc 100644 --- a/test/Particle.spec.js +++ b/test/Particle.spec.js @@ -2747,6 +2747,17 @@ describe('ParticleAPI', () => { api.setDefaultAuth(auth); expect(api._defaultAuth).to.eql(auth); }); + + it('throws error unless given a non-empty string', () => { + let error; + try { + api.setDefaultAuth(undefined); + } catch (e) { + error = e; + } + expect(error).to.be.an.instanceOf(Error); + expect(error.message).to.eql('Must pass a non-empty string'); + }); }); describe('_getActiveAuthToken(auth)', () => { @@ -2769,7 +2780,7 @@ describe('ParticleAPI', () => { it('returns undefined when both provided value and _defaultAuth are NOT truthy', () => { const providedValue = undefined; const expectedReturnValue = undefined; - api.setDefaultAuth(undefined); + api._defaultAuth = undefined; expect(api._getActiveAuthToken(providedValue)).to.eql(expectedReturnValue); }); }); From 05d7efc00aa65f20bc353647bb5f91970d741a4a Mon Sep 17 00:00:00 2001 From: Joe Goggins Date: Tue, 14 Jun 2022 16:31:08 -0500 Subject: [PATCH 12/14] Fix typo in error --- src/Particle.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Particle.js b/src/Particle.js index 70ab771a..b3ca2ac9 100644 --- a/src/Particle.js +++ b/src/Particle.js @@ -42,7 +42,7 @@ class Particle { if (this._isValidContext(name, context)){ this.context[name] = context; } else { - throw Error('uknown context name or undefined context: '+name); + throw Error('unknown context name or undefined context: '+name); } } } From 6408739d2cdaaccb6bc3afcfd92bb1df835abe32 Mon Sep 17 00:00:00 2001 From: Joe Goggins Date: Tue, 14 Jun 2022 17:27:51 -0500 Subject: [PATCH 13/14] Bugfix: getEventStream() should honor defaultAuth --- src/Particle.js | 1 + test/Particle.spec.js | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/Particle.js b/src/Particle.js index b3ca2ac9..200a7531 100644 --- a/src/Particle.js +++ b/src/Particle.js @@ -891,6 +891,7 @@ class Particle { uri += `/${encodeURIComponent(name)}`; } + auth = this._getActiveAuthToken(auth); return new EventStream(`${this.baseUrl}${uri}`, auth).connect(); } diff --git a/test/Particle.spec.js b/test/Particle.spec.js index ee8c38bc..6925b159 100644 --- a/test/Particle.spec.js +++ b/test/Particle.spec.js @@ -1031,6 +1031,13 @@ describe('ParticleAPI', () => { uri.should.endWith(`v1/products/test-product/devices/${props.deviceId}/events/foo`); }); }); + + it('calls _getActiveAuthToken(auth)', () => { + const fakeToken = 'abc123'; + sinon.stub(api, '_getActiveAuthToken').returns(fakeToken); + api.getEventStream({}); + expect(api._getActiveAuthToken).to.have.property('callCount', 1); + }); }); describe('.publishEvent', () => { From 10cb93b7b026dba2c27df45d0a5453a0250a63dc Mon Sep 17 00:00:00 2001 From: Joe Goggins Date: Tue, 14 Jun 2022 17:31:38 -0500 Subject: [PATCH 14/14] Bugfix for [sc-105035] This fix makes api.getEventStream() honor a baseUrl that has been changed via api.setBaseUrl. --- src/Particle.js | 1 + test/Particle.spec.js | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/Particle.js b/src/Particle.js index 200a7531..8d8093e4 100644 --- a/src/Particle.js +++ b/src/Particle.js @@ -2179,6 +2179,7 @@ class Particle { // Internal method used to target Particle's APIs other than the default setBaseUrl(baseUrl){ + this.baseUrl = baseUrl; this.agent.setBaseUrl(baseUrl); } } diff --git a/test/Particle.spec.js b/test/Particle.spec.js index 6925b159..5a6ee098 100644 --- a/test/Particle.spec.js +++ b/test/Particle.spec.js @@ -2734,6 +2734,12 @@ describe('ParticleAPI', () => { sinon.restore(); }); + it('sets baseUrl instance property', () => { + const baseUrl = 'foo'; + api.setBaseUrl(baseUrl); + expect(api.baseUrl).to.eql(baseUrl); + }); + it('calls agent.setBaseUrl', () => { const baseUrl = 'foo'; sinon.stub(api.agent, 'setBaseUrl');