Unverified Commit 994aab4c authored by Taha Tesser's avatar Taha Tesser Committed by GitHub

Update & improve `TabBar.labelColor` tests (#133668)

fixes [Improve `TabBar.labelColor` tests](https://github.com/flutter/flutter/issues/133665)

While working on a fix for https://github.com/flutter/flutter/issues/109484, I found the existing test could use some improvement first.
parent 44a9b364
...@@ -1216,4 +1216,77 @@ void main() { ...@@ -1216,4 +1216,77 @@ void main() {
tabBarBox = tester.firstRenderObject<RenderBox>(find.byType(TabBar)); tabBarBox = tester.firstRenderObject<RenderBox>(find.byType(TabBar));
expect(tabBarBox,paints..line(color: tabBarThemeIndicatorColor)); expect(tabBarBox,paints..line(color: tabBarThemeIndicatorColor));
}); });
testWidgets('TabBarTheme.labelColor resolves material states', (WidgetTester tester) async {
const Color selectedColor = Color(0xff00ff00);
const Color unselectedColor = Color(0xffff0000);
final MaterialStateColor labelColor = MaterialStateColor.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return selectedColor;
}
return unselectedColor;
});
final TabBarTheme tabBarTheme = TabBarTheme(labelColor: labelColor);
// Test labelColor correctly resolves material states.
await tester.pumpWidget(buildTabBar(tabBarTheme: tabBarTheme));
final IconThemeData selectedTabIcon = IconTheme.of(tester.element(find.text(_tab1Text)));
final IconThemeData uselectedTabIcon = IconTheme.of(tester.element(find.text(_tab2Text)));
final TextStyle selectedTextStyle = tester.renderObject<RenderParagraph>(find.text(_tab1Text)).text.style!;
final TextStyle unselectedTextStyle = tester.renderObject<RenderParagraph>(find.text(_tab2Text)).text.style!;
expect(selectedTabIcon.color, selectedColor);
expect(uselectedTabIcon.color, unselectedColor);
expect(selectedTextStyle.color, selectedColor);
expect(unselectedTextStyle.color, unselectedColor);
});
testWidgets('TabBarTheme.labelColor & TabBarTheme.unselectedLabelColor override material state TabBarTheme.labelColor',
(WidgetTester tester) async {
const Color selectedStateColor = Color(0xff00ff00);
const Color unselectedStateColor = Color(0xffff0000);
final MaterialStateColor labelColor = MaterialStateColor.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return selectedStateColor;
}
return unselectedStateColor;
});
const Color selectedColor = Color(0xff00ffff);
const Color unselectedColor = Color(0xffff12ff);
TabBarTheme tabBarTheme = TabBarTheme(labelColor: labelColor);
// Test material state label color.
await tester.pumpWidget(buildTabBar(tabBarTheme: tabBarTheme));
IconThemeData selectedTabIcon = IconTheme.of(tester.element(find.text(_tab1Text)));
IconThemeData uselectedTabIcon = IconTheme.of(tester.element(find.text(_tab2Text)));
TextStyle selectedTextStyle = tester.renderObject<RenderParagraph>(find.text(_tab1Text)).text.style!;
TextStyle unselectedTextStyle = tester.renderObject<RenderParagraph>(find.text(_tab2Text)).text.style!;
expect(selectedTabIcon.color, selectedStateColor);
expect(uselectedTabIcon.color, unselectedStateColor);
expect(selectedTextStyle.color, selectedStateColor);
expect(unselectedTextStyle.color, unselectedStateColor);
// Test labelColor & unselectedLabelColor override material state labelColor.
tabBarTheme = const TabBarTheme(
labelColor: selectedColor,
unselectedLabelColor: unselectedColor,
);
await tester.pumpWidget(buildTabBar(tabBarTheme: tabBarTheme));
await tester.pumpAndSettle();
selectedTabIcon = IconTheme.of(tester.element(find.text(_tab1Text)));
uselectedTabIcon = IconTheme.of(tester.element(find.text(_tab2Text)));
selectedTextStyle = tester.renderObject<RenderParagraph>(find.text(_tab1Text)).text.style!;
unselectedTextStyle = tester.renderObject<RenderParagraph>(find.text(_tab2Text)).text.style!;
expect(selectedTabIcon.color, selectedColor);
expect(uselectedTabIcon.color, unselectedColor);
expect(selectedTextStyle.color, selectedColor);
expect(unselectedTextStyle.color, unselectedColor);
});
} }
...@@ -4511,139 +4511,99 @@ void main() { ...@@ -4511,139 +4511,99 @@ void main() {
expect(iconTheme.color, equals(selectedTabColor)); expect(iconTheme.color, equals(selectedTabColor));
}); });
testWidgets('TabBar colors labels correctly', (WidgetTester tester) async { testWidgets('TabBar.labelColor resolves material states', (WidgetTester tester) async {
MaterialStateColor buildMSC(Color selectedColor, Color unselectedColor) { const String tab1 = 'Tab 1';
return MaterialStateColor const String tab2 = 'Tab 2';
.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) { const Color selectedColor = Color(0xff00ff00);
return selectedColor; const Color unselectedColor = Color(0xffff0000);
} final MaterialStateColor labelColor = MaterialStateColor.resolveWith((Set<MaterialState> states) {
return unselectedColor; if (states.contains(MaterialState.selected)) {
}); return selectedColor;
} }
return unselectedColor;
});
final Color materialLabelColor = buildMSC(const Color(0x00000000), const Color(0x00000001)); // Test labelColor correctly resolves material states.
const Color labelColor = Color(0x00000002); await tester.pumpWidget(boilerplate(
const Color unselectedLabelColor = Color(0x00000003); child: DefaultTabController(
length: 2,
// this is to make sure labelStyles (in TabBar and in TabBarTheme) don't child: TabBar(
// affect label's color. for details: https://github.com/flutter/flutter/pull/109541#issuecomment-1294241417 labelColor: labelColor,
const TextStyle labelStyle = TextStyle(color: Color(0x00000004)); tabs: const <Widget>[
const TextStyle unselectedLabelStyle = TextStyle(color: Color(0x00000005)); Text(tab1),
Text(tab2),
final TabBarTheme materialTabBarTheme = TabBarTheme( ],
labelColor: buildMSC(const Color(0x00000006), const Color(0x00000007)), ),
unselectedLabelColor: const Color(0x00000008), ),
labelStyle: TextStyle(color: buildMSC(const Color(0x00000009), const Color(0x00000010))), ));
unselectedLabelStyle: const TextStyle(color: Color(0x00000011)),
); final IconThemeData selectedTabIcon = IconTheme.of(tester.element(find.text(tab1)));
const TabBarTheme tabBarTheme = TabBarTheme( final IconThemeData uselectedTabIcon = IconTheme.of(tester.element(find.text(tab2)));
labelColor: Color(0x00000012), final TextStyle selectedTextStyle = tester.renderObject<RenderParagraph>(find.text(tab1)).text.style!;
unselectedLabelColor: Color(0x00000013), final TextStyle unselectedTextStyle = tester.renderObject<RenderParagraph>(find.text(tab2)).text.style!;
labelStyle: TextStyle(color: Color(0x00000014)),
unselectedLabelStyle: TextStyle(color: Color(0x00000015)), expect(selectedTabIcon.color, selectedColor);
); expect(uselectedTabIcon.color, unselectedColor);
const TabBarTheme tabBarThemeWithNullUnselectedLabelColor = TabBarTheme( expect(selectedTextStyle.color, selectedColor);
labelColor: Color(0x00000016), expect(unselectedTextStyle.color, unselectedColor);
labelStyle: TextStyle(color: Color(0x00000017)), });
unselectedLabelStyle: TextStyle(color: Color(0x00000018)),
); testWidgets('labelColor & unselectedLabelColor override material state labelColor', (WidgetTester tester) async {
final ThemeData theme = ThemeData(useMaterial3: false); const String tab1 = 'Tab 1';
Widget buildTabBar({ const String tab2 = 'Tab 2';
bool isLabelColorMSC = false,
bool isLabelColorNull = false, const Color selectedStateColor = Color(0xff00ff00);
bool isUnselectedLabelColorNull = false, const Color unselectedStateColor = Color(0xffff0000);
bool isTabBarThemeMSC = false, final MaterialStateColor labelColor = MaterialStateColor.resolveWith((Set<MaterialState> states) {
bool isTabBarThemeNull = false, if (states.contains(MaterialState.selected)) {
bool isTabBarThemeUnselectedLabelColorNull = false, return selectedStateColor;
}) { }
final TabBarTheme? effectiveTheme = isTabBarThemeNull return unselectedStateColor;
? null : isTabBarThemeUnselectedLabelColorNull });
? tabBarThemeWithNullUnselectedLabelColor const Color selectedColor = Color(0xff00ffff);
: isTabBarThemeMSC const Color unselectedColor = Color(0xffff12ff);
? materialTabBarTheme
: tabBarTheme; Widget buildTabBar({ bool stateColor = true }){
return boilerplate( return boilerplate(
child: Theme( child: DefaultTabController(
data: theme.copyWith(tabBarTheme: effectiveTheme), length: 2,
child: DefaultTabController( child: TabBar(
length: 2, labelColor: stateColor ? labelColor : selectedColor,
child: TabBar( unselectedLabelColor: stateColor ? null : unselectedColor,
labelColor: isLabelColorNull ? null : isLabelColorMSC ? materialLabelColor : labelColor, tabs: const <Widget>[
unselectedLabelColor: isUnselectedLabelColorNull ? null : unselectedLabelColor, Text(tab1),
labelStyle: labelStyle, Text(tab2),
unselectedLabelStyle: unselectedLabelStyle, ],
tabs: const <Widget>[Text('1'), Text('2')],
),
),
), ),
); ));
} }
// Returns int `color.value`s instead of Color `color`s to prevent false // Test material state label color.
// negative due to object types being different (Color != MaterialStateColor)
// when `expect`ing.
int? getTab1Color() => IconTheme.of(tester.element(find.text('1'))).color?.value;
int? getTab2Color() => IconTheme.of(tester.element(find.text('2'))).color?.value;
int getSelectedColor(Color color) => (color as MaterialStateColor)
.resolve(<MaterialState>{MaterialState.selected}).value;
int getUnselectedColor(Color color) => (color as MaterialStateColor)
.resolve(<MaterialState>{}).value;
// highest precedence: labelColor as MaterialStateColor
await tester.pumpWidget(buildTabBar(isLabelColorMSC: true));
expect(getTab1Color(), equals(getSelectedColor(materialLabelColor)));
expect(getTab2Color(), equals(getUnselectedColor(materialLabelColor)));
// next precedence: labelColor and unselectedLabelColor
await tester.pumpWidget(buildTabBar()); await tester.pumpWidget(buildTabBar());
expect(getTab1Color(), equals(labelColor.value));
expect(getTab2Color(), equals(unselectedLabelColor.value));
// next precedence: tabBarTheme.labelColor as MaterialStateColor IconThemeData selectedTabIcon = IconTheme.of(tester.element(find.text(tab1)));
await tester.pumpWidget(buildTabBar( IconThemeData uselectedTabIcon = IconTheme.of(tester.element(find.text(tab2)));
isLabelColorNull: true, TextStyle selectedTextStyle = tester.renderObject<RenderParagraph>(find.text(tab1)).text.style!;
isTabBarThemeMSC: true, TextStyle unselectedTextStyle = tester.renderObject<RenderParagraph>(find.text(tab2)).text.style!;
));
expect(getTab1Color(), equals(getSelectedColor(materialTabBarTheme.labelColor!)));
expect(getTab2Color(), equals(getUnselectedColor(materialTabBarTheme.labelColor!)));
// next precedence: tabBarTheme.labelColor and
// tabBarTheme.unselectedLabelColor
await tester.pumpWidget(buildTabBar(
isLabelColorNull: true,
isUnselectedLabelColorNull: true,
));
expect(getTab1Color(), equals(tabBarTheme.labelColor!.value));
expect(getTab2Color(), equals(tabBarTheme.unselectedLabelColor!.value));
// next precedence: labelColor and labelColor at 70% opacity expect(selectedTabIcon.color, selectedStateColor);
await tester.pumpWidget(buildTabBar( expect(uselectedTabIcon.color, unselectedStateColor);
isUnselectedLabelColorNull: true, expect(selectedTextStyle.color, selectedStateColor);
isTabBarThemeUnselectedLabelColorNull: true, expect(unselectedTextStyle.color, unselectedStateColor);
));
expect(getTab1Color(), equals(labelColor.value)); // Test labelColor & unselectedLabelColor override material state labelColor.
expect(getTab2Color(), equals(labelColor.withAlpha(0xB2).value)); await tester.pumpWidget(buildTabBar(stateColor: false));
// next precedence: tabBarTheme.labelColor and tabBarTheme.labelColor at 70% selectedTabIcon = IconTheme.of(tester.element(find.text(tab1)));
// opacity uselectedTabIcon = IconTheme.of(tester.element(find.text(tab2)));
await tester.pumpWidget(buildTabBar( selectedTextStyle = tester.renderObject<RenderParagraph>(find.text(tab1)).text.style!;
isLabelColorNull: true, unselectedTextStyle = tester.renderObject<RenderParagraph>(find.text(tab2)).text.style!;
isUnselectedLabelColorNull: true,
isTabBarThemeUnselectedLabelColorNull: true, expect(selectedTabIcon.color, selectedColor);
)); expect(uselectedTabIcon.color, unselectedColor);
expect(getTab1Color(), equals(tabBarThemeWithNullUnselectedLabelColor.labelColor!.value)); expect(selectedTextStyle.color, selectedColor);
expect(getTab2Color(), equals(tabBarThemeWithNullUnselectedLabelColor.labelColor!.withAlpha(0xB2).value)); expect(unselectedTextStyle.color, unselectedColor);
// last precedence: themeData.primaryTextTheme.bodyText1.color and
// themeData.primaryTextTheme.bodyText1.color.withAlpha(0xB2)
await tester.pumpWidget(buildTabBar(
isLabelColorNull: true,
isUnselectedLabelColorNull: true,
isTabBarThemeNull: true,
));
expect(getTab1Color(), equals(theme.primaryTextTheme.bodyText1!.color!.value));
expect(getTab2Color(), equals(theme.primaryTextTheme.bodyText1!.color!.withAlpha(0xB2).value));
}); });
testWidgets('Replacing the tabController after disposing the old one', (WidgetTester tester) async { testWidgets('Replacing the tabController after disposing the old one', (WidgetTester tester) async {
...@@ -5015,19 +4975,19 @@ void main() { ...@@ -5015,19 +4975,19 @@ void main() {
late Color firstColor; late Color firstColor;
late Color secondColor; late Color secondColor;
Widget buildTabBar({bool labelColorIsMaterialStateColor = false}) { Widget buildTabBar({ bool stateColor = false }) {
final Color labelColor = labelColorIsMaterialStateColor final Color labelColor = stateColor
? MaterialStateColor ? MaterialStateColor
.resolveWith((Set<MaterialState> states) { .resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) { if (states.contains(MaterialState.selected)) {
return Colors.white; return Colors.white;
} else { } else {
// this is a third color to also test if unselectedLabelColor // this is a third color to also test if unselectedLabelColor
// is ignored when labelColor is MaterialStateColor // is ignored when labelColor is MaterialStateColor
return Colors.transparent; return Colors.transparent;
} }
}) })
: Colors.white; : Colors.white;
return boilerplate( return boilerplate(
child: TabBar( child: TabBar(
...@@ -5087,7 +5047,7 @@ void main() { ...@@ -5087,7 +5047,7 @@ void main() {
controller.index = 0; controller.index = 0;
await tester.pump(); await tester.pump();
await tester.pumpWidget(buildTabBar(labelColorIsMaterialStateColor: true)); await tester.pumpWidget(buildTabBar(stateColor: true));
await testLabelColor(selectedColor: Colors.white, unselectedColor: Colors.transparent); await testLabelColor(selectedColor: Colors.white, unselectedColor: Colors.transparent);
}); });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment