From 99cfda0a5c4e0329ae7cd02df955131e7bd1baf3 Mon Sep 17 00:00:00 2001 From: Richard Shiue <71320345+richardshiue@users.noreply.github.com> Date: Wed, 21 Jun 2023 22:53:49 +0800 Subject: [PATCH] test: more integration tests (#2871) * test: date cell integration tests * test: single/multi-select integration tests --- .../integration_test/database_cell_test.dart | 213 +++++++++++++++++- .../util/database_test_op.dart | 76 ++++++- .../row/cells/date_cell/date_editor.dart | 6 +- 3 files changed, 285 insertions(+), 10 deletions(-) diff --git a/frontend/appflowy_flutter/integration_test/database_cell_test.dart b/frontend/appflowy_flutter/integration_test/database_cell_test.dart index a01ea6609f..d779bc00a8 100644 --- a/frontend/appflowy_flutter/integration_test/database_cell_test.dart +++ b/frontend/appflowy_flutter/integration_test/database_cell_test.dart @@ -1,6 +1,7 @@ import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; +import 'package:intl/intl.dart'; import 'util/database_test_op.dart'; import 'util/util.dart'; @@ -176,8 +177,72 @@ void main() { await tester.tapCellInGrid(rowIndex: 0, fieldType: fieldType); await tester.findDateEditor(findsOneWidget); - // Select the date - await tester.selectDay(content: 3); + // Toggle include time + await tester.toggleIncludeTime(); + + // Dismiss the cell editor + await tester.dismissCellEditor(); + + await tester.tapCellInGrid(rowIndex: 0, fieldType: fieldType); + await tester.findDateEditor(findsOneWidget); + + // Turn off include time + await tester.toggleIncludeTime(); + + // Select a date + final today = DateTime.now(); + await tester.selectDay(content: today.day); + + await tester.dismissCellEditor(); + + await tester.assertDateCellInGrid( + rowIndex: 0, + fieldType: fieldType, + content: DateFormat('MMM d, y').format(today), + ); + + await tester.tapCellInGrid(rowIndex: 0, fieldType: fieldType); + await tester.findDateEditor(findsOneWidget); + + // Toggle include time + final now = DateTime.now(); + await tester.toggleIncludeTime(); + + await tester.dismissCellEditor(); + + await tester.assertDateCellInGrid( + rowIndex: 0, + fieldType: fieldType, + content: DateFormat('MMM d, y HH:mm').format(now), + ); + + await tester.tapCellInGrid(rowIndex: 0, fieldType: fieldType); + await tester.findDateEditor(findsOneWidget); + + // Change date format + await tester.changeDateFormat(); + + await tester.dismissCellEditor(); + + await tester.assertDateCellInGrid( + rowIndex: 0, + fieldType: fieldType, + content: DateFormat('dd/MM/y HH:mm').format(now), + ); + + await tester.tapCellInGrid(rowIndex: 0, fieldType: fieldType); + await tester.findDateEditor(findsOneWidget); + + // Change time format + await tester.changeTimeFormat(); + + await tester.dismissCellEditor(); + + await tester.assertDateCellInGrid( + rowIndex: 0, + fieldType: fieldType, + content: DateFormat('dd/MM/y hh:mm a').format(now), + ); await tester.pumpAndSettle(); }); @@ -195,13 +260,151 @@ void main() { await tester.tapSelectOptionCellInGrid(rowIndex: 0, fieldType: fieldType); await tester.findSelectOptionEditor(findsOneWidget); - await tester.createOption(name: 'hello world'); - await tester.dismissSelectOptionEditor(); + // Create a new select option + await tester.createOption(name: 'tag 1'); + await tester.dismissCellEditor(); // Make sure the option is created and displayed in the cell await tester.findSelectOptionWithNameInGrid( rowIndex: 0, - name: 'hello world', + name: 'tag 1', + ); + + await tester.tapSelectOptionCellInGrid(rowIndex: 0, fieldType: fieldType); + await tester.findSelectOptionEditor(findsOneWidget); + + // Create another select option + await tester.createOption(name: 'tag 2'); + await tester.dismissCellEditor(); + + await tester.findSelectOptionWithNameInGrid( + rowIndex: 0, + name: 'tag 2', + ); + + await tester.assertNumberOfSelectedOptionsInGrid( + rowIndex: 0, + matcher: findsOneWidget, + ); + + await tester.tapSelectOptionCellInGrid(rowIndex: 0, fieldType: fieldType); + await tester.findSelectOptionEditor(findsOneWidget); + + // switch to first option + await tester.selectOption(name: 'tag 1'); + await tester.dismissCellEditor(); + + await tester.findSelectOptionWithNameInGrid( + rowIndex: 0, + name: 'tag 1', + ); + + await tester.assertNumberOfSelectedOptionsInGrid( + rowIndex: 0, + matcher: findsOneWidget, + ); + + await tester.tapSelectOptionCellInGrid(rowIndex: 0, fieldType: fieldType); + await tester.findSelectOptionEditor(findsOneWidget); + + // Deselect the currently-selected option + await tester.selectOption(name: 'tag 1'); + await tester.dismissCellEditor(); + + await tester.assertNumberOfSelectedOptionsInGrid( + rowIndex: 0, + matcher: findsNothing, + ); + + await tester.pumpAndSettle(); + }); + + testWidgets('edit multi select cell', (tester) async { + final tags = [ + 'tag 1', + 'tag 2', + 'tag 3', + 'tag 4', + ]; + + await tester.initializeAppFlowy(); + await tester.tapGoButton(); + + await tester.tapAddButton(); + await tester.tapCreateGridButton(); + + const fieldType = FieldType.MultiSelect; + await tester.createField(fieldType, fieldType.name); + + // Tap the cell to invoke the selection option editor + await tester.tapSelectOptionCellInGrid(rowIndex: 0, fieldType: fieldType); + await tester.findSelectOptionEditor(findsOneWidget); + + // Create a new select option + await tester.createOption(name: tags.first); + await tester.dismissCellEditor(); + + // Make sure the option is created and displayed in the cell + await tester.findSelectOptionWithNameInGrid( + rowIndex: 0, + name: tags.first, + ); + + await tester.tapSelectOptionCellInGrid(rowIndex: 0, fieldType: fieldType); + await tester.findSelectOptionEditor(findsOneWidget); + + // Create some other select options + await tester.createOption(name: tags[1]); + await tester.createOption(name: tags[2]); + await tester.createOption(name: tags[3]); + await tester.dismissCellEditor(); + + for (final tag in tags) { + await tester.findSelectOptionWithNameInGrid( + rowIndex: 0, + name: tag, + ); + } + + await tester.assertNumberOfSelectedOptionsInGrid( + rowIndex: 0, + matcher: findsNWidgets(4), + ); + + await tester.tapSelectOptionCellInGrid(rowIndex: 0, fieldType: fieldType); + await tester.findSelectOptionEditor(findsOneWidget); + + // Deselect all options + for (final tag in tags) { + await tester.selectOption(name: tag); + } + await tester.dismissCellEditor(); + + await tester.assertNumberOfSelectedOptionsInGrid( + rowIndex: 0, + matcher: findsNothing, + ); + + await tester.tapSelectOptionCellInGrid(rowIndex: 0, fieldType: fieldType); + await tester.findSelectOptionEditor(findsOneWidget); + + // Select some options + await tester.selectOption(name: tags[1]); + await tester.selectOption(name: tags[3]); + await tester.dismissCellEditor(); + + await tester.findSelectOptionWithNameInGrid( + rowIndex: 0, + name: tags[1], + ); + await tester.findSelectOptionWithNameInGrid( + rowIndex: 0, + name: tags[3], + ); + + await tester.assertNumberOfSelectedOptionsInGrid( + rowIndex: 0, + matcher: findsNWidgets(2), ); await tester.pumpAndSettle(); diff --git a/frontend/appflowy_flutter/integration_test/util/database_test_op.dart b/frontend/appflowy_flutter/integration_test/util/database_test_op.dart index 63e14b591d..f004d221f5 100644 --- a/frontend/appflowy_flutter/integration_test/util/database_test_op.dart +++ b/frontend/appflowy_flutter/integration_test/util/database_test_op.dart @@ -20,6 +20,7 @@ import 'package:appflowy/plugins/database_view/grid/presentation/widgets/sort/cr import 'package:appflowy/plugins/database_view/grid/presentation/widgets/sort/order_panel.dart'; import 'package:appflowy/plugins/database_view/grid/presentation/widgets/sort/sort_editor.dart'; import 'package:appflowy/plugins/database_view/grid/presentation/widgets/sort/sort_menu.dart'; +import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/type_option/date.dart'; import 'package:appflowy/plugins/database_view/grid/presentation/widgets/toolbar/filter_button.dart'; import 'package:appflowy/plugins/database_view/grid/presentation/widgets/toolbar/grid_layout.dart'; import 'package:appflowy/plugins/database_view/grid/presentation/widgets/toolbar/sort_button.dart'; @@ -35,6 +36,7 @@ import 'package:appflowy/plugins/database_view/widgets/row/cells/date_cell/date_ import 'package:appflowy/plugins/database_view/widgets/setting/database_setting.dart'; import 'package:appflowy/plugins/database_view/widgets/setting/setting_button.dart'; import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart'; +import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/setting_entities.pbenum.dart'; import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -166,7 +168,7 @@ extension AppFlowyDatabaseTest on WidgetTester { await tapButton(cell, warnIfMissed: false); } - /// The [fieldName] must be uqniue in the grid. + /// The [fieldName] must be unique in the grid. Future assertCellContent({ required int rowIndex, required FieldType fieldType, @@ -289,6 +291,48 @@ extension AppFlowyDatabaseTest on WidgetTester { await tapButton(finder); } + Future toggleIncludeTime() async { + final findDateEditor = find.byType(DateCellEditor); + final findToggle = find.byType(Toggle); + final finder = find.descendant( + of: findDateEditor, + matching: findToggle, + ); + await tapButton(finder); + } + + Future changeDateFormat() async { + final findDateEditor = find.byType(DateCellEditor); + final findDateTimeOptionButton = find.byType(DateTypeOptionButton); + final finder = find.descendant( + of: findDateEditor, + matching: findDateTimeOptionButton, + ); + await tapButton(finder); + + final findDateFormatButton = find.byType(DateFormatButton); + await tapButton(findDateFormatButton); + + final findNewDateFormat = find.text("Day/Month/Year"); + await tapButton(findNewDateFormat); + } + + Future changeTimeFormat() async { + final findDateEditor = find.byType(DateCellEditor); + final findDateTimeOptionButton = find.byType(DateTypeOptionButton); + final finder = find.descendant( + of: findDateEditor, + matching: findDateTimeOptionButton, + ); + await tapButton(finder); + + final findDateFormatButton = find.byType(TimeFormatButton); + await tapButton(findDateFormatButton); + + final findNewDateFormat = find.text("12 hour"); + await tapButton(findNewDateFormat); + } + Future tapSelectOptionCellInGrid({ required int rowIndex, required FieldType fieldType, @@ -325,6 +369,16 @@ extension AppFlowyDatabaseTest on WidgetTester { await pumpAndSettle(); } + Future selectOption({ + required String name, + }) async { + final option = find.byWidgetPredicate( + (widget) => widget is SelectOptionTagCell && widget.option.name == name, + ); + + await tapButton(option); + } + Future findSelectOptionWithNameInGrid({ required int rowIndex, required String name, @@ -342,6 +396,24 @@ extension AppFlowyDatabaseTest on WidgetTester { expect(cell, findsOneWidget); } + Future assertNumberOfSelectedOptionsInGrid({ + required int rowIndex, + required Matcher matcher, + }) async { + final findRow = find.byType(GridRow); + + final options = find.byWidgetPredicate( + (widget) => widget is SelectOptionTag, + ); + + final cell = find.descendant( + of: findRow.at(rowIndex), + matching: options, + ); + + expect(cell, matcher); + } + Future openFirstRowDetailPage() async { await hoverOnFirstRowOfGrid(); @@ -560,7 +632,7 @@ extension AppFlowyDatabaseTest on WidgetTester { expect(finder, matcher); } - Future dismissSelectOptionEditor() async { + Future dismissCellEditor() async { await sendKeyEvent(LogicalKeyboardKey.escape); await pumpAndSettle(); } diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/date_cell/date_editor.dart b/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/date_cell/date_editor.dart index 65e50bc8db..195e0ec953 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/date_cell/date_editor.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/date_cell/date_editor.dart @@ -123,7 +123,7 @@ class _CellCalendarWidgetState extends State<_CellCalendarWidget> { const TypeOptionSeparator(spacing: 12.0), const _IncludeTimeButton(), const TypeOptionSeparator(spacing: 12.0), - _DateTypeOptionButton(popoverMutex: popoverMutex) + DateTypeOptionButton(popoverMutex: popoverMutex) ]; return ListView.builder( @@ -337,9 +337,9 @@ class _TimeTextFieldState extends State<_TimeTextField> { } } -class _DateTypeOptionButton extends StatelessWidget { +class DateTypeOptionButton extends StatelessWidget { final PopoverMutex popoverMutex; - const _DateTypeOptionButton({ + const DateTypeOptionButton({ required this.popoverMutex, Key? key, }) : super(key: key);