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?
Related
I'm writting my very first widget tests in dart. I have to check if clicking on a button bring us to the next screen.
What am I doing wrong here?
testWidgets('Tapping staring the meeting button leads to conference screen', (widgetTester) async {
await widgetTester.pumpWidget(const MaterialApp(home: WelcomeScreen()));
await widgetTester.enterText(find.byKey(const Key('nameInput')), 'User');
await widgetTester.enterText(find.byKey(const Key('titleInput')), 'Title');
await widgetTester.enterText(find.byKey(const Key('passwordInput')), 'Password');
expect(find.byType(CallToActionButton), findsOneWidget);
await widgetTester.tap(find.byType(CallToActionButton));
await widgetTester.pump();
expect(find.byType(ConferenceScreen), findsOneWidget);
});
I'm using google flutter integration driver to automate the flutter mobile app.
I want to write multiple widgetTests in a single main_test.dart file.
First test is running successfully, but when second test starts i see Test starting...(attached screenshot below) screen in emulator, but actually not moving forward to launch the app screen.
And finally, getting below error saying that Bad state: No element as screen is not loaded.!
Failure Details:
Failure in method: check value increments
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞═════════════════
The following StateError was thrown running a test:
Bad state: No element
When the exception was thrown, this was the stack:
#0 Iterable.single (dart:core/iterable.dart:654:25)
#1 WidgetController.element (package:flutter_test/src/controller.dart:114:30)
#2 WidgetController.ensureVisible (package:flutter_test/src/controller.dart:1210:73)
#3 main.<anonymous closure>.<anonymous closure> (file:///Users/tummalacharlajagadeesh/Desktop/Sparrow/synapse-cards-mobile/synapse-cards-mobile/integration_test/sanity_test.dart:87:20)
<asynchronous suspension>
Here is my integration test file main_test.dart:
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:get_it/get_it.dart';
import 'package:integration_test/integration_test.dart';
import 'package:sparrowmobile/flavor/uat.dart' as app;
void main() {
final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
group('sanity test suite', () {
//runs before each test
setUp(() async {
app.main();
});
//runs after each test
tearDown(() async {
final getIt = GetIt.instance;
await getIt.reset();
});
testWidgets('sample test', (tester) async {
await tester.pumpAndSettle(const Duration(seconds: 5));
// ensure title is visible
await tester.ensureVisible(find.byKey(const ValueKey('startButton')));
await tester.tap(find.byKey(const ValueKey('startButton')));
await tester.pumpAndSettle();
expect(find.text('Home Screen'), findsOneWidget);
expect(find.text('Transactions'), findsOneWidget);
});
testWidgets('check value increments', (tester) async {
await tester.pumpAndSettle(const Duration(seconds: 10));
//ensure title is visible
await tester.ensureVisible(find.byKey(const ValueKey('startButton')));
await tester.tap(find.byKey(const ValueKey('startButton')));
await tester.pumpAndSettle();
});
});
}
Can anybody help here me to run multiple widgetTests in a single file?
To start, I did review this but to no avail.
How to access Flutter environment variables from tests?
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:main.dart' as app;
import 'package:mockito/annotations.dart';
import 'package:firebase_auth/firebase_auth.dart' as firebaseauth;
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'basic_app_test.mocks.dart';
#GenerateMocks([firebaseauth.FirebaseAuth])
void main() async {
TestWidgetsFlutterBinding.ensureInitialized();
await DotEnv().load(fileName: ".env");
group('Login Page Tests', () {
testWidgets('Empty Login Box', (WidgetTester tester) async {
app.main();
await tester.pumpAndSettle(Duration(seconds: 3));
expect(find.byKey(Key('loginButton')), findsOneWidget);
final Finder loginButton = find.byKey(Key('loginButton'));
await tester.tap(loginButton);
await tester.pumpAndSettle();
expect(
find.text(
'Something went wrong. Please check your email and password and try again.'),
findsOneWidget);
});
testWidgets('Email Login - Proper Credentials',
(WidgetTester tester) async {
app.main();
// Wait for app to reach the login page
await tester.pumpAndSettle(Duration(seconds: 3));
final Finder emailBox = find.byKey(Key('emailBox'));
final Finder passwordBox = find.byKey(Key('passwordBox'));
final Finder loginButton = find.byKey(Key('loginButton'));
final Finder welcomeHeader = find.byKey(Key('welcomeHeader'));
var testPassword = DotEnv().env['TEST_PASSWORD'];
await tester.enterText(passwordBox, testPassword);
expect(find.byKey(Key('loginButton')), findsOneWidget);
await tester.tap(loginButton);
await tester.pumpAndSettle(Duration(seconds: 5));
// SHOULD BE EXPECTING A WIDGET IN THE NEXT WINDOW
expect(welcomeHeader, findsOneWidget);
});
});
}
I have a group of tests. The first one runs just fine. The second one runs into an error when the testPassword variable is created.
Here is the error:
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following NotInitializedError was thrown running a test:
Instance of 'NotInitializedError'
When the exception was thrown, this was the stack:
#0 DotEnv.env (package:flutter_dotenv/src/dotenv.dart:42:7)
#1 main.<anonymous closure>.<anonymous closure> (file:///D:/WEBDEV/EndevStudios/MedicalApp/gshDevWork/medical-app-frontend/integration_test/basic_app_test.dart:52:31)
<asynchronous suspension>
<asynchronous suspension>
(elided one frame from package:stack_trace)
The test description was:
Email Login - Proper Credentials
The .env file is located at the root.
My pubspec.yaml file:
dependencies:
flutter_dotenv: ^5.0.2
flutter:
#Integration Testing
- .env
What I've tried:
Most solutions involve some variation of TestWidgetsFlutterBinding.ensureInitialized(); or IntegrationTestWidgetsFlutterBinding.ensureInitialized(); as well as await DotEnv().load(fileName: ".env"); and await DotEnv().load();.
Thank you in advance to anyone who can help.
You need to change from
await DotEnv().load(fileName: ".env");
to:
await dotenv.load(fileName: ".env");
using the latest library.
You need to add in youre tests this:
// Loading from a static string.
dotenv.testLoad(fileInput: '''FOO=foo
BAR=bar
''');
or
// Loading from a file synchronously.
dotenv.testLoad(fileInput: File('test/.env').readAsStringSync());
Hi I'm trying to verify mockObserver to check push to other screen. But when didPush(any,any), it's show err from type any.
I'm using mockito: ^5.0.13
(tester) async {
await tester.pumpWidget(widget);
await tester.tap(find.widgetWithText(TextButton, 'Join with us'));
await tester.pumpAndSettle();
verify(mockObserver.didPush(any, any));
});
I would like to test that when I am tapping a button, the user is routed to the next page. This works in the UI. I introduced the test but I get the following error:
The following TestFailure object was thrown running a test: Expected: exactly one matching node in the widget tree Actual: _WidgetTypeFinder:<zero widgets with type "MyNextView" (ignoring offstage widgets)> Which: means none were found but one was expected
What am I doing wrong?
testWidgets('Button tap routes to next page', (WidgetTester tester) async {
final button = createButton();
await tester.pumpWidget(button);
await tester.tap(find.byWidget(button));
expect(find.byType(MyNextView), findsOneWidget);
});
After >
await tester.tap(find.byWidget(button));
Put this line >
await tester.pumpAndSettle(); // Wait for screen to update
testWidgets('Button tap routes to next page', (WidgetTester tester) async {
final button = createButton();
await tester.pumpWidget(button);
await tester.tap(find.byWidget(button));
await tester.pumpAndSettle(); // Wait for screen to update
expect(find.byType(MyNextView), findsOneWidget);
});