Commit 91df6d9e authored by Lukas Eipert's avatar Lukas Eipert

Make favicon tests more fault resistent

It seems like every new version of Chrome renders the favicon canvas
differently. This reduces the problems with it by creating a more fault
tolerant check, which compares the color values in the pixels and is
okay if they are within a certain threshold.
parent d56b76a5
...@@ -3,6 +3,25 @@ import * as commonUtils from '~/lib/utils/common_utils'; ...@@ -3,6 +3,25 @@ import * as commonUtils from '~/lib/utils/common_utils';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import { faviconDataUrl, overlayDataUrl, faviconWithOverlayDataUrl } from './mock_data'; 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('common_utils', () => {
describe('parseUrl', () => { describe('parseUrl', () => {
it('returns an anchor tag with url', () => { it('returns an anchor tag with url', () => {
...@@ -513,8 +532,9 @@ describe('common_utils', () => { ...@@ -513,8 +532,9 @@ describe('common_utils', () => {
it('should return the favicon with the overlay', done => { it('should return the favicon with the overlay', done => {
commonUtils commonUtils
.createOverlayIcon(faviconDataUrl, overlayDataUrl) .createOverlayIcon(faviconDataUrl, overlayDataUrl)
.then(url => { .then(url => Promise.all([urlToImage(url), urlToImage(faviconWithOverlayDataUrl)]))
expect(url).toEqual(faviconWithOverlayDataUrl); .then(([actual, expected]) => {
expect(actual).toImageDiffEqual(expected, PIXEL_TOLERANCE);
done(); done();
}) })
.catch(done.fail); .catch(done.fail);
...@@ -536,10 +556,10 @@ describe('common_utils', () => { ...@@ -536,10 +556,10 @@ describe('common_utils', () => {
it('should set page favicon to provided favicon overlay', done => { it('should set page favicon to provided favicon overlay', done => {
commonUtils commonUtils
.setFaviconOverlay(overlayDataUrl) .setFaviconOverlay(overlayDataUrl)
.then(() => { .then(() => document.getElementById('favicon').getAttribute('href'))
expect(document.getElementById('favicon').getAttribute('href')).toEqual( .then(url => Promise.all([urlToImage(url), urlToImage(faviconWithOverlayDataUrl)]))
faviconWithOverlayDataUrl, .then(([actual, expected]) => {
); expect(actual).toImageDiffEqual(expected, PIXEL_TOLERANCE);
done(); done();
}) })
.catch(done.fail); .catch(done.fail);
...@@ -582,10 +602,10 @@ describe('common_utils', () => { ...@@ -582,10 +602,10 @@ describe('common_utils', () => {
commonUtils commonUtils
.setCiStatusFavicon(BUILD_URL) .setCiStatusFavicon(BUILD_URL)
.then(() => { .then(() => document.getElementById('favicon').getAttribute('href'))
const favicon = document.getElementById('favicon'); .then(url => Promise.all([urlToImage(url), urlToImage(faviconWithOverlayDataUrl)]))
.then(([actual, expected]) => {
expect(favicon.getAttribute('href')).toEqual(faviconWithOverlayDataUrl); expect(actual).toImageDiffEqual(expected, PIXEL_TOLERANCE);
done(); done();
}) })
.catch(done.fail); .catch(done.fail);
......
import pixelmatch from 'pixelmatch';
export default { export default {
toContainText: () => ({ toContainText: () => ({
compare(vm, text) { compare(vm, text) {
...@@ -54,4 +56,41 @@ export default { ...@@ -54,4 +56,41 @@ export default {
return result; 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.`,
};
},
};
},
}; };
...@@ -7735,6 +7735,13 @@ pinkie@^2.0.0: ...@@ -7735,6 +7735,13 @@ pinkie@^2.0.0:
resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
pixelmatch@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/pixelmatch/-/pixelmatch-4.0.2.tgz#8f47dcec5011b477b67db03c243bc1f3085e8854"
integrity sha1-j0fc7FARtHe2fbA8JDvB8wheiFQ=
dependencies:
pngjs "^3.0.0"
pkg-dir@^1.0.0: pkg-dir@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4"
...@@ -7766,6 +7773,11 @@ pn@^1.1.0: ...@@ -7766,6 +7773,11 @@ pn@^1.1.0:
resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb"
integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==
pngjs@^3.0.0:
version "3.3.3"
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.3.3.tgz#85173703bde3edac8998757b96e5821d0966a21b"
integrity sha512-1n3Z4p3IOxArEs1VRXnZ/RXdfEniAUS9jb68g58FIXMNkPJeZd+Qh4Uq7/e0LVxAQGos1eIUrqrt4FpjdnEd+Q==
pofile@^1: pofile@^1:
version "1.0.11" version "1.0.11"
resolved "https://registry.yarnpkg.com/pofile/-/pofile-1.0.11.tgz#35aff58c17491d127a07336d5522ebc9df57c954" resolved "https://registry.yarnpkg.com/pofile/-/pofile-1.0.11.tgz#35aff58c17491d127a07336d5522ebc9df57c954"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment