btrz-api-client 3.29.0 → 3.33.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/lib/client-standalone-min.js +1 -1
- package/lib/client.js +262 -209
- package/lib/endpoints/accounts/email-settings.js +85 -0
- package/lib/endpoints/gps/scanner-app-location.js +29 -0
- package/lib/endpoints/invoices/emails.js +31 -0
- package/package.json +1 -1
- package/src/client.js +217 -182
- package/src/endpoints/accounts/email-settings.js +55 -0
- package/src/endpoints/gps/scanner-app-location.js +18 -0
- package/src/endpoints/invoices/emails.js +19 -0
- package/test/client.test.js +157 -22
- package/test/endpoints/gps/scanner-app-location.js +26 -0
- package/test/test-helpers.js +36 -2
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const {authorizationHeaders} = require("./../endpoints_helpers.js");
|
|
2
|
+
|
|
3
|
+
//TODO: add docs function when docs published
|
|
4
|
+
function scannerAppLocationFactory({client}) {
|
|
5
|
+
function get({token, query = {}}) {
|
|
6
|
+
return client({
|
|
7
|
+
url: "/scanner-app-location",
|
|
8
|
+
headers: authorizationHeaders({token}),
|
|
9
|
+
params: query
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
get
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = scannerAppLocationFactory;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const {authorizationHeaders} = require("./../endpoints_helpers");
|
|
2
|
+
|
|
3
|
+
function emailsFactory({client, internalAuthTokenProvider}) {
|
|
4
|
+
function create({token, jwtToken, data, query = {}}) {
|
|
5
|
+
return client({
|
|
6
|
+
url: "/emails",
|
|
7
|
+
method: "post",
|
|
8
|
+
headers: authorizationHeaders({token, jwtToken, internalAuthTokenProvider}),
|
|
9
|
+
params: query,
|
|
10
|
+
data
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
create
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module.exports = emailsFactory;
|
package/test/client.test.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
const {
|
|
2
|
-
const MockAdapter = require(
|
|
1
|
+
const {expect} = require("chai");
|
|
2
|
+
const MockAdapter = require("axios-mock-adapter");
|
|
3
3
|
|
|
4
|
-
const {
|
|
4
|
+
const {createApiClient} = require("./../src/client.js");
|
|
5
|
+
const {createTestServer, axiosMock} = require("./test-helpers.js");
|
|
5
6
|
|
|
6
7
|
function expectKnownEndpoints(api) {
|
|
7
8
|
expect(api.inventory.products).to.exist;
|
|
@@ -9,10 +10,10 @@ function expectKnownEndpoints(api) {
|
|
|
9
10
|
expect(api.inventory.trips).to.exist;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
describe("client",
|
|
13
|
-
const baseURL = "http://someUrl.com"
|
|
13
|
+
describe("client", () => {
|
|
14
|
+
const baseURL = "http://someUrl.com";
|
|
14
15
|
|
|
15
|
-
it("should create a client with production values if no default provided",
|
|
16
|
+
it("should create a client with production values if no default provided", () => {
|
|
16
17
|
const api = createApiClient();
|
|
17
18
|
|
|
18
19
|
expectKnownEndpoints(api);
|
|
@@ -20,8 +21,8 @@ describe("client", function() {
|
|
|
20
21
|
expect(api.inventory.__test.client.defaults.timeout).to.eql(15000);
|
|
21
22
|
});
|
|
22
23
|
|
|
23
|
-
it("should create a client with default values",
|
|
24
|
-
const api = createApiClient({
|
|
24
|
+
it("should create a client with default values", () => {
|
|
25
|
+
const api = createApiClient({baseURL});
|
|
25
26
|
|
|
26
27
|
expectKnownEndpoints(api);
|
|
27
28
|
expect(api.inventory.__test.client.defaults.baseURL).to.eql(baseURL);
|
|
@@ -32,19 +33,29 @@ describe("client", function() {
|
|
|
32
33
|
const api = createApiClient({headers: {"x-test-header": "some_value"}});
|
|
33
34
|
|
|
34
35
|
const ignoredApiProperties = ["constants", "_cleanClient"];
|
|
35
|
-
|
|
36
|
+
function propertyIsRelevant(property) {
|
|
37
|
+
return !ignoredApiProperties.includes(property);
|
|
38
|
+
}
|
|
36
39
|
for (const subsystem of Object.keys(api).filter(propertyIsRelevant)) {
|
|
37
40
|
expect(api[subsystem].__test.client.defaults.headers).to.include({"x-test-header": "some_value"});
|
|
38
41
|
}
|
|
39
42
|
});
|
|
40
43
|
|
|
41
44
|
it("should expose a INTERNAL_AUTH_TOKEN constant", () => {
|
|
42
|
-
const api = createApiClient({
|
|
45
|
+
const api = createApiClient({baseURL});
|
|
43
46
|
expect(api.constants.INTERNAL_AUTH_TOKEN_SYMBOL).to.be.eql("internal_auth_token");
|
|
44
47
|
});
|
|
45
48
|
|
|
46
|
-
it("should allow to override baseUrl for custom endpoints",
|
|
47
|
-
const api = createApiClient({
|
|
49
|
+
it("should allow to override baseUrl for custom endpoints", () => {
|
|
50
|
+
const api = createApiClient({
|
|
51
|
+
baseURL,
|
|
52
|
+
timeout: 10,
|
|
53
|
+
baseURLOverride: {
|
|
54
|
+
inventory: (url) => {
|
|
55
|
+
return `${url}/somePath`;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
48
59
|
expect(api.inventory.products).to.exist;
|
|
49
60
|
expect(api.inventory.insurances).to.exist;
|
|
50
61
|
|
|
@@ -54,18 +65,22 @@ describe("client", function() {
|
|
|
54
65
|
});
|
|
55
66
|
|
|
56
67
|
it("should allow a different baseUrl to be specified for trip search endpoints", () => {
|
|
57
|
-
const api = createApiClient({
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
68
|
+
const api = createApiClient({
|
|
69
|
+
baseURL,
|
|
70
|
+
timeout: 10,
|
|
71
|
+
baseURLOverride: {
|
|
72
|
+
inventory: () => { return "http://localhost:3010/inventory"; },
|
|
73
|
+
trips: () => { return "http://localhost:3090/inventory"; }
|
|
74
|
+
}
|
|
75
|
+
});
|
|
61
76
|
|
|
62
77
|
expectKnownEndpoints(api);
|
|
63
78
|
expect(api.inventory.__test.client.defaults.baseURL).to.eql("http://localhost:3010/inventory");
|
|
64
79
|
expect(api.inventory.__test_trips.client.defaults.baseURL).to.eql("http://localhost:3090/inventory");
|
|
65
80
|
});
|
|
66
81
|
|
|
67
|
-
it("should allow to perform custom request on clean client",
|
|
68
|
-
const api = createApiClient({
|
|
82
|
+
it("should allow to perform custom request on clean client", () => {
|
|
83
|
+
const api = createApiClient({baseURL, timeout: 0});
|
|
69
84
|
expect(api.inventory.products).to.exist;
|
|
70
85
|
expect(api.inventory.insurances).to.exist;
|
|
71
86
|
|
|
@@ -73,12 +88,132 @@ describe("client", function() {
|
|
|
73
88
|
expect(api._cleanClient.defaults.baseURL).to.eql(baseURL);
|
|
74
89
|
expect(api._cleanClient.defaults.timeout).to.eql(0);
|
|
75
90
|
|
|
76
|
-
const mock =
|
|
77
|
-
mock.onPost(
|
|
78
|
-
const promise = api._cleanClient({
|
|
91
|
+
const mock = new MockAdapter(api._cleanClient);
|
|
92
|
+
mock.onPost("/custom/endpoint").reply(200);
|
|
93
|
+
const promise = api._cleanClient({url: "/custom/endpoint", method: "post"});
|
|
79
94
|
|
|
80
95
|
mock.restore();
|
|
81
96
|
return promise;
|
|
82
97
|
});
|
|
83
98
|
|
|
84
|
-
|
|
99
|
+
describe("http networking", () => {
|
|
100
|
+
describe("with keepAlive enabled in a custom endpoint", () => {
|
|
101
|
+
let mockServer = null;
|
|
102
|
+
|
|
103
|
+
before((done) => {
|
|
104
|
+
axiosMock.restore();
|
|
105
|
+
mockServer = createTestServer({
|
|
106
|
+
host: "localhost",
|
|
107
|
+
port: 8888,
|
|
108
|
+
maxSockets: 10
|
|
109
|
+
}, (req) => {
|
|
110
|
+
expect(req.headers.connection).to.equal("keep-alive");
|
|
111
|
+
});
|
|
112
|
+
mockServer.create((err) => {
|
|
113
|
+
if (err) return done(err);
|
|
114
|
+
return done();
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
after((done) => {
|
|
119
|
+
mockServer.close(() => {
|
|
120
|
+
done();
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("should only use the max sockets available to perform 100 concurrent requests", async () => {
|
|
125
|
+
const http = require("http");
|
|
126
|
+
const https = require("https");
|
|
127
|
+
|
|
128
|
+
const agents = {
|
|
129
|
+
httpAgent: new http.Agent({keepAlive: true, maxSockets: 10}),
|
|
130
|
+
httpsAgent: new https.Agent({keepAlive: true})
|
|
131
|
+
};
|
|
132
|
+
const api = createApiClient({baseURL: "http://localhost:8888", timeout: 0, agents});
|
|
133
|
+
const mock = new MockAdapter(api._cleanClient);
|
|
134
|
+
mock.restore();
|
|
135
|
+
const promises = new Array(100).fill().map((i) => {
|
|
136
|
+
return api._cleanClient({url: `/test/${i}`, method: "get"});
|
|
137
|
+
});
|
|
138
|
+
return Promise.all(promises);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
describe("with keepAlive enabled in a known endpoint", () => {
|
|
143
|
+
let mockServer = null;
|
|
144
|
+
|
|
145
|
+
before((done) => {
|
|
146
|
+
axiosMock.restore();
|
|
147
|
+
mockServer = createTestServer({
|
|
148
|
+
host: "localhost",
|
|
149
|
+
port: 8888,
|
|
150
|
+
maxSockets: 10
|
|
151
|
+
}, (req) => {
|
|
152
|
+
expect(req.headers.connection).to.equal("keep-alive");
|
|
153
|
+
});
|
|
154
|
+
mockServer.create((err) => {
|
|
155
|
+
if (err) return done(err);
|
|
156
|
+
return done();
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
after((done) => {
|
|
161
|
+
mockServer.close(() => {
|
|
162
|
+
done();
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it("should use at least 10 sockets to perform 100 concurrent product requests", async () => {
|
|
167
|
+
const http = require("http");
|
|
168
|
+
const https = require("https");
|
|
169
|
+
|
|
170
|
+
const agents = {
|
|
171
|
+
httpAgent: new http.Agent({keepAlive: true, maxSockets: 10}),
|
|
172
|
+
httpsAgent: new https.Agent({keepAlive: true})
|
|
173
|
+
};
|
|
174
|
+
const api = createApiClient({baseURL: "http://localhost:8888", timeout: 0, agents});
|
|
175
|
+
const mock = new MockAdapter(api._cleanClient);
|
|
176
|
+
mock.restore();
|
|
177
|
+
const promises = new Array(100).fill().map(() => {
|
|
178
|
+
return api.inventory.products.all({token: "I owe you a token"});
|
|
179
|
+
});
|
|
180
|
+
return Promise.all(promises);
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
describe("with keepAlive disabled (default)", () => {
|
|
185
|
+
let mockServer = null;
|
|
186
|
+
|
|
187
|
+
before((done) => {
|
|
188
|
+
axiosMock.restore();
|
|
189
|
+
mockServer = createTestServer({
|
|
190
|
+
host: "localhost",
|
|
191
|
+
port: 8888,
|
|
192
|
+
maxSockets: 100
|
|
193
|
+
}, (req) => {
|
|
194
|
+
expect(req.headers.connection).to.equal("close");
|
|
195
|
+
});
|
|
196
|
+
mockServer.create((err) => {
|
|
197
|
+
if (err) return done(err);
|
|
198
|
+
return done();
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
after((done) => {
|
|
203
|
+
mockServer.close(() => {
|
|
204
|
+
done();
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it("should socket no more than 100 sockets to perform 100 concurrent requests", async () => {
|
|
209
|
+
const api = createApiClient({baseURL: "http://localhost:8888", timeout: 0});
|
|
210
|
+
const mock = new MockAdapter(api._cleanClient);
|
|
211
|
+
mock.restore();
|
|
212
|
+
const promises = new Array(100).fill().map((i) => {
|
|
213
|
+
return api._cleanClient({url: `/test/${i}`, method: "get"});
|
|
214
|
+
});
|
|
215
|
+
return Promise.all(promises);
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const {axiosMock, expectRequest} = require("./../../test-helpers.js");
|
|
2
|
+
const api = require("./../../../src/client.js")
|
|
3
|
+
.createApiClient({baseURL: "http://test.com"});
|
|
4
|
+
|
|
5
|
+
describe("gps/scanner-app-location", () => {
|
|
6
|
+
const apiKey = "yourAccountAPIKey";
|
|
7
|
+
|
|
8
|
+
afterEach(() => {
|
|
9
|
+
axiosMock.reset();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it("should GET a location", () => {
|
|
13
|
+
const routeId = "myRoute";
|
|
14
|
+
const scheduleId = "myScheduleId";
|
|
15
|
+
const date = "2020-01-01";
|
|
16
|
+
const includeTravelledPath = true;
|
|
17
|
+
const query = {
|
|
18
|
+
routeId,
|
|
19
|
+
scheduleId,
|
|
20
|
+
date,
|
|
21
|
+
includeTravelledPath
|
|
22
|
+
};
|
|
23
|
+
axiosMock.onGet("/scanner-app-location").reply(expectRequest({statusCode: 200, token: apiKey}));
|
|
24
|
+
return api.gps.scannerAppLocation.get({token: apiKey, query});
|
|
25
|
+
});
|
|
26
|
+
});
|
package/test/test-helpers.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
const axios = require(
|
|
2
|
-
const MockAdapter = require(
|
|
1
|
+
const axios = require("axios");
|
|
2
|
+
const MockAdapter = require("axios-mock-adapter");
|
|
3
|
+
const http = require("http");
|
|
4
|
+
const {expect} = require("chai");
|
|
3
5
|
|
|
4
6
|
module.exports = {
|
|
5
7
|
axiosMock: new MockAdapter(axios),
|
|
@@ -22,5 +24,37 @@ module.exports = {
|
|
|
22
24
|
}
|
|
23
25
|
return [403];
|
|
24
26
|
};
|
|
27
|
+
},
|
|
28
|
+
createTestServer: (config = {}, reqCallback = () => {}) => {
|
|
29
|
+
const sockets = new Set();
|
|
30
|
+
const mockServer = http.createServer((req, res) => {
|
|
31
|
+
reqCallback(req, res);
|
|
32
|
+
res.writeHead(200, {"Content-Type": "text/plain"});
|
|
33
|
+
res.end("OK");
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
mockServer.on("connection", (socket) => {
|
|
37
|
+
sockets.add(socket);
|
|
38
|
+
if (config.maxSockets) {
|
|
39
|
+
expect(sockets.size).to.be.lessThanOrEqual(config.maxSockets);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
create: (callback) => {
|
|
45
|
+
mockServer.listen(config.port || 8888, config.host || "localhost", callback);
|
|
46
|
+
},
|
|
47
|
+
getSockets: () => {
|
|
48
|
+
return sockets.size;
|
|
49
|
+
},
|
|
50
|
+
close: (callback) => {
|
|
51
|
+
for (const socket of sockets) {
|
|
52
|
+
socket.destroy();
|
|
53
|
+
sockets.delete(socket);
|
|
54
|
+
}
|
|
55
|
+
sockets.clear();
|
|
56
|
+
mockServer.close(callback);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
25
59
|
}
|
|
26
60
|
};
|