Closed Maqcel closed 1 year ago
I'm on the same boat right now, without auto_routes router tests find my widgets, but when I try to use it none of the tests find any widget. If someone has resources on how to set this up greatly appreciated.
+1
I've found a way to mock auto_route using get_it
Call the router like this in your widget
getIt<AppRouter>().push(const ScreenHome()));
// intead of
context.router.push(const ScreenHome()));
main.dart
GetIt getIt = GetIt.instance;
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
getIt.registerSingleton<AppRouter>(
AppRouter(
checkIfAuthenticated: CheckIfAuthenticated(),
),
);
runApp(initApp()); // child: MyApp()
}
class MyApp extends StatelessWidget {
MyApp({Key? key}) : super(key: key);
final router = getIt<AppRouter>();
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerDelegate: AutoRouterDelegate(router),
routeInformationParser: router.defaultRouteParser(),
);
}
}
widget_test.dart
import 'package:projectname/routes/router.gr.dart' as router;
import 'package:projectname/screens/log_in.dart';
class AppRouterMock extends Mock implements router.AppRouter {}
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
WidgetsFlutterBinding.ensureInitialized();
setUpAll(() {
final appRouterMock = AppRouterMock();
getIt.registerSingleton<router.AppRouter>(appRouterMock);
});
testWidgets('Should goto home',
(WidgetTester tester) async {
// Given
when(() => getIt<router.AppRouter>().push(
const router.ScreenHome(),
)).thenAnswer((_) async => {});
// When
await tester.pumpWidget(
const MaterialApp(
home: ScreenLogIn(),
),
);
await tester.tap(find.byType(ElevatedButton));
await tester.pumpAndSettle();
await tester.pump(Duration(seconds: 2));
// Then
verify(() => getIt<router.AppRouter>().push(const router.ScreenHome()));
});
}
Here is a exemple how to use get_it with widget tests : https://github.com/TheSmartMonkey/flutter-http-widget-test
+1
@Maqcel seems i faced the same problem with AutoTabsScaffold, and successfully proceed to the next step with
return MultiProvider(
providers: [
...AppDependencies.getProviders(),
],
child: Portal(
child: MaterialApp.router(
theme: AppTheme.buildTheme(const DesignSystem.light()),
darkTheme: AppTheme.buildTheme(const DesignSystem.dark()),
routeInformationParser: router.defaultRouteParser(),
routerDelegate: router.delegate(),
themeMode: ThemeMode.light,
supportedLocales: I18n.supportedLocales,
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
],
),
),
);
but stuck with error, that provider can't find one of my dependencies in child page (one of route from routes list in AutoTabsScaffold)
BlocProvider.of() called with a context that does not contain a Bloc of type
SampleBlocType
What i want to achieve - it's not a track of transition between the pages, my target - golden test of page which contain multiple tabs.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions
The issue with injecting auto_route into DI (get_it) is that you can't pop from a nested route.
Navigating to a nested page (a page within BottomNavigationBar
) with
getIt<AppRouter>().push(const ScreenHome()));
works fine until you want to return from ScreenHome
using
getIt<AppRouter>().pop<bool>(false);
The docs mention the following:
navigating without context is not recommended in nested navigation unless you use navigate instead of push and you provide a full hierarchy. e.g router.navigate(SecondRoute(children: [SubChild2Route()]))
Using navigate instead of push means that you can't return a value. The only solution I can see now is to use callbacks on the child page.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions
+1, I am struggling to find clear information on the subject. IMO, it might be something easily solved by sharing knowledge. Did @Milad-Akarie have a look at this?
@guplem what's the main issue here? is it waiting for push and friends pop completers?
@guplem what's the main issue here? is it waiting for push and friends pop completers?
To be honest, @Milad-Akarie , I think that the issue is a lack of an example of how to easily and properly run widget tests with AutoRoute handling the navigation.
There is little to no information about the topic. I wanted to have an app with all the fronted testing, but I had to limit myself to the logic & backend due to not finding a way of testing it with AouteRoute.
Maybe a simple app/demo showing how to navigate between screens while testing the app apart from some basic testing (like testing the counter app) would be enough.
Also having the same issue with testing.
RouteData operation requested with a context that does not include an RouteData.
Similar setup to above.
+1. Any solution for this issue? My widget:
@RoutePage()
class MainHomePage extends StatelessWidget {
const MainHomePage({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return AutoTabsScaffold(
routes: [
MovieDetailRoute(text: 'Center text'),
const MovieRoute(),
],
bottomNavigationBuilder: (_, tabsRouter) {
return BottomNavigationBar(
key: const Key('BottomNavigationBarKey'),
currentIndex: tabsRouter.activeIndex,
onTap: tabsRouter.setActiveIndex,
items: const [
BottomNavigationBarItem(label: '', icon: Icon(Icons.home)),
BottomNavigationBarItem(label: '', icon: Icon(Icons.details)),
],
);
},
);
}
}
My test class:
void main(){
testWidgets('Find a BottomNavigationBar widget', (widgetTester) async {
await widgetTester.pumpWidget(
const MaterialApp(
title: 'Widget test',
home: MainHomePage(),
),
);
await widgetTester.pumpAndSettle();
final bottomNav = find.byType(BottomNavigationBar);
expect(bottomNav, findsOneWidget);
});
}
Get an error:
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following assertion was thrown building AutoTabsScaffold:
RouteData operation requested with a context that does not include an RouteData.
The context used to retrieve the RouteData must be that of a widget that is a descendant of a
AutoRoutePage.
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure was thrown running a test:
Expected: exactly one matching candidate
Actual: _TypeWidgetFinder:<Found 0 widgets with type "BottomNavigationBar": []>
Which: means none were found but one was expected
I have another issue. I am trying to check a router call through the build context when some event occurs in the bottom of the tree, inside a stream.
Hi, I'm struggling to find a clever way to write Widget Test with auto_route included. I've searched the entire issues for some help and only managed to work with #745. The solution that was suggested there worked for my login screen but going deeper to the home screen or any other one I tried to test unfortunately failed.
Test:
HomeScreen:
Helper method for providing
MaterialApp
:As mentioned this approach was successful for the Login Screen all tests for it:
Mocks created by mockito, I'm strongly looking for some docs/tutorials on how to create widget tests with this package