jonathanpuc
jonathanpuc

Reputation: 179

React jest testing. Cannot read property 'maps' of undefined with google js api

Hi guys I've setup the Google Maps JavaScript API and its working all fine, but my tests all fail now with the error

TypeError: Cannot read property 'maps' of undefined.

Here is what my component looks like

    import React, { Component } from 'react'
    import { connect } from 'react-redux'
    import List from './List'
    import { fetchPlaces } from '../../store/actions/places'
    const google = window.google
    export class Places extends Component {

    componentDidMount() {

    const pyrmont = { lat: -33.866, lng: 151.196 };

    const service = new google.maps.places.PlacesService(document.getElementById('map'))
    // this.props.fetchPlaces('fitzroy')
    const request = {
        location: pyrmont,
        radius: 500, type:
            ['restaurant'],
        placeId: 'ChIJN1t_tDeuEmsRUsoyG83frY4',
        fields: ['name', 'rating', 'formatted_phone_number', 'geometry']
    };

    service.nearbySearch(request, callback);


    function callback(place, status) {
        if (status == google.maps.places.PlacesServiceStatus.OK) {
            console.log(place)
        }
    }

   }
....rest of component

Here's what my test looks like

    import React from 'react'
    import { render, renderIntoDocument } from 'react-testing-library'
    import 'jest-dom/extend-expect'
    import { Places } from '../../Places/Places'

   const baseProps = {
    fetchPlaces: jest.fn(),
   };

    test('it shows a loading message when places are being loaded on mount', () => {
    const { container } = render(<Places loading={true} places={[]} {...baseProps} />)
    expect(container).toHaveTextContent('Loading')
    });

First line of the error stack is "at Places.componentDidMount (src/components/Places/Places.js:13:34)"

EDIT: I've setup a mock of the google api in my test file and if I console.log the google object its no longer undefined but I still get the same error in my test.

const setupGoogleMock = () => {

const google = {
    maps: {
        places: {
            AutocompleteService: () => { },
            PlacesServiceStatus: {
                INVALID_REQUEST: 'INVALID_REQUEST',
                NOT_FOUND: 'NOT_FOUND',
                OK: 'OK',
                OVER_QUERY_LIMIT: 'OVER_QUERY_LIMIT',
                REQUEST_DENIED: 'REQUEST_DENIED',
                UNKNOWN_ERROR: 'UNKNOWN_ERROR',
                ZERO_RESULTS: 'ZERO_RESULTS',
            },
        },
        Geocoder: () => { },
        GeocoderStatus: {
            ERROR: 'ERROR',
            INVALID_REQUEST: 'INVALID_REQUEST',
            OK: 'OK',
            OVER_QUERY_LIMIT: 'OVER_QUERY_LIMIT',
            REQUEST_DENIED: 'REQUEST_DENIED',
            UNKNOWN_ERROR: 'UNKNOWN_ERROR',
            ZERO_RESULTS: 'ZERO_RESULTS',
        },
    },
};
      global.window.google = google;
    };

    beforeAll(() => {
        setupGoogleMock();
    });

Upvotes: 2

Views: 7209

Answers (2)

zernab hussain
zernab hussain

Reputation: 384

Some modules might not work well inside a testing environment, or may not be as essential to the test itself. Mocking out these modules with dummy replacements can make it easier to write tests for your own code. Click Here For Detail

import MockedMap from "./map";

jest.mock("./map", () => {
  return function DummyMap(props) {
    return (
      <div data-testid="map">
        {props.center.lat}:{props.center.long}
      </div>
    );
  };
});

Upvotes: 0

SheaDev
SheaDev

Reputation: 36

I ran ran into a similar issue today, with an error of: TypeError: window.google.maps.places.AutocompleteService is not a constructor

I found a fix from CRA issue #955 - here

Basically you change the AutoCompleteService line to Autocomplete: class {}. Keep the rest of that mock file the same.

Although, the test that I have (which is now passing) is just the basic CRA initial test of 'it renders without crashing' but it should work out for you as well

Upvotes: 2

Related Questions