@webex/http-core 2.59.2 → 2.59.3-next.1
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/.eslintrc.js +6 -6
- package/README.md +64 -64
- package/babel.config.js +3 -3
- package/dist/http-error-subtypes.js +57 -57
- package/dist/http-error-subtypes.js.map +1 -1
- package/dist/http-error.js +25 -25
- package/dist/http-error.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/interceptors/http-status.js +13 -13
- package/dist/interceptors/http-status.js.map +1 -1
- package/dist/lib/detect.js +6 -6
- package/dist/lib/detect.js.map +1 -1
- package/dist/lib/interceptor.js +34 -34
- package/dist/lib/interceptor.js.map +1 -1
- package/dist/lib/xhr.js +2 -2
- package/dist/lib/xhr.js.map +1 -1
- package/dist/progress-event.js +6 -6
- package/dist/progress-event.js.map +1 -1
- package/dist/request/index.js +11 -11
- package/dist/request/index.js.map +1 -1
- package/dist/request/request.js +14 -14
- package/dist/request/request.js.map +1 -1
- package/dist/request/request.shim.js +65 -65
- package/dist/request/request.shim.js.map +1 -1
- package/jest.config.js +3 -3
- package/package.json +18 -17
- package/process +1 -1
- package/src/http-error-subtypes.js +187 -187
- package/src/http-error.js +147 -147
- package/src/index.js +58 -58
- package/src/interceptors/http-status.js +63 -63
- package/src/lib/detect.js +33 -33
- package/src/lib/interceptor.js +95 -95
- package/src/lib/xhr.js +258 -258
- package/src/progress-event.js +37 -37
- package/src/request/index.js +62 -62
- package/src/request/request.js +109 -109
- package/src/request/request.shim.js +304 -304
- package/test/integration/spec/http-error.js +188 -188
- package/test/integration/spec/interceptor.js +71 -71
- package/test/integration/spec/progress-event.js +83 -83
- package/test/integration/spec/request.js +310 -310
- package/test/unit/spec/interceptors/http-status.js +49 -49
|
@@ -1,310 +1,310 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import {inBrowser} from '@webex/common';
|
|
6
|
-
import {assert} from '@webex/test-helper-chai';
|
|
7
|
-
import file from '@webex/test-helper-file';
|
|
8
|
-
import {HttpError, request} from '@webex/http-core';
|
|
9
|
-
import makeLocalUrl from '@webex/test-helper-make-local-url';
|
|
10
|
-
import sinon from 'sinon';
|
|
11
|
-
import {flaky, nodeOnly} from '@webex/test-helper-mocha';
|
|
12
|
-
|
|
13
|
-
describe('http-core', function () {
|
|
14
|
-
this.timeout(30000);
|
|
15
|
-
describe('request()', () => {
|
|
16
|
-
describe('GET', () => {
|
|
17
|
-
it('retrieves html', () =>
|
|
18
|
-
request({uri: makeLocalUrl('/')}).then((res) => {
|
|
19
|
-
assert.statusCode(res, 200);
|
|
20
|
-
assert.isString(res.body);
|
|
21
|
-
}));
|
|
22
|
-
|
|
23
|
-
it('attaches the request options object to every response', () =>
|
|
24
|
-
request(makeLocalUrl('/')).then((res) => {
|
|
25
|
-
assert.property(res, 'options');
|
|
26
|
-
assert.property(res.options, 'uri');
|
|
27
|
-
assert.equal(res.options.uri, makeLocalUrl('/'));
|
|
28
|
-
}));
|
|
29
|
-
|
|
30
|
-
it('accepts `uri` as a separate parameter from `options`', () =>
|
|
31
|
-
request(makeLocalUrl('/')).then((res) => {
|
|
32
|
-
assert.statusCode(res, 200);
|
|
33
|
-
assert.isString(res.body);
|
|
34
|
-
}));
|
|
35
|
-
|
|
36
|
-
it('normalizes `options.url` as `options.uri`', () =>
|
|
37
|
-
request({url: makeLocalUrl('/')}).then((res) => {
|
|
38
|
-
assert.statusCode(res, 200);
|
|
39
|
-
assert.isString(res.body);
|
|
40
|
-
}));
|
|
41
|
-
|
|
42
|
-
it('retrieves JSON', () =>
|
|
43
|
-
request({uri: makeLocalUrl('/json/get')}).then((res) => {
|
|
44
|
-
assert.statusCode(res, 200);
|
|
45
|
-
assert.isObject(res.body);
|
|
46
|
-
assert.deepEqual(res.body, {isObject: true});
|
|
47
|
-
}));
|
|
48
|
-
|
|
49
|
-
it('emits download progress events', () => {
|
|
50
|
-
const options = {uri: makeLocalUrl('/sample-image-small-one.png')};
|
|
51
|
-
const promise = request(options);
|
|
52
|
-
const spy = sinon.spy();
|
|
53
|
-
|
|
54
|
-
options.download.on('progress', spy);
|
|
55
|
-
|
|
56
|
-
return promise.then(() => {
|
|
57
|
-
assert.called(spy);
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
describe('with responseType="buffer"', () => {
|
|
62
|
-
it('retrieves a file as a buffer', () =>
|
|
63
|
-
request({
|
|
64
|
-
uri: makeLocalUrl('/sample-image-small-one.png'),
|
|
65
|
-
responseType: 'buffer',
|
|
66
|
-
}).then((res) => {
|
|
67
|
-
assert.isBufferLike(res.body);
|
|
68
|
-
}));
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
describe('with responseType="blob"', () => {
|
|
72
|
-
it('retrieves a file as a file', () =>
|
|
73
|
-
request({
|
|
74
|
-
uri: makeLocalUrl('/sample-image-small-one.png'),
|
|
75
|
-
responseType: 'blob',
|
|
76
|
-
}).then((res) => {
|
|
77
|
-
assert.isBlobLike(res.body);
|
|
78
|
-
}));
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it('makes CORS compatible calls', () =>
|
|
82
|
-
request({
|
|
83
|
-
uri: 'https://ds.ciscospark.com/v1/region/',
|
|
84
|
-
}).then((res) => {
|
|
85
|
-
assert.notEqual(res.statusCode, 0);
|
|
86
|
-
}));
|
|
87
|
-
|
|
88
|
-
it('fails with a subtyped error', () =>
|
|
89
|
-
assert
|
|
90
|
-
.isRejected(
|
|
91
|
-
request({
|
|
92
|
-
uri: makeLocalUrl('/not-a-route'),
|
|
93
|
-
})
|
|
94
|
-
)
|
|
95
|
-
.then((err) => {
|
|
96
|
-
assert.instanceOf(err, HttpError);
|
|
97
|
-
assert.instanceOf(err, HttpError.BadRequest);
|
|
98
|
-
}));
|
|
99
|
-
|
|
100
|
-
// This is somewhat difficult to test in web browser, but network errors in
|
|
101
|
-
// browser look like network errors in browsers, so testing it isn`t that
|
|
102
|
-
// critical. That said, moving the error-reformatting logic out of the
|
|
103
|
-
// environment-specific implementations may make this easier to stub.
|
|
104
|
-
nodeOnly(it)('makes network errors look mostly like HTTP errors', () =>
|
|
105
|
-
assert.isRejected(request('https://localhost:0/not-a-route')).then((err) => {
|
|
106
|
-
assert.instanceOf(err, HttpError.NetworkOrCORSError);
|
|
107
|
-
})
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
it('passes cookies', () =>
|
|
111
|
-
request({
|
|
112
|
-
uri: makeLocalUrl('/cookies/set'),
|
|
113
|
-
jar: true,
|
|
114
|
-
})
|
|
115
|
-
.then(() =>
|
|
116
|
-
request({
|
|
117
|
-
uri: makeLocalUrl('/cookies/expect'),
|
|
118
|
-
jar: true,
|
|
119
|
-
})
|
|
120
|
-
)
|
|
121
|
-
.then((res) => {
|
|
122
|
-
assert.statusCode(res, 200);
|
|
123
|
-
}));
|
|
124
|
-
|
|
125
|
-
// this test fails in Safari 8+
|
|
126
|
-
nodeOnly(it)('passes cookies to endpoints on other origins', () => {
|
|
127
|
-
const p1 = request({
|
|
128
|
-
uri: `http://localhost:${process.env.CORS_PORT}/cookies/set`,
|
|
129
|
-
jar: true,
|
|
130
|
-
})
|
|
131
|
-
.then(() =>
|
|
132
|
-
request({
|
|
133
|
-
uri: `http://localhost:${process.env.CORS_PORT}/cookies/expect`,
|
|
134
|
-
jar: true,
|
|
135
|
-
})
|
|
136
|
-
)
|
|
137
|
-
.then((res) => {
|
|
138
|
-
assert.statusCode(res, 200);
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
const p2 = request({
|
|
142
|
-
uri: `http://localhost:${process.env.CORS_PORT}/cookies/set`,
|
|
143
|
-
withCredentials: true,
|
|
144
|
-
})
|
|
145
|
-
.then(() =>
|
|
146
|
-
request({
|
|
147
|
-
uri: `http://localhost:${process.env.CORS_PORT}/cookies/expect`,
|
|
148
|
-
withCredentials: true,
|
|
149
|
-
})
|
|
150
|
-
)
|
|
151
|
-
.then((res) => {
|
|
152
|
-
assert.statusCode(res, 200);
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
return Promise.all([p1, p2]);
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
it('makes Basic Auth authenticated requests', () => {
|
|
159
|
-
const p1 = request({
|
|
160
|
-
uri: makeLocalUrl('/requires-basic-auth'),
|
|
161
|
-
auth: {
|
|
162
|
-
pass: 'basicpass',
|
|
163
|
-
user: 'basicuser',
|
|
164
|
-
},
|
|
165
|
-
}).then((res) => {
|
|
166
|
-
assert.statusCode(res, 200);
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
const p2 = request({
|
|
170
|
-
uri: makeLocalUrl('/requires-basic-auth'),
|
|
171
|
-
auth: {
|
|
172
|
-
password: 'basicpass',
|
|
173
|
-
username: 'basicuser',
|
|
174
|
-
},
|
|
175
|
-
}).then((res) => {
|
|
176
|
-
assert.statusCode(res, 200);
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
return Promise.all([p1, p2]);
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
it('makes Bearer Auth authenticated requests', () =>
|
|
183
|
-
request({
|
|
184
|
-
uri: makeLocalUrl('/requires-bearer-auth'),
|
|
185
|
-
auth: {
|
|
186
|
-
bearer: 'bearertoken',
|
|
187
|
-
},
|
|
188
|
-
}).then((res) => {
|
|
189
|
-
assert.statusCode(res, 200);
|
|
190
|
-
}));
|
|
191
|
-
|
|
192
|
-
it('encodes querystring parameters', () => {
|
|
193
|
-
// treat all types as strings because that`s how querystrings get parsed
|
|
194
|
-
// on the server
|
|
195
|
-
const qs = {
|
|
196
|
-
string: 'this is a string',
|
|
197
|
-
object: {
|
|
198
|
-
string: 'this is a another string',
|
|
199
|
-
boolean: 'true',
|
|
200
|
-
integer: '5',
|
|
201
|
-
},
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
return request({
|
|
205
|
-
uri: makeLocalUrl('/return-qs-as-object'),
|
|
206
|
-
qs,
|
|
207
|
-
}).then((res) => {
|
|
208
|
-
assert.deepEqual(res.body, qs);
|
|
209
|
-
});
|
|
210
|
-
});
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
flaky(it, process.env.SKIP_FLAKY_TESTS)('submits files as multipart form data', () => {
|
|
214
|
-
file.fetch('sample-powerpoint-two-page.ppt').then((f) =>
|
|
215
|
-
request({
|
|
216
|
-
method: 'POST',
|
|
217
|
-
uri: makeLocalUrl('/files/metadata'),
|
|
218
|
-
formData: {
|
|
219
|
-
files: [f],
|
|
220
|
-
},
|
|
221
|
-
json: true,
|
|
222
|
-
}).then((res) => {
|
|
223
|
-
// This asserts that the server received the file and was able to
|
|
224
|
-
// decode its filename.
|
|
225
|
-
assert.equal(res.body[0].originalname, f.name);
|
|
226
|
-
})
|
|
227
|
-
);
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
['PUT', 'PATCH', 'POST'].forEach((method) => {
|
|
231
|
-
describe(method, () => {
|
|
232
|
-
it('submits json', () => {
|
|
233
|
-
const payload = {
|
|
234
|
-
string: 'this is a string',
|
|
235
|
-
object: {
|
|
236
|
-
string: 'this is a another string',
|
|
237
|
-
boolean: 'true',
|
|
238
|
-
integer: '5',
|
|
239
|
-
},
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
return request({
|
|
243
|
-
method,
|
|
244
|
-
uri: makeLocalUrl('/json/set'),
|
|
245
|
-
body: payload,
|
|
246
|
-
}).then((res) => {
|
|
247
|
-
assert.statusCode(res, 200);
|
|
248
|
-
assert.deepEqual(res.body, payload);
|
|
249
|
-
});
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
it('submits urlencoded form data', () =>
|
|
253
|
-
// treat all types as strings because that`s how querystrings get parsed
|
|
254
|
-
// on the server
|
|
255
|
-
request({
|
|
256
|
-
method,
|
|
257
|
-
uri: makeLocalUrl('/form/reflect'),
|
|
258
|
-
form: {
|
|
259
|
-
a: 1,
|
|
260
|
-
b: 2,
|
|
261
|
-
},
|
|
262
|
-
}).then((res) => {
|
|
263
|
-
assert.statusCode(res, 200);
|
|
264
|
-
assert.deepEqual(res.body, {
|
|
265
|
-
a: '1',
|
|
266
|
-
b: '2',
|
|
267
|
-
});
|
|
268
|
-
}));
|
|
269
|
-
|
|
270
|
-
it('submits files', () =>
|
|
271
|
-
file.fetch('/sample-image-small-one.png').then((f) =>
|
|
272
|
-
request({
|
|
273
|
-
method,
|
|
274
|
-
uri: makeLocalUrl('/files/reflect'),
|
|
275
|
-
body: f,
|
|
276
|
-
json: false,
|
|
277
|
-
// Note: setting response type so the `reflect()ed` response is in
|
|
278
|
-
// a form we can use, this is not needed for normal file uploads.
|
|
279
|
-
responseType: 'blob',
|
|
280
|
-
}).then((res) => {
|
|
281
|
-
assert.equal(res.body.type, f.type);
|
|
282
|
-
|
|
283
|
-
return file.isMatchingFile(res.body, f).then((result) => assert.isTrue(result));
|
|
284
|
-
})
|
|
285
|
-
));
|
|
286
|
-
|
|
287
|
-
(inBrowser ? it : it.skip)('emits upload progress events', () =>
|
|
288
|
-
file.fetch('/sample-image-small-one.png').then((f) => {
|
|
289
|
-
const options = {
|
|
290
|
-
method,
|
|
291
|
-
uri: makeLocalUrl('/files/reflect'),
|
|
292
|
-
body: f,
|
|
293
|
-
json: false,
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
const promise = request(options);
|
|
297
|
-
|
|
298
|
-
const spy = sinon.spy();
|
|
299
|
-
|
|
300
|
-
options.upload.on('progress', spy);
|
|
301
|
-
|
|
302
|
-
return promise.then(() => {
|
|
303
|
-
assert.called(spy);
|
|
304
|
-
});
|
|
305
|
-
})
|
|
306
|
-
);
|
|
307
|
-
});
|
|
308
|
-
});
|
|
309
|
-
});
|
|
310
|
-
});
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {inBrowser} from '@webex/common';
|
|
6
|
+
import {assert} from '@webex/test-helper-chai';
|
|
7
|
+
import file from '@webex/test-helper-file';
|
|
8
|
+
import {HttpError, request} from '@webex/http-core';
|
|
9
|
+
import makeLocalUrl from '@webex/test-helper-make-local-url';
|
|
10
|
+
import sinon from 'sinon';
|
|
11
|
+
import {flaky, nodeOnly} from '@webex/test-helper-mocha';
|
|
12
|
+
|
|
13
|
+
describe('http-core', function () {
|
|
14
|
+
this.timeout(30000);
|
|
15
|
+
describe('request()', () => {
|
|
16
|
+
describe('GET', () => {
|
|
17
|
+
it('retrieves html', () =>
|
|
18
|
+
request({uri: makeLocalUrl('/')}).then((res) => {
|
|
19
|
+
assert.statusCode(res, 200);
|
|
20
|
+
assert.isString(res.body);
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
it('attaches the request options object to every response', () =>
|
|
24
|
+
request(makeLocalUrl('/')).then((res) => {
|
|
25
|
+
assert.property(res, 'options');
|
|
26
|
+
assert.property(res.options, 'uri');
|
|
27
|
+
assert.equal(res.options.uri, makeLocalUrl('/'));
|
|
28
|
+
}));
|
|
29
|
+
|
|
30
|
+
it('accepts `uri` as a separate parameter from `options`', () =>
|
|
31
|
+
request(makeLocalUrl('/')).then((res) => {
|
|
32
|
+
assert.statusCode(res, 200);
|
|
33
|
+
assert.isString(res.body);
|
|
34
|
+
}));
|
|
35
|
+
|
|
36
|
+
it('normalizes `options.url` as `options.uri`', () =>
|
|
37
|
+
request({url: makeLocalUrl('/')}).then((res) => {
|
|
38
|
+
assert.statusCode(res, 200);
|
|
39
|
+
assert.isString(res.body);
|
|
40
|
+
}));
|
|
41
|
+
|
|
42
|
+
it('retrieves JSON', () =>
|
|
43
|
+
request({uri: makeLocalUrl('/json/get')}).then((res) => {
|
|
44
|
+
assert.statusCode(res, 200);
|
|
45
|
+
assert.isObject(res.body);
|
|
46
|
+
assert.deepEqual(res.body, {isObject: true});
|
|
47
|
+
}));
|
|
48
|
+
|
|
49
|
+
it('emits download progress events', () => {
|
|
50
|
+
const options = {uri: makeLocalUrl('/sample-image-small-one.png')};
|
|
51
|
+
const promise = request(options);
|
|
52
|
+
const spy = sinon.spy();
|
|
53
|
+
|
|
54
|
+
options.download.on('progress', spy);
|
|
55
|
+
|
|
56
|
+
return promise.then(() => {
|
|
57
|
+
assert.called(spy);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe('with responseType="buffer"', () => {
|
|
62
|
+
it('retrieves a file as a buffer', () =>
|
|
63
|
+
request({
|
|
64
|
+
uri: makeLocalUrl('/sample-image-small-one.png'),
|
|
65
|
+
responseType: 'buffer',
|
|
66
|
+
}).then((res) => {
|
|
67
|
+
assert.isBufferLike(res.body);
|
|
68
|
+
}));
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe('with responseType="blob"', () => {
|
|
72
|
+
it('retrieves a file as a file', () =>
|
|
73
|
+
request({
|
|
74
|
+
uri: makeLocalUrl('/sample-image-small-one.png'),
|
|
75
|
+
responseType: 'blob',
|
|
76
|
+
}).then((res) => {
|
|
77
|
+
assert.isBlobLike(res.body);
|
|
78
|
+
}));
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('makes CORS compatible calls', () =>
|
|
82
|
+
request({
|
|
83
|
+
uri: 'https://ds.ciscospark.com/v1/region/',
|
|
84
|
+
}).then((res) => {
|
|
85
|
+
assert.notEqual(res.statusCode, 0);
|
|
86
|
+
}));
|
|
87
|
+
|
|
88
|
+
it('fails with a subtyped error', () =>
|
|
89
|
+
assert
|
|
90
|
+
.isRejected(
|
|
91
|
+
request({
|
|
92
|
+
uri: makeLocalUrl('/not-a-route'),
|
|
93
|
+
})
|
|
94
|
+
)
|
|
95
|
+
.then((err) => {
|
|
96
|
+
assert.instanceOf(err, HttpError);
|
|
97
|
+
assert.instanceOf(err, HttpError.BadRequest);
|
|
98
|
+
}));
|
|
99
|
+
|
|
100
|
+
// This is somewhat difficult to test in web browser, but network errors in
|
|
101
|
+
// browser look like network errors in browsers, so testing it isn`t that
|
|
102
|
+
// critical. That said, moving the error-reformatting logic out of the
|
|
103
|
+
// environment-specific implementations may make this easier to stub.
|
|
104
|
+
nodeOnly(it)('makes network errors look mostly like HTTP errors', () =>
|
|
105
|
+
assert.isRejected(request('https://localhost:0/not-a-route')).then((err) => {
|
|
106
|
+
assert.instanceOf(err, HttpError.NetworkOrCORSError);
|
|
107
|
+
})
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
it('passes cookies', () =>
|
|
111
|
+
request({
|
|
112
|
+
uri: makeLocalUrl('/cookies/set'),
|
|
113
|
+
jar: true,
|
|
114
|
+
})
|
|
115
|
+
.then(() =>
|
|
116
|
+
request({
|
|
117
|
+
uri: makeLocalUrl('/cookies/expect'),
|
|
118
|
+
jar: true,
|
|
119
|
+
})
|
|
120
|
+
)
|
|
121
|
+
.then((res) => {
|
|
122
|
+
assert.statusCode(res, 200);
|
|
123
|
+
}));
|
|
124
|
+
|
|
125
|
+
// this test fails in Safari 8+
|
|
126
|
+
nodeOnly(it)('passes cookies to endpoints on other origins', () => {
|
|
127
|
+
const p1 = request({
|
|
128
|
+
uri: `http://localhost:${process.env.CORS_PORT}/cookies/set`,
|
|
129
|
+
jar: true,
|
|
130
|
+
})
|
|
131
|
+
.then(() =>
|
|
132
|
+
request({
|
|
133
|
+
uri: `http://localhost:${process.env.CORS_PORT}/cookies/expect`,
|
|
134
|
+
jar: true,
|
|
135
|
+
})
|
|
136
|
+
)
|
|
137
|
+
.then((res) => {
|
|
138
|
+
assert.statusCode(res, 200);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
const p2 = request({
|
|
142
|
+
uri: `http://localhost:${process.env.CORS_PORT}/cookies/set`,
|
|
143
|
+
withCredentials: true,
|
|
144
|
+
})
|
|
145
|
+
.then(() =>
|
|
146
|
+
request({
|
|
147
|
+
uri: `http://localhost:${process.env.CORS_PORT}/cookies/expect`,
|
|
148
|
+
withCredentials: true,
|
|
149
|
+
})
|
|
150
|
+
)
|
|
151
|
+
.then((res) => {
|
|
152
|
+
assert.statusCode(res, 200);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
return Promise.all([p1, p2]);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('makes Basic Auth authenticated requests', () => {
|
|
159
|
+
const p1 = request({
|
|
160
|
+
uri: makeLocalUrl('/requires-basic-auth'),
|
|
161
|
+
auth: {
|
|
162
|
+
pass: 'basicpass',
|
|
163
|
+
user: 'basicuser',
|
|
164
|
+
},
|
|
165
|
+
}).then((res) => {
|
|
166
|
+
assert.statusCode(res, 200);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
const p2 = request({
|
|
170
|
+
uri: makeLocalUrl('/requires-basic-auth'),
|
|
171
|
+
auth: {
|
|
172
|
+
password: 'basicpass',
|
|
173
|
+
username: 'basicuser',
|
|
174
|
+
},
|
|
175
|
+
}).then((res) => {
|
|
176
|
+
assert.statusCode(res, 200);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
return Promise.all([p1, p2]);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it('makes Bearer Auth authenticated requests', () =>
|
|
183
|
+
request({
|
|
184
|
+
uri: makeLocalUrl('/requires-bearer-auth'),
|
|
185
|
+
auth: {
|
|
186
|
+
bearer: 'bearertoken',
|
|
187
|
+
},
|
|
188
|
+
}).then((res) => {
|
|
189
|
+
assert.statusCode(res, 200);
|
|
190
|
+
}));
|
|
191
|
+
|
|
192
|
+
it('encodes querystring parameters', () => {
|
|
193
|
+
// treat all types as strings because that`s how querystrings get parsed
|
|
194
|
+
// on the server
|
|
195
|
+
const qs = {
|
|
196
|
+
string: 'this is a string',
|
|
197
|
+
object: {
|
|
198
|
+
string: 'this is a another string',
|
|
199
|
+
boolean: 'true',
|
|
200
|
+
integer: '5',
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
return request({
|
|
205
|
+
uri: makeLocalUrl('/return-qs-as-object'),
|
|
206
|
+
qs,
|
|
207
|
+
}).then((res) => {
|
|
208
|
+
assert.deepEqual(res.body, qs);
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
flaky(it, process.env.SKIP_FLAKY_TESTS)('submits files as multipart form data', () => {
|
|
214
|
+
file.fetch('sample-powerpoint-two-page.ppt').then((f) =>
|
|
215
|
+
request({
|
|
216
|
+
method: 'POST',
|
|
217
|
+
uri: makeLocalUrl('/files/metadata'),
|
|
218
|
+
formData: {
|
|
219
|
+
files: [f],
|
|
220
|
+
},
|
|
221
|
+
json: true,
|
|
222
|
+
}).then((res) => {
|
|
223
|
+
// This asserts that the server received the file and was able to
|
|
224
|
+
// decode its filename.
|
|
225
|
+
assert.equal(res.body[0].originalname, f.name);
|
|
226
|
+
})
|
|
227
|
+
);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
['PUT', 'PATCH', 'POST'].forEach((method) => {
|
|
231
|
+
describe(method, () => {
|
|
232
|
+
it('submits json', () => {
|
|
233
|
+
const payload = {
|
|
234
|
+
string: 'this is a string',
|
|
235
|
+
object: {
|
|
236
|
+
string: 'this is a another string',
|
|
237
|
+
boolean: 'true',
|
|
238
|
+
integer: '5',
|
|
239
|
+
},
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
return request({
|
|
243
|
+
method,
|
|
244
|
+
uri: makeLocalUrl('/json/set'),
|
|
245
|
+
body: payload,
|
|
246
|
+
}).then((res) => {
|
|
247
|
+
assert.statusCode(res, 200);
|
|
248
|
+
assert.deepEqual(res.body, payload);
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it('submits urlencoded form data', () =>
|
|
253
|
+
// treat all types as strings because that`s how querystrings get parsed
|
|
254
|
+
// on the server
|
|
255
|
+
request({
|
|
256
|
+
method,
|
|
257
|
+
uri: makeLocalUrl('/form/reflect'),
|
|
258
|
+
form: {
|
|
259
|
+
a: 1,
|
|
260
|
+
b: 2,
|
|
261
|
+
},
|
|
262
|
+
}).then((res) => {
|
|
263
|
+
assert.statusCode(res, 200);
|
|
264
|
+
assert.deepEqual(res.body, {
|
|
265
|
+
a: '1',
|
|
266
|
+
b: '2',
|
|
267
|
+
});
|
|
268
|
+
}));
|
|
269
|
+
|
|
270
|
+
it('submits files', () =>
|
|
271
|
+
file.fetch('/sample-image-small-one.png').then((f) =>
|
|
272
|
+
request({
|
|
273
|
+
method,
|
|
274
|
+
uri: makeLocalUrl('/files/reflect'),
|
|
275
|
+
body: f,
|
|
276
|
+
json: false,
|
|
277
|
+
// Note: setting response type so the `reflect()ed` response is in
|
|
278
|
+
// a form we can use, this is not needed for normal file uploads.
|
|
279
|
+
responseType: 'blob',
|
|
280
|
+
}).then((res) => {
|
|
281
|
+
assert.equal(res.body.type, f.type);
|
|
282
|
+
|
|
283
|
+
return file.isMatchingFile(res.body, f).then((result) => assert.isTrue(result));
|
|
284
|
+
})
|
|
285
|
+
));
|
|
286
|
+
|
|
287
|
+
(inBrowser ? it : it.skip)('emits upload progress events', () =>
|
|
288
|
+
file.fetch('/sample-image-small-one.png').then((f) => {
|
|
289
|
+
const options = {
|
|
290
|
+
method,
|
|
291
|
+
uri: makeLocalUrl('/files/reflect'),
|
|
292
|
+
body: f,
|
|
293
|
+
json: false,
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
const promise = request(options);
|
|
297
|
+
|
|
298
|
+
const spy = sinon.spy();
|
|
299
|
+
|
|
300
|
+
options.upload.on('progress', spy);
|
|
301
|
+
|
|
302
|
+
return promise.then(() => {
|
|
303
|
+
assert.called(spy);
|
|
304
|
+
});
|
|
305
|
+
})
|
|
306
|
+
);
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
});
|