Skip to content
This repository was archived by the owner on Aug 8, 2023. It is now read-only.

Commit 7b786a2

Browse files
authored
Merge release-v0.1.11 into master
2 parents 0216c82 + 798cde8 commit 7b786a2

File tree

5 files changed

+138
-5
lines changed

5 files changed

+138
-5
lines changed

.circleci/config.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ jobs:
3434
- deploy:
3535
command: |
3636
if [ "${CIRCLE_BRANCH}" == "master" ]; then
37-
# NPM login based on env variables
38-
echo -e "$NPM_USERNAME\n$NPM_PASSWORD\n$NPM_EMAIL" | npm login
37+
# Add NPM token to allow publishing from Circle
38+
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ~/.npmrc
39+
3940
npm publish
4041
fi

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## v0.1.11 (August 22, 2019)
2+
- Use NPM authentication token for circleci publishing.
3+
- Fix `callApi` JSON error parsing never settling its Promise.
4+
15
## v0.1.10 (July 2, 2019)
26
- Run security audit and upgrade offending npm dependencies. [#23](https://github.com/mobify/commercecloud-ocapi-client/pull/23)
37

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "commercecloud-ocapi-client",
3-
"version": "0.1.10",
3+
"version": "0.1.11",
44
"description": "An ES6 JavaScript Client for Salesforce Open Commerce API",
55
"repository": "https://github.com/mobify/commercecloud-ocapi-client",
66
"license": "SEE LICENSE IN LICENSE",

src/ApiClient.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -494,15 +494,30 @@ export default class ApiClient {
494494
}
495495
}
496496

497+
return this.sendApiRequest(request, returnType)
498+
}
499+
500+
/**
501+
* Sends the generated superagent request and deserializes the response.
502+
* @param {module:superagent.Request} request The superagent request to send.
503+
* @param {String} returnType The type to deserialize the response into.
504+
* @returns {Promise} A {@link https://www.promisejs.org/|Promise} object.
505+
*/
506+
sendApiRequest(request, returnType) {
497507
return new Promise((resolve, reject) => {
498508
request.end((error, response) => {
499509
if (error) {
500510

501511
// Looks like there was an fault returned from the API
502512
const hasErrorMessage = error.response && error.response.text
503513
if (hasErrorMessage) {
504-
const fault = Fault.constructFromObject(JSON.parse(error.response.text).fault)
505-
reject(fault)
514+
try {
515+
const fault = Fault.constructFromObject(JSON.parse(error.response.text).fault)
516+
reject(fault)
517+
} catch (err) {
518+
// Reject immediately on parsing error.
519+
reject(err)
520+
}
506521
}
507522

508523
// Most likely a network error has happened here so include entire error.

test/api/ApiClient.spec.js

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * */
2+
/* Copyright (c) 2019 Mobify Research & Development Inc. All rights reserved. */
3+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * */
4+
5+
import expect from 'expect.js'
6+
import sinon from 'sinon'
7+
8+
import ShopApi from '../../src/index'
9+
import {clientId, baseUrl} from '../config.json'
10+
11+
let client
12+
13+
beforeEach(() => {
14+
client = new ShopApi.ApiClient({
15+
basePath: `${baseUrl}`,
16+
defaultHeaders: {'x-dw-client-id': clientId}
17+
})
18+
})
19+
20+
describe('ApiClient', () => {
21+
describe('sendApiRequest', () => {
22+
let mockRequest
23+
24+
beforeEach(() => {
25+
mockRequest = {end: sinon.stub()}
26+
})
27+
28+
it('should deserialize a successful response into a string', () => {
29+
const mockData = Symbol()
30+
const mockResponse = Symbol()
31+
32+
client.deserialize = sinon.stub().returns(mockData)
33+
mockRequest.end.callsArgWith(0, null, mockResponse)
34+
35+
return client.sendApiRequest(mockRequest, 'String')
36+
.then((result) => {
37+
expect(result.data).to.be(mockData)
38+
expect(result.response).to.be(mockResponse)
39+
expect(client.deserialize.calledWith(mockResponse, 'String')).to.be(true)
40+
})
41+
})
42+
43+
it('should deserialize the response into a blob', () => {
44+
const mockData = Symbol()
45+
const mockResponse = Symbol()
46+
47+
client.deserialize = sinon.stub().returns(mockData)
48+
mockRequest.end.callsArgWith(0, null, mockResponse)
49+
50+
return client.sendApiRequest(mockRequest, 'Blob')
51+
.then((result) => {
52+
expect(result.data).to.be(mockData)
53+
expect(result.response).to.be(mockResponse)
54+
expect(client.deserialize.calledWith(mockResponse, 'Blob')).to.be(true)
55+
})
56+
})
57+
58+
it('should reject when deserializing the response throws an error', () => {
59+
const mockError = Symbol()
60+
61+
client.deserialize = sinon.stub().throws(mockError)
62+
mockRequest.end.callsArg(0)
63+
64+
return client.sendApiRequest(mockRequest, 'String')
65+
.catch((error) => {
66+
expect(error).to.be(mockError)
67+
})
68+
})
69+
70+
it('should reject when the request fails with valid JSON', () => {
71+
const mockError = {
72+
response: {
73+
text: '{ "fault": { "message": "foo", "type": "bar" } }'
74+
}
75+
}
76+
77+
mockRequest.end.callsArgWith(0, mockError)
78+
79+
return client.sendApiRequest(mockRequest, 'String')
80+
.catch((error) => {
81+
expect(error).to.be.a(ShopApi.Fault)
82+
expect(error.message).to.equal('foo')
83+
expect(error.type).to.equal('bar')
84+
})
85+
})
86+
87+
it('should reject when the request fails with HTML', () => {
88+
const mockError = {
89+
response: {
90+
text: '<html><head></head><body></body></html>'
91+
}
92+
}
93+
94+
mockRequest.end.callsArgWith(0, mockError)
95+
96+
return client.sendApiRequest(mockRequest, 'String')
97+
.catch((error) => {
98+
expect(error).to.be.a(SyntaxError)
99+
})
100+
})
101+
102+
it('should reject when the request fails for any reason', () => {
103+
const mockError = Symbol()
104+
105+
mockRequest.end.callsArgWith(0, mockError)
106+
107+
return client.sendApiRequest(mockRequest, 'String')
108+
.catch((error) => {
109+
expect(error).to.be(mockError)
110+
})
111+
})
112+
})
113+
})

0 commit comments

Comments
 (0)