diff options
author | Phil Hughes <me@iamphill.com> | 2019-01-22 15:20:12 +0000 |
---|---|---|
committer | Phil Hughes <me@iamphill.com> | 2019-01-22 15:20:12 +0000 |
commit | 7b6fa5ffcbead7c45c331df6d4c7a5352b6c3521 (patch) | |
tree | 574f2d202b8b16cc3d5deae78b947216954aaefa /spec | |
parent | 1f36297f4be95438d0a7d48d33cd75a6755ea9ac (diff) | |
parent | 91df6d9ef496bdab9fa3658b8dea131fb0a71c8c (diff) | |
download | gitlab-ce-7b6fa5ffcbead7c45c331df6d4c7a5352b6c3521.tar.gz |
Merge branch 'leipert-make-canvas-more-tolerant' into 'master'
Make favicon tests more fault resistent
Closes #50527
See merge request gitlab-org/gitlab-ce!22686
Diffstat (limited to 'spec')
-rw-r--r-- | spec/javascripts/lib/utils/common_utils_spec.js | 40 | ||||
-rw-r--r-- | spec/javascripts/matchers.js | 39 |
2 files changed, 69 insertions, 10 deletions
diff --git a/spec/javascripts/lib/utils/common_utils_spec.js b/spec/javascripts/lib/utils/common_utils_spec.js index 0dc7e93539a..121c4040212 100644 --- a/spec/javascripts/lib/utils/common_utils_spec.js +++ b/spec/javascripts/lib/utils/common_utils_spec.js @@ -3,6 +3,25 @@ import * as commonUtils from '~/lib/utils/common_utils'; import MockAdapter from 'axios-mock-adapter'; 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', () => { @@ -513,8 +532,9 @@ describe('common_utils', () => { it('should return the favicon with the overlay', done => { commonUtils .createOverlayIcon(faviconDataUrl, overlayDataUrl) - .then(url => { - expect(url).toEqual(faviconWithOverlayDataUrl); + .then(url => Promise.all([urlToImage(url), urlToImage(faviconWithOverlayDataUrl)])) + .then(([actual, expected]) => { + expect(actual).toImageDiffEqual(expected, PIXEL_TOLERANCE); done(); }) .catch(done.fail); @@ -536,10 +556,10 @@ describe('common_utils', () => { it('should set page favicon to provided favicon overlay', done => { commonUtils .setFaviconOverlay(overlayDataUrl) - .then(() => { - expect(document.getElementById('favicon').getAttribute('href')).toEqual( - faviconWithOverlayDataUrl, - ); + .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); @@ -582,10 +602,10 @@ describe('common_utils', () => { commonUtils .setCiStatusFavicon(BUILD_URL) - .then(() => { - const favicon = document.getElementById('favicon'); - - expect(favicon.getAttribute('href')).toEqual(faviconWithOverlayDataUrl); + .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); diff --git a/spec/javascripts/matchers.js b/spec/javascripts/matchers.js index 0d465510fd3..406527b08a3 100644 --- a/spec/javascripts/matchers.js +++ b/spec/javascripts/matchers.js @@ -1,3 +1,5 @@ +import pixelmatch from 'pixelmatch'; + export default { toContainText: () => ({ compare(vm, text) { @@ -54,4 +56,41 @@ export default { return result; }, }), + toImageDiffEqual: () => { + const getImageData = img => { + const canvas = document.createElement('canvas'); + canvas.width = img.width; + canvas.height = img.height; + canvas.getContext('2d').drawImage(img, 0, 0); + return canvas.getContext('2d').getImageData(0, 0, img.width, img.height).data; + }; + + return { + compare(actual, expected, threshold = 0.1) { + if (actual.height !== expected.height || actual.width !== expected.width) { + return { + pass: false, + message: `Expected image dimensions (h x w) of ${expected.height}x${expected.width}. + Received an image with ${actual.height}x${actual.width}`, + }; + } + + const { width, height } = actual; + const differentPixels = pixelmatch( + getImageData(actual), + getImageData(expected), + null, + width, + height, + { threshold }, + ); + + return { + pass: differentPixels < 20, + message: `${differentPixels} pixels differ more than ${threshold * + 100} percent between input and output.`, + }; + }, + }; + }, }; |