blob: 59b5de42400f8ce4b3d4449958c74cdcab4d1112 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:integration_test/integration_test.dart';
import 'package:flutter/widgets.dart';
import 'package:google_maps/google_maps.dart' as gmaps;
import 'package:google_maps_flutter_web/google_maps_flutter_web.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart';
class _MockGoogleMapController extends Mock implements GoogleMapController {}
/// Test GoogleMapsPlugin
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
group('GoogleMapsPlugin', () {
_MockGoogleMapController controller;
GoogleMapsPlugin plugin;
int reportedMapId;
void onPlatformViewCreated(int id) {
reportedMapId = id;
}
setUp(() {
controller = _MockGoogleMapController();
plugin = GoogleMapsPlugin();
reportedMapId = null;
});
group('init/dispose', () {
group('before buildWidget', () {
testWidgets('init throws assertion', (WidgetTester tester) async {
expect(() => plugin.init(0), throwsAssertionError);
});
});
group('after buildWidget', () {
setUp(() {
plugin.debugSetMapById({0: controller});
});
testWidgets('init initializes controller', (WidgetTester tester) async {
await plugin.init(0);
verify(controller.init());
});
testWidgets('cannot call methods after dispose',
(WidgetTester tester) async {
plugin.dispose(mapId: 0);
verify(controller.dispose());
expect(
() => plugin.init(0),
throwsAssertionError,
reason: 'Method calls should fail after dispose.',
);
});
});
});
group('buildView', () {
final testMapId = 33930;
testWidgets('throws without _webOnlyMapCreationId',
(WidgetTester tester) async {
expect(
() => plugin.buildView({}, null, onPlatformViewCreated),
throwsAssertionError,
reason:
'_webOnlyMapCreationId is mandatory to prevent unnecessary reloads in web.',
);
});
testWidgets(
'returns an HtmlElementView and caches the controller for later',
(WidgetTester tester) async {
final Map<int, GoogleMapController> cache = {};
plugin.debugSetMapById(cache);
final HtmlElementView widget = plugin.buildView({
'_webOnlyMapCreationId': testMapId,
}, null, onPlatformViewCreated);
expect(
widget.viewType,
contains('$testMapId'),
reason:
'view type should contain the mapId passed when creating the map.',
);
expect(
reportedMapId,
testMapId,
reason: 'Should call onPlatformViewCreated with the mapId',
);
expect(cache, contains(testMapId));
expect(
cache[testMapId],
isNotNull,
reason: 'cached controller cannot be null.',
);
});
testWidgets('returns cached instance if it already exists',
(WidgetTester tester) async {
final expected = HtmlElementView(viewType: 'only-for-testing');
when(controller.widget).thenReturn(expected);
plugin.debugSetMapById({testMapId: controller});
final widget = plugin.buildView({
'_webOnlyMapCreationId': testMapId,
}, null, onPlatformViewCreated);
expect(widget, equals(expected));
expect(
reportedMapId,
isNull,
reason:
'onPlatformViewCreated should not be called when returning a cached controller',
);
});
});
group('setMapStyles', () {
String mapStyle = '''[{
"featureType": "poi.park",
"elementType": "labels.text.fill",
"stylers": [{"color": "#6b9a76"}]
}]''';
testWidgets('translates styles for controller',
(WidgetTester tester) async {
plugin.debugSetMapById({0: controller});
await plugin.setMapStyle(mapStyle, mapId: 0);
var captured =
verify(controller.updateRawOptions(captureThat(isMap))).captured[0];
expect(captured, contains('styles'));
var styles = captured['styles'];
expect(styles.length, 1);
// Let's peek inside the styles...
var style = styles[0] as gmaps.MapTypeStyle;
expect(style.featureType, gmaps.MapTypeStyleFeatureType.POI_PARK);
expect(
style.elementType, gmaps.MapTypeStyleElementType.LABELS_TEXT_FILL);
expect(style.stylers.length, 1);
expect(style.stylers[0].color, '#6b9a76');
});
});
// These methods only pass-through values from the plugin to the controller
// so we verify them all together here...
group('Pass-through methods:', () {
int mapId = 0;
setUp(() {
plugin.debugSetMapById({mapId: controller});
});
// Options
testWidgets('updateMapOptions', (WidgetTester tester) async {
final expectedMapOptions = <String, dynamic>{'someOption': 12345};
await plugin.updateMapOptions(expectedMapOptions, mapId: mapId);
verify(controller.updateRawOptions(expectedMapOptions));
});
// Geometry
testWidgets('updateMarkers', (WidgetTester tester) async {
final expectedUpdates = MarkerUpdates.from(null, null);
await plugin.updateMarkers(expectedUpdates, mapId: mapId);
verify(controller.updateMarkers(expectedUpdates));
});
testWidgets('updatePolygons', (WidgetTester tester) async {
final expectedUpdates = PolygonUpdates.from(null, null);
await plugin.updatePolygons(expectedUpdates, mapId: mapId);
verify(controller.updatePolygons(expectedUpdates));
});
testWidgets('updatePolylines', (WidgetTester tester) async {
final expectedUpdates = PolylineUpdates.from(null, null);
await plugin.updatePolylines(expectedUpdates, mapId: mapId);
verify(controller.updatePolylines(expectedUpdates));
});
testWidgets('updateCircles', (WidgetTester tester) async {
final expectedUpdates = CircleUpdates.from(null, null);
await plugin.updateCircles(expectedUpdates, mapId: mapId);
verify(controller.updateCircles(expectedUpdates));
});
// Camera
testWidgets('animateCamera', (WidgetTester tester) async {
final expectedUpdates =
CameraUpdate.newLatLng(LatLng(43.3626, -5.8433));
await plugin.animateCamera(expectedUpdates, mapId: mapId);
verify(controller.moveCamera(expectedUpdates));
});
testWidgets('moveCamera', (WidgetTester tester) async {
final expectedUpdates =
CameraUpdate.newLatLng(LatLng(43.3628, -5.8478));
await plugin.moveCamera(expectedUpdates, mapId: mapId);
verify(controller.moveCamera(expectedUpdates));
});
// Viewport
testWidgets('getVisibleRegion', (WidgetTester tester) async {
await plugin.getVisibleRegion(mapId: mapId);
verify(controller.getVisibleRegion());
});
testWidgets('getZoomLevel', (WidgetTester tester) async {
await plugin.getZoomLevel(mapId: mapId);
verify(controller.getZoomLevel());
});
testWidgets('getScreenCoordinate', (WidgetTester tester) async {
final latLng = LatLng(43.3613, -5.8499);
await plugin.getScreenCoordinate(latLng, mapId: mapId);
verify(controller.getScreenCoordinate(latLng));
});
testWidgets('getLatLng', (WidgetTester tester) async {
final coordinates = ScreenCoordinate(x: 19, y: 26);
await plugin.getLatLng(coordinates, mapId: mapId);
verify(controller.getLatLng(coordinates));
});
// InfoWindows
testWidgets('showMarkerInfoWindow', (WidgetTester tester) async {
final markerId = MarkerId('testing-123');
await plugin.showMarkerInfoWindow(markerId, mapId: mapId);
verify(controller.showInfoWindow(markerId));
});
testWidgets('hideMarkerInfoWindow', (WidgetTester tester) async {
final markerId = MarkerId('testing-123');
await plugin.hideMarkerInfoWindow(markerId, mapId: mapId);
verify(controller.hideInfoWindow(markerId));
});
testWidgets('isMarkerInfoWindowShown', (WidgetTester tester) async {
final markerId = MarkerId('testing-123');
await plugin.isMarkerInfoWindowShown(markerId, mapId: mapId);
verify(controller.isInfoWindowShown(markerId));
});
});
// Verify all event streams are filtered correctly from the main one...
group('Event Streams', () {
int mapId = 0;
StreamController<MapEvent> streamController;
setUp(() {
streamController = StreamController<MapEvent>.broadcast();
when(controller.events)
.thenAnswer((realInvocation) => streamController.stream);
plugin.debugSetMapById({mapId: controller});
});
// Dispatches a few events in the global streamController, and expects *only* the passed event to be there.
void _testStreamFiltering(Stream<MapEvent> stream, MapEvent event) async {
Timer.run(() {
streamController.add(_OtherMapEvent(mapId));
streamController.add(event);
streamController.add(_OtherMapEvent(mapId));
streamController.close();
});
final events = await stream.toList();
expect(events.length, 1);
expect(events[0], event);
}
// Camera events
testWidgets('onCameraMoveStarted', (WidgetTester tester) async {
final event = CameraMoveStartedEvent(mapId);
final stream = plugin.onCameraMoveStarted(mapId: mapId);
await _testStreamFiltering(stream, event);
});
testWidgets('onCameraMoveStarted', (WidgetTester tester) async {
final event = CameraMoveEvent(
mapId,
CameraPosition(
target: LatLng(43.3790, -5.8660),
),
);
final stream = plugin.onCameraMove(mapId: mapId);
await _testStreamFiltering(stream, event);
});
testWidgets('onCameraIdle', (WidgetTester tester) async {
final event = CameraIdleEvent(mapId);
final stream = plugin.onCameraIdle(mapId: mapId);
await _testStreamFiltering(stream, event);
});
// Marker events
testWidgets('onMarkerTap', (WidgetTester tester) async {
final event = MarkerTapEvent(mapId, MarkerId('test-123'));
final stream = plugin.onMarkerTap(mapId: mapId);
await _testStreamFiltering(stream, event);
});
testWidgets('onInfoWindowTap', (WidgetTester tester) async {
final event = InfoWindowTapEvent(mapId, MarkerId('test-123'));
final stream = plugin.onInfoWindowTap(mapId: mapId);
await _testStreamFiltering(stream, event);
});
testWidgets('onMarkerDragEnd', (WidgetTester tester) async {
final event = MarkerDragEndEvent(
mapId,
LatLng(43.3677, -5.8372),
MarkerId('test-123'),
);
final stream = plugin.onMarkerDragEnd(mapId: mapId);
await _testStreamFiltering(stream, event);
});
// Geometry
testWidgets('onPolygonTap', (WidgetTester tester) async {
final event = PolygonTapEvent(mapId, PolygonId('test-123'));
final stream = plugin.onPolygonTap(mapId: mapId);
await _testStreamFiltering(stream, event);
});
testWidgets('onPolylineTap', (WidgetTester tester) async {
final event = PolylineTapEvent(mapId, PolylineId('test-123'));
final stream = plugin.onPolylineTap(mapId: mapId);
await _testStreamFiltering(stream, event);
});
testWidgets('onCircleTap', (WidgetTester tester) async {
final event = CircleTapEvent(mapId, CircleId('test-123'));
final stream = plugin.onCircleTap(mapId: mapId);
await _testStreamFiltering(stream, event);
});
// Map taps
testWidgets('onTap', (WidgetTester tester) async {
final event = MapTapEvent(mapId, LatLng(43.3597, -5.8458));
final stream = plugin.onTap(mapId: mapId);
await _testStreamFiltering(stream, event);
});
testWidgets('onLongPress', (WidgetTester tester) async {
final event = MapLongPressEvent(mapId, LatLng(43.3608, -5.8425));
final stream = plugin.onLongPress(mapId: mapId);
await _testStreamFiltering(stream, event);
});
});
});
}
class _OtherMapEvent extends MapEvent<void> {
_OtherMapEvent(int mapId) : super(mapId, null);
}