[google_maps_flutter] Add an interface for test inspection (#6133)

diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md
index c1a7c95..e8da5f3 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 2.2.1
+
+* Adds a new interface for inspecting the platform map state in tests.
+
 ## 2.2.0
 
 * Adds new versions of `buildView` and `updateOptions` that take a new option
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/google_maps_flutter_platform_interface.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/google_maps_flutter_platform_interface.dart
index b83eaf4..6484ae6 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/google_maps_flutter_platform_interface.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/google_maps_flutter_platform_interface.dart
@@ -6,4 +6,5 @@
 export 'src/method_channel/method_channel_google_maps_flutter.dart'
     show MethodChannelGoogleMapsFlutter;
 export 'src/platform_interface/google_maps_flutter_platform.dart';
+export 'src/platform_interface/google_maps_inspector_platform.dart';
 export 'src/types/types.dart';
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/platform_interface/google_maps_flutter_platform.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/platform_interface/google_maps_flutter_platform.dart
index b6b9501..d4621a7 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/platform_interface/google_maps_flutter_platform.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/platform_interface/google_maps_flutter_platform.dart
@@ -443,4 +443,12 @@
       mapOptions: jsonForMapConfiguration(mapConfiguration),
     );
   }
+
+  /// Populates [GoogleMapsFlutterInspectorPlatform.instance] to allow
+  /// inspecting the platform map state.
+  @visibleForTesting
+  void enableDebugInspection() {
+    throw UnimplementedError(
+        'enableDebugInspection() has not been implemented.');
+  }
 }
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/platform_interface/google_maps_inspector_platform.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/platform_interface/google_maps_inspector_platform.dart
new file mode 100644
index 0000000..70e3329
--- /dev/null
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/platform_interface/google_maps_inspector_platform.dart
@@ -0,0 +1,117 @@
+// Copyright 2013 The Flutter 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 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart';
+import 'package:plugin_platform_interface/plugin_platform_interface.dart';
+
+/// The interface that platform-specific implementations of
+/// `google_maps_flutter` can extend to support state inpsection in tests.
+///
+/// Avoid `implements` of this interface. Using `implements` makes adding any
+/// new methods here a breaking change for end users of your platform!
+///
+/// Do `extends GoogleMapsInspectorPlatform` instead, so new methods
+/// added here are inherited in your code with the default implementation (that
+/// throws at runtime), rather than breaking your users at compile time.
+abstract class GoogleMapsInspectorPlatform extends PlatformInterface {
+  /// Constructs a GoogleMapsFlutterPlatform.
+  GoogleMapsInspectorPlatform() : super(token: _token);
+
+  static final Object _token = Object();
+
+  static GoogleMapsInspectorPlatform? _instance;
+
+  /// The instance of [GoogleMapsInspectorPlatform], if any.
+  ///
+  /// This is usually populated by calling
+  /// [GoogleMapsFlutterPlatform.enableDebugInspection].
+  static GoogleMapsInspectorPlatform? get instance => _instance;
+
+  /// Platform-specific plugins should set this with their own platform-specific
+  /// class that extends [GoogleMapsInspectorPlatform] in their
+  /// implementation of [GoogleMapsFlutterPlatform.enableDebugInspection].
+  static set instance(GoogleMapsInspectorPlatform? instance) {
+    if (instance != null) {
+      PlatformInterface.verify(instance, _token);
+    }
+    _instance = instance;
+  }
+
+  /// Returns the minimum and maxmimum zoom level settings.
+  Future<MinMaxZoomPreference> getMinMaxZoomLevels({required int mapId}) {
+    throw UnimplementedError('getMinMaxZoomLevels() has not been implemented.');
+  }
+
+  /// Returns true if the compass is enabled.
+  Future<bool> isCompassEnabled({required int mapId}) {
+    throw UnimplementedError('isCompassEnabled() has not been implemented.');
+  }
+
+  /// Returns true if lite mode is enabled.
+  Future<bool> isLiteModeEnabled({required int mapId}) {
+    throw UnimplementedError('isLiteModeEnabled() has not been implemented.');
+  }
+
+  /// Returns true if the map toolbar is enabled.
+  Future<bool> isMapToolbarEnabled({required int mapId}) {
+    throw UnimplementedError('isMapToolbarEnabled() has not been implemented.');
+  }
+
+  /// Returns true if the "my location" button is enabled.
+  Future<bool> isMyLocationButtonEnabled({required int mapId}) {
+    throw UnimplementedError(
+        'isMyLocationButtonEnabled() has not been implemented.');
+  }
+
+  /// Returns true if the traffic overlay is enabled.
+  Future<bool> isTrafficEnabled({required int mapId}) {
+    throw UnimplementedError('isTrafficEnabled() has not been implemented.');
+  }
+
+  /// Returns true if the building layer is enabled.
+  Future<bool> areBuildingsEnabled({required int mapId}) {
+    throw UnimplementedError('areBuildingsEnabled() has not been implemented.');
+  }
+
+  /// Returns true if rotate gestures are enabled.
+  Future<bool> areRotateGesturesEnabled({required int mapId}) {
+    throw UnimplementedError(
+        'areRotateGesturesEnabled() has not been implemented.');
+  }
+
+  /// Returns true if scroll gestures are enabled.
+  Future<bool> areScrollGesturesEnabled({required int mapId}) {
+    throw UnimplementedError(
+        'areScrollGesturesEnabled() has not been implemented.');
+  }
+
+  /// Returns true if tilt gestures are enabled.
+  Future<bool> areTiltGesturesEnabled({required int mapId}) {
+    throw UnimplementedError(
+        'areTiltGesturesEnabled() has not been implemented.');
+  }
+
+  /// Returns true if zoom controls are enabled.
+  Future<bool> areZoomControlsEnabled({required int mapId}) {
+    throw UnimplementedError(
+        'areZoomControlsEnabled() has not been implemented.');
+  }
+
+  /// Returns true if zoom gestures are enabled.
+  Future<bool> areZoomGesturesEnabled({required int mapId}) {
+    throw UnimplementedError(
+        'areZoomGesturesEnabled() has not been implemented.');
+  }
+
+  /// Returns information about the tile overlay with the given ID.
+  ///
+  /// The returned object will be synthesized from platform data, so will not
+  /// be the same Dart object as the original [TileOverlay] provided to the
+  /// platform interface with that ID, and not all fields (e.g.,
+  /// [TileOverlay.tileProvider]) will be populated.
+  Future<TileOverlay?> getTileOverlayInfo(TileOverlayId tileOverlayId,
+      {required int mapId}) {
+    throw UnimplementedError('getTileOverlayInfo() has not been implemented.');
+  }
+}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml
index 2b01e62..c421d13 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml
@@ -4,7 +4,7 @@
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+maps%22
 # NOTE: We strongly prefer non-breaking changes, even at the expense of a
 # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
-version: 2.2.0
+version: 2.2.1
 
 environment:
   sdk: '>=2.12.0 <3.0.0'
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/platform_interface/google_maps_inspector_platform_test.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/platform_interface/google_maps_inspector_platform_test.dart
new file mode 100644
index 0000000..689289b
--- /dev/null
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/platform_interface/google_maps_inspector_platform_test.dart
@@ -0,0 +1,33 @@
+// Copyright 2013 The Flutter 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 'package:flutter_test/flutter_test.dart';
+import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart';
+import 'package:mockito/mockito.dart';
+
+void main() {
+  // Store the initial instance before any tests change it.
+  final GoogleMapsInspectorPlatform? initialInstance =
+      GoogleMapsInspectorPlatform.instance;
+
+  test('default instance is null', () {
+    expect(initialInstance, isNull);
+  });
+
+  test('cannot be implemented with `implements`', () {
+    expect(() {
+      GoogleMapsInspectorPlatform.instance =
+          ImplementsGoogleMapsInspectorPlatform();
+    }, throwsA(isInstanceOf<AssertionError>()));
+  });
+
+  test('can be implement with `extends`', () {
+    GoogleMapsInspectorPlatform.instance = ExtendsGoogleMapsInspectorPlatform();
+  });
+}
+
+class ImplementsGoogleMapsInspectorPlatform extends Mock
+    implements GoogleMapsInspectorPlatform {}
+
+class ExtendsGoogleMapsInspectorPlatform extends GoogleMapsInspectorPlatform {}