From 1893fbe842d5ed7328334b10a84acfa651e0eef8 Mon Sep 17 00:00:00 2001 From: Evandro Junior <47798920+evandrmb@users.noreply.github.com> Date: Sun, 1 Nov 2020 01:57:12 -0300 Subject: [PATCH 1/5] added tests over register controller Also typed the binds in AppModule this way i can change them in the tests to mocked binds --- lib/app/app_module.dart | 8 +- pubspec.lock | 298 +++++++++++++----- pubspec.yaml | 3 +- test/init_app_module_helper.dart | 19 ++ .../modules/auth/init_auth_module_helper.dart | 18 ++ .../presenter/register_controller_test.dart | 66 ++++ 6 files changed, 328 insertions(+), 84 deletions(-) create mode 100644 test/init_app_module_helper.dart create mode 100644 test/modules/auth/init_auth_module_helper.dart create mode 100644 test/modules/auth/presenter/register_controller_test.dart diff --git a/lib/app/app_module.dart b/lib/app/app_module.dart index dca218f..8f7fa14 100644 --- a/lib/app/app_module.dart +++ b/lib/app/app_module.dart @@ -12,10 +12,10 @@ import 'shared/service/repository.dart'; class AppModule extends MainModule { @override List get binds => [ - Bind((i) => FirebaseAuth.instance), - Bind((i) => FirebaseFirestore.instance), - Bind((i) => Repository(client: i())), - Bind((i) => FoodPromiseController()), + Bind((i) => FirebaseAuth.instance), + Bind((i) => FirebaseFirestore.instance), + Bind((i) => Repository(client: i())), + Bind((i) => FoodPromiseController()), ]; @override diff --git a/pubspec.lock b/pubspec.lock index db9c625..e07f987 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,174 +1,244 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + url: "https://pub.dartlang.org" + source: hosted + version: "12.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.dartlang.org" + source: hosted + version: "0.40.5" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.0" asuka: dependency: "direct main" description: name: asuka - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.4" async: dependency: transitive description: name: async - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.5.0-nullsafety.1" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.0-nullsafety.1" + build: + dependency: transitive + description: + name: build + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.0" + built_collection: + dependency: transitive + description: + name: built_collection + url: "https://pub.dartlang.org" + source: hosted + version: "4.3.2" + built_value: + dependency: transitive + description: + name: built_value + url: "https://pub.dartlang.org" + source: hosted + version: "7.1.0" cached_network_image: dependency: "direct main" description: name: cached_network_image - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.3.3" characters: dependency: transitive description: name: characters - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.1.0-nullsafety.3" charcode: dependency: transitive description: name: charcode - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.2.0-nullsafety.1" + cli_util: + dependency: transitive + description: + name: cli_util + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.0" clock: dependency: transitive description: name: clock - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.1.0-nullsafety.1" cloud_firestore: dependency: "direct main" description: name: cloud_firestore - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.14.1+3" + version: "0.14.2" cloud_firestore_platform_interface: dependency: transitive description: name: cloud_firestore_platform_interface - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.2" + version: "2.1.3" cloud_firestore_web: dependency: transitive description: name: cloud_firestore_web - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.2.0+4" + version: "0.2.0+5" + code_builder: + dependency: transitive + description: + name: code_builder + url: "https://pub.dartlang.org" + source: hosted + version: "3.5.0" collection: dependency: transitive description: name: collection - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.15.0-nullsafety.3" convert: dependency: transitive description: name: convert - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.1" crypto: dependency: transitive description: name: crypto - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.5" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.1.3" + dart_style: + dependency: transitive + description: + name: dart_style + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.8+1" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.2.0-nullsafety.1" ffi: dependency: transitive description: name: ffi - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.1.3" file: dependency: transitive description: name: file - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "5.2.1" firebase: dependency: transitive description: name: firebase - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "7.3.2" firebase_auth: dependency: "direct main" description: name: firebase_auth - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.18.1+2" + version: "0.18.2" firebase_auth_platform_interface: dependency: transitive description: name: firebase_auth_platform_interface - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.2" firebase_auth_web: dependency: transitive description: name: firebase_auth_web - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.3.1+1" + version: "0.3.1+2" firebase_core: dependency: "direct main" description: name: firebase_core - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.5.0+1" + version: "0.5.1" firebase_core_platform_interface: dependency: transitive description: name: firebase_core_platform_interface - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.0" firebase_core_web: dependency: transitive description: name: firebase_core_web - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.2.0" + fixnum: + dependency: transitive + description: + name: fixnum + url: "https://pub.dartlang.org" + source: hosted + version: "0.10.11" flutter: dependency: "direct main" description: flutter @@ -178,28 +248,28 @@ packages: dependency: transitive description: name: flutter_blurhash - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.5.0" flutter_cache_manager: dependency: transitive description: name: flutter_cache_manager - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.0" flutter_custom_dialog: dependency: "direct main" description: name: flutter_custom_dialog - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.20" flutter_modular: dependency: "direct main" description: name: flutter_modular - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.1" flutter_test: @@ -216,196 +286,245 @@ packages: dependency: "direct main" description: name: fluttertoast - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "7.1.1" get: dependency: "direct main" description: name: get - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.15.0" + glob: + dependency: transitive + description: + name: glob + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" google_fonts: dependency: "direct main" description: name: google_fonts - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.1.0" http: dependency: transitive description: name: http - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.12.2" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.1.4" intl: dependency: "direct main" description: name: intl - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.16.1" js: dependency: transitive description: name: js - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.6.2" + logging: + dependency: transitive + description: + name: logging + url: "https://pub.dartlang.org" + source: hosted + version: "0.11.4" matcher: dependency: transitive description: name: matcher - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.12.10-nullsafety.1" meta: dependency: transitive description: name: meta - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.3.0-nullsafety.3" + mockito: + dependency: "direct dev" + description: + name: mockito + url: "https://pub.dartlang.org" + source: hosted + version: "4.1.3" + node_interop: + dependency: transitive + description: + name: node_interop + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + node_io: + dependency: transitive + description: + name: node_io + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" octo_image: dependency: transitive description: name: octo_image - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.3.0" + package_config: + dependency: transitive + description: + name: package_config + url: "https://pub.dartlang.org" + source: hosted + version: "1.9.3" path: dependency: transitive description: name: path - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.8.0-nullsafety.1" path_provider: dependency: transitive description: name: path_provider - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.6.21" + version: "1.6.22" path_provider_linux: dependency: transitive description: name: path_provider_linux - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.0.1+2" path_provider_macos: dependency: transitive description: name: path_provider_macos - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.0.4+4" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.3" path_provider_windows: dependency: transitive description: name: path_provider_windows - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.0.4+1" pedantic: dependency: "direct dev" description: name: pedantic - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.9.2" platform: dependency: transitive description: name: platform - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.2.1" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.3" process: dependency: transitive description: name: process - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.0.13" + pub_semver: + dependency: transitive + description: + name: pub_semver + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.4" quiver: dependency: transitive description: name: quiver - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.3" + version: "2.1.4+1" rxdart: dependency: transitive description: name: rxdart - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.24.1" shared_preferences: dependency: "direct main" description: name: shared_preferences - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.5.12+2" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.0.2+2" shared_preferences_macos: dependency: transitive description: name: shared_preferences_macos - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.0.1+10" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.4" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.1.2+7" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.0.1+1" sky_engine: @@ -413,104 +532,125 @@ packages: description: flutter source: sdk version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.8" source_span: dependency: transitive description: name: source_span - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.8.0-nullsafety.2" sqflite: dependency: transitive description: name: sqflite - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.3.1+2" sqflite_common: dependency: transitive description: name: sqflite_common - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.2+1" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.10.0-nullsafety.1" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.0-nullsafety.1" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.1.0-nullsafety.1" synchronized: dependency: transitive description: name: synchronized - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.2.0+2" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.2.0-nullsafety.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.2.19-nullsafety.2" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.3.0-nullsafety.3" uuid: dependency: transitive description: name: uuid - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.2.2" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.0-nullsafety.3" + watcher: + dependency: transitive + description: + name: watcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.7+15" win32: dependency: transitive description: name: win32 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.7.3" xdg_directories: dependency: transitive description: name: xdg_directories - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.1.2" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.1" sdks: dart: ">=2.10.0 <2.11.0" flutter: ">=1.20.0 <2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index a22d568..dcfb60d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -29,7 +29,7 @@ dependencies: cupertino_icons: ^0.1.3 firebase_auth: ^0.18.0+1 firebase_core: ^0.5.0 - flutter_modular: + flutter_modular: ^2.0.0+1 fluttertoast: ^7.1.1 get: 3.15.0 flutter_custom_dialog: @@ -41,6 +41,7 @@ dev_dependencies: flutter_test: sdk: flutter pedantic: + mockito: # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/test/init_app_module_helper.dart b/test/init_app_module_helper.dart new file mode 100644 index 0000000..b3ca5e9 --- /dev/null +++ b/test/init_app_module_helper.dart @@ -0,0 +1,19 @@ +import 'package:flutter_modular/flutter_modular.dart'; +import 'package:flutter_modular/flutter_modular_test.dart'; +import 'package:food_promise/app/app_module.dart'; + +class InitAppModuleHelper extends IModularTest { + @override + final ModularTestType modularTestType; + + InitAppModuleHelper({this.modularTestType = ModularTestType.resetModules}); + + @override + List get binds => []; + + @override + IModularTest get modulardependency => null; + + @override + ChildModule get module => AppModule(); +} diff --git a/test/modules/auth/init_auth_module_helper.dart b/test/modules/auth/init_auth_module_helper.dart new file mode 100644 index 0000000..b655e65 --- /dev/null +++ b/test/modules/auth/init_auth_module_helper.dart @@ -0,0 +1,18 @@ +import 'package:flutter_modular/flutter_modular_test.dart'; +import 'package:flutter_modular/src/interfaces/child_module.dart'; +import 'package:flutter_modular/src/inject/bind.dart'; +import 'package:flutter_modular/flutter_modular.dart'; + +import 'package:food_promise/app/modules/auth/auth_module.dart'; +import '../../init_app_module_helper.dart'; + +class InitAuthModuleHelper extends IModularTest { + @override + List get binds => []; + + @override + ChildModule get module => AuthModule(); + + @override + IModularTest get modulardependency => InitAppModuleHelper(); +} diff --git a/test/modules/auth/presenter/register_controller_test.dart b/test/modules/auth/presenter/register_controller_test.dart new file mode 100644 index 0000000..139acf5 --- /dev/null +++ b/test/modules/auth/presenter/register_controller_test.dart @@ -0,0 +1,66 @@ +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter_modular/flutter_modular.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:food_promise/app/modules/auth/presenter/register/register_controller.dart'; +import 'package:mockito/mockito.dart'; + +import '../init_auth_module_helper.dart'; + +class FirebaseAuthMock extends Mock implements FirebaseAuth {} + +void main() { + group('RegisterController test', () { + RegisterController controller; + FirebaseAuthMock auth; + + setUp(() { + InitAuthModuleHelper().load(changeBinds: [ + Bind((i) => FirebaseAuthMock()), + ]); + controller = Modular.get(); + auth = Modular.get(); + }); + + test('Should have inputs', () { + controller.init(); + + expect(controller.inputs, isInstanceOf()); + expect(controller.inputs[0], isInstanceOf>()); + + expect(controller.inputs.isNotEmpty, true); + }); + + test( + 'Should return true to obscure if the input is a password or a repeat password', + () { + controller.init(); + final passwordInput = controller.inputs.firstWhere( + (element) => (element as Map).containsValue('Password')) + as Map; + + final rePasswordInput = controller.inputs.firstWhere( + (element) => (element as Map).containsValue('Re-Password')) + as Map; + + expect(passwordInput['obscure'], true); + + expect(rePasswordInput['obscure'], true); + }); + + test('Should return false to obscure if the input is a name or a e-mail', + () { + controller.init(); + final nameInput = controller.inputs + .firstWhere((element) => (element as Map).containsValue('Name')) + as Map; + + final emailInput = controller.inputs + .firstWhere((element) => (element as Map).containsValue('E-mail')) + as Map; + + expect(nameInput['obscure'], false); + + expect(emailInput['obscure'], false); + }); + }); +} From 0bce6e80a0ada65e11f68ab9f150aa335ad089aa Mon Sep 17 00:00:00 2001 From: Evandro Junior <47798920+evandrmb@users.noreply.github.com> Date: Tue, 3 Nov 2020 17:44:58 -0300 Subject: [PATCH 2/5] Fixed one test --- .../register/register_controller.dart | 8 +-- .../presenter/register_controller_test.dart | 56 +++++++++++++++++-- 2 files changed, 55 insertions(+), 9 deletions(-) diff --git a/lib/app/modules/auth/presenter/register/register_controller.dart b/lib/app/modules/auth/presenter/register/register_controller.dart index 73887b0..042d404 100644 --- a/lib/app/modules/auth/presenter/register/register_controller.dart +++ b/lib/app/modules/auth/presenter/register/register_controller.dart @@ -53,7 +53,7 @@ class RegisterController extends GetxController { inputs[3]['controller'] = textEditingControllerRePass; } - Future _signUpFunction() async { + Future signUpFunction() async { loading.value = true; final auth = Modular.get(); @@ -101,8 +101,8 @@ class RegisterController extends GetxController { return false; } - void _onSignUpPressed() async { - final success = await _signUpFunction(); + void onSignUpPressed() async { + final success = await signUpFunction(); if (success) { print('Sign Up'); @@ -113,7 +113,7 @@ class RegisterController extends GetxController { } void register() { - if (formKey.currentState.validate()) _onSignUpPressed(); + if (formKey.currentState.validate()) onSignUpPressed(); } void close() { diff --git a/test/modules/auth/presenter/register_controller_test.dart b/test/modules/auth/presenter/register_controller_test.dart index 139acf5..0c8e35d 100644 --- a/test/modules/auth/presenter/register_controller_test.dart +++ b/test/modules/auth/presenter/register_controller_test.dart @@ -1,29 +1,42 @@ import 'package:firebase_auth/firebase_auth.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_modular/flutter_modular.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:food_promise/app/modules/auth/presenter/register/register_controller.dart'; import 'package:mockito/mockito.dart'; - +import 'package:asuka/asuka.dart' as asuka; import '../init_auth_module_helper.dart'; class FirebaseAuthMock extends Mock implements FirebaseAuth {} +class UserCredentialMock extends Mock implements UserCredential {} + void main() { + Widget materialWidget() => MaterialApp( + builder: asuka.builder, + home: Scaffold( + body: Container(), + ), + ); + group('RegisterController test', () { RegisterController controller; FirebaseAuthMock auth; setUp(() { + Firebase.initializeApp(); InitAuthModuleHelper().load(changeBinds: [ Bind((i) => FirebaseAuthMock()), + Bind((i) => FirebaseMock()), ]); + controller = Modular.get(); auth = Modular.get(); + controller.init(); }); test('Should have inputs', () { - controller.init(); - expect(controller.inputs, isInstanceOf()); expect(controller.inputs[0], isInstanceOf>()); @@ -33,7 +46,6 @@ void main() { test( 'Should return true to obscure if the input is a password or a repeat password', () { - controller.init(); final passwordInput = controller.inputs.firstWhere( (element) => (element as Map).containsValue('Password')) as Map; @@ -49,7 +61,6 @@ void main() { test('Should return false to obscure if the input is a name or a e-mail', () { - controller.init(); final nameInput = controller.inputs .firstWhere((element) => (element as Map).containsValue('Name')) as Map; @@ -62,5 +73,40 @@ void main() { expect(emailInput['obscure'], false); }); + + testWidgets( + 'Should return false if passwords don\'t match and loading is false', + (WidgetTester tester) async { + await tester.pumpWidget(materialWidget()); + + controller.textEditingControllerPass.text = 'test'; + controller.textEditingControllerRePass.text = 'not-tested'; + + final result = await controller.signUpFunction(); + + expect(result, false); + expect(controller.loading.value, false); + await tester.pump(); + expect(find.text('The passwords don\'t match'), findsOneWidget); + }); + + testWidgets('Should display a error message', (WidgetTester tester) async { + await tester.pumpWidget(materialWidget()); + + final email = 'foodpromise@gmail.com'; + final password = 'somepassword'; + + when(auth.createUserWithEmailAndPassword( + email: email, password: password)) + .thenAnswer((_) => throw FirebaseAuthException( + email: email, code: 'weak-password', message: '')); + + final result = await controller.signUpFunction(); + + expect(result, false); + expect(controller.loading.value, false); + await tester.pump(); + expect(find.text('The password provided is too weak.'), findsOneWidget); + }); }); } From 62e6ba2dc2d7148f5b2c8ae57a5748f5a56d59c2 Mon Sep 17 00:00:00 2001 From: Evandro Junior <47798920+evandrmb@users.noreply.github.com> Date: Tue, 3 Nov 2020 21:44:18 -0300 Subject: [PATCH 3/5] Update register_controller_test.dart --- .../auth/presenter/register_controller_test.dart | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/test/modules/auth/presenter/register_controller_test.dart b/test/modules/auth/presenter/register_controller_test.dart index 0c8e35d..7af1bdc 100644 --- a/test/modules/auth/presenter/register_controller_test.dart +++ b/test/modules/auth/presenter/register_controller_test.dart @@ -1,11 +1,11 @@ +import 'package:asuka/asuka.dart' as asuka; import 'package:firebase_auth/firebase_auth.dart'; -import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_modular/flutter_modular.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:food_promise/app/modules/auth/presenter/register/register_controller.dart'; import 'package:mockito/mockito.dart'; -import 'package:asuka/asuka.dart' as asuka; + import '../init_auth_module_helper.dart'; class FirebaseAuthMock extends Mock implements FirebaseAuth {} @@ -24,11 +24,9 @@ void main() { RegisterController controller; FirebaseAuthMock auth; - setUp(() { - Firebase.initializeApp(); + setUp(() async { InitAuthModuleHelper().load(changeBinds: [ Bind((i) => FirebaseAuthMock()), - Bind((i) => FirebaseMock()), ]); controller = Modular.get(); @@ -98,7 +96,7 @@ void main() { when(auth.createUserWithEmailAndPassword( email: email, password: password)) - .thenAnswer((_) => throw FirebaseAuthException( + .thenAnswer((_) async => throw FirebaseAuthException( email: email, code: 'weak-password', message: '')); final result = await controller.signUpFunction(); From 4a5cb6d12f41716f5e77b1aeb31a8af8fe73576b Mon Sep 17 00:00:00 2001 From: Evandro Junior <47798920+evandrmb@users.noreply.github.com> Date: Wed, 4 Nov 2020 15:19:10 -0300 Subject: [PATCH 4/5] Added LoginController test --- .../presenter/login/login_controller.dart | 8 +-- .../register/register_controller.dart | 1 + .../auth/presenter/login_controller_test.dart | 67 +++++++++++++++++++ .../presenter/register_controller_test.dart | 4 +- 4 files changed, 75 insertions(+), 5 deletions(-) create mode 100644 test/modules/auth/presenter/login_controller_test.dart diff --git a/lib/app/modules/auth/presenter/login/login_controller.dart b/lib/app/modules/auth/presenter/login/login_controller.dart index a1b9c5c..1d79c11 100644 --- a/lib/app/modules/auth/presenter/login/login_controller.dart +++ b/lib/app/modules/auth/presenter/login/login_controller.dart @@ -34,7 +34,7 @@ class LoginController extends GetxController { inputs[1]['controller'] = textEditingControllerPass; } - Future _signInFunction() async { + Future signInFunction() async { loading.value = true; final auth = Modular.get(); @@ -71,8 +71,8 @@ class LoginController extends GetxController { return false; } - void _onSignInPressed() async { - final success = await _signInFunction(); + void onSignInPressed() async { + final success = await signInFunction(); if (success) { print('Sign in success'); @@ -83,7 +83,7 @@ class LoginController extends GetxController { } void login() { - if (formKey.currentState.validate()) _onSignInPressed(); + if (formKey.currentState.validate()) onSignInPressed(); } void close() { diff --git a/lib/app/modules/auth/presenter/register/register_controller.dart b/lib/app/modules/auth/presenter/register/register_controller.dart index 042d404..f87cd5e 100644 --- a/lib/app/modules/auth/presenter/register/register_controller.dart +++ b/lib/app/modules/auth/presenter/register/register_controller.dart @@ -66,6 +66,7 @@ class RegisterController extends GetxController { if (rePassword == password) { final userCredential = await auth.createUserWithEmailAndPassword( email: email, password: password); + final uid = userCredential.user.uid; final repository = Modular.get(); diff --git a/test/modules/auth/presenter/login_controller_test.dart b/test/modules/auth/presenter/login_controller_test.dart new file mode 100644 index 0000000..2b23840 --- /dev/null +++ b/test/modules/auth/presenter/login_controller_test.dart @@ -0,0 +1,67 @@ +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_modular/flutter_modular.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:food_promise/app/modules/auth/presenter/login/login_controller.dart'; +import 'package:mockito/mockito.dart'; + +import 'package:asuka/asuka.dart' as asuka; + +import '../init_auth_module_helper.dart'; + +class FirebaseAuthMock extends Mock implements FirebaseAuth {} + +class UserCredentialMock extends Mock implements UserCredential {} + +void main() { + Widget materialWidget() => MaterialApp( + builder: asuka.builder, + home: Scaffold( + body: Container(), + ), + ); + + LoginController controller; + FirebaseAuthMock auth; + + group('LoginController test', () { + setUp(() async { + InitAuthModuleHelper().load(changeBinds: [ + Bind((i) => FirebaseAuthMock()), + ]); + + controller = Modular.get(); + auth = Modular.get(); + controller.init(); + }); + + test('Loading should be false when init', () { + expect(controller.loading.value, false); + }); + + test('Should have two inputs', () { + expect(controller.inputs, isInstanceOf()); + expect(controller.inputs[0], isInstanceOf>()); + + expect(controller.inputs.isNotEmpty, true); + expect(controller.inputs.length, 2); + }); + + test( + 'Should return true to obscure if the input is a password or a repeat password', + () { + final passwordInput = controller.inputs.firstWhere( + (element) => (element as Map).containsValue('Password')) + as Map; + + expect(passwordInput['obscure'], true); + }); + + test('Controllers should be disposed', () { + controller.close(); + + expect(controller.textEditingControllerPass, isNull); + expect(controller.textEditingControllerUser, isNull); + }); + }); +} diff --git a/test/modules/auth/presenter/register_controller_test.dart b/test/modules/auth/presenter/register_controller_test.dart index 7af1bdc..62b4e6f 100644 --- a/test/modules/auth/presenter/register_controller_test.dart +++ b/test/modules/auth/presenter/register_controller_test.dart @@ -30,7 +30,7 @@ void main() { ]); controller = Modular.get(); - auth = Modular.get(); + auth = Modular.get(); controller.init(); }); @@ -94,6 +94,8 @@ void main() { final email = 'foodpromise@gmail.com'; final password = 'somepassword'; + expect(auth, isInstanceOf()); + when(auth.createUserWithEmailAndPassword( email: email, password: password)) .thenAnswer((_) async => throw FirebaseAuthException( From 5c7d7208dbaa5ec99fc5cf1b35ae9f6eb6a5947e Mon Sep 17 00:00:00 2001 From: Evandro Junior <47798920+evandrmb@users.noreply.github.com> Date: Fri, 6 Nov 2020 00:50:36 -0300 Subject: [PATCH 5/5] Fixed auth tests --- .../auth/presenter/login_controller_test.dart | 32 ++++++++++-- .../presenter/register_controller_test.dart | 49 ++++++++++++++++--- 2 files changed, 71 insertions(+), 10 deletions(-) diff --git a/test/modules/auth/presenter/login_controller_test.dart b/test/modules/auth/presenter/login_controller_test.dart index 2b23840..e216a13 100644 --- a/test/modules/auth/presenter/login_controller_test.dart +++ b/test/modules/auth/presenter/login_controller_test.dart @@ -33,6 +33,8 @@ void main() { controller = Modular.get(); auth = Modular.get(); controller.init(); + controller.textEditingControllerPass.text = 'somepassword'; + controller.textEditingControllerUser.text = 'foodpromise@gmail.com'; }); test('Loading should be false when init', () { @@ -57,11 +59,33 @@ void main() { expect(passwordInput['obscure'], true); }); - test('Controllers should be disposed', () { - controller.close(); + test('Should return true to result', () async { + final result = await controller.signInFunction(); + expect(controller.loading.value, false); + + expect(result, true); + }); + + testWidgets('Shouldn\'t display a error message for weak password', + (WidgetTester tester) async { + await tester.pumpWidget(materialWidget()); + const error = 'Error'; + + when(auth.signInWithEmailAndPassword( + email: controller.textEditingControllerUser.text, + password: controller.textEditingControllerPass.text)) + .thenAnswer((_) => throw FirebaseAuthException( + email: controller.textEditingControllerUser.text, + code: 'weak-password', + message: '')); + + final result = await controller.signInFunction(); + + await tester.pump(); + expect(find.text(error), findsOneWidget); + expect(controller.loading.value, false); - expect(controller.textEditingControllerPass, isNull); - expect(controller.textEditingControllerUser, isNull); + expect(result, false); }); }); } diff --git a/test/modules/auth/presenter/register_controller_test.dart b/test/modules/auth/presenter/register_controller_test.dart index 62b4e6f..a7b08f4 100644 --- a/test/modules/auth/presenter/register_controller_test.dart +++ b/test/modules/auth/presenter/register_controller_test.dart @@ -91,22 +91,59 @@ void main() { testWidgets('Should display a error message', (WidgetTester tester) async { await tester.pumpWidget(materialWidget()); - final email = 'foodpromise@gmail.com'; - final password = 'somepassword'; + const error = 'Error'; + + controller.textEditingControllerName.text = 'foodpromise'; + controller.textEditingControllerEmail.text = 'foodpromise@gmail.com'; + controller.textEditingControllerPass.text = 'somepassword'; + controller.textEditingControllerRePass.text = 'somepassword'; expect(auth, isInstanceOf()); when(auth.createUserWithEmailAndPassword( - email: email, password: password)) + email: controller.textEditingControllerEmail.text, + password: controller.textEditingControllerPass.text)) .thenAnswer((_) async => throw FirebaseAuthException( - email: email, code: 'weak-password', message: '')); + email: controller.textEditingControllerEmail.text, + code: 'weak-password', + message: '')); - final result = await controller.signUpFunction(); + var result = await controller.signUpFunction(); + + expect(result, false); + expect(controller.loading.value, false); + await tester.pump(); + expect(find.text(error), findsOneWidget); + + when(auth.createUserWithEmailAndPassword( + email: controller.textEditingControllerEmail.text, + password: controller.textEditingControllerPass.text)) + .thenAnswer((_) async => throw FirebaseAuthException( + email: controller.textEditingControllerEmail.text, + code: 'email-already-in-use', + message: '')); + + result = await controller.signUpFunction(); + + expect(result, false); + expect(controller.loading.value, false); + await tester.pump(); + expect(find.text(error), findsOneWidget); + + when(auth.createUserWithEmailAndPassword( + email: controller.textEditingControllerEmail.text, + password: controller.textEditingControllerPass.text)) + .thenAnswer((_) async => throw FirebaseAuthException( + email: controller.textEditingControllerEmail.text, + code: 'invalid-email', + message: '')); + + result = await controller.signUpFunction(); expect(result, false); expect(controller.loading.value, false); await tester.pump(); - expect(find.text('The password provided is too weak.'), findsOneWidget); + expect(find.text(error), findsOneWidget); }); }); }