228 lines
6.5 KiB
JavaScript
228 lines
6.5 KiB
JavaScript
/**
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @format
|
|
* @emails oncall+react_native
|
|
*/
|
|
|
|
'use strict';
|
|
jest.unmock('Platform');
|
|
const Platform = require('Platform');
|
|
let requestId = 1;
|
|
|
|
function setRequestId(id) {
|
|
if (Platform.OS === 'ios') {
|
|
return;
|
|
}
|
|
requestId = id;
|
|
}
|
|
|
|
jest.dontMock('event-target-shim').setMock('NativeModules', {
|
|
Networking: {
|
|
addListener: function() {},
|
|
removeListeners: function() {},
|
|
sendRequest(options, callback) {
|
|
if (typeof callback === 'function') {
|
|
// android does not pass a callback
|
|
callback(requestId);
|
|
}
|
|
},
|
|
abortRequest: function() {},
|
|
},
|
|
});
|
|
|
|
const XMLHttpRequest = require('XMLHttpRequest');
|
|
|
|
describe('XMLHttpRequest', function() {
|
|
let xhr;
|
|
let handleTimeout;
|
|
let handleError;
|
|
let handleLoad;
|
|
let handleReadyStateChange;
|
|
let handleLoadEnd;
|
|
|
|
beforeEach(() => {
|
|
xhr = new XMLHttpRequest();
|
|
|
|
xhr.ontimeout = jest.fn();
|
|
xhr.onerror = jest.fn();
|
|
xhr.onload = jest.fn();
|
|
xhr.onloadend = jest.fn();
|
|
xhr.onreadystatechange = jest.fn();
|
|
|
|
handleTimeout = jest.fn();
|
|
handleError = jest.fn();
|
|
handleLoad = jest.fn();
|
|
handleLoadEnd = jest.fn();
|
|
handleReadyStateChange = jest.fn();
|
|
|
|
xhr.addEventListener('timeout', handleTimeout);
|
|
xhr.addEventListener('error', handleError);
|
|
xhr.addEventListener('load', handleLoad);
|
|
xhr.addEventListener('loadend', handleLoadEnd);
|
|
xhr.addEventListener('readystatechange', handleReadyStateChange);
|
|
});
|
|
|
|
afterEach(() => {
|
|
xhr = null;
|
|
handleTimeout = null;
|
|
handleError = null;
|
|
handleLoad = null;
|
|
handleLoadEnd = null;
|
|
handleReadyStateChange = null;
|
|
});
|
|
|
|
it('should transition readyState correctly', function() {
|
|
expect(xhr.readyState).toBe(xhr.UNSENT);
|
|
|
|
xhr.open('GET', 'blabla');
|
|
|
|
expect(xhr.onreadystatechange.mock.calls.length).toBe(1);
|
|
expect(handleReadyStateChange.mock.calls.length).toBe(1);
|
|
expect(xhr.readyState).toBe(xhr.OPENED);
|
|
});
|
|
|
|
it('should expose responseType correctly', function() {
|
|
expect(xhr.responseType).toBe('');
|
|
|
|
// Setting responseType to an unsupported value has no effect.
|
|
xhr.responseType = 'arrayblobbuffertextfile';
|
|
expect(xhr.responseType).toBe('');
|
|
|
|
xhr.responseType = 'arraybuffer';
|
|
expect(xhr.responseType).toBe('arraybuffer');
|
|
|
|
// Can't change responseType after first data has been received.
|
|
xhr.open('GET', 'blabla');
|
|
xhr.send();
|
|
expect(() => {
|
|
xhr.responseType = 'text';
|
|
}).toThrow();
|
|
});
|
|
|
|
it('should expose responseText correctly', function() {
|
|
xhr.responseType = '';
|
|
expect(xhr.responseText).toBe('');
|
|
expect(xhr.response).toBe('');
|
|
|
|
xhr.responseType = 'arraybuffer';
|
|
expect(() => xhr.responseText).toThrow();
|
|
expect(xhr.response).toBe(null);
|
|
|
|
xhr.responseType = 'text';
|
|
expect(xhr.responseText).toBe('');
|
|
expect(xhr.response).toBe('');
|
|
|
|
// responseText is read-only.
|
|
expect(() => {
|
|
xhr.responseText = 'hi';
|
|
}).toThrow();
|
|
expect(xhr.responseText).toBe('');
|
|
expect(xhr.response).toBe('');
|
|
|
|
xhr.open('GET', 'blabla');
|
|
xhr.send();
|
|
setRequestId(2);
|
|
xhr.__didReceiveData(requestId, 'Some data');
|
|
expect(xhr.responseText).toBe('Some data');
|
|
});
|
|
|
|
it('should call ontimeout function when the request times out', function() {
|
|
xhr.open('GET', 'blabla');
|
|
xhr.send();
|
|
setRequestId(3);
|
|
xhr.__didCompleteResponse(requestId, 'Timeout', true);
|
|
xhr.__didCompleteResponse(requestId, 'Timeout', true);
|
|
|
|
expect(xhr.readyState).toBe(xhr.DONE);
|
|
|
|
expect(xhr.ontimeout.mock.calls.length).toBe(1);
|
|
expect(xhr.onloadend.mock.calls.length).toBe(1);
|
|
expect(xhr.onerror).not.toBeCalled();
|
|
expect(xhr.onload).not.toBeCalled();
|
|
|
|
expect(handleTimeout.mock.calls.length).toBe(1);
|
|
expect(handleLoadEnd.mock.calls.length).toBe(1);
|
|
expect(handleError).not.toBeCalled();
|
|
expect(handleLoad).not.toBeCalled();
|
|
});
|
|
|
|
it('should call onerror function when the request times out', function() {
|
|
xhr.open('GET', 'blabla');
|
|
xhr.send();
|
|
setRequestId(4);
|
|
xhr.__didCompleteResponse(requestId, 'Generic error');
|
|
|
|
expect(xhr.readyState).toBe(xhr.DONE);
|
|
|
|
expect(xhr.onreadystatechange.mock.calls.length).toBe(2);
|
|
expect(xhr.onerror.mock.calls.length).toBe(1);
|
|
expect(xhr.onloadend.mock.calls.length).toBe(1);
|
|
expect(xhr.ontimeout).not.toBeCalled();
|
|
expect(xhr.onload).not.toBeCalled();
|
|
|
|
expect(handleReadyStateChange.mock.calls.length).toBe(2);
|
|
expect(handleError.mock.calls.length).toBe(1);
|
|
expect(handleLoadEnd.mock.calls.length).toBe(1);
|
|
expect(handleTimeout).not.toBeCalled();
|
|
expect(handleLoad).not.toBeCalled();
|
|
});
|
|
|
|
it('should call onload function when there is no error', function() {
|
|
xhr.open('GET', 'blabla');
|
|
xhr.send();
|
|
setRequestId(5);
|
|
xhr.__didCompleteResponse(requestId, null);
|
|
|
|
expect(xhr.readyState).toBe(xhr.DONE);
|
|
|
|
expect(xhr.onreadystatechange.mock.calls.length).toBe(2);
|
|
expect(xhr.onload.mock.calls.length).toBe(1);
|
|
expect(xhr.onloadend.mock.calls.length).toBe(1);
|
|
expect(xhr.onerror).not.toBeCalled();
|
|
expect(xhr.ontimeout).not.toBeCalled();
|
|
|
|
expect(handleReadyStateChange.mock.calls.length).toBe(2);
|
|
expect(handleLoad.mock.calls.length).toBe(1);
|
|
expect(handleLoadEnd.mock.calls.length).toBe(1);
|
|
expect(handleError).not.toBeCalled();
|
|
expect(handleTimeout).not.toBeCalled();
|
|
});
|
|
|
|
it('should call upload onprogress', function() {
|
|
xhr.open('GET', 'blabla');
|
|
xhr.send();
|
|
|
|
xhr.upload.onprogress = jest.fn();
|
|
const handleProgress = jest.fn();
|
|
xhr.upload.addEventListener('progress', handleProgress);
|
|
setRequestId(6);
|
|
xhr.__didUploadProgress(requestId, 42, 100);
|
|
|
|
expect(xhr.upload.onprogress.mock.calls.length).toBe(1);
|
|
expect(handleProgress.mock.calls.length).toBe(1);
|
|
|
|
expect(xhr.upload.onprogress.mock.calls[0][0].loaded).toBe(42);
|
|
expect(xhr.upload.onprogress.mock.calls[0][0].total).toBe(100);
|
|
expect(handleProgress.mock.calls[0][0].loaded).toBe(42);
|
|
expect(handleProgress.mock.calls[0][0].total).toBe(100);
|
|
});
|
|
|
|
it('should combine response headers with CRLF', function() {
|
|
xhr.open('GET', 'blabla');
|
|
xhr.send();
|
|
setRequestId(7);
|
|
xhr.__didReceiveResponse(requestId, 200, {
|
|
'Content-Type': 'text/plain; charset=utf-8',
|
|
'Content-Length': '32',
|
|
});
|
|
|
|
expect(xhr.getAllResponseHeaders()).toBe(
|
|
'Content-Type: text/plain; charset=utf-8\r\n' + 'Content-Length: 32',
|
|
);
|
|
});
|
|
});
|