Flutter Riverpod WidgetTest not exceeding past loading state - flutter

UPDATE: Rewrote Test in a same way I test another consumer widget, which actually works, but it still doesn't work for my test and I can't get my head around why :(
Current approach:
void main() {
final List<Exercise> _mockExercises = [
Exercise(
userID: 'uid123',
title: 'Übung1',
repetitions: 10,
isCompleted: false,
isVideo: false,
unit: 'Sekunden',
description: 'Some description',
exerciseID: '42',
imageUrl: 'https://via.placeholder.com/150',
thumbUrl: 'https://via.placeholder.com/150'),
Exercise(
userID: 'uid123',
title: 'Übung2',
repetitions: 20,
isCompleted: false,
isVideo: false,
unit: 'Sekunden',
description: 'Some description2',
exerciseID: '43',
imageUrl: 'https://via.placeholder.com/150',
thumbUrl: 'https://via.placeholder.com/150'),
];
testWidgets('user exercise list - pump', (WidgetTester tester) async {
await mockNetworkImagesFor(() async {
await tester.pumpWidget(ProviderScope(
child: MyApp(),
/// overrides: provide fake asyncvalue data to stream
overrides: [
exerciseCollectionStream
.overrideWithValue(AsyncValue.data(_mockExercises))
],
));
await tester.pump();
// The first frame is a loading state.
expect(find.byType(Loading), findsOneWidget);
await tester.pumpAndSettle();
// await Future.delayed(Duration(seconds: 2));
// await tester.pumpAndSettle();
// No-longer loading
expect(find.byType(Loading), findsNothing);
});
});
}
I'm trying to write a widget test for a Listview Widget and I never get past the loading state of the "Asyncvalue".when state in my test and it is stuck in loading.
I tried to approach the test like in the Riverpod docs or as explained here: https://codewithandrea.com/videos/flutter-state-management-riverpod/
But I got stuck :-/
We have Loading() Widget, that we test against to see if it disappears, but it doesn't..
That's the code of the test:
class ExerciseRepo {
// ignore: missing_return
Future<List<Exercise>> exerciseList() {
// should get data from database
}
}
final exerciseRepoProvider = Provider((ref) => ExerciseRepo());
final exerciseListProvider = FutureProvider<List<Exercise>>((ref) {
final repo = ref.watch(exerciseRepoProvider);
return repo.exerciseList();
});
class MockExercisesRepository extends Mock implements ExerciseRepo {
#override
Future<List<Exercise>> exerciseList() {
return Future.value([
Exercise(
title: 'Übung1',
repetitions: 10,
isCompleted: false,
isVideo: false,
unit: 'Sekunden',
description: 'Some description',
exerciseID: '42',
imageUrl: 'https://via.placeholder.com/150',
thumbUrl: 'https://via.placeholder.com/150'),
Exercise(
title: 'Übung2',
repetitions: 20,
isCompleted: false,
isVideo: false,
unit: 'Sekunden',
description: 'Some description2',
exerciseID: '43',
imageUrl: 'https://via.placeholder.com/150',
thumbUrl: 'https://via.placeholder.com/150'),
]);
}
}
void main() {
testWidgets('override repositoryProvider', (WidgetTester tester) async {
await mockNetworkImagesFor(() async {
await tester.pumpWidget(
ProviderScope(
overrides: [
exerciseListProvider.overrideWithProvider(
Provider((ref) => MockExercisesRepository))
],
child: MaterialApp(
home: Builder(builder: (context) {
return UserExerciseList();
}),
),
),
);
// The first frame is a loading state.
expect(find.byType(Loading), findsOneWidget);
await tester.pump();
await tester.pumpAndSettle();
// await Future.delayed(Duration(seconds: 3));
await tester.pumpAndSettle();
// No-longer loading
expect(find.byType(Loading), findsNothing);
});
});
}
The error message is:
The following TestFailure object was thrown running a test:
Expected: no matching nodes in the widget tree
Actual: _WidgetTypeFinder:<exactly one widget with type "Loading" (ignoring offstage widgets):
Loading>
Which: means one was found but none were expected
When the exception was thrown, this was the stack:
#4 main.<anonymous closure>.<anonymous closure> (file:///.../test/widget_exercise_list_test.dart:77:7)
<asynchronous suspension>
#5 main.<anonymous closure>.<anonymous closure> (file:///.../test/widget_exercise_list_test.dart)
#10 HttpOverrides.runZoned (dart:_http/overrides.dart:55:26)
#11 mockNetworkImagesFor (package:network_image_mock/src/network_image_mock.dart:9:24)
#12 main.<anonymous closure> (file:///.../test/widget_exercise_list_test.dart:54:11)
#13 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:146:29)
<asynchronous suspension>
#14 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart)
#15 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:784:19)
<asynchronous suspension>
#18 TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:764:14)
#19 AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1173:24)
#20 FakeAsync.run.<anonymous closure>.<anonymous closure> (package:fake_async/fake_async.dart:178:54)
#25 withClock (package:clock/src/default.dart:48:10)
#26 FakeAsync.run.<anonymous closure> (package:fake_async/fake_async.dart:178:22)
#31 FakeAsync.run (package:fake_async/fake_async.dart:178:7)
#32 AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:1170:15)
#33 testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:138:24)
#34 Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:175:19)
<asynchronous suspension>
#35 Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart)
#40 Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:173:13)
#41 Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:231:15)
#46 Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:228:5)
#47 Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:383:17)
<asynchronous suspension>
#48 Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart)
#53 Invoker._onRun.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:370:9)
#54 Invoker._guardIfGuarded (package:test_api/src/backend/invoker.dart:415:15)
#55 Invoker._onRun.<anonymous closure> (package:test_api/src/backend/invoker.dart:369:7)
#62 Invoker._onRun (package:test_api/src/backend/invoker.dart:368:11)
#63 LiveTestController.run (package:test_api/src/backend/live_test_controller.dart:153:11)
#64 RemoteListener._runLiveTest.<anonymous closure> (package:test_api/src/remote_listener.dart:256:16)
#69 RemoteListener._runLiveTest (package:test_api/src/remote_listener.dart:255:5)
#70 RemoteListener._serializeTest.<anonymous closure> (package:test_api/src/remote_listener.dart:208:7)
#88 _GuaranteeSink.add (package:stream_channel/src/guarantee_channel.dart:125:12)
#89 new _MultiChannel.<anonymous closure> (package:stream_channel/src/multi_channel.dart:159:31)
#93 CastStreamSubscription._onData (dart:_internal/async_cast.dart:85:11)
#127 new _WebSocketImpl._fromSocket.<anonymous closure> (dart:_http/websocket_impl.dart:1145:21)
#135 _WebSocketProtocolTransformer._messageFrameEnd (dart:_http/websocket_impl.dart:338:23)
#136 _WebSocketProtocolTransformer.add (dart:_http/websocket_impl.dart:232:46)
#146 _Socket._onData (dart:io-patch/socket_patch.dart:2044:41)
#155 new _RawSocket.<anonymous closure> (dart:io-patch/socket_patch.dart:1580:33)
#156 _NativeSocket.issueReadEvent.issue (dart:io-patch/socket_patch.dart:1076:14)
(elided 115 frames from dart:async and package:stack_trace)
This was caught by the test expectation on the following line:
file:///.../test/widget_exercise_list_test.dart line 77
The test description was:
override repositoryProvider
════════════════════════════════════════════════════════════════════════════════════════════════════
Test failed. See exception logs above.
The test description was: override repositoryProvider
That's the relevant part of the UserExerciseList()
#override
Widget build(BuildContext context, ScopedReader watch) {
AsyncValue<List<Exercise>> userExercisesList =
watch(exerciseCollectionStream);
return userExercisesList.when(
error: (error, stack) => ErrorInfo(error, stack),
loading: () => Loading(),
data: (List<Exercise> exercises) {
I also replaced Future with stream in my tests, didn't work either :-/ Any help is highly appreciated!
Many thanks!

I had to try out using several pumps to get a my mock data to return and change the state.
await tester.pumpWidget(ProviderScope(child: const MyApp()));
await tester.pump(Duration(seconds: 1));
await tester.pump(Duration(seconds: 1));
await tester.pump(Duration(seconds: 1));
expect(find.text("Sample Text"), findsOneWidget);
pumpAndSettle did not work.

Related

Flutter-Test: Getting BlocProvider.of() called with a context that does not container Bloc

I am trying to test my submit button which fires a bloc event onPress.
SubmitButton.dart - Widget
class AuthenticationSubmitButton extends StatefulWidget {
final String buttonLabel;
final TextEditingController _userEmailController;
final TextEditingController _passwordController;
AuthenticationSubmitButton(
this.buttonLabel, this._userEmailController, this._passwordController);
#override
_AuthenticationSubmitButtonState createState() =>
_AuthenticationSubmitButtonState();
}
class _AuthenticationSubmitButtonState
extends State<AuthenticationSubmitButton> {
#override
Widget build(BuildContext context) {
Size screenSize = MediaQuery.of(context).size;
final _authBloc = BlocProvider.of<AuthenticationBloc>(context);
return Container(
child: FlatButton.icon(
height: screenSize.height * 0.07,
minWidth: screenSize.width * 0.5,
padding: EdgeInsets.all(10),
color: Colors.green,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
onPressed: () {
final email = widget._userEmailController.text.trim();
final password = widget._passwordController.text.trim();
_authBloc.add(UserLoginEvent(email, password));
},
icon: Icon(Icons.keyboard_return_rounded),
label: Text(
widget.buttonLabel,
style: SubmitButtonStyle,
),
),
);
}
}
As you can see I am calling the event UserLoginEvent
authentication_events.dart
#immutable
abstract class AuthenticationEvent {}
/**
* Login Event
* Logout Event
*/
class UserLoginEvent extends AuthenticationEvent {
final String userEmail;
final String userPassword;
UserLoginEvent(this.userEmail, this.userPassword);
}
class ClearLoginEvent extends AuthenticationEvent {
}
And here is my authentication states
authentication_states.dart
#immutable
abstract class AuthenticationState extends Equatable {
}
class AuthenticationInitial extends AuthenticationState {
#override
List<Object> get props => [];
}
/**
* LoginSuccessful
* LoginFailed
* LogoutSuccessful
*/
class LoginSuccessful extends AuthenticationState {
#override
List<Object> get props => [];
}
class LoginError extends AuthenticationState {
#override
List<Object> get props => [];
}
authentication_bloc.dart
class AuthenticationBloc
extends Bloc<AuthenticationEvent, AuthenticationState> {
AuthenticationBloc({this.userRepository}) : super(AuthenticationInitial());
UserRepository userRepository;
#override
Stream<AuthenticationState> mapEventToState(
AuthenticationEvent event,
) async* {
if (event is UserLoginEvent) {
UserRepository repository = userRepository ?? UserRepository();
try {
bool loggedIn = await repository.authenticateUserWithCredentials(
event.userEmail, event.userPassword);
if (loggedIn) {
yield LoginSuccessful();
} else {
yield LoginError();
}
} catch (e) {
yield EmptyLoginCredentials();
}
} else if (event is ClearLoginEvent) {
yield AuthenticationInitial();
}
}
}
And finally my test for submit button
> submit_button_test.dart
class MockAuthBloc extends MockBloc<AuthenticationState>
implements AuthenticationBloc {}
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
MockAuthBloc authBloc = MockAuthBloc();
TextEditingController _userEmailController;
TextEditingController _passwordController;
setUp(() {
_userEmailController = TextEditingController();
_passwordController = TextEditingController();
authBloc = MockAuthBloc();
});
tearDown(() {
_userEmailController.dispose();
_passwordController.dispose();
authBloc?.close();
});
///Provide Material App for giving access to MediaQuery
///Wrap any widget that needs Material widget
Widget buildTestableWidget(Widget widget) {
return MediaQuery(
data: MediaQueryData(),
child: BlocProvider.value(
value: authBloc,
child: MaterialApp(
home: Material(
child: widget,
),
),
),
);
}
group('Testing Submit button |', () {
testWidgets('description', (WidgetTester tester) async {
whenListen(
authBloc,
Stream.fromIterable(<AuthenticationState>[LoginSuccessful()]),
);
await tester.pumpWidget(buildTestableWidget(AuthenticationSubmitButton(
'Submit', _userEmailController, _passwordController)));
final buttonFinder = find.byType(FlatButton);
final button = tester.firstWidget(buttonFinder);
});
});
}
Could you please tell me what am I doing wrong here?
Below is my error
00:03 +19: /home/bhuvanesh/code/kaadhal_host_client/test/screens/Authentication/widgets/submit_button_test.dart: Testing Submit button | description
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following assertion was thrown building AuthenticationSubmitButton(dirty, dependencies:
[MediaQuery], state: _AuthenticationSubmitButtonState#da4f9):
BlocProvider.of() called with a context that does not contain a Bloc/Cubit of type
AuthenticationBloc.
No ancestor could be found starting from the context that was passed to
BlocProvider.of<AuthenticationBloc>().
This can happen if the context you used comes from a widget above the BlocProvider.
The context used was: AuthenticationSubmitButton(dirty, dependencies: [MediaQuery], state:
_AuthenticationSubmitButtonState#da4f9)
The relevant error-causing widget was:
AuthenticationSubmitButton
file:///home/bhuvanesh/code/kaadhal_host_client/test/screens/Authentication/widgets/submit_button_test.dart:57:51
When the exception was thrown, this was the stack:
#0 BlocProvider.of (package:flutter_bloc/src/bloc_provider.dart:121:7)
#1 _AuthenticationSubmitButtonState.build (package:kaadhal_host_client/screens/Authentication/widgets/submit_button.dart:26:36)
#2 StatefulElement.build (package:flutter/src/widgets/framework.dart:4744:28)
#3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4627:15)
#4 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4800:11)
#5 Element.rebuild (package:flutter/src/widgets/framework.dart:4343:5)
#6 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4606:5)
#7 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4791:11)
#8 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4601:5)
... Normal element mounting (174 frames)
#182 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
#183 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6236:32)
... Normal element mounting (267 frames)
#450 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
#451 Element.updateChild (package:flutter/src/widgets/framework.dart:3327:18)
#452 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4652:16)
#453 _InheritedProviderScopeElement.performRebuild (package:provider/src/inherited_provider.dart:426:11)
#454 Element.rebuild (package:flutter/src/widgets/framework.dart:4343:5)
#455 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4606:5)
#456 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4601:5)
... Normal element mounting (7 frames)
#463 SingleChildWidgetElementMixin.mount (package:nested/nested.dart:223:11)
... Normal element mounting (7 frames)
#470 SingleChildWidgetElementMixin.mount (package:nested/nested.dart:223:11)
... Normal element mounting (7 frames)
#477 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
#478 Element.updateChild (package:flutter/src/widgets/framework.dart:3324:20)
#479 RenderObjectToWidgetElement._rebuild (package:flutter/src/widgets/binding.dart:1252:16)
#480 RenderObjectToWidgetElement.update (package:flutter/src/widgets/binding.dart:1230:5)
#481 RenderObjectToWidgetElement.performRebuild (package:flutter/src/widgets/binding.dart:1244:7)
#482 Element.rebuild (package:flutter/src/widgets/framework.dart:4343:5)
#483 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2730:33)
#484 AutomatedTestWidgetsFlutterBinding.drawFrame (package:flutter_test/src/binding.dart:1088:18)
#485 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:302:5)
#486 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1117:15)
#487 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1055:9)
#488 AutomatedTestWidgetsFlutterBinding.pump.<anonymous closure> (package:flutter_test/src/binding.dart:961:9)
#491 TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:72:41)
#492 AutomatedTestWidgetsFlutterBinding.pump (package:flutter_test/src/binding.dart:948:27)
#493 WidgetTester.pumpWidget.<anonymous closure> (package:flutter_test/src/widget_tester.dart:524:22)
#496 TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:72:41)
#497 WidgetTester.pumpWidget (package:flutter_test/src/widget_tester.dart:521:27)
#498 main.<anonymous closure>.<anonymous closure> (file:///home/bhuvanesh/code/kaadhal_host_client/test/screens/Authentication/widgets/submit_button_test.dart:57:20)
#499 main.<anonymous closure>.<anonymous closure> (file:///home/bhuvanesh/code/kaadhal_host_client/test/screens/Authentication/widgets/submit_button_test.dart:46:32)
#500 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:146:29)
#511 FakeAsync.flushMicrotasks (package:fake_async/fake_async.dart:193:32)
#512 AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1189:17)
#513 AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1177:35)
(elided 29 frames from dart:async and package:stack_trace)
════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ 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.first (dart:core/iterable.dart:524:7)
#1 WidgetController.firstWidget (package:flutter_test/src/controller.dart:79:30)
#2 main.<anonymous closure>.<anonymous closure> (file:///home/bhuvanesh/code/kaadhal_host_client/test/screens/Authentication/widgets/submit_button_test.dart:60:29)
<asynchronous suspension>
#3 main.<anonymous closure>.<anonymous closure> (file:///home/bhuvanesh/code/kaadhal_host_client/test/screens/Authentication/widgets/submit_button_test.dart)
#4 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:146:29)
<asynchronous suspension>
#5 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart)
#6 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:784:19)
<asynchronous suspension>
#9 TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:764:14)
#10 AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1173:24)
#11 FakeAsync.run.<anonymous closure>.<anonymous closure> (package:fake_async/fake_async.dart:178:54)
#16 withClock (package:clock/src/default.dart:48:10)
#17 FakeAsync.run.<anonymous closure> (package:fake_async/fake_async.dart:178:22)
#22 FakeAsync.run (package:fake_async/fake_async.dart:178:7)
#23 AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:1170:15)
#24 testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:138:24)
#25 Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:175:19)
<asynchronous suspension>
#26 Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart)
#31 Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:173:13)
#32 Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:231:15)
#37 Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:228:5)
#38 Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:383:17)
<asynchronous suspension>
#39 Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart)
#44 Invoker._onRun.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:370:9)
#45 Invoker._guardIfGuarded (package:test_api/src/backend/invoker.dart:415:15)
#46 Invoker._onRun.<anonymous closure> (package:test_api/src/backend/invoker.dart:369:7)
#53 Invoker._onRun (package:test_api/src/backend/invoker.dart:368:11)
#54 LiveTestController.run (package:test_api/src/backend/live_test_controller.dart:153:11)
#55 RemoteListener._runLiveTest.<anonymous closure> (package:test_api/src/remote_listener.dart:256:16)
#60 RemoteListener._runLiveTest (package:test_api/src/remote_listener.dart:255:5)
#61 RemoteListener._serializeTest.<anonymous closure> (package:test_api/src/remote_listener.dart:208:7)
#79 _GuaranteeSink.add (package:stream_channel/src/guarantee_channel.dart:125:12)
#80 new _MultiChannel.<anonymous closure> (package:stream_channel/src/multi_channel.dart:159:31)
#84 CastStreamSubscription._onData (dart:_internal/async_cast.dart:85:11)
#118 new _WebSocketImpl._fromSocket.<anonymous closure> (dart:_http/websocket_impl.dart:1145:21)
#126 _WebSocketProtocolTransformer._messageFrameEnd (dart:_http/websocket_impl.dart:338:23)
#127 _WebSocketProtocolTransformer.add (dart:_http/websocket_impl.dart:232:46)
#137 _Socket._onData (dart:io-patch/socket_patch.dart:2044:41)
#146 new _RawSocket.<anonymous closure> (dart:io-patch/socket_patch.dart:1580:33)
#147 _NativeSocket.issueReadEvent.issue (dart:io-patch/socket_patch.dart:1076:14)
(elided 111 frames from dart:async and package:stack_trace)
The test description was:
description
════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following message was thrown:
Multiple exceptions (2) were detected during the running of the current test, and at least one was
unexpected.
════════════════════════════════════════════════════════════════════════════════════════════════════
00:03 +19 -1: /home/bhuvanesh/code/kaadhal_host_client/test/screens/Authentication/widgets/submit_button_test.dart: Testing Submit button | description [E]
Test failed. See exception logs above.
The test description was: description
Reasons-
You are coming on this class thought navigator
Your parent is not using same bloc
Solution-
You can use bloc here by passing it to constructor

Flutter tester..tap not working. How to solve "Bad state: No element" error?

I'm writing a widget test in my Flutter app. I'able to find the button using key or text or widget type but when I tap it, it gives Bad State No element error. Below is my test source code. I can also see the element in tester object while debugging under allWidgets item.
class MockSpeechRecognizer extends Mock implements SpeechRecognizer {}
void main() {
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
setUpAll(() {
const MethodChannel('plugins.flutter.io/shared_preferences')
.setMockMethodCallHandler((MethodCall methodCall) async {
if (methodCall.method == 'getAll') {
return <String, dynamic>{}; // set initial values here if desired
}
return null;
});
setupLocator();
});
group('DashboardView Test | ', () {
testWidgets('Build Dashboard view and change keyword', (WidgetTester tester) async {
final Preferences preferences=Preferences();
preferences.keyword='hello';
final MockSpeechRecognizer speechService = MockSpeechRecognizer();
when(speechService.isServiceRunning).thenReturn(true);
locator.unregister<SpeechRecognizer>();
locator.registerLazySingleton<SpeechRecognizer>(() => speechService);
locator<LocalStorageService>().setUserPreferences(preferences);
// Build our app and trigger a frame.
binding.window.physicalSizeTestValue = Size(600, 300);
await tester.pumpWidget(MaterialApp(home:Dashboard()));
await tester.pumpAndSettle();
expect(find.byType(Dashboard),findsOneWidget);
await tester.tap(find.byKey(const Key('ChangeKeyword')));
});
});
}
══╡ 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:554:25)
#1 WidgetController._getElementPoint (package:flutter_test/src/controller.dart:646:47)
#2 WidgetController.getCenter (package:flutter_test/src/controller.dart:618:12)
#3 WidgetController.tap (package:flutter_test/src/controller.dart:256:18)
#4 main.<anonymous closure>.<anonymous closure> (file:///E:/Siak/Meow/meow-phone-finder/test/Widgets/dashboardView_test.dart:52:20)
<asynchronous suspension>
#5 main.<anonymous closure>.<anonymous closure> (file:///E:/Siak/Meow/meow-phone-finder/test/Widgets/dashboardView_test.dart)
#6 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:140:29)
<asynchronous suspension>
#7 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart
Where do you define the Button, have you set the Key parameter?
await tester.pumpWidget(MaterialApp(home:
Container(child:
Button(
key: Key("ChangeKeyword"),
onTap: () => {},
child: Text("Press me"),
),
),
));

Flutter widget testing - no keyboard attached

I am trying to test my stateful widget CheckedTextField:
class _CheckedTextFieldState extends State<CheckedTextField> {
TextEditingController _controller = TextEditingController();
bool _checked;
String _valueBackup;
#override
void initState() {
super.initState();
_checked = widget.initialChecked;
_controller.text = widget.initialValue;
_controller.addListener(invokeCallback);
}
invokeCallback() {
widget.callback(_controller.text.trim(), _checked);
}
#override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Expanded(
child: TextField(
enabled: _checked,
controller: _controller,
decoration: widget.decoration,
),
),
Checkbox(
onChanged: (value) {
if (value == false) {
_valueBackup = _controller.text;
_controller.text = "";
}
if (value == true) {
_controller.text = _valueBackup;
}
setState(() {
_checked = value;
});
invokeCallback();
},
value: _checked,
),
],
);
}
}
When I try to test the widget with the following code, the engine tells me to show the keyboard first:
testWidgets('enter text when not checked', (WidgetTester tester) async {
String value = "";
bool checked = false;
await tester.pumpWidget(
wrapMaterial(
CheckedTextField(
initialValue: value,
initialChecked: checked,
callback: (_value, _checked) {
value = _value;
checked = _checked;
},
),
),
);
await tester.enterText(find.byType(TextField), "newText");
expect(value, "newText");
expect(checked, isFalse);
});
I already tried to show the keyboard manually with await tester.showKeyboard(find.byType(TextField)); before entering the text, but the issue still remains.
I also wrote a finder predicate to make sure the TextField is found, so the issue seems to be somewhere else.
The thrown exception:
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure object was thrown running a test:
Tried to use TestTextInput with no keyboard attached. You must use WidgetTester.showKeyboard() first.
When the exception was thrown, this was the stack:
#0 TestTextInput.updateEditingValue (package:flutter_test/src/test_text_input.dart:133:7)
#1 TestTextInput.enterText (package:flutter_test/src/test_text_input.dart:170:5)
#2 WidgetTester.enterText.<anonymous closure> (package:flutter_test/src/widget_tester.dart:875:21)
<asynchronous suspension>
#3 WidgetTester.enterText.<anonymous closure> (package:flutter_test/src/widget_tester.dart)
#6 TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:72:41)
#7 WidgetTester.enterText (package:flutter_test/src/widget_tester.dart:873:27)
#8 main.<anonymous closure> (file:///home/kevin/Projekte/Blackout/test/widget/checked_text_field/checked_text_field_test.dart:54:18)
<asynchronous suspension>
#9 main.<anonymous closure> (file:///home/kevin/Projekte/Blackout/test/widget/checked_text_field/checked_text_field_test.dart)
#10 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:140:29)
<asynchronous suspension>
#11 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart)
#12 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:703:19)
<asynchronous suspension>
#15 TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:683:14)
#16 AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1083:24)
#17 FakeAsync.run.<anonymous closure>.<anonymous closure> (package:fake_async/fake_async.dart:177:54)
#22 withClock (package:clock/src/default.dart:46:10)
#23 FakeAsync.run.<anonymous closure> (package:fake_async/fake_async.dart:177:22)
#28 FakeAsync.run (package:fake_async/fake_async.dart:177:7)
#29 AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:1080:15)
#30 testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:133:24)
#31 Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:172:27)
<asynchronous suspension>
#32 Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart)
#33 Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:246:15)
#38 Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:243:5)
#39 Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:170:33)
#44 Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:169:13)
#45 Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:400:30)
(elided 36 frames from class _RawReceivePortImpl, class _Timer, dart:async, dart:async-patch, and package:stack_trace)
The test description was:
enter text when not checked
════════════════════════════════════════════════════════════════════════════════════════════════════
You need attach the textInput to it. Simply use
await tester.showKeyboard(find.byType(TextField));
testWidgets('enter text when not checked', (WidgetTester tester) async {
String value = "";
bool checked = false;
await tester.pumpWidget(
wrapMaterial(
CheckedTextField(
initialValue: value,
initialChecked: checked,
callback: (_value, _checked) {
value = _value;
checked = _checked;
},
),
),
);
await tester.showKeyboard(find.byType(TextField));
await tester.enterText(find.byType(TextField), "newText");
expect(value, "newText"); //it's not part of the question but this WILL not change
expect(checked, isFalse);
});
If you want to check state of this EditableText, ie. controller, widget properties, ...;
final _focusedEditable = tester.state<EditableTextState>(
find.descendant(
of: find.byType(TextField).first,
matching: find.byType(EditableText),
matchRoot: true,
),
);
If you want to check the text input use
tester.testTextInput, ie. keyboard visibility, clients listening

