From 1b288c97448d4f84bd3c7cdb1121fc1cd9689964 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Thu, 1 Sep 2022 13:42:51 -0400 Subject: [PATCH] [google_maps_flutter] Fix integration tests Some integration tests behave slightly differently on Android when using Hybrid Composition, and need to wait for a change to become true rather than it being immediately true. This replicates the changes from `google_maps_flutter_android` to the app-facing copy of those integration tests. Fixes tree breakage from publishing https://github.com/flutter/plugins/pull/6334 --- .../integration_test/google_maps_test.dart | 44 +++++++++++++++---- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/packages/google_maps_flutter/google_maps_flutter/example/integration_test/google_maps_test.dart b/packages/google_maps_flutter/google_maps_flutter/example/integration_test/google_maps_test.dart index 7479917402ee..38a02ea0d8f1 100644 --- a/packages/google_maps_flutter/google_maps_flutter/example/integration_test/google_maps_test.dart +++ b/packages/google_maps_flutter/google_maps_flutter/example/integration_test/google_maps_test.dart @@ -22,6 +22,28 @@ void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); GoogleMapsFlutterPlatform.instance.enableDebugInspection(); + // Repeatedly checks an asynchronous value against a test condition, waiting + // one frame between each check, returing the value if it passes the predicate + // before [maxTries] is reached. + // + // Returns null if the predicate is never satisfied. + // + // This is useful for cases where the Maps SDK has some internally + // asynchronous operation that we don't have visibility into (e.g., native UI + // animations). + Future waitForValueMatchingPredicate(WidgetTester tester, + Future Function() getValue, bool Function(T) predicate, + {int maxTries = 100}) async { + for (int i = 0; i < maxTries; i++) { + final T value = await getValue(); + if (predicate(value)) { + return value; + } + await tester.pump(); + } + return null; + } + testWidgets('testCompassToggle', (WidgetTester tester) async { final Key key = GlobalKey(); final Completer mapIdCompleter = Completer(); @@ -481,12 +503,13 @@ void main() { final GoogleMapController mapController = await mapControllerCompleter.future; + // Wait for the visible region to be non-zero. final LatLngBounds firstVisibleRegion = - await mapController.getVisibleRegion(); - - expect(firstVisibleRegion, isNotNull); - expect(firstVisibleRegion.southwest, isNotNull); - expect(firstVisibleRegion.northeast, isNotNull); + await waitForValueMatchingPredicate( + tester, + () => mapController.getVisibleRegion(), + (LatLngBounds bounds) => bounds != zeroLatLngBounds) ?? + zeroLatLngBounds; expect(firstVisibleRegion, isNot(zeroLatLngBounds)); expect(firstVisibleRegion.contains(_kInitialMapCenter), isTrue); @@ -517,9 +540,6 @@ void main() { final LatLngBounds secondVisibleRegion = await mapController.getVisibleRegion(); - expect(secondVisibleRegion, isNotNull); - expect(secondVisibleRegion.southwest, isNotNull); - expect(secondVisibleRegion.northeast, isNotNull); expect(secondVisibleRegion, isNot(zeroLatLngBounds)); expect(firstVisibleRegion, isNot(secondVisibleRegion)); @@ -906,7 +926,13 @@ void main() { expect(iwVisibleStatus, false); await controller.showMarkerInfoWindow(marker.markerId); - iwVisibleStatus = await controller.isMarkerInfoWindowShown(marker.markerId); + // The Maps SDK doesn't always return true for whether it is shown + // immediately after showing it, so wait for it to report as shown. + iwVisibleStatus = await waitForValueMatchingPredicate( + tester, + () => controller.isMarkerInfoWindowShown(marker.markerId), + (bool visible) => visible) ?? + false; expect(iwVisibleStatus, true); await controller.hideMarkerInfoWindow(marker.markerId);