Sample integration test with Flutter new integration_test? - flutter

Sample integration test with Flutter new integration_test ?

First add a dependency in pubspec.yaml under dev
dev_dependencies:
flutter_test:
sdk: flutter
integration_test:
sdk: flutter
test: ^1.9.4
Your package should have a structure that looks like this:
in test/test_driver/integration_test.dart
import'package:integration_test/integration_test_driver.dart';
Future<void> main() => integrationDriver();
4.In integration_test/foo_test.dart
example
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
testWidgets("Sign in test example", (WidgetTester tester) async {
final Finder signInEmailField = find.byKey(Key('signInEmailField'));
final Finder signInPasswordField = find.byKey(Key('signInPasswordField'));
final Finder signInSaveButton = find.byKey(Key('signInSaveButton'));
await tester.pumpWidget(MyApp());
await tester.pumpAndSettle();
await tester.tap(find.byKey(Key('signInEmailField')));
await tester.enterText(signInEmailField, "paras#gmail.com");
await tester.tap(signInPasswordField);
await tester.enterText(signInPasswordField, "123456");
await tester.tap(signInSaveButton);
print("button tapped");
await tester.pumpAndSettle(Duration(seconds: 1));
expect(
find.byWidgetPredicate((widget) =>
widget is AppBar &&
widget.title is Text &&
(widget.title as Text).data.startsWith("ToDoApp")),
findsOneWidget);
await tester.pumpAndSettle(Duration(seconds: 1));
});
}
Add key like we set in flutter_driver
appBar: AppBar(
title: Text(
'ToDoApp',
key: Key("toDoKey"),
),
backgroundColor: Colors.brown[400],
),
Foo last run the command in your terminal
flutter drive
--driver=test_driver/integration_test.dart
--target=integration_test/foo_test.dart
Thanks.. happy Fluttering

Related

Flutter Firebase background push in terminated state

Flutter Firebase background push in terminated state has not been handled.
My env and deps :
Android 11, Nokia G21
environment:
sdk: ">=2.14.0 <3.0.0"
flutter: "^3.3.6"
firebase_messaging: ^14.0.3
firebase_core: ^2.1.1
firebase_crashlytics: ^3.0.3
main.dart:
late AndroidNotificationChannel channel;
late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
bool isFlutterLocalNotificationsInitialized = false;
#pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
await setupFlutterNotifications();
showFlutterNotification(message);
Logger().i("Handling a background message: ${message.messageId}");
}
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await SharedPreferences.getInstance();
await FlutterConfig.loadEnvVariables();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
await setupFlutterNotifications();
FirebaseMessaging.onMessage.listen((event) {
Logger().e('$CLASS_TAG onMessage ${event.data.toString()}');
showFlutterNotification(event);
});
runZonedGuarded(
() => runApp(const ErkcRequestApp()),
(Object object, StackTrace stackTrace) => dev.log(
object.toString(),
error: object,
stackTrace: stackTrace,
),
);
}
Used this example, also tried this, but still get error.
Error from Logcat (app in terminated state):

Stubbing TargetPlatform not working in flutter test

I have these 2 tests:
void main() {
group('...', () {
testWidgets('Should ... when the OS is macOS', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(
platform: TargetPlatform.macOS,
),
));
...
assert(Theme.of(context).platform...); // platform is android!!
});
testWidgets('Should ... when the OS is windows', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(
platform: TargetPlatform.windows,
),
));
...
assert(Theme.of(context).platform...); // platform is android!!
});
});
}
I overrided the platform in the theme of MaterialApp explicitly as per the docs:
In a test environment, the platform returned is TargetPlatform.android
regardless of the host platform. (Android was chosen because the tests
were originally written assuming Android-like behavior, and we added
platform adaptations for other platforms later). Tests can check
behavior for other platforms by setting the platform of the Theme
explicitly to another TargetPlatform value, or by setting
debugDefaultTargetPlatformOverride.
I also tried setting it via debugDefaultTargetPlatformOverride, like this:
void main() {
group('...', () {
testWidgets('Should ... when the OS is macOS', (WidgetTester tester) async {
// set the OS to macOS
debugDefaultTargetPlatformOverride = TargetPlatform.macOS;
await tester.pumpWidget(const MaterialApp());
await tester.pumpAndSettle();
BuildContext context = tester.element(find.byType(MaterialApp));
assert(Theme.of(context).platform...); // Works, platform is macOS
// reset the default target platform
debugDefaultTargetPlatformOverride = null;
});
testWidgets('Should ... when the OS is windows', (WidgetTester tester) async {
// set the OS to windows
debugDefaultTargetPlatformOverride = TargetPlatform.windows;
await tester.pumpWidget(const MaterialApp());
await tester.pumpAndSettle();
BuildContext context = tester.element(find.byType(MaterialApp));
assert(Theme.of(context).platform...); //Platform is still macOS!!
// reset the default target platform
debugDefaultTargetPlatformOverride = null;
});
});
}
But in the code above the first test only passes but the second fails bcz the platform resetting is not working and the platform is still macOS (due to the first test).
What am I doing wrong?

