// CODE
var catalogDOM = (function() {
return {
updateAvailabilityForItem: function(quant) {
console.log(">>>> in updateAvailabilityForItem")
},
syncAvailability: function() {
return new Promise(function(resolve, reject) {
...
})
}
}
})();
$(document).on("click", ".item_info", function() {
console.log(">> calling sync")
catalogDOM.syncAvailability()
.catch(function() {
console.log(">>> caught")
catalogDOM.updateAvailabilityForItem(0)
})
})
// SPEC
describe("click on item_info", function() {
beforeEach(function() {
info_btn = affix(".item_info")
spyOn(catalogDOM, "updateAvailabilityForItem")
syncFunction = spyOn(catalogDOM, "syncAvailability")
syncFunction.and.returnValue(new Promise(function(resolve, reject) {reject()}))
info_btn.click()
})
it("should call updateAvailabiliytForItem", function() {
expect(catalogDOM.updateAvailabilityForItem).toHaveBeenCalledWith(0)
})
})
// CONSOLE OUTPUT
>> calling sync
>>> caught
>>>> in updateAvailabilityForItem
The above spec is failing, moreover, I can see via console, see messages above, that catalogDOM.updateAvailabilityForItem
is actually being called through... is there something about the promise set up that negates the spy?
The issue is that the promise is happening asynchronously (at a later point in time) and when you expect, it is too early.
For a quick unblock, you can wrap you expectation in a setTimeout
which will lower the priority of what's happening in the setTimeout
to after the promise but I am not sure if this is a good approach.
// add done to function argument
it("should call updateAvailabiliytForItem", function(done) {
setTimeout(() => {
expect(catalogDOM.updateAvailabilityForItem).toHaveBeenCalledWith(0);
// call done to let Jasmine know your asynchronous work is done.
done();
}, 100);
})
You can read more about testing asynchronous stuff in Jasmine here: https://jasmine.github.io/tutorials/async
I usually use async/await
for asynchronous tasks.