From 999989f49d15b3128fd71fa8f9202709573b5d9a Mon Sep 17 00:00:00 2001 From: Harry Terkelsen Date: Wed, 20 Nov 2019 16:30:24 -0800 Subject: [PATCH] [firebase_core] Migrate to platform_interface --- .../firebase_core/firebase_core/CHANGELOG.md | 4 + .../firebase_core/lib/firebase_core.dart | 7 +- .../firebase_core/lib/src/firebase_app.dart | 38 ++--- .../lib/src/firebase_options.dart | 150 ------------------ .../firebase_core/firebase_core/pubspec.yaml | 4 +- .../test/firebase_core_test.dart | 126 ++++++--------- 6 files changed, 67 insertions(+), 262 deletions(-) delete mode 100644 packages/firebase_core/firebase_core/lib/src/firebase_options.dart diff --git a/packages/firebase_core/firebase_core/CHANGELOG.md b/packages/firebase_core/firebase_core/CHANGELOG.md index aa76e0bbbf2a..56dc50d2501a 100644 --- a/packages/firebase_core/firebase_core/CHANGELOG.md +++ b/packages/firebase_core/firebase_core/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.2 + +* Migrate to `firebase_core_platform_interface`. + ## 0.4.1+6 * Update the homepage now that the package structure has changed. diff --git a/packages/firebase_core/firebase_core/lib/firebase_core.dart b/packages/firebase_core/firebase_core/lib/firebase_core.dart index 7a8d76191744..02e92d5340cd 100644 --- a/packages/firebase_core/firebase_core/lib/firebase_core.dart +++ b/packages/firebase_core/firebase_core/lib/firebase_core.dart @@ -6,10 +6,11 @@ library firebase_core; import 'dart:async'; import 'dart:io' show Platform; -import 'dart:ui' show hashValues; -import 'package:flutter/services.dart'; +import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart'; import 'package:meta/meta.dart'; +export 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart' + show FirebaseOptions; + part 'src/firebase_app.dart'; -part 'src/firebase_options.dart'; diff --git a/packages/firebase_core/firebase_core/lib/src/firebase_app.dart b/packages/firebase_core/firebase_core/lib/src/firebase_app.dart index 7c0bec0e0dda..415388cbefed 100644 --- a/packages/firebase_core/firebase_core/lib/src/firebase_app.dart +++ b/packages/firebase_core/firebase_core/lib/src/firebase_app.dart @@ -14,37 +14,23 @@ class FirebaseApp { static final String defaultAppName = Platform.isIOS ? '__FIRAPP_DEFAULT' : '[DEFAULT]'; - @visibleForTesting - static const MethodChannel channel = MethodChannel( - 'plugins.flutter.io/firebase_core', - ); - /// A copy of the options for this app. These are non-modifiable. /// /// This getter is asynchronous because apps can also be configured by native /// code. Future get options async { - final Map app = - await channel.invokeMapMethod( - 'FirebaseApp#appNamed', - name, - ); + final PlatformFirebaseApp app = + await FirebaseCorePlatform.instance.appNamed(name); assert(app != null); - return FirebaseOptions.from(app['options']); + return app.options; } /// Returns a previously created FirebaseApp instance with the given name, /// or null if no such app exists. static Future appNamed(String name) async { - // TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter. - // https://github.com/flutter/flutter/issues/26431 - // ignore: strong_mode_implicit_dynamic_method - final Map app = - await channel.invokeMapMethod( - 'FirebaseApp#appNamed', - name, - ); - return app == null ? null : FirebaseApp(name: app['name']); + final PlatformFirebaseApp app = + await FirebaseCorePlatform.instance.appNamed(name); + return app == null ? null : FirebaseApp(name: app.name); } /// Returns the default (first initialized) instance of the FirebaseApp. @@ -69,22 +55,18 @@ class FirebaseApp { if (existingApp != null) { return existingApp; } - await channel.invokeMethod( - 'FirebaseApp#configure', - {'name': name, 'options': options.asMap}, - ); + await FirebaseCorePlatform.instance.configure(name, options); return FirebaseApp(name: name); } /// Returns a list of all extant FirebaseApp instances, or null if there are /// no FirebaseApp instances. static Future> allApps() async { - final List result = await channel.invokeListMethod( - 'FirebaseApp#allApps', - ); + final List result = + await FirebaseCorePlatform.instance.allApps(); return result ?.map( - (dynamic app) => FirebaseApp(name: app['name']), + (PlatformFirebaseApp app) => FirebaseApp(name: app.name), ) ?.toList(); } diff --git a/packages/firebase_core/firebase_core/lib/src/firebase_options.dart b/packages/firebase_core/firebase_core/lib/src/firebase_options.dart deleted file mode 100644 index 33aea5ced5b6..000000000000 --- a/packages/firebase_core/firebase_core/lib/src/firebase_options.dart +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2019 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. - -part of firebase_core; - -class FirebaseOptions { - const FirebaseOptions({ - this.apiKey, - this.bundleID, - this.clientID, - this.trackingID, - this.gcmSenderID, - this.projectID, - this.androidClientID, - @required this.googleAppID, - this.databaseURL, - this.deepLinkURLScheme, - this.storageBucket, - }) : assert(googleAppID != null); - - @visibleForTesting - FirebaseOptions.from(Map map) - : apiKey = map['APIKey'], - bundleID = map['bundleID'], - clientID = map['clientID'], - trackingID = map['trackingID'], - gcmSenderID = map['GCMSenderID'], - projectID = map['projectID'], - androidClientID = map['androidClientID'], - googleAppID = map['googleAppID'], - databaseURL = map['databaseURL'], - deepLinkURLScheme = map['deepLinkURLScheme'], - storageBucket = map['storageBucket'] { - assert(googleAppID != null); - } - - /// An API key used for authenticating requests from your app, e.g. - /// "AIzaSyDdVgKwhZl0sTTTLZ7iTmt1r3N2cJLnaDk", used to identify your app to - /// Google servers. - /// - /// This property is required on Android. - final String apiKey; - - /// The iOS bundle ID for the application. Defaults to - /// `[[NSBundle mainBundle] bundleID]` when not set manually or in a plist. - /// - /// This property is used on iOS only. - final String bundleID; - - /// The OAuth2 client ID for iOS application used to authenticate Google - /// users, for example "12345.apps.googleusercontent.com", used for signing in - /// with Google. - /// - /// This property is used on iOS only. - final String clientID; - - /// The tracking ID for Google Analytics, e.g. "UA-12345678-1", used to - /// configure Google Analytics. - /// - /// This property is used on iOS only. - final String trackingID; - - /// The Project Number from the Google Developer’s console, for example - /// "012345678901", used to configure Google Cloud Messaging. - /// - /// This property is required on iOS. - final String gcmSenderID; - - /// The Project ID from the Firebase console, for example "abc-xyz-123." - final String projectID; - - /// The Android client ID, for example "12345.apps.googleusercontent.com." - /// - /// This property is used on iOS only. - final String androidClientID; - - /// The Google App ID that is used to uniquely identify an instance of an app. - /// - /// This property cannot be `null`. - final String googleAppID; - - /// The database root URL, e.g. "http://abc-xyz-123.firebaseio.com." - /// - /// This property should be set for apps that use Firebase Database. - final String databaseURL; - - /// The URL scheme used to set up Durable Deep Link service. - /// - /// This property is used on iOS only. - final String deepLinkURLScheme; - - /// The Google Cloud Storage bucket name, e.g. - /// "abc-xyz-123.storage.firebase.com." - final String storageBucket; - - @visibleForTesting - Map get asMap { - return { - 'APIKey': apiKey, - 'bundleID': bundleID, - 'clientID': clientID, - 'trackingID': trackingID, - 'GCMSenderID': gcmSenderID, - 'projectID': projectID, - 'androidClientID': androidClientID, - 'googleAppID': googleAppID, - 'databaseURL': databaseURL, - 'deepLinkURLScheme': deepLinkURLScheme, - 'storageBucket': storageBucket, - }; - } - - @override - bool operator ==(dynamic other) { - if (identical(this, other)) return true; - if (other is! FirebaseOptions) return false; - return other.apiKey == apiKey && - other.bundleID == bundleID && - other.clientID == clientID && - other.trackingID == trackingID && - other.gcmSenderID == gcmSenderID && - other.projectID == projectID && - other.androidClientID == androidClientID && - other.googleAppID == googleAppID && - other.databaseURL == databaseURL && - other.deepLinkURLScheme == deepLinkURLScheme && - other.storageBucket == storageBucket; - } - - @override - int get hashCode { - return hashValues( - apiKey, - bundleID, - clientID, - trackingID, - gcmSenderID, - projectID, - androidClientID, - googleAppID, - databaseURL, - deepLinkURLScheme, - storageBucket, - ); - } - - @override - String toString() => asMap.toString(); -} diff --git a/packages/firebase_core/firebase_core/pubspec.yaml b/packages/firebase_core/firebase_core/pubspec.yaml index 1bc263c302d5..4506087f4685 100644 --- a/packages/firebase_core/firebase_core/pubspec.yaml +++ b/packages/firebase_core/firebase_core/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Core, enabling connecting to multiple Firebase apps. author: Flutter Team homepage: https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_core/firebase_core -version: 0.4.1+6 +version: 0.4.2 flutter: plugin: @@ -12,6 +12,7 @@ flutter: pluginClass: FirebaseCorePlugin dependencies: + firebase_core_platform_interface: ^1.0.0 flutter: sdk: flutter meta: "^1.0.5" @@ -22,6 +23,7 @@ dev_dependencies: sdk: flutter flutter_test: sdk: flutter + mockito: ^4.1.1 environment: sdk: ">=2.0.0-dev.28.0 <3.0.0" diff --git a/packages/firebase_core/firebase_core/test/firebase_core_test.dart b/packages/firebase_core/firebase_core/test/firebase_core_test.dart index 7c9effadc4f4..94d059094ba8 100755 --- a/packages/firebase_core/firebase_core/test/firebase_core_test.dart +++ b/packages/firebase_core/firebase_core/test/firebase_core_test.dart @@ -3,14 +3,14 @@ // found in the LICENSE file. import 'package:firebase_core/firebase_core.dart'; -import 'package:flutter/services.dart'; +import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/mockito.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); group('$FirebaseApp', () { - final List log = []; final FirebaseApp testApp = FirebaseApp( name: 'testApp', ); @@ -27,41 +27,36 @@ void main() { deepLinkURLScheme: 'testDeepLinkURLScheme', storageBucket: 'testStorageBucket', ); + MockFirebaseCore mock; setUp(() async { - FirebaseApp.channel - .setMockMethodCallHandler((MethodCall methodCall) async { - log.add(methodCall); - switch (methodCall.method) { - case 'FirebaseApp#appNamed': - if (methodCall.arguments != 'testApp') return null; - return { - 'name': 'testApp', - 'options': { - 'APIKey': 'testAPIKey', - 'bundleID': 'testBundleID', - 'clientID': 'testClientID', - 'trackingID': 'testTrackingID', - 'GCMSenderID': 'testGCMSenderID', - 'projectID': 'testProjectID', - 'androidClientID': 'testAndroidClientID', - 'googleAppID': 'testGoogleAppID', - 'databaseURL': 'testDatabaseURL', - 'deepLinkURLScheme': 'testDeepLinkURLScheme', - 'storageBucket': 'testStorageBucket', - }, - }; - case 'FirebaseApp#allApps': - return >[ - { - 'name': 'testApp', - }, - ]; - default: - return null; - } + mock = MockFirebaseCore(); + when(mock.isMock).thenReturn(true); + FirebaseCorePlatform.instance = mock; + + final PlatformFirebaseApp app = PlatformFirebaseApp( + 'testApp', + const FirebaseOptions( + apiKey: 'testAPIKey', + bundleID: 'testBundleID', + clientID: 'testClientID', + trackingID: 'testTrackingID', + gcmSenderID: 'testGCMSenderID', + projectID: 'testProjectID', + androidClientID: 'testAndroidClientID', + googleAppID: 'testGoogleAppID', + databaseURL: 'testDatabaseURL', + deepLinkURLScheme: 'testDeepLinkURLScheme', + storageBucket: 'testStorageBucket', + ), + ); + + when(mock.appNamed('testApp')).thenAnswer((_) { + return Future.value(app); }); - log.clear(); + + when(mock.allApps()).thenAnswer((_) => + Future>.value([app])); }); test('configure', () async { @@ -75,26 +70,13 @@ void main() { options: testOptions, ); expect(newApp.name, equals('newApp')); - expect( - log, - [ - isMethodCall( - 'FirebaseApp#appNamed', - arguments: 'testApp', - ), - isMethodCall( - 'FirebaseApp#appNamed', - arguments: 'newApp', - ), - isMethodCall( - 'FirebaseApp#configure', - arguments: { - 'name': 'newApp', - 'options': testOptions.asMap, - }, - ), - ], - ); + // It's ugly to specify mockito verification types + // ignore: always_specify_types + verifyInOrder([ + mock.appNamed('testApp'), + mock.appNamed('newApp'), + mock.configure('newApp', testOptions), + ]); }); test('appNamed', () async { @@ -103,37 +85,21 @@ void main() { expect((await existingApp.options), equals(testOptions)); final FirebaseApp missingApp = await FirebaseApp.appNamed('missingApp'); expect(missingApp, isNull); - expect( - log, - [ - isMethodCall( - 'FirebaseApp#appNamed', - arguments: 'testApp', - ), - isMethodCall( - 'FirebaseApp#appNamed', - arguments: 'testApp', - ), - isMethodCall( - 'FirebaseApp#appNamed', - arguments: 'missingApp', - ), - ], - ); + // It's ugly to specify mockito verification types + // ignore: always_specify_types + verifyInOrder([ + mock.appNamed('testApp'), + mock.appNamed('testApp'), + mock.appNamed('missingApp'), + ]); }); test('allApps', () async { final List allApps = await FirebaseApp.allApps(); expect(allApps, equals([testApp])); - expect( - log, - [ - isMethodCall( - 'FirebaseApp#allApps', - arguments: null, - ), - ], - ); + verify(mock.allApps()); }); }); } + +class MockFirebaseCore extends Mock implements FirebaseCorePlatform {}