flutter/packages/flutter/test/material/material_test.dart
Ian Hickson 2144a8964f Fill in the test for button color splash and highlights (#9224)
Fixes https://github.com/flutter/flutter/pull/8643

Fixes https://github.com/flutter/flutter/issues/8804 by adding a test
to verify that Material elevation changes animate.

Also tweak some dartdocs, add some trailing commas, improve some
toString output, make the inkwell test agnostic to the PhysicalModel
logic, and move the material buttons test to the material test
directory.
2017-04-05 22:46:58 -07:00

184 lines
5.9 KiB
Dart

// Copyright 2016 The Chromium 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';
class NotifyMaterial extends StatelessWidget {
@override
Widget build(BuildContext context) {
new LayoutChangedNotification().dispatch(context);
return new Container();
}
}
Widget buildMaterial(int elevation) {
return new Center(
child: new SizedBox(
height: 100.0,
width: 100.0,
child: new Material(
color: const Color(0xFF00FF00),
elevation: elevation,
),
),
);
}
List<BoxShadow> getShadow(WidgetTester tester) {
final RenderDecoratedBox box = tester.renderObject(find.byType(DecoratedBox).first);
final BoxDecoration decoration = box.decoration;
return decoration.boxShadow;
}
class PaintRecorder extends CustomPainter {
PaintRecorder(this.log);
List<Size> log;
@override
void paint(Canvas canvas, Size size) {
log.add(size);
final Paint paint = new Paint()..color = const Color(0xFF0000FF);
canvas.drawRect(Point.origin & size, paint);
}
@override
bool shouldRepaint(PaintRecorder oldDelegate) => false;
}
void main() {
testWidgets('LayoutChangedNotificaion test', (WidgetTester tester) async {
await tester.pumpWidget(
new Material(
child: new NotifyMaterial(),
),
);
});
testWidgets('ListView scroll does not repaint', (WidgetTester tester) async {
final List<Size> log = <Size>[];
await tester.pumpWidget(
new Column(
children: <Widget>[
new SizedBox(
width: 150.0,
height: 150.0,
child: new CustomPaint(
painter: new PaintRecorder(log),
),
),
new Expanded(
child: new Material(
child: new Column(
children: <Widget>[
new Expanded(
child: new ListView(
children: <Widget>[
new Container(
height: 2000.0,
decoration: const BoxDecoration(
backgroundColor: const Color(0xFF00FF00),
),
),
],
),
),
new SizedBox(
width: 100.0,
height: 100.0,
child: new CustomPaint(
painter: new PaintRecorder(log),
),
),
],
),
),
),
],
),
);
// We paint twice because we have two CustomPaint widgets in the tree above
// to test repainting both inside and outside the Material widget.
expect(log, equals(<Size>[
const Size(150.0, 150.0),
const Size(100.0, 100.0),
]));
log.clear();
await tester.drag(find.byType(ListView), const Offset(0.0, -300.0));
await tester.pump();
expect(log, isEmpty);
});
testWidgets('Shadows animate smoothly', (WidgetTester tester) async {
await tester.pumpWidget(buildMaterial(0));
final List<BoxShadow> shadowA = getShadow(tester);
await tester.pumpWidget(buildMaterial(9));
final List<BoxShadow> shadowB = getShadow(tester);
await tester.pump(const Duration(milliseconds: 1));
final List<BoxShadow> shadowC = getShadow(tester);
await tester.pump(kThemeChangeDuration ~/ 2);
final List<BoxShadow> shadowD = getShadow(tester);
await tester.pump(kThemeChangeDuration);
final List<BoxShadow> shadowE = getShadow(tester);
// This code verifies the following:
// 1. When the elevation is zero, there's no shadow.
// 2. When the elevation isn't zero, there's three shadows.
// 3. When the elevation changes from 0 to 9, one millisecond later, the
// shadows are still more or less indistinguishable from zero.
// 4. Have a kThemeChangeDuration later, they are distinguishable form
// zero.
// 5. ...but still distinguishable from the actual 9 elevation.
// 6. After kThemeChangeDuration, the shadows are exactly the elevation 9
// shadows.
// The point being to verify that the shadows animate, and do so
// continually, not in discrete increments (e.g. not jumping from elevation
// 0 to 1 to 2 to 3 and so forth).
// TODO(ianh): Port this test when we turn the physical model back on.
// 1
expect(shadowA, isNull);
expect(shadowB, isNull);
// 2
expect(shadowC, hasLength(3));
// 3
expect(shadowC[0].offset.dy, closeTo(0.0, 0.001));
expect(shadowC[1].offset.dy, closeTo(0.0, 0.001));
expect(shadowC[2].offset.dy, closeTo(0.0, 0.001));
expect(shadowC[0].blurRadius, closeTo(0.0, 0.001));
expect(shadowC[1].blurRadius, closeTo(0.0, 0.001));
expect(shadowC[2].blurRadius, closeTo(0.0, 0.001));
expect(shadowC[0].spreadRadius, closeTo(0.0, 0.001));
expect(shadowC[1].spreadRadius, closeTo(0.0, 0.001));
expect(shadowC[2].spreadRadius, closeTo(0.0, 0.001));
// 4
expect(shadowD[0].offset.dy, isNot(closeTo(0.0, 0.001)));
expect(shadowD[1].offset.dy, isNot(closeTo(0.0, 0.001)));
expect(shadowD[2].offset.dy, isNot(closeTo(0.0, 0.001)));
expect(shadowD[0].blurRadius, isNot(closeTo(0.0, 0.001)));
expect(shadowD[1].blurRadius, isNot(closeTo(0.0, 0.001)));
expect(shadowD[2].blurRadius, isNot(closeTo(0.0, 0.001)));
expect(shadowD[0].spreadRadius, isNot(closeTo(0.0, 0.001)));
expect(shadowD[1].spreadRadius, isNot(closeTo(0.0, 0.001)));
expect(shadowD[2].spreadRadius, isNot(closeTo(0.0, 0.001)));
// 5
expect(shadowD[0], isNot(shadowE[0]));
expect(shadowD[1], isNot(shadowE[1]));
expect(shadowD[2], isNot(shadowE[2]));
// 6
expect(shadowE, kElevationToShadow[9]);
});
}