Skip to content

Instantly share code, notes, and snippets.

@satazor
Last active November 3, 2019 17:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save satazor/c473756fadbb54826ce6004f297c7121 to your computer and use it in GitHub Desktop.
Save satazor/c473756fadbb54826ce6004f297c7121 to your computer and use it in GitHub Desktop.
join-url
import queryString from 'query-string';
const defaultUrlRegExp = /^(\w+:\/\/[^/?]+)?(.*?)(\?.+)?$/;
const protocolRelativeUrlRegExp = /^(\/\/[^/?]+)(.*?)(\?.+)?$/;
const normalizeParts = (parts) => (
parts
// Filter non-string or non-numeric values
.filter((part) => typeof part === 'string' || typeof part === 'number')
// Convert to strings
.map((part) => `${part}`)
// Remove empty parts
.filter((part) => part)
);
const parseParts = (parts, options) => {
const { protocolRelative } = options;
const partsStr = parts.join('/');
const urlRegExp = protocolRelative ? protocolRelativeUrlRegExp : defaultUrlRegExp;
const [, prefix = '', pathname = '', suffix = ''] = partsStr.match(urlRegExp) || [];
return {
prefix,
pathname: {
parts: pathname.split('/').filter((part) => part !== ''),
hasLeading: suffix ? /^\/\/+/.test(pathname) : /^\/+/.test(pathname),
hasTrailing: suffix ? /\/\/+$/.test(pathname) : /\/+$/.test(pathname),
},
suffix,
};
};
const buildUrl = (parsedParts, options) => {
const { prefix, pathname, suffix } = parsedParts;
const { parts: pathnameParts, hasLeading, hasTrailing } = pathname;
const { leadingSlash, trailingSlash } = options;
const addLeading = leadingSlash === true || (leadingSlash === 'keep' && hasLeading);
const addTrailing = trailingSlash === true || (trailingSlash === 'keep' && hasTrailing);
// Start with prefix if not empty (http://google.com)
let url = prefix;
// Add the parts
if (pathnameParts.length > 0) {
url += url || addLeading ? '/' : '';
url += pathnameParts.join('/');
}
// Add trailing to the end
if (addTrailing) {
url += '/';
}
// Add leading if URL is still empty
if (!url && addLeading) {
url += '/';
}
// Build a query object based on the url query string and options query object
const query = { ...queryString.parse(suffix, options.queryOptions), ...options.query };
const queryStr = queryString.stringify(query, options.queryOptions);
if (queryStr) {
url += `?${queryStr}`;
}
return url;
};
const urlJoin = (...parts) => {
const lastArg = parts[parts.length - 1];
let options;
// If last argument is an object, then it's the options
// Note that null is an object, so we verify if is truthy
if (lastArg && typeof lastArg === 'object') {
options = lastArg;
parts = parts.slice(0, -1);
}
// Parse options
options = {
leadingSlash: true,
trailingSlash: false,
protocolRelative: false,
...options,
};
// Normalize parts before parsing them
parts = normalizeParts(parts);
// Split the parts into prefix, pathname, and suffix
// (scheme://host)(/pathnameParts.join('/'))(?queryString)
const parsedParts = parseParts(parts, options);
// Finaly build the url based on the parsedParts
return buildUrl(parsedParts, options);
};
export default urlJoin;
import urlJoin from '../src';
it('should add leading slash and no trailing slash by default', () => {
expect(urlJoin()).toBe('/');
expect(urlJoin(undefined, 'foo')).toBe('/foo');
expect(urlJoin('foo', null, 'bar')).toBe('/foo/bar');
expect(urlJoin('foo', '', 'bar')).toBe('/foo/bar');
expect(urlJoin('foo')).toBe('/foo');
expect(urlJoin('/foo')).toBe('/foo');
expect(urlJoin('/', '/foo')).toBe('/foo');
expect(urlJoin('/', '//foo')).toBe('/foo');
expect(urlJoin('/', '/foo//')).toBe('/foo');
expect(urlJoin('/', '/foo/', '')).toBe('/foo');
expect(urlJoin('/', '/foo/', '/')).toBe('/foo');
expect(urlJoin('foo', 'bar')).toBe('/foo/bar');
expect(urlJoin('/foo', 'bar')).toBe('/foo/bar');
expect(urlJoin('/foo', '/bar')).toBe('/foo/bar');
expect(urlJoin('/foo/', '/bar/')).toBe('/foo/bar');
expect(urlJoin('/foo/', '/bar/baz')).toBe('/foo/bar/baz');
expect(urlJoin('/foo/', '/bar//baz')).toBe('/foo/bar/baz');
expect(urlJoin('http://google.com')).toBe('http://google.com');
expect(urlJoin('http://google.com/')).toBe('http://google.com');
expect(urlJoin('http://google.com', '')).toBe('http://google.com');
expect(urlJoin('http://google.com', 'foo')).toBe('http://google.com/foo');
expect(urlJoin('http://google.com/', 'foo')).toBe('http://google.com/foo');
expect(urlJoin('http://google.com/', '/foo')).toBe('http://google.com/foo');
expect(urlJoin('http://google.com//', '/foo')).toBe('http://google.com/foo');
expect(urlJoin('http://google.com/foo', 'bar')).toBe('http://google.com/foo/bar');
expect(urlJoin('http://google.com', '?queryString')).toBe('http://google.com?queryString');
expect(urlJoin('http://google.com', 'foo?queryString')).toBe('http://google.com/foo?queryString');
expect(urlJoin('http://google.com', 'foo', '?queryString')).toBe('http://google.com/foo?queryString');
expect(urlJoin('http://google.com', 'foo/', '?queryString')).toBe('http://google.com/foo?queryString');
expect(urlJoin('http://google.com?queryString')).toBe('http://google.com?queryString');
});
it('should add leading slash and trailing slash', () => {
const options = { trailingSlash: true };
expect(urlJoin(options)).toBe('/');
expect(urlJoin(undefined, 'foo', options)).toBe('/foo/');
expect(urlJoin('foo', null, 'bar', options)).toBe('/foo/bar/');
expect(urlJoin('foo', '', 'bar', options)).toBe('/foo/bar/');
expect(urlJoin('foo', options)).toBe('/foo/');
expect(urlJoin('/foo', options)).toBe('/foo/');
expect(urlJoin('/', '/foo', options)).toBe('/foo/');
expect(urlJoin('/', '//foo', options)).toBe('/foo/');
expect(urlJoin('/', '/foo//', options)).toBe('/foo/');
expect(urlJoin('/', '/foo/', '', options)).toBe('/foo/');
expect(urlJoin('/', '/foo/', '/', options)).toBe('/foo/');
expect(urlJoin('foo', 'bar', options)).toBe('/foo/bar/');
expect(urlJoin('/foo', 'bar', options)).toBe('/foo/bar/');
expect(urlJoin('/foo', '/bar', options)).toBe('/foo/bar/');
expect(urlJoin('/foo/', '/bar/', options)).toBe('/foo/bar/');
expect(urlJoin('/foo/', '/bar/baz', options)).toBe('/foo/bar/baz/');
expect(urlJoin('/foo/', '/bar//baz', options)).toBe('/foo/bar/baz/');
expect(urlJoin('http://google.com', options)).toBe('http://google.com/');
expect(urlJoin('http://google.com/', options)).toBe('http://google.com/');
expect(urlJoin('http://google.com', '', options)).toBe('http://google.com/');
expect(urlJoin('http://google.com', 'foo', options)).toBe('http://google.com/foo/');
expect(urlJoin('http://google.com/', 'foo', options)).toBe('http://google.com/foo/');
expect(urlJoin('http://google.com/', '/foo', options)).toBe('http://google.com/foo/');
expect(urlJoin('http://google.com//', '/foo', options)).toBe('http://google.com/foo/');
expect(urlJoin('http://google.com/foo', 'bar', options)).toBe('http://google.com/foo/bar/');
expect(urlJoin('http://google.com', '?queryString', options)).toBe('http://google.com/?queryString');
expect(urlJoin('http://google.com', 'foo?queryString', options)).toBe('http://google.com/foo/?queryString');
expect(urlJoin('http://google.com', 'foo', '?queryString', options)).toBe('http://google.com/foo/?queryString');
expect(urlJoin('http://google.com', 'foo/', '?queryString', options)).toBe('http://google.com/foo/?queryString');
expect(urlJoin('http://google.com?queryString', options)).toBe('http://google.com/?queryString');
});
it('should remove leading slash and add trailing slash', () => {
const options = { leadingSlash: false, trailingSlash: true };
expect(urlJoin(options)).toBe('/');
expect(urlJoin(undefined, 'foo', options)).toBe('foo/');
expect(urlJoin('foo', null, 'bar', options)).toBe('foo/bar/');
expect(urlJoin('foo', '', 'bar', options)).toBe('foo/bar/');
expect(urlJoin('foo', options)).toBe('foo/');
expect(urlJoin('/foo', options)).toBe('foo/');
expect(urlJoin('/', '/foo', options)).toBe('foo/');
expect(urlJoin('/', '//foo', options)).toBe('foo/');
expect(urlJoin('/', '/foo//', options)).toBe('foo/');
expect(urlJoin('/', '/foo/', '', options)).toBe('foo/');
expect(urlJoin('/', '/foo/', '/', options)).toBe('foo/');
expect(urlJoin('foo', 'bar', options)).toBe('foo/bar/');
expect(urlJoin('/foo', 'bar', options)).toBe('foo/bar/');
expect(urlJoin('/foo', '/bar', options)).toBe('foo/bar/');
expect(urlJoin('/foo/', '/bar/', options)).toBe('foo/bar/');
expect(urlJoin('/foo/', '/bar/baz', options)).toBe('foo/bar/baz/');
expect(urlJoin('/foo/', '/bar//baz', options)).toBe('foo/bar/baz/');
expect(urlJoin('http://google.com', options)).toBe('http://google.com/');
expect(urlJoin('http://google.com/', options)).toBe('http://google.com/');
expect(urlJoin('http://google.com', '', options)).toBe('http://google.com/');
expect(urlJoin('http://google.com', 'foo', options)).toBe('http://google.com/foo/');
expect(urlJoin('http://google.com/', 'foo', options)).toBe('http://google.com/foo/');
expect(urlJoin('http://google.com/', '/foo', options)).toBe('http://google.com/foo/');
expect(urlJoin('http://google.com//', '/foo', options)).toBe('http://google.com/foo/');
expect(urlJoin('http://google.com/foo', 'bar', options)).toBe('http://google.com/foo/bar/');
expect(urlJoin('http://google.com', '?queryString', options)).toBe('http://google.com/?queryString');
expect(urlJoin('http://google.com', 'foo?queryString', options)).toBe('http://google.com/foo/?queryString');
expect(urlJoin('http://google.com', 'foo', '?queryString', options)).toBe('http://google.com/foo/?queryString');
expect(urlJoin('http://google.com', 'foo/', '?queryString', options)).toBe('http://google.com/foo/?queryString');
expect(urlJoin('http://google.com?queryString', options)).toBe('http://google.com/?queryString');
});
it('should remove leading slash and trailing slash', () => {
const options = { leadingSlash: false, trailingSlash: false };
expect(urlJoin(options)).toBe('');
expect(urlJoin(undefined, 'foo', options)).toBe('foo');
expect(urlJoin('foo', null, 'bar', options)).toBe('foo/bar');
expect(urlJoin('foo', '', 'bar', options)).toBe('foo/bar');
expect(urlJoin('foo', options)).toBe('foo');
expect(urlJoin('/foo', options)).toBe('foo');
expect(urlJoin('/', '/foo', options)).toBe('foo');
expect(urlJoin('/', '//foo', options)).toBe('foo');
expect(urlJoin('/', '/foo//', options)).toBe('foo');
expect(urlJoin('/', '/foo/', '', options)).toBe('foo');
expect(urlJoin('/', '/foo/', '/', options)).toBe('foo');
expect(urlJoin('foo', 'bar', options)).toBe('foo/bar');
expect(urlJoin('/foo', 'bar', options)).toBe('foo/bar');
expect(urlJoin('/foo', '/bar', options)).toBe('foo/bar');
expect(urlJoin('/foo/', '/bar/', options)).toBe('foo/bar');
expect(urlJoin('/foo/', '/bar/baz', options)).toBe('foo/bar/baz');
expect(urlJoin('/foo/', '/bar//baz', options)).toBe('foo/bar/baz');
expect(urlJoin('http://google.com', options)).toBe('http://google.com');
expect(urlJoin('http://google.com/', options)).toBe('http://google.com');
expect(urlJoin('http://google.com', '', options)).toBe('http://google.com');
expect(urlJoin('http://google.com', 'foo', options)).toBe('http://google.com/foo');
expect(urlJoin('http://google.com/', 'foo', options)).toBe('http://google.com/foo');
expect(urlJoin('http://google.com/', '/foo', options)).toBe('http://google.com/foo');
expect(urlJoin('http://google.com//', '/foo', options)).toBe('http://google.com/foo');
expect(urlJoin('http://google.com/foo', 'bar', options)).toBe('http://google.com/foo/bar');
expect(urlJoin('http://google.com', '?queryString', options)).toBe('http://google.com?queryString');
expect(urlJoin('http://google.com', 'foo?queryString', options)).toBe('http://google.com/foo?queryString');
expect(urlJoin('http://google.com', 'foo', '?queryString', options)).toBe('http://google.com/foo?queryString');
expect(urlJoin('http://google.com', 'foo/', '?queryString', options)).toBe('http://google.com/foo?queryString');
expect(urlJoin('http://google.com?queryString', options)).toBe('http://google.com?queryString');
});
it('should support URLs with relative protocol according to options.protocolRelative', () => {
const options = { protocolRelative: true };
expect(urlJoin('//google.com', 'foo', options)).toBe('//google.com/foo');
expect(urlJoin('//google.com/', 'foo', options)).toBe('//google.com/foo');
expect(urlJoin('//google.com/foo', 'bar', options)).toBe('//google.com/foo/bar');
expect(urlJoin('//google.com/foo//', 'bar', options)).toBe('//google.com/foo/bar');
options.protocolRelative = false;
expect(urlJoin('//google.com', 'foo', options)).toBe('/google.com/foo');
expect(urlJoin('//google.com/', 'foo', options)).toBe('/google.com/foo');
expect(urlJoin('//google.com/foo', 'bar', options)).toBe('/google.com/foo/bar');
expect(urlJoin('//google.com/foo//', 'bar', options)).toBe('/google.com/foo/bar');
});
it('should include numbers', () => {
expect(urlJoin(undefined, 1)).toBe('/1');
expect(urlJoin(1, null, 2)).toBe('/1/2');
expect(urlJoin(1, '', 2)).toBe('/1/2');
expect(urlJoin(1)).toBe('/1');
expect(urlJoin('/1')).toBe('/1');
expect(urlJoin('/', '/1')).toBe('/1');
expect(urlJoin('/', '//1')).toBe('/1');
expect(urlJoin('/', '/1//')).toBe('/1');
expect(urlJoin('/', '/1/', '')).toBe('/1');
expect(urlJoin('/', '/1/', '/')).toBe('/1');
expect(urlJoin(1, 2)).toBe('/1/2');
expect(urlJoin('/1', 2)).toBe('/1/2');
expect(urlJoin('/1', '/2')).toBe('/1/2');
expect(urlJoin('/1/', '/2/')).toBe('/1/2');
expect(urlJoin('/1/', '/2/3')).toBe('/1/2/3');
expect(urlJoin('/1/', '/2//3')).toBe('/1/2/3');
expect(urlJoin('http://google.com', 1)).toBe('http://google.com/1');
expect(urlJoin('http://google.com/', 1)).toBe('http://google.com/1');
expect(urlJoin('http://google.com/', '/1')).toBe('http://google.com/1');
expect(urlJoin('http://google.com//', '/1')).toBe('http://google.com/1');
expect(urlJoin('http://google.com/1', 2)).toBe('http://google.com/1/2');
expect(urlJoin('http://google.com', '?1')).toBe('http://google.com?1');
expect(urlJoin('http://google.com', 'foo?1')).toBe('http://google.com/foo?1');
expect(urlJoin('http://google.com', 'foo', '?1')).toBe('http://google.com/foo?1');
expect(urlJoin('http://google.com', 'foo/', '?1')).toBe('http://google.com/foo?1');
expect(urlJoin('http://google.com?1')).toBe('http://google.com?1');
});
it('should handle the provided query object and append it to the url', () => {
const options = { query: { biz: 'buz', foo: 'bar' } };
expect(urlJoin('/google.com', options)).toBe('/google.com?biz=buz&foo=bar');
expect(urlJoin('google.com', options)).toBe('/google.com?biz=buz&foo=bar');
options.protocolRelative = false;
expect(urlJoin('//google.com', options)).toBe('/google.com?biz=buz&foo=bar');
options.leadingSlash = false;
expect(urlJoin('google.com', options)).toBe('google.com?biz=buz&foo=bar');
options.trailingSlash = true;
expect(urlJoin('google.com', options)).toBe('google.com/?biz=buz&foo=bar');
options.trailingSlash = false;
expect(urlJoin('google.com', 'qux?tux=baz', options)).toBe('google.com/qux?biz=buz&foo=bar&tux=baz');
});
it('should handle the provided query and query options objects', () => {
const options = { query: { foo: [1, 2, 3] }, queryOptions: {} };
expect(urlJoin('/google.com', options)).toBe('/google.com?foo=1&foo=2&foo=3');
options.queryOptions.arrayFormat = 'bracket';
expect(urlJoin('/google.com', options)).toBe('/google.com?foo[]=1&foo[]=2&foo[]=3');
options.queryOptions.arrayFormat = 'index';
expect(urlJoin('/google.com', options)).toBe('/google.com?foo[0]=1&foo[1]=2&foo[2]=3');
});
it('should keep leading slash and remove trailing slash', () => {
const options = { leadingSlash: 'keep' };
expect(urlJoin(options)).toBe('');
expect(urlJoin(undefined, 'foo', options)).toBe('foo');
expect(urlJoin('foo', null, 'bar', options)).toBe('foo/bar');
expect(urlJoin('foo', '', 'bar', options)).toBe('foo/bar');
expect(urlJoin('foo', options)).toBe('foo');
expect(urlJoin('/foo', options)).toBe('/foo');
expect(urlJoin('/', '/foo', options)).toBe('/foo');
expect(urlJoin('/', '//foo', options)).toBe('/foo');
expect(urlJoin('/', '/foo//', options)).toBe('/foo');
expect(urlJoin('/', '/foo/', '', options)).toBe('/foo');
expect(urlJoin('/', '/foo/', '/', options)).toBe('/foo');
expect(urlJoin('foo', 'bar', options)).toBe('foo/bar');
expect(urlJoin('/foo', 'bar', options)).toBe('/foo/bar');
expect(urlJoin('/foo', '/bar', options)).toBe('/foo/bar');
expect(urlJoin('/foo/', '/bar/', options)).toBe('/foo/bar');
expect(urlJoin('/foo/', '/bar/baz', options)).toBe('/foo/bar/baz');
expect(urlJoin('/foo/', '/bar//baz', options)).toBe('/foo/bar/baz');
expect(urlJoin('http://google.com', options)).toBe('http://google.com');
expect(urlJoin('http://google.com/', options)).toBe('http://google.com');
expect(urlJoin('http://google.com', '', options)).toBe('http://google.com');
expect(urlJoin('http://google.com', 'foo', options)).toBe('http://google.com/foo');
expect(urlJoin('http://google.com/', 'foo', options)).toBe('http://google.com/foo');
expect(urlJoin('http://google.com/', '/foo', options)).toBe('http://google.com/foo');
expect(urlJoin('http://google.com//', '/foo', options)).toBe('http://google.com/foo');
expect(urlJoin('http://google.com/foo', 'bar', options)).toBe('http://google.com/foo/bar');
expect(urlJoin('http://google.com', '?queryString', options)).toBe('http://google.com?queryString');
expect(urlJoin('http://google.com', 'foo?queryString', options)).toBe('http://google.com/foo?queryString');
expect(urlJoin('http://google.com', 'foo', '?queryString', options)).toBe('http://google.com/foo?queryString');
expect(urlJoin('http://google.com', 'foo/', '?queryString', options)).toBe('http://google.com/foo?queryString');
});
it('should add leading slash and keep trailing slash', () => {
const options = { trailingSlash: 'keep' };
expect(urlJoin(options)).toBe('/');
expect(urlJoin(undefined, 'foo', options)).toBe('/foo');
expect(urlJoin('foo', null, 'bar', options)).toBe('/foo/bar');
expect(urlJoin('foo', '', 'bar', options)).toBe('/foo/bar');
expect(urlJoin('foo', options)).toBe('/foo');
expect(urlJoin('/foo', options)).toBe('/foo');
expect(urlJoin('/', '/foo', options)).toBe('/foo');
expect(urlJoin('/', '//foo', options)).toBe('/foo');
expect(urlJoin('/', '/foo//', options)).toBe('/foo/');
expect(urlJoin('/', '/foo/', '', options)).toBe('/foo/');
expect(urlJoin('/', '/foo/', '/', options)).toBe('/foo/');
expect(urlJoin('foo', 'bar', options)).toBe('/foo/bar');
expect(urlJoin('/foo', 'bar', options)).toBe('/foo/bar');
expect(urlJoin('/foo', '/bar', options)).toBe('/foo/bar');
expect(urlJoin('/foo/', '/bar/', options)).toBe('/foo/bar/');
expect(urlJoin('/foo/', '/bar/baz', options)).toBe('/foo/bar/baz');
expect(urlJoin('/foo/', '/bar//baz', options)).toBe('/foo/bar/baz');
expect(urlJoin('http://google.com', options)).toBe('http://google.com');
expect(urlJoin('http://google.com/', options)).toBe('http://google.com/');
expect(urlJoin('http://google.com', '', options)).toBe('http://google.com');
expect(urlJoin('http://google.com', 'foo', options)).toBe('http://google.com/foo');
expect(urlJoin('http://google.com/', 'foo', options)).toBe('http://google.com/foo');
expect(urlJoin('http://google.com/', '/foo', options)).toBe('http://google.com/foo');
expect(urlJoin('http://google.com//', '/foo', options)).toBe('http://google.com/foo');
expect(urlJoin('http://google.com/foo', 'bar', options)).toBe('http://google.com/foo/bar');
expect(urlJoin('http://google.com', '?queryString', options)).toBe('http://google.com?queryString');
expect(urlJoin('http://google.com', 'foo?queryString', options)).toBe('http://google.com/foo?queryString');
expect(urlJoin('http://google.com', 'foo', '?queryString', options)).toBe('http://google.com/foo?queryString');
expect(urlJoin('http://google.com', 'foo/', '?queryString', options)).toBe('http://google.com/foo/?queryString');
});
it('should keep leading slash and add trailing slash', () => {
const options = { leadingSlash: 'keep', trailingSlash: true };
expect(urlJoin(options)).toBe('/');
expect(urlJoin(undefined, 'foo', options)).toBe('foo/');
expect(urlJoin('foo', null, 'bar', options)).toBe('foo/bar/');
expect(urlJoin('foo', '', 'bar', options)).toBe('foo/bar/');
expect(urlJoin('foo', options)).toBe('foo/');
expect(urlJoin('/foo', options)).toBe('/foo/');
expect(urlJoin('/', '/foo', options)).toBe('/foo/');
expect(urlJoin('/', '//foo', options)).toBe('/foo/');
expect(urlJoin('/', '/foo//', options)).toBe('/foo/');
expect(urlJoin('/', '/foo/', '', options)).toBe('/foo/');
expect(urlJoin('/', '/foo/', '/', options)).toBe('/foo/');
expect(urlJoin('foo', 'bar', options)).toBe('foo/bar/');
expect(urlJoin('/foo', 'bar', options)).toBe('/foo/bar/');
expect(urlJoin('/foo', '/bar', options)).toBe('/foo/bar/');
expect(urlJoin('/foo/', '/bar/', options)).toBe('/foo/bar/');
expect(urlJoin('/foo/', '/bar/baz', options)).toBe('/foo/bar/baz/');
expect(urlJoin('/foo/', '/bar//baz', options)).toBe('/foo/bar/baz/');
expect(urlJoin('http://google.com', options)).toBe('http://google.com/');
expect(urlJoin('http://google.com/', options)).toBe('http://google.com/');
expect(urlJoin('http://google.com', '', options)).toBe('http://google.com/');
expect(urlJoin('http://google.com', 'foo', options)).toBe('http://google.com/foo/');
expect(urlJoin('http://google.com/', 'foo', options)).toBe('http://google.com/foo/');
expect(urlJoin('http://google.com/', '/foo', options)).toBe('http://google.com/foo/');
expect(urlJoin('http://google.com//', '/foo', options)).toBe('http://google.com/foo/');
expect(urlJoin('http://google.com/foo', 'bar', options)).toBe('http://google.com/foo/bar/');
expect(urlJoin('http://google.com', '?queryString', options)).toBe('http://google.com/?queryString');
expect(urlJoin('http://google.com', 'foo?queryString', options)).toBe('http://google.com/foo/?queryString');
expect(urlJoin('http://google.com', 'foo', '?queryString', options)).toBe('http://google.com/foo/?queryString');
expect(urlJoin('http://google.com', 'foo/', '?queryString', options)).toBe('http://google.com/foo/?queryString');
expect(urlJoin('http://google.com?queryString', options)).toBe('http://google.com/?queryString');
});
it('should remove leading slash and keep trailing slash', () => {
const options = { leadingSlash: false, trailingSlash: 'keep' };
expect(urlJoin(options)).toBe('');
expect(urlJoin(undefined, 'foo', options)).toBe('foo');
expect(urlJoin('foo', null, 'bar', options)).toBe('foo/bar');
expect(urlJoin('foo', '', 'bar', options)).toBe('foo/bar');
expect(urlJoin('foo', options)).toBe('foo');
expect(urlJoin('/foo', options)).toBe('foo');
expect(urlJoin('/', '/foo', options)).toBe('foo');
expect(urlJoin('/', '//foo', options)).toBe('foo');
expect(urlJoin('/', '/foo//', options)).toBe('foo/');
expect(urlJoin('/', '/foo/', '', options)).toBe('foo/');
expect(urlJoin('/', '/foo/', '/', options)).toBe('foo/');
expect(urlJoin('foo', 'bar', options)).toBe('foo/bar');
expect(urlJoin('/foo', 'bar', options)).toBe('foo/bar');
expect(urlJoin('/foo', '/bar', options)).toBe('foo/bar');
expect(urlJoin('/foo/', '/bar/', options)).toBe('foo/bar/');
expect(urlJoin('/foo/', '/bar/baz', options)).toBe('foo/bar/baz');
expect(urlJoin('/foo/', '/bar//baz', options)).toBe('foo/bar/baz');
expect(urlJoin('http://google.com', options)).toBe('http://google.com');
expect(urlJoin('http://google.com/', options)).toBe('http://google.com/');
expect(urlJoin('http://google.com', '', options)).toBe('http://google.com');
expect(urlJoin('http://google.com', 'foo', options)).toBe('http://google.com/foo');
expect(urlJoin('http://google.com/', 'foo', options)).toBe('http://google.com/foo');
expect(urlJoin('http://google.com/', '/foo', options)).toBe('http://google.com/foo');
expect(urlJoin('http://google.com//', '/foo', options)).toBe('http://google.com/foo');
expect(urlJoin('http://google.com/foo', 'bar', options)).toBe('http://google.com/foo/bar');
expect(urlJoin('http://google.com', '?queryString', options)).toBe('http://google.com?queryString');
expect(urlJoin('http://google.com', 'foo?queryString', options)).toBe('http://google.com/foo?queryString');
expect(urlJoin('http://google.com', 'foo', '?queryString', options)).toBe('http://google.com/foo?queryString');
expect(urlJoin('http://google.com', 'foo/', '?queryString', options)).toBe('http://google.com/foo/?queryString');
expect(urlJoin('http://google.com?queryString', options)).toBe('http://google.com?queryString');
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment