Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
df3831073f
commit
32e1683f8b
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -2,6 +2,19 @@
|
|||
documentation](doc/development/changelog.md) for instructions on adding your own
|
||||
entry.
|
||||
|
||||
## 13.7.3 (2021-01-08)
|
||||
|
||||
### Fixed (7 changes)
|
||||
|
||||
- Fix Canary Ingress weight is not reflected on UI immediately. !50246
|
||||
- Change pages deployments size to bigint. !50262
|
||||
- Fix viewing container repositories with tags with corrupted manifest. !50362
|
||||
- Fix the graphQL type for container repository tags. !50419
|
||||
- Fix(eetrialbanner): fix EE trial banner to allow dismiss. !50436
|
||||
- Update Helm 2 version to 2.17.0. !50547
|
||||
- Fix project access token regression. !50800
|
||||
|
||||
|
||||
## 13.7.2 (2021-01-07)
|
||||
|
||||
### Security (7 changes)
|
||||
|
|
2
Gemfile
2
Gemfile
|
@ -81,7 +81,7 @@ gem 'gpgme', '~> 2.0.19'
|
|||
# GitLab fork with several improvements to original library. For full list of changes
|
||||
# see https://github.com/intridea/omniauth-ldap/compare/master...gitlabhq:master
|
||||
gem 'gitlab_omniauth-ldap', '~> 2.1.1', require: 'omniauth-ldap'
|
||||
gem 'net-ldap'
|
||||
gem 'net-ldap', '~> 0.16.3'
|
||||
|
||||
# API
|
||||
# Locked at Grape v1.4.0 until https://github.com/ruby-grape/grape/pull/2088 is merged
|
||||
|
|
|
@ -733,7 +733,7 @@ GEM
|
|||
nakayoshi_fork (0.0.4)
|
||||
nap (1.1.0)
|
||||
nenv (0.3.0)
|
||||
net-ldap (0.16.2)
|
||||
net-ldap (0.16.3)
|
||||
net-ntp (2.1.3)
|
||||
net-ssh (6.0.0)
|
||||
netrc (0.11.0)
|
||||
|
@ -1423,7 +1423,7 @@ DEPENDENCIES
|
|||
minitest (~> 5.11.0)
|
||||
multi_json (~> 1.14.1)
|
||||
nakayoshi_fork (~> 0.0.4)
|
||||
net-ldap
|
||||
net-ldap (~> 0.16.3)
|
||||
net-ntp
|
||||
net-ssh (~> 6.0)
|
||||
nokogiri (~> 1.10.9)
|
||||
|
|
|
@ -2,7 +2,7 @@ import Visibility from 'visibilityjs';
|
|||
import * as types from './mutation_types';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import Poll from '~/lib/utils/poll';
|
||||
import { setFaviconOverlay, resetFavicon } from '~/lib/utils/common_utils';
|
||||
import { setFaviconOverlay, resetFavicon } from '~/lib/utils/favicon';
|
||||
import { deprecatedCreateFlash as flash } from '~/flash';
|
||||
import { __ } from '~/locale';
|
||||
import {
|
||||
|
|
|
@ -6,7 +6,6 @@ import { GlBreakpointInstance as breakpointInstance } from '@gitlab/ui/dist/util
|
|||
import $ from 'jquery';
|
||||
import { isFunction, defer } from 'lodash';
|
||||
import Cookies from 'js-cookie';
|
||||
import axios from './axios_utils';
|
||||
import { getLocationHash } from './url_utility';
|
||||
import { convertToCamelCase, convertToSnakeCase } from './text_utility';
|
||||
import { isObject } from './type_utility';
|
||||
|
@ -548,92 +547,6 @@ export const backOff = (fn, timeout = 60000) => {
|
|||
});
|
||||
};
|
||||
|
||||
export const createOverlayIcon = (iconPath, overlayPath) => {
|
||||
const faviconImage = document.createElement('img');
|
||||
|
||||
return new Promise((resolve) => {
|
||||
faviconImage.onload = () => {
|
||||
const size = 32;
|
||||
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = size;
|
||||
canvas.height = size;
|
||||
|
||||
const context = canvas.getContext('2d');
|
||||
context.clearRect(0, 0, size, size);
|
||||
context.drawImage(
|
||||
faviconImage,
|
||||
0,
|
||||
0,
|
||||
faviconImage.width,
|
||||
faviconImage.height,
|
||||
0,
|
||||
0,
|
||||
size,
|
||||
size,
|
||||
);
|
||||
|
||||
const overlayImage = document.createElement('img');
|
||||
overlayImage.onload = () => {
|
||||
context.drawImage(
|
||||
overlayImage,
|
||||
0,
|
||||
0,
|
||||
overlayImage.width,
|
||||
overlayImage.height,
|
||||
0,
|
||||
0,
|
||||
size,
|
||||
size,
|
||||
);
|
||||
|
||||
const faviconWithOverlayUrl = canvas.toDataURL();
|
||||
|
||||
resolve(faviconWithOverlayUrl);
|
||||
};
|
||||
overlayImage.src = overlayPath;
|
||||
};
|
||||
faviconImage.src = iconPath;
|
||||
});
|
||||
};
|
||||
|
||||
export const setFaviconOverlay = (overlayPath) => {
|
||||
const faviconEl = document.getElementById('favicon');
|
||||
|
||||
if (!faviconEl) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const iconPath = faviconEl.getAttribute('data-original-href');
|
||||
|
||||
return createOverlayIcon(iconPath, overlayPath).then((faviconWithOverlayUrl) =>
|
||||
faviconEl.setAttribute('href', faviconWithOverlayUrl),
|
||||
);
|
||||
};
|
||||
|
||||
export const resetFavicon = () => {
|
||||
const faviconEl = document.getElementById('favicon');
|
||||
|
||||
if (faviconEl) {
|
||||
const originalFavicon = faviconEl.getAttribute('data-original-href');
|
||||
faviconEl.setAttribute('href', originalFavicon);
|
||||
}
|
||||
};
|
||||
|
||||
export const setCiStatusFavicon = (pageUrl) =>
|
||||
axios
|
||||
.get(pageUrl)
|
||||
.then(({ data }) => {
|
||||
if (data && data.favicon) {
|
||||
return setFaviconOverlay(data.favicon);
|
||||
}
|
||||
return resetFavicon();
|
||||
})
|
||||
.catch((error) => {
|
||||
resetFavicon();
|
||||
throw error;
|
||||
});
|
||||
|
||||
export const spriteIcon = (icon, className = '') => {
|
||||
const classAttribute = className.length > 0 ? `class="${className}"` : '';
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
import { FaviconOverlayManager } from '@gitlab/favicon-overlay';
|
||||
import { memoize } from 'lodash';
|
||||
|
||||
// FaviconOverlayManager is a glorious singleton/static class. Let's start to encapsulate that with this helper.
|
||||
const getDefaultFaviconManager = memoize(async () => {
|
||||
await FaviconOverlayManager.initialize({ faviconSelector: '#favicon' });
|
||||
|
||||
return FaviconOverlayManager;
|
||||
});
|
||||
|
||||
export const setFaviconOverlay = async (path) => {
|
||||
const manager = await getDefaultFaviconManager();
|
||||
|
||||
manager.setFaviconOverlay(path);
|
||||
};
|
||||
|
||||
export const resetFavicon = async () => {
|
||||
const manager = await getDefaultFaviconManager();
|
||||
|
||||
manager.resetFaviconOverlay();
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears the cached memoization of the default manager.
|
||||
*
|
||||
* This is needed for determinism in tests.
|
||||
*/
|
||||
export const clearMemoizeCache = () => {
|
||||
getDefaultFaviconManager.cache.clear();
|
||||
};
|
|
@ -0,0 +1,16 @@
|
|||
import axios from './axios_utils';
|
||||
import { setFaviconOverlay, resetFavicon } from './favicon';
|
||||
|
||||
export const setCiStatusFavicon = (pageUrl) =>
|
||||
axios
|
||||
.get(pageUrl)
|
||||
.then(({ data }) => {
|
||||
if (data && data.favicon) {
|
||||
return setFaviconOverlay(data.favicon);
|
||||
}
|
||||
return resetFavicon();
|
||||
})
|
||||
.catch((error) => {
|
||||
resetFavicon();
|
||||
throw error;
|
||||
});
|
|
@ -1,5 +1,5 @@
|
|||
import LinkedTabs from './lib/utils/bootstrap_linked_tabs';
|
||||
import { setCiStatusFavicon } from './lib/utils/common_utils';
|
||||
import { setCiStatusFavicon } from './lib/utils/favicon_ci';
|
||||
|
||||
export default class Pipelines {
|
||||
constructor(options = {}) {
|
||||
|
|
|
@ -43,7 +43,7 @@ import SourceBranchRemovalStatus from './components/source_branch_removal_status
|
|||
import TerraformPlan from './components/terraform/mr_widget_terraform_container.vue';
|
||||
import GroupedCodequalityReportsApp from '../reports/codequality_report/grouped_codequality_reports_app.vue';
|
||||
import GroupedTestReportsApp from '../reports/components/grouped_test_reports_app.vue';
|
||||
import { setFaviconOverlay } from '../lib/utils/common_utils';
|
||||
import { setFaviconOverlay } from '../lib/utils/favicon';
|
||||
import GroupedAccessibilityReportsApp from '../reports/accessibility_report/grouped_accessibility_reports_app.vue';
|
||||
import getStateQuery from './queries/get_state.query.graphql';
|
||||
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: 'Fix(eetrialbanner): fix EE trial banner to allow dismiss'
|
||||
merge_request: 50436
|
||||
author:
|
||||
type: fixed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Fix viewing container repositories with tags with corrupted manifest
|
||||
merge_request: 50362
|
||||
author:
|
||||
type: fixed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Change pages deployments size to bigint
|
||||
merge_request: 50262
|
||||
author:
|
||||
type: fixed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Fix project access token regression
|
||||
merge_request: 50800
|
||||
author:
|
||||
type: fixed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Fix Canary Ingress weight is not reflected on UI immediately
|
||||
merge_request: 50246
|
||||
author:
|
||||
type: fixed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Update net-ldap gem version
|
||||
merge_request: 50888
|
||||
author:
|
||||
type: other
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Update Helm 2 version to 2.17.0
|
||||
merge_request: 50547
|
||||
author:
|
||||
type: fixed
|
|
@ -91,7 +91,7 @@ module.exports = (path) => {
|
|||
'^.+\\.(md|zip|png)$': 'jest-raw-loader',
|
||||
},
|
||||
transformIgnorePatterns: [
|
||||
'node_modules/(?!(@gitlab/ui|bootstrap-vue|three|monaco-editor|monaco-yaml|fast-mersenne-twister)/)',
|
||||
'node_modules/(?!(@gitlab/ui|@gitlab/favicon-overlay|bootstrap-vue|three|monaco-editor|monaco-yaml|fast-mersenne-twister)/)',
|
||||
],
|
||||
timers: 'fake',
|
||||
testEnvironment: '<rootDir>/spec/frontend/environment.js',
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
"@babel/plugin-syntax-import-meta": "^7.10.1",
|
||||
"@babel/preset-env": "^7.10.1",
|
||||
"@gitlab/at.js": "1.5.5",
|
||||
"@gitlab/favicon-overlay": "2.0.0",
|
||||
"@gitlab/svgs": "1.178.0",
|
||||
"@gitlab/tributejs": "1.0.0",
|
||||
"@gitlab/ui": "25.4.0",
|
||||
|
|
|
@ -514,27 +514,6 @@ describe('common_utils', () => {
|
|||
});
|
||||
});
|
||||
|
||||
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('spriteIcon', () => {
|
||||
let beforeGon;
|
||||
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
import MockAdapter from 'axios-mock-adapter';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { setFaviconOverlay, resetFavicon } from '~/lib/utils/favicon';
|
||||
import { setCiStatusFavicon } from '~/lib/utils/favicon_ci';
|
||||
|
||||
jest.mock('~/lib/utils/favicon');
|
||||
|
||||
const TEST_URL = '/test/pipelinable/1';
|
||||
const TEST_FAVICON = '/favicon.test.ico';
|
||||
|
||||
describe('~/lib/utils/favicon_ci', () => {
|
||||
let mock;
|
||||
|
||||
beforeEach(() => {
|
||||
mock = new MockAdapter(axios);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mock.restore();
|
||||
mock = null;
|
||||
});
|
||||
|
||||
describe('setCiStatusFavicon', () => {
|
||||
it.each`
|
||||
response | setFaviconOverlayCalls | resetFaviconCalls
|
||||
${{}} | ${[]} | ${[[]]}
|
||||
${{ favicon: TEST_FAVICON }} | ${[[TEST_FAVICON]]} | ${[]}
|
||||
`(
|
||||
'with response=$response',
|
||||
async ({ response, setFaviconOverlayCalls, resetFaviconCalls }) => {
|
||||
mock.onGet(TEST_URL).replyOnce(200, response);
|
||||
|
||||
expect(setFaviconOverlay).not.toHaveBeenCalled();
|
||||
expect(resetFavicon).not.toHaveBeenCalled();
|
||||
|
||||
await setCiStatusFavicon(TEST_URL);
|
||||
|
||||
expect(setFaviconOverlay.mock.calls).toEqual(setFaviconOverlayCalls);
|
||||
expect(resetFavicon.mock.calls).toEqual(resetFaviconCalls);
|
||||
},
|
||||
);
|
||||
|
||||
it('with error', async () => {
|
||||
mock.onGet(TEST_URL).replyOnce(500);
|
||||
|
||||
await expect(setCiStatusFavicon(TEST_URL)).rejects.toEqual(expect.any(Error));
|
||||
expect(resetFavicon).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,39 @@
|
|||
import { FaviconOverlayManager } from '@gitlab/favicon-overlay';
|
||||
import * as faviconUtils from '~/lib/utils/favicon';
|
||||
|
||||
jest.mock('@gitlab/favicon-overlay');
|
||||
|
||||
describe('~/lib/utils/favicon', () => {
|
||||
afterEach(() => {
|
||||
faviconUtils.clearMemoizeCache();
|
||||
});
|
||||
|
||||
describe.each`
|
||||
fnName | managerFn | args
|
||||
${'setFaviconOverlay'} | ${FaviconOverlayManager.setFaviconOverlay} | ${['test']}
|
||||
${'resetFavicon'} | ${FaviconOverlayManager.resetFaviconOverlay} | ${[]}
|
||||
`('$fnName', ({ fnName, managerFn, args }) => {
|
||||
const call = () => faviconUtils[fnName](...args);
|
||||
|
||||
it('initializes only once when called', async () => {
|
||||
expect(FaviconOverlayManager.initialize).not.toHaveBeenCalled();
|
||||
|
||||
// Call twice so we can make sure initialize is only called once
|
||||
await call();
|
||||
await call();
|
||||
|
||||
expect(FaviconOverlayManager.initialize).toHaveBeenCalledWith({
|
||||
faviconSelector: '#favicon',
|
||||
});
|
||||
expect(FaviconOverlayManager.initialize).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('passes call to manager', async () => {
|
||||
expect(managerFn).not.toHaveBeenCalled();
|
||||
|
||||
await call();
|
||||
|
||||
expect(managerFn).toHaveBeenCalledWith(...args);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -3,6 +3,3 @@ export const faviconDataUrl =
|
|||
|
||||
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,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';
|
||||
|
|
|
@ -13,6 +13,9 @@ import './helpers/dom_shims';
|
|||
import './helpers/jquery';
|
||||
import '~/commons/bootstrap';
|
||||
|
||||
// This module has some fairly decent visual test coverage in it's own repository.
|
||||
jest.mock('@gitlab/favicon-overlay');
|
||||
|
||||
process.on('unhandledRejection', global.promiseRejectionHandler);
|
||||
|
||||
setupManualMocks();
|
||||
|
|
|
@ -7,6 +7,7 @@ import mrWidgetOptions from '~/vue_merge_request_widget/mr_widget_options.vue';
|
|||
import eventHub from '~/vue_merge_request_widget/event_hub';
|
||||
import notify from '~/lib/utils/notify';
|
||||
import SmartInterval from '~/smart_interval';
|
||||
import { setFaviconOverlay } from '~/lib/utils/favicon';
|
||||
import { stateKey } from '~/vue_merge_request_widget/stores/state_maps';
|
||||
import mockData from './mock_data';
|
||||
import { faviconDataUrl, overlayDataUrl } from '../lib/utils/mock_data';
|
||||
|
@ -14,6 +15,8 @@ import { SUCCESS } from '~/vue_merge_request_widget/components/deployment/consta
|
|||
|
||||
jest.mock('~/smart_interval');
|
||||
|
||||
jest.mock('~/lib/utils/favicon');
|
||||
|
||||
const returnPromise = (data) =>
|
||||
new Promise((resolve) => {
|
||||
resolve({
|
||||
|
@ -421,21 +424,12 @@ describe('mrWidgetOptions', () => {
|
|||
document.body.removeChild(document.getElementById('favicon'));
|
||||
});
|
||||
|
||||
it('should call setFavicon method', (done) => {
|
||||
it('should call setFavicon method', async () => {
|
||||
vm.mr.ciStatusFaviconPath = overlayDataUrl;
|
||||
vm.setFaviconHelper()
|
||||
.then(() => {
|
||||
/*
|
||||
It would be better if we'd could mock commonUtils.setFaviconURL
|
||||
with a spy and test that it was called. We are doing the following
|
||||
tests as a proxy to show that the function has been called
|
||||
*/
|
||||
expect(faviconElement.getAttribute('href')).not.toEqual(null);
|
||||
expect(faviconElement.getAttribute('href')).not.toEqual(overlayDataUrl);
|
||||
expect(faviconElement.getAttribute('href')).not.toEqual(faviconDataUrl);
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
|
||||
await vm.setFaviconHelper();
|
||||
|
||||
expect(setFaviconOverlay).toHaveBeenCalledWith(overlayDataUrl);
|
||||
});
|
||||
|
||||
it('should not call setFavicon when there is no ciStatusFaviconPath', (done) => {
|
||||
|
|
|
@ -5,30 +5,8 @@
|
|||
* 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', () => {
|
||||
|
@ -63,90 +41,6 @@ describe('common_utils browser specific specs', () => {
|
|||
});
|
||||
});
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -861,6 +861,11 @@
|
|||
eslint-plugin-vue "^6.2.1"
|
||||
vue-eslint-parser "^7.0.0"
|
||||
|
||||
"@gitlab/favicon-overlay@2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/favicon-overlay/-/favicon-overlay-2.0.0.tgz#2f32d0b6a4d5b8ac44e2927083d9ab478a78c984"
|
||||
integrity sha512-GNcORxXJ98LVGzOT9dDYKfbheqH6lNgPDD72lyXRnQIH7CjgGyos8i17aSBPq1f4s3zF3PyedFiAR4YEZbva2Q==
|
||||
|
||||
"@gitlab/svgs@1.178.0":
|
||||
version "1.178.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.178.0.tgz#069edb8abb4c7137d48f527592476655f066538b"
|
||||
|
|
Loading…
Reference in New Issue