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 = {}) => { ...@@ -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; export const isMetaKey = (e) => e.metaKey || e.ctrlKey || e.altKey || e.shiftKey;
// Identify following special clicks // Identify following special clicks
......
...@@ -18,6 +18,20 @@ function resetRegExp(regex) { ...@@ -18,6 +18,20 @@ function resetRegExp(regex) {
return 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 // Returns a decoded url parameter value
// - Treats '+' as '%20' // - Treats '+' as '%20'
function decodeUrlParameter(val) { function decodeUrlParameter(val) {
......
...@@ -2,13 +2,8 @@ ...@@ -2,13 +2,8 @@
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils'; import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import $ from 'jquery'; import $ from 'jquery';
import Vue from 'vue'; import Vue from 'vue';
import { import { getCookie, isMetaClick, parseBoolean, scrollToElement } from '~/lib/utils/common_utils';
getCookie, import { parseUrlPathname } from '~/lib/utils/url_utility';
parseUrlPathname,
isMetaClick,
parseBoolean,
scrollToElement,
} from '~/lib/utils/common_utils';
import createEventHub from '~/helpers/event_hub_factory'; import createEventHub from '~/helpers/event_hub_factory';
import BlobForkSuggestion from './blob/blob_fork_suggestion'; import BlobForkSuggestion from './blob/blob_fork_suggestion';
import Diff from './diff'; import Diff from './diff';
......
...@@ -51,31 +51,6 @@ describe('common_utils', () => { ...@@ -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', () => { describe('handleLocationHash', () => {
beforeEach(() => { beforeEach(() => {
jest.spyOn(window.document, 'getElementById'); jest.spyOn(window.document, 'getElementById');
......
...@@ -22,6 +22,27 @@ beforeEach(() => { ...@@ -22,6 +22,27 @@ beforeEach(() => {
}); });
describe('URL utility', () => { 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', () => { describe('webIDEUrl', () => {
afterEach(() => { afterEach(() => {
gon.relative_url_root = ''; gon.relative_url_root = '';
...@@ -636,7 +657,7 @@ describe('URL utility', () => { ...@@ -636,7 +657,7 @@ describe('URL utility', () => {
`('returns "$expectation" with "$protocol" protocol', ({ protocol, expectation }) => { `('returns "$expectation" with "$protocol" protocol', ({ protocol, expectation }) => {
setWindowLocation(`${protocol}//example.com`); setWindowLocation(`${protocol}//example.com`);
expect(urlUtils.getWebSocketProtocol()).toEqual(expectation); expect(urlUtils.getWebSocketProtocol()).toBe(expectation);
}); });
}); });
...@@ -646,7 +667,7 @@ describe('URL utility', () => { ...@@ -646,7 +667,7 @@ describe('URL utility', () => {
const path = '/lorem/ipsum?a=bc'; 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', () => { ...@@ -696,7 +717,7 @@ describe('URL utility', () => {
it('should return valid parameter', () => { it('should return valid parameter', () => {
setWindowLocation('?scope=all&p=2'); setWindowLocation('?scope=all&p=2');
expect(getParameterByName('p')).toEqual('2'); expect(getParameterByName('p')).toBe('2');
expect(getParameterByName('scope')).toBe('all'); expect(getParameterByName('scope')).toBe('all');
}); });
...@@ -737,7 +758,7 @@ describe('URL utility', () => { ...@@ -737,7 +758,7 @@ describe('URL utility', () => {
it('converts search query object back into a search query', () => { it('converts search query object back into a search query', () => {
const searchQueryObject = { one: '1', two: '2' }; 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', () => { it('returns empty string when `params` is undefined, null or empty string', () => {
...@@ -833,15 +854,15 @@ describe('URL utility', () => { ...@@ -833,15 +854,15 @@ describe('URL utility', () => {
it('adds new params as query string', () => { it('adds new params as query string', () => {
const url = 'https://gitlab.com/test'; const url = 'https://gitlab.com/test';
expect( expect(urlUtils.setUrlParams({ group_id: 'gitlab-org', project_id: 'my-project' }, url)).toBe(
urlUtils.setUrlParams({ group_id: 'gitlab-org', project_id: 'my-project' }, url), 'https://gitlab.com/test?group_id=gitlab-org&project_id=my-project',
).toEqual('https://gitlab.com/test?group_id=gitlab-org&project_id=my-project'); );
}); });
it('updates an existing parameter', () => { it('updates an existing parameter', () => {
const url = 'https://gitlab.com/test?group_id=gitlab-org&project_id=my-project'; 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', 'https://gitlab.com/test?group_id=gitlab-org&project_id=gitlab-test',
); );
}); });
...@@ -849,7 +870,7 @@ describe('URL utility', () => { ...@@ -849,7 +870,7 @@ describe('URL utility', () => {
it("removes the project_id param when it's value is null", () => { 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'; 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', 'https://gitlab.com/test?group_id=gitlab-org',
); );
}); });
...@@ -857,7 +878,7 @@ describe('URL utility', () => { ...@@ -857,7 +878,7 @@ describe('URL utility', () => {
it('adds parameters from arrays', () => { it('adds parameters from arrays', () => {
const url = 'https://gitlab.com/test'; 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', 'https://gitlab.com/test?labels=foo&labels=bar',
); );
}); });
...@@ -865,13 +886,13 @@ describe('URL utility', () => { ...@@ -865,13 +886,13 @@ describe('URL utility', () => {
it('removes parameters from empty arrays', () => { it('removes parameters from empty arrays', () => {
const url = 'https://gitlab.com/test?labels=foo&labels=bar'; 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', () => { it('removes parameters from empty arrays while keeping other parameters', () => {
const url = 'https://gitlab.com/test?labels=foo&labels=bar&unrelated=unrelated'; 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', 'https://gitlab.com/test?unrelated=unrelated',
); );
}); });
...@@ -879,7 +900,7 @@ describe('URL utility', () => { ...@@ -879,7 +900,7 @@ describe('URL utility', () => {
it('adds parameters from arrays when railsArraySyntax=true', () => { it('adds parameters from arrays when railsArraySyntax=true', () => {
const url = 'https://gitlab.com/test'; 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', 'https://gitlab.com/test?labels%5B%5D=foo&labels%5B%5D=bar',
); );
}); });
...@@ -887,7 +908,7 @@ describe('URL utility', () => { ...@@ -887,7 +908,7 @@ describe('URL utility', () => {
it('removes parameters from empty arrays when railsArraySyntax=true', () => { it('removes parameters from empty arrays when railsArraySyntax=true', () => {
const url = 'https://gitlab.com/test?labels%5B%5D=foo&labels%5B%5D=bar'; 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', 'https://gitlab.com/test',
); );
}); });
...@@ -895,7 +916,7 @@ describe('URL utility', () => { ...@@ -895,7 +916,7 @@ describe('URL utility', () => {
it('decodes URI when decodeURI=true', () => { it('decodes URI when decodeURI=true', () => {
const url = 'https://gitlab.com/test'; 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', 'https://gitlab.com/test?labels[]=foo&labels[]=bar',
); );
}); });
...@@ -903,7 +924,7 @@ describe('URL utility', () => { ...@@ -903,7 +924,7 @@ describe('URL utility', () => {
it('removes all existing URL params and sets a new param when cleanParams=true', () => { 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'; 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', 'https://gitlab.com/test?foo=bar',
); );
}); });
......
...@@ -4,6 +4,7 @@ import initMrPage from 'helpers/init_vue_mr_page_helper'; ...@@ -4,6 +4,7 @@ import initMrPage from 'helpers/init_vue_mr_page_helper';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import MergeRequestTabs from '~/merge_request_tabs'; import MergeRequestTabs from '~/merge_request_tabs';
import '~/lib/utils/common_utils'; import '~/lib/utils/common_utils';
import '~/lib/utils/url_utility';
jest.mock('~/lib/utils/webpack', () => ({ jest.mock('~/lib/utils/webpack', () => ({
resetServiceWorkersPublicPath: jest.fn(), 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