Closed AngDrew closed 7 months ago
Hi! Thanks for opening your first issue here! :smile:
in the screen shot, you can see there is too many "start date" while there is only one
Hmm, IIRC some widgets with weird behaviors moving around the tree may make the finder confused. Could you please make a minimal reproducible sample, e.g. an empty screen with only one dialog with that text? Then it would be easy to see what is wrong.
Btw, try the "expand" button and see whether it tells you more, e.g. the full ancestors of all the widgets found
indeed i have many animation on this app, maybe this cause some issue to the finder. anyway ill try empty screen with dialog opened using onInit() and "expand" the same error log ill try to reproduce the test first
tried to print using find.text('Contract').allCandidates.length
and it prints 869 widgets wihle dialog are open
i was wondering, is there any way to scroll while have showModalBottomSheet
open?
the best way to select the widget is using find.byWidgetPredicate(...) we can query any widget, and certain attribute as we wanted but one thing i still don't understand.. how to scroll if there's multiple scrollable in the screen π€ how to scroll only modal bottom sheet, how to scroll from the certain position of screen (using offside or coordinate maybe?)
I found out that if we want to specifically scroll within a scrollable widget, we can use t.tester.scrollUntilVisible(...)
and specify the scrollable parameter with a Finder.
Now, I've encountered another issue. I have a splash screen in my app that redirects users to the dashboard if they have an access token, otherwise they are redirected to the login screen. When I run the app by executing the main code (not the main test code) and receive a token, somehow the test no longer works for me. I have to uninstall the app and restart the test from scratch without a token.
Is this a bug or did I miss something? I'm relatively new to integration testing in Flutter. In the past, I've only implemented it in small projects and I'm still trying to fully understand it.
The test won't start and gets stuck if I skip the splash screen. log:
βββ‘ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK βββββββββββββββββββββββββββββββββββββββββββββββββββββ
The following assertion was thrown running a test:
pumpWithRunAsyncUntil timed out (startTime=WallAndFakeClock(wallClock: 2024-03-13 15:40:10.877824,
fakeClock: 2024-03-13 15:40:10.877813), endTime=WallAndFakeClock(wallClock: 2024-03-13
15:41:10.877824, fakeClock: 2024-03-13 15:41:10.877813), now=WallAndFakeClock(wallClock: 2024-03-13
15:41:10.963041, fakeClock: 2024-03-13 15:41:10.963029), pumpCount=434)
When the exception was thrown, this was the stack:
#0 ExtWidgetTesterPump.pumpWithRunAsyncUntil.<anonymous closure> (package:convenient_test_dev/src/functions/widget_tester.dart:132:11)
<asynchronous suspension>
#1 TestAsyncUtils.guard.<anonymous closure> (package:flutter_test/src/test_async_utils.dart:117:7)
<asynchronous suspension>
#2 ExtWidgetTesterPump.pumpAndSettleWithRunAsync (package:convenient_test_dev/src/functions/widget_tester.dart:92:7)
<asynchronous suspension>
#3 tTestWidgets.<anonymous closure>.<anonymous closure> (package:convenient_test_dev/src/functions/test_widgets.dart:37:16)
<asynchronous suspension>
#4 ConvenientTest.withActiveInstance (package:convenient_test_dev/src/functions/instance.dart:29:7)
<asynchronous suspension>
#5 tTestWidgets.<anonymous closure> (package:convenient_test_dev/src/functions/test_widgets.dart:26:23)
<asynchronous suspension>
#6 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:168:15)
<asynchronous suspension>
#7 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:1013:5)
<asynchronous suspension>
#8 TestWidgetsFlutterBinding._createTestCompletionHandler.<anonymous closure> (package:flutter_test/src/binding.dart:804:12)
<asynchronous suspension>
The test description was:
login, schedule, rate, booking
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
package:convenient_test_dev/src/functions/widget_tester.dart 132:11 ExtWidgetTesterPump.pumpWithRunAsyncUntil.<fn>
===== asynchronous gap ===========================
package:flutter_test/src/test_async_utils.dart 117:7 TestAsyncUtils.guard.<fn>
===== asynchronous gap ===========================
package:convenient_test_dev/src/functions/widget_tester.dart 92:7 ExtWidgetTesterPump.pumpAndSettleWithRunAsync
===== asynchronous gap ===========================
package:convenient_test_dev/src/functions/test_widgets.dart 37:16 tTestWidgets.<fn>.<fn>
===== asynchronous gap ===========================
package:convenient_test_dev/src/functions/instance.dart 29:7 ConvenientTest.withActiveInstance
===== asynchronous gap ===========================
package:convenient_test_dev/src/functions/test_widgets.dart 26:23 tTestWidgets.<fn>
===== asynchronous gap ===========================
package:flutter_test/src/widget_tester.dart 168:15 testWidgets.<fn>.<fn>
===== asynchronous gap ===========================
package:flutter_test/src/binding.dart 1013:5 TestWidgetsFlutterBinding._runTestBody
===== asynchronous gap ===========================
package:flutter_test/src/binding.dart 804:12 TestWidgetsFlutterBinding._createTestCompletionHandler.<fn>
So if I understand correctly, your question now is about the app token thing?
I personally do something like: during test setup (e.g. setUpAll / setUp), remove that token programmatically.
turns out the token was not the issue here..
ExtWidgetTesterPump.pumpWithRunAsyncUntil.
I got this exception while trying to run the test. It installs the app but cannot start the test somehow. It works perfectly fine if I uninstall the app using adb
command and run the test as if my app is freshly installed, with no setup on my test. But if I make another test group, it restarts the app (the token already saved using secure storage), the settings have been saved to shared preferences. Then the test will pump loop and eventually timeout.
I've changed my binding.dart, but the issue is not solved.
here's my test code:
import 'package:convenient_test/convenient_test.dart';
import 'package:convenient_test_dev/convenient_test_dev.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:super_app/core/core.dart';
import 'package:super_app/flavor.dart';
import 'package:super_app/main_for_test.dart' as app;
import 'package:super_app/modules/modules.dart';
import 'booking_flow_integration_test.dart';
import 'login_flow_integration_test.dart';
import 'rate_flow_integration_test.dart';
import 'schedule_flow_integration_test.dart';
class MyConvenientTestSlot extends ConvenientTestSlot {
@override
Future<void> appMain(AppMainExecuteMode mode) async => app.main();
@override
BuildContext? getNavContext(ConvenientTest t) => navigatorKey.currentContext;
}
// --dart-define PERSISTENT_ARGUMENTS="clSs.clSp"
//
// flutter run integration_test/main_test.dart --flavor dev --host-vmservice-port 9753 --disable-service-auth-codes --dart-define CONVENIENT_TEST_MANAGER_HOST=10.0.2.2 --dart-define CONVENIENT_TEST_APP_CODE_DIR="D:/projects/flutter-project/super_app" --dart-define TEST_ENTRY_POINT="dashboardNoPin"
void main() {
String entryPoint = const String.fromEnvironment('TEST_ENTRY_POINT');
ConvenientTestWrapperWidget.convenientTestActive = true;
ConvenientTestWrapperWidget.enableGestureVisualizer = true;
convenientTestMain(MyConvenientTestSlot(), () {
group('booking flow', () {
setUp(() async {
F.appFlavor = Flavor.dev;
// const String dartDefineArg =
// String.fromEnvironment('PERSISTENT_ARGUMENTS');
// if (dartDefineArg.contains('clSp')) {
// }
// if (dartDefineArg.contains('clSs')) {
// }
SharedPreferences sp = await SharedPreferences.getInstance();
await sp.clear();
await Storage.deleteAll();
await sp.setBool(StorageKeys.firstTimeOpen, false);
await TokenStorage.writeToken('xx');
await TokenStorage.writeRefreshToken('xx');
await UserPinStorage.writePreferBiometric(false);
await UserPinStorage.writeUserPin('123456');
return null;
});
tTestWidgets(
'login, schedule, rate, booking',
(ConvenientTest t) async {
if (entryPoint == 'onboarding') {
await loginFlow(t);
}
if (entryPoint == 'dashboardNoPin') {
await t.get(find.text('Quick Tracking')).should(findsOneWidget);
await scheduleFlow(t);
await rateFlow(t);
await bookingFlow(t);
}
},
);
});
});
}
my main.dart
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
Directory dir = await getApplicationDocumentsDirectory();
// initializing isar database schema
isarBookingDraft ??= await Isar.open(
<CollectionSchema<dynamic>>[
BookingDraftSchema,
],
directory: dir.path,
name: 'booking_drafts',
);
await SystemChrome.setPreferredOrientations(
<DeviceOrientation>[DeviceOrientation.portraitUp],
);
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
FirebaseMessaging firebaseInstance = FirebaseMessaging.instance;
String? fcmToken = await firebaseInstance.getToken();
await firebaseInstance.setAutoInitEnabled(true);
print('FCMToken $fcmToken');
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
AndroidInitializationSettings initializationSettingsAndroid =
const AndroidInitializationSettings('@mipmap/ic_launcher');
DarwinInitializationSettings initializationSettingsIOS =
const DarwinInitializationSettings(
requestAlertPermission: false,
requestBadgePermission: false,
requestSoundPermission: false,
);
InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS,
);
await flutterLocalNotificationsPlugin.initialize(initializationSettings);
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
if (notification != null && android != null) {
flutterLocalNotificationsPlugin.show(
notification.hashCode,
notification.title,
notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
'super_app_notification_channel',
'Super App Notification Channel',
channelDescription: 'Super App Default General Channel',
icon: android.smallIcon,
// other properties...
),
));
}
});
runApp(const ProviderScope(child: ConvenientTestWrapperWidget(child: App())));
}
tl;dr: i cannot restart the test, it will loop infinitely and timeout
Hmm, firstly try to bisect which line causes this problem (e.g. add a ton of print
s and see). Then feel free to post the details if it is nontrivial to fix!
aight, i've found the solution. it's not the library issue, but the flutter itself.
If you would like to scroll through dialog, you should use dragUntilVisible
instead of scrollUntilVisible
reference. that said, use scrollUntilVisible
if it's scrollable and not blocked by ignore pointer or other pointer blocking widget, and use dragUntilVisible
if it's overlay (dialog, bottom sheet, pop up, etc.)
thanks a lot ^^
You are welcome and happy to see it is solved!
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new issue.
Describe the bug The test can't detect object above the screen such as Dialog, Bottom Sheet, Overlay which has their own context detached from the MaterialApp context. if it's possible to detect, the screen below the Dialog, Bottom Sheet, Overlay will still visible to the tester
To Reproduce Steps to reproduce the behavior:
Expected behavior the finder should not be able to see the widget below the Dialog, Bottom Sheet, Overlay
Screenshots
Desktop (please complete the following information):
Smartphone (please complete the following information):
Additional context is there something that i missed? in the screen shot, you can see there is too many "start date" while there is only one above my bottom sheet. there's many "start date" below the bottom sheet. is there work around for me to check if there's bottom sheet opened?
thanks!