Commit a24f1a89 authored by Peter Hegman's avatar Peter Hegman

Merge branch 'migrate-url-js-utilities' into 'master'

Migrate `parseUrlPathname` to `url_util.js`

See merge request gitlab-org/gitlab!82834
parents fde98c13 1cb50a4d
......@@ -130,19 +130,6 @@ export const isInViewport = (el, offset = {}) => {
);
};
export const parseUrl = (url) => {
const parser = document.createElement('a');
parser.href = url;
return parser;
};
export const parseUrlPathname = (url) => {
const parsedUrl = parseUrl(url);
// parsedUrl.pathname will return an absolute path for Firefox and a relative path for IE11
// We have to make sure we always have an absolute path.
return parsedUrl.pathname.charAt(0) === '/' ? parsedUrl.pathname : `/${parsedUrl.pathname}`;
};
export const isMetaKey = (e) => e.metaKey || e.ctrlKey || e.altKey || e.shiftKey;
// Identify following special clicks
......
......@@ -18,6 +18,20 @@ function resetRegExp(regex) {
return regex;
}
/**
* Returns the absolute pathname for a relative or absolute URL string.
*
* A few examples of inputs and outputs:
* 1) 'http://a.com/b/c/d' => '/b/c/d'
* 2) '/b/c/d' => '/b/c/d'
* 3) 'b/c/d' => '/b/c/d' or '[path]/b/c/d' depending of the current path of the
* document.location
*/
export const parseUrlPathname = (url) => {
const { pathname } = new URL(url, document.location.href);
return pathname;
};
// Returns a decoded url parameter value
// - Treats '+' as '%20'
function decodeUrlParameter(val) {
......
......@@ -2,13 +2,8 @@
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import $ from 'jquery';
import Vue from 'vue';
import {
getCookie,
parseUrlPathname,
isMetaClick,
parseBoolean,
scrollToElement,
} from '~/lib/utils/common_utils';
import { getCookie, isMetaClick, parseBoolean, scrollToElement } from '~/lib/utils/common_utils';
import { parseUrlPathname } from '~/lib/utils/url_utility';
import createEventHub from '~/helpers/event_hub_factory';
import BlobForkSuggestion from './blob/blob_fork_suggestion';
import Diff from './diff';
......
......@@ -51,31 +51,6 @@ describe('common_utils', () => {
});
});
describe('parseUrl', () => {
it('returns an anchor tag with url', () => {
expect(commonUtils.parseUrl('/some/absolute/url').pathname).toContain('some/absolute/url');
});
it('url is escaped', () => {
// IE11 will return a relative pathname while other browsers will return a full pathname.
// parseUrl uses an anchor element for parsing an url. With relative urls, the anchor
// element will create an absolute url relative to the current execution context.
// The JavaScript test suite is executed at '/' which will lead to an absolute url
// starting with '/'.
expect(commonUtils.parseUrl('" test="asf"').pathname).toContain('/%22%20test=%22asf%22');
});
});
describe('parseUrlPathname', () => {
it('returns an absolute url when given an absolute url', () => {
expect(commonUtils.parseUrlPathname('/some/absolute/url')).toEqual('/some/absolute/url');
});
it('returns an absolute url when given a relative url', () => {
expect(commonUtils.parseUrlPathname('some/relative/url')).toEqual('/some/relative/url');
});
});
describe('handleLocationHash', () => {
beforeEach(() => {
jest.spyOn(window.document, 'getElementById');
......
......@@ -22,6 +22,27 @@ beforeEach(() => {
});
describe('URL utility', () => {
describe('parseUrlPathname', () => {
it('returns an absolute url when given an absolute url', () => {
expect(urlUtils.parseUrlPathname('/some/absolute/url')).toBe('/some/absolute/url');
});
it('returns an absolute url when given a relative url', () => {
expect(urlUtils.parseUrlPathname('some/relative/url')).toBe('/some/relative/url');
});
it('returns an absolute url that includes the document.location path when given a relative url', () => {
// Change the location to see the `/mypath/` included in the result
setWindowLocation(`${TEST_HOST}/mypath/`);
expect(urlUtils.parseUrlPathname('some/relative/url')).toBe('/mypath/some/relative/url');
});
it('encodes certain character in the url', () => {
expect(urlUtils.parseUrlPathname('test="a b"')).toBe('/test=%22a%20b%22');
});
});
describe('webIDEUrl', () => {
afterEach(() => {
gon.relative_url_root = '';
......@@ -636,7 +657,7 @@ describe('URL utility', () => {
`('returns "$expectation" with "$protocol" protocol', ({ protocol, expectation }) => {
setWindowLocation(`${protocol}//example.com`);
expect(urlUtils.getWebSocketProtocol()).toEqual(expectation);
expect(urlUtils.getWebSocketProtocol()).toBe(expectation);
});
});
......@@ -646,7 +667,7 @@ describe('URL utility', () => {
const path = '/lorem/ipsum?a=bc';
expect(urlUtils.getWebSocketUrl(path)).toEqual('ws://example.com/lorem/ipsum?a=bc');
expect(urlUtils.getWebSocketUrl(path)).toBe('ws://example.com/lorem/ipsum?a=bc');
});
});
......@@ -696,7 +717,7 @@ describe('URL utility', () => {
it('should return valid parameter', () => {
setWindowLocation('?scope=all&p=2');
expect(getParameterByName('p')).toEqual('2');
expect(getParameterByName('p')).toBe('2');
expect(getParameterByName('scope')).toBe('all');
});
......@@ -737,7 +758,7 @@ describe('URL utility', () => {
it('converts search query object back into a search query', () => {
const searchQueryObject = { one: '1', two: '2' };
expect(urlUtils.objectToQuery(searchQueryObject)).toEqual('one=1&two=2');
expect(urlUtils.objectToQuery(searchQueryObject)).toBe('one=1&two=2');
});
it('returns empty string when `params` is undefined, null or empty string', () => {
......@@ -833,15 +854,15 @@ describe('URL utility', () => {
it('adds new params as query string', () => {
const url = 'https://gitlab.com/test';
expect(
urlUtils.setUrlParams({ group_id: 'gitlab-org', project_id: 'my-project' }, url),
).toEqual('https://gitlab.com/test?group_id=gitlab-org&project_id=my-project');
expect(urlUtils.setUrlParams({ group_id: 'gitlab-org', project_id: 'my-project' }, url)).toBe(
'https://gitlab.com/test?group_id=gitlab-org&project_id=my-project',
);
});
it('updates an existing parameter', () => {
const url = 'https://gitlab.com/test?group_id=gitlab-org&project_id=my-project';
expect(urlUtils.setUrlParams({ project_id: 'gitlab-test' }, url)).toEqual(
expect(urlUtils.setUrlParams({ project_id: 'gitlab-test' }, url)).toBe(
'https://gitlab.com/test?group_id=gitlab-org&project_id=gitlab-test',
);
});
......@@ -849,7 +870,7 @@ describe('URL utility', () => {
it("removes the project_id param when it's value is null", () => {
const url = 'https://gitlab.com/test?group_id=gitlab-org&project_id=my-project';
expect(urlUtils.setUrlParams({ project_id: null }, url)).toEqual(
expect(urlUtils.setUrlParams({ project_id: null }, url)).toBe(
'https://gitlab.com/test?group_id=gitlab-org',
);
});
......@@ -857,7 +878,7 @@ describe('URL utility', () => {
it('adds parameters from arrays', () => {
const url = 'https://gitlab.com/test';
expect(urlUtils.setUrlParams({ labels: ['foo', 'bar'] }, url)).toEqual(
expect(urlUtils.setUrlParams({ labels: ['foo', 'bar'] }, url)).toBe(
'https://gitlab.com/test?labels=foo&labels=bar',
);
});
......@@ -865,13 +886,13 @@ describe('URL utility', () => {
it('removes parameters from empty arrays', () => {
const url = 'https://gitlab.com/test?labels=foo&labels=bar';
expect(urlUtils.setUrlParams({ labels: [] }, url)).toEqual('https://gitlab.com/test');
expect(urlUtils.setUrlParams({ labels: [] }, url)).toBe('https://gitlab.com/test');
});
it('removes parameters from empty arrays while keeping other parameters', () => {
const url = 'https://gitlab.com/test?labels=foo&labels=bar&unrelated=unrelated';
expect(urlUtils.setUrlParams({ labels: [] }, url)).toEqual(
expect(urlUtils.setUrlParams({ labels: [] }, url)).toBe(
'https://gitlab.com/test?unrelated=unrelated',
);
});
......@@ -879,7 +900,7 @@ describe('URL utility', () => {
it('adds parameters from arrays when railsArraySyntax=true', () => {
const url = 'https://gitlab.com/test';
expect(urlUtils.setUrlParams({ labels: ['foo', 'bar'] }, url, false, true)).toEqual(
expect(urlUtils.setUrlParams({ labels: ['foo', 'bar'] }, url, false, true)).toBe(
'https://gitlab.com/test?labels%5B%5D=foo&labels%5B%5D=bar',
);
});
......@@ -887,7 +908,7 @@ describe('URL utility', () => {
it('removes parameters from empty arrays when railsArraySyntax=true', () => {
const url = 'https://gitlab.com/test?labels%5B%5D=foo&labels%5B%5D=bar';
expect(urlUtils.setUrlParams({ labels: [] }, url, false, true)).toEqual(
expect(urlUtils.setUrlParams({ labels: [] }, url, false, true)).toBe(
'https://gitlab.com/test',
);
});
......@@ -895,7 +916,7 @@ describe('URL utility', () => {
it('decodes URI when decodeURI=true', () => {
const url = 'https://gitlab.com/test';
expect(urlUtils.setUrlParams({ labels: ['foo', 'bar'] }, url, false, true, true)).toEqual(
expect(urlUtils.setUrlParams({ labels: ['foo', 'bar'] }, url, false, true, true)).toBe(
'https://gitlab.com/test?labels[]=foo&labels[]=bar',
);
});
......@@ -903,7 +924,7 @@ describe('URL utility', () => {
it('removes all existing URL params and sets a new param when cleanParams=true', () => {
const url = 'https://gitlab.com/test?group_id=gitlab-org&project_id=my-project';
expect(urlUtils.setUrlParams({ foo: 'bar' }, url, true)).toEqual(
expect(urlUtils.setUrlParams({ foo: 'bar' }, url, true)).toBe(
'https://gitlab.com/test?foo=bar',
);
});
......
......@@ -4,6 +4,7 @@ import initMrPage from 'helpers/init_vue_mr_page_helper';
import axios from '~/lib/utils/axios_utils';
import MergeRequestTabs from '~/merge_request_tabs';
import '~/lib/utils/common_utils';
import '~/lib/utils/url_utility';
jest.mock('~/lib/utils/webpack', () => ({
resetServiceWorkersPublicPath: jest.fn(),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment