How to mock Google Places with Cypress
If you've ever tried to mock a Google Places services response by copy-pasting a real response, with the aim of catching the request in Cypress intercept and returning that response in a fixture, you'll likely have received an error in your test run.
Why doesn't it work as expected?
If we take a closer look at the response, whether it be the Google autocomplete predictions response or, for example, the Google geocode service response, we'll notice something odd. The stringified JSON has been wrapped and prefixed with some data as in the example below.
/**/_xdc_._arqn3n && _xdc_._arqn3n({
"predictions" : [
...
],
"status" : "OK"
})
This prefixed data is the problem. The values here are expected by the Google package responsible for parsing the response... but they are not always the same. If they don't match up, we get an error.
The solution!
Luckily for us, this data is included in the request URL in a param called callback
. We can extract this value from the URL during the lifecycle of a cy.intercept
and wrap our mock data with it to satisfy the parser and resolve the error.
// Util function stored elsewhere e.g. cypress/utils/
export const wrapResponse = (request, mockData) => {
const searchParams = new URLSearchParams(request.url);
const callbackParam = searchParams.get("callback");
request.reply(`${callbackParam} && ${callbackParam}(${JSON.stringify(mockData)})`);
};
// A cypress intercept making use of the wrapResponse util
cy.intercept(
"https://maps.googleapis.com/maps/api/place/js/AutocompletionService*",
request => wrapResponse(request, mockData)
);
mockData
value is simply the JS object part of the regular response, as if it hadn't been wrapped with all that other stuff.Happy testing!