rqlite-js 2.5.7 → 2.6.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.
Files changed (78) hide show
  1. package/README.md +174 -155
  2. package/lib/api/backup/index.js +46 -46
  3. package/lib/api/backup/index.js.map +1 -1
  4. package/lib/api/backup/test.unit.js +45 -0
  5. package/lib/api/backup/test.unit.js.map +1 -0
  6. package/lib/api/backup-formats.js +16 -0
  7. package/lib/api/backup-formats.js.map +1 -0
  8. package/lib/api/client/index.js +63 -42
  9. package/lib/api/client/index.js.map +1 -1
  10. package/lib/api/client/test.unit.js +53 -0
  11. package/lib/api/client/test.unit.js.map +1 -0
  12. package/lib/api/consistency-levels.js +30 -0
  13. package/lib/api/consistency-levels.js.map +1 -0
  14. package/lib/api/data/index.js +50 -72
  15. package/lib/api/data/index.js.map +1 -1
  16. package/lib/api/data/test.unit.js +98 -0
  17. package/lib/api/data/test.unit.js.map +1 -0
  18. package/lib/api/paths.js +33 -0
  19. package/lib/api/paths.js.map +1 -0
  20. package/lib/api/query-params.js +43 -0
  21. package/lib/api/query-params.js.map +1 -0
  22. package/lib/api/results/data-result-error.js +39 -10
  23. package/lib/api/results/data-result-error.js.map +1 -1
  24. package/lib/api/results/data-result.js +57 -51
  25. package/lib/api/results/data-result.js.map +1 -1
  26. package/lib/api/results/data-results.js +50 -30
  27. package/lib/api/results/data-results.js.map +1 -1
  28. package/lib/api/results/index.js +1 -1
  29. package/lib/api/results/result-fields.js +47 -0
  30. package/lib/api/results/result-fields.js.map +1 -0
  31. package/lib/api/results/test.unit.js +238 -0
  32. package/lib/api/results/test.unit.js.map +1 -0
  33. package/lib/api/status/index.js +40 -28
  34. package/lib/api/status/index.js.map +1 -1
  35. package/lib/api/status/test.unit.js +57 -0
  36. package/lib/api/status/test.unit.js.map +1 -0
  37. package/lib/http-request/auth-keys.js +15 -0
  38. package/lib/http-request/auth-keys.js.map +1 -0
  39. package/lib/http-request/http-headers.js +20 -0
  40. package/lib/http-request/http-headers.js.map +1 -0
  41. package/lib/http-request/index.js +291 -271
  42. package/lib/http-request/index.js.map +1 -1
  43. package/lib/http-request/test.unit.js +560 -0
  44. package/lib/http-request/test.unit.js.map +1 -0
  45. package/lib/index.js +23 -4
  46. package/lib/index.js.map +1 -1
  47. package/lib/test/api-data-execute-nock.js +142 -0
  48. package/lib/test/api-data-execute-nock.js.map +1 -0
  49. package/lib/test/api-data-query-nock.js +210 -0
  50. package/lib/test/api-data-query-nock.js.map +1 -0
  51. package/lib/test/backups/backup-nock.js +29 -0
  52. package/lib/test/backups/backup-nock.js.map +1 -0
  53. package/lib/test/backups/restore-nock.js +30 -0
  54. package/lib/test/backups/restore-nock.js.map +1 -0
  55. package/lib/test/env.js +15 -0
  56. package/lib/test/env.js.map +1 -0
  57. package/lib/test/unit/index.unit.js +27 -0
  58. package/lib/test/unit/index.unit.js.map +1 -0
  59. package/lib/test.integration.js +238 -0
  60. package/lib/test.integration.js.map +1 -0
  61. package/package.json +33 -23
  62. package/.eslintrc +0 -20
  63. package/.travis.yml +0 -24
  64. package/es6/api/backup/index.js +0 -71
  65. package/es6/api/client/index.js +0 -83
  66. package/es6/api/data/index.js +0 -129
  67. package/es6/api/results/data-result-error.js +0 -32
  68. package/es6/api/results/data-result.js +0 -134
  69. package/es6/api/results/data-results.js +0 -121
  70. package/es6/api/results/index.js +0 -7
  71. package/es6/api/status/index.js +0 -54
  72. package/es6/http-request/content-types.js +0 -4
  73. package/es6/http-request/errors.js +0 -16
  74. package/es6/http-request/http-methods.js +0 -39
  75. package/es6/http-request/index.js +0 -743
  76. package/es6/http-request/retryable.js +0 -41
  77. package/es6/index.js +0 -19
  78. package/jsconfig.json +0 -19
