Tag Archives: Spies

Spying on native functions in Jasmine

Recently I’ve been getting really into Jasmine spies. I’ve come across plenty of people online talking about the basics of how to use spies in Jasmine. They’re great resources and I’m indebted to them, but I don’t think they really do Spies justice. Spies are incredible. I feel like now I’m really starting to get my head around them and wanted to talk about that.

This week I’ve been using Spies to spy on native functions. It’s possible that the reason I’ve never found anyone else talking about doing this is it’s a bad idea, or so basic that no one else has thought to mention it before. I find it important to never discount the idea that I might be an idiot.. However, this wasn’t obvious to me at first and has proven devilishly useful so here’s what I’ve been up to.

It all started with testing a form submission. In the natural course of events this would take us off the page running the Jasmine tests, or create an endless loop of page refreshes. It occurred to me that there had to be a function behind the form submission hidden somewhere, and if I could spy on that, it’d prevent the form submitting and I could get on with my life. I can even use it to check that the form submission has been called. Sure enough, a bit of poking around revealed that:
spyOn(HTMLFormElement.prototype, 'submit');
Gives you a spy on the native submit function. It makes perfect sense really, of course the HTMLFormElement prototype has a submit function attached to it, and why shouldn’t Jasmine be able to spy on it? And with that one line, the headache of not refreshing or leaving your spec runner on form submissions goes away.

Pleased with this little trick I later came up against a bit of code that needed testing. It took an uploaded image file, converted it into an Image object and looked at scaled it to fit the user’s screen size. We’ve dabbled in actually uploading images for another image uploader test in the past. It was horrible and involved adding a timeOut into the test then hoping it was long enough. We eventually took that out. Keen not to re-introduce it, I figured if I could spy on a Form submission then why not spy on the Image object constructor? Sure enough:
spyOn(window, 'Image')
let me spy on that constructor, so I could then get it to return a mock object with just the information needed for the test.
spyOn(window, 'Image').andReturn({width: 100, height: 200});

Alas, I can’t claim to understand the inner workings of JavaScript well enough to predict what object any given function is attached to. I had assumed that the Image constructor would be attached to document, but turned out it’s on the window. There’s probably some easy way to look it up if you know where to look. If I were a better person, that last sentence would have been a link to that resource but I don’t have it, just assume it exists somewhere.

So anyone who, like me, didn’t find this immediately obvious I encourage you to go out and give it a try. Then if it creates some sort of horrible mess come back and let me know why I shouldn’t be doing it either. Remember, I may well be an idiot.

Tagged , , , , ,