Deactivating the Google Maps JS API loader in Cypress Testing

In my application, I am utilizing the Google Maps JS API for autocompletion and geocoding. To load the API, I am using the Google Maps JS API Loader package from NPM. During end-to-end testing with Cypress, I attempted to mock the API for testing purposes but encountered challenges in making it functional.

I have abstracted the API functionality into a separate module. Here is a simplified version of how it is loaded and initialized:

import {Loader} from "@googlemaps/js-api-loader";

let loading: Promise<typeof google>;
try {
  loading = new Loader({
    apiKey: "private key",
    libraries: ["places"],
  }).load();
} catch (e) {
  console.error("Failed to load Google Maps API");
}

class GoogleMapsAPI {
  // Class implementation details here...
}

async function loadGoogleMapsAPI(): Promise<GoogleMapsAPI | null> {
  // Load logic here...
}

This is how the API is integrated into my React app:

import React, {useEffect, useState} from "react";
import {GoogleMapsAPI, loadGoogleMapsAPI} from "../../services/google";

export default function Site() {
  // React component code here...
}

When attempting to test the functionality, I encountered difficulties related to stubbing out the necessary methods for proper test execution. Despite various attempts, the desired predictions were not being returned as expected.

As I navigate through this testing process with Cypress and frontend code, I seek guidance on effectively handling stubbing and ensuring the correct functioning of the mocked API. Any assistance or insights would be greatly appreciated!

Answer №1

After finding a solution, I decided to replace the loader with inline loading and implemented the following code:

let ready = false;

// The callback function called by the Google Maps API loader script loaded in index.html.
window.initGoogleMapsAPI = function() {
  ready = true;
}

async function waitForGoogleMapsAPI(): Promise<void> {
  return new Promise<void>((resolve) => {
    if (ready) {
      resolve();
    }
  })
}

...

async function loadGoogleMapsAPI(): Promise<GoogleMapsAPI | null> {
  // Wait for the loader to load the API, then return the API class.
  try {
    await waitForGoogleMapsAPI;

    return new GoogleMapsAPI();
  } catch (e) {
    console.error(`Google Maps API could not be loaded: ${e}`);
  }

  return null;
}

To ensure proper testing, I exported the waitForGoogleMapsAPI function and created a mock for it in the test.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Performing an insertion in TypeORM with a foreign key connection

In my database schema, I have set up a relationship where each Chatroom can have multiple Messages linked to it. However, when I try to insert a Message (or a batch of Messages), the foreign key for ChatRoom is not being assigned properly and remains null. ...

Mocha experiences a timeout when the method attempts to parse the body of the

Preamble: Despite looking at this question on Stack Overflow, I did not find any helpful solutions. The suggested solution of using async and await did not resolve the issue for me. This TypeScript test was created using Mocha and Supertest: it('retu ...

The NextJS API route functions flawlessly when tested locally, generating over 200 records. However, upon deployment to Vercel, the functionality seems to

Here is the API route that I am using: https://i.stack.imgur.com/OXaEx.png Below is the code snippet: import type { NextApiRequest, NextApiResponse } from "next"; import axios from "axios"; import prisma from "../../../lib/prisma ...

The NgRX Effect is malfunctioning

Working on integrating ngrx with Angular. Authentication is successful, but facing issues with product store implementation: Organizing the project using modules: const routes: Routes = [ { path: '', redirectTo: 'home', ...

Tips for ensuring your controls function properly and seamlessly when switching to another page

I utilized the instructions from this post to implement a slider. However, I encountered an issue with the controller when navigating to subsequent pages. While the controller functions correctly on the initial page, it duplicates the same values on the fo ...

Enhance the API response for Angular service purposes

I am currently working on modifying the response returned by an API request. At the moment, I receive the response as: [ { name: "Afghanistan" }, { name: "Åland Islands" } ] My goal is to adjust it to: [ { name: "A ...

Ways of modifying the readonly and required attributes of an HTML element using Angular2 Typescript

I am facing an issue with changing input field attributes back and forth in some of my components. I have a code that successfully changes the readonly attribute as needed. However, when trying to change the required attribute, Angular2 still considers the ...

Issue encountered while executing jest tests - unable to read runtime.json file

I've written multiple unit tests, and they all seem to pass except for one specific spec file that is causing the following error: Test suite failed to run The configuration file /Users/dfaizulaev/Documents/projectname/config/runtime.json cannot be r ...

Issues with the inheritance functionality in styled components are causing errors

The issue arises when I try to customize the styling of my PrimaryButton component, separate from the DefaultButton. Despite writing style properties for it, the changes do not take effect. Here is the folder structure: https://i.stack.imgur.com/0KjyH.pn ...

Utilizing SCSS variables

Currently, I am in the process of developing an Angular 4 application using angular-cli and have encountered a minor issue. I am attempting to create a component that has the ability to dynamically load styling. The ComponentX component needs to utilize a ...

Attempting to convert numerical data into a time format extracted from a database

Struggling with formatting time formats received from a database? Looking to convert two types of data from the database into a visually appealing format on your page? For example, database value 400 should be displayed as 04:00 and 1830 as 18:30. Here&apo ...

Problem with Grouping of Columns in Material-UI

Having some trouble with column grouping in MUI data grid pro. I am using typescript and trying to implement column grouping, but encountering issues with the module GridColumnGroupingModel, which is used as the type definition for columnGroupingModel. Fol ...

What is the method to dynamically add an error to a FormGroup control using programming?

I am working with a dynamic FormGroup and I need to add an error to a form control programmatically. However, the current method I know of replaces any existing errors as shown below: this.userForm.controls.username.setErrors({ 'exists': &apos ...

"Protractor encountered an issue when navigating to the most up-to-date Angular section in our

We are in the process of upgrading our application from AngularJS to the latest version of Angular. I am currently working on writing tests that transition from the AngularJS version of the app to the admin application, which is built using the latest ver ...

Show the current status of an API call in React using TypeScript

As a beginner in React and TypeScript, I'm working on calling a Graph API using POST method. Below is my code snippet: const OwnerPage: React.FunctionComponent = () => { const [TextFieldValue, setTextFieldValue] = React.useState('& ...

Typescript has a knack for uncovering non-existent errors

When I attempted to perform a save operation in MongoDB using Mongoose, the code I initially tried was not functioning as expected. Upon conducting a search online, I came across a solution that worked successfully; however, TypeScript continued to flag an ...

Declaring a subclass type in Typescript: A step-by-step guide

Would it be feasible to create something like this? export abstract class FilterBoxElement { abstract getEntities: any; } export interface FilterBoxControlSuggestions extends FilterBoxElement { getEntities: // some implementation with different pa ...

The parameter 'CallHistoryMethodAction<[string, unknown?]>' does not match the 'UserActionType' parameter

Using a development environment with React, TypeScript, and connected-react-router. My Intention: I aim to utilize the router action asynchronously within the user action. After successful login, I want the application to navigate to the main screen. Err ...

Building package dependencies for TypeScript bundled projects: a comprehensive guide

Currently, I am developing a TypeScript module that relies on another TypeScript-based project called winston. The types for winston are bundled in an index.d.ts file, and there is no @types/winston package available as a "devDependency". From what I gat ...

How can I transfer data between methods within Angular?

Help Needed: I have a service file with two methods, each having its own API. I want to call the getData method within the deleteData method. Can anyone guide me on how to achieve this? .service.file getData(): Promise<PagedResult<Sites>> { ...