How do unit test on 'window.open' (javascript) using sinon - javascript

this is the code I have to test:
myFunction: function(data) {
var file = new Blob(data, {type: 'text/plain'});
window.open(window.URL.createObjectURL(file));
}
In order to test it, I thought to test if the window.open function is called, applying a 'spy' on window.open , in the following way:
sandbox.spy(window, 'open');
but, even leaving previous line as the unique line in the test, what I only get is the test failure and the following message:
global leaks detected: consoleLogging, open
Thus, in order to avoid that, I tried to re-define the function in the test in this way:
global.window = {
open: function (url) {}
};
In this case an exception raised:
Attempted to assign to readonly property
Then I tried to mock the 'open' via the following:
sandbox.mock(window, 'open');
objectUnderTest.myFunction();
expect(window.open.callCount).to.equal(1);
this way, I get no global or readonly errors, but an exception on the 'expect', telling that:
expected undefined to equal 1
Does someone knows a way to successfully test window.open?

Here is the unit test solution based on Node.js environment:
index.js:
const obj = {
myFunction: function(data) {
var file = new Blob(data, { type: 'text/plain' });
window.open(window.URL.createObjectURL(file));
}
};
module.exports = obj;
index.spec.js:
const obj = require('./');
const sinon = require('sinon');
const { expect } = require('chai');
describe('53524524', () => {
before(() => {
class Blob {}
global.Blob = Blob;
global.window = {
open() {},
URL: {
createObjectURL() {}
}
};
});
it('should test myFunction correctly', () => {
const openStub = sinon.stub(window, 'open');
const createObjectURLStub = sinon.stub(global.window.URL, 'createObjectURL').returns('fake object url');
obj.myFunction('fake data');
expect(createObjectURLStub.calledOnce).to.be.true;
expect(openStub.calledWith('fake object url')).to.be.true;
});
});
Unit test result with coverage report:
53524524
✓ should test myFunction correctly
1 passing (11ms)
---------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
---------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 66.67 | 100 | |
index.js | 100 | 100 | 100 | 100 | |
index.spec.js | 100 | 100 | 60 | 100 | |
---------------|----------|----------|----------|----------|-------------------|
Source code: https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/53524524

Related

Unit test class constructor and method with Jest

