mirror of
https://github.com/tenrok/axios.git
synced 2026-06-20 20:00:40 +03:00
JSON improvements: throw if JSON parsing failed; number, boolean can be passed directly as payload for encoding to JSON #2613, #61, #907 (#3688)
* Draft * Added support for primitive types to be converted to JSON if the request Content-Type is 'application/json'; Added throwing SyntaxError if JSON parsing failed and responseType is json; Added transitional option object; Added options validator to assert transitional options; Added transitional option `silentJSONParsing= true` for backward compatibility; Updated README.md; Updated typings; * Fixed isOlderVersion helper; Fixed typo; Added validator.spec.js; * Added forcedJSONParsing transitional option #2791 * `transformData` is now called in the default configuration context if the function context is not specified (for tests compatibility); * Added `transitional.clarifyTimeoutError` to throw ETIMEDOUT error instead of generic ECONNABORTED on request timeouts; Added support of onloadend handler if available instead of onreadystatechange; Added xhr timeout test; Fixed potential bug of xhr adapter with proper handling timeouts&errors (FakeXMLHTTPRequest failed to handle timeouts);
This commit is contained in:
@@ -25,7 +25,7 @@ describe('defaults', function () {
|
||||
});
|
||||
|
||||
it('should transform response json', function () {
|
||||
var data = defaults.transformResponse[0]('{"foo":"bar"}');
|
||||
var data = defaults.transformResponse[0].call(defaults, '{"foo":"bar"}');
|
||||
|
||||
expect(typeof data).toEqual('object');
|
||||
expect(data.foo).toEqual('bar');
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
'use strict';
|
||||
|
||||
var validator = require('../../../lib/helpers/validator');
|
||||
|
||||
describe('validator::isOlderVersion', function () {
|
||||
it('should return true if dest version is older than the package version', function () {
|
||||
expect(validator.isOlderVersion('0.0.1', '1.0.0')).toEqual(true);
|
||||
expect(validator.isOlderVersion('0.0.1', '0.1.0')).toEqual(true);
|
||||
expect(validator.isOlderVersion('0.0.1', '0.0.1')).toEqual(false);
|
||||
|
||||
|
||||
expect(validator.isOlderVersion('100.0.0', '1.0.0')).toEqual(false);
|
||||
expect(validator.isOlderVersion('100.0.0', '0.1.0')).toEqual(false);
|
||||
expect(validator.isOlderVersion('100.0.0', '0.0.1')).toEqual(false);
|
||||
|
||||
expect(validator.isOlderVersion('0.10000.0', '1000.0.1')).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('validator::assertOptions', function () {
|
||||
it('should throw only if unknown an option was passed', function () {
|
||||
expect(function() {
|
||||
validator.assertOptions({
|
||||
x: true
|
||||
}, {
|
||||
y: validator.validators.boolean
|
||||
});
|
||||
}).toThrow(new Error('Unknown option x'));
|
||||
|
||||
expect(function() {
|
||||
validator.assertOptions({
|
||||
x: true
|
||||
}, {
|
||||
x: validator.validators.boolean,
|
||||
y: validator.validators.boolean
|
||||
});
|
||||
}).not.toThrow(new Error('Unknown option x'));
|
||||
});
|
||||
|
||||
it('should throw TypeError only if option type doesn\'t match', function () {
|
||||
expect(function() {
|
||||
validator.assertOptions({
|
||||
x: 123
|
||||
}, {
|
||||
x: validator.validators.boolean
|
||||
});
|
||||
}).toThrow(new TypeError('option x must be a boolean'));
|
||||
|
||||
expect(function() {
|
||||
validator.assertOptions({
|
||||
x: true
|
||||
}, {
|
||||
x: validator.validators.boolean,
|
||||
y: validator.validators.boolean
|
||||
});
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
@@ -63,6 +63,51 @@ describe('requests', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('timeouts', function(){
|
||||
beforeEach(function () {
|
||||
jasmine.clock().install();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
jasmine.clock().uninstall();
|
||||
});
|
||||
|
||||
it('should handle timeouts', function (done) {
|
||||
axios({
|
||||
url: '/foo',
|
||||
timeout: 100
|
||||
}).then(function () {
|
||||
fail(new Error('timeout error not caught'));
|
||||
}, function (err) {
|
||||
expect(err instanceof Error).toBe(true);
|
||||
expect(err.code).toEqual('ECONNABORTED');
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().responseTimeout();
|
||||
});
|
||||
|
||||
describe('transitional.clarifyTimeoutError', function () {
|
||||
it('should activate throwing ETIMEDOUT instead of ECONNABORTED on request timeouts', function (done) {
|
||||
axios({
|
||||
url: '/foo',
|
||||
timeout: 100,
|
||||
transitional: {
|
||||
clarifyTimeoutError: true
|
||||
}
|
||||
}).then(function () {
|
||||
fail(new Error('timeout error not caught'));
|
||||
}, function (err) {
|
||||
expect(err instanceof Error).toBe(true);
|
||||
expect(err.code).toEqual('ETIMEDOUT');
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().responseTimeout();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should reject on network errors', function (done) {
|
||||
// disable jasmine.Ajax since we're hitting a non-existent server anyway
|
||||
jasmine.Ajax.uninstall();
|
||||
|
||||
@@ -41,6 +41,90 @@ describe('transform', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw a SyntaxError if JSON parsing failed and responseType is "json" if silentJSONParsing is false',
|
||||
function (done) {
|
||||
var thrown;
|
||||
|
||||
axios({
|
||||
url: '/foo',
|
||||
responseType: 'json',
|
||||
transitional: {silentJSONParsing: false}
|
||||
}).then(function () {
|
||||
done(new Error('should fail'));
|
||||
}, function (err) {
|
||||
thrown = err;
|
||||
});
|
||||
|
||||
getAjaxRequest().then(function (request) {
|
||||
request.respondWith({
|
||||
status: 200,
|
||||
responseText: '{foo": "bar"}' // JSON SyntaxError
|
||||
});
|
||||
|
||||
setTimeout(function () {
|
||||
expect(thrown).toBeTruthy();
|
||||
expect(thrown.name).toContain('SyntaxError');
|
||||
expect(thrown.message).toContain('JSON');
|
||||
done();
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
it('should send data as JSON if request content-type is application/json', function (done) {
|
||||
var response;
|
||||
|
||||
axios.post('/foo', 123, {headers: {'Content-Type': 'application/json'}}).then(function (_response) {
|
||||
response = _response;
|
||||
}, function (err) {
|
||||
done(err);
|
||||
});
|
||||
|
||||
getAjaxRequest().then(function (request) {
|
||||
request.respondWith({
|
||||
status: 200,
|
||||
responseText: ''
|
||||
});
|
||||
|
||||
setTimeout(function () {
|
||||
expect(response).toBeTruthy();
|
||||
expect(request.requestHeaders['Content-Type']).toBe('application/json');
|
||||
expect(JSON.parse(request.params)).toBe(123);
|
||||
done();
|
||||
}, 100);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not assume JSON if responseType is not `json`', function (done) {
|
||||
var response;
|
||||
|
||||
axios.get('/foo', {
|
||||
responseType: 'text',
|
||||
transitional: {
|
||||
forcedJSONParsing: false
|
||||
}
|
||||
}).then(function (_response) {
|
||||
response = _response;
|
||||
}, function (err) {
|
||||
done(err);
|
||||
});
|
||||
|
||||
var rawData = '{"x":1}';
|
||||
|
||||
getAjaxRequest().then(function (request) {
|
||||
request.respondWith({
|
||||
status: 200,
|
||||
responseText: rawData
|
||||
});
|
||||
|
||||
setTimeout(function () {
|
||||
expect(response).toBeTruthy();
|
||||
expect(response.data).toBe(rawData);
|
||||
done();
|
||||
}, 100);
|
||||
});
|
||||
});
|
||||
|
||||
it('should override default transform', function (done) {
|
||||
var data = {
|
||||
foo: 'bar'
|
||||
|
||||
@@ -27,4 +27,4 @@ describe('transformResponse', function () {
|
||||
assert.strictEqual(result, data);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user