I am trying to Widget test my WelcomeScreen(). WelcomeScreen has a BlocProvider and a BlocBuilder. After I load WelcomeBloc() it checks with an if statement inside the builder to check if the state is WelcomeLoadSuccessState.
How do I find something under the if statement if the statement is true?
My Welcome screen:
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => WelcomeBloc(),
child: BlocBuilder<WelcomeBloc, WelcomeState>(
builder: (context, state) {
if (state is WelcomeLoadSuccessState) {
return Scaffold(
body: Container(
child: Column(
children: [
Wrap(
direction: Axis.vertical,
crossAxisAlignment: WrapCrossAlignment.center,
children: [
Padding(
padding: EdgeInsets.all(8),
child: ShowUp(
delay: _delay + 200,
child: Text('Welcome user’, // <——— I want to find this one
)),
),
],
),
],
)),
);
}
// return LoadingWidget();
return Text('Something'); // <——— This one I can find
},
),
);
}
The test that I have now:
main() {
WelcomeBloc welcomeBloc;
WelcomeService welcomeService;
final Brand brand = Brand();
setUp(() {
setUpMocks();
welcomeService = localServices<WelcomeService>();
welcomeBloc = MockWelcomeBloc();
});
_createWidget(WidgetTester tester) async {
when(welcomeService.getBrand(id: '609a88d324a01928242d1ca9')).thenAnswer((realInvocation) => Future.value(brand));
welcomeBloc.add(WelcomeLoadRequestEvent(id: '609a88d324a01928242d1ca9'));
when(welcomeBloc.state).thenAnswer((_) => WelcomeLoadSuccessState(brand: brand));
print(welcomeBloc.state); //Correct State (WelcomeLoadSuccessState)
await tester.pumpWidget(
MaterialApp(
title: 'Flutter Demo',
home: WelcomeScreen(),
)
);
await tester.pump();
}
testWidgets('Welcome Screen Test', (WidgetTester tester) async {
await _createWidget(tester);
await tester.pump();
//expect(find.textContaining('Welcome user'), findsOneWidget); //What I want
expect(find.text('Something'), findsOneWidget); //This works
});
tearDown(() {
welcomeBloc?.close();
});
}
Thank you for helping.
I solved it:
change:
create: (context) => WelcomeBloc()
to:
create: (context) => WelcomeBloc()..add(WelcomeLoadRequestEvent(id: '609a88d324a01928242d1ca9')),
and my test is now this:
main() {
WelcomeBloc welcomeBloc;
WelcomeService welcomeService;
final Brand brand = Brand();
setUp(() {
setUpMocks();
welcomeService = localServices<WelcomeService>();
welcomeBloc = MockWelcomeBloc();
});
_createWidget(WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
title: 'Flutter Demo',
home: WelcomeScreen(),
));
await tester.pump(Duration(seconds: 10));
}
testWidgets('Welcome Screen Test', (WidgetTester tester) async {
when(welcomeService.getBrand(id: '609a88d324a01928242d1ca9'))
.thenAnswer((realInvocation) => Future.value(brand));
whenListen(
welcomeBloc,
Stream.fromIterable([
WelcomeLoadInProgressState(),
WelcomeLoadSuccessState(brand: brand),
]));
await _createWidget(tester);
await tester.pump(Duration(seconds: 5));
expect(find.textContaining('Welcome user'), findsOneWidget);
});
tearDown(() {
welcomeBloc?.close();
unRegister();
});
}
Edit to add:
For my other pages it was useful to separate the blocProvider and the blocBuilder. This way I was able to Mock my blocProvider with a MockMyBloc() and then give the screen in the child.
My real widgets:
MyWidgetMakeBlocProviders(
Widget build(context) {
return BlocProvider<MyBloc>(
create: (context) => MyBloc(),
child: MyScreen(),
);
}
)
MyScreen(
Widget build(context) {
return BlocBuilder<MyBloc, MyBlocState>(
builder: (context, state) {...}
);
}
)
My test:
testWidgets('', (tester) async {
whenListen(MockMyBloc, Stream.fromIterable([
InitState(),
LoadedState()
]));
await _createWidget(tester);
await tester.pump();
//expect()
});
_createWidget(tester) async {
await tester.pumpWidget(
MaterialApp(
title: '',
home: BlocProvider<MockMyBloc>(
create: (context) => MockMyBloc(),
child: MyScreen(),
)
)
);
await tester.pump();
}