Let's say you have an Angular app that's showing a list of places. There is a button to get your current location, and clicking the button orders the list according to distance from your location, nearest first.
To test this in Protractor you want to be able to click the button and inspect the list:
it('Should order items according to distance', function () {
locButton.click();
expect(...).toBe(...); // Check that the first item on the list
// the closest to the given lat/long
});
Now, let's say the button calls a method in a controller, the controller calls a method in a service, and the service calls navigator.geolocation.getCurrentPosition() (and, for good measure, that call is wrapped in a promise). The best way to test this is to mock the call to getCurrentPosition() and return a specific latitude and longitude, so that has the required effects all the way back up the chain to the page output. How do you set that up that mock?
I tried the method in this answer to a similar question about Jasmine, creating a spy on navigator.geolocation, with the result:
ReferenceError: navigator is not defined
I also tried mocking the service with something similar to this answer with the result:
ReferenceError: angular is not defined
Update: Found a solution so I answered my own question below, but I'm really, really hoping there's a better answer than this.