Skip to content

Commit 36a61c1

Browse files
Merge pull request #191 from ScorpionFiko/feature/makeAPICall_auto_baseURL
enhancing makeApiCall to take endpoint uri only
2 parents 28182fa + 5992886 commit 36a61c1

File tree

3 files changed

+287
-1
lines changed

3 files changed

+287
-1
lines changed

README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,50 @@ oauthClient
437437
});
438438
```
439439

440+
441+
You can also make the calling using the endpoint path:
442+
443+
```javascript
444+
// Body sample from API explorer examples
445+
const body = {
446+
TrackQtyOnHand: true,
447+
Name: 'Garden Supplies',
448+
QtyOnHand: 10,
449+
InvStartDate: '2015-01-01',
450+
Type: 'Inventory',
451+
IncomeAccountRef: {
452+
name: 'Sales of Product Income',
453+
value: '79',
454+
},
455+
AssetAccountRef: {
456+
name: 'Inventory Asset',
457+
value: '81',
458+
},
459+
ExpenseAccountRef: {
460+
name: 'Cost of Goods Sold',
461+
value: '80',
462+
},
463+
};
464+
465+
oauthClient
466+
.makeApiCall({
467+
url: '/v3/company/1234/item',
468+
method: 'POST',
469+
headers: {
470+
'Content-Type': 'application/json',
471+
},
472+
body: JSON.stringify(body),
473+
})
474+
.then(function (response) {
475+
console.log('The API response is : ' + response);
476+
})
477+
.catch(function (e) {
478+
console.log('The error is ' + JSON.stringify(e));
479+
});
480+
```
481+
482+
483+
440484
The client validates the ID Token and returns boolean `true` if validates successfully else it would
441485
throw an exception.
442486

src/OAuthClient.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ OAuthClient.environment = {
9090
sandbox: 'https://sandbox-quickbooks.api.intuit.com/',
9191
production: 'https://quickbooks.api.intuit.com/',
9292
};
93+
OAuthClient.qbo_environment = {
94+
sandbox: 'https://sandbox.qbo.intuit.com/app/',
95+
production: 'https://qbo.intuit.com/app/',
96+
};
9397
OAuthClient.jwks_uri = 'https://oauth.platform.intuit.com/op/v1/jwks';
9498
OAuthClient.scopes = {
9599
Accounting: 'com.intuit.quickbooks.accounting',
@@ -123,6 +127,16 @@ OAuthClient.prototype.setAuthorizeURLs = function setAuthorizeURLs(params) {
123127
return this;
124128
};
125129

130+
OAuthClient.prototype.getEnvironmentURI = function getEnvironmentURI() {
131+
return (this.environment && this.environment === 'production') ? OAuthClient.environment.production : OAuthClient.environment.sandbox;
132+
}
133+
134+
135+
OAuthClient.prototype.getQBOEnvironmentURI = function getQBOEnvironmentURI() {
136+
return (this.environment && this.environment === 'production') ? OAuthClient.qbo_environment.production : OAuthClient.qbo_environment.sandbox;
137+
}
138+
139+
126140
/**
127141
* Redirect User to Authorization Page
128142
* *
@@ -389,8 +403,23 @@ OAuthClient.prototype.makeApiCall = function makeApiCall(params) {
389403
? Object.assign({}, baseHeaders, params.headers)
390404
: Object.assign({}, baseHeaders);
391405

406+
let baseURL = '';
407+
let endpoint = '';
408+
// backward compatibility:
409+
// checking to see if user has supplied the full url
410+
if (params.url.startsWith(OAuthClient.environment.sandbox) || params.url.startsWith(OAuthClient.environment.production)) {
411+
baseURL = params.url;
412+
413+
} else {
414+
baseURL = (this.environment && this.environment === 'production') ? OAuthClient.environment.production : OAuthClient.environment.sandbox;
415+
// checking to see if user supplied the endpoint only and if it begins with a slash
416+
// if it does, we remove the slash to avoid double slashes in the url
417+
endpoint = params.url.startsWith('/') ? params.url.slice(1) : params.url;
418+
419+
}
420+
392421
const request = {
393-
url: params.url,
422+
url: baseURL + endpoint,
394423
method: params.method || 'GET',
395424
headers,
396425
responseType,

test/OAuthClientTest.js

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,36 @@ describe('Tests for OAuthClient', () => {
306306
);
307307
});
308308
});
309+
it('Make API Call in Sandbox Environment using relative endpoint - starting slash', () => {
310+
oauthClient.environment = 'sandbox';
311+
oauthClient.getToken().realmId = '12345';
312+
// eslint-disable-next-line no-useless-concat
313+
return oauthClient
314+
.makeApiCall({
315+
url:
316+
'/v3/company/' + '12345' + '/companyinfo/' + '12345',
317+
})
318+
.then((authResponse) => {
319+
expect(JSON.stringify(authResponse.json)).to.be.equal(
320+
JSON.stringify(expectedMakeAPICall),
321+
);
322+
});
323+
});
324+
it('Make API Call in Sandbox Environment using relative endpoint - no starting slash', () => {
325+
oauthClient.environment = 'sandbox';
326+
oauthClient.getToken().realmId = '12345';
327+
// eslint-disable-next-line no-useless-concat
328+
return oauthClient
329+
.makeApiCall({
330+
url:
331+
'v3/company/' + '12345' + '/companyinfo/' + '12345',
332+
})
333+
.then((authResponse) => {
334+
expect(JSON.stringify(authResponse.json)).to.be.equal(
335+
JSON.stringify(expectedMakeAPICall),
336+
);
337+
});
338+
});
309339
it('Make API Call in Sandbox Environment with headers as parameters', () => {
310340
oauthClient.getToken().realmId = '12345';
311341
// eslint-disable-next-line no-useless-concat
@@ -322,6 +352,38 @@ describe('Tests for OAuthClient', () => {
322352
);
323353
});
324354
});
355+
it('Make API Call in Sandbox Environment with headers as parameters, relative endpoint path - starting slash', () => {
356+
oauthClient.getToken().realmId = '12345';
357+
// eslint-disable-next-line no-useless-concat
358+
return oauthClient
359+
.makeApiCall({
360+
url: `/v3/company/12345/companyinfo/12345`,
361+
headers: {
362+
Accept: 'application/json',
363+
},
364+
})
365+
.then((authResponse) => {
366+
expect(JSON.stringify(authResponse.json)).to.be.equal(
367+
JSON.stringify(expectedMakeAPICall),
368+
);
369+
});
370+
});
371+
it('Make API Call in Sandbox Environment with headers as parameters, relative endpoint path - no starting slash', () => {
372+
oauthClient.getToken().realmId = '12345';
373+
// eslint-disable-next-line no-useless-concat
374+
return oauthClient
375+
.makeApiCall({
376+
url: `v3/company/12345/companyinfo/12345`,
377+
headers: {
378+
Accept: 'application/json',
379+
},
380+
})
381+
.then((authResponse) => {
382+
expect(JSON.stringify(authResponse.json)).to.be.equal(
383+
JSON.stringify(expectedMakeAPICall),
384+
);
385+
});
386+
});
325387
xit('loadResponseFromJWKsURI', () => {
326388
const request = {
327389
url: 'https://sandbox-quickbooks.api.intuit.com/v3/company/12345/companyinfo/12345',
@@ -362,6 +424,36 @@ describe('Tests for OAuthClient', () => {
362424
);
363425
});
364426
});
427+
it('Make API Call in Production Environment with relative endpoint path - starting slash', () => {
428+
oauthClient.environment = 'production';
429+
oauthClient.getToken().realmId = '12345';
430+
// eslint-disable-next-line no-useless-concat
431+
return oauthClient
432+
.makeApiCall({
433+
url:
434+
'/v3/company/' + '12345' + '/companyinfo/' + '12345',
435+
})
436+
.then((authResponse) => {
437+
expect(JSON.stringify(authResponse.json)).to.be.equal(
438+
JSON.stringify(expectedMakeAPICall),
439+
);
440+
});
441+
});
442+
it('Make API Call in Production Environment with relative endpoing path - no starting slash', () => {
443+
oauthClient.environment = 'production';
444+
oauthClient.getToken().realmId = '12345';
445+
// eslint-disable-next-line no-useless-concat
446+
return oauthClient
447+
.makeApiCall({
448+
url:
449+
'v3/company/' + '12345' + '/companyinfo/' + '12345',
450+
})
451+
.then((authResponse) => {
452+
expect(JSON.stringify(authResponse.json)).to.be.equal(
453+
JSON.stringify(expectedMakeAPICall),
454+
);
455+
});
456+
});
365457
});
366458
});
367459

@@ -635,3 +727,124 @@ describe('Test Logging', () => {
635727
expect(oauthClient.logger.log.firstCall.args[1]).to.be.equal(message + messageData);
636728
});
637729
});
730+
731+
describe('Tests whether the correct environment urls is returned', () => {
732+
describe('tests sandbox environment', () => {
733+
it('returns the sandbox environment URL when environment is not set', () => {
734+
oauthClient.environment = null;
735+
const environmentURI = oauthClient.getEnvironmentURI();
736+
expect(environmentURI).to.be.equal(OAuthClientTest.environment.sandbox);
737+
});
738+
it('returns the sandbox environment URL when environment is sandbox', () => {
739+
oauthClient.environment = 'sandbox';
740+
const environmentURI = oauthClient.getEnvironmentURI();
741+
expect(environmentURI).to.be.equal(OAuthClientTest.environment.sandbox);
742+
});
743+
it('returns the sandbox environment URL when sandbox environment is misspelt', () => {
744+
oauthClient.environment = 'sandoboxo';
745+
const environmentURI = oauthClient.getEnvironmentURI();
746+
expect(environmentURI).to.be.equal(OAuthClientTest.environment.sandbox);
747+
});
748+
749+
});
750+
describe('tests production environment', () => {
751+
it('returns the production environment URL when environment is production', () => {
752+
oauthClient.environment = 'production';
753+
const environmentURI = oauthClient.getEnvironmentURI();
754+
expect(environmentURI).to.be.equal(OAuthClientTest.environment.production);
755+
});
756+
it('returns the sandbox environment URL when production environment is misspelt', () => {
757+
oauthClient.environment = 'productio';
758+
const environmentURI = oauthClient.getEnvironmentURI();
759+
expect(environmentURI).to.be.equal(OAuthClientTest.environment.sandbox);
760+
});
761+
});
762+
});
763+
764+
765+
766+
describe('Tests whether the correct Quickbooks online (QBO) environment urls is returned', () => {
767+
describe('tests sandbox environment', () => {
768+
it('returns the sandbox QBO environment URL when environment is not set', () => {
769+
oauthClient.environment = null;
770+
const qboEnvironmentURI = oauthClient.getQBOEnvironmentURI();
771+
expect(qboEnvironmentURI).to.be.equal(OAuthClientTest.qbo_environment.sandbox);
772+
});
773+
it('returns the sandbox environment URL when environment is sandbox', () => {
774+
oauthClient.environment = 'sandbox';
775+
const qboEnvironmentURI = oauthClient.getQBOEnvironmentURI();
776+
expect(qboEnvironmentURI).to.be.equal(OAuthClientTest.qbo_environment.sandbox);
777+
});
778+
it('returns the sandbox environment URL when sandbox environment is misspelt', () => {
779+
oauthClient.environment = 'sandoboxo';
780+
const qboEnvironmentURI = oauthClient.getQBOEnvironmentURI();
781+
expect(qboEnvironmentURI).to.be.equal(OAuthClientTest.qbo_environment.sandbox);
782+
});
783+
784+
});
785+
describe('tests production environment', () => {
786+
it('returns the production environment URL when environment is production', () => {
787+
oauthClient.environment = 'production';
788+
const qboEnvironmentURI = oauthClient.getQBOEnvironmentURI();
789+
expect(qboEnvironmentURI).to.be.equal(OAuthClientTest.qbo_environment.production);
790+
791+
});
792+
it('returns the sandbox environment URL when production environment is misspelt', () => {
793+
oauthClient.environment = 'productio';
794+
const qboEnvironmentURI = oauthClient.getQBOEnvironmentURI();
795+
expect(qboEnvironmentURI).to.be.equal(OAuthClientTest.qbo_environment.sandbox);
796+
797+
});
798+
});
799+
});
800+
801+
802+
803+
// must be last test as it changes the endpoints
804+
describe('Tests for OAuthClient to set custom Authorization URIs', () => {
805+
describe('set the authorizationURIs', () => {
806+
it('throws an error when no params provided', () => {
807+
expect(() => { oauthClient.setAuthorizeURLs() }).to.throw("Provide the custom authorize URL's");
808+
});
809+
it('throws an error when no params provided', () => {
810+
expect(() => { oauthClient.setAuthorizeURLs(null) }).to.throw("Provide the custom authorize URL's");
811+
});
812+
it('sets the Authorise urls to custom ones - sandbox', async (done) => {
813+
const customURLs = {
814+
authorizeEndpoint: "https://custom.Authorize.Endpoint",
815+
tokenEndpoint: "https://custom.Token.Endpoint",
816+
revokeEndpoint: "https://custom.Revoke.Endpoint",
817+
userInfoEndpoint: "https://custom.User.Info.Endpoint",
818+
}
819+
820+
oauthClient.environment = 'sandbox';
821+
oauthClient.setAuthorizeURLs(customURLs);
822+
done();
823+
expect(OAuthClientTest.authorizeEndpoint).to.be.equal('https://custom.Authorize.Endpoint');
824+
expect(OAuthClientTest.tokenEndpoint).to.be.equal('https://custom.Token.Endpoint');
825+
expect(OAuthClientTest.revokeEndpoint).to.be.equal('https://custom.Revoke.Endpoint');
826+
expect(OAuthClientTest.userinfo_endpoint_sandbox).to.be.equal('https://custom.User.Info.Endpoint');
827+
expect(OAuthClientTest.userinfo_endpoint_production).to.be.equal('https://accounts.platform.intuit.com/v1/openid_connect/userinfo');
828+
829+
});
830+
it('sets the Authorise urls to custom ones - production', async (done) => {
831+
const customURLs = {
832+
authorizeEndpoint: "https://custom.Authorize.Endpoint",
833+
tokenEndpoint: "https://custom.Token.Endpoint",
834+
revokeEndpoint: "https://custom.Revoke.Endpoint",
835+
userInfoEndpoint: "https://custom.User.Info.Endpoint",
836+
}
837+
838+
oauthClient.environment = 'production';
839+
oauthClient.setAuthorizeURLs(customURLs);
840+
done();
841+
expect(OAuthClientTest.authorizeEndpoint).to.be.equal('https://custom.Authorize.Endpoint');
842+
expect(OAuthClientTest.tokenEndpoint).to.be.equal('https://custom.Token.Endpoint');
843+
expect(OAuthClientTest.revokeEndpoint).to.be.equal('https://custom.Revoke.Endpoint');
844+
expect(OAuthClientTest.userinfo_endpoint_sandbox).to.be.equal('https://sandbox-accounts.platform.intuit.com/v1/openid_connect/userinfo');
845+
expect(OAuthClientTest.userinfo_endpoint_production).to.be.equal('https://custom.User.Info.Endpoint');
846+
847+
});
848+
});
849+
850+
});

0 commit comments

Comments
 (0)