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.
This commit is contained in:
parent
44a9b36461
commit
994aab4c78
@ -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() {
|
|||||||
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)) {
|
|
||||||
return selectedColor;
|
|
||||||
}
|
|
||||||
return unselectedColor;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
final Color materialLabelColor = buildMSC(const Color(0x00000000), const Color(0x00000001));
|
const Color selectedColor = Color(0xff00ff00);
|
||||||
const Color labelColor = Color(0x00000002);
|
const Color unselectedColor = Color(0xffff0000);
|
||||||
const Color unselectedLabelColor = Color(0x00000003);
|
final MaterialStateColor labelColor = MaterialStateColor.resolveWith((Set<MaterialState> states) {
|
||||||
|
if (states.contains(MaterialState.selected)) {
|
||||||
|
return selectedColor;
|
||||||
|
}
|
||||||
|
return unselectedColor;
|
||||||
|
});
|
||||||
|
|
||||||
// this is to make sure labelStyles (in TabBar and in TabBarTheme) don't
|
// Test labelColor correctly resolves material states.
|
||||||
// affect label's color. for details: https://github.com/flutter/flutter/pull/109541#issuecomment-1294241417
|
await tester.pumpWidget(boilerplate(
|
||||||
const TextStyle labelStyle = TextStyle(color: Color(0x00000004));
|
child: DefaultTabController(
|
||||||
const TextStyle unselectedLabelStyle = TextStyle(color: Color(0x00000005));
|
length: 2,
|
||||||
|
child: TabBar(
|
||||||
final TabBarTheme materialTabBarTheme = TabBarTheme(
|
labelColor: labelColor,
|
||||||
labelColor: buildMSC(const Color(0x00000006), const Color(0x00000007)),
|
tabs: const <Widget>[
|
||||||
unselectedLabelColor: const Color(0x00000008),
|
Text(tab1),
|
||||||
labelStyle: TextStyle(color: buildMSC(const Color(0x00000009), const Color(0x00000010))),
|
Text(tab2),
|
||||||
unselectedLabelStyle: const TextStyle(color: Color(0x00000011)),
|
],
|
||||||
);
|
|
||||||
const TabBarTheme tabBarTheme = TabBarTheme(
|
|
||||||
labelColor: Color(0x00000012),
|
|
||||||
unselectedLabelColor: Color(0x00000013),
|
|
||||||
labelStyle: TextStyle(color: Color(0x00000014)),
|
|
||||||
unselectedLabelStyle: TextStyle(color: Color(0x00000015)),
|
|
||||||
);
|
|
||||||
const TabBarTheme tabBarThemeWithNullUnselectedLabelColor = TabBarTheme(
|
|
||||||
labelColor: Color(0x00000016),
|
|
||||||
labelStyle: TextStyle(color: Color(0x00000017)),
|
|
||||||
unselectedLabelStyle: TextStyle(color: Color(0x00000018)),
|
|
||||||
);
|
|
||||||
final ThemeData theme = ThemeData(useMaterial3: false);
|
|
||||||
Widget buildTabBar({
|
|
||||||
bool isLabelColorMSC = false,
|
|
||||||
bool isLabelColorNull = false,
|
|
||||||
bool isUnselectedLabelColorNull = false,
|
|
||||||
bool isTabBarThemeMSC = false,
|
|
||||||
bool isTabBarThemeNull = false,
|
|
||||||
bool isTabBarThemeUnselectedLabelColorNull = false,
|
|
||||||
}) {
|
|
||||||
final TabBarTheme? effectiveTheme = isTabBarThemeNull
|
|
||||||
? null : isTabBarThemeUnselectedLabelColorNull
|
|
||||||
? tabBarThemeWithNullUnselectedLabelColor
|
|
||||||
: isTabBarThemeMSC
|
|
||||||
? materialTabBarTheme
|
|
||||||
: tabBarTheme;
|
|
||||||
return boilerplate(
|
|
||||||
child: Theme(
|
|
||||||
data: theme.copyWith(tabBarTheme: effectiveTheme),
|
|
||||||
child: DefaultTabController(
|
|
||||||
length: 2,
|
|
||||||
child: TabBar(
|
|
||||||
labelColor: isLabelColorNull ? null : isLabelColorMSC ? materialLabelColor : labelColor,
|
|
||||||
unselectedLabelColor: isUnselectedLabelColorNull ? null : unselectedLabelColor,
|
|
||||||
labelStyle: labelStyle,
|
|
||||||
unselectedLabelStyle: unselectedLabelStyle,
|
|
||||||
tabs: const <Widget>[Text('1'), Text('2')],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
final IconThemeData selectedTabIcon = IconTheme.of(tester.element(find.text(tab1)));
|
||||||
|
final IconThemeData uselectedTabIcon = IconTheme.of(tester.element(find.text(tab2)));
|
||||||
|
final TextStyle selectedTextStyle = tester.renderObject<RenderParagraph>(find.text(tab1)).text.style!;
|
||||||
|
final TextStyle unselectedTextStyle = tester.renderObject<RenderParagraph>(find.text(tab2)).text.style!;
|
||||||
|
|
||||||
|
expect(selectedTabIcon.color, selectedColor);
|
||||||
|
expect(uselectedTabIcon.color, unselectedColor);
|
||||||
|
expect(selectedTextStyle.color, selectedColor);
|
||||||
|
expect(unselectedTextStyle.color, unselectedColor);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('labelColor & unselectedLabelColor override material state labelColor', (WidgetTester tester) async {
|
||||||
|
const String tab1 = 'Tab 1';
|
||||||
|
const String tab2 = 'Tab 2';
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
Widget buildTabBar({ bool stateColor = true }){
|
||||||
|
return boilerplate(
|
||||||
|
child: DefaultTabController(
|
||||||
|
length: 2,
|
||||||
|
child: TabBar(
|
||||||
|
labelColor: stateColor ? labelColor : selectedColor,
|
||||||
|
unselectedLabelColor: stateColor ? null : unselectedColor,
|
||||||
|
tabs: const <Widget>[
|
||||||
|
Text(tab1),
|
||||||
|
Text(tab2),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
expect(selectedTabIcon.color, selectedStateColor);
|
||||||
// tabBarTheme.unselectedLabelColor
|
expect(uselectedTabIcon.color, unselectedStateColor);
|
||||||
await tester.pumpWidget(buildTabBar(
|
expect(selectedTextStyle.color, selectedStateColor);
|
||||||
isLabelColorNull: true,
|
expect(unselectedTextStyle.color, unselectedStateColor);
|
||||||
isUnselectedLabelColorNull: true,
|
|
||||||
));
|
|
||||||
expect(getTab1Color(), equals(tabBarTheme.labelColor!.value));
|
|
||||||
expect(getTab2Color(), equals(tabBarTheme.unselectedLabelColor!.value));
|
|
||||||
|
|
||||||
// next precedence: labelColor and labelColor at 70% opacity
|
// Test labelColor & unselectedLabelColor override material state labelColor.
|
||||||
await tester.pumpWidget(buildTabBar(
|
await tester.pumpWidget(buildTabBar(stateColor: false));
|
||||||
isUnselectedLabelColorNull: true,
|
|
||||||
isTabBarThemeUnselectedLabelColorNull: true,
|
|
||||||
));
|
|
||||||
expect(getTab1Color(), equals(labelColor.value));
|
|
||||||
expect(getTab2Color(), equals(labelColor.withAlpha(0xB2).value));
|
|
||||||
|
|
||||||
// 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(getTab1Color(), equals(tabBarThemeWithNullUnselectedLabelColor.labelColor!.value));
|
|
||||||
expect(getTab2Color(), equals(tabBarThemeWithNullUnselectedLabelColor.labelColor!.withAlpha(0xB2).value));
|
|
||||||
|
|
||||||
// last precedence: themeData.primaryTextTheme.bodyText1.color and
|
expect(selectedTabIcon.color, selectedColor);
|
||||||
// themeData.primaryTextTheme.bodyText1.color.withAlpha(0xB2)
|
expect(uselectedTabIcon.color, unselectedColor);
|
||||||
await tester.pumpWidget(buildTabBar(
|
expect(selectedTextStyle.color, selectedColor);
|
||||||
isLabelColorNull: true,
|
expect(unselectedTextStyle.color, unselectedColor);
|
||||||
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() {
|
|||||||
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() {
|
|||||||
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);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user