Skip to content
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
34 changes: 23 additions & 11 deletions packages/firebase_core/firebase_core/lib/src/firebase.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,15 @@ class Firebase {
return _delegate.apps.map(FirebaseApp._).toList(growable: false);
}

/// Initializes a new [FirebaseApp] instance by [name] and [options] and returns
/// the created app. This method should be called before any usage of FlutterFire plugins.
/// Initializes a new [FirebaseApp] instance by [name] and [options] and
/// returns the created app. This method should be called before any usage of
/// FlutterFire plugins.
///
/// If a [demoProjectId] is provided, a new [FirebaseApp] instance will be
/// initialized with a set of default options for demo projects, overriding
/// the [options] argument. If no [name] is provided alongside a
/// [demoProjectId], the [demoProjectId] will be used as the app name. By
/// convention, the [demoProjectId] should begin with "demo-".
///
/// The default app instance can be initialized here simply by passing no "name" as an argument
/// in both Dart & manual initialization flows.
Expand All @@ -52,16 +59,21 @@ class Firebase {
// We use 'web' as the default platform for unknown platforms.
platformString = 'web';
}
FirebaseAppPlatform app = await _delegate.initializeApp(
options: FirebaseOptions(
apiKey: '',
appId: '1:1:$platformString:1',
messagingSenderId: '',
projectId: demoProjectId,
),
// A name must be set, otherwise [DEFAULT] will be used and the options
// we've provided will be ignored if any platform specific configuration
// files exist (i.e. GoogleService-Info.plist for iOS).
name ??= demoProjectId;
// The user should not set any options if they specify a demo project
// id, but it was allowed when this API was first added, so we allow it
// for backwards compatibility and simply override the user-provided
// options.
options = FirebaseOptions(
apiKey: '12345',
appId: '1:1:$platformString:1',
messagingSenderId: '',
projectId: demoProjectId,
);

return FirebaseApp._(app);
// Now fall through to the normal initialization logic.
}
FirebaseAppPlatform app = await _delegate.initializeApp(
name: name,
Expand Down
39 changes: 39 additions & 0 deletions packages/firebase_core/firebase_core/test/firebase_core_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,45 @@ void main() {
]);
});
});

test('.initializeApp() with demoProjectId', () async {
const String demoProjectId = 'demo-project-id';
const String expectedName = demoProjectId;
const FirebaseOptions expectedOptions = FirebaseOptions(
apiKey: '12345',
// Flutter tests use android as the default platform.
appId: '1:1:android:1',
messagingSenderId: '',
projectId: demoProjectId,
);

final mock = MockFirebaseCore();
Firebase.delegatePackingProperty = mock;

final FirebaseAppPlatform platformApp =
FirebaseAppPlatform(expectedName, expectedOptions);

when(mock.apps).thenReturn([platformApp]);
when(mock.app(expectedName)).thenReturn(platformApp);
when(mock.initializeApp(name: expectedName, options: expectedOptions))
.thenAnswer((_) => Future.value(platformApp));

// Initialize the app with only a demo project id. The implementation will
// set the name and options accordingly.
FirebaseApp initializedApp = await Firebase.initializeApp(
demoProjectId: demoProjectId,
);
FirebaseApp app = Firebase.app(expectedName);

expect(initializedApp, app);
verifyInOrder([
mock.initializeApp(
name: expectedName,
options: expectedOptions,
),
mock.app(expectedName),
]);
});
}

class MockFirebaseCore extends Mock
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,7 @@ class MethodChannelFirebase extends FirebasePlatform {
// check to see if options are roughly identical (so we don't unnecessarily
// throw on minor differences such as platform specific keys missing
// e.g. hot reloads/restarts).
if (defaultApp != null &&
_options != null &&
!_options.projectId.startsWith('demo-')) {
if (defaultApp != null && _options != null) {
if (_options.apiKey != defaultApp.options.apiKey ||
(_options.databaseURL != null &&
_options.databaseURL != defaultApp.options.databaseURL) ||
Expand Down
Loading