Skip to content

Commit 219bb47

Browse files
awmackcopybara-github
authored andcommitted
chore: clean up testing fakes
PiperOrigin-RevId: 577297045
1 parent c04dd5e commit 219bb47

File tree

9 files changed

+123
-68
lines changed

9 files changed

+123
-68
lines changed

src/base/strings.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ export type StringFunction = (...args: any[]) => string;
1515
*/
1616
export declare interface StringLiterals extends
1717
Record<string, string|StringFunction> {
18+
BACK_BUTTON: string;
19+
LOCATOR_ALL_LOCATIONS: string;
20+
LOCATOR_LIST_HEADER: string;
21+
LOCATOR_SEARCH_PROMPT: string;
22+
LOCATOR_VIEW_DETAILS: string;
1823
PLACE_CLEAR_ARIA_LABEL: string;
1924
PLACE_CLOSED: string;
2025
PLACE_CLOSED_PERMANENTLY: string;
@@ -51,6 +56,11 @@ export declare interface StringLiterals extends
5156

5257
/** String literals in the `en-US` locale. */
5358
export const STRING_LITERALS_EN_US: StringLiterals = Object.freeze({
59+
'BACK_BUTTON': 'Back',
60+
'LOCATOR_ALL_LOCATIONS': 'All locations',
61+
'LOCATOR_LIST_HEADER': 'Find a location near you',
62+
'LOCATOR_SEARCH_PROMPT': 'Enter your address or zip code',
63+
'LOCATOR_VIEW_DETAILS': 'View details',
5464
'PLACE_CLEAR_ARIA_LABEL': 'Clear',
5565
'PLACE_CLOSED': 'Closed',
5666
'PLACE_CLOSED_PERMANENTLY': 'Permanently closed',

src/place_picker/place_picker_test.ts

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ const FAKE_PLACE_FROM_QUERY = makeFakePlace({
4242

4343
describe('PlacePicker', () => {
4444
const env = new Environment();
45-
let fakeAutocomplete: jasmine.SpyObj<google.maps.places.Autocomplete>;
4645

4746
beforeAll(() => {
4847
env.defineFakeMapElement();
@@ -57,13 +56,6 @@ describe('PlacePicker', () => {
5756
const fakeCircle = jasmine.createSpyObj('Circle', ['getBounds']);
5857
env.fakeGoogleMapsHarness!.libraries['maps'].Circle =
5958
jasmine.createSpy().and.returnValue(fakeCircle);
60-
61-
// Create a fake Autocomplete class with test-specific logic.
62-
fakeAutocomplete = jasmine.createSpyObj<google.maps.places.Autocomplete>(
63-
'Autocomplete',
64-
['addListener', 'bindTo', 'getBounds', 'getPlace', 'setOptions']);
65-
spyOn(env.fakeGoogleMapsHarness!, 'autocompleteConstructor')
66-
.and.returnValue(fakeAutocomplete);
6759
});
6860

6961
async function prepareState(template?: TemplateResult) {
@@ -101,6 +93,8 @@ describe('PlacePicker', () => {
10193
});
10294

10395
it('initializes Autocomplete widget with minimum configs', async () => {
96+
spyOn(env.fakeGoogleMapsHarness!, 'autocompleteConstructor')
97+
.and.callThrough();
10498
const {picker, input, searchButton, clearButton} = await prepareState();
10599

106100
expect(env.fakeGoogleMapsHarness!.autocompleteConstructor)
@@ -117,6 +111,9 @@ describe('PlacePicker', () => {
117111
});
118112

119113
it(`initializes Autocomplete widget based on attributes`, async () => {
114+
spyOn(env.fakeGoogleMapsHarness!, 'autocompleteConstructor')
115+
.and.callThrough();
116+
120117
// The call to `.Circle.and.exec()` grabs a reference to the Circle
121118
// spy object without recording a call to the constructor spy (e.g.
122119
// `.Circle()`)
@@ -160,13 +157,14 @@ describe('PlacePicker', () => {
160157
picker.type = 'restaurant';
161158
await env.waitForStability();
162159

163-
expect(fakeAutocomplete.setOptions).toHaveBeenCalledOnceWith({
164-
bounds: FAKE_BOUNDS,
165-
componentRestrictions: {country: ['uk']},
166-
fields: [...PLACE_RESULT_DATA_FIELDS],
167-
strictBounds: true,
168-
types: ['restaurant'],
169-
});
160+
expect(env.fakeGoogleMapsHarness!.autocompleteSpy.setOptions)
161+
.toHaveBeenCalledOnceWith({
162+
bounds: FAKE_BOUNDS,
163+
componentRestrictions: {country: ['uk']},
164+
fields: [...PLACE_RESULT_DATA_FIELDS],
165+
strictBounds: true,
166+
types: ['restaurant'],
167+
});
170168
});
171169

172170
it(`doesn't define bounds when only location bias is specified`, async () => {
@@ -175,7 +173,7 @@ describe('PlacePicker', () => {
175173
picker.locationBias = {lat: 12, lng: 34};
176174
await env.waitForStability();
177175

178-
expect(fakeAutocomplete.setOptions)
176+
expect(env.fakeGoogleMapsHarness!.autocompleteSpy.setOptions)
179177
.toHaveBeenCalledOnceWith(jasmine.objectContaining({
180178
bounds: undefined,
181179
}));
@@ -187,7 +185,7 @@ describe('PlacePicker', () => {
187185
picker.radius = 1000;
188186
await env.waitForStability();
189187

190-
expect(fakeAutocomplete.setOptions)
188+
expect(env.fakeGoogleMapsHarness!.autocompleteSpy.setOptions)
191189
.toHaveBeenCalledOnceWith(jasmine.objectContaining({
192190
bounds: undefined,
193191
}));
@@ -199,7 +197,8 @@ describe('PlacePicker', () => {
199197
picker.placeholder = 'Search nearby places';
200198
await env.waitForStability();
201199

202-
expect(fakeAutocomplete.setOptions).not.toHaveBeenCalled();
200+
expect(env.fakeGoogleMapsHarness!.autocompleteSpy.setOptions)
201+
.not.toHaveBeenCalled();
203202
});
204203

205204
it(`enables search & clear buttons on user input`, async () => {
@@ -230,12 +229,13 @@ describe('PlacePicker', () => {
230229
it(`sets value based on user selection and fires event`, async () => {
231230
const dispatchEventSpy = spyOn(PlacePicker.prototype, 'dispatchEvent');
232231
let autocompleteSelectionHandler: Function;
233-
fakeAutocomplete.addListener.withArgs('place_changed', jasmine.anything())
232+
env.fakeGoogleMapsHarness!.autocompleteSpy.addListener
233+
.withArgs('place_changed', jasmine.anything())
234234
.and.callFake((eventName, handler) => {
235235
autocompleteSelectionHandler = handler;
236236
return {} as google.maps.MapsEventListener;
237237
});
238-
fakeAutocomplete.getPlace.and.returnValue(
238+
env.fakeGoogleMapsHarness!.autocompleteSpy.getPlace.and.returnValue(
239239
FAKE_PLACE_RESULT_FROM_AUTOCOMPLETE);
240240
const {picker, input, searchButton, clearButton} = await prepareState();
241241

@@ -256,7 +256,8 @@ describe('PlacePicker', () => {
256256

257257
it(`sets value to undefined when place's cleared & fires event`, async () => {
258258
let autocompleteSelectionHandler: Function;
259-
fakeAutocomplete.addListener.withArgs('place_changed', jasmine.anything())
259+
env.fakeGoogleMapsHarness!.autocompleteSpy.addListener
260+
.withArgs('place_changed', jasmine.anything())
260261
.and.callFake((eventName, handler) => {
261262
autocompleteSelectionHandler = handler;
262263
return {} as google.maps.MapsEventListener;
@@ -280,7 +281,8 @@ describe('PlacePicker', () => {
280281
});
281282

282283
it(`sets value based on place returned by Find Place request`, async () => {
283-
fakeAutocomplete.getBounds.and.returnValue(FAKE_BOUNDS);
284+
env.fakeGoogleMapsHarness!.autocompleteSpy.getBounds.and.returnValue(
285+
FAKE_BOUNDS);
284286
const {picker, input, searchButton, clearButton} = await prepareState();
285287

286288
await enterQueryText(input, '123 Main St');
@@ -308,7 +310,8 @@ describe('PlacePicker', () => {
308310

309311
it('sets value from fallback GA API when Place.findPlaceFromQuery is not available',
310312
async () => {
311-
fakeAutocomplete.getBounds.and.returnValue(FAKE_BOUNDS);
313+
env.fakeGoogleMapsHarness!.autocompleteSpy.getBounds.and.returnValue(
314+
FAKE_BOUNDS);
312315
const {picker, input, searchButton, clearButton} = await prepareState();
313316
(env.fakeGoogleMapsHarness!.findPlaceFromQueryHandler as jasmine.Spy)
314317
.and.throwError(new Error(
@@ -412,7 +415,8 @@ describe('PlacePicker', () => {
412415

413416
await picker.bindTo(fakeMap);
414417

415-
expect(fakeAutocomplete.bindTo).toHaveBeenCalledOnceWith('bounds', fakeMap);
418+
expect(env.fakeGoogleMapsHarness!.autocompleteSpy.bindTo)
419+
.toHaveBeenCalledOnceWith('bounds', fakeMap);
416420
});
417421

418422
it(`binds to map bounds declaratively via attribute`, async () => {
@@ -422,7 +426,7 @@ describe('PlacePicker', () => {
422426
`);
423427
const mapElement = root.querySelector<FakeMapElement>('gmp-map')!;
424428

425-
expect(fakeAutocomplete.bindTo)
429+
expect(env.fakeGoogleMapsHarness!.autocompleteSpy.bindTo)
426430
.toHaveBeenCalledOnceWith('bounds', mapElement.innerMap);
427431
});
428432

@@ -431,7 +435,8 @@ describe('PlacePicker', () => {
431435
<gmpx-place-picker for-map="my-map"></gmpx-place-picker>
432436
`);
433437

434-
expect(fakeAutocomplete.bindTo).not.toHaveBeenCalled();
438+
expect(env.fakeGoogleMapsHarness!.autocompleteSpy.bindTo)
439+
.not.toHaveBeenCalled();
435440
});
436441

437442
it(`doesn't bind to map bounds when id matches non-Map element`, async () => {
@@ -440,6 +445,7 @@ describe('PlacePicker', () => {
440445
<div id="my-map"></div>
441446
`);
442447

443-
expect(fakeAutocomplete.bindTo).not.toHaveBeenCalled();
448+
expect(env.fakeGoogleMapsHarness!.autocompleteSpy.bindTo)
449+
.not.toHaveBeenCalled();
444450
});
445451
});

src/route_building_blocks/route_marker/route_marker_test.ts

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7-
import '../../testing/fake_gmp_components.js';
87
// import 'jasmine'; (google3-only)
98

109
import {html, TemplateResult} from 'lit';
@@ -19,25 +18,6 @@ import {RouteMarker} from './route_marker.js';
1918

2019
type LatLng = google.maps.LatLng;
2120

22-
const FAKE_MARKER_LIBRARY = {
23-
AdvancedMarkerElement: class {
24-
position?: LatLng|null;
25-
zIndex?: number|null;
26-
title: string = '';
27-
map?: google.maps.Map|null;
28-
29-
innerContent?: Element|null;
30-
set content(content: Element|null|undefined) {
31-
// Detach from the DOM as in the real AdvancedMarkerElement
32-
content?.remove();
33-
this.innerContent = content;
34-
}
35-
get content(): Element|null|undefined {
36-
return this.innerContent;
37-
}
38-
}
39-
};
40-
4121
function fakeRouteBetween(
4222
[startLat, startLng]: [number, number],
4323
[endLat, endLng]: [number, number]): google.maps.DirectionsRoute {
@@ -54,15 +34,14 @@ describe('RouteMarker', () => {
5434

5535
beforeAll(() => {
5636
env.defineFakeMapElement();
57-
});
58-
59-
beforeEach(() => {
60-
env.importLibrarySpy!.and.returnValue(FAKE_MARKER_LIBRARY);
37+
env.defineFakeAdvancedMarkerElement();
6138
});
6239

6340
async function prepareState(template?: TemplateResult) {
64-
const constructorSpy =
65-
spyOn(FAKE_MARKER_LIBRARY, 'AdvancedMarkerElement').and.callThrough();
41+
const constructorSpy = spyOn(
42+
env.fakeGoogleMapsHarness!.libraries['marker'],
43+
'AdvancedMarkerElement')
44+
.and.callThrough();
6645
const root =
6746
env.render(template ?? html`<gmpx-route-marker></gmpx-route-marker>`);
6847
await env.waitForStability();

src/testing/environment.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {ReactiveElement, render as litRender, TemplateResult} from 'lit';
1010

1111
import {APILoader} from '../api_loader/api_loader.js';
1212

13-
import {FakeMapElement} from './fake_gmp_components.js';
13+
import {FakeAdvancedMarkerElement, FakeMapElement} from './fake_gmp_components.js';
1414
import {FakeGoogleMapsHarness} from './fake_google_maps.js';
1515

1616
declare global {
@@ -103,12 +103,25 @@ export class Environment {
103103
return root;
104104
}
105105

106+
/**
107+
* Inserts a fake implementation of <gmp-map> into the test environment.
108+
*/
106109
defineFakeMapElement() {
107110
if (!customElements.get('gmp-map')) {
108111
customElements.define('gmp-map', FakeMapElement);
109112
}
110113
}
111114

115+
/**
116+
* Inserts a fake implementation of <gmp-advanced-marker> into the test
117+
* environment.
118+
*/
119+
defineFakeAdvancedMarkerElement() {
120+
if (!customElements.get('gmp-advanced-marker')) {
121+
customElements.define('gmp-advanced-marker', FakeAdvancedMarkerElement);
122+
}
123+
}
124+
112125
/**
113126
* Waits for all Lit `ReactiveElement` children of the given parent node to
114127
* finish rendering.

src/testing/fake_autocomplete.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/**
2+
* @license
3+
* Copyright 2023 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
// import 'jasmine'; (google3-only)
8+
9+
/** Creates a Jasmine spy to replace an Autocomplete object. */
10+
export const makeFakeAutocomplete = () =>
11+
jasmine.createSpyObj<google.maps.places.Autocomplete>(
12+
'Autocomplete',
13+
['addListener', 'bindTo', 'getBounds', 'getPlace', 'setOptions']);

src/testing/fake_gmp_components.ts

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,46 @@
2020

2121
import {LitElement} from 'lit';
2222

23-
import {LatLng, LatLngBounds, LatLngBoundsLiteral, LatLngLiteral} from '../utils/googlemaps_types.js';
23+
import {LatLng, LatLngLiteral} from '../utils/googlemaps_types.js';
2424

2525
declare global {
2626
interface HTMLElementTagNameMap {
2727
'gmp-map': FakeMapElement;
28+
'gmp-advanced-marker': FakeAdvancedMarkerElement;
2829
}
2930
}
3031

31-
/** A fake google.maps.MapElement class for testing purposes. */
32+
/** A fake `google.maps.MapElement` class for testing purposes. */
3233
export class FakeMapElement extends LitElement {
34+
/** Test-only property to spy on calls to fitBounds(). */
35+
readonly fitBoundsSpy = jasmine.createSpy('fitBounds');
36+
3337
center: LatLng|LatLngLiteral|null = null;
3438

3539
// tslint:disable-next-line:prefer-type-annotation
36-
readonly innerMap = {
37-
fitBounds: (bounds: LatLngBounds|LatLngBoundsLiteral) => {}
38-
} as google.maps.Map;
40+
readonly innerMap = {fitBounds: this.fitBoundsSpy} as unknown as
41+
google.maps.Map;
3942

4043
mapId: string|null = null;
4144
zoom: number|null = null;
4245
}
46+
47+
/**
48+
* A fake `google.maps.AdvancedMarkerElement` class for testing purposes.
49+
*/
50+
export class FakeAdvancedMarkerElement extends LitElement {
51+
position?: LatLng|null;
52+
zIndex?: number|null;
53+
override title = '';
54+
map?: google.maps.Map|null;
55+
56+
innerContent?: Element|null;
57+
set content(content: Element|null|undefined) {
58+
// Detach from the DOM as in the real AdvancedMarkerElement
59+
content?.remove();
60+
this.innerContent = content;
61+
}
62+
get content(): Element|null|undefined {
63+
return this.innerContent;
64+
}
65+
}

0 commit comments

Comments
 (0)