From 2a1bda246d9404b5df5950ea0f64320c4ccba5e1 Mon Sep 17 00:00:00 2001 From: Kolya Paradiuk Date: Thu, 28 Dec 2023 08:22:16 +0200 Subject: [PATCH 1/3] add tests for auth_code, bottom_sheet, button, carousel, checkbox, chip, drawer, menu_item, modal, popover --- test/auth_code_test.dart | 97 +++++++++++++++++++++++++ test/bottom_sheet_test.dart | 136 ++++++++++++++++++++++++++++++++++ test/button_test.dart | 117 ++++++++++++++++++++++++++++++ test/carousel_test.dart | 74 +++++++++++++++++++ test/checkbox_test.dart | 141 ++++++++++++++++++++++++++++++++++++ test/chip_test.dart | 71 ++++++++++++++++++ test/drawer_test.dart | 104 ++++++++++++++++++++++++++ test/menu_item_test.dart | 86 ++++++++++++++++++++++ test/modal_test.dart | 139 +++++++++++++++++++++++++++++++++++ test/popover_test.dart | 122 +++++++++++++++++++++++++++++++ 10 files changed, 1087 insertions(+) create mode 100644 test/auth_code_test.dart create mode 100644 test/bottom_sheet_test.dart create mode 100644 test/button_test.dart create mode 100644 test/carousel_test.dart create mode 100644 test/checkbox_test.dart create mode 100644 test/chip_test.dart create mode 100644 test/drawer_test.dart create mode 100644 test/menu_item_test.dart create mode 100644 test/modal_test.dart create mode 100644 test/popover_test.dart diff --git a/test/auth_code_test.dart b/test/auth_code_test.dart new file mode 100644 index 00000000..0c7bb2e5 --- /dev/null +++ b/test/auth_code_test.dart @@ -0,0 +1,97 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:moon_design/moon_design.dart'; + +void main() { + const key = Key("auth_code_test"); + + testWidgets("Provided key is used", (tester) async { + await tester.pumpWidget( + const TestWidget( + authCodeKey: key, + ), + ); + expect(find.byKey(key), findsOneWidget); + }); + + testWidgets("Enter valid code", (tester) async { + await tester.pumpWidget( + const TestWidget( + authCodeKey: key, + ), + ); + final widget = find.byType(TextFormField).first; + await tester.enterText(widget, '9921'); + await tester.pump(const Duration(milliseconds: 110)); + expect(find.text(errorMessage), findsNothing); + }); + testWidgets("Enter invalid code", (tester) async { + await tester.pumpWidget( + const TestWidget( + authCodeKey: key, + ), + ); + final widget = find.byType(TextFormField).first; + await tester.enterText(widget, '1111'); + await tester.pump(const Duration(milliseconds: 110)); + expect(find.text(errorMessage), findsOneWidget); + }); + + testWidgets("Initial error message", (tester) async { + await tester.pumpWidget( + const TestWidget( + authCodeKey: key, + initialErrorMessage: initialErrorMessage, + ), + ); + final widget = find.byType(TextFormField).first; + expect(find.text(initialErrorMessage), findsOneWidget); + await tester.enterText(widget, '1111'); + await tester.pump(const Duration(milliseconds: 110)); + expect(find.text(initialErrorMessage), findsNothing); + expect(find.text(errorMessage), findsOneWidget); + }); +} + +const errorMessage = 'Invalid authentication code. Please try again.'; +const initialErrorMessage = 'Initial error message'; + +class TestWidget extends StatelessWidget { + const TestWidget({ + super.key, + this.authCodeKey, + this.initialErrorMessage, + }); + + final Key? authCodeKey; + final String? initialErrorMessage; + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + body: Directionality( + textDirection: TextDirection.ltr, + child: MoonAuthCode( + key: authCodeKey, + authInputFieldCount: 4, + autoFocus: true, + enableInputFill: true, + validator: (String? pin) { + return pin?.length == 4 && pin != '9921' ? errorMessage : null; + }, + errorText: initialErrorMessage, + errorBuilder: (BuildContext context, String? errorText) { + return Align( + child: Padding( + padding: const EdgeInsets.only(top: 8), + child: Text(errorText ?? ''), + ), + ); + }, + ), + ), + ), + ); + } +} diff --git a/test/bottom_sheet_test.dart b/test/bottom_sheet_test.dart new file mode 100644 index 00000000..2c5c176b --- /dev/null +++ b/test/bottom_sheet_test.dart @@ -0,0 +1,136 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:moon_design/moon_design.dart'; + +// Test +void main() { + const key = Key("bottom_sheet_test"); + + testWidgets("Botton sheet is shown after clicking on button", (tester) async { + await tester.pumpWidget(const TestWidget(key: key, content: content)); + final button = find.byType(MoonFilledButton); + + expect(button, findsOneWidget); + + await tester.tap(button); + await tester.pumpAndSettle(); + + expect(find.byWidget(content), findsOneWidget); + }); + + testWidgets("Botton sheet is hidden after clicking outside content", + (tester) async { + await tester.pumpWidget(const TestWidget(key: key, content: content)); + final button = find.byType(MoonFilledButton); + + expect(button, findsOneWidget); + + await tester.tap(button); + await tester.pumpAndSettle(); + + expect(find.byWidget(content), findsOneWidget); + + await tester.tapAt(const Offset(10, 10)); + await tester.pumpAndSettle(); + + expect(find.byWidget(content), findsNothing); + }); + + testWidgets( + "Botton sheet is not hidden after clicking outside content if not dismissable", + (tester) async { + await tester.pumpWidget( + const TestWidget( + key: key, + content: content, + isDismissible: false, + ), + ); + final button = find.byType(MoonFilledButton); + + expect(button, findsOneWidget); + + await tester.tap(button); + await tester.pumpAndSettle(); + + expect(find.byWidget(content), findsOneWidget); + + await tester.tapAt(const Offset(10, 10)); + await tester.pumpAndSettle(); + + expect(find.byWidget(content), findsOneWidget); + }); + testWidgets("Botton sheet is expanded", (tester) async { + await tester.pumpWidget( + const TestWidget( + key: key, + content: content, + isExpanded: true, + ), + ); + final button = find.byType(MoonFilledButton); + + expect(button, findsOneWidget); + + await tester.tap(button); + await tester.pumpAndSettle(); + + expect(find.byWidget(content), findsOneWidget); + + await tester.tapAt(const Offset(1, 1)); + await tester.pumpAndSettle(); + + expect(find.byWidget(content), findsOneWidget); + + await tester.tapAt(const Offset(100, 1)); + await tester.pumpAndSettle(); + + expect(find.byWidget(content), findsOneWidget); + }); +} + +const String bottomSheetText = "Botton sheet content"; +const Widget content = Text(bottomSheetText); + +class TestWidget extends StatelessWidget { + final Widget content; + final bool isDismissible; + final bool isExpanded; + + const TestWidget({ + required this.content, + this.isDismissible = true, + this.isExpanded = false, + super.key, + }); + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + body: Center( + child: StatefulBuilder( + builder: (context, setState) { + return MoonFilledButton( + label: const Text("Tap me"), + onTap: () => bottomSheetBuilder(context), + ); + }, + ), + ), + ), + ); + } + + Future bottomSheetBuilder(BuildContext context) { + return showMoonModalBottomSheet( + isExpanded: isExpanded, + context: context, + backgroundColor: Colors.black38, + enableDrag: true, + isDismissible: isDismissible, + height: MediaQuery.of(context).size.height * 0.5, + builder: (BuildContext context) => content, + ); + } +} diff --git a/test/button_test.dart b/test/button_test.dart new file mode 100644 index 00000000..0ef50b95 --- /dev/null +++ b/test/button_test.dart @@ -0,0 +1,117 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:moon_design/moon_design.dart'; + +void main() { + const key = Key("button_test"); + + testWidgets("Provided key is used", (tester) async { + await tester.pumpWidget( + const TestWidget( + key: key, + ), + ); + expect(find.byKey(key), findsOneWidget); + }); + + testWidgets("Button with leading, trailing, label", (tester) async { + await tester.pumpWidget( + const TestWidget( + showLeading: true, + showLabel: true, + showTrailing: true, + ), + ); + expect(find.text(buttonLabel), findsOneWidget); + expect(find.byIcon(trailingIcon), findsOneWidget); + expect(find.byIcon(leadinIcon), findsOneWidget); + }); + + testWidgets("Button tap", (tester) async { + bool tapped = false; + await tester.pumpWidget( + TestWidget( + onTap: () => tapped = true, + ), + ); + await tester.tap(find.byType(MoonButton)); + await tester.pumpAndSettle(); + expect(tapped, true); + }); + + testWidgets("Button long press", (tester) async { + bool longPressed = false; + bool tapped = false; + await tester.pumpWidget( + TestWidget( + onLongPress: () => longPressed = true, + onTap: () => tapped = true, + ), + ); + await tester.longPress(find.byType(MoonButton)); + await tester.pumpAndSettle(); + expect(longPressed, true); + expect(tapped, false); + }); +} + +const String buttonLabel = "Button label"; +const IconData leadinIcon = MoonIcons.other_frame_24_light; +const IconData trailingIcon = MoonIcons.controls_close_small_24_light; + +class TestWidget extends StatefulWidget { + final bool showLeading; + final bool showTrailing; + final bool showLabel; + final VoidCallback? onTap; + final VoidCallback? onLongPress; + final Key? buttonKey; + + const TestWidget({ + super.key, + this.showLeading = false, + this.showTrailing = false, + this.showLabel = false, + this.buttonKey, + this.onTap, + this.onLongPress, + }); + @override + State createState() => _TestWidgetState(); +} + +class _TestWidgetState extends State { + bool _showAlert = true; + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + body: MoonButton( + key: widget.buttonKey, + onLongPress: widget.onLongPress, + onTap: widget.onTap, + leading: widget.showLeading ? const Icon(leadinIcon) : null, + label: widget.showLabel + ? const SizedBox( + height: 24, + child: Align( + alignment: AlignmentDirectional.centerStart, + child: Text(buttonLabel), + ), + ) + : null, + trailing: widget.showTrailing + ? MoonButton.icon( + buttonSize: MoonButtonSize.xs, + disabledOpacityValue: 1, + icon: const Icon(trailingIcon, size: 24), + gap: 0, + onTap: () => setState(() => _showAlert = !_showAlert), + ) + : null, + ), + ), + ); + } +} diff --git a/test/carousel_test.dart b/test/carousel_test.dart new file mode 100644 index 00000000..bab80ee4 --- /dev/null +++ b/test/carousel_test.dart @@ -0,0 +1,74 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:moon_design/moon_design.dart'; + +void main() { + const key = Key("button_test"); + + testWidgets( + "Provided key is used", + (tester) async { + await tester.pumpWidget( + const CarouselTestWidget( + widgetKey: key, + ), + ); + expect(find.byKey(key), findsOneWidget); + }, + ); + + testWidgets( + "Test scroll", + (tester) async { + await tester.pumpWidget( + const CarouselTestWidget( + widgetKey: key, + ), + ); + expect(find.text('1'), findsOneWidget); + expect(find.text('2'), findsOneWidget); + expect(find.text('3'), findsNothing); + await tester.drag(find.byKey(key), const Offset(-150, 0)); + await tester.pumpAndSettle(); + expect(find.text('1'), findsNothing); + expect(find.text('3'), findsOneWidget); + }, + ); +} + +class CarouselTestWidget extends StatelessWidget { + final Key? widgetKey; + + const CarouselTestWidget({super.key, this.widgetKey}); + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + body: SizedBox( + height: 114, + width: 200, + child: MoonCarousel( + key: widgetKey, + gap: 8, + itemCount: 10, + itemExtent: 100, + itemBuilder: (BuildContext context, int itemIndex, int realIndex) => + Container( + height: 100, + width: 100, + decoration: ShapeDecoration( + color: context.moonColors?.goku, + shape: MoonSquircleBorder( + borderRadius: + BorderRadius.circular(12).squircleBorderRadius(context), + ), + ), + child: Center( + child: Text("${itemIndex + 1}"), + ), + ), + ), + ), + )); + } +} diff --git a/test/checkbox_test.dart b/test/checkbox_test.dart new file mode 100644 index 00000000..bb8aeb35 --- /dev/null +++ b/test/checkbox_test.dart @@ -0,0 +1,141 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:moon_design/moon_design.dart'; + +void main() { + const key = Key("cehckbox_test"); + + testWidgets( + "Provided key is used", + (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + ), + ); + expect(find.byKey(key), findsOneWidget); + }, + ); + + testWidgets( + "Change checkbox value", + (tester) async { + bool? checkboxValue = false; + await tester.pumpWidget( + TestWidget( + widgetKey: key, + onChanged: (newValue) => checkboxValue = newValue, + ), + ); + final checkbox = find.byKey(key); + await tester.tap(checkbox); + await tester.pumpAndSettle(); + expect(checkboxValue, true); + + await tester.tap(checkbox); + await tester.pumpAndSettle(); + expect(checkboxValue, false); + }, + ); + + testWidgets( + "Change tristate checkbox value", + (tester) async { + bool? checkboxValue = false; + await tester.pumpWidget( + TestWidget( + widgetKey: key, + isTristate: true, + onChanged: (newValue) => checkboxValue = newValue, + ), + ); + final checkbox = find.byKey(key); + await tester.tap(checkbox); + await tester.pumpAndSettle(); + expect(checkboxValue, true); + + await tester.tap(checkbox); + await tester.pumpAndSettle(); + expect(checkboxValue, null); + + await tester.tap(checkbox); + await tester.pumpAndSettle(); + expect(checkboxValue, false); + }, + ); + + testWidgets( + "Check checkbox label", + (tester) async { + const label = 'Checkbox label'; + + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + label: label, + ), + ); + + expect(find.text(label), findsOneWidget); + }, + ); +} + +class TestWidget extends StatefulWidget { + final Key? widgetKey; + final void Function(bool?)? onChanged; + final bool isTristate; + final bool initialValue; + final String? label; + + const TestWidget({ + super.key, + this.widgetKey, + this.isTristate = false, + this.onChanged, + this.initialValue = false, + this.label, + }); + + @override + State createState() => _TestWidgetState(); +} + +class _TestWidgetState extends State { + bool? checkboxValue; + + @override + void initState() { + super.initState(); + checkboxValue = widget.initialValue; + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + body: widget.label != null + ? MoonCheckbox.withLabel( + context, + key: widget.widgetKey, + value: checkboxValue, + tristate: widget.isTristate, + onChanged: (bool? newValue) { + setState(() => checkboxValue = newValue); + widget.onChanged?.call(newValue); + }, + label: widget.label!, + ) + : MoonCheckbox( + key: widget.widgetKey, + value: checkboxValue, + tristate: widget.isTristate, + onChanged: (bool? newValue) { + setState(() => checkboxValue = newValue); + widget.onChanged?.call(newValue); + }, + ), + ), + ); + } +} diff --git a/test/chip_test.dart b/test/chip_test.dart new file mode 100644 index 00000000..5ba6f8fc --- /dev/null +++ b/test/chip_test.dart @@ -0,0 +1,71 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:moon_design/moon_design.dart'; + +void main() { + const key = Key("chip_test"); + + testWidgets("Provided key is used", (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + ), + ); + expect(find.byKey(key), findsOneWidget); + }); + + testWidgets("Simple chip", (tester) async { + await tester.pumpWidget( + const TestWidget( + showLabel: true, + ), + ); + + expect(find.text(label), findsOneWidget); + }); + + testWidgets("Chip with leading, trailing, body", (tester) async { + await tester.pumpWidget( + const TestWidget( + showLeading: true, + showLabel: true, + showTrailing: true, + ), + ); + expect(find.text(label), findsOneWidget); + expect(find.byIcon(trailingIcon), findsOneWidget); + expect(find.byIcon(leadinIcon), findsOneWidget); + }); +} + +const String label = "Label"; +const IconData leadinIcon = MoonIcons.other_frame_24_light; +const IconData trailingIcon = MoonIcons.controls_close_small_24_light; + +class TestWidget extends StatelessWidget { + final bool showLeading; + final bool showTrailing; + final bool showLabel; + final Key? widgetKey; + + const TestWidget({ + super.key, + this.showLeading = false, + this.showLabel = false, + this.showTrailing = false, + this.widgetKey, + }); + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + body: MoonChip( + key: widgetKey, + leading: showLeading ? const Icon(leadinIcon) : null, + label: showLabel ? const Text(label) : null, + trailing: showTrailing ? const Icon(trailingIcon) : null, + ), + ), + ); + } +} diff --git a/test/drawer_test.dart b/test/drawer_test.dart new file mode 100644 index 00000000..5fbb99b4 --- /dev/null +++ b/test/drawer_test.dart @@ -0,0 +1,104 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:moon_design/moon_design.dart'; + +void main() { + testWidgets("Drawer is shown after clicking on button", (tester) async { + await tester.pumpWidget(const TestWidget(content: content)); + final button = find.text(openButtonText); + + expect(button, findsOneWidget); + + await tester.tap(button); + await tester.pumpAndSettle(); + + expect(find.byWidget(content), findsOneWidget); + }); + + testWidgets("Drawer close after clicking outside", (tester) async { + await tester.pumpWidget(const TestWidget(content: content)); + final button = find.text(openButtonText); + + await tester.tap(button); + await tester.pumpAndSettle(); + + expect(find.byWidget(content), findsOneWidget); + await tester.tapAt(const Offset(210, 10)); + await tester.pumpAndSettle(); + expect(find.byWidget(content), findsNothing); + }); + + testWidgets("Drawer close after clicking on button", (tester) async { + await tester.pumpWidget(const TestWidget(content: content)); + final button = find.text(openButtonText); + + await tester.tap(button); + await tester.pumpAndSettle(); + + expect(find.byWidget(content), findsOneWidget); + await tester.tap(find.text(closeButtonText)); + await tester.pumpAndSettle(); + expect(find.byWidget(content), findsNothing); + }); +} + +const String contentText = "Drawer content"; +const String openButtonText = "Open"; +const String closeButtonText = "Close"; + +const Widget content = Text(contentText); + +class TestWidget extends StatelessWidget { + final Widget content; + + const TestWidget({ + required this.content, + super.key, + }); + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: OverflowBox( + maxHeight: MediaQuery.of(context).size.height, + maxWidth: MediaQuery.of(context).size.width, + child: Scaffold( + drawer: MoonDrawer( + width: 200, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + content, + const SizedBox(height: 32), + Builder( + builder: (BuildContext context) { + return MoonFilledButton( + label: const Text(closeButtonText), + onTap: () => Navigator.of(context).pop(), + ); + }, + ), + ], + ), + ), + body: Center( + child: Builder( + builder: (BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric( + vertical: 64.0, + horizontal: 16.0, + ), + child: MoonFilledButton( + label: const Text(openButtonText), + onTap: () => Scaffold.of(context).openDrawer(), + ), + ); + }, + ), + ), + ), + ), + ); + } +} diff --git a/test/menu_item_test.dart b/test/menu_item_test.dart new file mode 100644 index 00000000..fb7af6d2 --- /dev/null +++ b/test/menu_item_test.dart @@ -0,0 +1,86 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:moon_design/moon_design.dart'; + +void main() { + const key = Key("menu_item_test"); + + testWidgets("Provided key is used", (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + ), + ); + expect(find.byKey(key), findsOneWidget); + }); + + testWidgets("Simple menu item", (tester) async { + await tester.pumpWidget( + const TestWidget(), + ); + + expect(find.text(title), findsOneWidget); + }); + + testWidgets("Menu item with leading, trailing, description", (tester) async { + await tester.pumpWidget( + const TestWidget( + showLeading: true, + showDiscription: true, + showTrailing: true, + ), + ); + expect(find.text(description), findsOneWidget); + expect(find.byIcon(trailingIcon), findsOneWidget); + expect(find.byIcon(leadinIcon), findsOneWidget); + }); + + testWidgets("Tap menu item", (tester) async { + bool value = false; + await tester.pumpWidget( + TestWidget( + onTap: () => value = !value, + ), + ); + await tester.tap(find.byType(MoonMenuItem)); + await tester.pumpAndSettle(); + expect(value, true); + }); +} + +const String title = "Title"; +const String description = "Description"; +const IconData leadinIcon = MoonIcons.other_frame_24_light; +const IconData trailingIcon = MoonIcons.controls_close_small_24_light; + +class TestWidget extends StatelessWidget { + final bool showLeading; + final bool showTrailing; + final bool showDiscription; + final Key? widgetKey; + final VoidCallback? onTap; + + const TestWidget({ + super.key, + this.showLeading = false, + this.showDiscription = false, + this.showTrailing = false, + this.widgetKey, + this.onTap, + }); + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + body: MoonMenuItem( + key: widgetKey, + leading: showLeading ? const Icon(leadinIcon) : null, + description: showDiscription ? const Text(description) : null, + title: const Text(title), + trailing: showTrailing ? const Icon(trailingIcon) : null, + onTap: onTap, + ), + ), + ); + } +} diff --git a/test/modal_test.dart b/test/modal_test.dart new file mode 100644 index 00000000..5252d50b --- /dev/null +++ b/test/modal_test.dart @@ -0,0 +1,139 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:moon_design/moon_design.dart'; + +// Test +void main() { + const key = Key("modal_test"); + + testWidgets("Modal is shown after clicking on button", (tester) async { + await tester.pumpWidget(const TestWidget(key: key, content: content)); + final button = find.text(openButtonText); + + expect(button, findsOneWidget); + + await tester.tap(button); + await tester.pumpAndSettle(); + + expect(find.byWidget(content), findsOneWidget); + }); + + testWidgets("Modal is hidden after clicking outside content", (tester) async { + await tester.pumpWidget(const TestWidget(key: key, content: content)); + final button = find.text(openButtonText); + + expect(button, findsOneWidget); + + await tester.tap(button); + await tester.pumpAndSettle(); + + expect(find.byWidget(content), findsOneWidget); + + await tester.tapAt(const Offset(10, 10)); + await tester.pumpAndSettle(); + + expect(find.byWidget(content), findsNothing); + }); + + testWidgets( + "Modal is not hidden after clicking outside content if not dismissable", + (tester) async { + await tester.pumpWidget( + const TestWidget( + key: key, + content: content, + isDismissible: false, + ), + ); + final button = find.text(openButtonText); + + expect(button, findsOneWidget); + + await tester.tap(button); + await tester.pumpAndSettle(); + + expect(find.byWidget(content), findsOneWidget); + + await tester.tapAt(const Offset(10, 10)); + await tester.pumpAndSettle(); + + expect(find.byWidget(content), findsOneWidget); + }); + + testWidgets("Modal close after clicking on button", (tester) async { + await tester.pumpWidget(const TestWidget(content: content)); + final button = find.text(openButtonText); + + await tester.tap(button); + await tester.pumpAndSettle(); + + expect(find.byWidget(content), findsOneWidget); + await tester.tap(find.text(closeButtonText)); + await tester.pumpAndSettle(); + expect(find.byWidget(content), findsNothing); + }); +} + +const String contentText = "Content"; +const Widget content = Text(contentText); +const String openButtonText = "Open"; +const String closeButtonText = "Close"; + +class TestWidget extends StatelessWidget { + final Widget content; + final bool isDismissible; + + const TestWidget({ + required this.content, + this.isDismissible = true, + super.key, + }); + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + body: Center( + child: StatefulBuilder( + builder: (context, setState) { + return MoonFilledButton( + label: const Text(openButtonText), + onTap: () => modalBuilder(context), + ); + }, + ), + ), + ), + ); + } + + Future modalBuilder(BuildContext context) { + return showMoonModal( + context: context, + barrierDismissible: isDismissible, + useRootNavigator: false, + builder: (BuildContext _) { + return Directionality( + textDirection: Directionality.of(context), + child: MoonModal( + child: SizedBox( + width: 300, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + content, + MoonFilledButton( + label: const Text(closeButtonText), + isFullWidth: true, + onTap: () => Navigator.of(context).pop(), + ), + ], + ), + ), + ), + ); + }, + ); + } +} diff --git a/test/popover_test.dart b/test/popover_test.dart new file mode 100644 index 00000000..24e551fd --- /dev/null +++ b/test/popover_test.dart @@ -0,0 +1,122 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:moon_design/moon_design.dart'; + +// Test +void main() { + const key = Key("popover_test"); + + testWidgets("Provided key is used", (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + content: content, + ), + ); + expect(find.byKey(key), findsOneWidget); + }); + testWidgets("Popover is shown after clicking on button", (tester) async { + await tester.pumpWidget(const TestWidget(key: key, content: content)); + final button = find.text(openButtonText); + + expect(button, findsOneWidget); + + await tester.tap(button); + await tester.pumpAndSettle(); + + expect(find.byWidget(content), findsOneWidget); + }); + + testWidgets("Popover is hidden after clicking outside content", + (tester) async { + await tester.pumpWidget(const TestWidget(key: key, content: content)); + final button = find.text(openButtonText); + + expect(button, findsOneWidget); + + await tester.tap(button); + await tester.pumpAndSettle(); + + expect(find.byWidget(content), findsOneWidget); + + await tester.tapAt(const Offset(10, 10)); + await tester.pumpAndSettle(); + + expect(find.byWidget(content), findsNothing); + }); + + testWidgets("Popover is hidden after clicking on button", (tester) async { + await tester.pumpWidget(const TestWidget(content: content)); + final button = find.text(openButtonText); + + await tester.tap(button); + await tester.pumpAndSettle(); + + expect(find.byWidget(content), findsOneWidget); + await tester.tap(find.text(closeButtonText)); + await tester.pumpAndSettle(); + expect(find.byWidget(content), findsNothing); + }); +} + +const String contentText = "Content"; +const Widget content = Text(contentText); +const String openButtonText = "Open"; +const String closeButtonText = "Close"; + +class TestWidget extends StatefulWidget { + final Widget content; + final bool isDismissible; + final Key? widgetKey; + + const TestWidget({ + required this.content, + this.isDismissible = true, + this.widgetKey, + super.key, + }); + + @override + State createState() => _TestWidgetState(); +} + +class _TestWidgetState extends State { + bool show = false; + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + body: Center( + child: MoonPopover( + key: widget.widgetKey, + show: show, + onTapOutside: widget.isDismissible + ? () => setState(() => show = false) + : null, + content: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 190), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + widget.content, + const SizedBox(height: 16), + MoonFilledButton( + buttonSize: MoonButtonSize.sm, + isFullWidth: true, + onTap: () => setState(() => show = false), + label: const Text(closeButtonText), + ), + ], + ), + ), + child: MoonFilledButton( + onTap: () => setState(() => show = !show), + label: const Text(openButtonText), + ), + ), + ), + ), + ); + } +} From e8e7283eb996c11f979310a7593146651634c04d Mon Sep 17 00:00:00 2001 From: Kolya Paradiuk Date: Thu, 28 Dec 2023 11:19:45 +0200 Subject: [PATCH 2/3] fix analyze issue --- test/carousel_test.dart | 45 +++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/test/carousel_test.dart b/test/carousel_test.dart index bab80ee4..064cbd15 100644 --- a/test/carousel_test.dart +++ b/test/carousel_test.dart @@ -43,32 +43,33 @@ class CarouselTestWidget extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( - home: Scaffold( - body: SizedBox( - height: 114, - width: 200, - child: MoonCarousel( - key: widgetKey, - gap: 8, - itemCount: 10, - itemExtent: 100, - itemBuilder: (BuildContext context, int itemIndex, int realIndex) => - Container( - height: 100, - width: 100, - decoration: ShapeDecoration( - color: context.moonColors?.goku, - shape: MoonSquircleBorder( - borderRadius: - BorderRadius.circular(12).squircleBorderRadius(context), + home: Scaffold( + body: SizedBox( + height: 114, + width: 200, + child: MoonCarousel( + key: widgetKey, + gap: 8, + itemCount: 10, + itemExtent: 100, + itemBuilder: (BuildContext context, int itemIndex, int realIndex) => + Container( + height: 100, + width: 100, + decoration: ShapeDecoration( + color: context.moonColors?.goku, + shape: MoonSquircleBorder( + borderRadius: + BorderRadius.circular(12).squircleBorderRadius(context), + ), + ), + child: Center( + child: Text("${itemIndex + 1}"), ), - ), - child: Center( - child: Text("${itemIndex + 1}"), ), ), ), ), - )); + ); } } From d5967c30bf8de40030efa38c8404ba10bf8948bd Mon Sep 17 00:00:00 2001 From: Kolya Paradiuk Date: Wed, 3 Jan 2024 08:56:16 +0200 Subject: [PATCH 3/3] add tests for toast, text input, text area, tag, tab bar, switch, segment control, radio --- test/alert_test.dart | 6 +- test/button_test.dart | 6 +- test/chip_test.dart | 6 +- test/menu_item_test.dart | 6 +- test/radio_test.dart | 206 +++++++++++++++++++++++++++++++ test/segmented_control_test.dart | 142 +++++++++++++++++++++ test/switch_test.dart | 83 +++++++++++++ test/tab_bar_test.dart | 150 ++++++++++++++++++++++ test/tag_test.dart | 87 +++++++++++++ test/text_area_test.dart | 171 +++++++++++++++++++++++++ test/text_input_test.dart | 189 ++++++++++++++++++++++++++++ test/toast_test.dart | 59 +++++++++ 12 files changed, 1099 insertions(+), 12 deletions(-) create mode 100644 test/radio_test.dart create mode 100644 test/segmented_control_test.dart create mode 100644 test/switch_test.dart create mode 100644 test/tab_bar_test.dart create mode 100644 test/tag_test.dart create mode 100644 test/text_area_test.dart create mode 100644 test/text_input_test.dart create mode 100644 test/toast_test.dart diff --git a/test/alert_test.dart b/test/alert_test.dart index e933c041..78a44d29 100644 --- a/test/alert_test.dart +++ b/test/alert_test.dart @@ -37,7 +37,7 @@ void main() { expect(find.text(alertTitle), findsOneWidget); expect(find.text(alertBody), findsOneWidget); expect(find.byIcon(trailingIcon), findsOneWidget); - expect(find.byIcon(leadinIcon), findsOneWidget); + expect(find.byIcon(leadingIcon), findsOneWidget); }); testWidgets("Hide alert", (tester) async { @@ -59,7 +59,7 @@ void main() { const String alertTitle = "Alert title"; const String alertBody = "Alert body"; -const IconData leadinIcon = MoonIcons.other_frame_24_light; +const IconData leadingIcon = MoonIcons.other_frame_24_light; const IconData trailingIcon = MoonIcons.controls_close_small_24_light; class TestWidget extends StatefulWidget { @@ -86,7 +86,7 @@ class _TestWidgetState extends State { home: Scaffold( body: MoonAlert( show: _showAlert, - leading: widget.showLeading ? const Icon(leadinIcon) : null, + leading: widget.showLeading ? const Icon(leadingIcon) : null, title: const SizedBox( height: 24, child: Align( diff --git a/test/button_test.dart b/test/button_test.dart index 0ef50b95..e8ab76cb 100644 --- a/test/button_test.dart +++ b/test/button_test.dart @@ -24,7 +24,7 @@ void main() { ); expect(find.text(buttonLabel), findsOneWidget); expect(find.byIcon(trailingIcon), findsOneWidget); - expect(find.byIcon(leadinIcon), findsOneWidget); + expect(find.byIcon(leadingIcon), findsOneWidget); }); testWidgets("Button tap", (tester) async { @@ -56,7 +56,7 @@ void main() { } const String buttonLabel = "Button label"; -const IconData leadinIcon = MoonIcons.other_frame_24_light; +const IconData leadingIcon = MoonIcons.other_frame_24_light; const IconData trailingIcon = MoonIcons.controls_close_small_24_light; class TestWidget extends StatefulWidget { @@ -91,7 +91,7 @@ class _TestWidgetState extends State { key: widget.buttonKey, onLongPress: widget.onLongPress, onTap: widget.onTap, - leading: widget.showLeading ? const Icon(leadinIcon) : null, + leading: widget.showLeading ? const Icon(leadingIcon) : null, label: widget.showLabel ? const SizedBox( height: 24, diff --git a/test/chip_test.dart b/test/chip_test.dart index 5ba6f8fc..bfe77be6 100644 --- a/test/chip_test.dart +++ b/test/chip_test.dart @@ -34,12 +34,12 @@ void main() { ); expect(find.text(label), findsOneWidget); expect(find.byIcon(trailingIcon), findsOneWidget); - expect(find.byIcon(leadinIcon), findsOneWidget); + expect(find.byIcon(leadingIcon), findsOneWidget); }); } const String label = "Label"; -const IconData leadinIcon = MoonIcons.other_frame_24_light; +const IconData leadingIcon = MoonIcons.other_frame_24_light; const IconData trailingIcon = MoonIcons.controls_close_small_24_light; class TestWidget extends StatelessWidget { @@ -61,7 +61,7 @@ class TestWidget extends StatelessWidget { home: Scaffold( body: MoonChip( key: widgetKey, - leading: showLeading ? const Icon(leadinIcon) : null, + leading: showLeading ? const Icon(leadingIcon) : null, label: showLabel ? const Text(label) : null, trailing: showTrailing ? const Icon(trailingIcon) : null, ), diff --git a/test/menu_item_test.dart b/test/menu_item_test.dart index fb7af6d2..2b5710a5 100644 --- a/test/menu_item_test.dart +++ b/test/menu_item_test.dart @@ -32,7 +32,7 @@ void main() { ); expect(find.text(description), findsOneWidget); expect(find.byIcon(trailingIcon), findsOneWidget); - expect(find.byIcon(leadinIcon), findsOneWidget); + expect(find.byIcon(leadingIcon), findsOneWidget); }); testWidgets("Tap menu item", (tester) async { @@ -50,7 +50,7 @@ void main() { const String title = "Title"; const String description = "Description"; -const IconData leadinIcon = MoonIcons.other_frame_24_light; +const IconData leadingIcon = MoonIcons.other_frame_24_light; const IconData trailingIcon = MoonIcons.controls_close_small_24_light; class TestWidget extends StatelessWidget { @@ -74,7 +74,7 @@ class TestWidget extends StatelessWidget { home: Scaffold( body: MoonMenuItem( key: widgetKey, - leading: showLeading ? const Icon(leadinIcon) : null, + leading: showLeading ? const Icon(leadingIcon) : null, description: showDiscription ? const Text(description) : null, title: const Text(title), trailing: showTrailing ? const Icon(trailingIcon) : null, diff --git a/test/radio_test.dart b/test/radio_test.dart new file mode 100644 index 00000000..f29f429b --- /dev/null +++ b/test/radio_test.dart @@ -0,0 +1,206 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:moon_design/moon_design.dart'; + +enum Choice { first, second } + +void main() { + const firstKey = Key("first_radio_test"); + const secondKey = Key("second_radio_test"); + + Finder findSelecterFirstRadio() { + return find.byWidgetPredicate( + (widget) => + widget is MoonRadio && + widget.key == firstKey && + widget.value == Choice.first && + widget.groupValue == Choice.first, + ); + } + + Finder findSelecterSecondRadio() { + return find.byWidgetPredicate( + (widget) => + widget is MoonRadio && + widget.key == secondKey && + widget.value == Choice.second && + widget.groupValue == Choice.second, + ); + } + + testWidgets("Provided key is used", (tester) async { + await tester.pumpWidget( + const TestRadioWidget( + firstRadioKey: firstKey, + ), + ); + + expect( + find.byWidgetPredicate( + (widget) => widget is MoonRadio && widget.key == firstKey, + ), + findsOneWidget, + ); + }); + + testWidgets("Test radio with label", (tester) async { + await tester.pumpWidget( + const TestRadioWithLabelWidget(), + ); + + expect(find.text(label1), findsOneWidget); + expect(find.text(label2), findsOneWidget); + }); + + testWidgets("Test radio switch", (tester) async { + await tester.pumpWidget( + const TestRadioWidget( + firstRadioKey: firstKey, + secondRadioKey: secondKey, + ), + ); + + await tester.tap(find.byKey(firstKey)); + await tester.pumpAndSettle(); + + expect( + findSelecterFirstRadio(), + findsOneWidget, + ); + + await tester.tap(find.byKey(secondKey)); + await tester.pumpAndSettle(); + expect(findSelecterFirstRadio(), findsNothing); + expect(findSelecterSecondRadio(), findsOneWidget); + await tester.tap(find.byKey(secondKey)); + await tester.pumpAndSettle(); + expect(findSelecterFirstRadio(), findsNothing); + expect(findSelecterSecondRadio(), findsOneWidget); + }); + + testWidgets("Test toggable radio switch", (tester) async { + await tester.pumpWidget( + const TestRadioWidget( + firstRadioKey: firstKey, + secondRadioKey: secondKey, + toggleable: true, + ), + ); + + await tester.tap(find.byKey(firstKey)); + await tester.pumpAndSettle(); + + expect( + findSelecterFirstRadio(), + findsOneWidget, + ); + + await tester.tap(find.byKey(secondKey)); + await tester.pumpAndSettle(); + expect(findSelecterFirstRadio(), findsNothing); + expect(findSelecterSecondRadio(), findsOneWidget); + await tester.tap(find.byKey(secondKey)); + await tester.pumpAndSettle(); + expect(findSelecterFirstRadio(), findsNothing); + expect(findSelecterSecondRadio(), findsNothing); + }); +} + +class TestRadioWidget extends StatefulWidget { + final bool toggleable; + + final Key? firstRadioKey; + final Key? secondRadioKey; + const TestRadioWidget({ + super.key, + this.toggleable = false, + this.firstRadioKey, + this.secondRadioKey, + }); + @override + State createState() => _TestRadioWidgetState(); +} + +class _TestRadioWidgetState extends State { + Choice? value; + @override + Widget build(BuildContext context) { + // TODO: implement build + return MaterialApp( + home: Scaffold( + body: Center( + child: SingleChildScrollView( + padding: + const EdgeInsets.symmetric(vertical: 64.0, horizontal: 16.0), + child: Column( + children: [ + MoonRadio( + key: widget.firstRadioKey, + value: Choice.first, + groupValue: value, + onChanged: (Choice? choice) => setState(() => value = choice), + toggleable: widget.toggleable, + ), + const SizedBox(height: 8), + MoonRadio( + value: Choice.second, + key: widget.secondRadioKey, + groupValue: value, + onChanged: (Choice? choice) => setState(() => value = choice), + toggleable: widget.toggleable, + ), + ], + ), + ), + ), + ), + ); + } +} + +const label1 = 'Label 1'; +const label2 = 'Label 2'; + +class TestRadioWithLabelWidget extends StatefulWidget { + const TestRadioWithLabelWidget({super.key}); + @override + State createState() => + _TestRadioWithLabelWidgetState(); +} + +class _TestRadioWithLabelWidgetState extends State { + Choice? value; + @override + Widget build(BuildContext context) { + // TODO: implement build + return MaterialApp( + home: Scaffold( + body: Center( + child: SingleChildScrollView( + padding: + const EdgeInsets.symmetric(vertical: 64.0, horizontal: 16.0), + child: Column( + children: [ + MoonRadio.withLabel( + context, + label: label1, + value: Choice.first, + groupValue: value, + onChanged: (Choice? choice) => setState(() => value = choice), + ), + const SizedBox(height: 8), + MoonRadio.withLabel( + context, + value: Choice.second, + label: label2, + groupValue: value, + onChanged: (Choice? choice) => setState(() => value = choice), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/test/segmented_control_test.dart b/test/segmented_control_test.dart new file mode 100644 index 00000000..47831cf5 --- /dev/null +++ b/test/segmented_control_test.dart @@ -0,0 +1,142 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:moon_design/moon_design.dart'; + +void main() { + const key = Key("segment_control_test"); + + testWidgets("Provided key is used", (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + ), + ); + + expect( + find.byWidgetPredicate( + (widget) => widget is MoonSegmentedControl && widget.key == key, + ), + findsOneWidget, + ); + }); + + testWidgets("Segment with leading, trailing, label", (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + showLabel: true, + showLeading: true, + showTrailing: true, + ), + ); + + expect(find.textContaining(label), findsWidgets); + expect(find.byIcon(leadingIcon), findsWidgets); + expect(find.byIcon(trailingIcon), findsWidgets); + }); + + testWidgets("Press segment", (tester) async { + var value = 0; + await tester.pumpWidget( + TestWidget( + widgetKey: key, + showLabel: true, + onTap: (index) => value = index, + ), + ); + + await tester.tap(find.text('$label 2')); + await tester.pumpAndSettle(); + + expect(value, 1); + + await tester.tap(find.text('$label 1')); + await tester.pumpAndSettle(); + + expect(value, 0); + + await tester.tap(find.text('$label 3')); + await tester.pumpAndSettle(); + + expect(value, 2); + }); + + testWidgets("Disabled press segment", (tester) async { + var value = 0; + await tester.pumpWidget( + TestWidget( + widgetKey: key, + showLabel: true, + isDisabled: true, + onTap: (index) => value = index, + ), + ); + + await tester.tap(find.text('$label 2')); + await tester.pumpAndSettle(); + + expect(value, 0); + + await tester.tap(find.text('$label 1')); + await tester.pumpAndSettle(); + + expect(value, 0); + + await tester.tap(find.text('$label 3')); + await tester.pumpAndSettle(); + + expect(value, 0); + }); +} + +const String label = "Label"; +const IconData leadingIcon = MoonIcons.other_frame_24_light; +const IconData trailingIcon = MoonIcons.controls_close_small_24_light; + +class TestWidget extends StatelessWidget { + final bool showLeading; + final bool showTrailing; + final bool showLabel; + final Key? widgetKey; + final void Function(int)? onTap; + final bool isDisabled; + + const TestWidget({ + super.key, + this.showLeading = false, + this.showLabel = false, + this.showTrailing = false, + this.widgetKey, + this.onTap, + this.isDisabled = false, + }); + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + body: MoonSegmentedControl( + onSegmentChanged: onTap, + key: widgetKey, + isDisabled: isDisabled, + segments: [ + Segment( + leading: showLeading ? const Icon(leadingIcon) : null, + label: showLabel ? const Text('$label 1') : null, + trailing: showTrailing ? const Icon(trailingIcon) : null, + ), + Segment( + leading: showLeading ? const Icon(leadingIcon) : null, + label: showLabel ? const Text('$label 2') : null, + trailing: showTrailing ? const Icon(trailingIcon) : null, + ), + Segment( + leading: showLeading ? const Icon(leadingIcon) : null, + label: showLabel ? const Text('$label 3') : null, + trailing: showTrailing ? const Icon(trailingIcon) : null, + ), + ], + ), + ), + ); + } +} diff --git a/test/switch_test.dart b/test/switch_test.dart new file mode 100644 index 00000000..5c64879d --- /dev/null +++ b/test/switch_test.dart @@ -0,0 +1,83 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:moon_design/moon_design.dart'; + +void main() { + const key = Key("switch_test"); + + testWidgets("Provided key is used", (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + ), + ); + + expect( + find.byWidgetPredicate( + (widget) => widget is MoonSwitch && widget.key == key, + ), + findsOneWidget, + ); + }); + + testWidgets("Toggle switch", (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + ), + ); + + expect( + find.byWidgetPredicate( + (widget) => widget is MoonSwitch && widget.value == true, + ), + findsOneWidget, + ); + + await tester.tap(find.byKey(key)); + await tester.pumpAndSettle(); + + expect( + find.byWidgetPredicate( + (widget) => widget is MoonSwitch && widget.value == false, + ), + findsOneWidget, + ); + + await tester.tap(find.byKey(key)); + await tester.pumpAndSettle(); + + expect( + find.byWidgetPredicate( + (widget) => widget is MoonSwitch && widget.value == true, + ), + findsOneWidget, + ); + }); +} + +class TestWidget extends StatefulWidget { + final Key? widgetKey; + + const TestWidget({super.key, this.widgetKey}); + + @override + State createState() => _TestWidgetState(); +} + +class _TestWidgetState extends State { + var _switchValue = true; + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + body: MoonSwitch( + key: widget.widgetKey, + value: _switchValue, + onChanged: (bool newValue) => setState(() => _switchValue = newValue), + ), + ), + ); + } +} diff --git a/test/tab_bar_test.dart b/test/tab_bar_test.dart new file mode 100644 index 00000000..faace2b3 --- /dev/null +++ b/test/tab_bar_test.dart @@ -0,0 +1,150 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:moon_design/moon_design.dart'; + +void main() { + const key = Key("tab_bar_test"); + + testWidgets("Provided key is used", (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + ), + ); + + expect( + find.byWidgetPredicate( + (widget) => widget is MoonTabBar && widget.key == key, + ), + findsOneWidget, + ); + }); + + testWidgets("Tab bar with leading, trailing, label", (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + showLabel: true, + showLeading: true, + showTrailing: true, + ), + ); + + expect(find.textContaining(label), findsWidgets); + expect(find.byIcon(leadingIcon), findsWidgets); + expect(find.byIcon(trailingIcon), findsWidgets); + }); + + testWidgets("Press tab", (tester) async { + var value = 0; + await tester.pumpWidget( + TestWidget( + widgetKey: key, + showLabel: true, + onTap: (index) => value = index, + ), + ); + + await tester.tap(find.text('$label 2')); + await tester.pumpAndSettle(); + + expect(value, 1); + + await tester.tap(find.text('$label 1')); + await tester.pumpAndSettle(); + + expect(value, 0); + + await tester.tap(find.text('$label 3')); + await tester.pumpAndSettle(); + + expect(value, 2); + }); + + testWidgets("Disabled press tab", (tester) async { + var value = 0; + await tester.pumpWidget( + TestWidget( + widgetKey: key, + showLabel: true, + isDisabled: true, + onTap: (index) => value = index, + ), + ); + + await tester.tap(find.text('$label 2')); + await tester.pumpAndSettle(); + + expect(value, 0); + + await tester.tap(find.text('$label 1')); + await tester.pumpAndSettle(); + + expect(value, 0); + + await tester.tap(find.text('$label 3')); + await tester.pumpAndSettle(); + + expect(value, 0); + }); +} + +const String label = "Label"; +const IconData leadingIcon = MoonIcons.other_frame_24_light; +const IconData trailingIcon = MoonIcons.controls_close_small_24_light; + +class TestWidget extends StatelessWidget { + final bool showLeading; + final bool showTrailing; + final bool showLabel; + final Key? widgetKey; + final void Function(int)? onTap; + final bool isDisabled; + + const TestWidget({ + super.key, + this.showLeading = false, + this.showLabel = false, + this.showTrailing = false, + this.widgetKey, + this.onTap, + this.isDisabled = false, + }); + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + body: MoonTabBar( + key: widgetKey, + onTabChanged: onTap, + tabs: [ + MoonTab( + leading: showLeading ? const Icon(leadingIcon) : null, + label: showLabel ? const Text('$label 1') : null, + trailing: showTrailing ? const Icon(trailingIcon) : null, + disabled: isDisabled, + ), + MoonTab( + leading: showLeading ? const Icon(leadingIcon) : null, + label: showLabel ? const Text('$label 2') : null, + trailing: showTrailing ? const Icon(trailingIcon) : null, + disabled: isDisabled, + ), + MoonTab( + leading: showLeading ? const Icon(leadingIcon) : null, + label: showLabel ? const Text('$label 3') : null, + trailing: showTrailing ? const Icon(trailingIcon) : null, + disabled: isDisabled, + ), + MoonTab( + leading: showLeading ? const Icon(leadingIcon) : null, + label: showLabel ? const Text('$label 4') : null, + trailing: showTrailing ? const Icon(trailingIcon) : null, + disabled: isDisabled, + ), + ], + ), + ), + ); + } +} diff --git a/test/tag_test.dart b/test/tag_test.dart new file mode 100644 index 00000000..b80f3edf --- /dev/null +++ b/test/tag_test.dart @@ -0,0 +1,87 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:moon_design/moon_design.dart'; + +void main() { + const key = Key("tag_test"); + + testWidgets("Provided key is used", (tester) async { + await tester.pumpWidget( + const Directionality( + textDirection: TextDirection.ltr, + child: MoonTag( + key: key, + label: Text(title), + ), + ), + ); + expect(find.byKey(key), findsOneWidget); + }); + + testWidgets("Simple tag", (tester) async { + await tester.pumpWidget( + const TestWidget(), + ); + + expect(find.text(title), findsOneWidget); + }); + + testWidgets("Tag with leading, trailing", (tester) async { + await tester.pumpWidget( + const TestWidget( + showLeading: true, + showTrailing: true, + ), + ); + expect(find.text(title), findsOneWidget); + expect(find.byIcon(trailingIcon), findsOneWidget); + expect(find.byIcon(leadingIcon), findsOneWidget); + }); + + testWidgets("Press tag", (tester) async { + bool isPressed = false; + await tester.pumpWidget( + TestWidget( + showTrailing: true, + onTap: () { + isPressed = true; + }, + ), + ); + + await tester.tap(find.byType(MoonTag)); + await tester.pumpAndSettle(); + expect(isPressed, true); + }); +} + +const String title = "Tag title"; +const IconData leadingIcon = MoonIcons.other_frame_24_light; +const IconData trailingIcon = MoonIcons.controls_close_small_24_light; + +class TestWidget extends StatelessWidget { + final bool showLeading; + final bool showTrailing; + + final VoidCallback? onTap; + + const TestWidget({ + super.key, + this.showLeading = false, + this.showTrailing = false, + this.onTap, + }); + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + body: MoonTag( + onTap: onTap, + leading: showLeading ? const Icon(leadingIcon) : null, + label: const Text(title), + trailing: showTrailing ? const Icon(trailingIcon) : null, + ), + ), + ); + } +} diff --git a/test/text_area_test.dart b/test/text_area_test.dart new file mode 100644 index 00000000..a83b7d4f --- /dev/null +++ b/test/text_area_test.dart @@ -0,0 +1,171 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:moon_design/moon_design.dart'; + +void main() { + const key = Key("text_area_test"); + + Future submit(WidgetTester tester) async { + await tester.tap(find.byType(MoonFilledButton)); + await tester.pumpAndSettle(); + } + + testWidgets("Provided key is used", (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + ), + ); + + expect( + find.byWidgetPredicate( + (widget) => widget is MoonTextArea && widget.key == key, + ), + findsOneWidget, + ); + }); + + testWidgets("Enter valid text", (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + ), + ); + + final textArea = find.byKey(key); + + await tester.enterText(textArea, validText); + await tester.pumpAndSettle(); + expect( + find.text(validText), + findsOneWidget, + ); + await submit(tester); + expect( + find.text(error), + findsNothing, + ); + }); + + testWidgets("Enter invalid text", (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + ), + ); + + final textArea = find.byKey(key); + + await tester.enterText(textArea, invalidText); + await tester.pumpAndSettle(); + expect( + find.text(invalidText), + findsOneWidget, + ); + await submit(tester); + expect( + find.text(error), + findsOneWidget, + ); + }); + + testWidgets("Check helper text", (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + showHelper: true, + ), + ); + + expect( + find.text(helper), + findsOneWidget, + ); + }); + + testWidgets("Check hint", (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + showHelper: true, + ), + ); + + expect( + find.text(hint), + findsOneWidget, + ); + }); + + testWidgets("Disabled: enter text", (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + enabled: false, + ), + ); + + final textArea = find.byKey(key); + + await tester.enterText(textArea, validText); + await tester.pumpAndSettle(); + expect( + find.text(validText), + findsNothing, + ); + }); +} + +const validText = + 'Lorem Ipsum is simply dummy text of the printing and typesetting industry'; +const invalidText = 'Lorem'; + +const hint = 'Hint'; +const error = 'Error'; +const helper = 'Helper'; + +class TestWidget extends StatelessWidget { + final bool enabled; + final bool showHelper; + final Key? widgetKey; + + const TestWidget({ + super.key, + this.enabled = true, + this.showHelper = false, + this.widgetKey, + }); + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + body: Form( + child: Builder( + builder: (BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + MoonTextArea( + key: widgetKey, + enabled: enabled, + hintText: hint, + validator: (String? value) => + value?.length != null && value!.length < 10 + ? error + : null, + helper: showHelper ? const Text(helper) : null, + ), + const SizedBox(height: 32), + MoonFilledButton( + label: const Text("Submit"), + onTap: () => Form.of(context).validate(), + ), + ], + ); + }, + ), + ), + ), + ); + } +} diff --git a/test/text_input_test.dart b/test/text_input_test.dart new file mode 100644 index 00000000..ae4271eb --- /dev/null +++ b/test/text_input_test.dart @@ -0,0 +1,189 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:moon_design/moon_design.dart'; + +void main() { + const key = Key("text_input_test"); + + Future submit(WidgetTester tester) async { + await tester.tap(find.byType(MoonFilledButton)); + await tester.pumpAndSettle(); + } + + testWidgets("Provided key is used", (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + ), + ); + + expect( + find.byWidgetPredicate( + (widget) => widget is MoonFormTextInput && widget.key == key, + ), + findsOneWidget, + ); + }); + + testWidgets("Enter valid text", (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + ), + ); + + final textInput = find.byKey(key); + + await tester.enterText(textInput, validText); + await tester.pumpAndSettle(); + expect( + find.text(validText), + findsOneWidget, + ); + await submit(tester); + expect( + find.text(error), + findsNothing, + ); + }); + + testWidgets("Enter invalid text", (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + ), + ); + + final textInput = find.byKey(key); + + await tester.enterText(textInput, invalidText); + await tester.pumpAndSettle(); + expect( + find.text(invalidText), + findsOneWidget, + ); + await submit(tester); + expect( + find.text(error), + findsOneWidget, + ); + }); + + testWidgets("Check helper text", (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + showHelper: true, + ), + ); + + expect( + find.text(helper), + findsOneWidget, + ); + }); + + testWidgets("Check hint", (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + showHelper: true, + ), + ); + + expect( + find.text(hint), + findsOneWidget, + ); + }); + testWidgets("Check leading, traling", (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + showLeading: true, + showTrailing: true, + ), + ); + + expect(find.byIcon(leadingIcon), findsOneWidget); + expect(find.byIcon(trailingIcon), findsOneWidget); + }); + + testWidgets("Disabled: enter text", (tester) async { + await tester.pumpWidget( + const TestWidget( + widgetKey: key, + enabled: false, + ), + ); + + final textArea = find.byKey(key); + + await tester.enterText(textArea, validText); + await tester.pumpAndSettle(); + expect( + find.text(validText), + findsNothing, + ); + }); +} + +const validText = + 'Lorem Ipsum is simply dummy text of the printing and typesetting industry'; +const invalidText = 'Lorem'; + +const hint = 'Hint'; +const error = 'Error'; +const helper = 'Helper'; +const IconData leadingIcon = MoonIcons.other_frame_24_light; +const IconData trailingIcon = MoonIcons.controls_close_small_24_light; + +class TestWidget extends StatelessWidget { + final bool enabled; + final bool showHelper; + final Key? widgetKey; + final bool showLeading; + final bool showTrailing; + + const TestWidget({ + super.key, + this.enabled = true, + this.showHelper = false, + this.widgetKey, + this.showLeading = false, + this.showTrailing = false, + }); + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + body: Form( + child: Builder( + builder: (BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + MoonFormTextInput( + key: widgetKey, + enabled: enabled, + hintText: hint, + validator: (String? value) => + value != null && value.length < 10 ? error : null, + leading: showLeading ? const Icon(leadingIcon) : null, + trailing: showTrailing ? const Icon(trailingIcon) : null, + helper: showHelper ? const Text(helper) : null, + ), + const SizedBox(height: 32), + MoonFilledButton( + label: const Text("Submit"), + onTap: () => Form.of(context).validate(), + ), + ], + ); + }, + ), + ), + ), + ); + } +} diff --git a/test/toast_test.dart b/test/toast_test.dart new file mode 100644 index 00000000..e8a18669 --- /dev/null +++ b/test/toast_test.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:moon_design/moon_design.dart'; + +void main() { + testWidgets("Open toast", (tester) async { + await tester.pumpWidget( + TestWidget(), + ); + await tester.tap(find.byType(MoonFilledButton)); + await tester.pump(const Duration(milliseconds: 100)); + await tester.pump(const Duration(milliseconds: 100)); + + expect(find.text(title), findsOneWidget); + expect(find.text(body), findsOneWidget); + expect(find.byIcon(leadingIcon), findsOneWidget); + expect(find.byIcon(trailingIcon), findsOneWidget); + await tester.pump(const Duration(milliseconds: 100)); + await tester.pump(const Duration(milliseconds: 100)); + await tester.pump(const Duration(milliseconds: 100)); + await tester.pump(const Duration(milliseconds: 100)); + await tester.pump(const Duration(milliseconds: 100)); + + expect(find.text(title), findsNothing); + }); +} + +const IconData leadingIcon = MoonIcons.other_frame_24_light; +const IconData trailingIcon = MoonIcons.controls_close_small_24_light; +const title = 'Title'; +const body = 'Body'; + +class TestWidget extends StatelessWidget { + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + body: Builder( + builder: (context) { + return MoonFilledButton( + label: const Text("Tap me"), + onTap: () { + MoonToast.show( + context, + displayDuration: const Duration(milliseconds: 500), + transitionDuration: Duration.zero, + leading: const Icon(leadingIcon), + title: const Text(title), + trailing: const Icon(trailingIcon), + body: const Text(body), + ); + }, + ); + }, + ), + ), + ); + } +}