Commit 68728e9f authored by Victor Choueiri's avatar Victor Choueiri Committed by Hans Muller

Better error message when TextField is not in a Material (#16147)

Added a call to debugCheckHasMaterial() at the start of TextField's build method.
parent f0698786
......@@ -10,6 +10,7 @@ import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'debug.dart';
import 'feedback.dart';
import 'ink_well.dart' show InteractiveInkFeature;
import 'input_decorator.dart';
......@@ -42,7 +43,9 @@ export 'package:flutter/services.dart' show TextInputType;
/// extra padding introduced by the decoration to save space for the labels.
///
/// If [decoration] is non-null (which is the default), the text field requires
/// one of its ancestors to be a [Material] widget.
/// one of its ancestors to be a [Material] widget. When the [TextField] is
/// tapped an ink splash that paints on the material is triggered, see
/// [ThemeData.splashFactory].
///
/// To integrate the [TextField] into a [Form] with other [FormField] widgets,
/// consider using [TextFormField].
......@@ -450,6 +453,7 @@ class _TextFieldState extends State<TextField> with AutomaticKeepAliveClientMixi
@override
Widget build(BuildContext context) {
super.build(context); // See AutomaticKeepAliveClientMixin.
assert(debugCheckHasMaterial(context));
final ThemeData themeData = Theme.of(context);
final TextStyle style = widget.style ?? themeData.textTheme.subhead;
final TextEditingController controller = _effectiveController;
......
......@@ -132,14 +132,16 @@ void main() {
return new CupertinoPageRoute<void>(
settings: settings,
builder: (BuildContext context) {
return new CupertinoTabScaffold(
tabBar: _buildTabBar(),
tabBuilder: (BuildContext context, int index) {
return new TextField(
focusNode: focusNodes[index],
autofocus: true,
);
},
return new Material(
child: new CupertinoTabScaffold(
tabBar: _buildTabBar(),
tabBuilder: (BuildContext context, int index) {
return new TextField(
focusNode: focusNodes[index],
autofocus: true,
);
},
),
);
},
);
......
......@@ -7,11 +7,11 @@ import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('TextField works correctly when changing helperText', (WidgetTester tester) async {
await tester.pumpWidget(new MaterialApp(home: const TextField(decoration: const InputDecoration(helperText: 'Awesome'))));
await tester.pumpWidget(new MaterialApp(home: const Material(child: const TextField(decoration: const InputDecoration(helperText: 'Awesome')))));
expect(find.text('Awesome'), findsNWidgets(1));
await tester.pump(const Duration(milliseconds: 100));
expect(find.text('Awesome'), findsNWidgets(1));
await tester.pumpWidget(new MaterialApp(home: const TextField(decoration: const InputDecoration(errorText: 'Awesome'))));
await tester.pumpWidget(new MaterialApp(home: const Material(child: const TextField(decoration: const InputDecoration(errorText: 'Awesome')))));
expect(find.text('Awesome'), findsNWidgets(2));
});
}
\ No newline at end of file
......@@ -2060,5 +2060,13 @@ void main() {
semantics.dispose();
});
testWidgets('TextField throws when not descended from a Material widget', (WidgetTester tester) async {
const Widget textField = const TextField();
await tester.pumpWidget(textField);
final dynamic exception = tester.takeException();
expect(exception, isFlutterError);
expect(exception.toString(), startsWith('No Material widget found.'));
expect(exception.toString(), endsWith(':\n $textField\nThe ancestors of this widget were:\n [root]'));
});
}
......@@ -6,15 +6,16 @@ import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('PhysicalModel - creates a physical model layer when it needs compositing', (WidgetTester tester) async {
await tester.pumpWidget(new Directionality(
textDirection: TextDirection.ltr,
child: new PhysicalModel(
shape: BoxShape.rectangle,
color: Colors.grey,
shadowColor: Colors.red,
elevation: 1.0,
child: new TextField(controller: new TextEditingController()),
textDirection: TextDirection.ltr,
child: new PhysicalModel(
shape: BoxShape.rectangle,
color: Colors.grey,
shadowColor: Colors.red,
elevation: 1.0,
child: new Material(child: new TextField(controller: new TextEditingController())),
),
),
));
);
await tester.pump();
final RenderPhysicalModel renderPhysicalModel = tester.allRenderObjects.firstWhere((RenderObject object) => object is RenderPhysicalModel);
......
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