blob: 92c5fb6803e91d8521178fdccd74b04832a0bb16 [file] [log] [blame] [edit]
// 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/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
group('SafeArea', () {
testWidgets('SafeArea - basic', (WidgetTester tester) async {
await tester.pumpWidget(
const MediaQuery(
data: MediaQueryData(padding: EdgeInsets.all(20.0)),
child: SafeArea(
left: false,
child: Placeholder(),
),
),
);
expect(tester.getTopLeft(find.byType(Placeholder)), const Offset(0.0, 20.0));
expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(780.0, 580.0));
});
testWidgets('SafeArea - with minimums', (WidgetTester tester) async {
await tester.pumpWidget(
const MediaQuery(
data: MediaQueryData(padding: EdgeInsets.all(20.0)),
child: SafeArea(
top: false,
minimum: EdgeInsets.fromLTRB(0.0, 10.0, 20.0, 30.0),
child: Placeholder(),
),
),
);
expect(tester.getTopLeft(find.byType(Placeholder)), const Offset(20.0, 10.0));
expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(780.0, 570.0));
});
testWidgets('SafeArea - nested', (WidgetTester tester) async {
await tester.pumpWidget(
const MediaQuery(
data: MediaQueryData(padding: EdgeInsets.all(20.0)),
child: SafeArea(
top: false,
child: SafeArea(
right: false,
child: Placeholder(),
),
),
),
);
expect(tester.getTopLeft(find.byType(Placeholder)), const Offset(20.0, 20.0));
expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(780.0, 580.0));
});
testWidgets('SafeArea - changing', (WidgetTester tester) async {
const Widget child = SafeArea(
bottom: false,
child: SafeArea(
left: false,
bottom: false,
child: Placeholder(),
),
);
await tester.pumpWidget(
const MediaQuery(
data: MediaQueryData(padding: EdgeInsets.all(20.0)),
child: child,
),
);
expect(tester.getTopLeft(find.byType(Placeholder)), const Offset(20.0, 20.0));
expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(780.0, 600.0));
await tester.pumpWidget(
const MediaQuery(
data: MediaQueryData(padding: EdgeInsets.only(
left: 100.0,
top: 30.0,
bottom: 40.0,
)),
child: child,
),
);
expect(tester.getTopLeft(find.byType(Placeholder)), const Offset(100.0, 30.0));
expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(800.0, 600.0));
});
testWidgets('SafeArea - properties', (WidgetTester tester) async {
final SafeArea child = SafeArea(
right: false,
bottom: false,
child: Container(),
);
final DiagnosticPropertiesBuilder properties = DiagnosticPropertiesBuilder();
child.debugFillProperties(properties);
expect(properties.properties.any((DiagnosticsNode n) => n is FlagProperty && n.toString() == 'avoid left padding'), true);
expect(properties.properties.any((DiagnosticsNode n) => n is FlagProperty && n.toString() == 'avoid right padding'), false);
expect(properties.properties.any((DiagnosticsNode n) => n is FlagProperty && n.toString() == 'avoid top padding'), true);
expect(properties.properties.any((DiagnosticsNode n) => n is FlagProperty && n.toString() == 'avoid bottom padding'), false);
});
group('SafeArea maintains bottom viewPadding when specified for consumed bottom padding', () {
Widget boilerplate(Widget child) {
return Localizations(
locale: const Locale('en', 'us'),
delegates: const <LocalizationsDelegate<dynamic>>[
DefaultWidgetsLocalizations.delegate,
DefaultMaterialLocalizations.delegate,
],
child: Directionality(textDirection: TextDirection.ltr, child: child),
);
}
testWidgets('SafeArea alone.', (WidgetTester tester) async {
final Widget child = boilerplate(SafeArea(
maintainBottomViewPadding: true,
child: Column(
children: const <Widget>[
Expanded(child: Placeholder()),
],
),
));
await tester.pumpWidget(
MediaQuery(
data: const MediaQueryData(
padding: EdgeInsets.symmetric(vertical: 20.0),
viewPadding: EdgeInsets.only(bottom: 20.0),
),
child: child,
),
);
final Offset initialPoint = tester.getCenter(find.byType(Placeholder));
// Consume bottom padding - as if by the keyboard opening
await tester.pumpWidget(
MediaQuery(
data: const MediaQueryData(
padding: EdgeInsets.only(top: 20.0),
viewPadding: EdgeInsets.only(bottom: 20.0),
viewInsets: EdgeInsets.only(bottom: 300.0),
),
child: child,
),
);
final Offset finalPoint = tester.getCenter(find.byType(Placeholder));
expect(initialPoint, finalPoint);
});
testWidgets('SafeArea alone - partial ViewInsets consume Padding', (WidgetTester tester) async {
final Widget child = boilerplate(SafeArea(
maintainBottomViewPadding: true,
child: Column(
children: const <Widget>[
Expanded(child: Placeholder()),
],
),
));
await tester.pumpWidget(
MediaQuery(
data: const MediaQueryData(
viewPadding: EdgeInsets.only(bottom: 20.0),
),
child: child,
),
);
final Offset initialPoint = tester.getCenter(find.byType(Placeholder));
// Consume bottom padding - as if by the keyboard opening
await tester.pumpWidget(
MediaQuery(
data: const MediaQueryData(
viewPadding: EdgeInsets.only(bottom: 20.0),
viewInsets: EdgeInsets.only(bottom: 10.0),
),
child: child,
),
);
final Offset finalPoint = tester.getCenter(find.byType(Placeholder));
expect(initialPoint, finalPoint);
});
testWidgets('SafeArea with nested Scaffold', (WidgetTester tester) async {
final Widget child = boilerplate(SafeArea(
maintainBottomViewPadding: true,
child: Scaffold(
resizeToAvoidBottomInset: false,
body: Column(
children: const <Widget>[
Expanded(child: Placeholder()),
],
),
),
));
await tester.pumpWidget(
MediaQuery(
data: const MediaQueryData(
padding: EdgeInsets.symmetric(vertical: 20.0),
viewPadding: EdgeInsets.only(bottom: 20.0),
),
child: child,
),
);
final Offset initialPoint = tester.getCenter(find.byType(Placeholder));
// Consume bottom padding - as if by the keyboard opening
await tester.pumpWidget(
MediaQuery(
data: const MediaQueryData(
padding: EdgeInsets.only(top: 20.0),
viewPadding: EdgeInsets.only(bottom: 20.0),
viewInsets: EdgeInsets.only(bottom: 300.0),
),
child: child,
),
);
final Offset finalPoint = tester.getCenter(find.byType(Placeholder));
expect(initialPoint, finalPoint);
});
testWidgets('SafeArea with nested Scaffold - partial ViewInsets consume Padding', (WidgetTester tester) async {
final Widget child = boilerplate(SafeArea(
maintainBottomViewPadding: true,
child: Scaffold(
resizeToAvoidBottomInset: false,
body: Column(
children: const <Widget>[
Expanded(child: Placeholder()),
],
),
),
));
await tester.pumpWidget(
MediaQuery(
data: const MediaQueryData(
viewPadding: EdgeInsets.only(bottom: 20.0),
),
child: child,
),
);
final Offset initialPoint = tester.getCenter(find.byType(Placeholder));
// Consume bottom padding - as if by the keyboard opening
await tester.pumpWidget(
MediaQuery(
data: const MediaQueryData(
viewPadding: EdgeInsets.only(bottom: 20.0),
viewInsets: EdgeInsets.only(bottom: 10.0),
),
child: child,
),
);
final Offset finalPoint = tester.getCenter(find.byType(Placeholder));
expect(initialPoint, finalPoint);
});
});
});
group('SliverSafeArea', () {
Widget buildWidget(EdgeInsets mediaPadding, Widget sliver) {
return MediaQuery(
data: MediaQueryData(padding: mediaPadding),
child: Directionality(
textDirection: TextDirection.ltr,
child: Viewport(
offset: ViewportOffset.fixed(0.0),
slivers: <Widget>[
const SliverToBoxAdapter(child: SizedBox(width: 800.0, height: 100.0, child: Text('before'))),
sliver,
const SliverToBoxAdapter(child: SizedBox(width: 800.0, height: 100.0, child: Text('after'))),
],
),
),
);
}
void verify(WidgetTester tester, List<Rect> expectedRects) {
final List<Rect> testAnswers = tester.renderObjectList<RenderBox>(find.byType(SizedBox)).map<Rect>(
(RenderBox target) {
final Offset topLeft = target.localToGlobal(Offset.zero);
final Offset bottomRight = target.localToGlobal(target.size.bottomRight(Offset.zero));
return Rect.fromPoints(topLeft, bottomRight);
},
).toList();
expect(testAnswers, equals(expectedRects));
}
testWidgets('SliverSafeArea - basic', (WidgetTester tester) async {
await tester.pumpWidget(
buildWidget(
const EdgeInsets.all(20.0),
const SliverSafeArea(
left: false,
sliver: SliverToBoxAdapter(child: SizedBox(width: 800.0, height: 100.0, child: Text('padded'))),
),
),
);
verify(tester, <Rect>[
const Rect.fromLTWH(0.0, 0.0, 800.0, 100.0),
const Rect.fromLTWH(0.0, 120.0, 780.0, 100.0),
const Rect.fromLTWH(0.0, 240.0, 800.0, 100.0),
]);
});
testWidgets('SliverSafeArea - basic', (WidgetTester tester) async {
await tester.pumpWidget(
buildWidget(
const EdgeInsets.all(20.0),
const SliverSafeArea(
top: false,
minimum: EdgeInsets.fromLTRB(0.0, 10.0, 20.0, 30.0),
sliver: SliverToBoxAdapter(child: SizedBox(width: 800.0, height: 100.0, child: Text('padded'))),
),
),
);
verify(tester, <Rect>[
const Rect.fromLTWH(0.0, 0.0, 800.0, 100.0),
const Rect.fromLTWH(20.0, 110.0, 760.0, 100.0),
const Rect.fromLTWH(0.0, 240.0, 800.0, 100.0),
]);
});
testWidgets('SliverSafeArea - nested', (WidgetTester tester) async {
await tester.pumpWidget(
buildWidget(
const EdgeInsets.all(20.0),
const SliverSafeArea(
top: false,
sliver: SliverSafeArea(
right: false,
sliver: SliverToBoxAdapter(child: SizedBox(width: 800.0, height: 100.0, child: Text('padded'))),
),
),
),
);
verify(tester, <Rect>[
const Rect.fromLTWH(0.0, 0.0, 800.0, 100.0),
const Rect.fromLTWH(20.0, 120.0, 760.0, 100.0),
const Rect.fromLTWH(0.0, 240.0, 800.0, 100.0),
]);
});
testWidgets('SliverSafeArea - changing', (WidgetTester tester) async {
const Widget sliver = SliverSafeArea(
bottom: false,
sliver: SliverSafeArea(
left: false,
bottom: false,
sliver: SliverToBoxAdapter(child: SizedBox(width: 800.0, height: 100.0, child: Text('padded'))),
),
);
await tester.pumpWidget(
buildWidget(
const EdgeInsets.all(20.0),
sliver,
),
);
verify(tester, <Rect>[
const Rect.fromLTWH(0.0, 0.0, 800.0, 100.0),
const Rect.fromLTWH(20.0, 120.0, 760.0, 100.0),
const Rect.fromLTWH(0.0, 220.0, 800.0, 100.0),
]);
await tester.pumpWidget(
buildWidget(
const EdgeInsets.only(
left: 100.0,
top: 30.0,
bottom: 40.0,
),
sliver,
),
);
verify(tester, <Rect>[
const Rect.fromLTWH(0.0, 0.0, 800.0, 100.0),
const Rect.fromLTWH(100.0, 130.0, 700.0, 100.0),
const Rect.fromLTWH(0.0, 230.0, 800.0, 100.0),
]);
});
});
testWidgets('SliverSafeArea - properties', (WidgetTester tester) async {
const SliverSafeArea child = SliverSafeArea(
right: false,
bottom: false,
sliver: SliverToBoxAdapter(child: SizedBox(width: 800.0, height: 100.0, child: Text('padded'))),
);
final DiagnosticPropertiesBuilder properties = DiagnosticPropertiesBuilder();
child.debugFillProperties(properties);
expect(properties.properties.any((DiagnosticsNode n) => n is FlagProperty && n.toString() == 'avoid left padding'), true);
expect(properties.properties.any((DiagnosticsNode n) => n is FlagProperty && n.toString() == 'avoid right padding'), false);
expect(properties.properties.any((DiagnosticsNode n) => n is FlagProperty && n.toString() == 'avoid top padding'), true);
expect(properties.properties.any((DiagnosticsNode n) => n is FlagProperty && n.toString() == 'avoid bottom padding'), false);
});
}