How do I initialize Firebase App in Flutter widget testing - flutter

So I am new in flutter and trying to perform widget testing on my app, but I am keep getting this weird error.
below is my test file
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:folk_team_app/provider/auth_provider.dart';
import 'package:folk_team_app/screens/phone_login.dart';
import 'package:provider/provider.dart';
void main() async {
TestWidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
Widget loginScreen = ChangeNotifierProvider<AuthProvider>(
create: (context) => AuthProvider(),
builder: (context, child) {
return MaterialApp(
home: PhoneLogineScreen(),
);
});
testWidgets('Phone Authetication Page', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(loginScreen);
await tester.pump(const Duration(seconds: 10));
final titleText = find.text('Screen Title');
// Verify that our counter starts at 0.
expect(titleTextt, findsOneWidget);
});
}
here is the error :

You can't directly test Firebase because it requires platform configurations in order to initialize it properly.
You need to mock Firebase in the test environment using mockito.
You may find this comment and tutorial video helpful.

Related

Google OAuth 2.0 failing with Error 400: invalid_request for some client_id, Can't Sign in because 'App' sent an invalid request

I have an Flutter app that uses googleapis_auth 1.3.1 and googleapis 9.2.0 .
What I have done:
enabled the Google Calender API
connect Flutter Project to Firebase
and set up with basic template.
But I am getting the following error:
Here is my code:
`
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:googleapis/calendar/v3.dart' as cal;
import 'package:url_launcher/url_launcher.dart';
import 'gCalender/calendar_client.dart';
import 'secert.dart';
import 'package:googleapis_auth/auth_io.dart';
void main() async {
//firebase initialize
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
//google apis init
var clientID = ClientId(Secret.getId(),"");
var scopes = [cal.CalendarApi.calendarEventsScope];
await clientViaUserConsent(clientID, scopes, prompt).then((AuthClient client) async {
CalendarClient.calendar = cal.CalendarApi(client);
});
runApp(const MyApp());
}
void prompt(String url) async {
if (!await launchUrl(Uri.parse(url))) {
throw 'Could not launch $url';
}
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Social Login',
theme: theme(),
debugShowCheckedModeBanner: false,
initialRoute: SplashScreen.routeName,
// home: const SplashScreen(),
routes: routes,
);
}
}
`
I explored the internet but couldn't find any solution.
if you use emulator, try the app in real phone, cuz some times firebase services not working well in the virtual phones

Flutter Unit Class with Initializer

I'm trying to write the unit test for this class, but I'm having problems about the initializer... When I instantiate the class in the test file, the caller throws an error that " Null check operator used on a null value". I know that's because the UserProvider is not initialized on the test folders. But how can I mock this??
class ContactController extends ChangeNotifier {
BuildContext context;
ContactController(this.context) {
initializeData();
}
late Contact contact;
initializeData() {
var userProvider = context.read<UserProvider>();
var currentContact = userProvider?.contact;
if (currentContact != null) {
newContact = currentContact;
}
notifyListeners();
}
}
The code below should do the trick. The thing is that you need to provide a mocked UserProvider into the context. To do so, just use MultiProvider in the tests to inject the mocked one.
Note the use of #GenerateMocks([UserProvider]). This comes from mockito and it annotates the source to generate the MockUserProvider class. And to generate the *.mocks.dart just run flutter pub run build_runner build.
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';
import 'package:so72756235_test_provider/contact_controller.dart';
import 'contact_controller_test.mocks.dart';
#GenerateMocks([UserProvider])
void main() {
testWidgets('ContactController test', (WidgetTester tester) async {
final mockUserProvider = MockUserProvider();
when(mockUserProvider.contact).thenReturn(const Contact(name: 'Test'));
await tester.pumpWidget(
MultiProvider(
providers: [
Provider<UserProvider>(create: (_) => mockUserProvider),
ChangeNotifierProvider(
create: (context) => ContactController(context)),
],
child: Consumer<ContactController>(
builder: (context, value, child) =>
Text(value.newContact.name, textDirection: TextDirection.ltr)),
),
);
expect(find.text('Test'), findsOneWidget);
});
}

The name 'MyApp' isn't a class. Try correcting the name to match an existing class. flutter

I don't know what is the problem is / how to fix this while I tring to code it shows this error on the test folder widget_test.dart
x
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(const MyApp());
On the pumpWidget method change "const MyApp()" to the same name of your first Widget class. The class you instance on the runApp function inside the main function on the main.dart file.
For example, if your main.dart content is:
void main() async {
runApp(MyGreatApp());
}
class MyGreatApp extends StatelessWidget {
const MyGreatApp();
#override
Widget build(BuildContext context) {
return MaterialApp(
//rest of code ...
);
}
}
Put in your widget_test.dart file:
await tester.pumpWidget(const MyGreatApp()); //<-
You should add
await tester.pumpWidget(const MaterialApp());
at widget_test.dart file, if your main.dart begins like this:
void main() runApp(
MaterialApp(
home: Scaffold(
Try to remove the word "const"
I think because you did not import a file main.dart into widget_test.dart
You should insert "import 'package: yourapp folder/main.dart;'" It should be working.
try importing main.dart
import 'package:appName/main.dart';
if it's work, try the app.dart
import 'package:appName/app.dart';

How to export and use global variable

I am creating a Flutter App and I need a global http client with some setup.
Flutter: 1.5.4
Dart: 2.3.2
// utils/http.dart
import 'dart:io';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio/dio.dart';
import 'package:path_provider/path_provider.dart';
Dio http = Dio();
void main() async {
// Save cookies to cookie jar.
Directory appDir = await getApplicationDocumentsDirectory();
http.interceptors.add(CookieManager(PersistCookieJar(dir: appDir.path)));
}
// main.dart
import 'package:flutter/material.dart';
import 'app.dart';
import 'utils/http.dart';
void main() {
print(http.interceptors); // returns []
runApp(App());
}
I expect that main function in http should be automatically executed.
A common solution to this is to wrap it in a Widget and place that widget in the Widget Tree. High up in the tree, so that it's sort of global. It's called "lifing state up".
The out of box solution of Flutter for such things is InheritedWidget. It's worth looking at and understand because most 3rd-party solutions rely on it.
To make life a tad easier, however, I use pacakge:provider. Code would look like so:
Creating
Provider<Dio>(
builder: (_) => Dio(),
child: MaterialApp(/*...*/)
);
Consuming
later in the widget tree:
Consumer<Dio>(
builder: (ctx, dio, _) {
// widget builder method
debugPrint('Dio instance: ${dio}');
return Container();
}
);

How to create a scheduled service in Flutter

How can you create a scheduled service in Flutter, which will be triggered at a specific time every day, and it will run some code? It needs to work for both Android and IOS and even if the app is terminated.
You could make use of the alarm manager package.
A simple implementation of the same would look like below.
import 'dart:async';
import 'package:android_alarm_manager/android_alarm_manager.dart';
import 'package:flutter/widgets.dart';
void doStuff() {
print("do stuff every minute");
}
Future<void> main() async {
final int periodicID = 0;
// Start the AlarmManager service.
await AndroidAlarmManager.initialize();
runApp(const Center(
child:
Text('See device log for output', textDirection: TextDirection.ltr)));
await AndroidAlarmManager.periodic(
const Duration(minutes: 1), periodicID, doStuff,
wakeup: true);
}