@@ -0,0 +1,560 @@
1
+ "use strict";var _chai = require("chai");
2
+ var _http = require("http");
3
+ var _https = require("https");
4
+ var _apiDataQueryNock = require("../test/api-data-query-nock");
5
+
6
+
7
+
8
+
9
+
10
+
11
+ var _apiDataExecuteNock = require("../test/api-data-execute-nock");
12
+
13
+
14
+
15
+
16
+
17
+
18
+ var _contentTypes = require("./content-types");
19
+ var _retryable = require("./retryable");
20
+
21
+
22
+
23
+
24
+ var _ = _interopRequireWildcard(require("."));var cache;function _interopRequireWildcard(e, t) {if (!t && e && e.__esModule) return e;var r,c,a = Object.defineProperty,n = { __proto__: null, default: e };if (Object(e) !== e) return n;if (cache || "function" != typeof WeakMap || (cache = new WeakMap()), cache) {if (cache.has(e)) return cache.get(e);cache.set(e, n);}for (c in e) "default" !== c && {}.hasOwnProperty.call(e, c) && ((r = a && Object.getOwnPropertyDescriptor(e, c)) && (r.get || r.set) ? a(n, c, r) : n[c] = e[c]);return n;}
25
+
26
+ const username = 'TestUsername';
27
+ const password = 'TestPassword';
28
+ const auth = Object.freeze({
29
+ user: username,
30
+ pass: password
31
+ });
32
+
33
+ /**
34
+ * Capture the stream data and resolve a promise with the parsed JSON
35
+ */
36
+ function handleRequestStreamAsPromise(request) {
37
+ return new Promise((resolve, reject) => {
38
+ let json = Buffer.from('');
39
+ request.
40
+ on('data', (data) => {
41
+ json = Buffer.concat([json, data]);
42
+ }).
43
+ on('end', () => resolve(JSON.parse(json))).
44
+ on('error', reject);
45
+ });
46
+ }
47
+ const ERROR_CODE_NOT_RETRYABLE = 'UNKNOWN';
48
+ const HTTP_STATUS_CODE_NOT_RETRYABLE = 418; // I am little tea pot
49
+
50
+ describe('http-request', () => {
51
+ describe('construtor()', () => {
52
+ it('should throw an error if no hosts are provided', () => {
53
+ _chai.assert.throws(() => new _.default(''), 'At least one host must be provided');
54
+ });
55
+ it('should set the hosts when provided as a string', () => {
56
+ const host1 = 'http://www.rqlite.com:4001';
57
+ const host2 = 'http://www.rqlite.com:4002';
58
+ const request = new _.default(`${host1}, ${host2}`);
59
+ _chai.assert.deepEqual(request.getHosts(), [host1, host2]);
60
+ });
61
+ it('should set the hosts provided as an array', () => {
62
+ const host1 = 'http://www.rqlite.com:4001';
63
+ const host2 = 'http://www.rqlite.com:4002';
64
+ const request = new _.default([host1, host2]);
65
+ _chai.assert.deepEqual(request.getHosts(), [host1, host2]);
66
+ });
67
+ });
68
+ describe('Function: createDefaultHeaders()', () => {
69
+ it(`should add the Accept header with a value of ${_contentTypes.CONTENT_TYPE_APPLICATION_JSON}`, () => {
70
+ _chai.assert.deepEqual({ Accept: _contentTypes.CONTENT_TYPE_APPLICATION_JSON }, (0, _.createDefaultHeaders)());
71
+ });
72
+ });
73
+ describe('Function: getWaitTimeExponential()', () => {
74
+ it('should get the exponential value for attempt 0', () => {
75
+ _chai.assert.equal((0, _.getWaitTimeExponential)(0, 100, 2), 0);
76
+ });
77
+ it('should get the exponential value for attempt 1', () => {
78
+ _chai.assert.equal((0, _.getWaitTimeExponential)(1, 100, 2), 200);
79
+ });
80
+ it('should get the exponential value for attempt 2', () => {
81
+ _chai.assert.equal((0, _.getWaitTimeExponential)(2, 100, 2), 400);
82
+ });
83
+ });
84
+ describe('Method: HttpRequest.requestIsRetryable()', () => {
85
+ const url = 'http://www.rqlite.com:4001';
86
+ let httpRequest;
87
+ before('create http request instance', () => {
88
+ httpRequest = new _.default(url);
89
+ });
90
+ _retryable.RETRYABLE_HTTP_METHODS.forEach((httpMethod) => {
91
+ _retryable.RETRYABLE_STATUS_CODES.forEach((statusCode) => {
92
+ it(`should return true for HTTP method ${httpMethod} and status code ${statusCode}`, () => {
93
+ _chai.assert.isTrue(httpRequest.requestIsRetryable({
94
+ statusCode,
95
+ httpMethod
96
+ }));
97
+ });
98
+ });
99
+ _retryable.RETRYABLE_ERROR_CODES.forEach((errorCode) => {
100
+ it(`should return true for HTTP method ${httpMethod} error code ${errorCode}`, () => {
101
+ _chai.assert.isTrue(httpRequest.requestIsRetryable({
102
+ httpMethod,
103
+ statusCode: HTTP_STATUS_CODE_NOT_RETRYABLE,
104
+ errorCode
105
+ }));
106
+ });
107
+ });
108
+ it(`should return false for HTTP method ${httpMethod} and status code ${HTTP_STATUS_CODE_NOT_RETRYABLE}`, () => {
109
+ _chai.assert.isFalse(httpRequest.requestIsRetryable({
110
+ httpMethod,
111
+ statusCode: HTTP_STATUS_CODE_NOT_RETRYABLE
112
+ }));
113
+ });
114
+ it(`should return false for HTTP method ${httpMethod} and error code ${ERROR_CODE_NOT_RETRYABLE}`, () => {
115
+ _chai.assert.isFalse(httpRequest.requestIsRetryable({
116
+ httpMethod,
117
+ statusCode: HTTP_STATUS_CODE_NOT_RETRYABLE,
118
+ errorCode: ERROR_CODE_NOT_RETRYABLE
119
+ }));
120
+ });
121
+ });
122
+ it('should return false for HTTP method UNKNOWN', () => {
123
+ _chai.assert.isFalse(httpRequest.requestIsRetryable({
124
+ httpMethod: 'UNKNOWN'
125
+ }));
126
+ });
127
+ });
128
+ describe('Method: HttpRequest.get()', () => {
129
+ it('should set and get an http agent', async () => {
130
+ const url = 'http://www.rqlite.com:4001';
131
+ const httpAgent = new _http.Agent();
132
+ const httpRequest = new _.default(url, { httpAgent });
133
+ _chai.assert.equal(httpRequest.getHttpAgent(), httpAgent, 'http agent is set on http request');
134
+ });
135
+ it('should set and get an https agent', async () => {
136
+ const url = 'http://www.rqlite.com:4001';
137
+ const httpsAgent = new _https.Agent();
138
+ const httpRequest = new _.default(url, { httpsAgent });
139
+ _chai.assert.equal(httpRequest.getHttpsAgent(), httpsAgent, 'https agent is set on http request');
140
+ });
141
+ it('should perform a HTTP GET request', async () => {
142
+ const url = 'http://www.rqlite.com:4001';
143
+ const httpRequest = new _.default(url);
144
+ const path = '/test';
145
+ const scope = (0, _apiDataQueryNock.querySuccess)({ url, path, query: {} });
146
+ const res = await httpRequest.get({ uri: path });
147
+ _chai.assert.isTrue(scope.isDone(), 'http request captured by nock');
148
+ _chai.assert.deepEqual(_apiDataQueryNock.QUERY_SUCCESS_RESPONSE, res.body);
149
+ });
150
+ _retryable.RETRYABLE_STATUS_CODES.forEach((statusCode) => {
151
+ it(`should perform a HTTP GET request and retry using the next host on retryable http status code ${statusCode}`, async () => {
152
+ const host1 = 'http://www.rqlite.com:4001';
153
+ const host2 = 'http://www.rqlite.com:4002';
154
+ const httpRequest = new _.default(`${host1},${host2}`, { exponentailBackoffBase: 0, exponentailBackoffExponent: 0 });
155
+ const path = '/test';
156
+ const scopeFailure = (0, _apiDataQueryNock.queryFailureHttpStatusCode)({ url: host1, path, statusCode });
157
+ const scopeSuccess = (0, _apiDataQueryNock.querySuccess)({ url: host2, path });
158
+ const res = await httpRequest.get({ uri: path });
159
+ _chai.assert.isTrue(scopeSuccess.isDone(), 'http success request captured by nock');
160
+ _chai.assert.isTrue(scopeFailure.isDone(), 'http failure request captured by nock');
161
+ _chai.assert.deepEqual(_apiDataQueryNock.QUERY_SUCCESS_RESPONSE, res.body);
162
+ });
163
+ it(`should perform a HTTP GET request, retry using the next host on retryable http status code ${statusCode} and reject on max retries`, async () => {
164
+ const host1 = 'http://www.rqlite.com:4001';
165
+ const host2 = 'http://www.rqlite.com:4002';
166
+ const httpRequest = new _.default(`${host1},${host2}`, { exponentailBackoffBase: 0, exponentailBackoffExponent: 0 });
167
+ const path = '/test';
168
+ const scopes = [
169
+ (0, _apiDataQueryNock.queryFailureHttpStatusCode)({ url: host1, path, statusCode }),
170
+ (0, _apiDataQueryNock.queryFailureHttpStatusCode)({ url: host2, path, statusCode }),
171
+ (0, _apiDataQueryNock.queryFailureHttpStatusCode)({ url: host1, path, statusCode }),
172
+ (0, _apiDataQueryNock.queryFailureHttpStatusCode)({ url: host2, path, statusCode }),
173
+ (0, _apiDataQueryNock.queryFailureHttpStatusCode)({ url: host1, path, statusCode }),
174
+ (0, _apiDataQueryNock.queryFailureHttpStatusCode)({ url: host2, path, statusCode }),
175
+ // Circles back to original host on last retry
176
+ (0, _apiDataQueryNock.queryFailureHttpStatusCode)({ url: host1, path, statusCode })];
177
+
178
+ await _chai.assert.isRejected(httpRequest.get({ uri: path }), `Request failed with status code ${statusCode}`);
179
+ scopes.forEach((scope, i) => {
180
+ _chai.assert.isTrue(scope.isDone(), `http failure request attempt ${i} captured by nock`);
181
+ });
182
+ });
183
+ });
184
+ it(`should perform a HTTP GET request and not retry on http status code ${HTTP_STATUS_CODE_NOT_RETRYABLE}`, async () => {
185
+ const host1 = 'http://www.rqlite.com:4001';
186
+ const host2 = 'http://www.rqlite.com:4002';
187
+ const httpRequest = new _.default(`${host1},${host2}`, { exponentailBackoffBase: 0, exponentailBackoffExponent: 0 });
188
+ const path = '/test';
189
+ const scopeFailure = (0, _apiDataQueryNock.queryFailureHttpStatusCode)({
190
+ url: host1, path, statusCode: HTTP_STATUS_CODE_NOT_RETRYABLE
191
+ });
192
+ const scopeSuccess = (0, _apiDataQueryNock.querySuccess)({ url: host2, path });
193
+ await _chai.assert.isRejected(httpRequest.get({ uri: path }), `Request failed with status code ${HTTP_STATUS_CODE_NOT_RETRYABLE}`);
194
+ _chai.assert.isFalse(scopeSuccess.isDone(), 'http success request captured by nock, but not performed');
195
+ _chai.assert.isTrue(scopeFailure.isDone(), 'http failure request captured by nock');
196
+ });
197
+ _retryable.RETRYABLE_ERROR_CODES.forEach((errorCode) => {
198
+ it(`should perform a HTTP GET request and retry using the next host on retryable error code ${errorCode}`, async () => {
199
+ const host1 = 'http://www.rqlite.com:4001';
200
+ const host2 = 'http://www.rqlite.com:4002';
201
+ const httpRequest = new _.default(`${host1},${host2}`, { exponentailBackoffBase: 0, exponentailBackoffExponent: 0 });
202
+ const path = '/test';
203
+ const scopeFailure = (0, _apiDataQueryNock.queryFailureErrorCode)({ url: host1, path, errorCode });
204
+ const scopeSuccess = (0, _apiDataQueryNock.querySuccess)({ url: host2, path });
205
+ const res = await httpRequest.get({ uri: path });
206
+ _chai.assert.isTrue(scopeSuccess.isDone(), 'http success request captured by nock');
207
+ _chai.assert.isTrue(scopeFailure.isDone(), 'http failure request captured by nock');
208
+ _chai.assert.deepEqual(_apiDataQueryNock.QUERY_SUCCESS_RESPONSE, res.body);
209
+ });
210
+ it(`should perform a HTTP GET request, retry using the next host on retryable error code ${errorCode} and reject on max retries`, async () => {
211
+ const host1 = 'http://www.rqlite.com:4001';
212
+ const host2 = 'http://www.rqlite.com:4002';
213
+ const httpRequest = new _.default(`${host1},${host2}`, { exponentailBackoffBase: 0, exponentailBackoffExponent: 0 });
214
+ const path = '/test';
215
+ const scopes = [
216
+ (0, _apiDataQueryNock.queryFailureErrorCode)({ url: host1, path, errorCode }),
217
+ (0, _apiDataQueryNock.queryFailureErrorCode)({ url: host2, path, errorCode }),
218
+ (0, _apiDataQueryNock.queryFailureErrorCode)({ url: host1, path, errorCode }),
219
+ (0, _apiDataQueryNock.queryFailureErrorCode)({ url: host2, path, errorCode }),
220
+ (0, _apiDataQueryNock.queryFailureErrorCode)({ url: host1, path, errorCode }),
221
+ (0, _apiDataQueryNock.queryFailureErrorCode)({ url: host2, path, errorCode }),
222
+ // Circles back to original host on last retry
223
+ (0, _apiDataQueryNock.queryFailureErrorCode)({ url: host1, path, errorCode })];
224
+
225
+ await _chai.assert.isRejected(httpRequest.get({ uri: path }), errorCode);
226
+ scopes.forEach((scope, i) => {
227
+ _chai.assert.isTrue(scope.isDone(), `http failure request attempt ${i} captured by nock`);
228
+ });
229
+ });
230
+ });
231
+ it(`should perform a HTTP GET request and not retry on error code ${ERROR_CODE_NOT_RETRYABLE}`, async () => {
232
+ const host1 = 'http://www.rqlite.com:4001';
233
+ const host2 = 'http://www.rqlite.com:4002';
234
+ const httpRequest = new _.default(`${host1},${host2}`, { exponentailBackoffBase: 0, exponentailBackoffExponent: 0 });
235
+ const path = '/test';
236
+ const scopeFailure = (0, _apiDataQueryNock.queryFailureErrorCode)({
237
+ url: host1, path, errorCode: ERROR_CODE_NOT_RETRYABLE
238
+ });
239
+ const scopeSuccess = (0, _apiDataQueryNock.querySuccess)({ url: host2, path });
240
+ await _chai.assert.isRejected(httpRequest.get({ uri: path }), ERROR_CODE_NOT_RETRYABLE);
241
+ _chai.assert.isFalse(scopeSuccess.isDone(), 'http success request captured by nock, but not performed');
242
+ _chai.assert.isTrue(scopeFailure.isDone(), 'http failure request captured by nock');
243
+ });
244
+ it('should perform a HTTP GET request with a query', async () => {
245
+ const url = 'http://www.rqlite.com:4001';
246
+ const httpRequest = new _.default(url);
247
+ const path = '/test';
248
+ const query = { test: '123' };
249
+ const scope = (0, _apiDataQueryNock.querySuccess)({ url, path, query });
250
+ const res = await httpRequest.get({ uri: path, query });
251
+ _chai.assert.isTrue(scope.isDone(), 'http request captured by nock');
252
+ _chai.assert.deepEqual(_apiDataQueryNock.QUERY_SUCCESS_RESPONSE, res.body);
253
+ });
254
+ it('should perform a HTTP GET request with a query and follow redirects', async () => {
255
+ const url = 'http://www.rqlite.com:4001';
256
+ const urlRedirectDestination = 'http://www.rqlite.com:4002';
257
+ const httpRequest = new _.default(url);
258
+ const path = '/test';
259
+ const query = { test: '123' };
260
+ const scopeRedirect = (0, _apiDataQueryNock.queryRedirectSuccess)({
261
+ url,
262
+ path,
263
+ query,
264
+ redirectLocation: `${urlRedirectDestination}${path}`
265
+ });
266
+ const scope = (0, _apiDataQueryNock.querySuccess)({ url: urlRedirectDestination, path, query });
267
+ const res = await httpRequest.get({ uri: path, query });
268
+ _chai.assert.isTrue(scopeRedirect.isDone(), 'http redirect request captured by nock');
269
+ _chai.assert.isTrue(scope.isDone(), 'http request captured by nock');
270
+ _chai.assert.deepEqual(_apiDataQueryNock.QUERY_SUCCESS_RESPONSE, res.body);
271
+ });
272
+ it('should perform a HTTP GET request with basic authentication', async () => {
273
+ const url = 'http://www.rqlite.com:4001';
274
+ const httpRequest = new _.default(url, {
275
+ authentication: {
276
+ username,
277
+ password
278
+ }
279
+ });
280
+ const path = '/test';
281
+ const query = { test: '123' };
282
+ const scope = (0, _apiDataQueryNock.querySuccess)({ url, path, auth, query });
283
+ const res = await httpRequest.get({ uri: path, query });
284
+ _chai.assert.isTrue(scope.isDone(), 'http request captured by nock');
285
+ _chai.assert.deepEqual(_apiDataQueryNock.QUERY_SUCCESS_RESPONSE, res.body);
286
+ });
287
+ it('should perform a HTTP GET request with a query when the stream option is true', async () => {
288
+ const url = 'http://www.rqlite.com:4001';
289
+ const httpRequest = new _.default(url);
290
+ const path = '/test';
291
+ const query = { test: '123' };
292
+ const scope = (0, _apiDataQueryNock.querySuccess)({ url, path, query });
293
+ const request = await httpRequest.get({ uri: path, query, stream: true });
294
+ const result = await handleRequestStreamAsPromise(request);
295
+ _chai.assert.isTrue(scope.isDone(), 'http request captured by nock');
296
+ _chai.assert.deepEqual(result, _apiDataQueryNock.QUERY_SUCCESS_RESPONSE);
297
+ });
298
+ it('should perform a HTTP GET request with a query when the stream option is true and follow redirects', async () => {
299
+ const url = 'http://www.rqlite.com:4001';
300
+ const urlRedirectDestination = 'http://www.rqlite.com:4002';
301
+ const httpRequest = new _.default(url);
302
+ const path = '/test';
303
+ const query = { test: '123' };
304
+ const scopeRedirect = (0, _apiDataQueryNock.queryRedirectSuccess)({
305
+ url,
306
+ path,
307
+ query,
308
+ redirectLocation: `${urlRedirectDestination}${path}`
309
+ });
310
+ const scope = (0, _apiDataQueryNock.querySuccess)({ url: urlRedirectDestination, path, query });
311
+ const request = await httpRequest.get({ uri: path, query, stream: true });
312
+ const result = await handleRequestStreamAsPromise(request);
313
+ _chai.assert.isTrue(scopeRedirect.isDone(), 'http redirect request captured by nock');
314
+ _chai.assert.isTrue(scope.isDone(), 'http request captured by nock');
315
+ _chai.assert.deepEqual(result, _apiDataQueryNock.QUERY_SUCCESS_RESPONSE);
316
+ });
317
+ it('should perform a HTTP GET request with basic authentication when the stream option is true', async () => {
318
+ const url = 'http://www.rqlite.com:4001';
319
+ const httpRequest = new _.default(url, {
320
+ authentication: {
321
+ username,
322
+ password
323
+ }
324
+ });
325
+ const path = '/test';
326
+ const query = { test: '123' };
327
+ const scope = (0, _apiDataQueryNock.querySuccess)({ url, path, auth, query });
328
+ const request = await httpRequest.get({ uri: path, query, stream: true });
329
+ const result = await handleRequestStreamAsPromise(request);
330
+ _chai.assert.isTrue(scope.isDone(), 'http request captured by nock');
331
+ _chai.assert.deepEqual(result, _apiDataQueryNock.QUERY_SUCCESS_RESPONSE);
332
+ });
333
+ });
334
+ describe('Method: HttpRequest.post()', () => {
335
+ it(`should send a HTTP POST request including ${_contentTypes.CONTENT_TYPE_APPLICATION_JSON} body`, async () => {
336
+ const url = 'http://www.rqlite.com:4001';
337
+ const httpRequest = new _.default(url);
338
+ const path = '/test';
339
+ const body = ['INSERT INTO foo(name) VALUES("fiona")'];
340
+ const scope = (0, _apiDataExecuteNock.executeSuccess)({ url, path, body });
341
+ const res = await httpRequest.post({ uri: path, body });
342
+ _chai.assert.isTrue(scope.isDone(), 'http request captured by nock');
343
+ _chai.assert.deepEqual(res.body, _apiDataExecuteNock.EXECUTE_SUCCESS_RESPONSE);
344
+ });
345
+ _retryable.RETRYABLE_STATUS_CODES.forEach((statusCode) => {
346
+ it(`should send a HTTP POST request including ${_contentTypes.CONTENT_TYPE_APPLICATION_JSON} body and retry using the next host on retryable http status code ${statusCode}`, async () => {
347
+ const host1 = 'http://www.rqlite.com:4001';
348
+ const host2 = 'http://www.rqlite.com:4002';
349
+ const httpRequest = new _.default(`${host1},${host2}`, { exponentailBackoffBase: 0, exponentailBackoffExponent: 0 });
350
+ const path = '/test';
351
+ const body = ['INSERT INTO foo(name) VALUES("fiona")'];
352
+ const scopeFailure = (0, _apiDataExecuteNock.executeFailureHttpStatusCode)({ url: host1, path, body, statusCode });
353
+ const scopeSuccess = (0, _apiDataExecuteNock.executeSuccess)({ url: host2, path, body });
354
+ const res = await httpRequest.post({ uri: path, body });
355
+ _chai.assert.isTrue(scopeSuccess.isDone(), 'http success request captured by nock');
356
+ _chai.assert.isTrue(scopeFailure.isDone(), 'http failure request captured by nock');
357
+ _chai.assert.deepEqual(res.body, _apiDataExecuteNock.EXECUTE_SUCCESS_RESPONSE);
358
+ });
359
+ it(`should send a HTTP POST request including ${_contentTypes.CONTENT_TYPE_APPLICATION_JSON} body and retry using the next host on retryable http status code ${statusCode} and reject on max retries`, async () => {
360
+ const host1 = 'http://www.rqlite.com:4001';
361
+ const host2 = 'http://www.rqlite.com:4002';
362
+ const httpRequest = new _.default(`${host1},${host2}`, { exponentailBackoffBase: 0, exponentailBackoffExponent: 0 });
363
+ const path = '/test';
364
+ const body = ['INSERT INTO foo(name) VALUES("fiona")'];
365
+ const scopes = [
366
+ (0, _apiDataExecuteNock.executeFailureHttpStatusCode)({ url: host1, path, body, statusCode }),
367
+ (0, _apiDataExecuteNock.executeFailureHttpStatusCode)({ url: host2, path, body, statusCode }),
368
+ (0, _apiDataExecuteNock.executeFailureHttpStatusCode)({ url: host1, path, body, statusCode }),
369
+ (0, _apiDataExecuteNock.executeFailureHttpStatusCode)({ url: host2, path, body, statusCode }),
370
+ (0, _apiDataExecuteNock.executeFailureHttpStatusCode)({ url: host1, path, body, statusCode }),
371
+ (0, _apiDataExecuteNock.executeFailureHttpStatusCode)({ url: host2, path, body, statusCode }),
372
+ // Circles back to original host on last retry
373
+ (0, _apiDataExecuteNock.executeFailureHttpStatusCode)({ url: host1, path, body, statusCode })];
374
+
375
+ await _chai.assert.isRejected(httpRequest.post({ uri: path, body }), `Request failed with status code ${statusCode}`);
376
+ scopes.forEach((scope, i) => {
377
+ _chai.assert.isTrue(scope.isDone(), `http failure request attempt ${i} captured by nock`);
378
+ });
379
+ });
380
+ });
381
+ it(`should send a HTTP POST request including ${_contentTypes.CONTENT_TYPE_APPLICATION_JSON} body and not retry on http status code ${HTTP_STATUS_CODE_NOT_RETRYABLE}`, async () => {
382
+ const host1 = 'http://www.rqlite.com:4001';
383
+ const host2 = 'http://www.rqlite.com:4002';
384
+ const httpRequest = new _.default(`${host1},${host2}`, { exponentailBackoffBase: 0, exponentailBackoffExponent: 0 });
385
+ const path = '/test';
386
+ const body = ['INSERT INTO foo(name) VALUES("fiona")'];
387
+ const scopeFailure = (0, _apiDataExecuteNock.executeFailureHttpStatusCode)({
388
+ url: host1, path, body, statusCode: HTTP_STATUS_CODE_NOT_RETRYABLE
389
+ });
390
+ const scopeSuccess = (0, _apiDataExecuteNock.executeSuccess)({ url: host2, path, body });
391
+ await _chai.assert.isRejected(httpRequest.post({ uri: path, body }), `Request failed with status code ${HTTP_STATUS_CODE_NOT_RETRYABLE}`);
392
+ _chai.assert.isFalse(scopeSuccess.isDone(), 'http success request captured by nock, but not called');
393
+ _chai.assert.isTrue(scopeFailure.isDone(), 'http failure request captured by nock');
394
+ });
395
+ _retryable.RETRYABLE_ERROR_CODES.forEach((errorCode) => {
396
+ it(`should send a HTTP POST request including ${_contentTypes.CONTENT_TYPE_APPLICATION_JSON} body and retry using the next host on retryable error code ${errorCode}`, async () => {
397
+ const host1 = 'http://www.rqlite.com:4001';
398
+ const host2 = 'http://www.rqlite.com:4002';
399
+ const httpRequest = new _.default(`${host1},${host2}`, { exponentailBackoffBase: 0, exponentailBackoffExponent: 0 });
400
+ const path = '/test';
401
+ const body = ['INSERT INTO foo(name) VALUES("fiona")'];
402
+ const scopeFailure = (0, _apiDataExecuteNock.executeFailureErrorCode)({ url: host1, path, body, errorCode });
403
+ const scopeSuccess = (0, _apiDataExecuteNock.executeSuccess)({ url: host2, path, body });
404
+ const res = await httpRequest.post({ uri: path, body });
405
+ _chai.assert.isTrue(scopeSuccess.isDone(), 'http success request captured by nock');
406
+ _chai.assert.isTrue(scopeFailure.isDone(), 'http failure request captured by nock');
407
+ _chai.assert.deepEqual(res.body, _apiDataExecuteNock.EXECUTE_SUCCESS_RESPONSE);
408
+ });
409
+ it(`should send a HTTP POST request including ${_contentTypes.CONTENT_TYPE_APPLICATION_JSON} body and retry using the next host on retryable error code ${errorCode} and reject on max retries`, async () => {
410
+ const host1 = 'http://www.rqlite.com:4001';
411
+ const host2 = 'http://www.rqlite.com:4002';
412
+ const httpRequest = new _.default(`${host1},${host2}`, { exponentailBackoffBase: 0, exponentailBackoffExponent: 0 });
413
+ const path = '/test';
414
+ const body = ['INSERT INTO foo(name) VALUES("fiona")'];
415
+ const scopes = [
416
+ (0, _apiDataExecuteNock.executeFailureErrorCode)({ url: host1, path, body, errorCode }),
417
+ (0, _apiDataExecuteNock.executeFailureErrorCode)({ url: host2, path, body, errorCode }),
418
+ (0, _apiDataExecuteNock.executeFailureErrorCode)({ url: host1, path, body, errorCode }),
419
+ (0, _apiDataExecuteNock.executeFailureErrorCode)({ url: host2, path, body, errorCode }),
420
+ (0, _apiDataExecuteNock.executeFailureErrorCode)({ url: host1, path, body, errorCode }),
421
+ (0, _apiDataExecuteNock.executeFailureErrorCode)({ url: host2, path, body, errorCode }),
422
+ // Circles back to original host on last retry
423
+ (0, _apiDataExecuteNock.executeFailureErrorCode)({ url: host1, path, body, errorCode })];
424
+
425
+ await _chai.assert.isRejected(httpRequest.post({ uri: path, body }), errorCode);
426
+ scopes.forEach((scope, i) => {
427
+ _chai.assert.isTrue(scope.isDone(), `http failure request attempt ${i} captured by nock`);
428
+ });
429
+ });
430
+ });
431
+ it(`should send a HTTP POST request including ${_contentTypes.CONTENT_TYPE_APPLICATION_JSON} body and not retry on error code ${ERROR_CODE_NOT_RETRYABLE}`, async () => {
432
+ const host1 = 'http://www.rqlite.com:4001';
433
+ const host2 = 'http://www.rqlite.com:4002';
434
+ const httpRequest = new _.default(`${host1},${host2}`, { exponentailBackoffBase: 0, exponentailBackoffExponent: 0 });
435
+ const path = '/test';
436
+ const body = ['INSERT INTO foo(name) VALUES("fiona")'];
437
+ const scopeFailure = (0, _apiDataExecuteNock.executeFailureErrorCode)({
438
+ url: host1, path, body, errorCode: ERROR_CODE_NOT_RETRYABLE
439
+ });
440
+ const scopeSuccess = (0, _apiDataExecuteNock.executeSuccess)({ url: host2, path, body });
441
+ await _chai.assert.isRejected(httpRequest.post({ uri: path, body }), ERROR_CODE_NOT_RETRYABLE);
442
+ _chai.assert.isFalse(scopeSuccess.isDone(), 'http success request captured by nock, but not called');
443
+ _chai.assert.isTrue(scopeFailure.isDone(), 'http failure request captured by nock');
444
+ });
445
+ it(`should send a HTTP POST request including ${_contentTypes.CONTENT_TYPE_APPLICATION_JSON} body and follow redirects`, async () => {
446
+ const url = 'http://www.rqlite.com:4001';
447
+ const urlRedirectDestination = 'http://www.rqlite.com:4002';
448
+ const httpRequest = new _.default(url);
449
+ const path = '/test';
450
+ const body = ['INSERT INTO foo(name) VALUES("fiona")'];
451
+ const scopeRedirect = (0, _apiDataExecuteNock.executeRedirectSuccess)({
452
+ url,
453
+ path,
454
+ redirectLocation: `${urlRedirectDestination}${path}`,
455
+ body
456
+ });
457
+ const scope = (0, _apiDataExecuteNock.executeSuccess)({ url: urlRedirectDestination, path });
458
+ const res = await httpRequest.post({ uri: path, body });
459
+ _chai.assert.isTrue(scopeRedirect.isDone(), 'http redirect request captured by nock');
460
+ _chai.assert.isTrue(scope.isDone(), 'http request captured by nock');
461
+ _chai.assert.deepEqual(res.body, _apiDataExecuteNock.EXECUTE_SUCCESS_RESPONSE);
462
+ });
463
+ it(`should send a HTTP POST request including ${_contentTypes.CONTENT_TYPE_APPLICATION_JSON} body and follow redirects when useLeader is true plus redirect host is not in host list`, async () => {
464
+ const url = 'http://www.rqlite.com:4001';
465
+ const urlRedirectDestination = 'http://www.rqlite.com:4002';
466
+ const httpRequest = new _.default(url);
467
+ const path = '/test';
468
+ const body = ['INSERT INTO foo(name) VALUES("fiona")'];
469
+ const scopeRedirect = (0, _apiDataExecuteNock.executeRedirectSuccess)({
470
+ url,
471
+ path,
472
+ redirectLocation: `${urlRedirectDestination}${path}`,
473
+ body
474
+ });
475
+ const scope = (0, _apiDataExecuteNock.executeSuccess)({ url: urlRedirectDestination, path });
476
+ const res = await httpRequest.post({ uri: path, body, useLeader: true });
477
+ _chai.assert.isTrue(scopeRedirect.isDone(), 'http redirect request captured by nock');
478
+ _chai.assert.isTrue(scope.isDone(), 'http request captured by nock');
479
+ _chai.assert.deepEqual(res.body, _apiDataExecuteNock.EXECUTE_SUCCESS_RESPONSE);
480
+ });
481
+ it(`should send a HTTP POST request including ${_contentTypes.CONTENT_TYPE_APPLICATION_JSON} body and follow redirects when useLeader is true plus redirect host is in host list`, async () => {
482
+ const url = 'http://www.rqlite.com:4001';
483
+ const urlRedirectDestination = 'http://www.rqlite.com:4002';
484
+ const path = '/test';
485
+ const httpRequest = new _.default(`${url},${urlRedirectDestination}${path}`);
486
+ const body = ['INSERT INTO foo(name) VALUES("fiona")'];
487
+ const scopeRedirect = (0, _apiDataExecuteNock.executeRedirectSuccess)({
488
+ url,
489
+ path,
490
+ redirectLocation: `${urlRedirectDestination}${path}`,
491
+ body
492
+ });
493
+ const scope = (0, _apiDataExecuteNock.executeSuccess)({ url: urlRedirectDestination, path });
494
+ const res = await httpRequest.post({ uri: path, body, useLeader: true });
495
+ _chai.assert.isTrue(scopeRedirect.isDone(), 'http redirect request captured by nock');
496
+ _chai.assert.isTrue(scope.isDone(), 'http request captured by nock');
497
+ _chai.assert.deepEqual(res.body, _apiDataExecuteNock.EXECUTE_SUCCESS_RESPONSE);
498
+ _chai.assert.equal(httpRequest.getLeaderHostIndex(), 1, 'leader host index matches redirect');
499
+ });
500
+ it(`should send a HTTP POST request including ${_contentTypes.CONTENT_TYPE_APPLICATION_JSON} body with basic auth`, async () => {
501
+ const url = 'http://www.rqlite.com:4001';
502
+ const httpRequest = new _.default(url, {
503
+ authentication: {
504
+ username,
505
+ password
506
+ }
507
+ });
508
+ const path = '/test';
509
+ const body = ['INSERT INTO foo(name) VALUES("fiona")'];
510
+ const scope = (0, _apiDataExecuteNock.executeSuccess)({ url, path, auth });
511
+ const res = await httpRequest.post({ uri: path, body });
512
+ _chai.assert.isTrue(scope.isDone(), 'http request captured by nock');
513
+ _chai.assert.deepEqual(res.body, _apiDataExecuteNock.EXECUTE_SUCCESS_RESPONSE);
514
+ });
515
+ it(`should send a HTTP POST request including ${_contentTypes.CONTENT_TYPE_APPLICATION_JSON} body when the stream option is true`, async () => {
516
+ const url = 'http://www.rqlite.com:4001';
517
+ const httpRequest = new _.default(url);
518
+ const path = '/test';
519
+ const body = ['INSERT INTO foo(name) VALUES("fiona")'];
520
+ const scope = (0, _apiDataExecuteNock.executeSuccess)({ url, path });
521
+ const request = await httpRequest.post({ uri: path, body, stream: true });
522
+ const result = await handleRequestStreamAsPromise(request);
523
+ _chai.assert.isTrue(scope.isDone(), 'http request captured by nock');
524
+ _chai.assert.deepEqual(result, _apiDataExecuteNock.EXECUTE_SUCCESS_RESPONSE);
525
+ });
526
+ it(`should send a HTTP POST request including ${_contentTypes.CONTENT_TYPE_APPLICATION_JSON} body with basic auth when the stream option is true`, async () => {
527
+ const url = 'http://www.rqlite.com:4001';
528
+ const httpRequest = new _.default(url, {
529
+ authentication: {
530
+ username,
531
+ password
532
+ }
533
+ });
534
+ const path = '/test';
535
+ const body = ['INSERT INTO foo(name) VALUES("fiona")'];
536
+ const scope = (0, _apiDataExecuteNock.executeSuccess)({ url, path, auth });
537
+ const request = await httpRequest.post({ uri: path, body, stream: true });
538
+ const result = await handleRequestStreamAsPromise(request);
539
+ _chai.assert.isTrue(scope.isDone(), 'http request captured by nock');
540
+ _chai.assert.deepEqual(result, _apiDataExecuteNock.EXECUTE_SUCCESS_RESPONSE);
541
+ });
542
+ it(`should send a HTTP POST request including ${_contentTypes.CONTENT_TYPE_APPLICATION_JSON} body with basic auth used in constructor when the stream option is true`, async () => {
543
+ const url = 'http://www.rqlite.com:4001';
544
+ const httpRequest = new _.default(url, {
545
+ authentication: {
546
+ username,
547
+ password
548
+ }
549
+ });
550
+ const path = '/test';
551
+ const body = ['INSERT INTO foo(name) VALUES("fiona")'];
552
+ const scope = (0, _apiDataExecuteNock.executeSuccess)({ url, path, auth });
553
+ const request = await httpRequest.post({ uri: path, body, stream: true });
554
+ const result = await handleRequestStreamAsPromise(request);
555
+ _chai.assert.isTrue(scope.isDone(), 'http request captured by nock');
556
+ _chai.assert.deepEqual(result, _apiDataExecuteNock.EXECUTE_SUCCESS_RESPONSE);
557
+ });
558
+ });
559
+ });
560
+ //# sourceMappingURL=test.unit.js.map