mirror of
				https://github.com/AppFlowy-IO/AppFlowy.git
				synced 2025-10-31 18:15:09 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			348 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			348 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
| import 'package:appflowy/plugins/database_view/widgets/row/row_banner.dart';
 | |
| import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum.dart';
 | |
| import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 | |
| import 'package:appflowy_editor/appflowy_editor.dart';
 | |
| import 'package:flowy_infra_ui/style_widget/text.dart';
 | |
| import 'package:flutter/material.dart';
 | |
| import 'package:flutter_test/flutter_test.dart';
 | |
| import 'package:integration_test/integration_test.dart';
 | |
| 
 | |
| import 'util/database_test_op.dart';
 | |
| import 'util/emoji.dart';
 | |
| import 'util/util.dart';
 | |
| 
 | |
| void main() {
 | |
|   IntegrationTestWidgetsFlutterBinding.ensureInitialized();
 | |
| 
 | |
|   group('grid', () {
 | |
|     testWidgets('row details page opens', (tester) async {
 | |
|       await tester.initializeAppFlowy();
 | |
|       await tester.tapGoButton();
 | |
| 
 | |
|       // Create a new grid
 | |
|       await tester.createNewPageWithName(layout: ViewLayoutPB.Grid);
 | |
| 
 | |
|       // Hover first row and then open the row page
 | |
|       await tester.openFirstRowDetailPage();
 | |
| 
 | |
|       // Make sure that the row page is opened
 | |
|       tester.assertRowDetailPageOpened();
 | |
|     });
 | |
| 
 | |
|     testWidgets('insert emoji in the row detail page', (tester) async {
 | |
|       await tester.initializeAppFlowy();
 | |
|       await tester.tapGoButton();
 | |
| 
 | |
|       // Create a new grid
 | |
|       await tester.createNewPageWithName(layout: ViewLayoutPB.Grid);
 | |
| 
 | |
|       // Hover first row and then open the row page
 | |
|       await tester.openFirstRowDetailPage();
 | |
| 
 | |
|       await tester.hoverRowBanner();
 | |
| 
 | |
|       await tester.openEmojiPicker();
 | |
|       await tester.switchToEmojiList();
 | |
|       await tester.tapEmoji('😀');
 | |
| 
 | |
|       // After select the emoji, the EmojiButton will show up
 | |
|       await tester.tapButton(find.byType(EmojiButton));
 | |
|     });
 | |
| 
 | |
|     testWidgets('update emoji in the row detail page', (tester) async {
 | |
|       await tester.initializeAppFlowy();
 | |
|       await tester.tapGoButton();
 | |
| 
 | |
|       // Create a new grid
 | |
|       await tester.createNewPageWithName(layout: ViewLayoutPB.Grid);
 | |
| 
 | |
|       // Hover first row and then open the row page
 | |
|       await tester.openFirstRowDetailPage();
 | |
|       await tester.hoverRowBanner();
 | |
|       await tester.openEmojiPicker();
 | |
|       await tester.switchToEmojiList();
 | |
|       await tester.tapEmoji('😀');
 | |
| 
 | |
|       // Update existing selected emoji
 | |
|       await tester.tapButton(find.byType(EmojiButton));
 | |
|       await tester.switchToEmojiList();
 | |
|       await tester.tapEmoji('😅');
 | |
| 
 | |
|       // The emoji already displayed in the row banner
 | |
|       final emojiText = find.byWidgetPredicate(
 | |
|         (widget) => widget is FlowyText && widget.text == '😅',
 | |
|       );
 | |
| 
 | |
|       // The number of emoji should be two. One in the row displayed in the grid
 | |
|       // one in the row detail page.
 | |
|       expect(emojiText, findsNWidgets(2));
 | |
|     });
 | |
| 
 | |
|     testWidgets('remove emoji in the row detail page', (tester) async {
 | |
|       await tester.initializeAppFlowy();
 | |
|       await tester.tapGoButton();
 | |
| 
 | |
|       // Create a new grid
 | |
|       await tester.createNewPageWithName(layout: ViewLayoutPB.Grid);
 | |
| 
 | |
|       // Hover first row and then open the row page
 | |
|       await tester.openFirstRowDetailPage();
 | |
|       await tester.hoverRowBanner();
 | |
|       await tester.openEmojiPicker();
 | |
|       await tester.switchToEmojiList();
 | |
|       await tester.tapEmoji('😀');
 | |
| 
 | |
|       // Remove the emoji
 | |
|       await tester.tapButton(find.byType(RemoveEmojiButton));
 | |
|       final emojiText = find.byWidgetPredicate(
 | |
|         (widget) => widget is FlowyText && widget.text == '😀',
 | |
|       );
 | |
|       expect(emojiText, findsNothing);
 | |
|     });
 | |
| 
 | |
|     testWidgets('create list of fields in row detail page', (tester) async {
 | |
|       await tester.initializeAppFlowy();
 | |
|       await tester.tapGoButton();
 | |
| 
 | |
|       // Create a new grid
 | |
|       await tester.createNewPageWithName(layout: ViewLayoutPB.Grid);
 | |
| 
 | |
|       // Hover first row and then open the row page
 | |
|       await tester.openFirstRowDetailPage();
 | |
| 
 | |
|       for (final fieldType in [
 | |
|         FieldType.Checklist,
 | |
|         FieldType.DateTime,
 | |
|         FieldType.Number,
 | |
|         FieldType.URL,
 | |
|         FieldType.MultiSelect,
 | |
|         FieldType.LastEditedTime,
 | |
|         FieldType.CreatedTime,
 | |
|         FieldType.Checkbox,
 | |
|       ]) {
 | |
|         await tester.tapRowDetailPageCreatePropertyButton();
 | |
|         await tester.renameField(fieldType.name);
 | |
| 
 | |
|         // Open the type option menu
 | |
|         await tester.tapTypeOptionButton();
 | |
| 
 | |
|         await tester.selectFieldType(fieldType);
 | |
|         await tester.dismissFieldEditor();
 | |
| 
 | |
|         // After update the field type, the cells should be updated
 | |
|         await tester.findCellByFieldType(fieldType);
 | |
|         await tester.scrollRowDetailByOffset(const Offset(0, -50));
 | |
|       }
 | |
|     });
 | |
| 
 | |
|     testWidgets('change order of fields and cells', (tester) async {
 | |
|       await tester.initializeAppFlowy();
 | |
|       await tester.tapGoButton();
 | |
| 
 | |
|       // Create a new grid
 | |
|       await tester.createNewPageWithName(layout: ViewLayoutPB.Grid);
 | |
| 
 | |
|       // Hover first row and then open the row page
 | |
|       await tester.openFirstRowDetailPage();
 | |
| 
 | |
|       // Assert that the first field in the row details page is the select
 | |
|       // option type
 | |
|       tester.assertFirstFieldInRowDetailByType(FieldType.SingleSelect);
 | |
| 
 | |
|       // Reorder first field in list
 | |
|       final gesture = await tester.hoverOnFieldInRowDetail(index: 0);
 | |
|       await tester.pumpAndSettle();
 | |
|       await tester.reorderFieldInRowDetail(offset: 30);
 | |
| 
 | |
|       // Orders changed, now the checkbox is first
 | |
|       tester.assertFirstFieldInRowDetailByType(FieldType.Checkbox);
 | |
|       await gesture.removePointer();
 | |
|       await tester.pumpAndSettle();
 | |
| 
 | |
|       // Reorder second field in list
 | |
|       await tester.hoverOnFieldInRowDetail(index: 1);
 | |
|       await tester.pumpAndSettle();
 | |
|       await tester.reorderFieldInRowDetail(offset: -30);
 | |
| 
 | |
|       // First field is now back to select option
 | |
|       tester.assertFirstFieldInRowDetailByType(FieldType.SingleSelect);
 | |
|     });
 | |
| 
 | |
|     testWidgets('hide and show hidden fields', (tester) async {
 | |
|       await tester.initializeAppFlowy();
 | |
|       await tester.tapGoButton();
 | |
| 
 | |
|       // Create a new grid
 | |
|       await tester.createNewPageWithName(layout: ViewLayoutPB.Grid);
 | |
| 
 | |
|       // Hover first row and then open the row page
 | |
|       await tester.openFirstRowDetailPage();
 | |
| 
 | |
|       // Assert that the show hidden fields button isn't visible
 | |
|       tester.assertToggleShowHiddenFieldsVisibility(false);
 | |
| 
 | |
|       // Hide the first field in the field list
 | |
|       await tester.tapGridFieldWithNameInRowDetailPage("Type");
 | |
|       await tester.tapHidePropertyButtonInFieldEditor();
 | |
| 
 | |
|       // Assert that the field is now hidden
 | |
|       tester.noFieldWithName("Type");
 | |
| 
 | |
|       // Assert that the show hidden fields button appears
 | |
|       tester.assertToggleShowHiddenFieldsVisibility(true);
 | |
| 
 | |
|       // Click on the show hidden fields button
 | |
|       await tester.toggleShowHiddenFields();
 | |
| 
 | |
|       // Assert that the hidden field is shown again and that the show
 | |
|       // hidden fields button is still present
 | |
|       tester.findFieldWithName("Type");
 | |
|       tester.assertToggleShowHiddenFieldsVisibility(true);
 | |
| 
 | |
|       // Click hide hidden fields
 | |
|       await tester.toggleShowHiddenFields();
 | |
| 
 | |
|       // Assert that the hidden field has vanished
 | |
|       tester.noFieldWithName("Type");
 | |
| 
 | |
|       // Click show hidden fields
 | |
|       await tester.toggleShowHiddenFields();
 | |
| 
 | |
|       // delete the hidden field
 | |
|       await tester.tapGridFieldWithNameInRowDetailPage("Type");
 | |
|       await tester.tapDeletePropertyInFieldEditor();
 | |
| 
 | |
|       // Assert that the that the show hidden fields button is gone
 | |
|       tester.assertToggleShowHiddenFieldsVisibility(false);
 | |
|     });
 | |
| 
 | |
|     testWidgets('check document exists in row detail page', (tester) async {
 | |
|       await tester.initializeAppFlowy();
 | |
|       await tester.tapGoButton();
 | |
| 
 | |
|       // Create a new grid
 | |
|       await tester.createNewPageWithName(layout: ViewLayoutPB.Grid);
 | |
| 
 | |
|       // Hover first row and then open the row page
 | |
|       await tester.openFirstRowDetailPage();
 | |
| 
 | |
|       // Each row detail page should have a document
 | |
|       await tester.assertDocumentExistInRowDetailPage();
 | |
|     });
 | |
| 
 | |
|     testWidgets('update the contents of the document and re-open it',
 | |
|         (tester) async {
 | |
|       await tester.initializeAppFlowy();
 | |
|       await tester.tapGoButton();
 | |
| 
 | |
|       // Create a new grid
 | |
|       await tester.createNewPageWithName(layout: ViewLayoutPB.Grid);
 | |
| 
 | |
|       // Hover first row and then open the row page
 | |
|       await tester.openFirstRowDetailPage();
 | |
| 
 | |
|       // Wait for the document to be loaded
 | |
|       await tester.wait(500);
 | |
| 
 | |
|       // Focus on the editor
 | |
|       final textBlock = find.byType(ParagraphBlockComponentWidget);
 | |
|       await tester.tapAt(tester.getCenter(textBlock));
 | |
|       await tester.pumpAndSettle();
 | |
| 
 | |
|       // Input some text
 | |
|       const inputText = 'Hello World';
 | |
|       await tester.ime.insertText(inputText);
 | |
|       expect(
 | |
|         find.textContaining(inputText, findRichText: true),
 | |
|         findsOneWidget,
 | |
|       );
 | |
| 
 | |
|       // Tap outside to dismiss the field
 | |
|       await tester.tapAt(Offset.zero);
 | |
|       await tester.pumpAndSettle();
 | |
| 
 | |
|       // Re-open the document
 | |
|       await tester.openFirstRowDetailPage();
 | |
|       expect(
 | |
|         find.textContaining(inputText, findRichText: true),
 | |
|         findsOneWidget,
 | |
|       );
 | |
|     });
 | |
| 
 | |
|     testWidgets(
 | |
|         'check if the title wraps properly when a long text is inserted',
 | |
|         (tester) async {
 | |
|       await tester.initializeAppFlowy();
 | |
|       await tester.tapGoButton();
 | |
| 
 | |
|       // Create a new grid
 | |
|       await tester.createNewPageWithName(layout: ViewLayoutPB.Grid);
 | |
| 
 | |
|       // Hover first row and then open the row page
 | |
|       await tester.openFirstRowDetailPage();
 | |
| 
 | |
|       // Wait for the document to be loaded
 | |
|       await tester.wait(500);
 | |
| 
 | |
|       // Focus on the editor
 | |
|       final textField = find
 | |
|           .descendant(
 | |
|             of: find.byType(SimpleDialog),
 | |
|             matching: find.byType(TextField),
 | |
|           )
 | |
|           .first;
 | |
| 
 | |
|       // Input a long text
 | |
|       await tester.enterText(textField, 'Long text' * 25);
 | |
|       await tester.pumpAndSettle();
 | |
| 
 | |
|       // Tap outside to dismiss the field
 | |
|       await tester.tapAt(Offset.zero);
 | |
|       await tester.pumpAndSettle();
 | |
| 
 | |
|       // Check if there is any overflow in the widget tree
 | |
|       expect(tester.takeException(), isNull);
 | |
| 
 | |
|       // Re-open the document
 | |
|       await tester.openFirstRowDetailPage();
 | |
| 
 | |
|       // Check again if there is any overflow in the widget tree
 | |
|       expect(tester.takeException(), isNull);
 | |
|     });
 | |
| 
 | |
|     testWidgets('delete row in row detail page', (tester) async {
 | |
|       await tester.initializeAppFlowy();
 | |
|       await tester.tapGoButton();
 | |
| 
 | |
|       // Create a new grid
 | |
|       await tester.createNewPageWithName(layout: ViewLayoutPB.Grid);
 | |
| 
 | |
|       // Hover first row and then open the row page
 | |
|       await tester.openFirstRowDetailPage();
 | |
| 
 | |
|       await tester.tapRowDetailPageRowActionButton();
 | |
|       await tester.tapRowDetailPageDeleteRowButton();
 | |
|       await tester.tapEscButton();
 | |
| 
 | |
|       await tester.assertNumberOfRowsInGridPage(2);
 | |
|     });
 | |
| 
 | |
|     testWidgets('duplicate row in row detail page', (tester) async {
 | |
|       await tester.initializeAppFlowy();
 | |
|       await tester.tapGoButton();
 | |
| 
 | |
|       // Create a new grid
 | |
|       await tester.createNewPageWithName(layout: ViewLayoutPB.Grid);
 | |
| 
 | |
|       // Hover first row and then open the row page
 | |
|       await tester.openFirstRowDetailPage();
 | |
| 
 | |
|       await tester.tapRowDetailPageRowActionButton();
 | |
|       await tester.tapRowDetailPageDuplicateRowButton();
 | |
|       await tester.tapEscButton();
 | |
| 
 | |
|       await tester.assertNumberOfRowsInGridPage(4);
 | |
|     });
 | |
|   });
 | |
| }
 | 
