smartystreets-javascript-sdk 1.13.7 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Makefile +2 -2
- package/package.json +3 -3
- package/src/ClientBuilder.js +8 -2
- package/src/HttpSender.js +4 -12
- package/src/Response.js +2 -1
- package/src/RetrySender.js +50 -0
- package/src/international_street/Candidate.js +8 -0
- package/src/util/Sleeper.js +8 -0
- package/src/util/buildSmartyResponse.js +10 -0
- package/tests/fixtures/MockSleeper.js +10 -0
- package/tests/fixtures/mock_senders.js +19 -1
- package/tests/international_street/test_Candidate.js +16 -0
- package/tests/test_HttpSender.js +3 -2
- package/tests/test_RetrySender.js +98 -0
package/Makefile
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/make -f
|
|
2
2
|
|
|
3
|
-
VERSION := $(shell tagit -
|
|
3
|
+
VERSION := $(shell tagit -m --dry-run)
|
|
4
4
|
VERSION_FILE1 := package.json
|
|
5
5
|
VERSION_FILE2 := package-lock.json
|
|
6
6
|
|
|
@@ -11,7 +11,7 @@ node_modules:
|
|
|
11
11
|
npm install
|
|
12
12
|
|
|
13
13
|
publish: test version upload unversion
|
|
14
|
-
tagit -
|
|
14
|
+
tagit -m
|
|
15
15
|
git push origin --tags
|
|
16
16
|
|
|
17
17
|
upload:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "smartystreets-javascript-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Quick and easy Smarty address validation.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"smarty",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"url": "github:smartystreets/smartystreets-javascript-sdk"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"chai": "^4.
|
|
36
|
-
"mocha": "^9.2.
|
|
35
|
+
"chai": "^4.3.6",
|
|
36
|
+
"mocha": "^9.2.2"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"axios": "^0.26.1",
|
package/src/ClientBuilder.js
CHANGED
|
@@ -8,6 +8,8 @@ const CustomHeaderSender = require("./CustomHeaderSender");
|
|
|
8
8
|
const StatusCodeSender = require("./StatusCodeSender");
|
|
9
9
|
const LicenseSender = require("./LicenseSender");
|
|
10
10
|
const BadCredentialsError = require("./Errors").BadCredentialsError;
|
|
11
|
+
const RetrySender = require("./RetrySender.js");
|
|
12
|
+
const Sleeper = require("./util/Sleeper.js");
|
|
11
13
|
|
|
12
14
|
//TODO: refactor this to work more cleanly with a bundler.
|
|
13
15
|
const UsStreetClient = require("./us_street/Client");
|
|
@@ -151,10 +153,14 @@ class ClientBuilder {
|
|
|
151
153
|
buildSender() {
|
|
152
154
|
if (this.httpSender) return this.httpSender;
|
|
153
155
|
|
|
154
|
-
const httpSender = new HttpSender(this.maxTimeout, this.
|
|
156
|
+
const httpSender = new HttpSender(this.maxTimeout, this.proxy, this.debug);
|
|
155
157
|
const statusCodeSender = new StatusCodeSender(httpSender);
|
|
156
158
|
const signingSender = new SigningSender(statusCodeSender, this.signer);
|
|
157
|
-
|
|
159
|
+
let agentSender = new AgentSender(signingSender);
|
|
160
|
+
if (this.maxRetries > 0) {
|
|
161
|
+
const retrySender = new RetrySender(this.maxRetries, signingSender, new Sleeper());
|
|
162
|
+
agentSender = new AgentSender(retrySender);
|
|
163
|
+
}
|
|
158
164
|
const customHeaderSender = new CustomHeaderSender(agentSender, this.customHeaders);
|
|
159
165
|
const baseUrlSender = new BaseUrlSender(customHeaderSender, this.baseUrl);
|
|
160
166
|
const licenseSender = new LicenseSender(baseUrlSender, this.licenses);
|
package/src/HttpSender.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
const Response = require("./Response");
|
|
2
2
|
const Axios = require("axios");
|
|
3
|
-
const
|
|
3
|
+
const {buildSmartyResponse} = require("../src/util/buildSmartyResponse");
|
|
4
4
|
|
|
5
5
|
class HttpSender {
|
|
6
|
-
constructor(timeout = 10000,
|
|
7
|
-
axiosRetry(Axios, {
|
|
8
|
-
retries: retries,
|
|
9
|
-
});
|
|
6
|
+
constructor(timeout = 10000, proxyConfig, debug = false) {
|
|
10
7
|
this.timeout = timeout;
|
|
11
8
|
this.proxyConfig = proxyConfig;
|
|
12
9
|
if (debug) this.enableDebug();
|
|
@@ -33,24 +30,19 @@ class HttpSender {
|
|
|
33
30
|
return config;
|
|
34
31
|
}
|
|
35
32
|
|
|
36
|
-
buildSmartyResponse(response, error) {
|
|
37
|
-
if (response) return new Response(response.status, response.data);
|
|
38
|
-
return new Response(undefined, undefined, error)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
33
|
send(request) {
|
|
42
34
|
return new Promise((resolve, reject) => {
|
|
43
35
|
let requestConfig = this.buildRequestConfig(request);
|
|
44
36
|
|
|
45
37
|
Axios(requestConfig)
|
|
46
38
|
.then(response => {
|
|
47
|
-
let smartyResponse =
|
|
39
|
+
let smartyResponse = buildSmartyResponse(response);
|
|
48
40
|
|
|
49
41
|
if (smartyResponse.statusCode >= 400) reject(smartyResponse);
|
|
50
42
|
|
|
51
43
|
resolve(smartyResponse);
|
|
52
44
|
})
|
|
53
|
-
.catch(error => reject(
|
|
45
|
+
.catch(error => reject(buildSmartyResponse(undefined, error)));
|
|
54
46
|
});
|
|
55
47
|
}
|
|
56
48
|
|
package/src/Response.js
CHANGED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
class RetrySender {
|
|
2
|
+
constructor(maxRetires = 5, inner, sleeper) {
|
|
3
|
+
this.maxRetries = maxRetires;
|
|
4
|
+
this.statusToRetry = [408, 429, 500, 502, 503, 504];
|
|
5
|
+
this.statusTooManyRequests = 429;
|
|
6
|
+
this.maxBackoffDuration = 10;
|
|
7
|
+
this.inner = inner;
|
|
8
|
+
this.sleeper = sleeper;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async send(request) {
|
|
12
|
+
let response = await this.inner.send(request);
|
|
13
|
+
|
|
14
|
+
for (let i = 0; i < this.maxRetries; i++) {
|
|
15
|
+
|
|
16
|
+
if (!this.statusToRetry.includes(parseInt(response.statusCode))) {
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (parseInt(response.statusCode) === this.statusTooManyRequests) {
|
|
21
|
+
let secondsToBackoff = 10;
|
|
22
|
+
if (response.headers) {
|
|
23
|
+
const retryAfterHeader = response.headers["Retry-After"];
|
|
24
|
+
if (Number.isInteger(retryAfterHeader)) {
|
|
25
|
+
secondsToBackoff = retryAfterHeader;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
await this.rateLimitBackOff(secondsToBackoff);
|
|
29
|
+
} else {
|
|
30
|
+
await this.backoff(i);
|
|
31
|
+
}
|
|
32
|
+
response = await this.inner.send(request);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return response;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
async backoff(attempt) {
|
|
39
|
+
const backoffDuration = Math.min(attempt, this.maxBackoffDuration);
|
|
40
|
+
console.log(`There was an error processing the request. Retrying in ${backoffDuration} seconds...`);
|
|
41
|
+
await this.sleeper.sleep(backoffDuration);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
async rateLimitBackOff(backoffDuration) {
|
|
45
|
+
console.log(`Rate limit reached. Retrying in ${backoffDuration} seconds...`);
|
|
46
|
+
await this.sleeper.sleep(backoffDuration);
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = RetrySender;
|
|
@@ -25,6 +25,8 @@ class Candidate {
|
|
|
25
25
|
this.components.countryIso3 = responseData.components.country_iso_3;
|
|
26
26
|
this.components.superAdministrativeArea = responseData.components.super_administrative_area;
|
|
27
27
|
this.components.administrativeArea = responseData.components.administrative_area;
|
|
28
|
+
this.components.administrativeAreaShort = responseData.components.administrative_area_short;
|
|
29
|
+
this.components.administrativeAreaLong = responseData.components.administrative_area_long;
|
|
28
30
|
this.components.subAdministrativeArea = responseData.components.sub_administrative_area;
|
|
29
31
|
this.components.dependentLocality = responseData.components.dependent_locality;
|
|
30
32
|
this.components.dependentLocalityName = responseData.components.dependent_locality_name;
|
|
@@ -58,6 +60,8 @@ class Candidate {
|
|
|
58
60
|
this.components.subBuildingNumber = responseData.components.sub_building_number;
|
|
59
61
|
this.components.subBuildingName = responseData.components.sub_building_name;
|
|
60
62
|
this.components.subBuilding = responseData.components.sub_building;
|
|
63
|
+
this.components.levelType = responseData.components.level_type;
|
|
64
|
+
this.components.levelNumber = responseData.components.level_number;
|
|
61
65
|
this.components.postBox = responseData.components.post_box;
|
|
62
66
|
this.components.postBoxType = responseData.components.post_box_type;
|
|
63
67
|
this.components.postBoxNumber = responseData.components.post_box_number;
|
|
@@ -90,6 +94,8 @@ class Candidate {
|
|
|
90
94
|
this.analysis.changes.components.countryIso3 = responseData.analysis.changes.components.country_iso_3;
|
|
91
95
|
this.analysis.changes.components.superAdministrativeArea = responseData.analysis.changes.components.super_administrative_area;
|
|
92
96
|
this.analysis.changes.components.administrativeArea = responseData.analysis.changes.components.administrative_area;
|
|
97
|
+
this.analysis.changes.components.administrativeAreaShort = responseData.analysis.changes.components.administrative_area_short;
|
|
98
|
+
this.analysis.changes.components.administrativeAreaLong = responseData.analysis.changes.components.administrative_area_long;
|
|
93
99
|
this.analysis.changes.components.subAdministrativeArea = responseData.analysis.changes.components.sub_administrative_area;
|
|
94
100
|
this.analysis.changes.components.dependentLocality = responseData.analysis.changes.components.dependent_locality;
|
|
95
101
|
this.analysis.changes.components.dependentLocalityName = responseData.analysis.changes.components.dependent_locality_name;
|
|
@@ -123,6 +129,8 @@ class Candidate {
|
|
|
123
129
|
this.analysis.changes.components.subBuildingNumber = responseData.analysis.changes.components.sub_building_number;
|
|
124
130
|
this.analysis.changes.components.subBuildingName = responseData.analysis.changes.components.sub_building_name;
|
|
125
131
|
this.analysis.changes.components.subBuilding = responseData.analysis.changes.components.sub_building;
|
|
132
|
+
this.analysis.changes.components.levelType = responseData.analysis.changes.components.level_type;
|
|
133
|
+
this.analysis.changes.components.levelNumber = responseData.analysis.changes.components.level_number;
|
|
126
134
|
this.analysis.changes.components.postBox = responseData.analysis.changes.components.post_box;
|
|
127
135
|
this.analysis.changes.components.postBoxType = responseData.analysis.changes.components.post_box_type;
|
|
128
136
|
this.analysis.changes.components.postBoxNumber = responseData.analysis.changes.components.post_box_number;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const Response = require("../Response.js");
|
|
2
|
+
|
|
3
|
+
function buildSmartyResponse(response, error) {
|
|
4
|
+
if (response) return new Response(response.status, response.data, response.error, response.headers);
|
|
5
|
+
return new Response(undefined, undefined, error)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
module.exports = {
|
|
9
|
+
buildSmartyResponse
|
|
10
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const {buildSmartyResponse} = require("../../src/util/buildSmartyResponse.js");
|
|
1
2
|
const Response = require("../../src/Response");
|
|
2
3
|
|
|
3
4
|
module.exports = {
|
|
@@ -20,4 +21,21 @@ module.exports = {
|
|
|
20
21
|
});
|
|
21
22
|
}
|
|
22
23
|
},
|
|
23
|
-
|
|
24
|
+
MockSenderWithStatusCodesAndHeaders: function (statusCodes, headers = undefined, error = undefined) {
|
|
25
|
+
this.statusCodes = statusCodes;
|
|
26
|
+
this.headers = headers;
|
|
27
|
+
this.error = error;
|
|
28
|
+
this.currentStatusCodeIndex = 0;
|
|
29
|
+
|
|
30
|
+
this.send = function (request) {
|
|
31
|
+
let mockResponse = {
|
|
32
|
+
status: this.statusCodes[this.currentStatusCodeIndex],
|
|
33
|
+
headers: this.headers,
|
|
34
|
+
error: this.error,
|
|
35
|
+
};
|
|
36
|
+
const response = buildSmartyResponse(mockResponse);
|
|
37
|
+
this.currentStatusCodeIndex += 1;
|
|
38
|
+
return response;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
};
|
|
@@ -22,6 +22,8 @@ describe("An International match candidate", function () {
|
|
|
22
22
|
country_iso_3: "14",
|
|
23
23
|
super_administrative_area: "15",
|
|
24
24
|
administrative_area: "16",
|
|
25
|
+
administrative_area_short: "16.1",
|
|
26
|
+
administrative_area_long: "16.2",
|
|
25
27
|
sub_administrative_area: "17",
|
|
26
28
|
dependent_locality: "18",
|
|
27
29
|
dependent_locality_name: "19",
|
|
@@ -55,6 +57,8 @@ describe("An International match candidate", function () {
|
|
|
55
57
|
sub_building_number: "46",
|
|
56
58
|
sub_building_name: "47",
|
|
57
59
|
sub_building: "48",
|
|
60
|
+
level_type: "48.1",
|
|
61
|
+
level_number: "48.2",
|
|
58
62
|
post_box: "49",
|
|
59
63
|
post_box_type: "50",
|
|
60
64
|
post_box_number: "51",
|
|
@@ -88,6 +92,8 @@ describe("An International match candidate", function () {
|
|
|
88
92
|
country_iso_3: "73",
|
|
89
93
|
super_administrative_area: "74",
|
|
90
94
|
administrative_area: "75",
|
|
95
|
+
administrative_area_short: "75.1",
|
|
96
|
+
administrative_area_long: "75.2",
|
|
91
97
|
sub_administrative_area: "76",
|
|
92
98
|
dependent_locality: "77",
|
|
93
99
|
dependent_locality_name: "78",
|
|
@@ -121,6 +127,8 @@ describe("An International match candidate", function () {
|
|
|
121
127
|
sub_building_number: "106",
|
|
122
128
|
sub_building_name: "107",
|
|
123
129
|
sub_building: "108",
|
|
130
|
+
level_type: "108.1",
|
|
131
|
+
level_number: "108.2",
|
|
124
132
|
post_box: "109",
|
|
125
133
|
post_box_type: "110",
|
|
126
134
|
post_box_number: "111",
|
|
@@ -148,6 +156,8 @@ describe("An International match candidate", function () {
|
|
|
148
156
|
expect(components.countryIso3).to.equal("14");
|
|
149
157
|
expect(components.superAdministrativeArea).to.equal("15");
|
|
150
158
|
expect(components.administrativeArea).to.equal("16");
|
|
159
|
+
expect(components.administrativeAreaShort).to.equal("16.1");
|
|
160
|
+
expect(components.administrativeAreaLong).to.equal("16.2");
|
|
151
161
|
expect(components.subAdministrativeArea).to.equal("17");
|
|
152
162
|
expect(components.dependentLocality).to.equal("18");
|
|
153
163
|
expect(components.dependentLocalityName).to.equal("19");
|
|
@@ -181,6 +191,8 @@ describe("An International match candidate", function () {
|
|
|
181
191
|
expect(components.subBuildingNumber).to.equal("46");
|
|
182
192
|
expect(components.subBuildingName).to.equal("47");
|
|
183
193
|
expect(components.subBuilding).to.equal("48");
|
|
194
|
+
expect(components.levelType).to.equal("48.1");
|
|
195
|
+
expect(components.levelNumber).to.equal("48.2");
|
|
184
196
|
expect(components.postBox).to.equal("49");
|
|
185
197
|
expect(components.postBoxType).to.equal("50");
|
|
186
198
|
expect(components.postBoxNumber).to.equal("51");
|
|
@@ -212,6 +224,8 @@ describe("An International match candidate", function () {
|
|
|
212
224
|
expect(ccomponents.countryIso3).to.equal("73");
|
|
213
225
|
expect(ccomponents.superAdministrativeArea).to.equal("74");
|
|
214
226
|
expect(ccomponents.administrativeArea).to.equal("75");
|
|
227
|
+
expect(ccomponents.administrativeAreaShort).to.equal("75.1");
|
|
228
|
+
expect(ccomponents.administrativeAreaLong).to.equal("75.2");
|
|
215
229
|
expect(ccomponents.subAdministrativeArea).to.equal("76");
|
|
216
230
|
expect(ccomponents.dependentLocality).to.equal("77");
|
|
217
231
|
expect(ccomponents.dependentLocalityName).to.equal("78");
|
|
@@ -245,6 +259,8 @@ describe("An International match candidate", function () {
|
|
|
245
259
|
expect(ccomponents.subBuildingNumber).to.equal("106");
|
|
246
260
|
expect(ccomponents.subBuildingName).to.equal("107");
|
|
247
261
|
expect(ccomponents.subBuilding).to.equal("108");
|
|
262
|
+
expect(ccomponents.levelType).to.equal("108.1");
|
|
263
|
+
expect(ccomponents.levelNumber).to.equal("108.2");
|
|
248
264
|
expect(ccomponents.postBox).to.equal("109");
|
|
249
265
|
expect(ccomponents.postBoxType).to.equal("110");
|
|
250
266
|
expect(ccomponents.postBoxNumber).to.equal("111");
|
package/tests/test_HttpSender.js
CHANGED
|
@@ -2,6 +2,7 @@ const chai = require("chai");
|
|
|
2
2
|
const expect = chai.expect;
|
|
3
3
|
const Request = require("../src/Request");
|
|
4
4
|
const HttpSender = require("../src/HttpSender");
|
|
5
|
+
const {buildSmartyResponse} = require("../src/util/buildSmartyResponse");
|
|
5
6
|
|
|
6
7
|
describe ("An Axios implementation of a HTTP sender", function () {
|
|
7
8
|
it("adds a data payload to the HTTP request config.", function () {
|
|
@@ -71,7 +72,7 @@ describe ("An Axios implementation of a HTTP sender", function () {
|
|
|
71
72
|
let mockResponse = {
|
|
72
73
|
status: 200
|
|
73
74
|
};
|
|
74
|
-
let smartyResponse =
|
|
75
|
+
let smartyResponse = buildSmartyResponse(mockResponse);
|
|
75
76
|
|
|
76
77
|
expect(smartyResponse.hasOwnProperty("statusCode")).to.equal(true);
|
|
77
78
|
expect(smartyResponse.statusCode).to.equal(200);
|
|
@@ -84,7 +85,7 @@ describe ("An Axios implementation of a HTTP sender", function () {
|
|
|
84
85
|
status: 200,
|
|
85
86
|
data: mockData
|
|
86
87
|
};
|
|
87
|
-
let smartyResponse =
|
|
88
|
+
let smartyResponse = buildSmartyResponse(mockResponse);
|
|
88
89
|
|
|
89
90
|
expect(smartyResponse.hasOwnProperty("payload")).to.equal(true);
|
|
90
91
|
expect(smartyResponse.payload).to.equal(mockData);
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
const chai = require("chai");
|
|
2
|
+
const expect = chai.expect;
|
|
3
|
+
const RetrySender = require("../src/RetrySender");
|
|
4
|
+
const {MockSenderWithStatusCodesAndHeaders} = require("./fixtures/mock_senders");
|
|
5
|
+
const Request = require("../src/Request.js");
|
|
6
|
+
const MockSleeper = require("./fixtures/MockSleeper.js");
|
|
7
|
+
|
|
8
|
+
async function sendWithRetry(retries, inner, sleeper) {
|
|
9
|
+
const request = new Request();
|
|
10
|
+
const sender = new RetrySender(retries, inner, sleeper);
|
|
11
|
+
return await sender.send(request);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
describe ("Retry Sender tests", function () {
|
|
15
|
+
it("test success does not retry", async function () {
|
|
16
|
+
let inner = new MockSenderWithStatusCodesAndHeaders(["200"]);
|
|
17
|
+
await sendWithRetry(5, inner, new MockSleeper());
|
|
18
|
+
|
|
19
|
+
expect(inner.currentStatusCodeIndex).to.equal(1);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("test client error does not retry", async function () {
|
|
23
|
+
let inner = new MockSenderWithStatusCodesAndHeaders(["422"]);
|
|
24
|
+
await sendWithRetry(5, inner, new MockSleeper());
|
|
25
|
+
|
|
26
|
+
expect(inner.currentStatusCodeIndex).to.equal(1);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("test will retry until success", async function () {
|
|
30
|
+
let inner = new MockSenderWithStatusCodesAndHeaders(["500", "500", "500", "200", "500"]);
|
|
31
|
+
await sendWithRetry(10, inner, new MockSleeper());
|
|
32
|
+
|
|
33
|
+
expect(inner.currentStatusCodeIndex).to.equal(4);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("test return response if retry limit exceeded", async function () {
|
|
37
|
+
let inner = new MockSenderWithStatusCodesAndHeaders(["500", "500", "500", "500", "500"]);
|
|
38
|
+
const sleeper = new MockSleeper();
|
|
39
|
+
const response = await sendWithRetry(4, inner, sleeper);
|
|
40
|
+
|
|
41
|
+
expect(response);
|
|
42
|
+
expect(inner.currentStatusCodeIndex).to.equal(5);
|
|
43
|
+
expect(response.statusCode).to.equal("500");
|
|
44
|
+
expect(sleeper.sleepDurations).to.deep.equal([0, 1, 2, 3]);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("test backoff does not exceed max", async function () {
|
|
48
|
+
let inner = new MockSenderWithStatusCodesAndHeaders(["500", "500", "500", "500", "500", "500", "500", "500", "500", "500", "500", "500", "500", "200"]);
|
|
49
|
+
const sleeper = new MockSleeper();
|
|
50
|
+
|
|
51
|
+
await sendWithRetry(20, inner, sleeper);
|
|
52
|
+
|
|
53
|
+
expect(sleeper.sleepDurations).to.deep.equal([0,1,2,3,4,5,6,7,8,9,10,10,10]);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("test empty status does not retry", async function () {
|
|
57
|
+
let inner = new MockSenderWithStatusCodesAndHeaders([]);
|
|
58
|
+
await sendWithRetry(5, inner, new MockSleeper());
|
|
59
|
+
|
|
60
|
+
expect(inner.currentStatusCodeIndex).to.equal(1);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("test sleep on rate limit", async function () {
|
|
64
|
+
let inner = new MockSenderWithStatusCodesAndHeaders(["429", "200"]);
|
|
65
|
+
const sleeper = new MockSleeper();
|
|
66
|
+
|
|
67
|
+
await sendWithRetry(5, inner, sleeper);
|
|
68
|
+
|
|
69
|
+
expect(sleeper.sleepDurations).to.deep.equal([10]);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("test rate limit error return", async function () {
|
|
73
|
+
let inner = new MockSenderWithStatusCodesAndHeaders(["429"], {"Retry-After": 7});
|
|
74
|
+
const sleeper = new MockSleeper();
|
|
75
|
+
|
|
76
|
+
await sendWithRetry(10, inner, sleeper);
|
|
77
|
+
|
|
78
|
+
expect(sleeper.sleepDurations).to.deep.equal([7]);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("test retry after invalid value", async function () {
|
|
82
|
+
let inner = new MockSenderWithStatusCodesAndHeaders(["429"], {"Retry-After": "a"});
|
|
83
|
+
const sleeper = new MockSleeper();
|
|
84
|
+
|
|
85
|
+
await sendWithRetry(10, inner, sleeper);
|
|
86
|
+
|
|
87
|
+
expect(sleeper.sleepDurations).to.deep.equal([10]);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("test retry error", async function () {
|
|
91
|
+
let inner = new MockSenderWithStatusCodesAndHeaders(["429"], undefined, "Big Bad");
|
|
92
|
+
const sleeper = new MockSleeper();
|
|
93
|
+
|
|
94
|
+
const response = await sendWithRetry(10, inner, sleeper);
|
|
95
|
+
|
|
96
|
+
expect(response.error).to.equal("Big Bad");
|
|
97
|
+
});
|
|
98
|
+
});
|