Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat#58/teste login view #54

Merged
merged 6 commits into from
Dec 24, 2024
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
2 changes: 1 addition & 1 deletion lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'package:aranduapp/config/ThemeApp.dart';
import 'package:aranduapp/ui/login/view/LoginView.dart';
import 'package:aranduapp/ui/login/view/login_view.dart';
import 'package:aranduapp/ui/welcome/view/WelcomeView.dart';
import 'package:flutter/material.dart';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import 'package:aranduapp/core/log/Log.dart';
import 'package:aranduapp/ui/navbar/view/navBarView.dart';
import 'package:aranduapp/ui/shared/TextAndLink.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';

import 'package:aranduapp/ui/login/viewModel/LoginViewModel.dart';
import 'package:aranduapp/ui/login/viewModel/login_view_model.dart';

import 'package:aranduapp/ui/recover_account/view/recover_account_view.dart';
import 'package:aranduapp/ui/register_account/view/RegisterAccount.dart';
Expand All @@ -23,28 +22,28 @@ class Login extends StatelessWidget {
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => LoginViewModel(context),
child: const _Login(),
child: const LoginScreen(),
);
}
}

class _Login extends StatefulWidget {
const _Login({super.key});
class LoginScreen extends StatefulWidget {
const LoginScreen({super.key});

@override
State<StatefulWidget> createState() {
return _LoginState();
return _LoginScreenState();
}
}

class _LoginState extends State<_Login> {
class _LoginScreenState extends State<LoginScreen> {
late Future<void> _future;

@override
void initState() {
super.initState();
_future = Provider.of<LoginViewModel>(context, listen: false)
.validateToken();
_future =
Provider.of<LoginViewModel>(context, listen: false).validateToken();
}

@override
Expand All @@ -58,7 +57,6 @@ class _LoginState extends State<_Login> {
if (snapshot.connectionState == ConnectionState.waiting) {
return _loadingScreen(viewModel);
} else if (!snapshot.hasError) {
viewModel.loginWithDeviceAuth();
return _authDevice(viewModel);
} else {
return _emailAndPassword(viewModel);
Expand All @@ -73,6 +71,14 @@ class _LoginState extends State<_Login> {
}

Widget _authDevice(LoginViewModel viewModel) {
Log.d("Mostrando tela de autorização do dispositivo");

viewModel.loginWithDeviceAuth().then((ok) {
if (ok) {
viewModel.goToHome();
}
});

return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expand All @@ -93,7 +99,7 @@ class _LoginState extends State<_Login> {
child: ElevatedButton(
onPressed: () async {
viewModel.loginWithDeviceAuth().then((ok) {
viewModel.goNextPage();
viewModel.goToHome();
});
},
child: const Text('Usar senha do celular'),
Expand Down Expand Up @@ -156,7 +162,7 @@ class _LoginState extends State<_Login> {
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => RecoverAccount(),
builder: (context) => const RecoverAccount(),
),
);
},
Expand Down Expand Up @@ -185,9 +191,7 @@ class _LoginState extends State<_Login> {
child: ElevatedButton(
onPressed: () {
viewModel.loginWithEmailAndPassword().then((_) {

viewModel.goNextPage();

viewModel.goToHome();
}).catchError((e) => showDialog<Object>(
context: context,
builder: (BuildContext context) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,18 @@ class LoginViewModel extends ChangeNotifier {
.authenticate(localizedReason: 'Toque com o dedo no sensor para logar');
}

void goNextPage() {
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (context) => const NavbarView(),
),
);
void goToHome() {
try {
if (context.mounted) {
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (context) => const NavbarView(),
),
);
}
} catch (e) {
Log.e(e);
rethrow;
}
}
}
2 changes: 1 addition & 1 deletion lib/ui/onboarding/viewModel/onboarding_view_model.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import 'package:aranduapp/ui/login/view/LoginView.dart';
import 'package:aranduapp/ui/login/view/login_view.dart';
import 'package:flutter/material.dart';

class OnboardingViewModel extends ChangeNotifier {
Expand Down
2 changes: 1 addition & 1 deletion lib/ui/register_account/view/RegisterAccount.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import 'package:aranduapp/ui/login/view/LoginView.dart';
import 'package:aranduapp/ui/login/view/login_view.dart';
import 'package:aranduapp/ui/shared/OrDivider.dart';
import 'package:aranduapp/ui/shared/TextAndLink.dart';
import 'package:aranduapp/ui/shared/TextName.dart';
Expand Down
118 changes: 118 additions & 0 deletions test/ui/login/view/login_view_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import 'package:aranduapp/ui/login/view/login_view.dart';
import 'package:aranduapp/ui/login/viewModel/login_view_model.dart';
import 'package:aranduapp/ui/shared/TextEmail.dart';
import 'package:aranduapp/ui/shared/TextPassword.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';

@GenerateNiceMocks([MockSpec<LoginViewModel>()])
import 'login_view_test.mocks.dart';

void main() {
late MockLoginViewModel mockViewModel;

setUp(() {
mockViewModel = MockLoginViewModel();
when(mockViewModel.formKey).thenReturn(GlobalKey<FormState>());
when(mockViewModel.emailController).thenReturn(TextEditingController());
when(mockViewModel.passwordController).thenReturn(TextEditingController());
});

Widget createLoginScreen(LoginViewModel mockViewModel) {
return ChangeNotifierProvider<LoginViewModel>.value(
value: mockViewModel,
child: const MaterialApp(
home: LoginScreen(),
),
);
}

testWidgets('Displays loading screen while waiting for Future',
(WidgetTester tester) async {
when(mockViewModel.validateToken()).thenAnswer(
(_) async => await Future.delayed(const Duration(seconds: 1)));

await tester.pumpWidget(createLoginScreen(mockViewModel));

await tester.pump(const Duration(milliseconds: 500));

expect(find.byType(CircularProgressIndicator), findsOneWidget);

await tester.pumpAndSettle();

expect(find.byType(CircularProgressIndicator), findsNothing);
});

testWidgets('login with auth device', (WidgetTester tester) async {
when(mockViewModel.loginWithDeviceAuth()).thenAnswer((_) async => false);

await tester.pumpWidget(createLoginScreen(mockViewModel));
await tester.pumpAndSettle();

when(mockViewModel.loginWithDeviceAuth()).thenAnswer((_) async => true);
final button = find.text('Usar senha do celular');
expect(button, findsOneWidget);
await tester.tap(button);

await tester.pumpAndSettle();

verify(mockViewModel.goToHome()).called(1);
verify(mockViewModel.loginWithDeviceAuth()).called(2);
});

testWidgets(
'Login screen displays email and password fields and login button',
(WidgetTester tester) async {
when(mockViewModel.validateToken())
.thenAnswer((_) async => throw Exception('Token validation failed'));

await tester.pumpWidget(createLoginScreen(mockViewModel));
await tester.pumpAndSettle();

expect(find.byType(TextEmail), findsOneWidget);
expect(find.byType(TextPassWord), findsOneWidget);
expect(find.text('Entrar'), findsOneWidget);
});

testWidgets('Test User Input for Email and Password',
(WidgetTester tester) async {
when(mockViewModel.validateToken())
.thenAnswer((_) async => throw Exception('Token validation failed'));

await tester.pumpWidget(createLoginScreen(mockViewModel));
await tester.pumpAndSettle();

const email = '[email protected]';
const password = 'password123';

await tester.enterText(find.byType(TextEmail), email);
await tester.enterText(find.byType(TextPassWord), password);

expect(mockViewModel.emailController.text, email);
expect(mockViewModel.passwordController.text, password);
});

testWidgets('Login is successful',
(WidgetTester tester) async {
when(mockViewModel.validateToken())
.thenAnswer((_) async => throw Exception('Token validation failed'));

await tester.pumpWidget(createLoginScreen(mockViewModel));
await tester.pumpAndSettle();

await tester.tap(find.text('Entrar'));

when(mockViewModel.loginWithEmailAndPassword()).thenAnswer(
(_) async => await Future.delayed(const Duration(seconds: 1)));

await tester.pumpAndSettle();
verify(mockViewModel.loginWithEmailAndPassword()).called(1);
verify(mockViewModel.goToHome()).called(1);
});

testWidgets('Displays error when login fails', (WidgetTester tester) async {
});
}
Loading
Loading