diff --git a/packages/firebase_ui_auth/doc/README.md b/packages/firebase_ui_auth/doc/README.md index f87252e1..e5e55711 100644 --- a/packages/firebase_ui_auth/doc/README.md +++ b/packages/firebase_ui_auth/doc/README.md @@ -42,7 +42,34 @@ Future main() async { ## macOS entitlements -If you're building for macOS, make sure to add necessary entitlements. Learn more [from the official Flutter documentation](https://docs.flutter.dev/development/platform-integration/macos/building). +If you're building for macOS, make sure to add necessary entitlements. Learn more [from the official Flutter documentation](https://docs.flutter.dev/platform-integration/macos/building#setting-up-entitlements). + +## Writing widget unit tests + +If you're writing widget unit tests, you'll need to add the following to your `setUpAll` method: + +```dart +setUpAll(() { + setFirebaseUiIsTestMode(true); +}); +``` + +Also, you will likely want to mock the `FirebaseAuth` instance: + +```dart +class MockFirebaseAuth extends Mock implements FirebaseAuth { + /// mock necessary methods +} +``` + +An instance of `MockFirebaseAuth` can then be passed to Firebase UI widgets: + +```dart +SignInScreen( + auth: MockFirebaseAuth(), + /// ... other props +) +``` ## Next steps diff --git a/packages/firebase_ui_auth/example/windows/flutter/generated_plugin_registrant.cc b/packages/firebase_ui_auth/example/windows/flutter/generated_plugin_registrant.cc index 6cae0978..53301a6f 100644 --- a/packages/firebase_ui_auth/example/windows/flutter/generated_plugin_registrant.cc +++ b/packages/firebase_ui_auth/example/windows/flutter/generated_plugin_registrant.cc @@ -7,12 +7,15 @@ #include "generated_plugin_registrant.h" #include +#include #include #include void RegisterPlugins(flutter::PluginRegistry* registry) { DesktopWebviewAuthPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("DesktopWebviewAuthPlugin")); + FirebaseAuthPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FirebaseAuthPluginCApi")); FirebaseCorePluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); FlutterSecureStorageWindowsPluginRegisterWithRegistrar( diff --git a/packages/firebase_ui_auth/example/windows/flutter/generated_plugins.cmake b/packages/firebase_ui_auth/example/windows/flutter/generated_plugins.cmake index a1eb5b7e..73d6fa1c 100644 --- a/packages/firebase_ui_auth/example/windows/flutter/generated_plugins.cmake +++ b/packages/firebase_ui_auth/example/windows/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST desktop_webview_auth + firebase_auth firebase_core flutter_secure_storage_windows ) diff --git a/packages/firebase_ui_auth/lib/firebase_ui_auth.dart b/packages/firebase_ui_auth/lib/firebase_ui_auth.dart index f223cd6f..1419a38c 100644 --- a/packages/firebase_ui_auth/lib/firebase_ui_auth.dart +++ b/packages/firebase_ui_auth/lib/firebase_ui_auth.dart @@ -95,6 +95,13 @@ export 'src/widgets/sign_out_button.dart'; export 'src/widgets/sms_code_input.dart' show SMSCodeInputState, SMSCodeInput; export 'src/widgets/user_avatar.dart'; +bool _isTestMode = false; + +@visibleForTesting +void setFirebaseUiIsTestMode(bool isTestMode) { + _isTestMode = isTestMode; +} + class FirebaseUIAuth { static final _providers = >{}; static final _configuredApps = {}; @@ -104,6 +111,7 @@ class FirebaseUIAuth { } static bool isAppConfigured(FirebaseApp app) { + if (_isTestMode) return true; return _providers.containsKey(app); } @@ -111,7 +119,7 @@ class FirebaseUIAuth { List configs, { FirebaseApp? app, }) { - if (Firebase.apps.isEmpty) { + if (!_isTestMode && Firebase.apps.isEmpty) { throw Exception( 'You must call Firebase.initializeApp() ' 'before calling configureProviders()', diff --git a/packages/firebase_ui_auth/lib/src/screens/sign_in_screen.dart b/packages/firebase_ui_auth/lib/src/screens/sign_in_screen.dart index 970a5df3..90bcbdbc 100644 --- a/packages/firebase_ui_auth/lib/src/screens/sign_in_screen.dart +++ b/packages/firebase_ui_auth/lib/src/screens/sign_in_screen.dart @@ -95,6 +95,9 @@ class SignInScreen extends MultiProviderScreen { /// * [EmailFormStyle] final Set? styles; + /// {@macro ui.auth.widgets.email_form.showPasswordVisibilityToggle} + final bool showPasswordVisibilityToggle; + /// {@macro ui.auth.screens.sign_in_screen} const SignInScreen({ super.key, @@ -114,6 +117,7 @@ class SignInScreen extends MultiProviderScreen { this.actions = const [], this.breakpoint = 800, this.styles, + this.showPasswordVisibilityToggle = false, }); Future _signInWithDifferentProvider( @@ -165,6 +169,7 @@ class SignInScreen extends MultiProviderScreen { subtitleBuilder: subtitleBuilder, footerBuilder: footerBuilder, breakpoint: breakpoint, + showPasswordVisibilityToggle: showPasswordVisibilityToggle, ), ); } diff --git a/packages/firebase_ui_auth/test/screens/sign_in_screen_test.dart b/packages/firebase_ui_auth/test/screens/sign_in_screen_test.dart new file mode 100644 index 00000000..99609b5f --- /dev/null +++ b/packages/firebase_ui_auth/test/screens/sign_in_screen_test.dart @@ -0,0 +1,43 @@ +import 'package:firebase_ui_auth/firebase_ui_auth.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../test_utils.dart'; + +void main() { + group("$SignInScreen", () { + setUpAll(() { + setFirebaseUiIsTestMode(true); + }); + + testWidgets( + "doesn't have password visibility toggle by default", + (tester) async { + await tester.pumpWidget( + TestMaterialApp( + child: SignInScreen( + auth: MockAuth(), + providers: [EmailAuthProvider()], + ), + ), + ); + + expect(find.byIcon(Icons.visibility), findsNothing); + }, + ); + + testWidgets('allows to add password visibility toggle', (tester) async { + await tester.pumpWidget( + TestMaterialApp( + child: SignInScreen( + auth: MockAuth(), + providers: [EmailAuthProvider()], + showPasswordVisibilityToggle: true, + ), + ), + ); + + expect(find.byIcon(Icons.visibility), findsOneWidget); + }); + }); +} diff --git a/packages/firebase_ui_auth/test/test_utils.dart b/packages/firebase_ui_auth/test/test_utils.dart index ccbb9a49..283c9d7e 100644 --- a/packages/firebase_ui_auth/test/test_utils.dart +++ b/packages/firebase_ui_auth/test/test_utils.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:firebase_auth/firebase_auth.dart'; +import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_dynamic_links/firebase_dynamic_links.dart'; import 'package:flutter/material.dart'; import 'package:mockito/mockito.dart'; @@ -60,12 +61,19 @@ class MockDynamicLinks extends Mock implements FirebaseDynamicLinks { Stream get onLink => _linkStream; } +class MockApp extends Mock implements FirebaseApp {} + class MockAuth extends Mock implements FirebaseAuth { MockUser? user; @override User? get currentUser => user; + @override + FirebaseApp get app => MockApp(); + + List get apps => [app]; + @override Future signInWithCredential( AuthCredential? credential, diff --git a/packages/firebase_ui_auth/test/src/views/login_view_test.dart b/packages/firebase_ui_auth/test/views/login_view_test.dart similarity index 98% rename from packages/firebase_ui_auth/test/src/views/login_view_test.dart rename to packages/firebase_ui_auth/test/views/login_view_test.dart index 4c856a42..493c1eb3 100644 --- a/packages/firebase_ui_auth/test/src/views/login_view_test.dart +++ b/packages/firebase_ui_auth/test/views/login_view_test.dart @@ -8,7 +8,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_test/flutter_test.dart'; -import '../../test_utils.dart'; +import '../test_utils.dart'; void main() { group("$LoginView", () { diff --git a/packages/firebase_ui_localizations/example/windows/flutter/generated_plugin_registrant.cc b/packages/firebase_ui_localizations/example/windows/flutter/generated_plugin_registrant.cc index d71cf017..171e6b21 100644 --- a/packages/firebase_ui_localizations/example/windows/flutter/generated_plugin_registrant.cc +++ b/packages/firebase_ui_localizations/example/windows/flutter/generated_plugin_registrant.cc @@ -7,11 +7,14 @@ #include "generated_plugin_registrant.h" #include +#include #include void RegisterPlugins(flutter::PluginRegistry* registry) { DesktopWebviewAuthPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("DesktopWebviewAuthPlugin")); + FirebaseAuthPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FirebaseAuthPluginCApi")); FirebaseCorePluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); } diff --git a/packages/firebase_ui_localizations/example/windows/flutter/generated_plugins.cmake b/packages/firebase_ui_localizations/example/windows/flutter/generated_plugins.cmake index e34ce28a..1650ccb9 100644 --- a/packages/firebase_ui_localizations/example/windows/flutter/generated_plugins.cmake +++ b/packages/firebase_ui_localizations/example/windows/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST desktop_webview_auth + firebase_auth firebase_core ) diff --git a/packages/firebase_ui_oauth/example/windows/flutter/generated_plugin_registrant.cc b/packages/firebase_ui_oauth/example/windows/flutter/generated_plugin_registrant.cc index 6cae0978..53301a6f 100644 --- a/packages/firebase_ui_oauth/example/windows/flutter/generated_plugin_registrant.cc +++ b/packages/firebase_ui_oauth/example/windows/flutter/generated_plugin_registrant.cc @@ -7,12 +7,15 @@ #include "generated_plugin_registrant.h" #include +#include #include #include void RegisterPlugins(flutter::PluginRegistry* registry) { DesktopWebviewAuthPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("DesktopWebviewAuthPlugin")); + FirebaseAuthPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FirebaseAuthPluginCApi")); FirebaseCorePluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); FlutterSecureStorageWindowsPluginRegisterWithRegistrar( diff --git a/packages/firebase_ui_oauth/example/windows/flutter/generated_plugins.cmake b/packages/firebase_ui_oauth/example/windows/flutter/generated_plugins.cmake index a1eb5b7e..73d6fa1c 100644 --- a/packages/firebase_ui_oauth/example/windows/flutter/generated_plugins.cmake +++ b/packages/firebase_ui_oauth/example/windows/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST desktop_webview_auth + firebase_auth firebase_core flutter_secure_storage_windows )