I have 2 simple functions. First function X either receives a number or string. If it receives a number, I return its double and if it receives a string I call another function Y. How do I test if my function X calls function Y when it receives a string as parameter?
function X(arg) {
if (typeof (arg) === 'String') Y(arg)
else return arg * 2
}
function Y(arg) {
return 'Got empty string'
}
What I want to do in my test..
describe('A function X that checks data type', function() {
it('should call function Y is argument is a string', function() {
let arg = arguments[0]
expect(Y is called if typeof(arg)).toEqual('string')
})
})
A more general answer for these type of problems where 'do X if Y' would be awesome. Thanks :)
You have to create a spy. You can even check the argument with which Y was called. Assuming you defined those functions globally, they belong to the window object:
function X(arg) {
if (typeof (arg) === 'String') Y(arg)
else return arg * 2
}
function Y(arg) {
return 'Got empty string'
}
Your tests:
describe('A function X that checks data type', () => {
beforeEach(() => {
spyOn(window, 'Y')
})
it('should call function Y is argument is a string', () => {
// Call X with a string
window.X('hello')
// If you don't want to check the argument:
expect(window.Y).toHaveBeenCalled()
// If you want to check the argument:
expect(window.Y).toHaveBeenCalledWitH('hello')
})
})
It is worth noticing that using the window object for this kind of things is not the best way to go. If you want to use spies like this you should create an object where you hold your methods.
Documentation on jasmine spies: https://jasmine.github.io/2.0/introduction.html#section-Spies
If you're using Jasmine, you can use Spies: https://jasmine.github.io/2.0/introduction.html#section-Spies
function X(arg) {
if (typeof (arg) === 'string') Y(arg);
else return arg * 2;
}
function Y(arg) {
return 'Got empty string'
}
describe('A function X that checks data type', function() {
it('should call function Y is argument is a string', function() {
spyOn(window, 'Y').and.callThrough();
X('Hello');
expect(window.Y).toHaveBeenCalledWith('Hello');
})
})
Check the working demo here: jsFiddle
And here is how you can handle async Y
function:
jsFiddle - asnyc
function X(arg) {
let deferred = {};
let promise = new Promise(function(res, rej) {
deferred.res = res;
deferred.rej = rej;
});
if (typeof(arg) === 'string') {
setTimeout(function() {
deferred.res(Y(arg));
}, 1000);
return promise;
} else {
return arg * 2;
}
}
function Y(arg) {
console.log('Y with timeout');
return 'Got empty string';
}
describe('A function X that checks data type', function() {
it('should call function Y is argument is a string', function(done) {
spyOn(window, 'Y').and.callThrough();
let promise = X('Hello');
if (promise instanceof Promise) {
promise.then(function() {
expect(window.Y).toHaveBeenCalledWith('Hello');
done();
});
} else {
done();
}
})
})
However I recommend to attach your functions to some objects (modules), to easier track what was called when and where.
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