I want to test my promise function to load an image, the piece of code looks like this:
function imagePromise() {
return new Promise((resolve, reject) => {
const img = new Image();
img.addEventListener('load', () => resolve(true));
img.addEventListener('error', () => reject(false));
img.src = 'http://78.media.tumblr.com/tumblr_lr9mx5Axur1qlyuwso1_1280.jpg';
});
}
When I consume my promise in the browser, it works fine:
imagePromise().then((result) => console.log(result));
// fulfill the promise and log the result: true
However, when I'm testing my promise using ava and browser-env, ava returns an error:
Promise returned by test never resolved
My test file looks like this:
import test from 'ava';
function imagePromise() {
return new Promise((resolve, reject) => {
const img = new Image();
img.addEventListener('load', () => resolve(true));
img.addEventListener('error', () => reject(false));
img.src = 'http://78.media.tumblr.com/tumblr_lr9mx5Axur1qlyuwso1_1280.jpg';
});
}
test('load image with promise', (t) => {
return imagePromise().then((result) => {
t.is(result, true);
});
});
Note that I have both tried addEventListener
and onload
/onerror
methods due to browser compatibility, and browser-env have been configured to work with ava. Is there something I'm missing?
I finally fixed my tests, using browser-env
(which itself uses jsdom
). I've made a small repo for people interested:
My first mistake was I forgot to install canvas-prebuilt
, which allow jsdom
to manipulate images
and canvas
elements.
// install browser-env and canvas-prebuilt
// (https://github.com/jsdom/jsdom#loading-subresources)
yarn add browser-env canvas-prebuilt -D
My second mistake that I forgot to put a special config on the browser-env
declaration for the tests, in the test/helpers/setup-browser-env.js
file:
require('browser-env')(['window', 'document', 'Image'], {
resources: 'usable',
});
Then we can run our image-loading promises tests, from test/test.js
:
import test from 'ava';
function imagePromise() {
return new Promise((resolve, reject) => {
const img = new Image();
img.addEventListener('load', () => resolve(true));
img.addEventListener('error', () => reject(false));
// an heavy 4k wallpaper to check if promise is resolved after a long time
img.src = 'https://www.wallpaperup.com/wallpaper/download/991808/8000/5224';
});
}
test('load image with promise', (t) => {
return imagePromise().then((result) => {
t.is(result, true);
});
});
To run the tests, you can exec ava
but I highly recommend to add --verbose
flag as it helps to debug with --watch
flag (kind of a live-reload for your tests).