Jaime Blasco
Committed by GitHub

test: increase test coverage (#267)

... ... @@ -13,7 +13,7 @@ jobs:
uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/flutter_package.yml@v1
with:
working_directory: sheet
min_coverage: 60 # Working to reach 100% XD
min_coverage: 70 # Working to reach 100% XD
pana:
uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/pana.yml@v1
... ...
... ... @@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>9.0</string>
<string>11.0</string>
</dict>
</plist>
... ...
... ... @@ -272,7 +272,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
... ... @@ -358,7 +358,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
... ... @@ -407,7 +407,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
... ...
... ... @@ -4,41 +4,25 @@ import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:sheet/sheet.dart';
class FitSheet extends StatefulWidget {
@override
_FitSheetState createState() => _FitSheetState();
}
class _FitSheetState extends State<FitSheet> {
final SheetController controller = SheetController();
@override
void initState() {
Future<void>.delayed(const Duration(milliseconds: 400), animateSheet);
super.initState();
}
void animateSheet() {
controller.relativeAnimateTo(1,
duration: const Duration(milliseconds: 400), curve: Curves.easeOut);
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
class FitSheet extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Sheet(
elevation: 4,
child: Container(
height: 400,
child: const Text('hello'),
return DefaultSheetController(
onCreated: (controller) async {
await Future<void>.delayed(const Duration(milliseconds: 400));
controller.relativeAnimateTo(
1,
duration: const Duration(milliseconds: 400),
curve: Curves.easeOut,
);
},
child: Sheet(
elevation: 4,
child: Container(
height: 400,
child: const Text('hello'),
),
),
controller: controller,
);
}
}
... ...
... ... @@ -7,7 +7,7 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.8.2"
version: "2.9.0"
boolean_selector:
dependency: transitive
description:
... ... @@ -21,21 +21,14 @@ packages:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
version: "1.2.1"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.1.1"
collection:
dependency: transitive
description:
... ... @@ -63,7 +56,7 @@ packages:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
version: "1.3.1"
flutter:
dependency: "direct main"
description: flutter
... ... @@ -106,21 +99,21 @@ packages:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.11"
version: "0.12.12"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.4"
version: "0.1.5"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
version: "1.8.0"
nested:
dependency: transitive
description:
... ... @@ -134,7 +127,7 @@ packages:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.1"
version: "1.8.2"
provider:
dependency: "direct main"
description:
... ... @@ -160,7 +153,7 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.2"
version: "1.9.0"
stack_trace:
dependency: transitive
description:
... ... @@ -181,21 +174,21 @@ packages:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.1.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.9"
version: "0.4.12"
vector_math:
dependency: transitive
description:
... ... @@ -205,4 +198,4 @@ packages:
version: "2.1.2"
sdks:
dart: ">=2.17.0 <3.0.0"
flutter: ">=3.0.0"
flutter: ">=3.3.0"
... ...
... ... @@ -2,3 +2,5 @@ export 'src/physics.dart';
export 'src/scroll_controller.dart';
export 'src/scrollable.dart';
export 'src/sheet.dart';
export 'src/widgets/default_sheet_controller.dart';
export 'src/widgets/sheet_media_query.dart';
... ...
... ... @@ -272,7 +272,7 @@ class Sheet extends StatelessWidget {
offset: offset,
minExtent: minResizableExtent ?? 0,
child: Builder(
key: const Key('_sheet_builder'),
key: const Key('_sheet_child'),
builder: (BuildContext context) {
return decorationBuilder(
context,
... ... @@ -290,45 +290,6 @@ class Sheet extends StatelessWidget {
}
}
class SheetMediaQuery extends StatelessWidget {
const SheetMediaQuery({Key? key, required this.child}) : super(key: key);
final Widget child;
@override
Widget build(BuildContext context) {
final SheetPosition position = Sheet.of(context)!.controller.position;
final EdgeInsets padding = MediaQuery.of(context).padding;
return LayoutBuilder(
builder: (
BuildContext context,
BoxConstraints constraints,
) {
return AnimatedBuilder(
animation: position,
builder: (BuildContext context, Widget? child) {
final double pixels = position.hasPixels ? position.pixels : 0;
final double viewportDimension = position.hasViewportDimension
? position.viewportDimension
: double.infinity;
final double top = math.max(
0.0,
padding.top - (viewportDimension - pixels),
);
return MediaQuery(
data: MediaQuery.of(context).copyWith(
padding: padding.copyWith(top: top),
),
child: child!,
);
},
child: child,
);
},
);
}
}
class _DefaultSheetScrollController extends StatelessWidget {
const _DefaultSheetScrollController({Key? key, required this.child})
: super(key: key);
... ... @@ -436,61 +397,6 @@ class SheetController extends ScrollController {
}
}
typedef SheetControllerCallback = void Function(SheetController controller);
class DefaultSheetController extends StatefulWidget {
const DefaultSheetController({Key? key, required this.child, this.onCreated})
: super(key: key);
final Widget child;
final SheetControllerCallback? onCreated;
static SheetController? of(BuildContext context) {
return context
.dependOnInheritedWidgetOfExactType<_InheritedSheetController>()
?.controller;
}
@override
State<DefaultSheetController> createState() => _DefaultSheetControllerState();
}
class _DefaultSheetControllerState extends State<DefaultSheetController> {
late final SheetController controller = SheetController();
@override
void initState() {
widget.onCreated?.call(controller);
super.initState();
}
@override
Widget build(BuildContext context) {
return _InheritedSheetController(
child: widget.child, controller: controller);
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
}
class _InheritedSheetController extends InheritedWidget {
const _InheritedSheetController(
{Key? key, required super.child, required this.controller})
: super(key: key);
final SheetController controller;
@override
bool updateShouldNotify(_InheritedSheetController oldWidget) {
return false;
}
}
/// A scroll position that manages scroll activities for
/// [_SheetScrollController].
///
... ... @@ -528,8 +434,11 @@ class SheetPosition extends ScrollPositionWithSingleContext {
Future<void> relativeAnimateTo(double to,
{required Duration duration, required Curve curve}) {
assert(to >= 0 && to <= 1);
return super
.animateTo(to * maxScrollExtent, duration: duration, curve: curve);
return super.animateTo(
pixelsFromRelativeOffset(to, minScrollExtent, maxScrollExtent),
duration: duration,
curve: curve,
);
}
@override
... ... @@ -541,7 +450,9 @@ class SheetPosition extends ScrollPositionWithSingleContext {
void relativeJumpTo(double to) {
assert(to >= 0 && to <= 1);
return super.jumpTo(to * maxScrollExtent);
final value =
pixelsFromRelativeOffset(to, minScrollExtent, maxScrollExtent);
return super.jumpTo(value);
}
@override
... ... @@ -567,13 +478,21 @@ class SheetPosition extends ScrollPositionWithSingleContext {
@override
double setPixels(double newPixels) {
_controller.value = (newPixels / maxScrollExtent).clamp(0, 1);
_controller.value = relativeOffsetFromPixels(
newPixels,
minScrollExtent,
maxScrollExtent,
);
return super.setPixels(newPixels);
}
@override
void forcePixels(double value) {
_controller.value = (value / maxScrollExtent).clamp(0, 1);
_controller.value = relativeOffsetFromPixels(
value,
minScrollExtent,
maxScrollExtent,
);
super.forcePixels(value);
}
... ... @@ -589,9 +508,34 @@ class SheetPosition extends ScrollPositionWithSingleContext {
// Clamp initial extent to maxScrollExtent
if (!hasContentDimensions) {
correctPixels(pixels.clamp(minScrollExtent, maxScrollExtent));
_controller.value = relativeOffsetFromPixels(
pixels,
minScrollExtent,
maxScrollExtent,
);
}
return super.applyContentDimensions(minScrollExtent, maxScrollExtent);
}
static double relativeOffsetFromPixels(
double pixels,
double minScrollExtent,
double maxScrollExtent,
) {
if (minScrollExtent == maxScrollExtent) return 1;
final value =
((pixels - minScrollExtent) / (maxScrollExtent - minScrollExtent))
.clamp(0.0, 1.0);
return value;
}
static double pixelsFromRelativeOffset(
double offset,
double minScrollExtent,
double maxScrollExtent,
) {
return minScrollExtent + offset * (maxScrollExtent - minScrollExtent);
}
}
class SheetViewport extends SingleChildRenderObjectWidget {
... ...
import 'package:flutter/material.dart';
import 'package:sheet/sheet.dart';
typedef SheetControllerCallback = void Function(SheetController controller);
/// A widget that injets a [SheetController] that can be used by
/// any [Sheet] children
///
/// It is useful for creating initial animations
/// ```dart
/// DefaultSheetController(
/// onCreated: (controller) => controller.play
/// )
///
///
class DefaultSheetController extends StatefulWidget {
const DefaultSheetController({Key? key, required this.child, this.onCreated})
: super(key: key);
final Widget child;
/// A callback called when the controller is created
final SheetControllerCallback? onCreated;
static SheetController? of(BuildContext context) {
return context
.dependOnInheritedWidgetOfExactType<_InheritedSheetController>()
?.controller;
}
@override
State<DefaultSheetController> createState() => _DefaultSheetControllerState();
}
class _DefaultSheetControllerState extends State<DefaultSheetController> {
late final SheetController controller = SheetController();
@override
void initState() {
widget.onCreated?.call(controller);
super.initState();
}
@override
Widget build(BuildContext context) {
return _InheritedSheetController(
child: widget.child, controller: controller);
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
}
class _InheritedSheetController extends InheritedWidget {
const _InheritedSheetController(
{Key? key, required super.child, required this.controller})
: super(key: key);
final SheetController controller;
@override
bool updateShouldNotify(_InheritedSheetController oldWidget) {
return false;
}
}
... ...
import 'package:flutter/widgets.dart';
import 'package:sheet/sheet.dart';
import 'dart:math' as math;
/// A widget that updates the top safe area proportionally to the position
/// of the sheet
///
/// If the sheet is below the top safe area the inner top padding will be 0.
/// Once the sheet enters the top safe area the inner top padding will increase
/// proportionally to the sheet offset.
/// If the sheet is fully expanded to the top of the screen the top padding
/// will be the same as the parent top safe area.
class SheetMediaQuery extends StatelessWidget {
const SheetMediaQuery({Key? key, required this.child}) : super(key: key);
final Widget child;
@override
Widget build(BuildContext context) {
final controller = Sheet.of(context)!.controller;
final MediaQueryData data = MediaQuery.of(context);
return LayoutBuilder(builder: (context, constraints) {
return AnimatedBuilder(
animation: controller.animation,
builder: (BuildContext context, Widget? child) {
final position = controller.position;
final viewportDimension = position.hasViewportDimension
? position.viewportDimension
: double.infinity;
final pixels = position.hasPixels ? position.pixels : 0;
final offset = viewportDimension - pixels;
final topPadding = math.max(0.0, data.padding.top - offset);
return MediaQuery(
data: data.copyWith(
padding: data.padding.copyWith(
top: topPadding,
),
),
child: child!,
);
},
child: child,
);
});
}
}
... ...
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:sheet/sheet.dart';
import '../helpers.dart';
void main() {
group('SheetController.animation', () {
testWidgets('is 0 when starts in minExtent', (tester) async {
await tester.pumpWidget(
MaterialApp(
home: Sheet(
minExtent: 100,
maxExtent: 400,
initialExtent: 100,
child: SizedBox(height: 400),
),
),
);
expect(tester.getSheetController().animation.value, 0);
});
testWidgets('is 1 when starts in maxExtent', (tester) async {
await tester.pumpWidget(
MaterialApp(
home: Sheet(
minExtent: 100,
maxExtent: 400,
initialExtent: 400,
child: SizedBox(height: 400),
),
),
);
expect(tester.getSheetController().animation.value, 1);
});
testWidgets('is 0.5 when is between minExtent and maxExtent',
(tester) async {
await tester.pumpWidget(
MaterialApp(
home: Sheet(
minExtent: 100,
maxExtent: 300,
initialExtent: 200,
child: SizedBox(height: 300),
),
),
);
expect(tester.getSheetController().animation.value, 0.5);
});
testWidgets('is 1 when minExtent equals maxExtent', (tester) async {
await tester.pumpWidget(
MaterialApp(
home: Sheet(
minExtent: 100,
maxExtent: 100,
child: SizedBox(height: 100),
),
),
);
expect(tester.getSheetController().animation.value, 1);
});
testWidgets('updates to 0 when it goes to minExtent', (tester) async {
await tester.pumpWidget(
MaterialApp(
home: Sheet(
minExtent: 100,
maxExtent: 400,
initialExtent: 400,
fit: SheetFit.expand,
child: SizedBox(),
),
),
);
expect(tester.getSheetController().animation.value, 1);
tester.getSheetController().relativeJumpTo(0);
await tester.pumpAndSettle();
expect(tester.getSheetController().animation.value, 0);
});
testWidgets('updates to 1 when it goes to maxExtent', (tester) async {
await tester.pumpWidget(
MaterialApp(
home: Sheet(
minExtent: 100,
maxExtent: 400,
initialExtent: 100,
child: SizedBox(height: 400),
),
),
);
expect(tester.getSheetController().animation.value, 0);
tester.getSheetController().relativeJumpTo(1);
expect(tester.getSheetController().animation.value, 1);
});
testWidgets('updates linearly', (tester) async {
await tester.pumpWidget(
MaterialApp(
home: Sheet(
minExtent: 100,
maxExtent: 300,
initialExtent: 100,
child: SizedBox(height: 300),
),
),
);
tester.getSheetController().relativeJumpTo(0.5);
await tester.pumpAndSettle();
expect(tester.getSheetController().animation.value, 0.5);
});
});
}
... ...
... ... @@ -9,132 +9,184 @@ import '../screen_size_test.dart';
void main() {
group('SheetController', () {
testWidgets('jumpTo', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
await tester.pumpApp(
Sheet(
initialExtent: 200,
child: Container(
key: key,
height: kScreenRect.height,
const curve = Curves.easeInOut;
const duration = Duration(milliseconds: 1);
const child = SizedBox(height: kScreenHeight);
group('jumpTo', () {
testWidgets('a custom extent - 400', (WidgetTester tester) async {
await tester.pumpApp(
Sheet(child: child),
);
tester.getSheetController().jumpTo(400);
expect(tester.getSheetExtent(), 400);
});
testWidgets('minExtent', (WidgetTester tester) async {
await tester.pumpApp(
Sheet(
minExtent: 100,
child: child,
),
),
);
expect(tester.getSheetSize(), equals(kScreenRect.size));
expect(tester.getSheetTop(), equals(kScreenRect.bottom - 200));
tester.getSheetController().jumpTo(400);
expect(tester.getSheetSize(), equals(kScreenRect.size));
expect(tester.getSheetTop(), kScreenRect.height - 400);
tester.getSheetController().jumpTo(-100);
expect(tester.getSheetSize(), equals(kScreenRect.size));
expect(tester.getSheetTop(), equals(kScreenRect.height));
tester.getSheetController().jumpTo(kScreenRect.height + 100);
);
tester.getSheetController().jumpTo(100);
expect(tester.getSheetExtent(), 100);
});
testWidgets('maxExtent', (WidgetTester tester) async {
await tester.pumpApp(
Sheet(
maxExtent: 400,
child: child,
),
);
tester.getSheetController().jumpTo(400);
expect(tester.getSheetExtent(), 400);
});
testWidgets('less than 0 clamps to 0', (WidgetTester tester) async {
await tester.pumpApp(
Sheet(child: child),
);
tester.getSheetController().jumpTo(-100);
expect(tester.getSheetExtent(), equals(0));
});
testWidgets('less than minExtent clamps to minExtent',
(WidgetTester tester) async {
await tester.pumpApp(
Sheet(
minExtent: 100,
initialExtent: 200,
child: child,
),
);
expect(tester.getSheetExtent(), equals(200));
tester.getSheetController().jumpTo(100);
expect(tester.getSheetExtent(), equals(100));
});
testWidgets(
'more than than screenHeight clamps to screenHeight '
'if maxExtent is null', (WidgetTester tester) async {
await tester.pumpApp(
Sheet(
child: child,
),
);
tester.getSheetController().jumpTo(kScreenHeight + 100);
expect(tester.getSheetExtent(), equals(kScreenHeight));
});
testWidgets('more than maxExtent clamps to maxExtent',
(WidgetTester tester) async {
await tester.pumpApp(
Sheet(
maxExtent: 400,
child: child,
),
);
expect(tester.getSheetSize(), equals(kScreenRect.size));
expect(tester.getSheetTop(), equals(0));
tester.getSheetController().jumpTo(500);
expect(tester.getSheetExtent(), 400);
});
});
testWidgets('relativeJumpTo', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
await tester.pumpApp(
Sheet(
initialExtent: 200,
child: Container(
key: key,
height: kScreenRect.height,
height: kScreenHeight,
),
),
);
expect(tester.getSheetSize(), equals(kScreenRect.size));
expect(tester.getSheetTop(), equals(kScreenRect.bottom - 200));
expect(tester.getSheetExtent(), equals(200));
tester.getSheetController().relativeJumpTo(1);
expect(tester.getSheetSize(), equals(kScreenRect.size));
expect(tester.getSheetTop(), equals(0));
expect(tester.getSheetExtent(), equals(kScreenHeight));
tester.getSheetController().relativeJumpTo(0.5);
expect(tester.getSheetSize(), equals(kScreenRect.size));
expect(tester.getSheetTop(), equals(kScreenRect.bottom / 2));
expect(tester.getSheetExtent(), equals(kScreenHeight / 2));
});
testWidgets('animateTo', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
await tester.pumpApp(
Sheet(
initialExtent: 200,
child: Container(
key: key,
height: kScreenRect.height,
height: kScreenHeight,
),
),
);
expect(tester.getSheetSize(), equals(kScreenRect.size));
expect(tester.getSheetTop(), equals(kScreenRect.height - 200));
expect(tester.getSheetExtent(), equals(200));
tester.getSheetController().animateTo(400,
curve: Curves.easeInOut, duration: const Duration(milliseconds: 1));
tester
.getSheetController()
.animateTo(400, curve: curve, duration: duration);
await tester.pumpAndSettle();
final controller = tester.getSheetController();
expect(tester.getSheetExtent(), equals(400));
expect(tester.getSheetSize(), equals(kScreenRect.size));
expect(tester.getSheetTop(), equals(kScreenRect.bottom - 400));
tester.getSheetController().animateTo(-100,
curve: Curves.easeInOut, duration: const Duration(milliseconds: 1));
controller.animateTo(-100, curve: curve, duration: duration);
await tester.pumpAndSettle();
expect(tester.getSheetSize(), equals(kScreenRect.size));
expect(tester.getSheetTop(), equals(kScreenRect.bottom));
tester.getSheetController().animateTo(kScreenRect.height + 100,
curve: Curves.easeInOutCirc,
duration: const Duration(milliseconds: 1));
expect(tester.getSheetExtent(), equals(0));
controller.animateTo(
kScreenHeight + 100,
curve: curve,
duration: duration,
);
await tester.pumpAndSettle();
expect(tester.getSheetSize(), equals(kScreenRect.size));
expect(tester.getSheetTop(), equals(0));
expect(tester.getSheetExtent(), equals(kScreenHeight));
});
testWidgets('relativeAnimateTo', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
await tester.pumpApp(
Sheet(
initialExtent: 200,
child: Container(
key: key,
height: kScreenRect.height,
height: kScreenHeight,
),
),
);
final controller = tester.getSheetController();
expect(tester.getSheetExtent(), equals(200));
expect(tester.getSheetSize(), equals(kScreenRect.size));
expect(tester.getSheetTop(), equals(kScreenRect.bottom - 200));
controller.relativeAnimateTo(1, curve: curve, duration: duration);
await tester.pumpAndSettle();
expect(tester.getSheetExtent(), equals(kScreenHeight));
tester.getSheetController().relativeAnimateTo(1,
curve: Curves.easeInOut, duration: const Duration(milliseconds: 1));
controller.relativeAnimateTo(0.5, curve: curve, duration: duration);
await tester.pumpAndSettle();
expect(tester.getSheetExtent(), equals(kScreenHeight * 0.5));
});
expect(tester.getSheetSize(), equals(kScreenRect.size));
expect(tester.getSheetTop(), equals(0));
testWidgets('relativeAnimateTo with min xtent',
(WidgetTester tester) async {
await tester.pumpApp(
Sheet(
initialExtent: 200,
child: Container(
height: kScreenHeight,
),
),
);
final controller = tester.getSheetController();
expect(tester.getSheetExtent(), equals(200));
tester.getSheetController().relativeAnimateTo(0.5,
curve: Curves.easeInOut, duration: const Duration(milliseconds: 1));
controller.relativeAnimateTo(1, curve: curve, duration: duration);
await tester.pumpAndSettle();
expect(tester.getSheetExtent(), equals(kScreenHeight));
expect(tester.getSheetSize(), equals(kScreenRect.size));
expect(tester.getSheetTop(), equals(kScreenRect.bottom / 2));
controller.relativeAnimateTo(0.5, curve: curve, duration: duration);
await tester.pumpAndSettle();
expect(tester.getSheetExtent(), equals(kScreenHeight * 0.5));
});
});
}
... ...
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:sheet/sheet.dart';
import '../helpers.dart';
void main() {
group('SheetPosition', () {
testWidgets('can prevent drag', (WidgetTester tester) async {
await tester.pumpApp(
Sheet(
child: SizedBox(height: 200),
),
);
final position = tester.getSheetPosition();
expect(position.preventingDrag, false);
position.preventDrag();
expect(position.preventingDrag, true);
});
testWidgets('can stops preventing drag', (WidgetTester tester) async {
await tester.pumpApp(
Sheet(
child: SizedBox(height: 200),
),
);
final position = tester.getSheetPosition();
position.preventDrag();
expect(position.preventingDrag, true);
position.stopPreventingDrag();
expect(position.preventingDrag, false);
});
});
}
... ...
... ... @@ -2,9 +2,9 @@ import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:sheet/sheet.dart';
const Key _key = Key('_sheet_builder');
const Key _childKey = Key('_sheet_child');
Finder findSheet() => find.byKey(_key);
Finder findSheet() => find.byKey(_childKey);
extension SheetTester on WidgetTester {
Future<void> pumpApp(Widget sheet, {VoidCallback? onButtonPressed}) async {
... ... @@ -41,26 +41,37 @@ extension SheetTester on WidgetTester {
}
double getSheetTop() {
final Offset offset = getTopLeft(find.byKey(_key));
final Offset offset = getTopLeft(find.byKey(_childKey));
return offset.dy;
}
double getSheetExtent() {
final Rect rootRect = getRect(find.byType(Sheet));
final Offset offset = getTopLeft(find.byKey(_childKey));
return rootRect.bottom - offset.dy;
}
SheetController getSheetController() {
final Element context = element(find.byKey(_key));
final BuildContext context = element(find.byKey(_childKey));
return Sheet.of(context)!.controller;
}
SheetPosition getSheetPosition() {
final BuildContext context = element(find.byKey(_childKey));
return Sheet.of(context)!.position;
}
double getSheetHeight() {
final Size rect = getSize(find.byKey(_key));
final Size rect = getSize(find.byKey(_childKey));
return rect.height;
}
Size getSheetSize() {
return getSize(find.byKey(_key));
return getSize(find.byKey(_childKey));
}
Future<void> dragSheet(double offset) {
return drag(find.byKey(_key), Offset(0, offset));
return drag(find.byKey(_childKey), Offset(0, offset));
}
}
... ...
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:sheet/sheet.dart';
void main() {
group('Sheet', () {
testWidgets('default has material appareance', (tester) async {
await tester.pumpWidget(
MaterialApp(
home: Sheet(
child: SizedBox(),
),
),
);
expect(find.byType(Material), findsOneWidget);
final material = tester.widget<Material>(find.byType(Material));
expect(
material.color,
ThemeData.fallback().bottomSheetTheme.backgroundColor,
);
});
testWidgets('Sheet uses bottomSheetTheme by default', (tester) async {
await tester.pumpWidget(
MaterialApp(
home: Sheet(
child: SizedBox(),
),
),
);
final material = tester.widget<Material>(find.byType(Material));
expect(
material.color,
ThemeData.fallback().bottomSheetTheme.backgroundColor,
);
expect(
material.shape,
ThemeData.fallback().bottomSheetTheme.shape,
);
expect(material.elevation, 0);
expect(material.clipBehavior, Clip.none);
});
testWidgets('.raw has no material appareance', (tester) async {
await tester.pumpWidget(
MaterialApp(
home: Sheet.raw(
child: SizedBox(),
),
),
);
expect(find.byType(Material), findsNothing);
});
});
}
... ...
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:sheet/sheet.dart';
void main() {
group('DefaultSheetController', () {
testWidgets('DefaultSheetController injects a SheetController',
(tester) async {
final childKey = UniqueKey();
await tester.pumpWidget(
MaterialApp(
home: DefaultSheetController(
child: SizedBox(key: childKey),
),
),
);
await tester.pumpAndSettle();
final context = tester.element(find.byKey(childKey));
expect(DefaultSheetController.of(context), isA<SheetController>());
});
testWidgets('Sheet uses its SheetController', (tester) async {
final childKey = UniqueKey();
await tester.pumpWidget(
MaterialApp(
home: DefaultSheetController(
child: Sheet(
child: SizedBox(key: childKey),
),
),
),
);
await tester.pumpAndSettle();
final context = tester.element(find.byKey(childKey));
final controller = DefaultSheetController.of(context);
expect(Sheet.of(context)!.controller, controller);
});
testWidgets('SheetController is the same between rebuilds', (tester) async {
final childKey = UniqueKey();
late StateSetter setState;
await tester.pumpWidget(
MaterialApp(
home: StatefulBuilder(builder: (context, stateSetter) {
setState = stateSetter;
return DefaultSheetController(
child: Sheet(
child: SizedBox(key: childKey),
),
);
}),
),
);
await tester.pumpAndSettle();
final context = tester.element(find.byKey(childKey));
final controller = DefaultSheetController.of(context);
setState(() {});
await tester.pumpAndSettle();
expect(DefaultSheetController.of(context), controller);
});
});
}
... ...
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:sheet/sheet.dart';
import '../../helpers.dart';
void main() {
group('SheetMediaQuery', () {
testWidgets('top padding is zero if sheet is not inside top safe area',
(tester) async {
final childKey = UniqueKey();
await tester.pumpWidget(
MaterialApp(
home: MediaQuery(
data: MediaQueryData(padding: EdgeInsets.only(top: 20)),
child: Sheet(
child: SheetMediaQuery(
child: SizedBox.expand(key: childKey),
),
),
),
),
);
await tester.pumpAndSettle();
final context = tester.element(find.byKey(childKey));
expect(MediaQuery.of(context).padding.top, 0);
});
testWidgets(
'top padding is same as top safe area if sheet is fully open '
'before viewportDimension is rendered', (tester) async {
// viewportDimension is not available in first frame
final childKey = UniqueKey();
await tester.pumpWidget(
MaterialApp(
home: MediaQuery(
data: MediaQueryData(padding: EdgeInsets.only(top: 20)),
child: Sheet(
initialExtent: 600,
child: SheetMediaQuery(
child: SizedBox.expand(key: childKey),
),
),
),
),
);
await tester.pumpAndSettle();
final context = tester.element(find.byKey(childKey));
expect(MediaQuery.of(context).padding.top, 20);
});
testWidgets(
'top padding is same as top safe area if sheet is fully open '
'after viewportDimension is rendered', (tester) async {
final childKey = UniqueKey();
await tester.pumpWidget(
MaterialApp(
home: MediaQuery(
data: MediaQueryData(padding: EdgeInsets.only(top: 20)),
child: Sheet(
child: SheetMediaQuery(
child: SizedBox.expand(key: childKey),
),
),
),
),
);
tester.getSheetController().relativeJumpTo(1);
await tester.pumpAndSettle();
final context = tester.element(find.byKey(childKey));
expect(MediaQuery.of(context).padding.top, 20);
});
testWidgets('top padding increase is lineal', (tester) async {
final offsetToTest = 10.0;
final childKey = UniqueKey();
await tester.pumpWidget(
MaterialApp(
home: MediaQuery(
data: MediaQueryData(padding: EdgeInsets.only(top: 20)),
child: Sheet(
initialExtent: 600 - offsetToTest,
child: SizedBox(
child: SheetMediaQuery(
child: SizedBox.expand(key: childKey),
),
),
),
),
),
);
await tester.pumpAndSettle();
final context = tester.element(find.byKey(childKey));
expect(MediaQuery.of(context).padding.top, 20 - offsetToTest);
});
});
}
... ...