Flutter: Can't click listview item on integration test - android

I have an app with a listview feature with provider pattern, and it has 5 items of data. Here is my snippet code
ListView.builder(
key: Key("listview_portfolio"),
itemBuilder: (context, index) =>
_itemListPortofolio(data.items[index], context),
itemCount: data.items.length,
)
...
Widget _itemListPortofolio(Portfolio portfolio, BuildContext context) {
return Container(
key: ValueKey("item_list_portfolio"),
margin: EdgeInsets.only(bottom: 16),
child: InkWell(
When I run this code, it doesn't throw an error, but when I do the integration test, it throws an error when trying to click the item listview
'package:flutter_test/src/binding.dart': Failed assertion: line 802 pos 14: '_pendingExceptionDetails != null': A test
overrode FlutterError.onError but either failed to return it to its original state, or had unexpected additional errors that it could
not handle. Typically, this is caused by using expect() before restoring FlutterError.onError.
flutter: dart:core-patch/errors_patch.dart 51:61 _AssertionError._doThrowNew
here's my integration test class
Future<void> tapPortfolioItem({bool scrollUp = false}) async {
await _tester.pumpAndSettle(Duration(seconds: 5));
final Widget itemPortfolio =
find.byKey(ValueKey("item_list_portfolio")).evaluate().last.widget;
await _tester.tap(find.byWidget(itemPortfolio));
}

try the code below:
final Finder instance = find.byKey(ValueKey("item_list_portifolio"));
final _itemListPortofolio test = _tester.widget(instance);
await _tester.tap(instance);
expect(anything, findsOneWidget);
expect(test.color, Colors.red);
see also other way to use pumpAndSeatle() here.

Related

I can't get a return from flutterfire realtime database emulator?

I have already done everything for the setup I'm sure. I connected my project in the firebase console, and I was able to get my app to run after an await firebase initialize (options : options...etc.) once I finished with the flutterfire CLI config.
But now I can't get the actual value from my json file in the realtime database emulator. All I can get is null. Maybe I am not referring to the json right, but my json right now is just:
{ "hello" : "hi" }
so I don't think that's the problem. This is how I'm calling the database.
final _database = FirebaseDatabase.instance.ref();
and I'm using a future builder.
child:FutureBuilder(
future: _database.child('http://{$host_number}/?ns=nimble-autumn-{$project_id_number}/hello').get(),
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return ListView.builder(
//shrinkWrap: true,
scrollDirection: Axis.vertical,
physics: AlwaysScrollableScrollPhysics(),
itemCount: gocrazy.length,
itemBuilder: (BuildContext context, int index) {
return PostCard(
status: public[0], comments: [snapshot.toString()]);
//rags[index]);
},
);
}
else {
return Column(
children: <Widget>[
SizedBox(
width: 60,
height: 60,
child: CircularProgressIndicator(),
),
Padding(
padding: EdgeInsets.only(top: 16),
child: Text('Awaiting result...'),
),
]
);
};
And the UI will complete with the if statement because I am using .toString() and this what I get (if I use .value it will cause null error).
It says invalid Firebase Database data path. So what is the valid way to put it? I am using:
'http://{$host_number}/?ns=nimble-autumn-{$projectid}/hello'
but using 'nimble-autumn-projectid/hello' or 'hello' will just have the futurebuilder hang indefinitely.

How can I display last StreamBuilder data when snapshot.data is null?

I'm making a to-do list with Flutter and Firebase Firestore, but I have a slight problem. Whenever I add a new task, snapshot.data becomes null. If I do not add a check for snapshot.connectionState and render a different widget according to that, I get the following error: NoSuchMethodError (NoSuchMethodError: The getter 'docs' was called on null.
return StreamBuilder(
stream: FirebaseFirestore.instance
.collection('tasks')
.doc(widget.uid)
.collection('mytasks')
.snapshots(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: SizedBox(
height: 100, width: 100, child: CircularProgressIndicator()),
);
} else {
> final docs = snapshot.data.docs;
return ListView.builder(
itemCount: docs.length,
itemBuilder: (ctx, index) {
final currTask = docs[index];
return Dismissible(
direction: DismissDirection.startToEnd,
key: UniqueKey(),
onDismissed: (_) async {
FirebaseFirestore.instance
.collection('tasks')
.doc(widget.uid)
.collection('mytasks')
.doc(currTask['id'])
.delete();
.
.
.
I don't want to have to display a CircularProgressIndicator or an empty screen. I want the tasks to remain visible and seamlessly add new tasks. How can I achieve that? I know what I asked for in the question title might be a little silly, what should I do instead?

Flutter RefreshIndicator method is being called but the context is not rebuild

When I delete the item from the list, then I go back and refresh the page, RefreshIndicator seems not working(The animation is working but not refreshing the page). I have searched a lot about this problem. I tried everything I found on the web but none of them worked for me. The problem is that I have the method of _refresh to call this method onRefresh but it didn't work. I debugged the code to see whether the refresh method is being called. As far as I see it seems it is being called because I see refresh method is called on the debug console. The ListView.builder also has the physics property and it's not shrunk. I saw one more solution that suggests adding items that fill the whole screen. I added as many items as I can but it didn't work. So any suggestions? I am suspecting from the FutureBuilder that is a parent of the ListView.builder, I tried to cover the FutureBuilder too but it didn't work either.
class _DraftsState extends State<Drafts> {
final SQFLiteHelper _helper = SQFLiteHelper.instance;
#override
void initState() {
print('init state is called');
super.initState();
_helper.getForms();
}
Future<void> _refresh() async {
print('refresh method is called');
await _helper.getForms();
}
//TODO: RefreshIndicator not working.
//TODO:When the list changed nothing is happening until the draft section is rebuilt
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<List<FormData>?>(
future: _helper.getForms(),
builder:
(BuildContext context, AsyncSnapshot<List<FormData>?> snapshot) {
if (snapshot.hasData && snapshot.data!.isEmpty) {
return const Center(
child: Text("Henüz kaydedilmiş taslak bulunmamaktadır."));
}
if (snapshot.hasError) {
return Center(
child: Text(
'Bir şeyler ters gitti.',
style: TEXT_STYLE,
));
}
if (snapshot.connectionState == ConnectionState.done) {
return RefreshIndicator(
backgroundColor: Colors.grey[700],
color: LIGHT_BUTTON_COLOR,
onRefresh: _refresh,
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: ListView.builder(
physics: const AlwaysScrollableScrollPhysics(),
itemCount: snapshot.data!.length,
itemBuilder: (BuildContext context, int index) {
return CustomListTile(
formData: snapshot.data![index], index: index);
},
),
),
);
}
return const Center(
child: CircularProgressIndicator(),
);
}),
);
}
}
Future<void> _refresh() async {
print('refresh method is called');
setState(() {
await _helper.getForms();
});
}
use setState in your refresh function. coz you need to reload the build method. or I think you can use setState like this.
Future<void> _refresh() async {
print('refresh method is called');
await _helper.getForms();
setState(() { });
}

cant get subcollection in firebase firestore

i cant get subcollection that i created before. i am able to create subcollection named "sinav_gorselleri" after i pressed this RaisedButton and going to SinavOlusturPage with this code:
RaisedButton(
color: Colors.blue,
child: Text("Sınav oluştur"),
onPressed: () async{
final newDoc = await FirebaseFirestore.instance.collection("ders_sinavlari_olusturulanlar")
.add({"baslik": "4oluşturulanSınav2", "gorsel": "gorsel", "konu": "", "ogretmen": "ömer kalfa",
"sira": 3, "tarih": ""});
final idnewDoc = newDoc.id;
debugPrint(idnewDoc);
final newDoc_newCol = await newDoc.collection("sinav_gorselleri")
.add({"gorsel": "https://firebasestorage.googleapis.com/v0/b/sbycpaldemo.appspot.com/o/ders_notlari_gorseller%2Fyeni?alt=media&token=4af59ada-4a8b-45cc-86ef-2f691a5baf62"});
final idnewCol = await newDoc_newCol.id;
debugPrint(idnewCol);
Navigator.of(context,rootNavigator: true).pop('dialog');
Navigator.push(context, MaterialPageRoute(builder: (context)=> SinavOlusturPage(idnewDoc: idnewDoc,)));
}),
and in SinavOlusturPage i am expecting to get first doc in subcollection named "sinav_gorselleri" but cant get it with this code:
import 'dart:io';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
class SinavOlusturPage extends StatefulWidget{
final idnewDoc;
const SinavOlusturPage({Key key, this.idnewDoc}) : super(key: key);
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return SinavOlusturPageState(this.idnewDoc);
}
}
class SinavOlusturPageState extends State {
final idnewDoc;
SinavOlusturPageState(this.idnewDoc);
File _imageSelected;
final _formKey = GlobalKey<FormState>();
final _scaffoldKey = GlobalKey<ScaffoldState>();
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(key: _scaffoldKey,
appBar: AppBar(
title: Text("SINAV OLUŞTURMA SAYFASI"),
),
body: ListView(
children: [
Center(
child: Text("..."),
StreamBuilder(
stream: FirebaseFirestore.instance.collection("ders_sinavlari_olusturulanlar/$idnewDoc/sinav_gorselleri").snapshots(),
builder: (context, snapshot){
final querySnapshot = snapshot.data();
return GridView.builder(
itemCount: 3,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
mainAxisSpacing: 10, crossAxisCount: 2,),
itemBuilder: (context, index){
final mapOlusturulan = querySnapshot.docs[index].data();
final idOlusturulan = querySnapshot.docs[index].id;
return GridTile(
child: Center(
child: Image.network(mapOlusturulan["gorsel"])),
);
});
})
],
),
);
}
}
i did tried
FirebaseFirestore.instance.collection("ders_sinavlari_olusturulanlar").doc(idnewDoc) .collection("sinav_gorselleri").snapshots(), also but cant do it. here is my error that i get all the time:
Performing hot reload...
Syncing files to device SNE LX1...
════════ Exception caught by image resource service ════════════════════════════════════════════════
The following ArgumentError was thrown resolving an image codec:
Invalid argument(s): No host specified in URI file:///gorsel
When the exception was thrown, this was the stack:
#0 _HttpClient._openUrl (dart:_http/http_impl.dart:2407:9)
#1 _HttpClient.getUrl (dart:_http/http_impl.dart:2328:48)
#2 NetworkImage._loadAsync (package:flutter/src/painting/_network_image_io.dart:89:59)
#3 NetworkImage.load (package:flutter/src/painting/_network_image_io.dart:50:14)
#4 ImageProvider.resolveStreamForKey.<anonymous closure> (package:flutter/src/painting/image_provider.dart:504:13)
...
Image provider: NetworkImage("gorsel", scale: 1.0)
Image key: NetworkImage("gorsel", scale: 1.0)
════════════════════════════════════════════════════════════════════════════════════════════════════
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The method 'call' was called on null.
Receiver: null
Tried calling: call()
The relevant error-causing widget was:
StreamBuilder<QuerySnapshot> file:///C:/ornekler/sby_cpal_demo/lib/Dersler/SinavOlusturPage.dart:39:9
════════════════════════════════════════════════════════════════════════════════════════════════════
Reloaded 22 of 694 libraries in 3.748ms.
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following NoSuchMethodError was thrown building StreamBuilder<QuerySnapshot>(dirty, state: _StreamBuilderBaseState<QuerySnapshot, AsyncSnapshot<QuerySnapshot>>#41144):
Class 'QuerySnapshot' has no instance method 'call'.
Receiver: Instance of 'QuerySnapshot'
Tried calling: call()
The relevant error-causing widget was:
StreamBuilder<QuerySnapshot> file:///C:/ornekler/sby_cpal_demo/lib/Dersler/SinavOlusturPage.dart:39:9
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
#1 SinavOlusturPageState.build.<anonymous closure> (package:sby_cpal_demo/Dersler/SinavOlusturPage.dart:42:50)
#2 StreamBuilder.build (package:flutter/src/widgets/async.dart:525:81)
#3 _StreamBuilderBaseState.build (package:flutter/src/widgets/async.dart:129:48)
#4 StatefulElement.build (package:flutter/src/widgets/framework.dart:4744:28)
...
════════════════════════════════════════════════════════════════════════════════════════════════════
════════ Exception caught by image resource service ════════════════════════════════════════════════
Invalid argument(s): No host specified in URI file:///gorsel
════════════════════════════════════════════════════════════════════════════════════════════════════
"gorsel" is my unique field key of subcollection document. this error realy makes me tired but really need to use subcollections in my app.
i didnt solved this with codings i just removed all the codes, pages and stuffs recorded to firebase firestore and rewrite them all step by step. i guess i get the reason of the error. it was about navigation time. after i pressed the button named Sinav Oluştur i was expecting the creation of the subcollection named "soru_gorselleri" of new document firstly and then navigation to SinavOlusturPage but all of these were happennig reversely so the Page was returning null. after i did all of them step by step with different RisedButtons , all of errors gone and happy end.

how to handle navigation inside build method in dart flutter

I have an application where I want to implement finger authentication. I have written the classes for authentication is working fine.
Now the scenario is, when the app starts it loads login page where I have a form. I want to check for finger print authentication first if it is successful then I want to switch to home page otherwise show the login form if not successful.
Here is my code:
final LocalAuthenticationService _localAuth = locator<LocalAuthenticationService>();
#override
Widget build(BuildContext context) {
_localAuth.authenticate().then((result){
if(result)
Navigator.pushReplacementNamed(context, Routes.HomePage);
});
return return Scaffold(
body: Container(
decoration: BoxDecoration(image: _builSplashBackgroundImage()),
child: _buildLoginForm()
);
}
I get this error when I navigate to homepage: Unhandled Exception: Looking up a deactivated widget's ancestor is unsafe.
It is quite simple. Just implement it like this using FutureBuilder
final LocalAuthenticationService _localAuth = locator<LocalAuthenticationService>();
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: _localAuth.authenticate,
builder:(ctx, snapshot)=>!snapshot.hasData? CircularProgressIndicator():
snapshot.data == true?Routes.HomePage:
Container(
decoration: BoxDecoration(image: _builSplashBackgroundImage()),
child: _buildLoginForm()
)));
}
This code will show a progressbar when loading user's connection state.
You can learn more Here about FutureBuilder

Categories

Resources