context doesn't match when testing Provider

I have written a test to check that a provider works as expected, however i get the following exception when checking that the context matches the providers context:
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure object was thrown running a test:
Expected:
_InheritedProvderElement<AuthScreen>:<ChangeNotifierProvider<AuthScreen>-[GlobalKey#11403](value:
Instance of 'AuthScreen', listening to value)>
Actual:
_DefaultInheritedProviderScopeElement<AuthScreen>:<_DefaultInheritedProviderScope<AuthScreen>(value:
Instance of 'AuthScreen', listening to value)>
When the exception was thrown, this was the stack:
#4 main.<anonymous closure> (file:///home/hannes/Documents/StudioProjects/brf/test/Authentication/authenticate_test.dart:24:5)
<asynchronous suspension>
#5 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:140:29)
<asynchronous suspension>
#6 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:699:19)
<asynchronous suspension>
#9 TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:679:14)
#10 AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1079:24)
#16 AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:1076:15)
#17 testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:133:24)
#18 Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:171:27)
<asynchronous suspension>
#19 Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:242:15)
#24 Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:239:5)
#25 Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:169:33)
#30 Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:168:13)
#31 Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:392:25)
#45 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:398:19)
#46 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:429:5)
#47 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
(elided 28 frames from class _FakeAsync, package dart:async, package dart:async-patch, and package stack_trace)
This was caught by the test expectation on the following line:
file:///home/hannes/Documents/StudioProjects/brf/test/Authentication/authenticate_test.dart line 24
The test description was:
AuthScreen provider changes value
════════════════════════════════════════════════════════════════════════════════════════════════════
Also, _childKey.currentContext is null. I don't know if that is related or if it's something else that I'm doing wrong.
I have tried to follow this guide, and my test looks like this:
import 'package:brf/models/auth_screen.dart';
import 'package:brf/screens/authenticate/authenticate.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
setUp(() {
AuthScreen();
});
testWidgets('AuthScreen provider changes value', (WidgetTester tester) async {
final _providerKey = GlobalKey();
final _childKey = GlobalKey();
BuildContext context;
await tester.pumpWidget(
MaterialApp(
home: ChangeNotifierProvider<AuthScreen>(
key: _providerKey,
create: (c) {
context = c;
return AuthScreen();
},
child: Authenticate(key: _childKey),
),
),
);
expect(context, equals(_providerKey.currentContext));
expect(Provider.of<AuthScreen>(_childKey.currentContext).showSignIn, true);
Provider.of<AuthScreen>(context, listen: false).switchScreen();
await Future.microtask(tester.pump);
expect(Provider.of<AuthScreen>(_childKey.currentContext).showSignIn, false);
});
}
And finally AuthScreen looks like this:
import 'package:flutter/material.dart';
class AuthScreen extends ChangeNotifier{
bool _showSignIn = true;
bool get showSignIn => _showSignIn;
void switchScreen(){
_showSignIn = !_showSignIn;
notifyListeners();
}
}
This is the error for the null context you passed
you this one:
Builder(builder: (context) => Widget here
Try like this where you want to pass the context:
MaterialApp(
home: Builder(builder: (context) => ChangeNotifierProvider<AuthScreen>(
key: _providerKey,
create: (c) {
context = c;
return AuthScreen();
},
child: Authenticate(key: _childKey),
),
),
);

Flutter: version 0.2.8 breaks code that used to work

Before I update to the new version of flutter (see below) everything worked OK.
Now it does no longer work.
The following piece of code performs a "paged" load of a gridView
Could somebody tell me what has changed with the last version of Flutter and how to solve this issue ?
Many thanks
Flutter version:
flutter --version
Flutter 0.2.8 • channel beta • https://github.com/flutter/flutter.git
Framework • revision b397406561 (11 days ago) • 2018-04-02 13:53:20 -0700
Engine • revision c903c217a1
Tools • Dart 2.0.0-dev.43.0.flutter-52afcba357
Here is the code that used to work:
typedef Future<PageAnswer> ApiPageRequest(int page, int pageSize);
class MIDApi {
///
/// Returns the list of items belonging to the active profile
///
Future<PageAnswer> getItems({
int pageIndex: 0,
int pageSize: 50,
#required String sortOrder
}) async {
String url = "ItemsList/$sortOrder";
return ajaxGet(url).then((String responseBody) async {
// print(responseBody);
final Map response = json.decode(responseBody);
final _status = response["status"];
if (_status == "OK"){
// Everything is OK
Map map = json.decode(response["data"]);
List<Map> objects = map["List"];
int total = map["Total"];
return new PageAnswer(objects, total);
}
return Null;
}).catchError((){
return Null;
});
}
}
///
/// This widget is used to display a "paged" GridView
///
/// Invocation example:
/// new PagedGridView<Map>(request, widgetAdapter: adapt);
///
/// where: request could be
/// Future<List<Map>> request(int page, int pageSize) async {
/// routine to fetch the data from the server
/// }
///
/// and adapt could be:
/// Widget adapt(Map map){
/// return new MyWidget(map);
/// }
///
class PagedGridView extends StatefulWidget {
/// Abstraction for loading the data.
/// This can be anything: An API-Call,
/// loading data from a certain file or database,
/// etc. If will deliver a list of objects (of type T)
final ApiPageRequest pageRequest;
/// The number of columns per row of the grid
final int numberColumns;
/// The number of elements requested for each page
final int pageSize;
/// The number of left-over elements in list which
/// will trigger loading the next page
final int pageThreshold;
/// Used for building Widgets out of the fetched data
final WidgetAdapter<Map> widgetAdapter;
final bool reverse;
final Indexer<Map> indexer;
final Stream<Map> topStream;
/// Constructor
const PagedGridView({
Key key,
this.numberColumns: 2,
this.pageSize: 50,
this.pageThreshold: 10,
#required this.pageRequest,
#required this.widgetAdapter,
this.reverse: false,
this.indexer,
this.topStream
}): super(key: key);
#override
State<StatefulWidget> createState() {
return new PagedGridViewState();
}
}
class PagedGridViewState extends State<PagedGridView> {
/// Contains all fetched elements ready to display
List<Map> objects = [];
/// Total number of objects that could be returned
int total = -1;
/// A Future returned by loadNext() if there
/// is currently a request running
/// or null, if no request is performed
Future request;
Map<int, int> index = {};
void doSomething(){
print("I need to do something");
}
void Clear() async {
await onRefresh();
}
#override
void initState(){
super.initState();
/// At start, let's systematically try to fetch some data
this.lockedLoadNext();
if (widget.topStream != null){
widget.topStream.listen((Map t){
setState((){
this.objects.insert(0, t);
this.reIndex();
});
});
}
}
#override
Widget build(BuildContext context){
GridView listView = new GridView.builder(
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: widget.numberColumns),
itemBuilder: itemBuilder,
itemCount: objects.length,
reverse: widget.reverse
);
RefreshIndicator refreshIndicator = new RefreshIndicator(
onRefresh: onRefresh,
child: listView
);
return new NotificationListener<ListElementUpdate<Map>>(
child: refreshIndicator,
onNotification: onUpdate
);
}
Widget itemBuilder(BuildContext context, int index){
/// If we are entering the threshold zone,
/// try to fetch additional objects
if (index + widget.pageThreshold > objects.length){
notifyThreshold();
}
return widget.widgetAdapter != null ? widget.widgetAdapter(objects[index])
: new Container();
}
void notifyThreshold(){
lockedLoadNext();
}
bool onUpdate(ListElementUpdate<Map> update){
if (widget.indexer == null){
debugPrint('ListElementUpdate on un-indexed list');
return false;
}
int index = this.index[update.key];
if (index == null){
debugPrint('ListElementUpdate index not found');
return false;
}
setState((){
this.objects[index] = update.instance;
});
return true;
}
Future onRefresh() async {
this.request?.timeout(const Duration());
PageAnswer answer = await widget.pageRequest(0, widget.pageSize);
List<Map> fetched = answer.list;
total = answer.total;
setState(() {
this.objects.clear();
this.index.clear();
this.addObjects(fetched);
});
return true;
}
///
/// This routine only fetches new data, if no other request is pending
///
void lockedLoadNext() {
if (this.request == null) {
this.request = loadNext().then((x) {
this.request = null;
});
}
}
Future loadNext() async {
// If there is no need to fetch any further data, simply return
if (objects.length >= total && total != -1){
return Null;
}
int page = (objects.length / widget.pageSize).floor();
PageAnswer answer = await widget.pageRequest(page, widget.pageSize);
List<Map> fetched = answer.list;
total = answer.total;
if (mounted) {
this.setState(() {
addObjects(fetched);
});
}
}
void addObjects(Iterable<Map> objects) {
objects.forEach((Map object) {
int index = this.objects.length;
this.objects.add(object);
if (widget.indexer != null) {
this.index[widget.indexer(object)] = index;
}
});
}
void reIndex(){
this.index .clear();
if (widget.indexer!=null){
int i = 0;
this.objects.forEach((object){
index[widget.indexer(object)] == i;
i++;
});
}
}
}
Invocation code:
class ItemsPage extends StatefulWidget {
#override
_ItemsPageState createState() => new _ItemsPageState();
}
class _ItemsPageState extends State<ItemsPage> {
static final GlobalKey<PagedGridViewState> _gridKey = new GlobalKey<PagedGridViewState>();
String _path = mid.serverHttps ? "https://${mid.serverUrl}/"
: "http://${mid.serverUrl}/";
String _sortOrder;
final List<SortMethod> sortMethods = const <SortMethod>[
const SortMethod(value: 'alpha', title: "Alpha", icon: Icons.sort_by_alpha),
const SortMethod(value: 'older_first', title: "Older first", icon: Icons.autorenew),
const SortMethod(value: 'last_first', title: "Last first", icon: Icons.change_history),
];
Future<PageAnswer> request(int page, int pageSize) async {
PageAnswer answer = await mid.api.getItems(sortOrder: _sortOrder);
return answer;
}
void _handleTap(int lookId) {
print('tap:' + lookId.toString());
}
Widget adapt(Map map){
var photos = map["Photos"].split(";");
String photoName = photos[0].split("|")[0];
return new GestureDetector(
onTap: () {_handleTap(map["Id"]);},
child: new GridTile(
child: new Card(
child: new Stack(
fit: StackFit.expand,
children: <Widget>[
new Image.network(_path + photoName,
fit: BoxFit.fitHeight),
new Center(
child: new Text(
map["Title"],
textAlign: TextAlign.center,
)),
],
),
),
),
);
}
_onSortOrderChanged(String value) {
setState((){
_sortOrder = value;
_gridKey.currentState.Clear();
});
}
#override
void initState(){
super.initState();
_sortOrder = 'alpha';
}
#override
Widget build(BuildContext context) {
PagedGridView grid = new PagedGridView(
key: _gridKey,
pageRequest: request,
widgetAdapter: adapt,
numberColumns: 2,
);
DropdownButton ddl = new DropdownButton<String>(
value: _sortOrder,
items: sortMethods.map((SortMethod sort){
return new DropdownMenuItem(
value: sort.value,
child: new Row(children: <Widget>[new Icon(sort.icon), new Text(sort.title)],)
);
}).toList(),
onChanged: _onSortOrderChanged,
);
PopupMenuButton<ItemSorting> popSort = new PopupMenuButton<ItemSorting>(
icon: new Icon(Icons.sort),
itemBuilder: (BuildContext context) => <PopupMenuItem<ItemSorting>> [
const PopupMenuItem<ItemSorting>(
value: ItemSorting.alpha,
child: const Text('Sort Alpha')
),
const PopupMenuItem<ItemSorting>(
value: ItemSorting.last_first,
child: const Text('Sort Last First')
),
const PopupMenuItem<ItemSorting>(
value: ItemSorting.older_first,
child: const Text('Sort Older First')
)
],
onSelected: (ItemSorting action){
_onSortOrderChanged(action.toString().split('.')[1]);
},
);
return new Scaffold(
appBar: new AppBar(
title: new Text('My Items'),
actions: <Widget>[
popSort, //ddl,
],
),
body: new Center(
child: grid,
),
);
}
}
class SortMethod {
const SortMethod({this.title, this.icon, this.value});
final String title;
final IconData icon;
final String value;
}
Error stack:
E/flutter (15195): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
E/flutter (15195): type 'Future<Object>' is not a subtype of type 'FutureOr<PageAnswer>' where
E/flutter (15195): Future is from dart:async
E/flutter (15195): Object is from dart:core
E/flutter (15195): FutureOr is from dart:async
E/flutter (15195): PageAnswer is from file:///D:/Development/appli/lib/libraries/function_types.dart
E/flutter (15195):
E/flutter (15195): #0 MIDApi.getItems (file:///D:/Development/appli/lib/libraries/api.dart:35:8)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #1 _ItemsPageState.request (file:///D:/Development/appli/lib/pages/items.dart:30:39)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #2 PagedGridViewState.loadNext (file:///D:/Development/appli/lib/widgets/paged_grid_view.dart:191:38)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #3 PagedGridViewState.lockedLoadNext (file:///D:/Development/appli/lib/widgets/paged_grid_view.dart:178:22)
E/flutter (15195): #4 PagedGridViewState.initState (file:///D:/Development/appli/lib/widgets/paged_grid_view.dart:93:10)
E/flutter (15195): #5 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3734:58)
E/flutter (15195): #6 ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
E/flutter (15195): #7 Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
E/flutter (15195): #8 Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
E/flutter (15195): #9 SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4637:14)
E/flutter (15195): #10 Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
E/flutter (15195): #11 Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
E/flutter (15195): #12 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
E/flutter (15195): #13 Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
E/flutter (15195): #14 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
E/flutter (15195): #15 ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
E/flutter (15195): #16 Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
E/flutter (15195): #17 Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
E/flutter (15195): #18 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
E/flutter (15195): #19 Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
E/flutter (15195): #20 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
E/flutter (15195): #21 ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
E/flutter (15195): #22 ParentDataElement.mount (package:flutter/src/widgets/framework.dart:3938:11)
E/flutter (15195): #23 Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
E/flutter (15195): #24 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4742:32)
E/flutter (15195): #25 Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
E/flutter (15195): #26 Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
E/flutter (15195): #27 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
E/flutter (15195): #28 Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
E/flutter (15195): #29 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
E/flutter (15195): #30 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3752:11)
E/flutter (15195): #31 ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
E/flutter (15195): #32 Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
E/flutter (15195): #33 Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
E/flutter (15195): #34 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
E/flutter (15195): #35 Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
E/flutter (15195): #36 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
E/flutter (15195): #37 ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
E/flutter (15195): #38 Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
E/flutter (15195): #39 Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
E/flutter (15195): #40 ComponentElement.performRebuild (packag
E/flutter (15195): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
E/flutter (15195): type 'Future<Object>' is not a subtype of type 'FutureOr<PageAnswer>' where
E/flutter (15195): Future is from dart:async
E/flutter (15195): Object is from dart:core
E/flutter (15195): FutureOr is from dart:async
E/flutter (15195): PageAnswer is from file:///D:/Development/appli/lib/libraries/function_types.dart
E/flutter (15195):
E/flutter (15195): #0 MIDApi.getItems (file:///D:/Development/appli/lib/libraries/api.dart:34:8)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #1 _ItemsPageState.request (file:///D:/Development/appli/lib/pages/items.dart:30:39)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #2 PagedGridViewState.onRefresh (file:///D:/Development/appli/lib/widgets/paged_grid_view.dart:160:38)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #3 PagedGridViewState.Clear (file:///D:/Development/appli/lib/widgets/paged_grid_view.dart:85:11)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #4 _ItemsPageState._onSortOrderChanged.<anonymous closure> (file:///D:/Development/appli/lib/pages/items.dart:67:29)
E/flutter (15195): #5 State.setState (package:flutter/src/widgets/framework.dart:1108:30)
E/flutter (15195): #6 _ItemsPageState._onSortOrderChanged (file:///D:/Development/appli/lib/pages/items.dart:65:5)
E/flutter (15195): #7 _ItemsPageState.build.<anonymous closure> (file:///D:/Development/appli/lib/pages/items.dart:114:9)
E/flutter (15195): #8 _PopupMenuButtonState.showButtonMenu.<anonymous closure> (package:flutter/src/material/popup_menu.dart)
E/flutter (15195): #9 _RootZone.runUnary (dart:async/zone.dart:1381:54)
E/flutter (15195): #10 _FutureListener.handleValue (dart:async/future_impl.dart:129:18)
E/flutter (15195): #11 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:633:45)
E/flutter (15195): #12 Future._propagateToListeners (dart:async/future_impl.dart:662:32)
E/flutter (15195): #13 Future._completeWithValue (dart:async/future_impl.dart:477:5)
E/flutter (15195): #14 Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:507:7)
E/flutter (15195): #15 _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
E/flutter (15195): #16 _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
I/flutter (15195): Another exception was thrown: type '() => Future<dynamic>' is not a subtype of type '() => Future<Null>'
E/flutter (15195): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
E/flutter (15195): type '() => Type' is not a subtype of type '(Object) => FutureOr<Object>'
E/flutter (15195): #0 _FutureListener.handleError (dart:async/future_impl.dart:145:11)
E/flutter (15195): #1 Future._propagateToListeners.handleError (dart:async/future_impl.dart:645:47)
E/flutter (15195): #2 Future._propagateToListeners (dart:async/future_impl.dart:666:24)
E/flutter (15195): #3 Future._completeError (dart:async/future_impl.dart:485:5)
E/flutter (15195): #4 _SyncCompleter._completeError (dart:async/future_impl.dart:55:12)
E/flutter (15195): #5 _Completer.completeError (dart:async/future_impl.dart:27:5)
E/flutter (15195): #6 MIDApi.getItems.<anonymous closure> (file:///D:/Development/appli/lib/libraries/api.dart)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #7 _RootZone.runUnary (dart:async/zone.dart:1381:54)
E/flutter (15195): #8 _FutureListener.handleValue (dart:async/future_impl.dart:129:18)
E/flutter (15195): #9 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:633:45)
E/flutter (15195): #10 Future._propagateToListeners (dart:async/future_impl.dart:662:32)
E/flutter (15195): #11 Future._complete (dart:async/future_impl.dart:467:7)
E/flutter (15195): #12 _SyncCompleter.complete (dart:async/future_impl.dart:51:12)
E/flutter (15195): #13 ajaxGet (file:///D:/Development/appli/lib/libraries/ajax.dart)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #14 MIDApi.getItems (file:///D:/Development/appli/lib/libraries/api.dart:21:12)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #15 _ItemsPageState.request (file:///D:/Development/appli/lib/pages/items.dart:30:39)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #16 PagedGridViewState.onRefresh (file:///D:/Development/appli/lib/widgets/paged_grid_view.dart:160:38)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #17 PagedGridViewState.Clear (file:///D:/Development/appli/lib/widgets/paged_grid_view.dart:85:11)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #18 _ItemsPageState._onSortOrderChanged.<anonymous closure> (file:///D:/Development/appli/lib/pages/items.dart:67:29)
E/flutter (15195): #19 State.setState (package:flutter/src/widgets/framework.dart:1108:30)
E/flutter (15195): #20 _ItemsPageState._onSortOrderChanged (file:///D:/Development/appli/lib/pages/items.dart:65:5)
E/flutter (15195): #21 _ItemsPageState.build.<anonymous closure> (file:///D:/Development/appli/lib/pages/items.dart:114:9)
E/flutter (15195): #22 _PopupMenuButtonState.showButtonMenu.<anonymous closure> (package:flutter/src/material/popup_menu.dart)
E/flutter (15195): #23 _RootZone.runUnary (dart:async/zone.dart:1381:54)
E/flutter (15195): #24 _FutureListener.handleValue (dart:async/future_impl.dart:129:18)
E/flutter (15195): #25 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:633:45)
E/flutter (15195): #26 Future._propagateToListeners (dart:async/future_impl.dart:662:32)
E/flutter (15195): #27 Future._completeWithValue (dart:async/future_impl.dart:477:5)
E/flutter (15195): #28 Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:507:7)
E/flutter (15195): #29 _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
E/flutter (15195): #30 _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)