mirror of
https://github.com/axios/axios.git
synced 2026-04-11 02:11:50 +08:00
* chore: port karma tests * chore: port karma tests * chore: port karma tests * chore: tests * chore: tests * chore: tests * chore: fix issues with port collisions * refactor: utils tests * refactor: utils tests * refactor: utils tests * refactor: tests to vitests * refactor: tests to vitests * refactor: tests to vitests * refactor: tests to vitests * refactor: tests to vitests * refactor: tests to vitests * refactor: tests to vitests * refactor: ci * chore: install pw deps * chore: fixx ai feedback * chore: wip compatability tests * chore: wip compatability tests * chore: wip compatability tests * refactor: wip smoke * chore: smoke test run * chore: update unzip * chore: update testing * chore: update testing * chore: update testing * chore: update testing * chore: update testing * chore: skip tests that cannot run on node 16 and lower * chore: fix 16x under tests * chore: rest of tests * fix: functions and runs * feat: added tests for esm smoke * feat: added smoke * chore: ignore ai gen plans * chore: ci fixes * chore: fix small p2s
283 lines
7.8 KiB
JavaScript
283 lines
7.8 KiB
JavaScript
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
|
|
import axios from '../../index.js';
|
|
import defaults from '../../lib/defaults/index.js';
|
|
import AxiosHeaders from '../../lib/core/AxiosHeaders.js';
|
|
|
|
class MockXMLHttpRequest {
|
|
constructor() {
|
|
this.requestHeaders = {};
|
|
this.responseHeaders = '';
|
|
this.readyState = 0;
|
|
this.status = 0;
|
|
this.statusText = '';
|
|
this.responseText = '';
|
|
this.response = null;
|
|
this.onreadystatechange = null;
|
|
this.onloadend = null;
|
|
this.upload = {
|
|
addEventListener() {},
|
|
};
|
|
}
|
|
|
|
open(method, url, async = true) {
|
|
this.method = method;
|
|
this.url = url;
|
|
this.async = async;
|
|
}
|
|
|
|
setRequestHeader(key, value) {
|
|
this.requestHeaders[key] = value;
|
|
}
|
|
|
|
addEventListener() {}
|
|
|
|
getAllResponseHeaders() {
|
|
return this.responseHeaders;
|
|
}
|
|
|
|
send(data) {
|
|
this.params = data;
|
|
requests.push(this);
|
|
}
|
|
|
|
respondWith({ status = 200, statusText = 'OK', responseText = '', responseHeaders = '' } = {}) {
|
|
this.status = status;
|
|
this.statusText = statusText;
|
|
this.responseText = responseText;
|
|
this.response = responseText;
|
|
this.responseHeaders = responseHeaders;
|
|
this.readyState = 4;
|
|
|
|
queueMicrotask(() => {
|
|
if (this.onloadend) {
|
|
this.onloadend();
|
|
} else if (this.onreadystatechange) {
|
|
this.onreadystatechange();
|
|
}
|
|
});
|
|
}
|
|
|
|
abort() {}
|
|
}
|
|
|
|
const XSRF_COOKIE_NAME = 'CUSTOM-XSRF-TOKEN';
|
|
|
|
let requests = [];
|
|
let OriginalXMLHttpRequest;
|
|
|
|
const getLastRequest = () => {
|
|
const request = requests.at(-1);
|
|
|
|
expect(request).toBeDefined();
|
|
|
|
return request;
|
|
};
|
|
|
|
const finishRequest = async (request, promise) => {
|
|
request.respondWith({ status: 200 });
|
|
await promise;
|
|
};
|
|
|
|
describe('defaults (vitest browser)', () => {
|
|
beforeEach(() => {
|
|
requests = [];
|
|
OriginalXMLHttpRequest = window.XMLHttpRequest;
|
|
window.XMLHttpRequest = MockXMLHttpRequest;
|
|
});
|
|
|
|
afterEach(() => {
|
|
window.XMLHttpRequest = OriginalXMLHttpRequest;
|
|
delete axios.defaults.baseURL;
|
|
delete axios.defaults.headers.get['X-CUSTOM-HEADER'];
|
|
delete axios.defaults.headers.post['X-CUSTOM-HEADER'];
|
|
document.cookie = `${XSRF_COOKIE_NAME}=;expires=${new Date(Date.now() - 86400000).toUTCString()}`;
|
|
});
|
|
|
|
it('should transform request json', () => {
|
|
expect(defaults.transformRequest[0]({ foo: 'bar' }, new AxiosHeaders())).toBe('{"foo":"bar"}');
|
|
});
|
|
|
|
it("should also transform request json when 'Content-Type' is 'application/json'", () => {
|
|
const headers = new AxiosHeaders({
|
|
'Content-Type': 'application/json',
|
|
});
|
|
|
|
expect(defaults.transformRequest[0](JSON.stringify({ foo: 'bar' }), headers)).toBe('{"foo":"bar"}');
|
|
expect(defaults.transformRequest[0]([42, 43], headers)).toBe('[42,43]');
|
|
expect(defaults.transformRequest[0]('foo', headers)).toBe('"foo"');
|
|
expect(defaults.transformRequest[0](42, headers)).toBe('42');
|
|
expect(defaults.transformRequest[0](true, headers)).toBe('true');
|
|
expect(defaults.transformRequest[0](false, headers)).toBe('false');
|
|
expect(defaults.transformRequest[0](null, headers)).toBe('null');
|
|
});
|
|
|
|
it("should transform the plain data object to a FormData instance when header is 'multipart/form-data'", () => {
|
|
const headers = new AxiosHeaders({
|
|
'Content-Type': 'multipart/form-data',
|
|
});
|
|
|
|
const transformed = defaults.transformRequest[0]({ x: 1 }, headers);
|
|
|
|
expect(transformed).toBeInstanceOf(FormData);
|
|
});
|
|
|
|
it('should do nothing to request string', () => {
|
|
expect(defaults.transformRequest[0]('foo=bar', new AxiosHeaders())).toBe('foo=bar');
|
|
});
|
|
|
|
it('should transform response json', () => {
|
|
const data = defaults.transformResponse[0].call(defaults, '{"foo":"bar"}');
|
|
|
|
expect(typeof data).toBe('object');
|
|
expect(data.foo).toBe('bar');
|
|
});
|
|
|
|
it('should do nothing to response string', () => {
|
|
expect(defaults.transformResponse[0]('foo=bar')).toBe('foo=bar');
|
|
});
|
|
|
|
it('should use global defaults config', async () => {
|
|
const promise = axios('/foo');
|
|
const request = getLastRequest();
|
|
|
|
expect(request.url).toBe('/foo');
|
|
|
|
await finishRequest(request, promise);
|
|
});
|
|
|
|
it('should use modified defaults config', async () => {
|
|
axios.defaults.baseURL = 'http://example.com/';
|
|
|
|
const promise = axios('/foo');
|
|
const request = getLastRequest();
|
|
|
|
expect(request.url).toBe('http://example.com/foo');
|
|
|
|
await finishRequest(request, promise);
|
|
});
|
|
|
|
it('should use request config', async () => {
|
|
const promise = axios('/foo', {
|
|
baseURL: 'http://www.example.com',
|
|
});
|
|
const request = getLastRequest();
|
|
|
|
expect(request.url).toBe('http://www.example.com/foo');
|
|
|
|
await finishRequest(request, promise);
|
|
});
|
|
|
|
it('should use default config for custom instance', async () => {
|
|
const instance = axios.create({
|
|
xsrfCookieName: XSRF_COOKIE_NAME,
|
|
xsrfHeaderName: 'X-CUSTOM-XSRF-TOKEN',
|
|
});
|
|
document.cookie = `${instance.defaults.xsrfCookieName}=foobarbaz`;
|
|
|
|
const promise = instance.get('/foo');
|
|
const request = getLastRequest();
|
|
|
|
expect(request.requestHeaders[instance.defaults.xsrfHeaderName]).toBe('foobarbaz');
|
|
|
|
await finishRequest(request, promise);
|
|
});
|
|
|
|
it('should use GET headers', async () => {
|
|
axios.defaults.headers.get['X-CUSTOM-HEADER'] = 'foo';
|
|
|
|
const promise = axios.get('/foo');
|
|
const request = getLastRequest();
|
|
|
|
expect(request.requestHeaders['X-CUSTOM-HEADER']).toBe('foo');
|
|
|
|
await finishRequest(request, promise);
|
|
});
|
|
|
|
it('should use POST headers', async () => {
|
|
axios.defaults.headers.post['X-CUSTOM-HEADER'] = 'foo';
|
|
|
|
const promise = axios.post('/foo', {});
|
|
const request = getLastRequest();
|
|
|
|
expect(request.requestHeaders['X-CUSTOM-HEADER']).toBe('foo');
|
|
|
|
await finishRequest(request, promise);
|
|
});
|
|
|
|
it('should use header config', async () => {
|
|
const instance = axios.create({
|
|
headers: {
|
|
common: {
|
|
'X-COMMON-HEADER': 'commonHeaderValue',
|
|
},
|
|
get: {
|
|
'X-GET-HEADER': 'getHeaderValue',
|
|
},
|
|
post: {
|
|
'X-POST-HEADER': 'postHeaderValue',
|
|
},
|
|
},
|
|
});
|
|
|
|
const promise = instance.get('/foo', {
|
|
headers: {
|
|
'X-FOO-HEADER': 'fooHeaderValue',
|
|
'X-BAR-HEADER': 'barHeaderValue',
|
|
},
|
|
});
|
|
const request = getLastRequest();
|
|
|
|
expect(request.requestHeaders).toEqual(
|
|
AxiosHeaders.concat(defaults.headers.common, defaults.headers.get, {
|
|
'X-COMMON-HEADER': 'commonHeaderValue',
|
|
'X-GET-HEADER': 'getHeaderValue',
|
|
'X-FOO-HEADER': 'fooHeaderValue',
|
|
'X-BAR-HEADER': 'barHeaderValue',
|
|
}).toJSON()
|
|
);
|
|
|
|
await finishRequest(request, promise);
|
|
});
|
|
|
|
it('should be used by custom instance if set before instance created', async () => {
|
|
axios.defaults.baseURL = 'http://example.org/';
|
|
const instance = axios.create();
|
|
|
|
const promise = instance.get('/foo');
|
|
const request = getLastRequest();
|
|
|
|
expect(request.url).toBe('http://example.org/foo');
|
|
|
|
await finishRequest(request, promise);
|
|
});
|
|
|
|
it('should not be used by custom instance if set after instance created', async () => {
|
|
const instance = axios.create();
|
|
axios.defaults.baseURL = 'http://example.org/';
|
|
|
|
const promise = instance.get('/foo/users');
|
|
const request = getLastRequest();
|
|
|
|
expect(request.url).toBe('/foo/users');
|
|
|
|
await finishRequest(request, promise);
|
|
});
|
|
|
|
it('should resistant to ReDoS attack', async () => {
|
|
const instance = axios.create();
|
|
const start = performance.now();
|
|
const slashes = '/'.repeat(100000);
|
|
instance.defaults.baseURL = `/${slashes}bar/`;
|
|
|
|
const promise = instance.get('/foo');
|
|
const request = getLastRequest();
|
|
const elapsedTimeMs = performance.now() - start;
|
|
|
|
expect(elapsedTimeMs).toBeLessThan(20);
|
|
expect(request.url).toBe(`/${slashes}bar/foo`);
|
|
|
|
await finishRequest(request, promise);
|
|
});
|
|
});
|