Files
react-native/Libraries/Network/__tests__/XMLHttpRequest-test.js
T
Deepak Jacob 2c5a966054 Remove babel plugins from jest preprocessor which are part of preset
Summary:
Changelog:
[Internal][Changed] - Remove babel plugins from jest preprocessor which are part of preset metro-react-native-babel-preset

Transformer metro-react-native-babel-transformer has preset metro-react-native-babel-preset which has necessary plugins to transpile the source. So we don’t need to pass it again in the preprocessor.

As part of the change, updated one test to use strict mode since metro-react-native-babel-preset has strictMode is set to false.

Reviewed By: motiz88

Differential Revision: D34868961

fbshipit-source-id: 71678f1ee6f1b5ebf9a0c6fd2d6444a61d7583ac
2022-05-12 03:48:24 -07:00

316 lines
9.3 KiB
JavaScript

/**
* Copyright (c) Meta Platforms, Inc. and 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';
import createPerformanceLogger from '../../Utilities/createPerformanceLogger';
jest.unmock('../../Utilities/Platform');
jest.mock('../../Utilities/GlobalPerformanceLogger');
const Platform = require('../../Utilities/Platform');
const GlobalPerformanceLogger = require('../../Utilities/GlobalPerformanceLogger');
let requestId = 1;
function setRequestId(id) {
if (Platform.OS === 'ios') {
return;
}
requestId = id;
}
jest
.dontMock('event-target-shim')
.setMock('../../BatchedBridge/NativeModules', {
Networking: {
addListener: function () {},
removeListeners: function () {},
sendRequest(options, callback) {
if (typeof callback === 'function') {
// android does not pass a callback
callback(requestId);
}
},
abortRequest: function () {},
},
PlatformConstants: {
getConstants() {
return {};
},
},
});
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);
jest.clearAllMocks();
});
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('');
jest.spyOn(console, 'warn').mockReturnValue(undefined);
// Setting responseType to an unsupported value has no effect.
xhr.responseType = 'arrayblobbuffertextfile';
expect(xhr.responseType).toBe('');
expect(console.warn).toBeCalledWith(
"The provided value 'arrayblobbuffertextfile' is not a valid 'responseType'.",
);
console.warn.mockRestore();
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-length: 32\r\n' + 'content-type: text/plain; charset=utf-8\r\n',
);
});
it('should log to GlobalPerformanceLogger if a custom performance logger is not set', () => {
xhr.open('GET', 'blabla');
xhr.send();
expect(GlobalPerformanceLogger.startTimespan).toHaveBeenCalledWith(
'network_XMLHttpRequest_blabla',
);
expect(GlobalPerformanceLogger.stopTimespan).not.toHaveBeenCalled();
setRequestId(8);
xhr.__didReceiveResponse(requestId, 200, {
'Content-Type': 'text/plain; charset=utf-8',
'Content-Length': '32',
});
expect(GlobalPerformanceLogger.stopTimespan).toHaveBeenCalledWith(
'network_XMLHttpRequest_blabla',
);
});
it('should log to a custom performance logger if set', () => {
const performanceLogger = createPerformanceLogger();
jest.spyOn(performanceLogger, 'startTimespan');
jest.spyOn(performanceLogger, 'stopTimespan');
xhr.setPerformanceLogger(performanceLogger);
xhr.open('GET', 'blabla');
xhr.send();
expect(performanceLogger.startTimespan).toHaveBeenCalledWith(
'network_XMLHttpRequest_blabla',
);
expect(GlobalPerformanceLogger.startTimespan).not.toHaveBeenCalled();
expect(performanceLogger.stopTimespan).not.toHaveBeenCalled();
setRequestId(9);
xhr.__didReceiveResponse(requestId, 200, {
'Content-Type': 'text/plain; charset=utf-8',
'Content-Length': '32',
});
expect(performanceLogger.stopTimespan).toHaveBeenCalledWith(
'network_XMLHttpRequest_blabla',
);
expect(GlobalPerformanceLogger.stopTimespan).not.toHaveBeenCalled();
});
it('should sort and lowercase response headers', function () {
// Derived from XHR Web Platform Test: https://github.com/web-platform-tests/wpt/blob/master/xhr/getallresponseheaders.htm
xhr.open('GET', 'blabla');
xhr.send();
setRequestId(10);
xhr.__didReceiveResponse(requestId, 200, {
'foo-TEST': '1',
'FOO-test': '2',
__Custom: 'token',
'ALSO-here': 'Mr. PB',
ewok: 'lego',
});
expect(xhr.getAllResponseHeaders()).toBe(
'also-here: Mr. PB\r\newok: lego\r\nfoo-test: 1, 2\r\n__custom: token\r\n',
);
});
});