255 lines
9.1 KiB
Dart
255 lines
9.1 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'package:flutter/widgets.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
class TestRoute extends PageRouteBuilder<void> {
|
|
TestRoute(Widget child) : super(
|
|
pageBuilder: (BuildContext _, Animation<double> __, Animation<double> ___) => child,
|
|
);
|
|
}
|
|
|
|
class IconTextBox extends StatelessWidget {
|
|
const IconTextBox(this.text, { Key key }) : super(key: key);
|
|
final String text;
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Container(
|
|
alignment: Alignment.center,
|
|
child: Row(
|
|
children: <Widget>[const Icon(IconData(0x41, fontFamily: 'Roboto')), Text(text)],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
testWidgets('InheritedTheme.captureAll()', (WidgetTester tester) async {
|
|
const double fontSize = 32;
|
|
const double iconSize = 48;
|
|
const Color textColor = Color(0xFF00FF00);
|
|
const Color iconColor = Color(0xFF0000FF);
|
|
bool useCaptureAll = false;
|
|
BuildContext navigatorContext;
|
|
|
|
Widget buildFrame() {
|
|
return WidgetsApp(
|
|
color: const Color(0xFFFFFFFF),
|
|
onGenerateRoute: (RouteSettings settings) {
|
|
return TestRoute(
|
|
// The outer DefaultTextStyle and IconTheme widgets must have
|
|
// no effect on the test because InheritedTheme.captureAll()
|
|
// is required to only save the closest InheritedTheme ancestors.
|
|
DefaultTextStyle(
|
|
style: const TextStyle(fontSize: iconSize, color: iconColor),
|
|
child: IconTheme(
|
|
data: const IconThemeData(size: fontSize, color: textColor),
|
|
// The inner DefaultTextStyle and IconTheme widgets define
|
|
// InheritedThemes that captureAll() will wrap() around
|
|
// TestRoute's IconTextBox child.
|
|
child: DefaultTextStyle(
|
|
style: const TextStyle(fontSize: fontSize, color: textColor),
|
|
child: IconTheme(
|
|
data: const IconThemeData(size: iconSize, color: iconColor),
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
return GestureDetector(
|
|
behavior: HitTestBehavior.opaque,
|
|
onTap: () {
|
|
navigatorContext = context;
|
|
Navigator.of(context).push(
|
|
TestRoute(
|
|
useCaptureAll
|
|
? InheritedTheme.captureAll(context, const IconTextBox('Hello'))
|
|
: const IconTextBox('Hello')
|
|
),
|
|
);
|
|
},
|
|
child: const IconTextBox('Tap'),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
TextStyle getIconStyle() {
|
|
return tester.widget<RichText>(
|
|
find.descendant(
|
|
of: find.byType(Icon),
|
|
matching: find.byType(RichText),
|
|
),
|
|
).text.style;
|
|
}
|
|
|
|
TextStyle getTextStyle(String text) {
|
|
return tester.widget<RichText>(
|
|
find.descendant(
|
|
of: find.text(text),
|
|
matching: find.byType(RichText),
|
|
),
|
|
).text.style;
|
|
}
|
|
|
|
useCaptureAll = false;
|
|
await tester.pumpWidget(buildFrame());
|
|
expect(find.text('Tap'), findsOneWidget);
|
|
expect(find.text('Hello'), findsNothing);
|
|
expect(getTextStyle('Tap').color, textColor);
|
|
expect(getTextStyle('Tap').fontSize, fontSize);
|
|
expect(getIconStyle().color, iconColor);
|
|
expect(getIconStyle().fontSize, iconSize);
|
|
|
|
// Tap to show the TestRoute
|
|
await tester.tap(find.text('Tap'));
|
|
await tester.pumpAndSettle(); // route transition
|
|
expect(find.text('Tap'), findsNothing);
|
|
expect(find.text('Hello'), findsOneWidget);
|
|
// The new route's text and icons will NOT inherit the DefaultTextStyle or
|
|
// IconTheme values.
|
|
expect(getTextStyle('Hello').color, isNot(textColor));
|
|
expect(getTextStyle('Hello').fontSize, isNot(fontSize));
|
|
expect(getIconStyle().color, isNot(iconColor));
|
|
expect(getIconStyle().fontSize, isNot(iconSize));
|
|
|
|
// Return to the home route
|
|
useCaptureAll = true;
|
|
Navigator.of(navigatorContext).pop();
|
|
await tester.pumpAndSettle(); // route transition
|
|
|
|
// Verify that all is the same as it was when the test started
|
|
expect(find.text('Tap'), findsOneWidget);
|
|
expect(find.text('Hello'), findsNothing);
|
|
expect(getTextStyle('Tap').color, textColor);
|
|
expect(getTextStyle('Tap').fontSize, fontSize);
|
|
expect(getIconStyle().color, iconColor);
|
|
expect(getIconStyle().fontSize, iconSize);
|
|
|
|
// Tap to show the TestRoute. The test route's IconTextBox will have been
|
|
// wrapped with InheritedTheme.captureAll().
|
|
await tester.tap(find.text('Tap'));
|
|
await tester.pumpAndSettle(); // route transition
|
|
expect(find.text('Tap'), findsNothing);
|
|
expect(find.text('Hello'), findsOneWidget);
|
|
// The new route's text and icons will inherit the DefaultTextStyle or
|
|
// IconTheme values because captureAll.
|
|
expect(getTextStyle('Hello').color, textColor);
|
|
expect(getTextStyle('Hello').fontSize, fontSize);
|
|
expect(getIconStyle().color, iconColor);
|
|
expect(getIconStyle().fontSize, iconSize);
|
|
});
|
|
|
|
testWidgets('InheritedTheme.captureAll() multiple IconTheme ancestors', (WidgetTester tester) async {
|
|
// This is a regression test for https://github.com/flutter/flutter/issues/39087
|
|
|
|
const Color outerColor = Color(0xFF0000FF);
|
|
const Color innerColor = Color(0xFF00FF00);
|
|
const double iconSize = 48;
|
|
final Key icon1 = UniqueKey();
|
|
final Key icon2 = UniqueKey();
|
|
|
|
await tester.pumpWidget(
|
|
WidgetsApp(
|
|
color: const Color(0xFFFFFFFF),
|
|
onGenerateRoute: (RouteSettings settings) {
|
|
return TestRoute(
|
|
IconTheme(
|
|
data: const IconThemeData(color: outerColor),
|
|
child: IconTheme(
|
|
data: const IconThemeData(size: iconSize, color: innerColor),
|
|
child: Center(
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: <Widget>[
|
|
Icon(const IconData(0x41, fontFamily: 'Roboto'), key: icon1),
|
|
Builder(
|
|
builder: (BuildContext context) {
|
|
// The same IconThemes are visible from this context
|
|
// and the context that the widget returned by captureAll()
|
|
// is built in. So only the inner green IconTheme should
|
|
// apply to the icon, i.e. both icons will be big and green.
|
|
return InheritedTheme.captureAll(
|
|
context,
|
|
Icon(const IconData(0x41, fontFamily: 'Roboto'), key: icon2),
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
);
|
|
|
|
TextStyle getIconStyle(Key key) {
|
|
return tester.widget<RichText>(
|
|
find.descendant(
|
|
of: find.byKey(key),
|
|
matching: find.byType(RichText),
|
|
),
|
|
).text.style;
|
|
}
|
|
|
|
expect(getIconStyle(icon1).color, innerColor);
|
|
expect(getIconStyle(icon1).fontSize, iconSize);
|
|
expect(getIconStyle(icon2).color, innerColor);
|
|
expect(getIconStyle(icon2).fontSize, iconSize);
|
|
});
|
|
|
|
testWidgets('InheritedTheme.captureAll() multiple DefaultTextStyle ancestors', (WidgetTester tester) async {
|
|
// This is a regression test for https://github.com/flutter/flutter/issues/39087
|
|
|
|
const Color textColor = Color(0xFF00FF00);
|
|
|
|
await tester.pumpWidget(
|
|
WidgetsApp(
|
|
color: const Color(0xFFFFFFFF),
|
|
onGenerateRoute: (RouteSettings settings) {
|
|
return TestRoute(
|
|
DefaultTextStyle(
|
|
style: const TextStyle(fontSize: 48),
|
|
child: DefaultTextStyle(
|
|
style: const TextStyle(color: textColor),
|
|
child: Row(
|
|
children: <Widget>[
|
|
const Text('Hello'),
|
|
Builder(
|
|
builder: (BuildContext context) {
|
|
return InheritedTheme.captureAll(context, const Text('World'));
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
);
|
|
|
|
TextStyle getTextStyle(String text) {
|
|
return tester.widget<RichText>(
|
|
find.descendant(
|
|
of: find.text(text),
|
|
matching: find.byType(RichText),
|
|
),
|
|
).text.style;
|
|
}
|
|
|
|
expect(getTextStyle('Hello').fontSize, null);
|
|
expect(getTextStyle('Hello').color, textColor);
|
|
expect(getTextStyle('World').fontSize, null);
|
|
expect(getTextStyle('World').color, textColor);
|
|
});
|
|
}
|