ListView in integration test (Flutter) - flutter

I haven't found a complex examples for testing ListViews. Example.
I have a ListView, which has three objects Person.
Person{
String name;
String surname;
}
In UI, Person is wrapped in Column, giving them two Text Widgets for name and surname.
I click on FAB. Clicking on FAB adds new Person with name Tom and surname Thomson to the ListView. Now there are 4 objects of Person. And I know data of the last one.
How can I validate, that item was successfully added? Is there a way to check length/count of ListView?
Is there a way to validate last added item params?
Appreciate!

widgetList provides a matching widget in the tree, just need to mention key of Listview which required to test.
final count = tester
.widgetList<ListView>(find.byKey(ValueKey("ListViewKey")))
.length;

I add my ListTile titles with a unique key (ex. 'tile_surname_#'). Assuming your ListView is built with an array of Person objects called persons, you can try something like:
final String valueKey = 'tile_$newPerson.surname_${persons.length}';
final newPersonFinder = find.byValueKey(valueKey);
expect(
await driver.getText(newPersonFinder), valueKey
);

Related

Detect user created widgets in flutter widget tree

I've been working on a problem today to detect certain widgets in the widget tree so I've been playing around with context.visitChildElements and element. visitChildren. I can see all the widgets in the tree, but there's just too many.
I looked at the way the flutter widget inspector does it and they have some internal expectations that won't exist within other users code bases. The example, I have a scaffold with a body Center and a child Material button. Passing the context to my function below prints out about 200+ widgets with those three scattered in between. I would like to only print out those three, or at least elliminate all widgets created by Flutter automatically and not created by the code the user supplied.
List<WidgetInfo> getElements(BuildContext context) {
var widgetsOfInterest = <WidgetInfo>[];
widgetsOfInterest.clear();
int indentation = 0;
void visitor(Element element) {
indentation++;
Key? key = element.widget.key;
String className = element.widget.runtimeType.toString();
while (element.findRenderObject() is! RenderBox) {}
RenderBox box = element.findRenderObject() as RenderBox;
var offset = box.getTransformTo(null).getTranslation();
final indent = ' ' * indentation;
// Here I want to check if this is a widget we created and print its name and offset
if (debugIsLocalCreationLocation(element)) print('$className $offset');
if ((MaterialButton).toString() == className) {
widgetsOfInterest.add(WidgetInfo(
indentation: indentation,
size: box.size,
paintBounds: box.paintBounds.shift(
Offset(offset.x, offset.y),
),
key: key,
className: className,
));
}
element.visitChildren(visitor);
}
context.visitChildElements(visitor);
return widgetsOfInterest;
}
If anyone have any insights or experience with the Flutter widget tree that could point me in the right direction I would appreciate that.
it's obviously seems not the best solution here(and will increase unnecessary code) but this might work.
you can create a custom widget key that have some prefix inside of it and use it in every component you want it to be detected
for example
//1
Appbar(key: FSKey())
//2
Center(key:FSKey("awesome_widget"))
internally if you have access to those key while you iterate through elements you can detect those widgets using the prefix you set.
actuall key values
//1
"fskey_1273zj72ek628"
//2
"fskey_awesome_widget"
again this might not be a very optimal solution but iit gives you some control of what parts of the tree you want it to be detected and eventually if there is no other way.. this will work.

I have a stored List data and how can I localize it in flutter?

I can translate the text inside the widget using AppLocalizations.of(context)!.translated and it work fine
However, when I want to localize a stored List<> data which will be used in listView Builder, I am not able to do so, since it need (context).
My question is how to localize a stored list data(outside widget) and pass to list view builder?
Thanks for your help.
I think you should do 2 things
In case if you have a list in another file, then it should be static like this:
class Presets {
static var presetData = [];
}
after you loaded up your list, you can do these steps:
First,
Create Widgets as children like this:
List<Widget> presetsLoadUp() {
List<Widget> children = <Widget>[];
for(i < yourList.length){
children.add(Text(yourList[i]));
}
return children;
}
You can create your own unique widget inside the children.add method.
Secondly,
Create the list:
...
child: ListView(
children: presetsLoadUp(),
),
If anyone has similar problem, please take it for reference.
I just build another widget to solve this.
What I do is :
build another widget,
then put the list data inside and
return ListViewBuilder.
Everything is same,
just put your list data inside another widget can solve the problem

When I use list.filled() and initialize the value, why do I still prompt for syntax errors?

When I use list.filled() and initialize the value, why do I still prompt for syntax errors?
enter image description here
you can not fill list of widget with number
List<Widget> list= List.filled(10,SizedBox.shrink());
If you want List of int, define List as int.
You defined a List of Widget but filled by int. See this enter link description here
List<int> list= List.filled(0,10);
// or
List<Widget> list= List.filled(0,Container());
This happens because you declared your type of your List as Widget.
List<Widget> list = List.filled(0, Container());
If you want it as type int then declare it as the following.
List<int> list = List.filled(0, 10);
as you have declared list with data type widget it can only store widgets like
List<Widgets> widgets=[Container(),Container(),Container()];
and if you need to store int as data type use this code
List<int> intList=[1,2,3,4,5];
by the way dart is smart you do not need to specify data type you can use it just like
List data =[]; //store anything here

List with Custom Class and operations on List

Hi, I have a class called Items.
class Items{
String name;
String picture;
int quantity;
int price;
Items(#required this.name, this.picture,this.quantity,this.price);
}
The same class items are rendered on the screen shown in the screenshot. I have been struggling to add an item to the cart on click of addToCart image button.Im struck at how to search the List and perform add, delete and edit operations on the list. Can somebody help me? thanks in advance.
I don't want to alter your model Items but in order to know which item you must (add, remove) in/from your cart, each item must have a unique Id or similar
class Items{
int id;
// ...
}
Hence, your ListView.builder will look like this
ListView.builder(
itemBuilder: (context, index) {
return ListTile(
// ...
trailing: IconButton(
icon: Icon(Icons.add_shopping_cart,),
onPressed: () {
// Get the item id
final itemId = itemList[index].id;
// Then do your operations
},
),
);
},
),
After some struggle, i'm able to do what I wanted. A brief explanation can help others.
Here we go:
Render your UI from Model data.
Use providers and apply at appropriate level. I declared a 'List of Items class' and add/delete
methods to perform operations on the List. With help of
ListView,identified the index and added that item to the List
of the provider class.
Cart UI can be rendered from the List of the provider class.
My explanation helps in understanding theoretically first because there is so much of practical code available. This is easily doable provided what is needed and what is available in the flutter are clear.

Keep a list from provider up to date with AnimatedListView

I'm using the Provider library and have a class that extends ChangeNotifier. The class provides an UnmodifiableListView of historicalRosters to my widgets.
I want to create an AnimatedListView that displays these rosters. The animated list supposedly needs a separate list which will tell the widget when the widget to animate in or out new list items.
final GlobalKey<AnimatedListState> _listKey = GlobalKey<AnimatedListState>();
This example uses a model to update both the list attached to the widget's state and the AnimateListState at the same time.
// Inside model
void insert(int index, E item) {
_items.insert(index, item);
_animatedList.insertItem(index);
}
I want to do the same thing but I'm having trouble thinking how. That is, what's a good way I can update the list provided by provider and also change the AnimatedListState.