mirror of
https://github.com/tenrok/axios.git
synced 2026-06-17 19:21:29 +03:00
847d89b436
* fix(buildURL): support URL object as input Fixes #6546 When passing a URL object (e.g., new URL(...)) to axios methods like axios.get(url, { params: {...} }), the buildURL function would crash with 'url.indexOf is not a function' because it assumed url was always a string. This fix converts URL objects to strings before processing. * fix: support URL object as config.url input - Move URL object coercion from buildURL to Axios._request so that all downstream consumers (buildFullPath, combineURLs, adapters) see a string. This fixes the crash when using URL object with baseURL (combineURLs calls .replace() on the URL object). - Remove the broken buildURL unit test that tested buildURL(url, null) without actually exercising URL coercion (buildURL early-returns when !params). - Add e2e tests via the HTTP adapter for URL object with params and URL object without params (no crash). * feat: note + example added under axios(url[, config]) documenting URL support * feat: url widened to string | URL * feat: oercion now uses config.url instanceof url * chore: add additional test cases to improve coverage * fix: apply suggestions from cubic review --------- Co-authored-by: liuwei53 <liuwei53@baidu.com> Co-authored-by: Jason Saayman <jasonsaayman@gmail.com>
208 lines
5.1 KiB
JavaScript
208 lines
5.1 KiB
JavaScript
import { describe, it, expect, vi } from 'vitest';
|
|
import buildURL, { encode } from '../../../lib/helpers/buildURL.js';
|
|
|
|
describe('helpers::buildURL', () => {
|
|
it('should support null params', () => {
|
|
expect(buildURL('/foo')).toEqual('/foo');
|
|
});
|
|
|
|
it('should support params', () => {
|
|
expect(
|
|
buildURL('/foo', {
|
|
foo: 'bar',
|
|
isUndefined: undefined,
|
|
isNull: null,
|
|
})
|
|
).toEqual('/foo?foo=bar');
|
|
});
|
|
|
|
it('should support sending raw params to custom serializer func', () => {
|
|
const serializer = vi.fn().mockReturnValue('foo=bar');
|
|
const params = { foo: 'bar' };
|
|
const options = {
|
|
serialize: serializer,
|
|
};
|
|
expect(
|
|
buildURL(
|
|
'/foo',
|
|
{
|
|
foo: 'bar',
|
|
},
|
|
options
|
|
)
|
|
).toEqual('/foo?foo=bar');
|
|
expect(serializer).toHaveBeenCalledTimes(1);
|
|
expect(serializer).toHaveBeenCalledWith(params, options);
|
|
});
|
|
|
|
it('should support object params', () => {
|
|
expect(
|
|
buildURL('/foo', {
|
|
foo: {
|
|
bar: 'baz',
|
|
},
|
|
})
|
|
).toEqual('/foo?foo%5Bbar%5D=baz');
|
|
});
|
|
|
|
it('should support date params', () => {
|
|
const date = new Date();
|
|
|
|
expect(
|
|
buildURL('/foo', {
|
|
date,
|
|
})
|
|
).toEqual('/foo?date=' + date.toISOString());
|
|
});
|
|
|
|
it('should support array params with encode', () => {
|
|
expect(
|
|
buildURL('/foo', {
|
|
foo: ['bar', 'baz'],
|
|
})
|
|
).toEqual('/foo?foo%5B%5D=bar&foo%5B%5D=baz');
|
|
});
|
|
|
|
it('should support special char params', () => {
|
|
expect(
|
|
buildURL('/foo', {
|
|
foo: ':$, ',
|
|
})
|
|
).toEqual('/foo?foo=:$,+');
|
|
});
|
|
|
|
it('should support existing params', () => {
|
|
expect(
|
|
buildURL('/foo?foo=bar', {
|
|
bar: 'baz',
|
|
})
|
|
).toEqual('/foo?foo=bar&bar=baz');
|
|
});
|
|
|
|
it('should support "length" parameter', () => {
|
|
expect(
|
|
buildURL('/foo', {
|
|
query: 'bar',
|
|
start: 0,
|
|
length: 5,
|
|
})
|
|
).toEqual('/foo?query=bar&start=0&length=5');
|
|
});
|
|
|
|
it('should correct discard url hash mark', () => {
|
|
expect(
|
|
buildURL('/foo?foo=bar#hash', {
|
|
query: 'baz',
|
|
})
|
|
).toEqual('/foo?foo=bar&query=baz');
|
|
});
|
|
|
|
it('should support URLSearchParams', () => {
|
|
expect(buildURL('/foo', new URLSearchParams('bar=baz'))).toEqual('/foo?bar=baz');
|
|
});
|
|
|
|
it('should support URL object without params', () => {
|
|
const url = new URL('http://example.com/foo?a=1');
|
|
expect(buildURL(url)).toEqual('http://example.com/foo?a=1');
|
|
});
|
|
|
|
it('should support URL object with params', () => {
|
|
const url = new URL('http://example.com/foo?a=1');
|
|
expect(buildURL(url, { b: 2 })).toEqual('http://example.com/foo?a=1&b=2');
|
|
});
|
|
|
|
it('should support URL-like object with params', () => {
|
|
const url = {
|
|
toString() {
|
|
return 'http://example.com/foo?a=1';
|
|
},
|
|
};
|
|
|
|
expect(buildURL(url, { b: 2 })).toEqual('http://example.com/foo?a=1&b=2');
|
|
});
|
|
|
|
it('should not require global URL to be a constructor', () => {
|
|
const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'URL');
|
|
const url = {
|
|
toString() {
|
|
return 'http://example.com/foo?a=1';
|
|
},
|
|
};
|
|
|
|
Object.defineProperty(globalThis, 'URL', {
|
|
configurable: true,
|
|
writable: true,
|
|
value: {},
|
|
});
|
|
|
|
try {
|
|
expect(buildURL(url, { b: 2 })).toEqual('http://example.com/foo?a=1&b=2');
|
|
} finally {
|
|
if (descriptor) {
|
|
Object.defineProperty(globalThis, 'URL', descriptor);
|
|
} else {
|
|
delete globalThis.URL;
|
|
}
|
|
}
|
|
});
|
|
|
|
it('should support custom serialize function', () => {
|
|
const params = {
|
|
x: 1,
|
|
};
|
|
|
|
const options = {
|
|
serialize: (thisParams, thisOptions) => {
|
|
expect(thisParams).toEqual(params);
|
|
expect(thisOptions).toEqual(options);
|
|
return 'rendered';
|
|
},
|
|
};
|
|
|
|
expect(buildURL('/foo', params, options)).toEqual('/foo?rendered');
|
|
|
|
const customSerializer = (thisParams) => {
|
|
expect(thisParams).toEqual(params);
|
|
return 'rendered';
|
|
};
|
|
|
|
expect(buildURL('/foo', params, customSerializer)).toEqual('/foo?rendered');
|
|
});
|
|
});
|
|
|
|
describe('helpers::encode', () => {
|
|
it('should be exported as a named export', () => {
|
|
expect(typeof encode).toBe('function');
|
|
});
|
|
|
|
it('should leave plain ASCII unchanged', () => {
|
|
expect(encode('foo')).toEqual('foo');
|
|
});
|
|
|
|
it('should preserve `:` rather than percent-encoding it', () => {
|
|
expect(encode(':')).toEqual(':');
|
|
});
|
|
|
|
it('should preserve `$` rather than percent-encoding it', () => {
|
|
expect(encode('$')).toEqual('$');
|
|
});
|
|
|
|
it('should preserve `,` rather than percent-encoding it', () => {
|
|
expect(encode(',')).toEqual(',');
|
|
});
|
|
|
|
it('should encode space as `+` (form-style) rather than `%20`', () => {
|
|
expect(encode(' ')).toEqual('+');
|
|
});
|
|
|
|
it('should still percent-encode characters outside the preserved set', () => {
|
|
expect(encode('a/b')).toEqual('a%2Fb');
|
|
expect(encode('a&b')).toEqual('a%26b');
|
|
expect(encode('a=b')).toEqual('a%3Db');
|
|
});
|
|
|
|
it('should apply all substitutions together', () => {
|
|
expect(encode('a:b$c,d e')).toEqual('a:b$c,d+e');
|
|
});
|
|
});
|