I'm trying to figure out how to perform unit tests, with Jest, on my code but I have been struggling with this. I want to be able to test the constructor and the method in my unit test but I can't understand how to do it in an efficient way.
class CommandOption {
constructor(commands) {
this.section = commands[0]
this.method = commands[1]
this.command1 = commands[2]
}
option(optionName) {
return require(`../commands/options/${optionName}`)(this)
}
}
I know that I can test the constructor fairly easily, in this case, but I don't know if it is good way or not.
const CommandOption = require('./command-option')
it('should equal "hardware", "get", and "byid"', () => {
let commandOption = new CommandOption(['hardware','get','byid'])
expect(commandOption.section).toBe('hardware')
expect(commandOption.method).toBe('get')
expect(commandOption.command1).toBe('byid')
}
I don't really know how to go about mocking the option method from there... I have read about using jest.spyOn() but I can't seem to wrap my head around it for my case... probably because I am trying to overthink it.
Unit test solution:
command-option.js:
class CommandOption {
constructor(commands) {
this.section = commands[0];
this.method = commands[1];
this.command1 = commands[2];
}
option(optionName) {
return require(`./commands/options/${optionName}`)(this);
}
}
module.exports = CommandOption;
command-option.test.js:
const CommandOption = require('./command-option');
describe('64327189', () => {
it('should equal "hardware", "get", and "byid"', () => {
let commandOption = new CommandOption(['hardware', 'get', 'byid']);
expect(commandOption.section).toBe('hardware');
expect(commandOption.method).toBe('get');
expect(commandOption.command1).toBe('byid');
});
it('should load option by name', () => {
const optionSetter = jest.fn();
jest.doMock('./commands/options/host', () => optionSetter);
let commandOption = new CommandOption(['hardware', 'get', 'byid']);
const optionName = 'host';
commandOption.option(optionName);
expect(optionSetter).toBeCalledWith(commandOption);
});
});
commands/options/host.js:
// whatever
unit test result with coverage report:
PASS src/stackoverflow/64327189/command-option.test.js
64327189
✓ should equal "hardware", "get", and "byid" (4ms)
✓ should load option by name (3ms)
-------------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
-------------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
command-option.js | 100 | 100 | 100 | 100 | |
-------------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 4.848s, estimated 10s

Mock the return value of an imported function in Typescript with Jest

I have a function, lets call it generateName, which as you’ve guessed it, generates a name. The problem is that a new name is generated each time time a test is ran.
In one of my tests, I assert that a function is called with an object containing this name. However, the name keeps on changing. I could just check that the object has property name, but I don’t really want to do that.
My idea is that I can mock the return value of the generateName function and do something like this
Import { generateName } from ‘libs/generateName’
jest.fn(generateName).mockResolvedValue ( ‘hello’ )
expect ( spy ).toHaveBeenCalledWith (
expect.objectContaining ( {
name: 'houses',
} )
)
You can use jest.mock(moduleName, factory, options) to mock libs/generateName module.
E.g.
generateName.ts:
export async function generateName() {
const name = Math.random() + '';
return name;
}
main.ts:
import { generateName } from './generateName';
export function main() {
return generateName();
}
main.test.ts:
import { main } from './main';
import { generateName } from './generateName';
jest.mock('./generateName', () => {
return {
generateName: jest.fn(),
};
});
describe('61350152', () => {
it('should pass', async () => {
(generateName as jest.MockedFunction<typeof generateName>).mockResolvedValueOnce('hello');
const actual = await main();
expect(actual).toBe('hello');
});
});
unit test results with coverage report:
PASS stackoverflow/61350152/main.test.ts (28.524s)
61350152
✓ should pass (6ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
main.ts | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 31.98s

Sinon - spy to wrap *any* property access on object

I have a function that looks roughly like this:
import {someLibraryMethod} from 'someLibrary';
function setFullWidth(el) {
someLibraryMethod(el);
el.setAttribute('width', '100%');
}
I'm testing this function by using Sinon to create a mock element that only supports setAttribute:
const fakeElement = {
setAttribute: sinon.spy()
};
setFullWidth(fakeElement);
assert(fakeElement.setAttribute.calledWithExactly('width', '100%'));
The problem is that someLibraryMethod assumets el is an HTML element and tries to call some other methods on it, such as hasAttribute. I could add these as stubs or spies to fakeElement too, but I was wondering if Sinon has a way to create an object that will spy on any method or property access on it?
Something like:
const fakeElement = sinon.spyOnAnyPropety();
fakeElement.setAttribute(); // valid
fakeElement.hasAttribute(); // valid
fakeElement.foo(); // also valid
// some way to check which methods were called
You can use sinon.stub(obj) to
Stubs all the object’s methods.
E.g.
index.ts:
export function setFullWidth(el) {
el.setAttribute('width', '100%');
el.hasAttribute('width');
el.foo();
}
index.spec.ts:
import { setFullWidth } from './';
import sinon, { SinonStubbedInstance } from 'sinon';
import { expect } from 'chai';
describe('58868361', () => {
const fakeElement = {
setAttribute(attr, value) {
console.log('setAttribute');
},
hasAttribute(attr) {
console.log('hasAttribute');
},
foo() {
console.log('foo');
},
};
afterEach(() => {
sinon.restore();
});
it('should spy all methods of el', () => {
const logSpy = sinon.spy(console, 'log');
const stub: SinonStubbedInstance<typeof fakeElement> = sinon.stub(fakeElement);
setFullWidth(fakeElement);
expect(stub.setAttribute.calledWithExactly('width', '100%')).to.be.true;
expect(stub.hasAttribute.calledWithExactly('width')).to.be.true;
expect(stub.foo.calledOnce).to.be.true;
expect(logSpy.callCount).to.be.equal(0);
logSpy.restore();
});
it('should restore to original methods of el', () => {
const logSpy = sinon.spy(console, 'log');
setFullWidth(fakeElement);
expect(logSpy.callCount).to.be.equal(3);
});
});
Unit test result with 100% coverage:
58868361
✓ should spy all methods of el
setAttribute
hasAttribute
foo
✓ should restore to original methods of el
2 passing (13ms)
---------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
---------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.spec.ts | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
---------------|----------|----------|----------|----------|-------------------|
Source code: https://github.com/mrdulin/mongoose5.x-lab/tree/master/src/stackoverflow/58868361

Mock jQuery method call on an object created inside function under test

I'm creating a jQuery object inside a function that I'm testing. I need to mock the prop method call.
How can I do this? I'm using Jest. I tried with Sinon as well, but I couldn't get this working.
Here's my method:
import $ from 'jquery';
export function myFunc(element) {
var htmlControl = $(element);
var tagName = htmlControl.prop('tagName');
}
Here is the unit test solution using sinonjs:
index.ts:
import $ from 'jquery';
export function myFunc(element) {
var htmlControl = $(element);
var tagName = htmlControl.prop('tagName');
}
index.spec.ts:
import proxyquire from 'proxyquire';
import sinon from 'sinon';
import { expect } from 'chai';
describe('myFunc', () => {
it('should mock prop() method', () => {
const el = {};
const propStub = sinon.stub().returnsThis();
const jqueryStub = sinon.stub().callsFake(() => {
return {
prop: propStub
};
});
const { myFunc } = proxyquire('./', {
jquery: jqueryStub
});
myFunc(el);
expect(jqueryStub.calledWith(el)).to.be.true;
expect(propStub.calledWith('tagName')).to.be.true;
});
});
Unit test result with 100% coverage:
myFunc
✓ should mock prop() method (156ms)
1 passing (161ms)
---------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
---------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.spec.ts | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
---------------|----------|----------|----------|----------|-------------------|
Source code: https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/57461604

sinon stubbed class not found

I started to write unit test cases using sinon and facing the following problem.
myfile.js
module.exports = class A{
constructor(classB_Obj){
this.classBobj = classB_Obj;
classBobj.someFunctionOfClassB(); // error coming here
}
doSomething(){
}
}
where class B is in
myfile2.js
module.exports = class B{
constructor(arg1, arg2){
this.arg1 = arg1;
this.arg2 = arg2;
}
someFunctionOfClassB(){
}
}
when I test class A and use sinon to stub Class B
const myfile2 = require('../myfile2').prototype;
const loggerStub = sinon.stub(myfile2, 'someFunctionOfClassB');
while executing it gives exception
classBobj.someFunctionOfClassB is not a function.
What is the correct way of stubbing it? I don't want to instantiate class B.
This has really nothing to do with stubbing.
You have to define this function as a static method to achieve this:
module.exports = class B{
constructor(arg1, arg2){
this.arg1 = arg1;
this.arg2 = arg2;
}
static someFunctionOfClassB(){
}
}
Then you can call the method on the class object.
When you write a normal class method you always have to instantiate the class before you can you use it on the instance:
const b = new class_Obj();
b.someFunctionOfClassB();
See also: Class vs. static method in JavaScript
Here is the unit test solution:
myfile.js:
module.exports = class A {
constructor(classB_Obj) {
this.classBobj = classB_Obj;
this.classBobj.someFunctionOfClassB();
}
doSomething() {}
};
myfile2.js:
module.exports = class B {
constructor(arg1, arg2) {
this.arg1 = arg1;
this.arg2 = arg2;
}
someFunctionOfClassB() {}
};
myfile.test.js:
const A = require("./myfile");
const B = require("./myfile2");
const sinon = require("sinon");
describe("52559903", () => {
afterEach(() => {
sinon.restore();
});
it("should pass", () => {
const bStub = sinon.createStubInstance(B, {
someFunctionOfClassB: sinon.stub(),
});
new A(bStub);
sinon.assert.calledOnce(bStub.someFunctionOfClassB);
});
});
Unit test result with coverage report:
myfile
✓ should pass
1 passing (10ms)
----------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------------|----------|----------|----------|----------|-------------------|
All files | 87.5 | 100 | 57.14 | 87.5 | |
myfile.js | 100 | 100 | 50 | 100 | |
myfile.test.js | 100 | 100 | 100 | 100 | |
myfile2.js | 33.33 | 100 | 0 | 33.33 | 3,4 |
----------------|----------|----------|----------|----------|-------------------|
Source code: https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/52559903

Categories

Resources