Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-02-27 03:09:19 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-02-27 03:09:19 +0300
commit0a0e82d1440b06650e5fc524168b1f50a8feec68 (patch)
treec2202560fb250008cf4109e99537b10604faf01b /spec/javascripts
parentf82d5dcab7c3d9a672abc827c92f86887b683a7d (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/javascripts')
-rw-r--r--spec/javascripts/lib/utils/browser_spec.js175
-rw-r--r--spec/javascripts/lib/utils/common_utils_spec.js981
-rw-r--r--spec/javascripts/lib/utils/mock_data.js9
-rw-r--r--spec/javascripts/monitoring/components/dashboard_resize_spec.js2
4 files changed, 177 insertions, 990 deletions
diff --git a/spec/javascripts/lib/utils/browser_spec.js b/spec/javascripts/lib/utils/browser_spec.js
new file mode 100644
index 00000000000..6b1074a3b4f
--- /dev/null
+++ b/spec/javascripts/lib/utils/browser_spec.js
@@ -0,0 +1,175 @@
+/**
+ * This file should only contain browser specific specs.
+ * If you need to add or update a spec, please see spec/frontend/lib/utils/*.js
+ * https://gitlab.com/gitlab-org/gitlab/issues/194242#note_292137135
+ * https://gitlab.com/groups/gitlab-org/-/epics/895#what-if-theres-a-karma-spec-which-is-simply-unmovable-to-jest-ie-it-is-dependent-on-a-running-browser-environment
+ */
+
+import MockAdapter from 'axios-mock-adapter';
+import { GlBreakpointInstance as breakpointInstance } from '@gitlab/ui/dist/utils';
+import axios from '~/lib/utils/axios_utils';
+import * as commonUtils from '~/lib/utils/common_utils';
+import { faviconDataUrl, overlayDataUrl, faviconWithOverlayDataUrl } from './mock_data';
+
+const PIXEL_TOLERANCE = 0.2;
+
+/**
+ * Loads a data URL as the src of an
+ * {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image|Image}
+ * and resolves to that Image once loaded.
+ *
+ * @param url
+ * @returns {Promise}
+ */
+const urlToImage = url =>
+ new Promise(resolve => {
+ const img = new Image();
+ img.onload = function() {
+ resolve(img);
+ };
+ img.src = url;
+ });
+
+describe('common_utils browser specific specs', () => {
+ describe('contentTop', () => {
+ it('does not add height for fileTitle or compareVersionsHeader if screen is too small', () => {
+ spyOn(breakpointInstance, 'isDesktop').and.returnValue(false);
+
+ setFixtures(`
+ <div class="diff-file file-title-flex-parent">
+ blah blah blah
+ </div>
+ <div class="mr-version-controls">
+ more blah blah blah
+ </div>
+ `);
+
+ expect(commonUtils.contentTop()).toBe(0);
+ });
+
+ it('adds height for fileTitle and compareVersionsHeader screen is large enough', () => {
+ spyOn(breakpointInstance, 'isDesktop').and.returnValue(true);
+
+ setFixtures(`
+ <div class="diff-file file-title-flex-parent">
+ blah blah blah
+ </div>
+ <div class="mr-version-controls">
+ more blah blah blah
+ </div>
+ `);
+
+ expect(commonUtils.contentTop()).toBe(18);
+ });
+ });
+
+ describe('createOverlayIcon', () => {
+ it('should return the favicon with the overlay', done => {
+ commonUtils
+ .createOverlayIcon(faviconDataUrl, overlayDataUrl)
+ .then(url => Promise.all([urlToImage(url), urlToImage(faviconWithOverlayDataUrl)]))
+ .then(([actual, expected]) => {
+ expect(actual).toImageDiffEqual(expected, PIXEL_TOLERANCE);
+ done();
+ })
+ .catch(done.fail);
+ });
+ });
+
+ describe('setFaviconOverlay', () => {
+ beforeEach(() => {
+ const favicon = document.createElement('link');
+ favicon.setAttribute('id', 'favicon');
+ favicon.setAttribute('data-original-href', faviconDataUrl);
+ document.body.appendChild(favicon);
+ });
+
+ afterEach(() => {
+ document.body.removeChild(document.getElementById('favicon'));
+ });
+
+ it('should set page favicon to provided favicon overlay', done => {
+ commonUtils
+ .setFaviconOverlay(overlayDataUrl)
+ .then(() => document.getElementById('favicon').getAttribute('href'))
+ .then(url => Promise.all([urlToImage(url), urlToImage(faviconWithOverlayDataUrl)]))
+ .then(([actual, expected]) => {
+ expect(actual).toImageDiffEqual(expected, PIXEL_TOLERANCE);
+ done();
+ })
+ .catch(done.fail);
+ });
+ });
+
+ describe('setCiStatusFavicon', () => {
+ const BUILD_URL = `${gl.TEST_HOST}/frontend-fixtures/builds-project/-/jobs/1/status.json`;
+ let mock;
+
+ beforeEach(() => {
+ const favicon = document.createElement('link');
+ favicon.setAttribute('id', 'favicon');
+ favicon.setAttribute('href', 'null');
+ favicon.setAttribute('data-original-href', faviconDataUrl);
+ document.body.appendChild(favicon);
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ document.body.removeChild(document.getElementById('favicon'));
+ });
+
+ it('should reset favicon in case of error', done => {
+ mock.onGet(BUILD_URL).replyOnce(500);
+
+ commonUtils.setCiStatusFavicon(BUILD_URL).catch(() => {
+ const favicon = document.getElementById('favicon');
+
+ expect(favicon.getAttribute('href')).toEqual(faviconDataUrl);
+ done();
+ });
+ });
+
+ it('should set page favicon to CI status favicon based on provided status', done => {
+ mock.onGet(BUILD_URL).reply(200, {
+ favicon: overlayDataUrl,
+ });
+
+ commonUtils
+ .setCiStatusFavicon(BUILD_URL)
+ .then(() => document.getElementById('favicon').getAttribute('href'))
+ .then(url => Promise.all([urlToImage(url), urlToImage(faviconWithOverlayDataUrl)]))
+ .then(([actual, expected]) => {
+ expect(actual).toImageDiffEqual(expected, PIXEL_TOLERANCE);
+ done();
+ })
+ .catch(done.fail);
+ });
+ });
+
+ describe('isInViewport', () => {
+ let el;
+
+ beforeEach(() => {
+ el = document.createElement('div');
+ });
+
+ afterEach(() => {
+ document.body.removeChild(el);
+ });
+
+ it('returns true when provided `el` is in viewport', () => {
+ el.setAttribute('style', `position: absolute; right: ${window.innerWidth + 0.2};`);
+ document.body.appendChild(el);
+
+ expect(commonUtils.isInViewport(el)).toBe(true);
+ });
+
+ it('returns false when provided `el` is not in viewport', () => {
+ el.setAttribute('style', 'position: absolute; top: -1000px; left: -1000px;');
+ document.body.appendChild(el);
+
+ expect(commonUtils.isInViewport(el)).toBe(false);
+ });
+ });
+});
diff --git a/spec/javascripts/lib/utils/common_utils_spec.js b/spec/javascripts/lib/utils/common_utils_spec.js
deleted file mode 100644
index 504d4a3e01a..00000000000
--- a/spec/javascripts/lib/utils/common_utils_spec.js
+++ /dev/null
@@ -1,981 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import { GlBreakpointInstance as breakpointInstance } from '@gitlab/ui/dist/utils';
-import axios from '~/lib/utils/axios_utils';
-import * as commonUtils from '~/lib/utils/common_utils';
-import { faviconDataUrl, overlayDataUrl, faviconWithOverlayDataUrl } from './mock_data';
-
-const PIXEL_TOLERANCE = 0.2;
-
-/**
- * Loads a data URL as the src of an
- * {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image|Image}
- * and resolves to that Image once loaded.
- *
- * @param url
- * @returns {Promise}
- */
-const urlToImage = url =>
- new Promise(resolve => {
- const img = new Image();
- img.onload = function() {
- resolve(img);
- };
- img.src = url;
- });
-
-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('urlParamsToArray', () => {
- it('returns empty array for empty querystring', () => {
- expect(commonUtils.urlParamsToArray('')).toEqual([]);
- });
-
- it('should decode params', () => {
- expect(commonUtils.urlParamsToArray('?label_name%5B%5D=test')[0]).toBe('label_name[]=test');
- });
-
- it('should remove the question mark from the search params', () => {
- const paramsArray = commonUtils.urlParamsToArray('?test=thing');
-
- expect(paramsArray[0][0]).not.toBe('?');
- });
- });
-
- describe('urlParamsToObject', () => {
- it('parses path for label with trailing +', () => {
- expect(commonUtils.urlParamsToObject('label_name[]=label%2B', {})).toEqual({
- label_name: ['label+'],
- });
- });
-
- it('parses path for milestone with trailing +', () => {
- expect(commonUtils.urlParamsToObject('milestone_title=A%2B', {})).toEqual({
- milestone_title: 'A+',
- });
- });
-
- it('parses path for search terms with spaces', () => {
- expect(commonUtils.urlParamsToObject('search=two+words', {})).toEqual({
- search: 'two words',
- });
- });
- });
-
- describe('handleLocationHash', () => {
- beforeEach(() => {
- spyOn(window.document, 'getElementById').and.callThrough();
- jasmine.clock().install();
- });
-
- afterEach(() => {
- window.history.pushState({}, null, '');
- jasmine.clock().uninstall();
- });
-
- function expectGetElementIdToHaveBeenCalledWith(elementId) {
- expect(window.document.getElementById).toHaveBeenCalledWith(elementId);
- }
-
- it('decodes hash parameter', () => {
- window.history.pushState({}, null, '#random-hash');
- commonUtils.handleLocationHash();
-
- expectGetElementIdToHaveBeenCalledWith('random-hash');
- expectGetElementIdToHaveBeenCalledWith('user-content-random-hash');
- });
-
- it('decodes cyrillic hash parameter', () => {
- window.history.pushState({}, null, '#definição');
- commonUtils.handleLocationHash();
-
- expectGetElementIdToHaveBeenCalledWith('definição');
- expectGetElementIdToHaveBeenCalledWith('user-content-definição');
- });
-
- it('decodes encoded cyrillic hash parameter', () => {
- window.history.pushState({}, null, '#defini%C3%A7%C3%A3o');
- commonUtils.handleLocationHash();
-
- expectGetElementIdToHaveBeenCalledWith('definição');
- expectGetElementIdToHaveBeenCalledWith('user-content-definição');
- });
-
- it('scrolls element into view', () => {
- document.body.innerHTML += `
- <div id="parent">
- <div style="height: 2000px;"></div>
- <div id="test" style="height: 2000px;"></div>
- </div>
- `;
-
- window.history.pushState({}, null, '#test');
- commonUtils.handleLocationHash();
-
- expectGetElementIdToHaveBeenCalledWith('test');
-
- expect(window.scrollY).toBe(document.getElementById('test').offsetTop);
-
- document.getElementById('parent').remove();
- });
-
- it('scrolls user content element into view', () => {
- document.body.innerHTML += `
- <div id="parent">
- <div style="height: 2000px;"></div>
- <div id="user-content-test" style="height: 2000px;"></div>
- </div>
- `;
-
- window.history.pushState({}, null, '#test');
- commonUtils.handleLocationHash();
-
- expectGetElementIdToHaveBeenCalledWith('test');
- expectGetElementIdToHaveBeenCalledWith('user-content-test');
-
- expect(window.scrollY).toBe(document.getElementById('user-content-test').offsetTop);
-
- document.getElementById('parent').remove();
- });
-
- it('scrolls to element with offset from navbar', () => {
- spyOn(window, 'scrollBy').and.callThrough();
- document.body.innerHTML += `
- <div id="parent">
- <div class="navbar-gitlab" style="position: fixed; top: 0; height: 50px;"></div>
- <div style="height: 2000px; margin-top: 50px;"></div>
- <div id="user-content-test" style="height: 2000px;"></div>
- </div>
- `;
-
- window.history.pushState({}, null, '#test');
- commonUtils.handleLocationHash();
- jasmine.clock().tick(1);
-
- expectGetElementIdToHaveBeenCalledWith('test');
- expectGetElementIdToHaveBeenCalledWith('user-content-test');
-
- expect(window.scrollY).toBe(document.getElementById('user-content-test').offsetTop - 50);
- expect(window.scrollBy).toHaveBeenCalledWith(0, -50);
-
- document.getElementById('parent').remove();
- });
- });
-
- describe('historyPushState', () => {
- afterEach(() => {
- window.history.replaceState({}, null, null);
- });
-
- it('should call pushState with the correct path', () => {
- spyOn(window.history, 'pushState');
-
- commonUtils.historyPushState('newpath?page=2');
-
- expect(window.history.pushState).toHaveBeenCalled();
- expect(window.history.pushState.calls.allArgs()[0][2]).toContain('newpath?page=2');
- });
- });
-
- describe('parseQueryStringIntoObject', () => {
- it('should return object with query parameters', () => {
- expect(commonUtils.parseQueryStringIntoObject('scope=all&page=2')).toEqual({
- scope: 'all',
- page: '2',
- });
-
- expect(commonUtils.parseQueryStringIntoObject('scope=all')).toEqual({ scope: 'all' });
- expect(commonUtils.parseQueryStringIntoObject()).toEqual({});
- });
- });
-
- describe('objectToQueryString', () => {
- it('returns empty string when `param` is undefined, null or empty string', () => {
- expect(commonUtils.objectToQueryString()).toBe('');
- expect(commonUtils.objectToQueryString('')).toBe('');
- });
-
- it('returns query string with values of `params`', () => {
- const singleQueryParams = { foo: true };
- const multipleQueryParams = { foo: true, bar: true };
-
- expect(commonUtils.objectToQueryString(singleQueryParams)).toBe('foo=true');
- expect(commonUtils.objectToQueryString(multipleQueryParams)).toBe('foo=true&bar=true');
- });
- });
-
- describe('buildUrlWithCurrentLocation', () => {
- it('should build an url with current location and given parameters', () => {
- expect(commonUtils.buildUrlWithCurrentLocation()).toEqual(window.location.pathname);
- expect(commonUtils.buildUrlWithCurrentLocation('?page=2')).toEqual(
- `${window.location.pathname}?page=2`,
- );
- });
- });
-
- describe('debounceByAnimationFrame', () => {
- it('debounces a function to allow a maximum of one call per animation frame', done => {
- const spy = jasmine.createSpy('spy');
- const debouncedSpy = commonUtils.debounceByAnimationFrame(spy);
- window.requestAnimationFrame(() => {
- debouncedSpy();
- debouncedSpy();
- window.requestAnimationFrame(() => {
- expect(spy).toHaveBeenCalledTimes(1);
- done();
- });
- });
- });
- });
-
- describe('getParameterByName', () => {
- beforeEach(() => {
- window.history.pushState({}, null, '?scope=all&p=2');
- });
-
- afterEach(() => {
- window.history.replaceState({}, null, null);
- });
-
- it('should return valid parameter', () => {
- const value = commonUtils.getParameterByName('scope');
-
- expect(commonUtils.getParameterByName('p')).toEqual('2');
- expect(value).toBe('all');
- });
-
- it('should return invalid parameter', () => {
- const value = commonUtils.getParameterByName('fakeParameter');
-
- expect(value).toBe(null);
- });
-
- it('should return valid paramentes if URL is provided', () => {
- let value = commonUtils.getParameterByName('foo', 'http://cocteau.twins/?foo=bar');
-
- expect(value).toBe('bar');
-
- value = commonUtils.getParameterByName('manan', 'http://cocteau.twins/?foo=bar&manan=canchu');
-
- expect(value).toBe('canchu');
- });
- });
-
- 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 = commonUtils.normalizeHeaders(apiHeaders);
-
- const WORKHORSE = 'X-SOMETHING-WORKHORSE';
- const NGINX = 'X-SOMETHING-NGINX';
-
- expect(normalized[WORKHORSE].workhorse).toBe('ok');
- expect(normalized[NGINX].nginx).toBe('ok');
- });
- });
-
- describe('normalizeCRLFHeaders', () => {
- beforeEach(function() {
- this.CLRFHeaders =
- 'a-header: a-value\nAnother-Header: ANOTHER-VALUE\nLaSt-HeAdEr: last-VALUE';
- spyOn(String.prototype, 'split').and.callThrough();
- this.normalizeCRLFHeaders = commonUtils.normalizeCRLFHeaders(this.CLRFHeaders);
- });
-
- it('should split by newline', function() {
- expect(String.prototype.split).toHaveBeenCalledWith('\n');
- });
-
- it('should split by colon+space for each header', function() {
- expect(String.prototype.split.calls.allArgs().filter(args => args[0] === ': ').length).toBe(
- 3,
- );
- });
-
- it('should return a normalized headers object', function() {
- expect(this.normalizeCRLFHeaders).toEqual({
- 'A-HEADER': 'a-value',
- 'ANOTHER-HEADER': 'ANOTHER-VALUE',
- 'LAST-HEADER': 'last-VALUE',
- });
- });
- });
-
- describe('parseIntPagination', () => {
- it('should parse to integers all string values and return pagination object', () => {
- const pagination = {
- 'X-PER-PAGE': 10,
- 'X-PAGE': 2,
- 'X-TOTAL': 30,
- 'X-TOTAL-PAGES': 3,
- 'X-NEXT-PAGE': 3,
- 'X-PREV-PAGE': 1,
- };
-
- const expectedPagination = {
- perPage: 10,
- page: 2,
- total: 30,
- totalPages: 3,
- nextPage: 3,
- previousPage: 1,
- };
-
- expect(commonUtils.parseIntPagination(pagination)).toEqual(expectedPagination);
- });
- });
-
- describe('isMetaClick', () => {
- it('should identify meta click on Windows/Linux', () => {
- const e = {
- metaKey: false,
- ctrlKey: true,
- which: 1,
- };
-
- expect(commonUtils.isMetaClick(e)).toBe(true);
- });
-
- it('should identify meta click on macOS', () => {
- const e = {
- metaKey: true,
- ctrlKey: false,
- which: 1,
- };
-
- expect(commonUtils.isMetaClick(e)).toBe(true);
- });
-
- it('should identify as meta click on middle-click or Mouse-wheel click', () => {
- const e = {
- metaKey: false,
- ctrlKey: false,
- which: 2,
- };
-
- expect(commonUtils.isMetaClick(e)).toBe(true);
- });
- });
-
- describe('contentTop', () => {
- it('does not add height for fileTitle or compareVersionsHeader if screen is too small', () => {
- spyOn(breakpointInstance, 'isDesktop').and.returnValue(false);
-
- setFixtures(`
- <div class="diff-file file-title-flex-parent">
- blah blah blah
- </div>
- <div class="mr-version-controls">
- more blah blah blah
- </div>
- `);
-
- expect(commonUtils.contentTop()).toBe(0);
- });
-
- it('adds height for fileTitle and compareVersionsHeader screen is large enough', () => {
- spyOn(breakpointInstance, 'isDesktop').and.returnValue(true);
-
- setFixtures(`
- <div class="diff-file file-title-flex-parent">
- blah blah blah
- </div>
- <div class="mr-version-controls">
- more blah blah blah
- </div>
- `);
-
- expect(commonUtils.contentTop()).toBe(18);
- });
- });
-
- describe('parseBoolean', () => {
- const { parseBoolean } = commonUtils;
-
- it('returns true for "true"', () => {
- expect(parseBoolean('true')).toEqual(true);
- });
-
- it('returns false for "false"', () => {
- expect(parseBoolean('false')).toEqual(false);
- });
-
- it('returns false for "something"', () => {
- expect(parseBoolean('something')).toEqual(false);
- });
-
- it('returns false for null', () => {
- expect(parseBoolean(null)).toEqual(false);
- });
-
- it('is idempotent', () => {
- const input = ['true', 'false', 'something', null];
- input.forEach(value => {
- const result = parseBoolean(value);
-
- expect(parseBoolean(result)).toBe(result);
- });
- });
- });
-
- describe('backOff', () => {
- beforeEach(() => {
- // shortcut our timeouts otherwise these tests will take a long time to finish
- const origSetTimeout = window.setTimeout;
- spyOn(window, 'setTimeout').and.callFake(cb => origSetTimeout(cb, 0));
- });
-
- it('solves the promise from the callback', done => {
- const expectedResponseValue = 'Success!';
- commonUtils
- .backOff((next, stop) =>
- new Promise(resolve => {
- resolve(expectedResponseValue);
- })
- .then(resp => {
- stop(resp);
- })
- .catch(done.fail),
- )
- .then(respBackoff => {
- expect(respBackoff).toBe(expectedResponseValue);
- done();
- })
- .catch(done.fail);
- });
-
- it('catches the rejected promise from the callback ', done => {
- const errorMessage = 'Mistakes were made!';
- commonUtils
- .backOff((next, stop) => {
- new Promise((resolve, reject) => {
- reject(new Error(errorMessage));
- })
- .then(resp => {
- stop(resp);
- })
- .catch(err => stop(err));
- })
- .catch(errBackoffResp => {
- expect(errBackoffResp instanceof Error).toBe(true);
- expect(errBackoffResp.message).toBe(errorMessage);
- done();
- });
- });
-
- it('solves the promise correctly after retrying a third time', done => {
- let numberOfCalls = 1;
- const expectedResponseValue = 'Success!';
- commonUtils
- .backOff((next, stop) =>
- Promise.resolve(expectedResponseValue)
- .then(resp => {
- if (numberOfCalls < 3) {
- numberOfCalls += 1;
- next();
- } else {
- stop(resp);
- }
- })
- .catch(done.fail),
- )
- .then(respBackoff => {
- const timeouts = window.setTimeout.calls.allArgs().map(([, timeout]) => timeout);
-
- expect(timeouts).toEqual([2000, 4000]);
- expect(respBackoff).toBe(expectedResponseValue);
- done();
- })
- .catch(done.fail);
- });
-
- it('rejects the backOff promise after timing out', done => {
- commonUtils
- .backOff(next => next(), 64000)
- .catch(errBackoffResp => {
- const timeouts = window.setTimeout.calls.allArgs().map(([, timeout]) => timeout);
-
- expect(timeouts).toEqual([2000, 4000, 8000, 16000, 32000, 32000]);
- expect(errBackoffResp instanceof Error).toBe(true);
- expect(errBackoffResp.message).toBe('BACKOFF_TIMEOUT');
- done();
- });
- });
- });
-
- describe('setFavicon', () => {
- beforeEach(() => {
- const favicon = document.createElement('link');
- favicon.setAttribute('id', 'favicon');
- favicon.setAttribute('href', 'default/favicon');
- favicon.setAttribute('data-default-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';
- commonUtils.setFavicon(faviconPath);
-
- expect(document.getElementById('favicon').getAttribute('href')).toEqual(faviconPath);
- });
- });
-
- describe('resetFavicon', () => {
- beforeEach(() => {
- const favicon = document.createElement('link');
- favicon.setAttribute('id', 'favicon');
- favicon.setAttribute('data-original-href', 'default/favicon');
- document.body.appendChild(favicon);
- });
-
- afterEach(() => {
- document.body.removeChild(document.getElementById('favicon'));
- });
-
- it('should reset page favicon to the default icon', () => {
- const favicon = document.getElementById('favicon');
- favicon.setAttribute('href', 'new/favicon');
- commonUtils.resetFavicon();
-
- expect(document.getElementById('favicon').getAttribute('href')).toEqual('default/favicon');
- });
- });
-
- describe('createOverlayIcon', () => {
- it('should return the favicon with the overlay', done => {
- commonUtils
- .createOverlayIcon(faviconDataUrl, overlayDataUrl)
- .then(url => Promise.all([urlToImage(url), urlToImage(faviconWithOverlayDataUrl)]))
- .then(([actual, expected]) => {
- expect(actual).toImageDiffEqual(expected, PIXEL_TOLERANCE);
- done();
- })
- .catch(done.fail);
- });
- });
-
- describe('setFaviconOverlay', () => {
- beforeEach(() => {
- const favicon = document.createElement('link');
- favicon.setAttribute('id', 'favicon');
- favicon.setAttribute('data-original-href', faviconDataUrl);
- document.body.appendChild(favicon);
- });
-
- afterEach(() => {
- document.body.removeChild(document.getElementById('favicon'));
- });
-
- it('should set page favicon to provided favicon overlay', done => {
- commonUtils
- .setFaviconOverlay(overlayDataUrl)
- .then(() => document.getElementById('favicon').getAttribute('href'))
- .then(url => Promise.all([urlToImage(url), urlToImage(faviconWithOverlayDataUrl)]))
- .then(([actual, expected]) => {
- expect(actual).toImageDiffEqual(expected, PIXEL_TOLERANCE);
- done();
- })
- .catch(done.fail);
- });
- });
-
- describe('setCiStatusFavicon', () => {
- const BUILD_URL = `${gl.TEST_HOST}/frontend-fixtures/builds-project/-/jobs/1/status.json`;
- let mock;
-
- beforeEach(() => {
- const favicon = document.createElement('link');
- favicon.setAttribute('id', 'favicon');
- favicon.setAttribute('href', 'null');
- favicon.setAttribute('data-original-href', faviconDataUrl);
- document.body.appendChild(favicon);
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- document.body.removeChild(document.getElementById('favicon'));
- });
-
- it('should reset favicon in case of error', done => {
- mock.onGet(BUILD_URL).replyOnce(500);
-
- commonUtils.setCiStatusFavicon(BUILD_URL).catch(() => {
- const favicon = document.getElementById('favicon');
-
- expect(favicon.getAttribute('href')).toEqual(faviconDataUrl);
- done();
- });
- });
-
- it('should set page favicon to CI status favicon based on provided status', done => {
- mock.onGet(BUILD_URL).reply(200, {
- favicon: overlayDataUrl,
- });
-
- commonUtils
- .setCiStatusFavicon(BUILD_URL)
- .then(() => document.getElementById('favicon').getAttribute('href'))
- .then(url => Promise.all([urlToImage(url), urlToImage(faviconWithOverlayDataUrl)]))
- .then(([actual, expected]) => {
- expect(actual).toImageDiffEqual(expected, PIXEL_TOLERANCE);
- done();
- })
- .catch(done.fail);
- });
- });
-
- describe('spriteIcon', () => {
- let beforeGon;
-
- beforeEach(() => {
- window.gon = window.gon || {};
- beforeGon = Object.assign({}, window.gon);
- window.gon.sprite_icons = 'icons.svg';
- });
-
- afterEach(() => {
- window.gon = beforeGon;
- });
-
- it('should return the svg for a linked icon', () => {
- expect(commonUtils.spriteIcon('test')).toEqual(
- '<svg ><use xlink:href="icons.svg#test" /></svg>',
- );
- });
-
- it('should set svg className when passed', () => {
- expect(commonUtils.spriteIcon('test', 'fa fa-test')).toEqual(
- '<svg class="fa fa-test"><use xlink:href="icons.svg#test" /></svg>',
- );
- });
- });
-
- describe('convertObjectPropsToCamelCase', () => {
- it('returns new object with camelCase property names by converting object with snake_case names', () => {
- const snakeRegEx = /(_\w)/g;
- const mockObj = {
- id: 1,
- group_name: 'GitLab.org',
- absolute_web_url: 'https://gitlab.com/gitlab-org/',
- };
- const mappings = {
- id: 'id',
- groupName: 'group_name',
- absoluteWebUrl: 'absolute_web_url',
- };
-
- const convertedObj = commonUtils.convertObjectPropsToCamelCase(mockObj);
-
- Object.keys(convertedObj).forEach(prop => {
- expect(snakeRegEx.test(prop)).toBeFalsy();
- expect(convertedObj[prop]).toBe(mockObj[mappings[prop]]);
- });
- });
-
- it('return empty object if method is called with null or undefined', () => {
- expect(Object.keys(commonUtils.convertObjectPropsToCamelCase(null)).length).toBe(0);
- expect(Object.keys(commonUtils.convertObjectPropsToCamelCase()).length).toBe(0);
- expect(Object.keys(commonUtils.convertObjectPropsToCamelCase({})).length).toBe(0);
- });
-
- it('does not deep-convert by default', () => {
- const obj = {
- snake_key: {
- child_snake_key: 'value',
- },
- };
-
- expect(commonUtils.convertObjectPropsToCamelCase(obj)).toEqual({
- snakeKey: {
- child_snake_key: 'value',
- },
- });
- });
-
- describe('convertObjectPropsToSnakeCase', () => {
- it('converts each object key to snake case', () => {
- const obj = {
- some: 'some',
- 'cool object': 'cool object',
- likeThisLongOne: 'likeThisLongOne',
- };
-
- expect(commonUtils.convertObjectPropsToSnakeCase(obj)).toEqual({
- some: 'some',
- cool_object: 'cool object',
- like_this_long_one: 'likeThisLongOne',
- });
- });
-
- it('returns an empty object if there are no keys', () => {
- ['', {}, [], null].forEach(badObj => {
- expect(commonUtils.convertObjectPropsToSnakeCase(badObj)).toEqual({});
- });
- });
- });
-
- describe('with options', () => {
- const objWithoutChildren = {
- project_name: 'GitLab CE',
- group_name: 'GitLab.org',
- license_type: 'MIT',
- };
-
- const objWithChildren = {
- project_name: 'GitLab CE',
- group_name: 'GitLab.org',
- license_type: 'MIT',
- tech_stack: {
- backend: 'Ruby',
- frontend_framework: 'Vue',
- database: 'PostgreSQL',
- },
- };
-
- describe('when options.deep is true', () => {
- it('converts object with child objects', () => {
- const obj = {
- snake_key: {
- child_snake_key: 'value',
- },
- };
-
- expect(commonUtils.convertObjectPropsToCamelCase(obj, { deep: true })).toEqual({
- snakeKey: {
- childSnakeKey: 'value',
- },
- });
- });
-
- it('converts array with child objects', () => {
- const arr = [
- {
- child_snake_key: 'value',
- },
- ];
-
- expect(commonUtils.convertObjectPropsToCamelCase(arr, { deep: true })).toEqual([
- {
- childSnakeKey: 'value',
- },
- ]);
- });
-
- it('converts array with child arrays', () => {
- const arr = [
- [
- {
- child_snake_key: 'value',
- },
- ],
- ];
-
- expect(commonUtils.convertObjectPropsToCamelCase(arr, { deep: true })).toEqual([
- [
- {
- childSnakeKey: 'value',
- },
- ],
- ]);
- });
- });
-
- describe('when options.dropKeys is provided', () => {
- it('discards properties mentioned in `dropKeys` array', () => {
- expect(
- commonUtils.convertObjectPropsToCamelCase(objWithoutChildren, {
- dropKeys: ['group_name'],
- }),
- ).toEqual({
- projectName: 'GitLab CE',
- licenseType: 'MIT',
- });
- });
-
- it('discards properties mentioned in `dropKeys` array when `deep` is true', () => {
- expect(
- commonUtils.convertObjectPropsToCamelCase(objWithChildren, {
- deep: true,
- dropKeys: ['group_name', 'database'],
- }),
- ).toEqual({
- projectName: 'GitLab CE',
- licenseType: 'MIT',
- techStack: {
- backend: 'Ruby',
- frontendFramework: 'Vue',
- },
- });
- });
- });
-
- describe('when options.ignoreKeyNames is provided', () => {
- it('leaves properties mentioned in `ignoreKeyNames` array intact', () => {
- expect(
- commonUtils.convertObjectPropsToCamelCase(objWithoutChildren, {
- ignoreKeyNames: ['group_name'],
- }),
- ).toEqual({
- projectName: 'GitLab CE',
- licenseType: 'MIT',
- group_name: 'GitLab.org',
- });
- });
-
- it('leaves properties mentioned in `ignoreKeyNames` array intact when `deep` is true', () => {
- expect(
- commonUtils.convertObjectPropsToCamelCase(objWithChildren, {
- deep: true,
- ignoreKeyNames: ['group_name', 'frontend_framework'],
- }),
- ).toEqual({
- projectName: 'GitLab CE',
- group_name: 'GitLab.org',
- licenseType: 'MIT',
- techStack: {
- backend: 'Ruby',
- frontend_framework: 'Vue',
- database: 'PostgreSQL',
- },
- });
- });
- });
- });
- });
-
- describe('roundOffFloat', () => {
- it('Rounds off decimal places of a float number with provided precision', () => {
- expect(commonUtils.roundOffFloat(3.141592, 3)).toBeCloseTo(3.142);
- });
-
- it('Rounds off a float number to a whole number when provided precision is zero', () => {
- expect(commonUtils.roundOffFloat(3.141592, 0)).toBeCloseTo(3);
- expect(commonUtils.roundOffFloat(3.5, 0)).toBeCloseTo(4);
- });
-
- it('Rounds off float number to nearest 0, 10, 100, 1000 and so on when provided precision is below 0', () => {
- expect(commonUtils.roundOffFloat(34567.14159, -1)).toBeCloseTo(34570);
- expect(commonUtils.roundOffFloat(34567.14159, -2)).toBeCloseTo(34600);
- expect(commonUtils.roundOffFloat(34567.14159, -3)).toBeCloseTo(35000);
- expect(commonUtils.roundOffFloat(34567.14159, -4)).toBeCloseTo(30000);
- expect(commonUtils.roundOffFloat(34567.14159, -5)).toBeCloseTo(0);
- });
- });
-
- describe('isInViewport', () => {
- let el;
-
- beforeEach(() => {
- el = document.createElement('div');
- });
-
- afterEach(() => {
- document.body.removeChild(el);
- });
-
- it('returns true when provided `el` is in viewport', () => {
- el.setAttribute('style', `position: absolute; right: ${window.innerWidth + 0.2};`);
- document.body.appendChild(el);
-
- expect(commonUtils.isInViewport(el)).toBe(true);
- });
-
- it('returns false when provided `el` is not in viewport', () => {
- el.setAttribute('style', 'position: absolute; top: -1000px; left: -1000px;');
- document.body.appendChild(el);
-
- expect(commonUtils.isInViewport(el)).toBe(false);
- });
- });
-
- describe('searchBy', () => {
- const searchSpace = {
- iid: 1,
- reference: '&1',
- title: 'Error omnis quos consequatur ullam a vitae sed omnis libero cupiditate.',
- url: '/groups/gitlab-org/-/epics/1',
- };
-
- it('returns null when `query` or `searchSpace` params are empty/undefined', () => {
- expect(commonUtils.searchBy('omnis', null)).toBeNull();
- expect(commonUtils.searchBy('', searchSpace)).toBeNull();
- expect(commonUtils.searchBy()).toBeNull();
- });
-
- it('returns object with matching props based on `query` & `searchSpace` params', () => {
- // String `omnis` is found only in `title` prop so return just that
- expect(commonUtils.searchBy('omnis', searchSpace)).toEqual(
- jasmine.objectContaining({
- title: searchSpace.title,
- }),
- );
-
- // String `1` is found in both `iid` and `reference` props so return both
- expect(commonUtils.searchBy('1', searchSpace)).toEqual(
- jasmine.objectContaining({
- iid: searchSpace.iid,
- reference: searchSpace.reference,
- }),
- );
-
- // String `/epics/1` is found in `url` prop so return just that
- expect(commonUtils.searchBy('/epics/1', searchSpace)).toEqual(
- jasmine.objectContaining({
- url: searchSpace.url,
- }),
- );
- });
- });
-
- describe('isScopedLabel', () => {
- it('returns true when `::` is present in title', () => {
- expect(commonUtils.isScopedLabel({ title: 'foo::bar' })).toBe(true);
- });
-
- it('returns false when `::` is not present', () => {
- expect(commonUtils.isScopedLabel({ title: 'foobar' })).toBe(false);
- });
- });
-
- describe('getDashPath', () => {
- it('returns the path following /-/', () => {
- expect(commonUtils.getDashPath('/some/-/url-with-dashes-/')).toEqual('url-with-dashes-/');
- });
-
- it('returns null when no path follows /-/', () => {
- expect(commonUtils.getDashPath('/some/url')).toEqual(null);
- });
- });
-});
diff --git a/spec/javascripts/lib/utils/mock_data.js b/spec/javascripts/lib/utils/mock_data.js
index c466b0cd1ed..c2f79a32377 100644
--- a/spec/javascripts/lib/utils/mock_data.js
+++ b/spec/javascripts/lib/utils/mock_data.js
@@ -1,8 +1 @@
-export const faviconDataUrl =
- 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAACcFBMVEX////iQyniQyniQyniQyniQyniQyniQyniQynhRiriQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniRCniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQynhQiniQiniQiniQinhQinpUSjqUSjqTyjqTyjqTyjlSCniRCniQynjRCjqTyjsZSjrWyj8oib9kSb8pyb9pib8oyb8fyb3ZSb4Zib8fCb8oyb8oyb8oyb8pCb8cSbiQyn7bCb8cib8oyb8oSb8bSbtVSjpTij8nyb8oyb8oyb8lCb2Yyf3ZCf8mCb8oyb8oyb8oyb8iib8bSbiRCn8gyb8oyb8eCbpTinrUSj8oyb8oyb8oyb8pSb8bib4Zif0YCf8byb8oyb8oyb8oyb7oib8oyb8nCbjRSn9bib8ayb8nib8oyb8oyb8oyb8kSbpTyjpTyj8jib8oyb8oyb8oyb8fib0Xyf2ZSb8gCb8oyb6pSb8oyb8dib+cCbgQCnjRSn8cCb8oib8oyb8oyb8oybqUCjnSyn8bCb8oyb8oyb8oyb8myb2YyfyXyf8oyb8oyb8hibhQSn+bib8iSb8oyb8qCb+fSbmSSnqTyj8oib9pCb1YifxXyf7pSb8oCb8pCb+mCb0fCf8pSb7hSXvcSjiQyniQinqTyj9kCb9bib9byb+cCbqUSjiRCnsVCj+cSb8pib8bCb8bSbgQCn7bCb8bibjRSn8oyb8ayb8oib8aib8pCbjRCn8pybhQinhQSn8pSb7ayb7aSb6aib8eib///8IbM+7AAAAr3RSTlMBA3NtX2vT698HGQcRLwWLiXnv++3V+eEd/R8HE2V/Y5HjyefdFw99YWfJ+/3nwQP78/HvX1VTQ/kdA2HzbQXj9fX79/3DGf379/33T/v99/f7ba33+/f1+9/18/v59V339flzF/H9+fX3/fMhBwOh9/v5/fmvBV/z+fP3Awnp9/f38+UFgff7+/37+4c77/f7/flFz/f59dFr7/v98Wnr+/f3I5/197EDBU1ZAwUD8/kLUwAAAAFiS0dEAIgFHUgAAAAHdElNRQfhBQoLHiBV6/1lAAACHUlEQVQ4y41TZXsTQRCe4FAIUigN7m7FXY+iLRQKBG2x4g7BjhZ3Le7uMoEkFJprwyQk0CC/iZnNhUZaHt4vt6/szO7cHcD/wFKjZrJWq3YMq1M3eVc9rFzXR2yQkuA3RGxkjZLGiEk9miA2tURJs1RsnhhokYYtzaU13WZDbBVnW1sjo43J2vI6tZ0lLtFeAh1M0lECneI7dGYtrUtk3RUVIKaEJR25qw27yT0s3W0qEHuPlB4RradivXo7GX36xnbo51SQ+fWHARmCgYMGDxkaxbD3SssYPmIkwKgPLrfA87EETTg/fVaSa/SYsQDjSsd7DcGEsr+BieVKmaRNBsjUtClTfUI900y/5Mt05c8oJQKYSURZ2UqYFa0w283M588JEM2BuRwI5EqT8nmmXzZf4l8XsGNfCIv4QcHFklhiBpaqAsuC4tghj+ySyOdjeJYrP7RCCuR/E5tWAqxaLcmCNSyujdxjHZdbn8UHoA0bN/GoNm8hjQJb/ZzYpo6w3TB27JRduxxqrA7YzbWCezixN8RD2Oc2/Ptlfx7o5uT1A4XMiwzj4HfEikNe7+Ew0ZGjeuW70eEYaeHjxomTiKd++E4XnKGz8d+HDufOB3Ky3RcwdNF1qZiKLyf/B44r2tWf15wV143cwI2qfi8dbtKtX6Hbd+6G74EDqkTm/QcPH/0ufFyNLXjy9NnzF9Xb8BJevYY38C+8fZcg/AF3QTYemVkCwwAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNy0wNS0xMFQxMTozMDozMiswMjowMMzup8UAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTctMDUtMTBUMTE6MzA6MzIrMDI6MDC9sx95AAAAAElFTkSuQmCC';
-
-export const overlayDataUrl =
- 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAA85JREFUWAntVllIVGEUPv/9b46O41KplYN7PeRkti8TjQlhCUGh3MmeQugpIsGKAi2soIcIooiohxYKK2daqDAlIpIiWwxtQaJcaHE0d5tMrbn37z9XRqfR0TvVW56Hudf//uec72zfEWBCJjIwkYGJDPzvGSD/KgExN3Oi2Q+2DJgSDYQEMwItVGH1iZGmJw/Si1y+/PwVAMYYib22MYc/8hVQFgKDEfYoId0KYzagAQebsos/ewMZoeB9wdffcTYpQSaCTWHKoqSQaDk7zkIt0+aCUR8BelEHrf3dUNv9AcqbnsHtT5UKB/hTASh0SLYjnjb/CIDRJi0XiFAaJOpCD8zLpdb4NB66b1OfelthX815dtdRRfiti2aAXLvVLiMQ6olGyztGDkSo4JGGXk8/QFdGpYzpHG2GBQTDhtgVhPEaVbbVpvI6GJz22rv4TcAfrYI1x7Rj5MWWAppomKFVVb2302SFzUkZHAbkG+0b1+Gh77yNYjrmqnWTrLBLRxdvBWv8qlFujH/kYjJYyvLkj71t78zAUvzMAMnHhpN4zf9UREJhd8omyssxu1IgazQDwDnHUcNuH6vhPIE1fmuBzHt74Hn7W89jWGtcAjoaIDOFrdcMYJBkgOCoaRF0Lj0oglddDbCj6tRvKjphEpgjkzEQs2YAKsNxMzjn3nKurhzK+Ly7xe28ua8TwgMMcHJZnvvT0BPtEEKM4tDJ+C8GvIIk4ylINIXVZ0EUKJxYuh3mhCeokbudl6TtVc88dfBdLwbyaWB6zQCYQJpBYSrDGQxBQ/ZWRM2B+VNmQnVnHWx7elyNuL2/R336co7KyJR8CL9oLgEuFlREevWUkEl6uGwpVEG4FBm0OEf9N10NMgPlvWYAuNVwsWDKvcUNYsHUWTCZ13ysyFEXe6TO6aC8CUr9IiK+A05TQrc8yjwmxARHeeMAPlfQJw+AQRwu0YhL/GDXi9NwufG+S8dYkuYMqIb4SsWthotlNMOUCOM6r+G9cqXxPmd1dqrBav/o1zJy2l5/NUjJA/VORwYuFnOUaTQcPs9wMqwV++Xv8oADxKAcZ8nLPr8AoGW+xR6HSqYk3GodAz2QNj0V+Gr26dT9ASNH5239Pf0gktVNWZca8ZvfAFBprWS6hSu1pqt++Y0PD+WIwDAhIWQGtzvSHDbcodfFUFB9hg1Gjs5LXqIdFL+acFBl+FddqYwdxsWC3I70OvgfUaA65zhq2O2c8VxYcyIGFTVlXegYtvCXANCQZJMobjVcLMjtSK/IcEgyOOe8Ve5w7ryKDefp2P3+C/5ohv8HZmVLAAAAAElFTkSuQmCC';
-
-export const faviconWithOverlayDataUrl =
- 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAGtElEQVRYR8WXf3CT9R3H35/nSdIQIktrCf0RStI0FYRjVBAccxTq5MDBKUoz4ZyjbPO87q4yBsPDMdExTjlvIsdQexyI0oMBeuKhdjsNHhwcMgpjIlublLIm/UlJKZSSJs/z/e6+T5v0CQ22wB/7/pPck8/383l9fj6fEOec8H88NAjAS1LwknsFSVLU8WXd1rtm85LUeKnwGQKzjj3s33azvsEAAEIlnn8ByHL4/Pa7BgAQLCm8QOBOh88vDQkQeMxjMkcQEYKqYsyJWWPhgs/80TsFafzROJtkNIXFfYI0pfXqPeennjqlxPUNikBoTuEmEF+lCRBV3G0aQiWFrwH8d30AWJubGdiEfZzdGqDEEwbICnADQGGHry7zTr0X94IlnnMACggwAWh0+PxOvb5EBGqmTTNkj7ySxWS62C+g5Usm1Zn95YXG24UQ+r5n75Li6Ux4LBkyc7/4t5YSLSr6Lgg9UvBLcKocMEYKON/gGB3YoA/bcGFCczzLQdieLE9bHL66FakBSjzCU0cSAHDa4at7aLhG9XLBEk8zAVnxZxyIEhBy+PwFgwAafpxvNzK5NZUhrX28JA07Cl6SmtvcOUwm4ZAouHj7ad+jMrN1dqb3iG7oS4EYPh2etQS+XiesC8TQ3ZD3yZJsHuUPgbMcI+ej5v3ncv5PasNlk1p7JJnzJL+I0/O5h+u0VCdqIDi78AQRHuirft3hYJzQPvawPydVdPI+/OnTnNNKBjYVXHRa8rFFGeb4w1he0wZ7d/84IXTEhxzxUsgitB2LPFGwvgGUfLSeZUpEXqEqrIdz0nr4iHOUfeOccb/tNMtutzWHPeWcJc0aMxm5lkxYDGloj1zB+Sv/RXXTSXzaeBwSY3j+bHNv2bdtMYCbpHtRkNFd36xFQN3tXkZhvgP1fdPi5kMEXL4oIXKVAA58M8aCVQs84BYLXi5aDq+zGJTqYr+i4PV2vHxmJ/7WUoOn2i/jz6yhW7JjrdSV8U4fQFV+I2Q4UIsedMCSSlcsgp72WtnSajOhzDsBNtsYfFD8e+Rbs4fdIG98uw9vnj+AX7FWvk4NHZOXXphF/INx2SpJIU2L8L4GDAoMwlP9kWSg6awcKVs83tyUnY5Dj75+W8bjutae3o5d9X/HTiWAuUtOS6RUOR8Hp48TxjgU/AMSeKJ1Ej/tMWXG1sxwGt98sBxe5+xhe64XVLiK2Z9XwNgdRLXyzQsC4ENwelIHAFxDBOdh1qdCdNLCoon8RnY+HZ6/+TtzPhTZweAxlJ94C5VqoI2U3a7rACzJjQqgBd24CGscos1kxPQZ38fqSU/jhQkDvN9lrKG7FeUnNuPVKcvwYOb4hGgvi2HSx8vwRKyJkVLl+hk43gdBAcfADBD1cA4RXIdZ1EN1Zjqem+DGoUc2oigjMUlvaV8YL/1qPVpuhOG+JwdH5m1Okn3m6Eacaz3V2jeI9uTbVYY6AKOSKw8MX0MBg2lXjh3r3Hk4s7ASdrMtSWxnoBpZIzIwP3e69lxv3Gay4q/F6zDJ5kq6s6amEnsafJ0Db8P9JKkx1w5wPJuY36IToojgNMzb8rLwmsuB2kW7YDWMSCgTg+YXx9+AQZKxdUaFZiju+a2Mi8uvnH0f2/2f9g4AVE4z4LlTilrlehag9xIpEam4jO4DXfdaV97nwtH5byW137VYD5Yc2YAz4YAGIYx2RLq0z1Sex8l//fUWfBI83jh4Kd1PEuAwqVGjWEwSS+nJJmt0sWu86d0frMQCR/LbWQ8hDAxlXMgUV69Q67ubv0q5FUNAlHKmVLnXE/gfREpUiaQHqAizXbO0UN98BMTSo39Cw7UW7E2Rc728qJGHP68ASbQyNYCQTkAUzCSwQ+CwvSjnsQPGLOnI/C0YO3Lwxq5yhhtqb1KNpGqT1TXvigJU0jh33xpAf7NymoGNDJ9sJtPkYuNkqTh7KnY8vGaoeZPy93+GA1joe4kzzv/SVLqvYngA/dFgVfnlb8tjtm6Ux+I39y/Gqone24IQM+GxL15UO3q7WrhsnhJatCs8PAC9md3OrPK0goaDyEj7uXsuXi0qg4HkIUGE52XHNqmXIl0RGOiHoUV7xb+v5K14SC39At79Ximdhc8ekjImuiyjsXryUszLnY40yThIhSi4bbUHsbfBJ6ZKE5dpQdz4HQOgf2a8tLvklY+M6cuvSnJummxSZ46+X+7biMzaRnSu84IauNYsE5HCOX+HDCPWi7DrKW8/BTcVZ2UN8Me57kc5448TaCYR5XJwC0BtHMwPjs/SgAP1pfuCqSL8Pxhr/wunLWAOAAAAAElFTkSuQmCC';
+export * from '../../../frontend/lib/utils/mock_data.js';
diff --git a/spec/javascripts/monitoring/components/dashboard_resize_spec.js b/spec/javascripts/monitoring/components/dashboard_resize_spec.js
index 2422934f4b3..6a35069ccff 100644
--- a/spec/javascripts/monitoring/components/dashboard_resize_spec.js
+++ b/spec/javascripts/monitoring/components/dashboard_resize_spec.js
@@ -112,7 +112,7 @@ describe('Dashboard', () => {
setupComponentStore(component);
return Vue.nextTick().then(() => {
- [, promPanel] = component.$el.querySelectorAll('.prometheus-panel');
+ [promPanel] = component.$el.querySelectorAll('.prometheus-panel');
promGroup = promPanel.querySelector('.prometheus-graph-group');
panelToggle = promPanel.querySelector('.js-graph-group-toggle');
chart = promGroup.querySelector('.position-relative svg');