| // 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_test/flutter_test.dart'; |
| |
| import '../rendering/mock_canvas.dart'; |
| |
| enum RadiusType { |
| Sharp, |
| Shifting, |
| Round |
| } |
| |
| void matches(BorderRadius? borderRadius, RadiusType top, RadiusType bottom) { |
| final Radius cardRadius = kMaterialEdges[MaterialType.card]!.topLeft; |
| |
| if (top == RadiusType.Sharp) { |
| expect(borderRadius?.topLeft, equals(Radius.zero)); |
| expect(borderRadius?.topRight, equals(Radius.zero)); |
| } else if (top == RadiusType.Shifting) { |
| expect(borderRadius?.topLeft.x, greaterThan(0.0)); |
| expect(borderRadius?.topLeft.x, lessThan(cardRadius.x)); |
| expect(borderRadius?.topLeft.y, greaterThan(0.0)); |
| expect(borderRadius?.topLeft.y, lessThan(cardRadius.y)); |
| expect(borderRadius?.topRight.x, greaterThan(0.0)); |
| expect(borderRadius?.topRight.x, lessThan(cardRadius.x)); |
| expect(borderRadius?.topRight.y, greaterThan(0.0)); |
| expect(borderRadius?.topRight.y, lessThan(cardRadius.y)); |
| } else { |
| expect(borderRadius?.topLeft, equals(cardRadius)); |
| expect(borderRadius?.topRight, equals(cardRadius)); |
| } |
| |
| if (bottom == RadiusType.Sharp) { |
| expect(borderRadius?.bottomLeft, equals(Radius.zero)); |
| expect(borderRadius?.bottomRight, equals(Radius.zero)); |
| } else if (bottom == RadiusType.Shifting) { |
| expect(borderRadius?.bottomLeft.x, greaterThan(0.0)); |
| expect(borderRadius?.bottomLeft.x, lessThan(cardRadius.x)); |
| expect(borderRadius?.bottomLeft.y, greaterThan(0.0)); |
| expect(borderRadius?.bottomLeft.y, lessThan(cardRadius.y)); |
| expect(borderRadius?.bottomRight.x, greaterThan(0.0)); |
| expect(borderRadius?.bottomRight.x, lessThan(cardRadius.x)); |
| expect(borderRadius?.bottomRight.y, greaterThan(0.0)); |
| expect(borderRadius?.bottomRight.y, lessThan(cardRadius.y)); |
| } else { |
| expect(borderRadius?.bottomLeft, equals(cardRadius)); |
| expect(borderRadius?.bottomRight, equals(cardRadius)); |
| } |
| } |
| |
| // Returns the border radius decoration of an item within a MergeableMaterial. |
| // This depends on the exact structure of objects built by the Material and |
| // MergeableMaterial widgets. |
| BorderRadius? getBorderRadius(WidgetTester tester, int index) { |
| final List<Element> containers = tester.elementList(find.byType(Container)) |
| .toList(); |
| |
| final Container container = containers[index].widget as Container; |
| final BoxDecoration? boxDecoration = container.decoration as BoxDecoration?; |
| |
| return boxDecoration!.borderRadius as BorderRadius?; |
| } |
| |
| void main() { |
| testWidgets('MergeableMaterial empty', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial(), |
| ), |
| ), |
| ), |
| ); |
| |
| final RenderBox box = tester.renderObject(find.byType(MergeableMaterial)); |
| expect(box.size.height, equals(0)); |
| }); |
| |
| testWidgets('MergeableMaterial update slice', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| RenderBox box = tester.renderObject(find.byType(MergeableMaterial)); |
| expect(box.size.height, equals(100.0)); |
| |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 200.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| box = tester.renderObject(find.byType(MergeableMaterial)); |
| expect(box.size.height, equals(200.0)); |
| }); |
| |
| testWidgets('MergeableMaterial swap slices', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('B'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| RenderBox box = tester.renderObject(find.byType(MergeableMaterial)); |
| expect(box.size.height, equals(200.0)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); |
| |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('B'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| box = tester.renderObject(find.byType(MergeableMaterial)); |
| expect(box.size.height, equals(200.0)); |
| |
| await tester.pump(const Duration(milliseconds: 100)); |
| expect(box.size.height, equals(200.0)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); |
| }); |
| |
| testWidgets('MergeableMaterial paints shadows', (WidgetTester tester) async { |
| debugDisableShadows = false; |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| final BoxShadow boxShadow = kElevationToShadow[2]![0]; |
| final RRect rrect = kMaterialEdges[MaterialType.card]!.toRRect( |
| const Rect.fromLTRB(0.0, 0.0, 800.0, 100.0) |
| ); |
| expect( |
| find.byType(MergeableMaterial), |
| paints..rrect(rrect: rrect, color: boxShadow.color, hasMaskFilter: true), |
| ); |
| debugDisableShadows = true; |
| }); |
| |
| testWidgets('MergeableMaterial merge gap', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialGap( |
| key: ValueKey<String>('x') |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('B'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| final RenderBox box = tester.renderObject(find.byType(MergeableMaterial)); |
| expect(box.size.height, equals(216)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); |
| matches(getBorderRadius(tester, 1), RadiusType.Round, RadiusType.Round); |
| |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('B'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| await tester.pump(const Duration(milliseconds: 100)); |
| expect(box.size.height, lessThan(216)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Shifting); |
| matches(getBorderRadius(tester, 1), RadiusType.Shifting, RadiusType.Round); |
| |
| await tester.pump(const Duration(milliseconds: 100)); |
| expect(box.size.height, equals(200)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Sharp); |
| matches(getBorderRadius(tester, 1), RadiusType.Sharp, RadiusType.Round); |
| }); |
| |
| testWidgets('MergeableMaterial separate slices', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('B'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| final RenderBox box = tester.renderObject(find.byType(MergeableMaterial)); |
| expect(box.size.height, equals(200)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); |
| |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialGap( |
| key: ValueKey<String>('x') |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('B'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| await tester.pump(const Duration(milliseconds: 100)); |
| expect(box.size.height, lessThan(216)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Shifting); |
| matches(getBorderRadius(tester, 1), RadiusType.Shifting, RadiusType.Round); |
| |
| await tester.pump(const Duration(milliseconds: 100)); |
| expect(box.size.height, equals(216)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); |
| matches(getBorderRadius(tester, 1), RadiusType.Round, RadiusType.Round); |
| }); |
| |
| testWidgets('MergeableMaterial separate merge separate', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('B'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| final RenderBox box = tester.renderObject(find.byType(MergeableMaterial)); |
| expect(box.size.height, equals(200)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); |
| |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialGap( |
| key: ValueKey<String>('x') |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('B'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| await tester.pump(const Duration(milliseconds: 100)); |
| expect(box.size.height, lessThan(216)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Shifting); |
| matches(getBorderRadius(tester, 1), RadiusType.Shifting, RadiusType.Round); |
| |
| await tester.pump(const Duration(milliseconds: 100)); |
| expect(box.size.height, equals(216)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); |
| matches(getBorderRadius(tester, 1), RadiusType.Round, RadiusType.Round); |
| |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('B'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| await tester.pump(const Duration(milliseconds: 100)); |
| expect(box.size.height, lessThan(216)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Shifting); |
| matches(getBorderRadius(tester, 1), RadiusType.Shifting, RadiusType.Round); |
| |
| await tester.pump(const Duration(milliseconds: 100)); |
| expect(box.size.height, equals(200)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Sharp); |
| matches(getBorderRadius(tester, 1), RadiusType.Sharp, RadiusType.Round); |
| |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialGap( |
| key: ValueKey<String>('x') |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('B'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| await tester.pump(const Duration(milliseconds: 100)); |
| expect(box.size.height, lessThan(216)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Shifting); |
| matches(getBorderRadius(tester, 1), RadiusType.Shifting, RadiusType.Round); |
| |
| await tester.pump(const Duration(milliseconds: 100)); |
| expect(box.size.height, equals(216)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); |
| matches(getBorderRadius(tester, 1), RadiusType.Round, RadiusType.Round); |
| }); |
| |
| testWidgets('MergeableMaterial insert slice', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('C'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| final RenderBox box = tester.renderObject(find.byType(MergeableMaterial)); |
| expect(box.size.height, equals(200)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); |
| |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('B'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('C'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| expect(box.size.height, equals(300)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); |
| }); |
| |
| testWidgets('MergeableMaterial remove slice', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('B'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('C'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| final RenderBox box = tester.renderObject(find.byType(MergeableMaterial)); |
| expect(box.size.height, equals(300)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); |
| |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('C'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| await tester.pump(); |
| expect(box.size.height, equals(200)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); |
| }); |
| |
| testWidgets('MergeableMaterial insert chunk', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('C'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| final RenderBox box = tester.renderObject(find.byType(MergeableMaterial)); |
| expect(box.size.height, equals(200)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); |
| |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialGap( |
| key: ValueKey<String>('x') |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('B'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialGap( |
| key: ValueKey<String>('y') |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('C'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| await tester.pump(const Duration(milliseconds: 100)); |
| expect(box.size.height, lessThan(332)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Shifting); |
| matches(getBorderRadius(tester, 1), RadiusType.Shifting, RadiusType.Shifting); |
| matches(getBorderRadius(tester, 2), RadiusType.Shifting, RadiusType.Round); |
| |
| await tester.pump(const Duration(milliseconds: 100)); |
| expect(box.size.height, equals(332)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); |
| matches(getBorderRadius(tester, 1), RadiusType.Round, RadiusType.Round); |
| matches(getBorderRadius(tester, 2), RadiusType.Round, RadiusType.Round); |
| }); |
| |
| testWidgets('MergeableMaterial remove chunk', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialGap( |
| key: ValueKey<String>('x') |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('B'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialGap( |
| key: ValueKey<String>('y') |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('C'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| final RenderBox box = tester.renderObject(find.byType(MergeableMaterial)); |
| expect(box.size.height, equals(332)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); |
| matches(getBorderRadius(tester, 1), RadiusType.Round, RadiusType.Round); |
| matches(getBorderRadius(tester, 2), RadiusType.Round, RadiusType.Round); |
| |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('C'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| await tester.pump(const Duration(milliseconds: 100)); |
| expect(box.size.height, lessThan(332)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Shifting); |
| matches(getBorderRadius(tester, 1), RadiusType.Shifting, RadiusType.Round); |
| |
| await tester.pump(const Duration(milliseconds: 100)); |
| expect(box.size.height, equals(200)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Sharp); |
| matches(getBorderRadius(tester, 1), RadiusType.Sharp, RadiusType.Round); |
| }); |
| |
| testWidgets('MergeableMaterial replace gap with chunk', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialGap( |
| key: ValueKey<String>('x') |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('C'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| final RenderBox box = tester.renderObject(find.byType(MergeableMaterial)); |
| expect(box.size.height, equals(216)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); |
| matches(getBorderRadius(tester, 1), RadiusType.Round, RadiusType.Round); |
| |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialGap( |
| key: ValueKey<String>('y') |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('B'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialGap( |
| key: ValueKey<String>('z') |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('C'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| await tester.pump(const Duration(milliseconds: 100)); |
| expect(box.size.height, lessThan(332)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Shifting); |
| matches(getBorderRadius(tester, 1), RadiusType.Shifting, RadiusType.Shifting); |
| matches(getBorderRadius(tester, 2), RadiusType.Shifting, RadiusType.Round); |
| |
| await tester.pump(const Duration(milliseconds: 100)); |
| expect(box.size.height, equals(332)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); |
| matches(getBorderRadius(tester, 1), RadiusType.Round, RadiusType.Round); |
| matches(getBorderRadius(tester, 2), RadiusType.Round, RadiusType.Round); |
| }); |
| |
| testWidgets('MergeableMaterial replace chunk with gap', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialGap( |
| key: ValueKey<String>('x') |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('B'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialGap( |
| key: ValueKey<String>('y') |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('C'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| final RenderBox box = tester.renderObject(find.byType(MergeableMaterial)); |
| expect(box.size.height, equals(332)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); |
| matches(getBorderRadius(tester, 1), RadiusType.Round, RadiusType.Round); |
| matches(getBorderRadius(tester, 2), RadiusType.Round, RadiusType.Round); |
| |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialGap( |
| key: ValueKey<String>('z') |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('C'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| await tester.pump(const Duration(milliseconds: 100)); |
| expect(box.size.height, lessThan(332)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Shifting); |
| matches(getBorderRadius(tester, 1), RadiusType.Shifting, RadiusType.Round); |
| |
| await tester.pump(const Duration(milliseconds: 100)); |
| expect(box.size.height, equals(216)); |
| |
| matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); |
| matches(getBorderRadius(tester, 1), RadiusType.Round, RadiusType.Round); |
| }); |
| |
| bool isDivider(Widget widget, bool top, bool bottom) { |
| final DecoratedBox box = widget as DecoratedBox; |
| const BorderSide side = BorderSide(color: Color(0x1F000000), width: 0.5); |
| |
| return box.decoration == BoxDecoration( |
| border: Border( |
| top: top ? side : BorderSide.none, |
| bottom: bottom ? side : BorderSide.none, |
| ), |
| ); |
| } |
| |
| testWidgets('MergeableMaterial dividers', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| hasDividers: true, |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('B'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('C'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('D'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| List<Widget> boxes = tester.widgetList(find.byType(DecoratedBox)).toList(); |
| int offset = 1; |
| |
| expect(isDivider(boxes[offset], false, true), isTrue); |
| expect(isDivider(boxes[offset + 1], true, true), isTrue); |
| expect(isDivider(boxes[offset + 2], true, true), isTrue); |
| expect(isDivider(boxes[offset + 3], true, false), isTrue); |
| |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| hasDividers: true, |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('B'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialGap( |
| key: ValueKey<String>('x') |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('C'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('D'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| // Wait for dividers to shrink. |
| await tester.pump(const Duration(milliseconds: 200)); |
| |
| boxes = tester.widgetList(find.byType(DecoratedBox)).toList(); |
| offset = 1; |
| |
| expect(isDivider(boxes[offset], false, true), isTrue); |
| expect(isDivider(boxes[offset + 1], true, false), isTrue); |
| // offset + 2 is gap |
| expect(isDivider(boxes[offset + 3], false, true), isTrue); |
| expect(isDivider(boxes[offset + 4], true, false), isTrue); |
| }); |
| |
| testWidgets('MergeableMaterial respects dividerColor', (WidgetTester tester) async { |
| const Color dividerColor = Colors.red; |
| await tester.pumpWidget( |
| const MaterialApp( |
| home: Scaffold( |
| body: SingleChildScrollView( |
| child: MergeableMaterial( |
| hasDividers: true, |
| dividerColor: dividerColor, |
| children: <MergeableMaterialItem>[ |
| MaterialSlice( |
| key: ValueKey<String>('A'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| MaterialSlice( |
| key: ValueKey<String>('B'), |
| child: SizedBox( |
| width: 100.0, |
| height: 100.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| final DecoratedBox decoratedBox = tester.widget(find.byType(DecoratedBox).last); |
| final BoxDecoration decoration = decoratedBox.decoration as BoxDecoration; |
| // Since we are getting the last DecoratedBox, it will have a Border.top. |
| expect(decoration.border!.top.color, dividerColor); |
| }); |
| } |