| // Copyright 2015 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 'dart:async'; |
| import 'dart:typed_data'; |
| import 'dart:ui' as ui show Image; |
| |
| import 'package:flutter/foundation.dart'; |
| import 'package:flutter/material.dart'; |
| import 'package:flutter/painting.dart'; |
| import 'package:flutter/widgets.dart'; |
| import 'package:flutter_test/flutter_test.dart'; |
| |
| import '../painting/image_data.dart'; |
| import '../rendering/mock_canvas.dart'; |
| |
| class TestImageProvider extends ImageProvider<TestImageProvider> { |
| TestImageProvider(this.future); |
| |
| final Future<Null> future; |
| |
| static ui.Image image; |
| |
| @override |
| Future<TestImageProvider> obtainKey(ImageConfiguration configuration) { |
| return new SynchronousFuture<TestImageProvider>(this); |
| } |
| |
| @override |
| ImageStreamCompleter load(TestImageProvider key) { |
| return new OneFrameImageStreamCompleter( |
| future.then<ImageInfo>((Null value) => new ImageInfo(image: image)) |
| ); |
| } |
| } |
| |
| Future<Null> main() async { |
| TestImageProvider.image = await decodeImageFromList(new Uint8List.fromList(kTransparentImage)); |
| |
| testWidgets('DecoratedBox handles loading images', (WidgetTester tester) async { |
| final GlobalKey key = new GlobalKey(); |
| final Completer<Null> completer = new Completer<Null>(); |
| await tester.pumpWidget( |
| new KeyedSubtree( |
| key: key, |
| child: new DecoratedBox( |
| decoration: new BoxDecoration( |
| image: new DecorationImage( |
| image: new TestImageProvider(completer.future), |
| ), |
| ), |
| ), |
| ), |
| ); |
| expect(tester.binding.hasScheduledFrame, isFalse); |
| completer.complete(); |
| await tester.idle(); |
| expect(tester.binding.hasScheduledFrame, isTrue); |
| await tester.pump(); |
| expect(tester.binding.hasScheduledFrame, isFalse); |
| }); |
| |
| testWidgets('Moving a DecoratedBox', (WidgetTester tester) async { |
| final Completer<Null> completer = new Completer<Null>(); |
| final Widget subtree = new KeyedSubtree( |
| key: new GlobalKey(), |
| child: new RepaintBoundary( |
| child: new DecoratedBox( |
| decoration: new BoxDecoration( |
| image: new DecorationImage( |
| image: new TestImageProvider(completer.future), |
| ), |
| ), |
| ), |
| ), |
| ); |
| await tester.pumpWidget(subtree); |
| await tester.idle(); |
| expect(tester.binding.hasScheduledFrame, isFalse); |
| await tester.pumpWidget(new Container(child: subtree)); |
| await tester.idle(); |
| expect(tester.binding.hasScheduledFrame, isFalse); |
| completer.complete(); // schedules microtask, does not run it |
| expect(tester.binding.hasScheduledFrame, isFalse); |
| await tester.idle(); // runs microtask |
| expect(tester.binding.hasScheduledFrame, isTrue); |
| await tester.pump(); |
| await tester.idle(); |
| expect(tester.binding.hasScheduledFrame, isFalse); |
| }); |
| |
| testWidgets('Circles can have uniform borders', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| new Container( |
| padding: const EdgeInsets.all(50.0), |
| decoration: new BoxDecoration( |
| shape: BoxShape.circle, |
| border: new Border.all(width: 10.0, color: const Color(0x80FF00FF)), |
| color: Colors.teal[600] |
| ) |
| ) |
| ); |
| }); |
| |
| testWidgets('Bordered Container insets its child', (WidgetTester tester) async { |
| const Key key = const Key('outerContainer'); |
| await tester.pumpWidget( |
| new Center( |
| child: new Container( |
| key: key, |
| decoration: new BoxDecoration(border: new Border.all(width: 10.0)), |
| child: new Container( |
| width: 25.0, |
| height: 25.0 |
| ) |
| ) |
| ) |
| ); |
| expect(tester.getSize(find.byKey(key)), equals(const Size(45.0, 45.0))); |
| }); |
| |
| testWidgets('BoxDecoration paints its border correctly', (WidgetTester tester) async { |
| // Regression test for https://github.com/flutter/flutter/issues/7672 |
| |
| const Key key = const Key('Container with BoxDecoration'); |
| Widget buildFrame(Border border) { |
| return new Center( |
| child: new Container( |
| key: key, |
| width: 100.0, |
| height: 50.0, |
| decoration: new BoxDecoration(border: border), |
| ), |
| ); |
| } |
| |
| const Color black = const Color(0xFF000000); |
| |
| await tester.pumpWidget(buildFrame(new Border.all())); |
| expect(find.byKey(key), paints |
| ..rect(color: black, style: PaintingStyle.stroke, strokeWidth: 1.0)); |
| |
| await tester.pumpWidget(buildFrame(new Border.all(width: 0.0))); |
| expect(find.byKey(key), paints |
| ..rect(color: black, style: PaintingStyle.stroke, strokeWidth: 0.0)); |
| |
| const Color green = const Color(0xFF00FF00); |
| const BorderSide greenSide = const BorderSide(color: green, width: 10.0); |
| |
| await tester.pumpWidget(buildFrame(const Border(top: greenSide))); |
| expect(find.byKey(key), paints..path(color: green, style: PaintingStyle.fill)); |
| |
| await tester.pumpWidget(buildFrame(const Border(left: greenSide))); |
| expect(find.byKey(key), paints..path(color: green, style: PaintingStyle.fill)); |
| |
| await tester.pumpWidget(buildFrame(const Border(right: greenSide))); |
| expect(find.byKey(key), paints..path(color: green, style: PaintingStyle.fill)); |
| |
| await tester.pumpWidget(buildFrame(const Border(bottom: greenSide))); |
| expect(find.byKey(key), paints..path(color: green, style: PaintingStyle.fill)); |
| |
| const Color blue = const Color(0xFF0000FF); |
| const BorderSide blueSide = const BorderSide(color: blue, width: 0.0); |
| |
| await tester.pumpWidget(buildFrame(const Border(top: blueSide, right: greenSide, bottom: greenSide))); |
| expect(find.byKey(key), paints |
| ..path() // There's not much point checking the arguments to these calls because paintBorder |
| ..path() // reuses the same Paint object each time, configured differently, and so they will |
| ..path()); // all appear to have the same settings here (that of the last call). |
| }); |
| |
| testWidgets('BoxDecoration paints its border correctly', (WidgetTester tester) async { |
| // Regression test for https://github.com/flutter/flutter/issues/12165 |
| await tester.pumpWidget( |
| new Column( |
| children: <Widget>[ |
| new Container( |
| // There's not currently a way to verify that this paints the same size as the others, |
| // so the pattern below just asserts that there's four paths but doesn't check the geometry. |
| width: 100.0, |
| height: 100.0, |
| decoration: const BoxDecoration( |
| border: const Border( |
| top: const BorderSide( |
| width: 10.0, |
| color: const Color(0xFFEEEEEE), |
| ), |
| left: const BorderSide( |
| width: 10.0, |
| color: const Color(0xFFFFFFFF), |
| ), |
| right: const BorderSide( |
| width: 10.0, |
| color: const Color(0xFFFFFFFF), |
| ), |
| bottom: const BorderSide( |
| width: 10.0, |
| color: const Color(0xFFFFFFFF), |
| ), |
| ), |
| ), |
| ), |
| new Container( |
| width: 100.0, |
| height: 100.0, |
| decoration: new BoxDecoration( |
| border: new Border.all( |
| width: 10.0, |
| color: const Color(0xFFFFFFFF), |
| ), |
| ), |
| ), |
| new Container( |
| width: 100.0, |
| height: 100.0, |
| decoration: new BoxDecoration( |
| border: new Border.all( |
| width: 10.0, |
| color: const Color(0xFFFFFFFF), |
| ), |
| borderRadius: const BorderRadius.only( |
| topRight: const Radius.circular(10.0), |
| ), |
| ), |
| ), |
| new Container( |
| width: 100.0, |
| height: 100.0, |
| decoration: new BoxDecoration( |
| border: new Border.all( |
| width: 10.0, |
| color: const Color(0xFFFFFFFF), |
| ), |
| shape: BoxShape.circle, |
| ), |
| ), |
| ], |
| ), |
| ); |
| expect(find.byType(Column), paints |
| ..path() |
| ..path() |
| ..path() |
| ..path() |
| ..rect(rect: new Rect.fromLTRB(355.0, 105.0, 445.0, 195.0)) |
| ..drrect( |
| outer: new RRect.fromLTRBAndCorners( |
| 350.0, 200.0, 450.0, 300.0, |
| topLeft: Radius.zero, |
| topRight: const Radius.circular(10.0), |
| bottomRight: Radius.zero, |
| bottomLeft: Radius.zero, |
| ), |
| inner: new RRect.fromLTRBAndCorners( |
| 360.0, 210.0, 440.0, 290.0, |
| topLeft: const Radius.circular(-10.0), |
| topRight: Radius.zero, |
| bottomRight: const Radius.circular(-10.0), |
| bottomLeft: const Radius.circular(-10.0), |
| ), |
| ) |
| ..circle(x: 400.0, y: 350.0, radius: 45.0) |
| ); |
| }); |
| |
| testWidgets('Can hit test on BoxDecoration', (WidgetTester tester) async { |
| |
| List<int> itemsTapped; |
| |
| const Key key = const Key('Container with BoxDecoration'); |
| Widget buildFrame(Border border) { |
| itemsTapped = <int>[]; |
| return new Center( |
| child: new GestureDetector( |
| behavior: HitTestBehavior.deferToChild, |
| child: new Container( |
| key: key, |
| width: 100.0, |
| height: 50.0, |
| decoration: new BoxDecoration(border: border), |
| ), |
| onTap: () { |
| itemsTapped.add(1); |
| }, |
| ) |
| ); |
| } |
| |
| await tester.pumpWidget(buildFrame(new Border.all())); |
| expect(itemsTapped, isEmpty); |
| |
| await tester.tap(find.byKey(key)); |
| expect(itemsTapped, <int>[1]); |
| |
| await tester.tapAt(const Offset(350.0, 275.0)); |
| expect(itemsTapped, <int>[1,1]); |
| |
| await tester.tapAt(const Offset(449.0, 324.0)); |
| expect(itemsTapped, <int>[1,1,1]); |
| |
| }); |
| |
| testWidgets('Can hit test on BoxDecoration circle', (WidgetTester tester) async { |
| |
| List<int> itemsTapped; |
| |
| const Key key = const Key('Container with BoxDecoration'); |
| Widget buildFrame(Border border) { |
| itemsTapped = <int>[]; |
| return new Center( |
| child: new GestureDetector( |
| behavior: HitTestBehavior.deferToChild, |
| child: new Container( |
| key: key, |
| width: 100.0, |
| height: 50.0, |
| decoration: new BoxDecoration(border: border, shape: BoxShape.circle), |
| ), |
| onTap: () { |
| itemsTapped.add(1); |
| }, |
| ) |
| ); |
| } |
| |
| await tester.pumpWidget(buildFrame(new Border.all())); |
| expect(itemsTapped, isEmpty); |
| |
| await tester.tapAt(const Offset(0.0, 0.0)); |
| expect(itemsTapped, isEmpty); |
| |
| await tester.tapAt(const Offset(350.0, 275.0)); |
| expect(itemsTapped, isEmpty); |
| |
| await tester.tapAt(const Offset(400.0, 300.0)); |
| expect(itemsTapped, <int>[1]); |
| |
| await tester.tap(find.byKey(key)); |
| expect(itemsTapped, <int>[1,1]); |
| |
| }); |
| |
| } |