Installations
npm install @googlemaps/jest-mocks
Score
99.7
Supply Chain
100
Quality
82.2
Maintenance
100
Vulnerability
100
License
Developer
googlemaps
Developer Guide
Module System
CommonJS
Min. Node Version
Typescript Support
Yes
Node Version
20.10.0
NPM Version
10.2.3
Statistics
40 Stars
675 Commits
30 Forks
12 Watching
8 Branches
24 Contributors
Updated on 25 Nov 2024
Languages
TypeScript (98.1%)
JavaScript (1.9%)
Total Downloads
Cumulative downloads
Total Downloads
13,027,601
Last day
-4.9%
19,794
Compared to previous day
Last week
0.3%
104,317
Compared to previous week
Last month
6.6%
501,727
Compared to previous month
Last year
23.7%
5,974,578
Compared to previous year
Daily Downloads
Weekly Downloads
Monthly Downloads
Yearly Downloads
Jest Mocks for Google Maps
Description
Jest mocks for Google Maps in TypeScript.
Note: If you find a missing mock, please open an issue.
NPM
Available via NPM as the package @googlemaps/jest-mocks
Usage
These mocks need the tests to run in a browser-like environment (for example
jest-environment-jsdom
).
Before running the tests, you have to call the exported initialize
function to set up the global namespaces of the mocked Google Maps API:
1import { initialize } from "@googlemaps/jest-mocks"; 2 3beforeEach(() => { 4 initialize(); 5});
You can then run the test-code that makes use of the Maps API almost as normal. "Almost" is referring to the fact that the objects are all non-functional and some things you can do with the real maps API cannot be done with the mocks library.
We also export the mockInstances
object and mocked constructors of all
classes (e.g. Map
or Marker
) that can be used to retrieve, inspect and
configure the mocks.
1import { initialize, Map, Marker, mockInstances } from "@googlemaps/jest-mocks"; 2 3// this represents your code being tested 4function codeUnderTest() { 5 const map = new google.maps.Map(null); 6 const markerOne = new google.maps.Marker(); 7 const markerTwo = new google.maps.Marker(); 8 9 map.setHeading(8); 10 markerOne.setMap(map); 11 markerTwo.setLabel("My marker"); 12} 13 14beforeEach(() => { 15 initialize(); 16}); 17 18test("my test", () => { 19 codeUnderTest(); 20 21 // mockInstances stores the lists of all maps-objects created since 22 // `initialize` was called, organized by constructor. 23 const mapMocks = mockInstances.get(Map); 24 const markerMocks = mockInstances.get(Marker); 25 26 expect(mapMocks).toHaveLength(1); 27 expect(markerMocks).toHaveLength(2); 28 expect(mapMocks[0].setHeading).toHaveBeenCalledWith(8); 29 expect(markerMocks[0].setMap).toHaveBeenCalledTimes(1); 30 expect(markerMocks[1].setLabel).toHaveBeenCalledWith("My marker"); 31 32 // note that this will not work (`map.setHeading(8)` will not update any 33 // internal state of the map): 34 expect(mapMocks[0].getHeading()).toBe(8); 35});
Testing Events
To test code that uses events dispatched by Maps API objects, you can follow a pattern like this:
1import { mockInstances, Map } from "./registry"; 2 3let eventTriggered = false; 4 5function codeUnderTest() { 6 const map = new google.maps.Map(null); 7 const listener = map.addListener("bounds_changed", () => { 8 // whatever happens here should be observeable in some way, for the 9 // sake of this example, we just set a global variable: 10 eventTriggered = true; 11 }); 12} 13 14test("testing events", () => { 15 // run the code under test, which will register an event-listener 16 codeUnderTest(); 17 18 // since `map.addListener` doesn't actually do anything, we'll have to 19 // retrieve the event-handler function and trigger the event ourselves 20 const map: google.maps.Map = mockInstances.get(Map); 21 const addListener: jest.MockedFunction<typeof map.addListener> = 22 map.addListener; 23 24 expect(addListener).toHaveBeenCalledTimes(1); 25 26 const [eventType, listener] = addListener.mock.lastCall; 27 28 // call the listener function (for mouse-events you'd have to create the 29 // event-object here as well) 30 listener(); 31 32 // assert that whatever the effect of your code receiving the event happened 33 expect(eventTriggered).toBe(true); 34});
Extending Mocks
There are situations where you need some more functionality from the mocks than what is provided by this library. In these cases, you can extend the existing mocks.
For example, if you want to observe the creation of a Map instance to validate constructor-arguments, you can add a spy function like this:
1let createMapSpy: jest.Mock< 2 void, 3 ConstructorParameters<typeof google.maps.Map> 4>; 5 6beforeEach(() => { 7 initialize(); 8 9 createMapSpy = jest.fn(); 10 11 // overwrite the mock implementation with an anonymous class 12 google.maps.Map = class extends google.maps.Map { 13 constructor(...args: ConstructorParameters<typeof google.maps.Map>) { 14 createMapSpy(...args); 15 super(...args); 16 } 17 }; 18}); 19 20test("map constructor", () => { 21 const mapOptions = { mapId: "abcd" }; 22 const map = new google.maps.Map(null, mapOptions); 23 24 expect(createMapSpy).toHaveBeenCalledWith(null, mapOptions); 25});
So essentially, you can overwrite the classes in the global google.maps
namespace with your own classes extending the existing ones. The initialize
function will always restore them to their initial state.
Mocking Services
If your code is interacting with services provided by the Maps API, you can
control the results that will be returned when calling the methods of the
service. First you need to get the service instance that was created by
your code using the mockInstances
registry:
1import { 2 initialize, 3 AutocompleteService, 4 mockInstances, 5} from "@googlemaps/jest-mocks"; 6 7beforeEach(() => { 8 initialize(); 9}); 10 11test("...", () => { 12 // [... do something that creates a google.maps.AutocompleteService instance] 13 14 const [serviceMock] = mockInstances.get(AutocompleteService); 15 expect(serviceMock.getPlacePredictions).toHaveBeenCalled(); 16});
Note that the imported AutocompleteService
and
google.maps.places.AutocompleteService
are the same object.
The only difference is that the former one is known to be the mocked version
(so you can access the mock-interface without type-errors when writing tests
in TS.
Since the mocked methods are created in the constructor of the mocked
AutocompleteService
, we can't overwrite the behavior of the methods before
the constructor has been called.
If the creation of the AutocompleteService is separated from it's usage, this is relatively easy:
1// assuming your class under test looks like this: 2class MyAutocomplete { 3 constructor() { 4 this.service = new google.maps.places.AutocompleteService(); 5 } 6 7 async update() { 8 const res = await this.service.getPlacePredictions(); 9 } 10} 11 12// configure the mocks after the constructor has been called: 13test("...", async () => { 14 const subject = new MyAutocomplete(); 15 16 const [serviceMock] = mockInstances.get(AutocompleteService); 17 serviceMock.getPlacePredictions.mockImplementation(() => { 18 return { 19 // whatever you want the return-value to be 20 }; 21 }); 22 23 // now call the method under test 24 await subject.update(); 25 26 // validate the outcome 27});
The same applies if you can somehow separate the creation of the service-object from its usage, for example, by monkey-patching it in the tests:
1test("...", async () => { 2 const subject = new MyAutocomplete(); 3 4 // this is assuming that `subject.update()` will internally call a method 5 // `this.createAutocompleteService()` when called. 6 subject.createAutocompleteService = jest.fn(() => { 7 const svc = new AutocompleteService(); 8 9 // configure mocked methods as above 10 11 return svc; 12 }); 13 14 await subject.update(); 15});
Both of these solutions are probably more of an antipattern, since they
expose implementation details (like the service
property or the
createAutocompleteService
method) to the test, making it harder to change
the implementation without updating the test.
The recommended way is to achieve this is to replace the AutocompleteService
class entirely to get full control over its behavior in your tests:
1const getPlacePredictionsMock = jest.fn(); 2class MockAutocompleteService extends AutocompleteService { 3 constructor() { 4 super(); 5 6 this.getPlacePredictions = getPlacePredictionsMock; 7 } 8} 9 10test("...", () => { 11 google.maps.places.AutocompleteService = MockAutocompleteService; 12 getPlacePredictions.mockImplementation(() => { 13 return { ... }; 14 }); 15 16 // run your test 17});
Cleaning up mocks
Whenever initialize()
is called, the captured mocks are automatically cleaned. Using any of Jest's methods, you can clean the mock instances at any time:
1import { initialize, Map, Marker, mockInstances } from "@googlemaps/jest-mocks"; 2 3beforeAll(() => { 4 initialize(); 5}); 6 7// Clear all mocks 8beforeEach(() => { 9 mockInstances.clearAll(); 10}); 11 12// Clear specific mocks 13beforeEach(() => { 14 mockInstances.clear(Map, Marker); 15});
Support
This library is community supported. We're comfortable enough with the stability and features of the library that we want you to build real production applications on it.
If you find a bug, or have a feature suggestion, please log an issue. If you'd like to contribute, please read How to Contribute.
No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
security policy file detected
Details
- Info: security policy file detected: SECURITY.md:1
- Info: Found linked content: SECURITY.md:1
- Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1
- Info: Found text in security policy: SECURITY.md:1
Reason
30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Reason
no binaries found in the repo
Reason
license file detected
Details
- Info: project has a license file: LICENSE:0
- Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0
Reason
SAST tool is run on all commits
Details
- Info: SAST configuration detected: CodeQL
- Info: all commits (30) are checked with a SAST tool
Reason
1 existing vulnerabilities detected
Details
- Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275
Reason
dependency not pinned by hash detected -- score normalized to 3
Details
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:38: update your workflow using https://app.stepsecurity.io/secureworkflow/googlemaps/js-jest-mocks/codeql.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:42: update your workflow using https://app.stepsecurity.io/secureworkflow/googlemaps/js-jest-mocks/codeql.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:47: update your workflow using https://app.stepsecurity.io/secureworkflow/googlemaps/js-jest-mocks/codeql.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/commitlint.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/googlemaps/js-jest-mocks/commitlint.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/docs.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/googlemaps/js-jest-mocks/docs.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/docs.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/googlemaps/js-jest-mocks/docs.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/docs.yml:40: update your workflow using https://app.stepsecurity.io/secureworkflow/googlemaps/js-jest-mocks/docs.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/release-please.yml:35: update your workflow using https://app.stepsecurity.io/secureworkflow/googlemaps/js-jest-mocks/release-please.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release-please.yml:49: update your workflow using https://app.stepsecurity.io/secureworkflow/googlemaps/js-jest-mocks/release-please.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release-please.yml:53: update your workflow using https://app.stepsecurity.io/secureworkflow/googlemaps/js-jest-mocks/release-please.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release-please.yml:65: update your workflow using https://app.stepsecurity.io/secureworkflow/googlemaps/js-jest-mocks/release-please.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/googlemaps/js-jest-mocks/test.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/googlemaps/js-jest-mocks/test.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/test.yml:42: update your workflow using https://app.stepsecurity.io/secureworkflow/googlemaps/js-jest-mocks/test.yml/main?enable=pin
- Warn: npmCommand not pinned by hash: .github/workflows/commitlint.yml:34
- Info: 0 out of 11 GitHub-owned GitHubAction dependencies pinned
- Info: 0 out of 3 third-party GitHubAction dependencies pinned
- Info: 3 out of 4 npmCommand dependencies pinned
Reason
Found 0/1 approved changesets -- score normalized to 0
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
detected GitHub workflow tokens with excessive permissions
Details
- Info: jobLevel 'actions' permission set to 'read': .github/workflows/codeql.yml:32
- Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql.yml:33
- Warn: no topLevel permission defined: .github/workflows/codeql.yml:1
- Warn: no topLevel permission defined: .github/workflows/commitlint.yml:1
- Warn: topLevel 'contents' permission set to 'write': .github/workflows/dependabot.yml:21
- Warn: no topLevel permission defined: .github/workflows/docs.yml:1
- Warn: topLevel 'contents' permission set to 'write': .github/workflows/release-please.yml:24
- Warn: no topLevel permission defined: .github/workflows/test.yml:1
- Info: no jobLevel write permissions found
Reason
project is not fuzzed
Details
- Warn: no fuzzer integrations found
Score
6.3
/10
Last Scanned on 2024-11-18
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn MoreOther packages similar to @googlemaps/jest-mocks
@soleo/google-maps-vitest-mocks
[![npm](https://img.shields.io/npm/v/@googlemaps/jest-mocks)](https://www.npmjs.com/package/@googlemaps/jest-mocks) ![Build](https://github.com/googlemaps/js-jest-mocks/workflows/Test/badge.svg) ![Release](https://github.com/googlemaps/js-jest-mocks/workf
jest-mock
**Note:** More details on user side API can be found in [Jest documentation](https://jestjs.io/docs/mock-function-api).
aws-sdk-client-mock
Easy and powerful mocking of AWS SDK v3 Clients
@anshulsanghi/googlemaps-vitest-mocks
## Forked from https://github.com/googlemaps/js-jest-mocks