Skip to content

Commit

Permalink
feat: add initial integration tests for ground overlays
Browse files Browse the repository at this point in the history
  • Loading branch information
jokerttu committed Jan 2, 2025
1 parent 8ea6b58 commit ef71871
Show file tree
Hide file tree
Showing 18 changed files with 782 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,263 @@ void runTests() {
expect(heatmapInfo1, isNull);
}
});

group('GroundOverlay', () {
final LatLngBounds kGroundOverlayBounds = LatLngBounds(
southwest: const LatLng(37.77483, -122.41942),
northeast: const LatLng(37.78183, -122.39105),
);

final GroundOverlay groundOverlayBounds1 = GroundOverlay.fromBounds(
groundOverlayId: const GroundOverlayId('bounds_1'),
bounds: kGroundOverlayBounds,
image: AssetMapBitmap(
'assets/red_square.png',
imagePixelRatio: 1.0,
),
);

final GroundOverlay groundOverlayPosition1 = GroundOverlay.fromPosition(
groundOverlayId: const GroundOverlayId('position_1'),
position: kGroundOverlayBounds.northeast,
width: 100,
height: 100,
anchor: const Offset(0.1, 0.2),
image: AssetMapBitmap(
'assets/red_square.png',
imagePixelRatio: 1.0,
));

void expectGroundOverlayEquals(
GroundOverlay source, GroundOverlay response) {
expect(response.groundOverlayId, source.groundOverlayId);
expect(
response.transparency,
moreOrLessEquals(source.transparency, epsilon: floatTolerance),
);
expect(
response.bearing,
moreOrLessEquals(source.bearing, epsilon: floatTolerance),
);

// Only test bounds if it was given in the original object
if (source.bounds != null) {
expect(response.bounds, source.bounds);
}

// Only test position if it was given in the original object
if (source.position != null) {
expect(response.position, source.position);
}

expect(response.clickable, source.clickable);
expect(response.zIndex, source.zIndex);

// Only Android supports width and height
if (Platform.isAndroid) {
expect(response.width, source.width);
expect(response.height, source.height);
}
// Only Android (using position) and iOS supports `anchor`
if ((Platform.isAndroid && source.position != null) || Platform.isIOS) {
expect(
response.anchor?.dx,
moreOrLessEquals(source.anchor!.dx, epsilon: floatTolerance),
);
expect(
response.anchor?.dy,
moreOrLessEquals(source.anchor!.dy, epsilon: floatTolerance),
);
}
}

testWidgets('set ground overlays correctly', (WidgetTester tester) async {
final Completer<int> mapIdCompleter = Completer<int>();
final GroundOverlay groundOverlayBounds2 = GroundOverlay.fromBounds(
groundOverlayId: const GroundOverlayId('bounds_2'),
bounds: groundOverlayBounds1.bounds!,
image: groundOverlayBounds1.image,
);

await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: GoogleMap(
initialCameraPosition: kInitialCameraPosition,
groundOverlays: <GroundOverlay>{
groundOverlayBounds1,
groundOverlayBounds2,
groundOverlayPosition1,
},
onMapCreated: (GoogleMapController controller) {
mapIdCompleter.complete(controller.mapId);
},
),
),
);
await tester.pumpAndSettle(const Duration(seconds: 3));

final int mapId = await mapIdCompleter.future;
final GoogleMapsInspectorPlatform inspector =
GoogleMapsInspectorPlatform.instance!;

if (inspector.supportsGettingGroundOverlayInfo()) {
final GroundOverlay groundOverlayBoundsInfo1 = (await inspector
.getGroundOverlayInfo(groundOverlayBounds1.mapsId, mapId: mapId))!;
final GroundOverlay groundOverlayBoundsInfo2 = (await inspector
.getGroundOverlayInfo(groundOverlayBounds2.mapsId, mapId: mapId))!;
final GroundOverlay groundOverlayPositionInfo1 =
(await inspector.getGroundOverlayInfo(groundOverlayPosition1.mapsId,
mapId: mapId))!;

expectGroundOverlayEquals(
groundOverlayBounds1,
groundOverlayBoundsInfo1,
);
expectGroundOverlayEquals(
groundOverlayBounds2,
groundOverlayBoundsInfo2,
);
expectGroundOverlayEquals(
groundOverlayPosition1,
groundOverlayPositionInfo1,
);
}
});

