Reputation: 7990
Intro
We have a ListView
named OrganizationList which contains a ListTile
widget for every item. We use a Text
widget to display the name of the organization inside the ListTile
.
We would like to test if the organization name is displayed correctly and in the correct order.
Our current solution
We have the following assertions:
var organizationA = find
.descendant(
of: find.byType(OrganizationList),
matching: find.byKey(
Key('0'),
),
)
.evaluate()
.first
.widget as Text;
expect(textOrganization.data, 'organization-a');
var organizationB = find
.descendant(
of: find.byType(OrganizationList),
matching: find.byKey(
Key('1'),
),
)
.evaluate()
.first
.widget as Text;
expect(textOrganization.data, 'organization-b');
This feels like a very cumbersome way of testing if the right label is shown for the list items. But I fail to find a more elegant way.
Question
What is a more elegant way in Flutter / Dart to assert both the content of a list item and the order of all items?
Upvotes: 6
Views: 5566
Reputation: 1
Try a for
loop:
// This is for saving a reference to the ListTile from the previous iteration
ListTile? previousListTile;
for (int j = 0; j < aListOfModels.length; j++) {
final organizationA = find.descendant(
of: find.byType(OrganizationList),
matching: find.byKey(
Key('0'),
),
);
// This is important to show the invisible late elements
await widgetTester.scrollUntilVisible(organizationA, tryToFindTheSuitableDelta);
// I suppose that organizationA finds a ListTile widget
ListTile currentListTile = widgetTester.widget<ListTile>(organizationA);
/*
Make your expectations about the content as you like
....
...
*/
// To expect about the order, do the following:
final listTileWidgetList = widgetTester
.widgetList<ListTile>(find.byType(ListTile))
.toList();
if (j > 0) {
// Expect that the currentListTile is the first next ListTile of the previousListTile
expect(listTileWidgetList.indexOf(currentListTile),
equals(listTileWidgetList.indexOf(previousListTile!) + 1));
}
// To allow you to make your expectation about the order in the next iteration
previousListTile = currentListTile;
}
Upvotes: 0
Reputation: 34220
The easiest way to get elements from List and verify is widgetList
, which gives a list of elements of whatever data type we have provided.
Sample test:
Problem: Verify the second item from List
const List<String> listString = [
"Ac",
"Fuel Sensor",
"Power",
"Panic",
"Camera",
"Relay",
"Duty Button",
"Other"
];
Test:
testWidgets('Listview item verify', (WidgetTester tester) async {
await tester.pumpWidget(ListViewApp());
/// Verify OrganizationIte sequence to get and verify title.
OrganizationItem item = tester
.widgetList<OrganizationItem>(find.byType(OrganizationItem))
.elementAt(2);
String data = item.title;
expect("Power", data);
});
App Code:
class ListViewApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Checked Listview',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: MyHomePage(title: 'Flutter Checked Listview'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> _list = [];
@override
void initState() {
setState(() {
for (int i = 0; i < listString.length; i++) {
_list.add('${listString[i]}');
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Listview Sample'),
),
body: ListView.builder(
itemBuilder: (_, int index) {
return OrganizationItem(
title: _list[index],
);
},
itemCount: _list.length,
),
);
}
}
class OrganizationItem extends StatelessWidget {
final String title;
const OrganizationItem({Key? key, required this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
return ListTile(
title: Text(this.title),
);
}
}
Upvotes: 5
Reputation: 31
With my solution you can check if a ListItemWidget at specific position and text is visible(or not):
void checkPosition(int index, SomeObj obj, {bool isOnPosition = true}) {
final listItemFinder = find.byType(ListItemWidget);
final listItem = listItemFinder.evaluate().isEmpty
? null
: listItemFinder.at(index);
if (listItem == null) {
if (isOnPosition) {
fail('List not found');
}
return;
}
final positionText = find.text(obj.text);
expect(find.descendant(of: listItem, matching: positionText),
isOnPosition ? findsOneWidget : findsNothing);
}
Upvotes: 3