Testing image loading using jsdom, sinon, mocha and chai

Can someone help me with testing the 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 through jsdom. I want so that I can verify that cb is called cb

+5
source share
1 answer

Option 1: Actively loading external resources in JSDOM

Initializing the JSDOM with resources: 'usable' should usually be sufficient using the latest API ( v10+ ):

 const jsdom = new JSDOM('<!doctype html><html><body></body></html>',{ resources: 'usable' }); const { window } = jsdom; 

This requires a canvas ( canvas or canvas-prebuilt ) as specified in the JSDOM doc .


Option 2: mock window.Image to gain control over it

Using the latest canvas module, you can mock window.Image to fire load events.

So, first create a layout 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; } }; }; 

You can then mock window.Image in your tests by overriding the one used by JSDOM:

 window.Image = WindowImage; 

This is not very elegant, but it gives you the ability to control the loading of image data, since canvas.Image.src can usually accept any buffer.

0
source

Source: https://habr.com/ru/post/1257927/


All Articles