Can anyone help me with testing of following function
function onload(cb){
const image = 'http://placehold.it/350x150'
const img = new Image()
img.src = image
img.onload = () => {
cb()
}
}
In my test file Image
is available via jsdom. I want that I can test that cb
is calledOnce
Initializing JSDOM with resources: 'usable'
should normally be enough with the latest API (v10+
):
const jsdom = new JSDOM('<!doctype html><html><body></body></html>',{
resources: 'usable'
});
const { window } = jsdom;
It requires the canvas
(canvas or canvas-prebuilt) module as stated in JSDOM doc.
Using the latest canvas
module, you can mock the window.Image
to trigger load
events.
So first create a mock for the window.Image
class:
import CanvasImage from 'canvas/lib/image';
import fs from 'fs';
import path from 'path';
import { URL } from 'url';
import request from 'request';
// Where to fetch assets on the file system when path are provided.
const ASSETS_DIRECTORY = path.join(__dirname,'.');
const WindowImage = function() {
// Reimplemented the following class:
// https://github.com/tmpvar/jsdom/blob/master/lib/jsdom/living/nodes/HTMLImageElement-impl.js
// https://github.com/Automattic/node-canvas#imagesrcbuffer
let source;
let image;
let onload;
let onerror;
return {
set src (value) {
// TODO Throw errors to the Image.onerror handler.
const onDataLoaded = function (data) {
image = new CanvasImage();
image.onload = () => {
if (onload) {
onload(image);
}
};
image.onerror = err => {
if (onerror) {
onerror(err);
}
};
image.src = data;
source = value;
};
// URL or path?
let url;
try {
url = new URL(value);
} catch (e) {}
// Fetch the data.
if (url) {
request(url.href, (error, response, body) => {
if (response && response.statusCode !== undefined && response.statusCode !== 200) {
throw new Error("Status code: " + response.statusCode);
}
onDataLoaded(body);
});
} else {
// Assume it is a file path: try a local file read.
fs.readFile(path.join(ASSETS_DIRECTORY,value),function (err,data) {
if (err) {
throw err;
}
onDataLoaded(data);
});
}
},
set onload (handler) {
onload = handler;
},
set onerror (handler) {
onerror = handler;
},
get src () {
return source;
},
// TODO Should allows to modify height and width
// + add natural height and width
// Cf. https://github.com/tmpvar/jsdom/blob/master/lib/jsdom/living/nodes/HTMLImageElement-impl.js#L51
get width () {
return image && image.width;
},
get height () {
return image && image.height;
}
};
};
Then you can mock window.Image
in your tests, by redefining the one used by JSDOM:
window.Image = WindowImage;
This is not really elegant, but it gives you control over how image data is loaded, as canvas.Image.src
can normally take any Buffer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With