testWidgets('update ground overlays correctly',
(WidgetTester tester) async {
final Completer<int> mapIdCompleter = Completer<int>();
final Key key = GlobalKey();

await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: GoogleMap(
key: key,
initialCameraPosition: kInitialCameraPosition,
groundOverlays: <GroundOverlay>{
groundOverlayBounds1,
groundOverlayPosition1
},
onMapCreated: (GoogleMapController controller) {
mapIdCompleter.complete(controller.mapId);
},
),
),
);

final int mapId = await mapIdCompleter.future;
final GoogleMapsInspectorPlatform inspector =
GoogleMapsInspectorPlatform.instance!;

final GroundOverlay groundOverlayBounds1New =
groundOverlayBounds1.copyWith(
bearingParam: 10,
clickableParam: false,
transparencyParam: 0.5,
visibleParam: false,
zIndexParam: 10,
);

final GroundOverlay groundOverlayPosition1New =
groundOverlayPosition1.copyWith(
bearingParam: 10,
clickableParam: false,
transparencyParam: 0.5,
visibleParam: false,
zIndexParam: 10,
);

await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: GoogleMap(
key: key,
initialCameraPosition: kInitialCameraPosition,
groundOverlays: <GroundOverlay>{
groundOverlayBounds1New,
groundOverlayPosition1New
},
onMapCreated: (GoogleMapController controller) {
fail('update: OnMapCreated should get called only once.');
},
),
),
);

await tester.pumpAndSettle(const Duration(seconds: 3));

if (inspector.supportsGettingGroundOverlayInfo()) {
final GroundOverlay groundOverlayBounds1Info = (await inspector
.getGroundOverlayInfo(groundOverlayBounds1.mapsId, mapId: mapId))!;
final GroundOverlay groundOverlayPosition1Info =
(await inspector.getGroundOverlayInfo(groundOverlayPosition1.mapsId,
mapId: mapId))!;

expectGroundOverlayEquals(
groundOverlayBounds1New,
groundOverlayBounds1Info,
);
expectGroundOverlayEquals(
groundOverlayPosition1New,
groundOverlayPosition1Info,
);
}
});

testWidgets('remove ground overlays correctly',
(WidgetTester tester) async {
final Completer<int> mapIdCompleter = Completer<int>();
final Key key = GlobalKey();

await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: GoogleMap(
key: key,
initialCameraPosition: kInitialCameraPosition,
groundOverlays: <GroundOverlay>{
groundOverlayBounds1,
groundOverlayPosition1
},
onMapCreated: (GoogleMapController controller) {
mapIdCompleter.complete(controller.mapId);
},
),
),
);

final int mapId = await mapIdCompleter.future;
final GoogleMapsInspectorPlatform inspector =
GoogleMapsInspectorPlatform.instance!;

await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: GoogleMap(
key: key,
initialCameraPosition: kInitialCameraPosition,
onMapCreated: (GoogleMapController controller) {
fail('OnMapCreated should get called only once.');
},
),
),
);

await tester.pumpAndSettle(const Duration(seconds: 3));

if (inspector.supportsGettingGroundOverlayInfo()) {
final GroundOverlay? groundOverlayBounds1Info = await inspector
.getGroundOverlayInfo(groundOverlayBounds1.mapsId, mapId: mapId);
final GroundOverlay? groundOverlayPositionInfo = await inspector
.getGroundOverlayInfo(groundOverlayPosition1.mapsId, mapId: mapId);

expect(groundOverlayBounds1Info, isNull);
expect(groundOverlayPositionInfo, isNull);
}
});
});
}