Firebase packages - Error: Couldn't resolve the package | Flutter

I divide the hms and gms services in my project, and I also created a local packages that is a collection of my own helper classes for push notification service
The dependencies of local package for gms devices include firebase_core and firebase_messaging. Dart analytics doesn't shows the problem "Undefinded" which appear when dependencies are not loaded by pub get or doesn`t exist in pubspec.yaml. But when i started debug build, it have exceptions
pubspec.yaml:
name: push_service
description: A new Flutter package project.
version: 0.0.1
homepage:
publish_to: none
environment:
sdk: ">=2.17.1 <3.0.0"
flutter: ">=1.17.0"
dependencies:
flutter:
sdk: flutter
push_service_interface:
path: ../../interface/push_service_interface
firebase_analytics: ^9.1.4
firebase_core: ^1.12.0
firebase_messaging: ^11.2.6
flutter_local_notifications: ^9.2.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
flutter:
The part of my code:
class GmsService implements IService {
#override
Future<void> init() async {
await Firebase.initializeApp();
if (Platform.isIOS) {
await Firebase.initializeApp(options: _firebaseOptions);
} else {
await Firebase.initializeApp();
}
FirebaseMessaging fcm = FirebaseMessaging.instance;
///Request permissions for Ios
await fcm.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
}
#override
Future<String?> getToken() async {
return await FirebaseMessaging.instance.getToken();
}
#override
Future<void> backgroundHandler() async {
FirebaseMessaging.onBackgroundMessage((message) async {
if (Platform.isIOS) {
await Firebase.initializeApp(options: _firebaseOptions);
} else {
await Firebase.initializeApp();
}
log("[Firebase] Handling a background message: ${message.messageId}");
});
}
#override
Future<void> onTapWhenAppClosed({required Function() onTap}) async {
FirebaseMessaging.instance.getInitialMessage().then((message) {
if (message != null) {
onTap;
}
});
}
#override
Future<void> onTapWhenAppFon({required Function() onTap}) async {
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
onTap;
});
}
#override
Future<void> listener<T>({T? plugin}) async {
plugin as FlutterLocalNotificationsPlugin;
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
RemoteNotification? notification = message.notification;
// AndroidNotification? android = message.notification?.android;
if (notification != null) {
plugin.show(
notification.hashCode,
notification.title,
notification.body,
const NotificationDetails(
iOS: IOSNotificationDetails(),
android: AndroidNotificationDetails(
'default_notification_channel',
'Notifications',
channelDescription: 'This channel is used for notifications.',
icon: '#drawable/res_notification_logo',
color: Colors.orange,
),
),
);
}
});
}
}
const FirebaseOptions _firebaseOptions = FirebaseOptions(
apiKey: "AIzaSyDlDrc6NbcGVR4rr8DTfV82dAk_vD3Jpi0",
appId: "1:150088765423:ios:23edb87f9ecb47a756301a",
messagingSenderId: "150088765423",
projectId: "android-foxfit-push",
);
And the build output:
I`m really tired to find the solution of this problem, anybody help me pls

Flutter Integration Screenshot not working for Android

I am trying to capture screenshots using integration_test but the
await binding.takeScreenshot('${platform}-1');
Hangs for Android with a message
VMServiceFlutterDriver: request_data message is taking a long time to complete...
The app is the Flutter default app with
import 'package:flutter_driver/driver_extension.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'dart:io';
import 'package:flutter_stam/main.dart' as app;
void main() {
final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding();
group('Screenshot', () {
testWidgets('Screenshot-1', (WidgetTester tester) async {
String platform;
if (Platform.isAndroid) {
platform = 'android';
} else if (Platform.isIOS) {
platform = 'ios';
} else {
platform = Platform.operatingSystem;
}
app.main();
await tester.pumpAndSettle();
// Verify the counter starts at 0.
expect(find.text('0'), findsOneWidget);
// Finds the floating action button to tap on.
final Finder fab = find.byTooltip('Increment');
// Emulate a tap on the floating action button.
await tester.tap(fab);
// Trigger a frame.
await tester.pumpAndSettle();
await binding.convertFlutterSurfaceToImage();
await binding.takeScreenshot('${platform}-screenshot-1');
// Verify the counter increments by 1.
expect(find.text('1'), findsOneWidget);
});
});
}
script
#!/bin/zsh
flutter drive \
--driver=integration_test/driver.dart \
--target=integration_test/app_test.dart \
-d "iPhone 13 Pro Max"
flutter drive \
--driver=integration_test/driver.dart \
--target=integration_test/app_test.dart \
-d "emulator-5554"
Driver
import 'dart:io';
import 'package:integration_test/integration_test_driver_extended.dart';
Future<void> main() async {
try {
await integrationDriver(
onScreenshot: (String screenshotName, List<int> screenshotBytes) async {
final File image = await File('screenshots/$screenshotName.png')
.create(recursive: true);
image.writeAsBytesSync(screenshotBytes);
return true;
},
);
} catch (e) {
print('An error occurred: $e');
}
}
For iOS, I also had an issue but I managed to solve it
I was getting an error
The following MissingPluginException was thrown running a test:
MissingPluginException(No implementation found for method
captureScreenshot on channel plugins.flutter.io/integration_test)
I changed IntegrationTestPlugin.m
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
[[IntegrationTestPlugin instance] setupChannels:registrar.messenger];
}
Adding an additional tester.pumpAndSettle(); after convertFlutterSurfaceToImage fixed the problem
await tester.pumpAndSettle();
await binding.convertFlutterSurfaceToImage();
await tester.pumpAndSettle();

Error with navigation testing using mockito

I'm trying to write a test to debug my app. I want to try out my login page, I have two textfields and one button. When the textfields are filled, then If i tap the button I have a Dio request to Log In and navigate to HomePage if its ok. I have the following test:
testWidgets('Login ok',
(WidgetTester tester) async {
LoginPage loginPage = new LoginPage();
final mockObserver = MockNavigatorObserver();
await tester.pumpWidget(
MaterialApp(
home: loginPage,
navigatorObservers: [mockObserver],
),
);
var app = new MediaQuery(
data: new MediaQueryData(), child: new MaterialApp(home: loginPage));
await tester.pumpWidget(app);
Finder username = find.byKey(new Key('emailField'));
Finder password = find.byKey(new Key('passwordField'));
await tester.enterText(username, "user");
await tester.enterText(password, "pass");
await tester.pump();
Finder formWidgetFinder = find.byType(Form);
Form formWidget = tester.widget(formWidgetFinder) as Form;
GlobalKey<FormState> formKey = formWidget.key as GlobalKey<FormState>;
expect(formKey.currentState.validate(), isTrue);
Finder loginButon = find.byKey(new Key('loginButon'));
await tester.tap(loginButon);
await tester.pumpAndSettle();
verify(mockObserver.didPush(any, any));
expect(find.byType(HomePage), findsOneWidget);
});
But I think that
verify(mockObserver.didPush(any, any));
doesn't check if the app go to new page, because the Dio request fail due to the following error:
DioError [DioErrorType.DEFAULT]: type '_StreamHandlerTransformer<List<int>, Uint8List>' is not a subtype of type 'StreamTransformer<Uint8List, Uint8List>'#0 _MockHttpResponse.transform (package:flutter_test/src/binding.dart:2012:35)
#1 DefaultHttpClientAdapter.fetch (package:dio/src/adapter.dart:165:46)
<asynchronous suspension>
#2 Dio._makeRequest (package:dio/src/dio.dart:739:46)
<asynchronous suspension>
...
I have tried many versions of Dio, 2.0.1, 2.0.9, 2.0.10, 2.0.13 but nothing works. If I run my app on simuator, the Dio request is Ok.
How can I solve this or there is another way to test navigation on Flutter?