How to mock navigator.geolocation in a LWC?

Having a component that uses the embedded geolocation feature to get coordinates, how can I mock the call in a Jest test?

The component’s code work in the org:

...

get locationService () {
    return navigator.geolocation
}

...

getCurrentPosition () {
    if (this.locationService) {
        let component = this
        this.locationService.getCurrentPosition(position => {
            component.markers = [{
                location: {
                    Latitude: position.coords.latitude,
                    Longitude: position.coords.longitude
                },
                title: 'You are here!'
            }]
            component.coordinates.lat = position.coords.latitude
            component.coordinates.lon = position.coords.longitude
        })
    }
}

...

But how can I test it, since having the following mock implementation results in an error when calling afterEach?

it('Should display the coordinate.', () => {

    const mockGeolocation = {
        getCurrentPosition: jest.fn()
            .mockImplementation((success) => Promise.resolve(success({
                coords: {
                    latitude: 10,
                    longitude: 10
                }
            })))
    }

    navigator.geolocation = mockGeolocation

    ...


    ... rest of the test goes below
})

The error on afterEach is this one on the terminal:

Assert Violation: undefined is not a vm.

      36 |     afterEach(() => {
      37 |         while (document.body.firstChild) {
    > 38 |             document.body.removeChild(document.body.firstChild)
         |             ^
      39 |         }
      40 |         jest.clearAllMocks()
      41 |     })

The error doesn’t show up if I comment out the line that assigns the mockGeolocation object to the navigator.geolocation:

// navigator.geolocation = mockGeolocation

Answer

Most info copied from discussion on the sample git commit here.

The technique you used to mock out the navigator.geolocation API is fine. The relevant code block from the original question is the following:

const mockGeolocation = {
    getCurrentPosition: jest.fn().mockImplementation((success) => 
        Promise.resolve(
            success({
                coords: {
                    latitude: 10,
                    longitude: 10
                }
            })
        )
    )
}

navigator.geolocation = mockGeolocation

The error referenced in the question is because a property was attempted to be accessed which did not have the @api decorator attached to it, making it a private property and inaccessible from the test case.

Attribution
Source : Link , Question Author : Renato Oliveira , Answer Author : TrevorBliss

Leave a Comment