class _DebugTileProvider implements TileProvider {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ class GroundOverlayBodyState extends State<GroundOverlayBody> {
groundOverlayId: id,
image: assetMapBitmap,
bounds: _currentGroundOverlayBounds,
anchor: _anchor,
onTap: () {
_onGroundOverlayTapped();
},
Expand Down Expand Up @@ -225,13 +226,11 @@ class GroundOverlayBodyState extends State<GroundOverlayBody> {

Future<void> _changeAnchor() async {
assert(_groundOverlay != null);
assert(_placingType == _GroundOverlayPlacing.position);
setState(() {
_anchor = _groundOverlay!.anchor == const Offset(0.5, 0.5)
? const Offset(1.0, 1.0)
: const Offset(0.5, 0.5);
});
debugPrint(_anchor.toString());

// Re-add the ground overlay to apply the new anchor as the anchor cannot be
// changed after the ground overlay is created.
Expand Down Expand Up @@ -296,6 +295,12 @@ class GroundOverlayBodyState extends State<GroundOverlayBody> {
: () => _changeZIndex(),
child: const Text('change zIndex'),
),
if (!kIsWeb)
TextButton(
onPressed:
_groundOverlay == null ? null : () => _changeAnchor(),
child: const Text('change anchor'),
),
if (!kIsWeb)
TextButton(
onPressed: _groundOverlay == null ? null : () => _changeType(),
Expand All @@ -319,14 +324,6 @@ class GroundOverlayBodyState extends State<GroundOverlayBody> {
: () => _changeDimensions(),
child: const Text('change dimensions'),
),
if (!kIsWeb)
TextButton(
onPressed: _placingType != _GroundOverlayPlacing.position ||
_groundOverlay == null
? null
: () => _changeAnchor(),
child: const Text('change anchor'),
),
TextButton(
onPressed: _placingType != _GroundOverlayPlacing.bounds ||
_groundOverlay == null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,20 +229,20 @@ class GoogleMap extends StatefulWidget {
/// Ground overlays to be initialized for the map.
///
/// Ground overlay feature support table:
/// | Feature | Android | iOS | Web |
/// |-----------------------------|---------|-----|-----|
/// | [GroundOverlay.bounds] | Yes | Yes | Yes |
/// | [GroundOverlay.position] | Yes | Yes | No |
/// | [GroundOverlay.width] | Yes | No | No |
/// | [GroundOverlay.height] | Yes | No | No |
/// | [GroundOverlay.anchor] | Yes | Yes | No |
/// | [GroundOverlay.zoomLevel] | No | Yes | No |
/// | [GroundOverlay.bearing] | Yes | Yes | Yes |
/// | [GroundOverlay.transparency]| Yes | Yes | Yes |
/// | [GroundOverlay.zIndex] | Yes | Yes | Yes |
/// | [GroundOverlay.visible] | Yes | Yes | Yes |
/// | [GroundOverlay.clickable] | Yes | Yes | Yes |
/// | [GroundOverlay.onTap] | Yes | Yes | Yes |
/// | Feature | Android | iOS | Web |
/// |-----------------------------|-------------------------|-----|-----|
/// | [GroundOverlay.bounds] | Yes | Yes | Yes |
/// | [GroundOverlay.position] | Yes | Yes | No |
/// | [GroundOverlay.width] | Yes (for position only) | No | No |
/// | [GroundOverlay.height] | Yes (for position only) | No | No |
/// | [GroundOverlay.anchor] | Yes (for position only) | Yes | No |
/// | [GroundOverlay.zoomLevel] | No | Yes | No |
/// | [GroundOverlay.bearing] | Yes | Yes | Yes |
/// | [GroundOverlay.transparency]| Yes | Yes | Yes |
/// | [GroundOverlay.zIndex] | Yes | Yes | Yes |
/// | [GroundOverlay.visible] | Yes | Yes | Yes |
/// | [GroundOverlay.clickable] | Yes | Yes | Yes |
/// | [GroundOverlay.onTap] | Yes | Yes | Yes |
final Set<GroundOverlay> groundOverlays;

/// Called when the camera starts moving.
Expand Down Expand Up @@ -382,6 +382,7 @@ class _GoogleMapState extends State<GoogleMap> {
circles: widget.circles,
clusterManagers: widget.clusterManagers,
heatmaps: widget.heatmaps,
groundOverlays: widget.groundOverlays,
),
mapConfiguration: _mapConfiguration,
);
Expand All @@ -397,6 +398,7 @@ class _GoogleMapState extends State<GoogleMap> {
_polylines = keyByPolylineId(widget.polylines);
_circles = keyByCircleId(widget.circles);
_heatmaps = keyByHeatmapId(widget.heatmaps);
_groundOverlays = keyByGroundOverlayId(widget.groundOverlays);
}

@override
Expand Down
Loading

0 comments on commit ef71871

Please sign in to comment.