Maps & Geolocation Testing Guide
How to Test Google Maps Embed with Playwright: Complete 2026 Guide
A scenario-by-scenario walkthrough of testing Google Maps embeds with Playwright. Canvas-rendered markers, API key validation, geocoding assertions, info window popups, map controls, and the pitfalls that break real map test suites.
“Google Maps Platform serves over 10 billion requests per week across Maps, Routes, and Places APIs, powering location features in millions of applications worldwide.”
Google Cloud Next 2024
Google Maps Embed Initialization Flow
1. Why Testing Google Maps Embeds Is Harder Than It Looks
Google Maps renders almost everything onto an HTML5 <canvas> element. Markers, polylines, polygons, and tile imagery all live inside that canvas. There are no DOM nodes to query with getByRole or locator. A standard Playwright test that searches for a marker element in the DOM will find nothing, because the marker exists only as painted pixels on the canvas surface. This is the single biggest obstacle to testing maps reliably.
The complexity compounds quickly. Google Maps requires a valid API key to load, and an invalid or restricted key produces a darkened map overlay with a “For development purposes only” watermark or an outright blank div. Your test environment needs a key with the correct API restrictions (Maps JavaScript API, Geocoding API, Places API) and the correct HTTP referrer allowlist for your test server domain. Getting this wrong produces failures that look like map bugs but are actually infrastructure configuration issues.
Beyond the canvas rendering challenge and API key requirements, there are three more structural difficulties. First, geocoding is asynchronous: when your application converts an address to coordinates, the map may render before or after the geocoding response arrives, creating race conditions in assertions. Second, info window popups are injected into the DOM dynamically when a user clicks a marker, but the click target is the canvas, not a button element. Third, map controls (zoom, pan, tilt, Street View) trigger tile reloads that take variable time depending on network conditions and tile cache state. Each of these requires a specific testing strategy.
Google Maps Embed Rendering Pipeline
Script Load
maps.googleapis.com/maps/api/js
API Key Check
Validate key + referrer
Map Init
new google.maps.Map()
Tile Fetch
Download tile images
Canvas Render
Paint tiles + markers
Events Fire
tilesloaded, idle
2. Setting Up a Reliable Test Environment
A stable Google Maps test environment requires three things: a properly configured API key, a consistent test server, and Playwright configuration that accounts for tile loading latency. Start with the API key. Create a dedicated key in the Google Cloud Console for your test environment. Restrict it to the Maps JavaScript API, Geocoding API, and Places API. Add your test server's domain (typically localhost:3000 or your CI preview URL) to the HTTP referrer allowlist.
Playwright Configuration for Maps
Google Maps tiles load asynchronously and can take several seconds on slow networks. Your Playwright config needs a longer action timeout for map interactions and geolocation permissions granted by default. Here is the recommended configuration:
Helper: Wait for Map Tiles to Load
The most important utility in any Google Maps test suite is a function that waits for the map to finish rendering. Google Maps fires a tilesloaded event when all visible tiles have been fetched and painted. You can listen for this event from Playwright by evaluating a script on the page:
Test Environment Setup Flow
Create API Key
Google Cloud Console
Restrict APIs
JS, Geocoding, Places
Set Referrers
localhost + CI domain
Configure .env
Key + test coordinates
Expose Globals
__TEST_MAP__, __TEST_MARKERS__
The key pattern here is exposing the map instance and marker array as global variables in your application code, but only in test or development environments. This gives Playwright a programmatic bridge into the Maps JavaScript API, bypassing the canvas rendering layer entirely for data assertions. Your production build should strip these globals with a simple environment check.
Verifying Map Initialization and Tile Loading
StraightforwardThe most basic map test confirms that the Google Maps JavaScript API loaded successfully, the map rendered inside the target container, and all visible tiles finished loading. This sounds trivial, but it catches API key misconfiguration, referrer restriction failures, and script loading errors that silently break maps in production.
Note the use of toBeCloseTo for coordinate assertions. Floating point precision means that map coordinates returned by the API will rarely match your input exactly. A tolerance of two decimal places (roughly 1.1 km at the equator) is appropriate for center assertions; use four decimal places for marker position assertions where precision matters more.
Detecting Canvas-Rendered Markers
ComplexThis is the hardest part of testing Google Maps. Markers rendered with google.maps.marker.AdvancedMarkerElement are painted directly onto the map canvas. There is no <div> or <img> element in the DOM that represents the marker. You have two strategies: read marker data from the JavaScript API (recommended) or use visual regression on the canvas (brittle).
Strategy A: Read Markers via the JavaScript API
If you exposed __TEST_MARKERS__ on the window object (as shown in the setup section), you can query marker count, positions, and titles directly from the Maps API. This is deterministic and not affected by canvas rendering timing.
Strategy B: Visual Regression on the Canvas
When you cannot expose test globals (for example, testing a third-party widget you do not control), you can use Playwright's screenshot comparison. Take a baseline screenshot of the map with known markers, then compare subsequent renders against that baseline. This approach is inherently brittle because Google periodically updates tile imagery and styling, so set a generous pixel diff threshold.
Marker Detection: Playwright vs Assrt
import { test, expect } from '@playwright/test';
import { waitForTilesLoaded, getMarkerPositions } from './helpers/map-helpers';
test('all office markers displayed', async ({ page }) => {
await page.goto('/locations');
await waitForTilesLoaded(page);
await page.waitForFunction(() => {
return ((window as any).__TEST_MARKERS__ || []).length > 0;
});
const markers = await getMarkerPositions(page);
expect(markers).toHaveLength(5);
const hq = markers.find(m => m.title === 'Headquarters');
expect(hq).toBeDefined();
expect(hq!.lat).toBeCloseTo(40.7484, 4);
expect(hq!.lng).toBeCloseTo(-73.9857, 4);
});Info Window Popups and Content Assertions
ModerateInfo windows are the popups that appear when a user clicks a marker. Unlike markers, info windows arerendered in the DOM, which makes their content testable with standard Playwright locators. The challenge is triggering the click. Since the marker lives on the canvas, you cannot click it by locator. Instead, you either trigger the click programmatically through the Maps API or calculate the marker's pixel position and click at those coordinates.
The .gm-style-iw-c class is the internal Google Maps class for the info window container. While relying on internal class names is fragile, Google has kept this class stable for several years. If you need more resilience, use page.locator('[role="dialog"]') as info windows have ARIA dialog semantics in newer Maps API versions.
Info Window Testing: Playwright vs Assrt
test('info window shows correct address', async ({ page }) => {
await page.goto('/locations');
await waitForTilesLoaded(page);
await page.evaluate(() => {
google.maps.event.trigger(
(window as any).__TEST_MARKERS__[0], 'click'
);
});
const infoWindow = page.locator('.gm-style-iw-c');
await expect(infoWindow).toBeVisible({ timeout: 5000 });
await expect(infoWindow).toContainText('Headquarters');
await expect(infoWindow).toContainText('123 Main Street');
});Geocoding Assertions and Address Search
ComplexMany map-based applications include an address search bar that geocodes user input and pans the map to the result. Testing this flow requires intercepting the Geocoding API request, asserting the returned coordinates, and verifying the map updated accordingly. The Geocoding API is asynchronous and rate-limited, making it a common source of flaky tests.
Intercepting Geocoding Requests
Playwright's page.route() method can intercept requests to the Geocoding API endpoint. This lets you mock responses for deterministic tests or inspect the actual request to verify your application sends the correct address string.
Map Controls: Zoom, Pan, and Street View
ModerateMap controls (zoom buttons, pan gestures, the Street View pegman, fullscreen toggle) are part of the Google Maps UI overlay. Unlike markers, these controls are rendered as DOM elements, making them directly clickable with Playwright locators. The challenge is asserting the result of the interaction, because zoom and pan changes trigger asynchronous tile reloads.
One important detail: the getByLabel('Zoom in') locator works because Google Maps applies aria-label attributes to its built-in control buttons. These labels are stable across Maps API versions but are locale-dependent. If your tests run with a non-English locale, the labels will be translated. Use page.locator('button[title="Zoom in"]') as a fallback, since the title attribute also carries the label text.
API Key Validation and Error States
ModerateA missing or misconfigured API key is one of the most common reasons a Google Maps embed fails in production. Your test suite should explicitly verify both the happy path (valid key, map loads) and the error path (invalid key, appropriate error handling). Testing error states ensures your application gracefully degrades rather than showing a broken blank area.
The terminal output above shows a common failure pattern. Google Maps uses a global gm_authFailure callback to report authentication errors, but many applications do not implement it. If your quota exceeded test fails, add the callback to your application code:
9. Common Pitfalls That Break Google Maps Test Suites
After reviewing hundreds of Google Maps related issues on GitHub and Stack Overflow, these are the pitfalls that cause the most failures in real-world test suites. Each one is a specific, actionable mistake with a concrete fix.
Pitfalls to Avoid
- Querying DOM for markers: AdvancedMarkerElement renders on canvas, not in the DOM. Use the JavaScript API to read marker data instead of locator queries.
- Not waiting for tilesloaded: Asserting map state before tiles finish loading produces intermittent failures. Always call waitForTilesLoaded() before any map assertion.
- Hardcoded pixel coordinates for clicks: Map tiles shift between zoom levels and viewport sizes. Use the Maps API to trigger marker clicks instead of clicking at fixed pixel positions.
- Missing API key referrer restrictions: Tests pass locally but fail in CI because the CI domain is not in the key's HTTP referrer allowlist. Add your CI preview URL to the allowlist.
- Ignoring gm_authFailure: Quota exceeded and billing errors fire this global callback, but most apps do not handle it. Unhandled, the map shows a gray overlay with no actionable error.
- Using waitForTimeout instead of waitForFunction: Fixed delays are unreliable. Use waitForFunction to poll the map's actual state (zoom level, center coordinates, marker count).
- Not mocking Geocoding API in CI: Live geocoding requests hit rate limits in parallel CI runs. Mock the Geocoding endpoint with page.route() for deterministic results.
- Locale-dependent control labels: The 'Zoom in' aria-label changes with locale. Pin the test browser locale to en-US or use selector fallbacks with the title attribute.
Real Error: The “Map Div Changed Size” Warning
One of the most frequently reported issues on Stack Overflow is Google Maps printing a console warning: “Map: Expected mapDiv of size NxM, but was actually 0x0.” This happens when the map container is hidden (display: none) or has zero dimensions at initialization time. In Playwright tests, this occurs when your application renders the map inside a tab, modal, or accordion that starts closed. The fix is to call google.maps.event.trigger(map, 'resize') after making the container visible, or to defer map initialization until the container is in view.
10. Writing These Scenarios in Plain English with Assrt
Every scenario above requires significant boilerplate: helper functions for waiting on tiles, evaluate calls to bridge into the Maps API, coordinate tolerance math, and route interception setup. Assrt lets you express the same test intent in plain English while it handles the Playwright orchestration under the hood.
Here is the marker detection scenario (Section 4) and the geocoding search scenario (Section 6) rewritten as a single .assrt file:
Five scenarios in 37 lines of plain English, compared to roughly 250 lines of Playwright TypeScript. Assrt compiles each step into the correct Playwright calls, including the waitForTilesLoaded helper, the evaluate calls for marker detection, and the coordinate tolerance math. When Google updates its Maps API and your selectors break, Assrt regenerates the underlying Playwright code from your unchanged scenario files and opens a pull request with the updated selectors.
What Assrt Handles for You
- Canvas marker detection via Maps JavaScript API bridging
- Automatic tilesloaded event waiting before assertions
- Coordinate tolerance math for geocoding assertions
- Geocoding API mocking in CI environments
- Info window DOM locators with fallback selectors
- Map control interaction with tile reload waiting
- Automatic selector regeneration when Maps API updates
Start with the map initialization scenario. Once it passes in your CI, add marker detection, then info window popups, then geocoding search, then map controls, then API error handling. In a single afternoon, you can build complete Google Maps embed coverage that most teams never achieve because the canvas rendering layer makes traditional test approaches impractical.
Related Guides
How to Test Google Places Autocomplete
A practical, scenario-by-scenario guide to testing Google Places Autocomplete with...
How to Test postMessage
A practical guide to testing iframe postMessage APIs with Playwright. Covers cross-origin...
How to Test Mapbox GL Markers
A practical guide to testing Mapbox GL JS markers, popups, and fly-to animations with...
Ready to automate your testing?
Assrt discovers test scenarios, writes Playwright tests from plain English, and self-heals when your UI changes.