fregante/image-promise

Does not work in jest test environment

ktrungha opened this issue · 5 comments

I have to make changes to the code to make it works
Basically, you need to attach the fullfill function to the Image object before setting the src attribute

Check: https://stackoverflow.com/a/12355031/3785650

That’s the case if you only use the load event, but image-promise also checks the .complete property.

This might be the same as #10. If not, please give more details than “it does not work”

My case is I use jest to test my app in React-redux.
By not working, it means the promise neither resolve nor reject leaving my test app in a hanging state

Does Jest execute in a real browser? If not, it doesn’t sound like the implementation follow the specification. The complete property immediately follows setting naturalWidth and is followed by the load event. image-promise expects either property to be truthy or a load event to fire. They can’t be both falsy without being followed by a load event.

Once one body part has been completely decoded, the user agent must set the img element to the completely available state and queue a task to fire a simple event named load at the img element.

Your situation seems to happen because load fires before naturalWidth is ready and before compleye is false

Either that, or the problem is elsewhere.

Jest does not execute in a real browser, it has its own mock DOM environment. However, that is beside the point.

So you agree that it can

happen because load fires before naturalWidth is ready and before compleye is false

My understanding is that loading image in Jest will lead to error (because we are in a test, no real network activity allowed), so the event for onerror will be fired first, and then your code checks for naturalWidth which is 0, and then the image is in broken state so complete is false

In addition, it is also possible that your code allows a race condition in real browser (it is rare but it can happen) . It happens when the load event is fired right after you check the complete attr, and before the event listener function is registered.

Either way, I think it makes more sense to attach the event listener before setting src. I am forking your code, thanks for the base

that is beside the point.

That is the whole point. If the mock DOM environment does it wrong, it's not image-promise's bug.

so the event for onerror will be fired first, and then your code checks for naturalWidth which is 0, and then the image is in broken state so complete is false

Incorrect. complete is true whether it's loaded or not (errored or no-src at all).

demo code
img = new Image();
img.addEventListener("error", err => {
  // attached first to log all errors
  console.error(err);
  console.log("complete (pre-attached event):", img.complete);
});
img.src = "///broken"; // fails on github.com
img.addEventListener("error", err => {
  // attached later to see if it's still fired
  console.log("complete (post-attached event):", img.complete);
});
console.log("complete (sync):", img.complete);

screen shot 2017-12-29 at 12 00 16

attach the event listener before setting src

I can't do that because image-promise also accepts DOM nodes that are already loading. I can't have it behave differently based on input.