Skip to content

Instantly share code, notes, and snippets.

@prajwal27
Last active September 22, 2021 04:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save prajwal27/4735ed549779b8c8bd941adab574fb12 to your computer and use it in GitHub Desktop.
Save prajwal27/4735ed549779b8c8bd941adab574fb12 to your computer and use it in GitHub Desktop.
widget_testing_with_cubit
import 'dart:developer';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:mobility_one/repositories/accounts_repository.dart';
import 'package:mobility_one/repositories/authentication_repository.dart';
import 'package:mobility_one/util/api_client.dart';
import 'package:mobility_one/util/auth_util.dart';
import 'package:mobility_one/util/util.dart';
import 'package:oauth2/oauth2.dart' as oauth2;
import 'dart:html' as html;
part 'authentication_state.dart';
class AuthenticationCubit extends Cubit<AuthenticationState> {
AuthenticationCubit({required this.authenticationRepository, required this.accountsRepository})
: super(AuthenticationInitial());
final AuthenticationRepository authenticationRepository;
final AccountsRepository accountsRepository;
void onAppStart({required Uri currentUrl}) async {
final credentials = await authenticationRepository.getCredentials();
if (credentials != null && credentials.isExpired == false) {
emit(AuthenticationAuthenticated(credentials: credentials));
} else if (credentials != null && credentials.isExpired == true) {
try {
final newCredentials =
await credentials.refresh(identifier: AuthUtil.clientId);
await authenticationRepository.setCredentials(newCredentials);
emit(AuthenticationAuthenticated(credentials: newCredentials));
} catch (error) {
await authenticationRepository.deleteCredentials();
await authenticationRepository.deleteGrantCodeVerifier();
log('Error refreshing credentials $error');
emit(AuthenticationUnauthenticated());
}
} else {
final grant = await getGrant();
final queryParameters = currentUrl.queryParameters;
if (queryParameters.containsKey('code')) {
try {
final client =
await grant.handleAuthorizationResponse(queryParameters);
await authenticationRepository.setCredentials(client.credentials);
emit(AuthenticationAuthenticated(credentials: client.credentials));
client.close();
} catch (error) {
await authenticationRepository.deleteCredentials();
await authenticationRepository.deleteGrantCodeVerifier();
log('Error checking the token $error');
emit(AuthenticationUnauthenticated());
}
} else {
// html.window.location.assign(authorizationUrl);
}
}
}
Future<oauth2.AuthorizationCodeGrant> getGrant() async {
final savedCodeVerifier =
await authenticationRepository.getGrantCodeVerifier();
if (savedCodeVerifier != null) {
final savedGrant = oauth2.AuthorizationCodeGrant(AuthUtil.clientId,
AuthUtil.authorizationEndpoint, AuthUtil.tokenEndpoint,
codeVerifier: savedCodeVerifier);
await authenticationRepository.deleteGrantCodeVerifier();
return savedGrant;
}
final newCodeVerifier = Util.createCodeVerifier();
final newGrant = oauth2.AuthorizationCodeGrant(AuthUtil.clientId,
AuthUtil.authorizationEndpoint, AuthUtil.tokenEndpoint,
codeVerifier: newCodeVerifier);
await authenticationRepository.setGrantCodeVerifier(
codeVerifier: newCodeVerifier);
return newGrant;
}
Future<void> redirectToLoginPage() async {
final grant = await getGrant();
final authorizationUrl = grant
.getAuthorizationUrl(AuthUtil.redirectUrl, scopes: AuthUtil.scopes)
.toString();
html.window.location.assign(authorizationUrl);
}
Future<void> makeLogin(
{required String email, required String password}) async {
try {
emit(AuthenticationAuthenticating());
final authorizationUrl = AuthUtil.tokenEndpoint;
var client = await oauth2.resourceOwnerPasswordGrant(
authorizationUrl, email, password, identifier: 'trusted-login', secret: 'trusted-secret');
await authenticationRepository.setCredentials(client.credentials);
final userName = await accountsRepository.getCurrentAccount();
await accountsRepository.setUserName(userName);
emit(AuthenticationAuthenticated(credentials: client.credentials));
client.close();
} catch (err) {
print('err $err');
emit(AuthenticationFailed());
}
}
Future<void> signup(
{required String email,
required String password,
required String name,
required String companyName,
required String accountName}) async {
try {
emit(AuthenticationSigningUp());
final authorizationUrl = AuthUtil.tokenEndpoint;
var client = await oauth2.clientCredentialsGrant(authorizationUrl, 'trusted-login', 'trusted-secret', scopes: ['IdentityServerApi', 'create-users']);
await authenticationRepository.setAppCredentials(client.credentials);
await accountsRepository.signUp(requestBody: {
'Email': email,
'FullName': name,
'AccountName': accountName,
'CompanyName': companyName,
'Password': password
});
emit(AuthenticationSigningUpCompleted());
await makeLogin(email: email, password: password);
} catch (err) {
print('Error');
print((err as MobilityOneError));
emit(AuthenticationSignUpFailed());
}
}
Future<void> logout() async {
final credentials = await authenticationRepository.getCredentials();
if (credentials != null) {
print('deleting');
print('cr3ddtials ${credentials.idToken}');
print('cr3ddtials ${credentials.accessToken}');
await authenticationRepository.deleteCredentials();
await authenticationRepository.deleteGrantCodeVerifier();
print('credentials ${credentials.idToken}');
}
print('emiting');
emit(AuthenticationUnauthenticated());
}
}
import 'package:flip_card/flip_card.dart';
import 'package:flutter/material.dart';
import 'package:mobility_one/ui/screens/login_screen.dart';
import 'package:mobility_one/ui/screens/signup_screen.dart';
import 'package:mobility_one/util/my_colors.dart';
class AuthenticationScreen extends StatefulWidget {
const AuthenticationScreen({Key? key}) : super(key: key);
@override
_AuthenticationScreenState createState() => _AuthenticationScreenState();
}
class _AuthenticationScreenState extends State<AuthenticationScreen> {
GlobalKey<FlipCardState> cardKey =
GlobalKey<FlipCardState>(debugLabel: 'test');
var keys = Key('dc');
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: MyColors.backgroundColor,
body: FlipCard(
key: cardKey,
flipOnTouch: false,
front: LoginScreen(
onSignUpClick: _toggleCardFlip,
),
back: SignUpScreen(
onSignInClick: _toggleCardFlip,
),
),
);
}
void _toggleCardFlip() {
cardKey.currentState!.toggleCard();
}
}
import 'package:bloc_test/bloc_test.dart';
import 'package:flip_card/flip_card.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mobility_one/blocs/authentication_cubit/authentication_cubit.dart';
import 'package:mobility_one/blocs/drawer_cubit/drawer_cubit.dart';
import 'package:mobility_one/blocs/drawer_cubit/drawer_state.dart';
import 'package:mobility_one/ui/screens/authentication_screen.dart';
import 'package:mockito/mockito.dart';
import 'package:mocktail/mocktail.dart' as mocktail;
class MockAuthenticationCubit extends MockCubit<AuthenticationState>
implements AuthenticationCubit {}
class MockDrawerCubit extends MockCubit<DrawerState> implements DrawerCubit {}
class AuthenticationStateFake extends Fake implements AuthenticationState {}
void main() {
group('DetailsScreen', () {
late MockAuthenticationCubit mockAuthenticationCubit;
late MockDrawerCubit mockDrawerCubit;
setUp(() {
mockAuthenticationCubit = MockAuthenticationCubit();
mockDrawerCubit = MockDrawerCubit();
mocktail.registerFallbackValue<AuthenticationState>(
AuthenticationStateFake());
});
var key = GlobalKey<FlipCardState>(debugLabel: 'test');
testWidgets('renders properly with no todos', (WidgetTester tester) async {
when(() => mockAuthenticationCubit.state)
.thenReturn(() => AuthenticationUnauthenticated());
whenListen<AuthenticationState>(
mockAuthenticationCubit,
Stream<AuthenticationState>.fromIterable(
[
AuthenticationUnauthenticated(),
],
),
initialState: AuthenticationInitial(),
);
await tester.pumpWidget(MultiBlocProvider(
providers: [
BlocProvider<AuthenticationCubit>.value(
value: mockAuthenticationCubit,
),
BlocProvider<DrawerCubit>.value(
value: mockDrawerCubit,
),
],
child: MaterialApp(home: AuthenticationScreen()),
));
await tester.pumpAndSettle();
var cardKey = find.byType(GlobalKey);
expect(cardKey, findsOneWidget);
//expect(find.byKey(key), findsOneWidget);
});
});
}
part of 'authentication_cubit.dart';
abstract class AuthenticationState extends Equatable {
const AuthenticationState();
@override
List<Object?> get props => [];
}
class AuthenticationInitial extends AuthenticationState {}
class AuthenticationAuthenticating extends AuthenticationState {}
class AuthenticationAuthenticated extends AuthenticationState {
final oauth2.Credentials credentials;
AuthenticationAuthenticated({required this.credentials});
@override
List<Object?> get props => [credentials];
}
class AuthenticationFailed extends AuthenticationState {}
class AuthenticationUnauthenticated extends AuthenticationState {}
class AuthenticationSigningUp extends AuthenticationState {}
class AuthenticationSigningUpCompleted extends AuthenticationState {}
class AuthenticationSignUpFailed extends AuthenticationState {}
import 'package:beamer/beamer.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:mobility_one/blocs/authentication_cubit/authentication_cubit.dart';
import 'package:mobility_one/ui/widgets/confirm_button.dart';
import 'package:mobility_one/ui/widgets/my_circular_progress_indicator.dart';
import 'package:mobility_one/ui/widgets/my_text_form_field.dart';
import 'package:mobility_one/util/app_routes.dart';
import 'package:mobility_one/util/my_colors.dart';
import 'package:mobility_one/util/my_fields_validations.dart';
import 'package:mobility_one/util/my_images.dart';
import 'package:mobility_one/util/my_localization.dart';
import 'package:mobility_one/util/my_text_styles.dart';
class LoginScreen extends StatefulWidget {
final Function onSignUpClick;
const LoginScreen({required this.onSignUpClick});
@override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
final _formKey = GlobalKey<FormState>();
bool rememberLogin = false;
@override
Widget build(BuildContext context) {
final screenSize = MediaQuery.of(context).size;
return BlocListener<AuthenticationCubit, AuthenticationState>(
listener: (context, state) {
if (state is AuthenticationAuthenticated) {
Beamer.of(context).beamToNamed(AppRoutes.home);
} else {
Beamer.of(context).beamToNamed(AppRoutes.root);
}
if (state is AuthenticationFailed) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(MyLocalization.of(context)!.wrongCredentials)));
}
},
child: BlocBuilder<AuthenticationCubit, AuthenticationState>(
builder: (context, state) {
return Scaffold(
backgroundColor: MyColors.backgroundColor,
body: Center(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [_buildLoginForm(state)],
),
),
),
);
},
),
);
}
Widget _buildLoginForm(AuthenticationState state) {
return Form(
key: _formKey,
child: Container(
height: 775,
width: 552,
child: Card(
color: MyColors.backgroundCardColor,
elevation: 10,
child: state is AuthenticationAuthenticating
? MyCircularProgressIndicator()
: Padding(
padding: const EdgeInsets.all(50),
child: Column(
children: [
SvgPicture.asset(
MyImages.mobilityOneLogo,
width: 252,
),
Text(
MyLocalization.of(context)!.loginWelcomeMessage,
style: TextStyle(
color: Colors.white,
fontSize: 30,
fontFamily: 'Averta',
fontWeight: FontWeight.bold),
),
SizedBox(
height: 24,
),
Text(
MyLocalization.of(context)!.loginInstructionMessage,
style: TextStyle(
color: Colors.white.withOpacity(.6),
fontSize: 12,
fontFamily: 'Averta'),
),
SizedBox(
height: 20,
),
MyTextFormField(
controller: _emailController,
label: MyLocalization.of(context)!.email,
fieldValidator: MyFieldValidations.validateEmail,
expanded: true,
),
SizedBox(
height: 16,
),
MyTextFormField(
controller: _passwordController,
label: MyLocalization.of(context)!.password,
isPasswordField: true,
fieldValidator: MyFieldValidations.validatePassword,
expanded: true,
),
SizedBox(
height: 40,
),
ConfirmButton(
onPressed: () {
var error = MyFieldValidations.validateEmail(
context, _emailController.value.text);
_formKey.currentState!.validate();
if (error == null) {
// context.read<AuthenticationCubit>().redirectToLoginPage();
context.read<AuthenticationCubit>().makeLogin(
email: _emailController.value.text,
password: _passwordController.value.text);
}
},
title: MyLocalization.of(context)!.login,
expanded: true,
height: 60,
),
SizedBox(
height: 20,
),
Row(
children: [
..._buildRememberLoginButton(),
Spacer(),
_buildResetHereButton()
],
),
SizedBox(
height: 40,
),
_buildCreateAnAccountButton(),
SizedBox(
height: 40,
),
_buildAzureAdLoginButton()
],
),
),
),
),
);
}
List<Widget> _buildRememberLoginButton() {
return [
Checkbox(
value: rememberLogin,
onChanged: (selected) {
setState(
() {
rememberLogin = selected!;
},
);
},
),
TextButton(
onPressed: () {
setState(() {
rememberLogin = !rememberLogin;
});
},
child: Text(
MyLocalization.of(context)!.rememberLoginText,
style: MyTextStyles.dataTableText
.copyWith(color: MyColors.cardTextColor),
),
)
];
}
Widget _buildResetHereButton() {
return MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
onTap: () {},
child: Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
MyLocalization.of(context)!.resetHereText.toUpperCase(),
style: MyTextStyles.dataTableViewAll.copyWith(fontSize: 14),
),
const SizedBox(
height: 3,
),
Container(
height: 1,
width: 84,
color: MyColors.mobilityOneLightGreenColor,
)
],
),
),
),
);
}
Widget _buildCreateAnAccountButton() {
return MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
onTap: () {
widget.onSignUpClick();
},
child: Container(
width: double.infinity,
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Color(0xFF585876),
borderRadius: BorderRadius.all(
Radius.circular(20),
),
),
child: Center(
child: Text(
MyLocalization.of(context)!.createAnAccountText.toUpperCase(),
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold),
),
),
),
),
);
}
Widget _buildAzureAdLoginButton() {
return MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
onTap: () {},
child: Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'AZURE AD LOGIN',
style: MyTextStyles.dataTableViewAll.copyWith(fontSize: 14),
),
const SizedBox(
height: 3,
),
Container(
height: 1,
width: 110,
color: MyColors.mobilityOneLightGreenColor,
)
],
),
),
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment