summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilipa Lacerda <filipa@gitlab.com>2017-09-06 17:14:34 +0100
committerFilipa Lacerda <filipa@gitlab.com>2017-09-09 09:54:27 +0100
commit96e6fc70b40c51af50bee6c421f7f363acd899d4 (patch)
tree1bcdec4ae4d83d08c5a2c43573df64edd7d309d7
parent6a1b84c7b450e65eaad6bf016fc9b7310e89784c (diff)
downloadgitlab-ce-96e6fc70b40c51af50bee6c421f7f363acd899d4.tar.gz
Import modules instead of using the ones in global namespace
Removes set favicon related methods from global scope Improves test related with favicon Removes convertPermissionToBoolean from global scope. Adds tests for convertPermissionToBoolean - were non existant Removes setParamInURL from gl.utils Removes parseIntPagination from gl.utils namespace Remove normalizeCRLFHeaders from gl.utils namespace Removes normalizeHeaders from gl.utils namespace Use gl.utils for filtered search Fix bad import Fix broken test by cleaning window.history namespace Adds changelog
-rw-r--r--app/assets/javascripts/blob/viewer/index.js4
-rw-r--r--app/assets/javascripts/boards/stores/boards_store.js3
-rw-r--r--app/assets/javascripts/build.js3
-rw-r--r--app/assets/javascripts/copy_as_gfm.js6
-rw-r--r--app/assets/javascripts/dispatcher.js4
-rw-r--r--app/assets/javascripts/environments/components/environment.vue20
-rw-r--r--app/assets/javascripts/environments/folder/environments_folder_view.vue18
-rw-r--r--app/assets/javascripts/environments/stores/environments_store.js6
-rw-r--r--app/assets/javascripts/groups/components/groups.vue5
-rw-r--r--app/assets/javascripts/groups/groups_filterable_list.js3
-rw-r--r--app/assets/javascripts/groups/index.js7
-rw-r--r--app/assets/javascripts/groups/stores/groups_store.js5
-rw-r--r--app/assets/javascripts/groups_select.js3
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js32
-rw-r--r--app/assets/javascripts/lib/utils/poll.js3
-rw-r--r--app/assets/javascripts/main.js8
-rw-r--r--app/assets/javascripts/merge_request_tabs.js10
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue4
-rw-r--r--app/assets/javascripts/notes.js6
-rw-r--r--app/assets/javascripts/pager.js4
-rw-r--r--app/assets/javascripts/pipeline_schedules/setup_pipeline_variable_list.js4
-rw-r--r--app/assets/javascripts/pipelines.js3
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines.vue11
-rw-r--r--app/assets/javascripts/pipelines/stores/pipelines_store.js6
-rw-r--r--app/assets/javascripts/todos.js3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js9
-rw-r--r--changelogs/unreleased/37220-es-modules.yml5
-rw-r--r--spec/javascripts/environments/folder/environments_folder_view_spec.js4
-rw-r--r--spec/javascripts/lib/utils/common_utils_spec.js165
-rw-r--r--spec/javascripts/merge_request_tabs_spec.js7
-rw-r--r--spec/javascripts/todos_spec.js5
-rw-r--r--spec/javascripts/vue_mr_widget/mr_widget_options_spec.js27
32 files changed, 233 insertions, 170 deletions
diff --git a/app/assets/javascripts/blob/viewer/index.js b/app/assets/javascripts/blob/viewer/index.js
index 187fab084fd..e0b73f13d36 100644
--- a/app/assets/javascripts/blob/viewer/index.js
+++ b/app/assets/javascripts/blob/viewer/index.js
@@ -1,4 +1,6 @@
/* global Flash */
+import { handleLocationHash } from '../../lib/utils/common_utils';
+
export default class BlobViewer {
constructor() {
BlobViewer.initAuxiliaryViewer();
@@ -114,7 +116,7 @@ export default class BlobViewer {
$(viewer).renderGFM();
this.$fileHolder.trigger('highlight:line');
- gl.utils.handleLocationHash();
+ handleLocationHash();
this.toggleCopyButtonState();
})
diff --git a/app/assets/javascripts/boards/stores/boards_store.js b/app/assets/javascripts/boards/stores/boards_store.js
index 43928e602d6..ea82958e80d 100644
--- a/app/assets/javascripts/boards/stores/boards_store.js
+++ b/app/assets/javascripts/boards/stores/boards_store.js
@@ -2,6 +2,7 @@
/* global List */
import _ from 'underscore';
import Cookies from 'js-cookie';
+import { getUrlParamsArray } from '../../lib/utils/common_utils';
window.gl = window.gl || {};
window.gl.issueBoards = window.gl.issueBoards || {};
@@ -21,7 +22,7 @@ gl.issueBoards.BoardsStore = {
},
create () {
this.state.lists = [];
- this.filter.path = gl.utils.getUrlParamsArray().join('&');
+ this.filter.path = getUrlParamsArray().join('&');
this.detail = { issue: {} };
},
addList (listObj, defaultAvatar) {
diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js
index ae1a23132a7..286a758b8a9 100644
--- a/app/assets/javascripts/build.js
+++ b/app/assets/javascripts/build.js
@@ -3,6 +3,7 @@ consistent-return, prefer-rest-params */
import _ from 'underscore';
import bp from './breakpoints';
import { bytesToKiB } from './lib/utils/number_utils';
+import { setCiStatusFavicon } from './lib/utils/common_utils';
window.Build = (function () {
Build.timeout = null;
@@ -169,7 +170,7 @@ window.Build = (function () {
data: this.state,
})
.done((log) => {
- gl.utils.setCiStatusFavicon(`${this.pageUrl}/status.json`);
+ setCiStatusFavicon(`${this.pageUrl}/status.json`);
if (log.state) {
this.state = log.state;
diff --git a/app/assets/javascripts/copy_as_gfm.js b/app/assets/javascripts/copy_as_gfm.js
index 13ba4a57293..e3e2c798570 100644
--- a/app/assets/javascripts/copy_as_gfm.js
+++ b/app/assets/javascripts/copy_as_gfm.js
@@ -1,6 +1,6 @@
/* eslint-disable class-methods-use-this, object-shorthand, no-unused-vars, no-use-before-define, no-new, max-len, no-restricted-syntax, guard-for-in, no-continue */
import _ from 'underscore';
-import './lib/utils/common_utils';
+import { insertText, getSelectedFragment, nodeMatchesSelector } from './lib/utils/common_utils';
import { placeholderImage } from './lazy_loader';
const gfmRules = {
@@ -295,7 +295,7 @@ class CopyAsGFM {
const clipboardData = e.originalEvent.clipboardData;
if (!clipboardData) return;
- const documentFragment = window.gl.utils.getSelectedFragment();
+ const documentFragment = getSelectedFragment();
if (!documentFragment) return;
const el = transformer(documentFragment.cloneNode(true));
@@ -412,7 +412,7 @@ class CopyAsGFM {
for (const selector in rules) {
const func = rules[selector];
- if (!window.gl.utils.nodeMatchesSelector(node, selector)) continue;
+ if (!nodeMatchesSelector(node, selector)) continue;
let result;
if (func.length === 2) {
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index ca2de53fe44..31214818496 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -77,7 +77,7 @@ import initProjectVisibilitySelector from './project_visibility';
import GpgBadges from './gpg_badges';
import UserFeatureHelper from './helpers/user_feature_helper';
import initChangesDropdown from './init_changes_dropdown';
-import { ajaxGet } from './lib/utils/common_utils';
+import { ajaxGet, convertPermissionToBoolean } from './lib/utils/common_utils';
(function() {
var Dispatcher;
@@ -101,7 +101,7 @@ import { ajaxGet } from './lib/utils/common_utils';
$('.js-gfm-input:not(.js-vue-textarea)').each((i, el) => {
const gfm = new GfmAutoComplete(gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources);
- const enableGFM = gl.utils.convertPermissionToBoolean(el.dataset.supportsAutocomplete);
+ const enableGFM = convertPermissionToBoolean(el.dataset.supportsAutocomplete);
gfm.setup($(el), {
emojis: true,
members: enableGFM,
diff --git a/app/assets/javascripts/environments/components/environment.vue b/app/assets/javascripts/environments/components/environment.vue
index f54d573db6e..14fde1afb16 100644
--- a/app/assets/javascripts/environments/components/environment.vue
+++ b/app/assets/javascripts/environments/components/environment.vue
@@ -6,7 +6,7 @@ import environmentTable from './environments_table.vue';
import EnvironmentsStore from '../stores/environments_store';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
import tablePagination from '../../vue_shared/components/table_pagination.vue';
-import '../../lib/utils/common_utils';
+import { convertPermissionToBoolean, getParameterByName, setParamInURL } from '../../lib/utils/common_utils';
import eventHub from '../event_hub';
import Poll from '../../lib/utils/poll';
import environmentsMixin from '../mixins/environments_mixin';
@@ -51,19 +51,19 @@ export default {
computed: {
scope() {
- return gl.utils.getParameterByName('scope');
+ return getParameterByName('scope');
},
canReadEnvironmentParsed() {
- return gl.utils.convertPermissionToBoolean(this.canReadEnvironment);
+ return convertPermissionToBoolean(this.canReadEnvironment);
},
canCreateDeploymentParsed() {
- return gl.utils.convertPermissionToBoolean(this.canCreateDeployment);
+ return convertPermissionToBoolean(this.canCreateDeployment);
},
canCreateEnvironmentParsed() {
- return gl.utils.convertPermissionToBoolean(this.canCreateEnvironment);
+ return convertPermissionToBoolean(this.canCreateEnvironment);
},
},
@@ -72,8 +72,8 @@ export default {
* Toggles loading property.
*/
created() {
- const scope = gl.utils.getParameterByName('scope') || this.visibility;
- const page = gl.utils.getParameterByName('page') || this.pageNumber;
+ const scope = getParameterByName('scope') || this.visibility;
+ const page = getParameterByName('page') || this.pageNumber;
this.service = new EnvironmentsService(this.endpoint);
@@ -126,15 +126,15 @@ export default {
* @return {String}
*/
changePage(pageNumber) {
- const param = gl.utils.setParamInURL('page', pageNumber);
+ const param = setParamInURL('page', pageNumber);
gl.utils.visitUrl(param);
return param;
},
fetchEnvironments() {
- const scope = gl.utils.getParameterByName('scope') || this.visibility;
- const page = gl.utils.getParameterByName('page') || this.pageNumber;
+ const scope = getParameterByName('scope') || this.visibility;
+ const page = getParameterByName('page') || this.pageNumber;
this.isLoading = true;
diff --git a/app/assets/javascripts/environments/folder/environments_folder_view.vue b/app/assets/javascripts/environments/folder/environments_folder_view.vue
index 925503a01c4..35891240239 100644
--- a/app/assets/javascripts/environments/folder/environments_folder_view.vue
+++ b/app/assets/javascripts/environments/folder/environments_folder_view.vue
@@ -9,7 +9,7 @@ import tablePagination from '../../vue_shared/components/table_pagination.vue';
import Poll from '../../lib/utils/poll';
import eventHub from '../event_hub';
import environmentsMixin from '../mixins/environments_mixin';
-import '../../lib/utils/common_utils';
+import { convertPermissionToBoolean, getParameterByName, setParamInURL } from '../../lib/utils/common_utils';
export default {
components: {
@@ -47,15 +47,15 @@ export default {
computed: {
scope() {
- return gl.utils.getParameterByName('scope');
+ return getParameterByName('scope');
},
canReadEnvironmentParsed() {
- return gl.utils.convertPermissionToBoolean(this.canReadEnvironment);
+ return convertPermissionToBoolean(this.canReadEnvironment);
},
canCreateDeploymentParsed() {
- return gl.utils.convertPermissionToBoolean(this.canCreateDeployment);
+ return convertPermissionToBoolean(this.canCreateDeployment);
},
/**
@@ -82,8 +82,8 @@ export default {
* Toggles loading property.
*/
created() {
- const scope = gl.utils.getParameterByName('scope') || this.visibility;
- const page = gl.utils.getParameterByName('page') || this.pageNumber;
+ const scope = getParameterByName('scope') || this.visibility;
+ const page = getParameterByName('page') || this.pageNumber;
this.service = new EnvironmentsService(this.endpoint);
@@ -125,15 +125,15 @@ export default {
* @param {Number} pageNumber desired page to go to.
*/
changePage(pageNumber) {
- const param = gl.utils.setParamInURL('page', pageNumber);
+ const param = setParamInURL('page', pageNumber);
gl.utils.visitUrl(param);
return param;
},
fetchEnvironments() {
- const scope = gl.utils.getParameterByName('scope') || this.visibility;
- const page = gl.utils.getParameterByName('page') || this.pageNumber;
+ const scope = getParameterByName('scope') || this.visibility;
+ const page = getParameterByName('page') || this.pageNumber;
this.isLoading = true;
diff --git a/app/assets/javascripts/environments/stores/environments_store.js b/app/assets/javascripts/environments/stores/environments_store.js
index 038c149be2d..aff8227c38c 100644
--- a/app/assets/javascripts/environments/stores/environments_store.js
+++ b/app/assets/javascripts/environments/stores/environments_store.js
@@ -1,4 +1,4 @@
-import '~/lib/utils/common_utils';
+import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
/**
* Environments Store.
*
@@ -66,8 +66,8 @@ export default class EnvironmentsStore {
}
setPagination(pagination = {}) {
- const normalizedHeaders = gl.utils.normalizeHeaders(pagination);
- const paginationInformation = gl.utils.parseIntPagination(normalizedHeaders);
+ const normalizedHeaders = normalizeHeaders(pagination);
+ const paginationInformation = parseIntPagination(normalizedHeaders);
this.state.paginationInformation = paginationInformation;
return paginationInformation;
diff --git a/app/assets/javascripts/groups/components/groups.vue b/app/assets/javascripts/groups/components/groups.vue
index 36a04d4202f..d17a43b048a 100644
--- a/app/assets/javascripts/groups/components/groups.vue
+++ b/app/assets/javascripts/groups/components/groups.vue
@@ -1,6 +1,7 @@
<script>
import tablePagination from '~/vue_shared/components/table_pagination.vue';
import eventHub from '../event_hub';
+import { getParameterByName } from '../../lib/utils/common_utils';
export default {
props: {
@@ -18,8 +19,8 @@ export default {
},
methods: {
change(page) {
- const filterGroupsParam = gl.utils.getParameterByName('filter_groups');
- const sortParam = gl.utils.getParameterByName('sort');
+ const filterGroupsParam = getParameterByName('filter_groups');
+ const sortParam = getParameterByName('sort');
eventHub.$emit('fetchPage', page, filterGroupsParam, sortParam);
},
},
diff --git a/app/assets/javascripts/groups/groups_filterable_list.js b/app/assets/javascripts/groups/groups_filterable_list.js
index 439a931ddad..83b102764ba 100644
--- a/app/assets/javascripts/groups/groups_filterable_list.js
+++ b/app/assets/javascripts/groups/groups_filterable_list.js
@@ -1,5 +1,6 @@
import FilterableList from '~/filterable_list';
import eventHub from './event_hub';
+import { getParameterByName } from '../lib/utils/common_utils';
export default class GroupFilterableList extends FilterableList {
constructor({ form, filter, holder, filterEndpoint, pagePath }) {
@@ -54,7 +55,7 @@ export default class GroupFilterableList extends FilterableList {
e.preventDefault();
const queryData = {};
- const sortParam = gl.utils.getParameterByName('sort', e.currentTarget.href);
+ const sortParam = getParameterByName('sort', e.currentTarget.href);
if (sortParam) {
queryData.sort = sortParam;
diff --git a/app/assets/javascripts/groups/index.js b/app/assets/javascripts/groups/index.js
index 00e1bd94c9c..9ad8e5c6052 100644
--- a/app/assets/javascripts/groups/index.js
+++ b/app/assets/javascripts/groups/index.js
@@ -8,6 +8,7 @@ import GroupItem from './components/group_item.vue';
import GroupsStore from './stores/groups_store';
import GroupsService from './services/groups_service';
import eventHub from './event_hub';
+import { getParameterByName } from '../lib/utils/common_utils';
document.addEventListener('DOMContentLoaded', () => {
const el = document.getElementById('dashboard-group-app');
@@ -58,17 +59,17 @@ document.addEventListener('DOMContentLoaded', () => {
this.isLoading = true;
}
- pageParam = gl.utils.getParameterByName('page');
+ pageParam = getParameterByName('page');
if (pageParam) {
page = pageParam;
}
- filterGroupsParam = gl.utils.getParameterByName('filter_groups');
+ filterGroupsParam = getParameterByName('filter_groups');
if (filterGroupsParam) {
filterGroups = filterGroupsParam;
}
- sortParam = gl.utils.getParameterByName('sort');
+ sortParam = getParameterByName('sort');
if (sortParam) {
sort = sortParam;
}
diff --git a/app/assets/javascripts/groups/stores/groups_store.js b/app/assets/javascripts/groups/stores/groups_store.js
index 6eab6083e8f..f59ec677603 100644
--- a/app/assets/javascripts/groups/stores/groups_store.js
+++ b/app/assets/javascripts/groups/stores/groups_store.js
@@ -1,4 +1,5 @@
import Vue from 'vue';
+import { parseIntPagination, normalizeHeaders } from '../../lib/utils/common_utils';
export default class GroupsStore {
constructor() {
@@ -30,8 +31,8 @@ export default class GroupsStore {
let paginationInfo;
if (Object.keys(pagination).length) {
- const normalizedHeaders = gl.utils.normalizeHeaders(pagination);
- paginationInfo = gl.utils.parseIntPagination(normalizedHeaders);
+ const normalizedHeaders = normalizeHeaders(pagination);
+ paginationInfo = parseIntPagination(normalizedHeaders);
} else {
paginationInfo = pagination;
}
diff --git a/app/assets/javascripts/groups_select.js b/app/assets/javascripts/groups_select.js
index 4d629bc6326..90ca70289ab 100644
--- a/app/assets/javascripts/groups_select.js
+++ b/app/assets/javascripts/groups_select.js
@@ -4,6 +4,7 @@
prefer-rest-params, prefer-spread, no-unused-vars, prefer-template,
promise/catch-or-return */
import Api from './api';
+import { normalizeCRLFHeaders } from './lib/utils/common_utils';
var slice = [].slice;
@@ -30,7 +31,7 @@ window.GroupsSelect = (function() {
$.ajax(params).then((data, status, xhr) => {
const results = data || [];
- const headers = gl.utils.normalizeCRLFHeaders(xhr.getAllResponseHeaders());
+ const headers = normalizeCRLFHeaders(xhr.getAllResponseHeaders());
const currentPage = parseInt(headers['X-PAGE'], 10) || 0;
const totalPages = parseInt(headers['X-TOTAL-PAGES'], 10) || 0;
const more = currentPage < totalPages;
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js
index 87b3b0bc8a4..76e436ceab5 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -1,4 +1,5 @@
-/* eslint-disable no-param-reassing */
+window.gl = window.gl || {};
+window.gl.utils = window.gl.utils || {};
export const getPagePath = (index = 0) => $('body').data('page').split(':')[index];
window.gl.utils.getPagePath = getPagePath;
@@ -48,7 +49,7 @@ export const ajaxPost = (url, data) => $.ajax({
window.gl.utils.ajaxPost = ajaxPost;
// TODO: This function seems not to be used anywhere
-window.gl.utils.extractLast = term => this.split(term).pop();
+// window.gl.utils.extractLast = term => this.split(term).pop();
export const rstrip = function rstrip(val) {
if (val) {
@@ -145,10 +146,11 @@ window.gl.utils.parseUrlPathname = parseUrlPathname;
// We can trust that each param has one & since values containing & will be encoded
// Remove the first character of search as it is always ?
-window.gl.utils.getUrlParamsArray = () => window.location.search.slice(1).split('&').map((param) => {
+export const getUrlParamsArray = () => window.location.search.slice(1).split('&').map((param) => {
const split = param.split('=');
return [decodeURI(split[0]), split[1]].join('=');
});
+window.gl.utils.getUrlParamsArray = getUrlParamsArray;
export const isMetaKey = e => e.metaKey || e.ctrlKey || e.altKey || e.shiftKey;
window.gl.utils.isMetaKey = isMetaKey;
@@ -178,8 +180,8 @@ window.gl.utils.scrollToElement = scrollToElement;
*/
export const getParameterByName = (name, urlToParse) => {
const url = urlToParse || window.location.href;
- name = name.replace(/[[\]]/g, '\\$&');
- const regex = new RegExp(`[?&]${name}(=([^&#]*)|&|#|$)`);
+ const parsedName = name.replace(/[[\]]/g, '\\$&');
+ const regex = new RegExp(`[?&]${parsedName}(=([^&#]*)|&|#|$)`);
const results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
@@ -200,6 +202,7 @@ export const getSelectedFragment = () => {
};
window.gl.utils.getSelectedFragment = getSelectedFragment;
+// TODO: Update this name, there is a gl.text.insertText function.
export const insertText = (target, text) => {
// Firefox doesn't support `document.execCommand('insertText', false, text)` on textareas
const selectionStart = target.selectionStart;
@@ -212,7 +215,9 @@ export const insertText = (target, text) => {
const insertedText = text instanceof Function ? text(textBefore, textAfter) : text;
const newText = textBefore + insertedText + textAfter;
+ // eslint-disable-next-line no-param-reassign
target.value = newText;
+ // eslint-disable-next-line no-param-reassign
target.selectionStart = target.selectionEnd = selectionStart + insertedText.length;
// Trigger autosave
@@ -242,6 +247,7 @@ export const nodeMatchesSelector = (node, selector) => {
let parentNode = node.parentNode;
if (!parentNode) {
parentNode = document.createElement('div');
+ // eslint-disable-next-line no-param-reassign
node = node.cloneNode(true);
parentNode.appendChild(node);
}
@@ -264,7 +270,6 @@ export const normalizeHeaders = (headers) => {
return upperCaseHeaders;
};
-window.gl.utils.normalizeHeaders = normalizeHeaders;
/**
this will take in the getAllResponseHeaders result and normalize them
@@ -281,7 +286,6 @@ export const normalizeCRLFHeaders = (headers) => {
return normalizeHeaders(headersObject);
};
-window.gl.utils.normalizeCRLFHeaders = normalizeCRLFHeaders;
/**
* Parses pagination object string values into numbers.
@@ -297,7 +301,6 @@ export const parseIntPagination = paginationInformation => ({
nextPage: parseInt(paginationInformation['X-NEXT-PAGE'], 10),
previousPage: parseInt(paginationInformation['X-PREV-PAGE'], 10),
});
-window.gl.utils.parseIntPagination = parseIntPagination;
/**
* Updates the search parameter of a URL given the parameter and value provided.
@@ -320,6 +323,7 @@ export const setParamInURL = (param, value) => {
.split('&')
.reduce((acc, element) => {
const val = element.split('=');
+ // eslint-disable-next-line no-param-reassign
acc[val[0]] = decodeURIComponent(val[1]);
return acc;
}, {});
@@ -337,7 +341,6 @@ export const setParamInURL = (param, value) => {
return search;
};
-window.gl.utils.setParamInURL = setParamInURL;
/**
* Converts permission provided as strings to booleans.
@@ -346,7 +349,6 @@ window.gl.utils.setParamInURL = setParamInURL;
* @returns {Boolean}
*/
export const convertPermissionToBoolean = permission => permission === 'true';
-window.gl.utils.convertPermissionToBoolean = convertPermissionToBoolean;
/**
* Back Off exponential algorithm
@@ -400,7 +402,6 @@ export const backOff = (fn, timeout = 60000) => {
fn(next, stop);
});
};
-window.gl.utils.backOff = backOff;
export const setFavicon = (faviconPath) => {
const faviconEl = document.getElementById('favicon');
@@ -408,7 +409,6 @@ export const setFavicon = (faviconPath) => {
faviconEl.setAttribute('href', faviconPath);
}
};
-window.gl.utils.setFavicon = setFavicon;
export const resetFavicon = () => {
const faviconEl = document.getElementById('favicon');
@@ -417,7 +417,6 @@ export const resetFavicon = () => {
faviconEl.setAttribute('href', originalFavicon);
}
};
-window.gl.utils.resetFavicon = resetFavicon;
export const setCiStatusFavicon = (pageUrl) => {
$.ajax({
@@ -425,14 +424,13 @@ export const setCiStatusFavicon = (pageUrl) => {
dataType: 'json',
success: (data) => {
if (data && data.favicon) {
- gl.utils.setFavicon(data.favicon);
+ setFavicon(data.favicon);
} else {
- gl.utils.resetFavicon();
+ resetFavicon();
}
},
error: () => {
- gl.utils.resetFavicon();
+ resetFavicon();
},
});
};
-window.gl.utils.setCiStatusFavicon = setCiStatusFavicon;
diff --git a/app/assets/javascripts/lib/utils/poll.js b/app/assets/javascripts/lib/utils/poll.js
index 97666e13ebe..1485e900945 100644
--- a/app/assets/javascripts/lib/utils/poll.js
+++ b/app/assets/javascripts/lib/utils/poll.js
@@ -1,4 +1,5 @@
import httpStatusCodes from './http_status';
+import { normalizeHeaders } from './common_utils';
/**
* Polling utility for handling realtime updates.
@@ -57,7 +58,7 @@ export default class Poll {
}
checkConditions(response) {
- const headers = gl.utils.normalizeHeaders(response.headers);
+ const headers = normalizeHeaders(response.headers);
const pollInterval = parseInt(headers[this.intervalHeader], 10);
if (pollInterval > 0 && response.status === httpStatusCodes.OK && this.canPoll) {
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index 0bc31a56684..d99839fadb4 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -41,7 +41,7 @@ import './commit/image_file';
// lib/utils
import './lib/utils/animate';
import './lib/utils/bootstrap_linked_tabs';
-import './lib/utils/common_utils';
+import { handleLocationHash } from './lib/utils/common_utils';
import './lib/utils/datetime_utility';
import './lib/utils/pretty_time';
import './lib/utils/text_utility';
@@ -162,10 +162,10 @@ document.addEventListener('beforeunload', function () {
$('[data-toggle="popover"]').popover('destroy');
});
-window.addEventListener('hashchange', gl.utils.handleLocationHash);
+window.addEventListener('hashchange', handleLocationHash);
window.addEventListener('load', function onLoad() {
window.removeEventListener('load', onLoad, false);
- gl.utils.handleLocationHash();
+ handleLocationHash();
}, false);
gl.lazyLoader = new LazyLoader({
@@ -191,7 +191,7 @@ $(function () {
$body.on('click', 'a[href^="#"]', function() {
var href = this.getAttribute('href');
if (href.substr(1) === gl.utils.getLocationHash()) {
- setTimeout(gl.utils.handleLocationHash, 1);
+ setTimeout(handleLocationHash, 1);
}
});
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index efcda7c38fb..f71a59aaa84 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -7,7 +7,11 @@ import './flash';
import BlobForkSuggestion from './blob/blob_fork_suggestion';
import initChangesDropdown from './init_changes_dropdown';
import bp from './breakpoints';
-import parseUrlPathname from './lib/utils/common_utils';
+import {
+ parseUrlPathname,
+ handleLocationHash,
+ isMetaClick,
+} from './lib/utils/common_utils';
/* eslint-disable max-len */
// MergeRequestTabs
@@ -115,7 +119,7 @@ import parseUrlPathname from './lib/utils/common_utils';
}
clickTab(e) {
- if (e.currentTarget && gl.utils.isMetaClick(e)) {
+ if (e.currentTarget && isMetaClick(e)) {
const targetLink = e.currentTarget.getAttribute('href');
e.stopImmediatePropagation();
e.preventDefault();
@@ -310,7 +314,7 @@ import parseUrlPathname from './lib/utils/common_utils';
forceShow: true,
});
anchor[0].scrollIntoView();
- window.gl.utils.handleLocationHash();
+ handleLocationHash();
// We have multiple elements on the page with `#note_xxx`
// (discussion and diff tabs) and `:target` only applies to the first
anchor.addClass('target');
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index a87fe7fa9d3..f39ea643da4 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -8,7 +8,7 @@
import EmptyState from './empty_state.vue';
import MonitoringStore from '../stores/monitoring_store';
import eventHub from '../event_hub';
- import { backOff } from '../../lib/utils/common_utils';
+ import { backOff, convertPermissionToBoolean } from '../../lib/utils/common_utils';
export default {
@@ -19,7 +19,7 @@
return {
store,
state: 'gettingStarted',
- hasMetrics: gl.utils.convertPermissionToBoolean(metricsData.hasMetrics),
+ hasMetrics: convertPermissionToBoolean(metricsData.hasMetrics),
documentationPath: metricsData.documentationPath,
settingsPath: metricsData.settingsPath,
endpoint: metricsData.additionalMetrics,
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index 7146ecb0b3e..93aa29454a0 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -23,7 +23,7 @@ import loadAwardsHandler from './awards_handler';
import './autosave';
import './dropzone_input';
import TaskList from './task_list';
-import { ajaxPost, isInViewport, getPagePath } from './lib/utils/common_utils';
+import { ajaxPost, isInViewport, getPagePath, scrollToElement, isMetaKey } from './lib/utils/common_utils';
window.autosize = autosize;
window.Dropzone = Dropzone;
@@ -176,7 +176,7 @@ export default class Notes {
keydownNoteText(e) {
var $textarea, discussionNoteForm, editNote, myLastNote, myLastNoteEditBtn, newText, originalText;
- if (gl.utils.isMetaKey(e)) {
+ if (isMetaKey(e)) {
return;
}
@@ -1482,7 +1482,7 @@ export default class Notes {
*
* 1) Get Form metadata
* 2) Update note element with new content
- * 3) Perform network request to submit the updated note using `gl.utils.ajaxPost`
+ * 3) Perform network request to submit the updated note using `ajaxPost`
* a) If request is successfully completed
* 1. Show submitted Note element
* b) If request failed
diff --git a/app/assets/javascripts/pager.js b/app/assets/javascripts/pager.js
index 01110420cca..e3fc1e2fc2f 100644
--- a/app/assets/javascripts/pager.js
+++ b/app/assets/javascripts/pager.js
@@ -1,4 +1,4 @@
-import '~/lib/utils/common_utils';
+import { getParameterByName } from '~/lib/utils/common_utils';
import '~/lib/utils/url_utility';
(() => {
@@ -9,7 +9,7 @@ import '~/lib/utils/url_utility';
init(limit = 0, preload = false, disable = false, prepareData = $.noop, callback = $.noop) {
this.url = $('.content_list').data('href') || gl.utils.removeParams(['limit', 'offset']);
this.limit = limit;
- this.offset = parseInt(gl.utils.getParameterByName('offset'), 10) || this.limit;
+ this.offset = parseInt(getParameterByName('offset'), 10) || this.limit;
this.disable = disable;
this.prepareData = prepareData;
this.callback = callback;
diff --git a/app/assets/javascripts/pipeline_schedules/setup_pipeline_variable_list.js b/app/assets/javascripts/pipeline_schedules/setup_pipeline_variable_list.js
index 644efd10509..9e0e5cacb11 100644
--- a/app/assets/javascripts/pipeline_schedules/setup_pipeline_variable_list.js
+++ b/app/assets/javascripts/pipeline_schedules/setup_pipeline_variable_list.js
@@ -1,3 +1,5 @@
+import { convertPermissionToBoolean } from '../lib/utils/common_utils';
+
function insertRow($row) {
const $rowClone = $row.clone();
$rowClone.removeAttr('data-is-persisted');
@@ -6,7 +8,7 @@ function insertRow($row) {
}
function removeRow($row) {
- const isPersisted = gl.utils.convertPermissionToBoolean($row.attr('data-is-persisted'));
+ const isPersisted = convertPermissionToBoolean($row.attr('data-is-persisted'));
if (isPersisted) {
$row.hide();
diff --git a/app/assets/javascripts/pipelines.js b/app/assets/javascripts/pipelines.js
index 26a36ad54d1..07abe714367 100644
--- a/app/assets/javascripts/pipelines.js
+++ b/app/assets/javascripts/pipelines.js
@@ -1,4 +1,5 @@
import LinkedTabs from './lib/utils/bootstrap_linked_tabs';
+import { setCiStatusFavicon } from './lib/utils/common_utils';
export default class Pipelines {
constructor(options = {}) {
@@ -8,7 +9,7 @@ export default class Pipelines {
}
if (options.pipelineStatusUrl) {
- gl.utils.setCiStatusFavicon(options.pipelineStatusUrl);
+ setCiStatusFavicon(options.pipelineStatusUrl);
}
}
}
diff --git a/app/assets/javascripts/pipelines/components/pipelines.vue b/app/assets/javascripts/pipelines/components/pipelines.vue
index 5e6d6b2fbdc..4c53e2541fc 100644
--- a/app/assets/javascripts/pipelines/components/pipelines.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines.vue
@@ -4,6 +4,7 @@
import tablePagination from '../../vue_shared/components/table_pagination.vue';
import navigationTabs from './navigation_tabs.vue';
import navigationControls from './nav_controls.vue';
+ import { convertPermissionToBoolean, getParameterByName, setParamInURL } from '../../lib/utils/common_utils';
export default {
props: {
@@ -44,10 +45,10 @@
},
computed: {
canCreatePipelineParsed() {
- return gl.utils.convertPermissionToBoolean(this.canCreatePipeline);
+ return convertPermissionToBoolean(this.canCreatePipeline);
},
scope() {
- const scope = gl.utils.getParameterByName('scope');
+ const scope = getParameterByName('scope');
return scope === null ? 'all' : scope;
},
@@ -105,10 +106,10 @@
};
},
pageParameter() {
- return gl.utils.getParameterByName('page') || this.pagenum;
+ return getParameterByName('page') || this.pagenum;
},
scopeParameter() {
- return gl.utils.getParameterByName('scope') || this.apiScope;
+ return getParameterByName('scope') || this.apiScope;
},
},
created() {
@@ -122,7 +123,7 @@
* @param {Number} pageNumber desired page to go to.
*/
change(pageNumber) {
- const param = gl.utils.setParamInURL('page', pageNumber);
+ const param = setParamInURL('page', pageNumber);
gl.utils.visitUrl(param);
return param;
diff --git a/app/assets/javascripts/pipelines/stores/pipelines_store.js b/app/assets/javascripts/pipelines/stores/pipelines_store.js
index ffefe0192f2..651251d2623 100644
--- a/app/assets/javascripts/pipelines/stores/pipelines_store.js
+++ b/app/assets/javascripts/pipelines/stores/pipelines_store.js
@@ -1,3 +1,5 @@
+import { parseIntPagination, normalizeHeaders } from '../../lib/utils/common_utils';
+
export default class PipelinesStore {
constructor() {
this.state = {};
@@ -19,8 +21,8 @@ export default class PipelinesStore {
let paginationInfo;
if (Object.keys(pagination).length) {
- const normalizedHeaders = gl.utils.normalizeHeaders(pagination);
- paginationInfo = gl.utils.parseIntPagination(normalizedHeaders);
+ const normalizedHeaders = normalizeHeaders(pagination);
+ paginationInfo = parseIntPagination(normalizedHeaders);
} else {
paginationInfo = pagination;
}
diff --git a/app/assets/javascripts/todos.js b/app/assets/javascripts/todos.js
index a606852c22c..3dc0c3f8d43 100644
--- a/app/assets/javascripts/todos.js
+++ b/app/assets/javascripts/todos.js
@@ -1,6 +1,7 @@
/* eslint-disable class-methods-use-this, no-unneeded-ternary, quote-props */
import UsersSelect from './users_select';
+import { isMetaClick } from './lib/utils/common_utils';
export default class Todos {
constructor() {
@@ -141,7 +142,7 @@ export default class Todos {
return;
}
- if (gl.utils.isMetaClick(e)) {
+ if (isMetaClick(e)) {
const windowTarget = '_blank';
const selected = e.target;
e.stopPropagation();
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js
index 0042c48816f..fa4411e716b 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js
@@ -31,6 +31,7 @@ import {
SquashBeforeMerge,
notify,
} from './dependencies';
+import { setFavicon } from '../lib/utils/common_utils';
export default {
el: '#js-vue-mr-widget',
@@ -86,7 +87,7 @@ export default {
.then((res) => {
this.handleNotification(res);
this.mr.setData(res);
- this.setFavicon();
+ this.setFaviconHelper();
if (cb) {
cb.call(null, res);
@@ -115,9 +116,9 @@ export default {
immediateExecution: true,
});
},
- setFavicon() {
+ setFaviconHelper() {
if (this.mr.ciStatusFaviconPath) {
- gl.utils.setFavicon(this.mr.ciStatusFaviconPath);
+ setFavicon(this.mr.ciStatusFaviconPath);
}
},
fetchDeployments() {
@@ -193,7 +194,7 @@ export default {
});
},
handleMounted() {
- this.setFavicon();
+ this.setFaviconHelper();
this.initDeploymentsPolling();
},
},
diff --git a/changelogs/unreleased/37220-es-modules.yml b/changelogs/unreleased/37220-es-modules.yml
new file mode 100644
index 00000000000..de81fa9e74d
--- /dev/null
+++ b/changelogs/unreleased/37220-es-modules.yml
@@ -0,0 +1,5 @@
+---
+title: Exports common_utils utility functions as modules
+merge_request:
+author:
+type: other
diff --git a/spec/javascripts/environments/folder/environments_folder_view_spec.js b/spec/javascripts/environments/folder/environments_folder_view_spec.js
index fdaea5c0b0c..09916629bd1 100644
--- a/spec/javascripts/environments/folder/environments_folder_view_spec.js
+++ b/spec/javascripts/environments/folder/environments_folder_view_spec.js
@@ -14,6 +14,10 @@ describe('Environments Folder View', () => {
window.history.pushState({}, null, 'environments/folders/build');
});
+ afterEach(() => {
+ window.history.pushState({}, null, '');
+ });
+
let component;
describe('successfull request', () => {
diff --git a/spec/javascripts/lib/utils/common_utils_spec.js b/spec/javascripts/lib/utils/common_utils_spec.js
index 097de24f6ea..fd5b7d4e5da 100644
--- a/spec/javascripts/lib/utils/common_utils_spec.js
+++ b/spec/javascripts/lib/utils/common_utils_spec.js
@@ -18,26 +18,22 @@ describe('common_utils', () => {
});
describe('parseUrlPathname', () => {
- beforeEach(() => {
- spyOn(gl.utils, 'parseUrl').and.callFake(url => ({
- pathname: url,
- }));
- });
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('gl.utils.getUrlParamsArray', () => {
+ describe('getUrlParamsArray', () => {
it('should return params array', () => {
- expect(gl.utils.getUrlParamsArray() instanceof Array).toBe(true);
+ expect(commonUtils.getUrlParamsArray() instanceof Array).toBe(true);
});
it('should remove the question mark from the search params', () => {
- const paramsArray = gl.utils.getUrlParamsArray();
+ const paramsArray = commonUtils.getUrlParamsArray();
expect(paramsArray[0][0] !== '?').toBe(true);
});
@@ -45,7 +41,7 @@ describe('common_utils', () => {
history.pushState('', '', '?label_name%5B%5D=test');
expect(
- gl.utils.getUrlParamsArray()[0],
+ commonUtils.getUrlParamsArray()[0],
).toBe('label_name[]=test');
history.pushState('', '', '?');
@@ -90,7 +86,7 @@ describe('common_utils', () => {
});
});
- describe('gl.utils.setParamInURL', () => {
+ describe('setParamInURL', () => {
afterEach(() => {
window.history.pushState({}, null, '');
});
@@ -98,40 +94,40 @@ describe('common_utils', () => {
it('should return the parameter', () => {
window.history.replaceState({}, null, '');
- expect(gl.utils.setParamInURL('page', 156)).toBe('?page=156');
- expect(gl.utils.setParamInURL('page', '156')).toBe('?page=156');
+ expect(commonUtils.setParamInURL('page', 156)).toBe('?page=156');
+ expect(commonUtils.setParamInURL('page', '156')).toBe('?page=156');
});
it('should update the existing parameter when its a number', () => {
window.history.pushState({}, null, '?page=15');
- expect(gl.utils.setParamInURL('page', 16)).toBe('?page=16');
- expect(gl.utils.setParamInURL('page', '16')).toBe('?page=16');
- expect(gl.utils.setParamInURL('page', true)).toBe('?page=true');
+ expect(commonUtils.setParamInURL('page', 16)).toBe('?page=16');
+ expect(commonUtils.setParamInURL('page', '16')).toBe('?page=16');
+ expect(commonUtils.setParamInURL('page', true)).toBe('?page=true');
});
it('should update the existing parameter when its a string', () => {
window.history.pushState({}, null, '?scope=all');
- expect(gl.utils.setParamInURL('scope', 'finished')).toBe('?scope=finished');
+ expect(commonUtils.setParamInURL('scope', 'finished')).toBe('?scope=finished');
});
it('should update the existing parameter when more than one parameter exists', () => {
window.history.pushState({}, null, '?scope=all&page=15');
- expect(gl.utils.setParamInURL('scope', 'finished')).toBe('?scope=finished&page=15');
+ expect(commonUtils.setParamInURL('scope', 'finished')).toBe('?scope=finished&page=15');
});
it('should add a new parameter to the end of the existing ones', () => {
window.history.pushState({}, null, '?scope=all');
- expect(gl.utils.setParamInURL('page', 16)).toBe('?scope=all&page=16');
- expect(gl.utils.setParamInURL('page', '16')).toBe('?scope=all&page=16');
- expect(gl.utils.setParamInURL('page', true)).toBe('?scope=all&page=true');
+ expect(commonUtils.setParamInURL('page', 16)).toBe('?scope=all&page=16');
+ expect(commonUtils.setParamInURL('page', '16')).toBe('?scope=all&page=16');
+ expect(commonUtils.setParamInURL('page', true)).toBe('?scope=all&page=true');
});
});
- describe('gl.utils.getParameterByName', () => {
+ describe('getParameterByName', () => {
beforeEach(() => {
window.history.pushState({}, null, '?scope=all&p=2');
});
@@ -141,33 +137,33 @@ describe('common_utils', () => {
});
it('should return valid parameter', () => {
- const value = gl.utils.getParameterByName('scope');
- expect(gl.utils.getParameterByName('p')).toEqual('2');
+ const value = commonUtils.getParameterByName('scope');
+ expect(commonUtils.getParameterByName('p')).toEqual('2');
expect(value).toBe('all');
});
it('should return invalid parameter', () => {
- const value = gl.utils.getParameterByName('fakeParameter');
+ const value = commonUtils.getParameterByName('fakeParameter');
expect(value).toBe(null);
});
it('should return valid paramentes if URL is provided', () => {
- let value = gl.utils.getParameterByName('foo', 'http://cocteau.twins/?foo=bar');
+ let value = commonUtils.getParameterByName('foo', 'http://cocteau.twins/?foo=bar');
expect(value).toBe('bar');
- value = gl.utils.getParameterByName('manan', 'http://cocteau.twins/?foo=bar&manan=canchu');
+ value = commonUtils.getParameterByName('manan', 'http://cocteau.twins/?foo=bar&manan=canchu');
expect(value).toBe('canchu');
});
});
- describe('gl.utils.normalizedHeaders', () => {
+ describe('normalizedHeaders', () => {
it('should upperCase all the header keys to keep them consistent', () => {
const apiHeaders = {
'X-Something-Workhorse': { workhorse: 'ok' },
'x-something-nginx': { nginx: 'ok' },
};
- const normalized = gl.utils.normalizeHeaders(apiHeaders);
+ const normalized = commonUtils.normalizeHeaders(apiHeaders);
const WORKHORSE = 'X-SOMETHING-WORKHORSE';
const NGINX = 'X-SOMETHING-NGINX';
@@ -177,14 +173,11 @@ describe('common_utils', () => {
});
});
- describe('gl.utils.normalizeCRLFHeaders', () => {
+ describe('normalizeCRLFHeaders', () => {
beforeEach(function () {
this.CLRFHeaders = 'a-header: a-value\nAnother-Header: ANOTHER-VALUE\nLaSt-HeAdEr: last-VALUE';
-
spyOn(String.prototype, 'split').and.callThrough();
- spyOn(gl.utils, 'normalizeHeaders').and.callThrough();
-
- this.normalizeCRLFHeaders = gl.utils.normalizeCRLFHeaders(this.CLRFHeaders);
+ this.normalizeCRLFHeaders = commonUtils.normalizeCRLFHeaders(this.CLRFHeaders);
});
it('should split by newline', function () {
@@ -195,10 +188,6 @@ describe('common_utils', () => {
expect(String.prototype.split.calls.allArgs().filter(args => args[0] === ': ').length).toBe(3);
});
- it('should call gl.utils.normalizeHeaders with a parsed headers object', function () {
- expect(gl.utils.normalizeHeaders).toHaveBeenCalledWith(jasmine.any(Object));
- });
-
it('should return a normalized headers object', function () {
expect(this.normalizeCRLFHeaders).toEqual({
'A-HEADER': 'a-value',
@@ -208,7 +197,7 @@ describe('common_utils', () => {
});
});
- describe('gl.utils.parseIntPagination', () => {
+ describe('parseIntPagination', () => {
it('should parse to integers all string values and return pagination object', () => {
const pagination = {
'X-PER-PAGE': 10,
@@ -228,11 +217,11 @@ describe('common_utils', () => {
previousPage: 1,
};
- expect(gl.utils.parseIntPagination(pagination)).toEqual(expectedPagination);
+ expect(commonUtils.parseIntPagination(pagination)).toEqual(expectedPagination);
});
});
- describe('gl.utils.isMetaClick', () => {
+ describe('isMetaClick', () => {
it('should identify meta click on Windows/Linux', () => {
const e = {
metaKey: false,
@@ -240,7 +229,7 @@ describe('common_utils', () => {
which: 1,
};
- expect(gl.utils.isMetaClick(e)).toBe(true);
+ expect(commonUtils.isMetaClick(e)).toBe(true);
});
it('should identify meta click on macOS', () => {
@@ -250,7 +239,7 @@ describe('common_utils', () => {
which: 1,
};
- expect(gl.utils.isMetaClick(e)).toBe(true);
+ expect(commonUtils.isMetaClick(e)).toBe(true);
});
it('should identify as meta click on middle-click or Mouse-wheel click', () => {
@@ -260,7 +249,14 @@ describe('common_utils', () => {
which: 2,
};
- expect(gl.utils.isMetaClick(e)).toBe(true);
+ expect(commonUtils.isMetaClick(e)).toBe(true);
+ });
+ });
+
+ describe('convertPermissionToBoolean', () => {
+ it('should convert a boolean in a string to a boolean', () => {
+ expect(commonUtils.convertPermissionToBoolean('true')).toEqual(true);
+ expect(commonUtils.convertPermissionToBoolean('false')).toEqual(false);
});
});
@@ -333,53 +329,76 @@ describe('common_utils', () => {
});
});
- describe('gl.utils.setFavicon', () => {
+ describe('setFavicon', () => {
+ beforeEach(() => {
+ const favicon = document.createElement('link');
+ favicon.setAttribute('id', 'favicon');
+ favicon.setAttribute('href', 'default/favicon');
+ document.body.appendChild(favicon);
+ });
+
+ afterEach(() => {
+ document.body.removeChild(document.getElementById('favicon'));
+ });
it('should set page favicon to provided favicon', () => {
const faviconPath = '//custom_favicon';
- const fakeLink = {
- setAttribute() {},
- };
+ commonUtils.setFavicon(faviconPath);
- spyOn(window.document, 'getElementById').and.callFake(() => fakeLink);
- spyOn(fakeLink, 'setAttribute').and.callFake((attr, val) => {
- expect(attr).toEqual('href');
- expect(val.indexOf(faviconPath) > -1).toBe(true);
- });
- gl.utils.setFavicon(faviconPath);
+ expect(document.getElementById('favicon').getAttribute('href')).toEqual(faviconPath);
});
});
- describe('gl.utils.resetFavicon', () => {
+ describe('resetFavicon', () => {
+ beforeEach(() => {
+ const favicon = document.createElement('link');
+ favicon.setAttribute('id', 'favicon');
+ favicon.setAttribute('href', 'default/favicon');
+ document.body.appendChild(favicon);
+ });
+
+ afterEach(() => {
+ document.body.removeChild(document.getElementById('favicon'));
+ });
+
it('should reset page favicon to tanuki', () => {
- const fakeLink = {
- setAttribute() {},
- };
+ commonUtils.resetFavicon();
+ expect(document.getElementById('favicon').getAttribute('href')).toEqual('default/favicon');
+ });
+ });
+
+ describe('setCiStatusFavicon', () => {
+ const BUILD_URL = `${gl.TEST_HOST}/frontend-fixtures/builds-project/-/jobs/1/status.json`;
+
+ beforeEach(() => {
+ const favicon = document.createElement('link');
+ favicon.setAttribute('id', 'favicon');
+ document.body.appendChild(favicon);
+ });
- spyOn(window.document, 'getElementById').and.callFake(() => fakeLink);
- spyOn(fakeLink, 'setAttribute').and.callFake((attr, val) => {
- expect(attr).toEqual('href');
- expect(val).toMatch(/favicon/);
+ afterEach(() => {
+ document.body.removeChild(document.getElementById('favicon'));
+ });
+
+ it('should reset favicon in case of error', () => {
+ const favicon = document.getElementById('favicon');
+ spyOn($, 'ajax').and.callFake(function (options) {
+ options.error();
+ expect(favicon.getAttribute('href')).toEqual('null');
});
- gl.utils.resetFavicon();
+
+ commonUtils.setCiStatusFavicon(BUILD_URL);
});
- });
- describe('gl.utils.setCiStatusFavicon', () => {
it('should set page favicon to CI status favicon based on provided status', () => {
- const BUILD_URL = `${gl.TEST_HOST}/frontend-fixtures/builds-project/-/jobs/1/status.json`;
const FAVICON_PATH = '//icon_status_success';
- const spySetFavicon = spyOn(gl.utils, 'setFavicon').and.stub();
- const spyResetFavicon = spyOn(gl.utils, 'resetFavicon').and.stub();
+ const favicon = document.getElementById('favicon');
+
spyOn($, 'ajax').and.callFake(function (options) {
options.success({ favicon: FAVICON_PATH });
- expect(spySetFavicon).toHaveBeenCalledWith(FAVICON_PATH);
- options.success();
- expect(spyResetFavicon).toHaveBeenCalled();
- options.error();
- expect(spyResetFavicon).toHaveBeenCalled();
+ expect(favicon.getAttribute('href')).toEqual(FAVICON_PATH);
});
- gl.utils.setCiStatusFavicon(BUILD_URL);
+ commonUtils.setCiStatusFavicon(BUILD_URL);
});
});
diff --git a/spec/javascripts/merge_request_tabs_spec.js b/spec/javascripts/merge_request_tabs_spec.js
index 8830a2d29e5..eadab738376 100644
--- a/spec/javascripts/merge_request_tabs_spec.js
+++ b/spec/javascripts/merge_request_tabs_spec.js
@@ -78,8 +78,9 @@ import 'vendor/jquery.scrollTo';
});
describe('meta click', () => {
+ let metakeyEvent;
beforeEach(function () {
- spyOn(gl.utils, 'isMetaClick').and.returnValue(true);
+ metakeyEvent = $.Event('click', { keyCode: 91, ctrlKey: true });
});
it('opens page when commits link is clicked', function () {
@@ -89,7 +90,7 @@ import 'vendor/jquery.scrollTo';
});
this.class.bindEvents();
- document.querySelector('.merge-request-tabs .commits-tab a').click();
+ $('.merge-request-tabs .commits-tab a').trigger(metakeyEvent);
});
it('opens page when commits badge is clicked', function () {
@@ -99,7 +100,7 @@ import 'vendor/jquery.scrollTo';
});
this.class.bindEvents();
- document.querySelector('.merge-request-tabs .commits-tab a .badge').click();
+ $('.merge-request-tabs .commits-tab a .badge').trigger(metakeyEvent);
});
});
diff --git a/spec/javascripts/todos_spec.js b/spec/javascripts/todos_spec.js
index fd492159081..207ad2d6f97 100644
--- a/spec/javascripts/todos_spec.js
+++ b/spec/javascripts/todos_spec.js
@@ -26,9 +26,10 @@ describe('Todos', () => {
describe('meta click', () => {
let visitUrlSpy;
+ let metakeyEvent;
beforeEach(() => {
- spyOn(gl.utils, 'isMetaClick').and.returnValue(true);
+ metakeyEvent = $.Event('click', { keyCode: 91, ctrlKey: true });
visitUrlSpy = spyOn(gl.utils, 'visitUrl').and.callFake(() => {});
});
@@ -41,7 +42,7 @@ describe('Todos', () => {
done();
});
- todoItem.click();
+ $('.todos-list .todo').trigger(metakeyEvent);
expect(visitUrlSpy).not.toHaveBeenCalled();
});
diff --git a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
index 669ee248bf1..baa40516d28 100644
--- a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
+++ b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
@@ -232,29 +232,42 @@ describe('mrWidgetOptions', () => {
describe('handleMounted', () => {
it('should call required methods to do the initial kick-off', () => {
spyOn(vm, 'initDeploymentsPolling');
- spyOn(vm, 'setFavicon');
+ spyOn(vm, 'setFaviconHelper');
vm.handleMounted();
- expect(vm.setFavicon).toHaveBeenCalled();
+ expect(vm.setFaviconHelper).toHaveBeenCalled();
expect(vm.initDeploymentsPolling).toHaveBeenCalled();
});
});
describe('setFavicon', () => {
+ let faviconElement;
+
+ beforeEach(() => {
+ const favicon = document.createElement('link');
+ favicon.setAttribute('id', 'favicon');
+ favicon.setAttribute('href', 'default/favicon');
+ document.body.appendChild(favicon);
+
+ faviconElement = document.body.getElementById('favicon');
+ });
+
+ afterEach(() => {
+ document.body.removeChild(document.getElementById('favicon'));
+ });
+
it('should call setFavicon method', () => {
- spyOn(gl.utils, 'setFavicon');
vm.setFavicon();
- expect(gl.utils.setFavicon).toHaveBeenCalledWith(vm.mr.ciStatusFaviconPath);
+ expect(faviconElement.getAttribute('href')).toEqual(vm.mr.ciStatusFaviconPath);
});
it('should not call setFavicon when there is no ciStatusFaviconPath', () => {
- spyOn(gl.utils, 'setFavicon');
vm.mr.ciStatusFaviconPath = null;
- vm.setFavicon();
+ vm.setFaviconHelper();
- expect(gl.utils.setFavicon).not.toHaveBeenCalled();
+ expect(faviconElement.getAttribute('href')).toEqual(null);
});
});