The function to be tested:
index.ts
:
function funcToTest(imgUrl: string, callback: Function) {
const img = new Image();
img.src = imgUrl;
img.onload = () => {
callback(true);
};
img.onerror = e => {
callback(false);
console.log(e);
};
return img;
}
export { funcToTest };
/**
* @jest-environment jsdom
*/
import { funcToTest } from './';
describe('test suites', () => {
it('onload', done => {
const callback = jest.fn(status => {
expect(status).toBe(true);
done();
});
const imageUrl = 'https://github.com/mrdulin';
const img = funcToTest(imageUrl, callback);
if (img.onload) {
const event: any = {};
img.onload(event);
}
});
it('onerror', done => {
const consoleLogSpyOn = jest.spyOn(console, 'log');
const callback = jest.fn(status => {
expect(status).toBe(false);
done();
});
const imageUrl = 'https://github.com/mrdulin';
const img = funcToTest(imageUrl, callback);
if (img.onerror) {
const event: any = { message: 'some error' };
img.onerror(event);
expect(consoleLogSpyOn).toBeCalledWith(event);
}
consoleLogSpyOn.mockRestore();
});
});
Unit test result and coverage:
PASS src/stackoverflow/57092154/index.spec.ts
test suites
✓ onload (8ms)
✓ onerror (8ms)
console.log node_modules/jest-mock/build/index.js:860
{ message: 'some error' }
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 3.821s
Here is the completed demo: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/57092154
UPDATE: undeleted answer, unit test solution 2
You can use Object.defineProperty() method to create getter and setter for Image.prototype.onload
method. Then, you can get the onload
function in your test cases and execute it manually.
index.test.ts
:
import { funcToTest } from './';
describe('57092154', () => {
let onloadRef: Function | undefined;
let onerrorRef: Function | undefined;
beforeAll(() => {
Object.defineProperty(Image.prototype, 'onload', {
get() {
return this._onload;
},
set(onload: Function) {
onloadRef = onload;
this._onload = onload;
},
});
Object.defineProperty(Image.prototype, 'onerror', {
get() {
return this._onerror;
},
set(onerror: Function) {
onerrorRef = onerror;
this._onerror = onerror;
},
});
});
it('should handle onload event', () => {
const callback = jest.fn();
funcToTest('./test.png', callback);
onloadRef!();
expect(callback).toBeCalledWith(true);
});
it('should handle onerror event', () => {
const callback = jest.fn();
const logSpy = jest.spyOn(console, 'log').mockImplementation(() => 'suppress error');
funcToTest('./test.png', callback);
const mErr = new Error('network');
onerrorRef!(mErr);
expect(callback).toBeCalledWith(false);
expect(logSpy).toBeCalledWith(mErr);
});
});
unit test result:
PASS examples/57092154/index.test.ts
57092154
✓ should handle onload event (4 ms)
✓ should handle onerror event
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
index.ts | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 3.741 s
img.src = img
to the end offuncToTest
, i.e. after you've defined theonload
/onerror
functions? – user7290573