Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add initial integration tests for ground overlays #11

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 |
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we put here (for position only) also for zoomLevel and iOS?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes. let's merge this and you can update the iOS side, as I am not sure about other methods either

/// | [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
Loading