database_row_page_test.dart 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. import 'package:appflowy/plugins/database_view/widgets/row/row_banner.dart';
  2. import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum.dart';
  3. import 'package:appflowy_editor/appflowy_editor.dart';
  4. import 'package:flowy_infra_ui/style_widget/text.dart';
  5. import 'package:flutter/material.dart';
  6. import 'package:flutter_test/flutter_test.dart';
  7. import 'package:integration_test/integration_test.dart';
  8. import 'util/database_test_op.dart';
  9. import 'util/emoji.dart';
  10. import 'util/ime.dart';
  11. import 'util/util.dart';
  12. void main() {
  13. IntegrationTestWidgetsFlutterBinding.ensureInitialized();
  14. group('grid', () {
  15. testWidgets('row details page opens', (tester) async {
  16. await tester.initializeAppFlowy();
  17. await tester.tapGoButton();
  18. // Create a new grid
  19. await tester.tapAddButton();
  20. await tester.tapCreateGridButton();
  21. // Hover first row and then open the row page
  22. await tester.openFirstRowDetailPage();
  23. // Make sure that the row page is opened
  24. tester.assertRowDetailPageOpened();
  25. });
  26. testWidgets('insert emoji in the row detail page', (tester) async {
  27. await tester.initializeAppFlowy();
  28. await tester.tapGoButton();
  29. // Create a new grid
  30. await tester.tapAddButton();
  31. await tester.tapCreateGridButton();
  32. // Hover first row and then open the row page
  33. await tester.openFirstRowDetailPage();
  34. await tester.hoverRowBanner();
  35. await tester.openEmojiPicker();
  36. await tester.switchToEmojiList();
  37. await tester.tapEmoji('😀');
  38. // After select the emoji, the EmojiButton will show up
  39. await tester.tapButton(find.byType(EmojiButton));
  40. });
  41. testWidgets('update emoji in the row detail page', (tester) async {
  42. await tester.initializeAppFlowy();
  43. await tester.tapGoButton();
  44. // Create a new grid
  45. await tester.tapAddButton();
  46. await tester.tapCreateGridButton();
  47. // Hover first row and then open the row page
  48. await tester.openFirstRowDetailPage();
  49. await tester.hoverRowBanner();
  50. await tester.openEmojiPicker();
  51. await tester.switchToEmojiList();
  52. await tester.tapEmoji('😀');
  53. // Update existing selected emoji
  54. await tester.tapButton(find.byType(EmojiButton));
  55. await tester.switchToEmojiList();
  56. await tester.tapEmoji('😅');
  57. // The emoji already displayed in the row banner
  58. final emojiText = find.byWidgetPredicate(
  59. (widget) => widget is FlowyText && widget.text == '😅',
  60. );
  61. // The number of emoji should be two. One in the row displayed in the grid
  62. // one in the row detail page.
  63. expect(emojiText, findsNWidgets(2));
  64. });
  65. testWidgets('remove emoji in the row detail page', (tester) async {
  66. await tester.initializeAppFlowy();
  67. await tester.tapGoButton();
  68. // Create a new grid
  69. await tester.tapAddButton();
  70. await tester.tapCreateGridButton();
  71. // Hover first row and then open the row page
  72. await tester.openFirstRowDetailPage();
  73. await tester.hoverRowBanner();
  74. await tester.openEmojiPicker();
  75. await tester.switchToEmojiList();
  76. await tester.tapEmoji('😀');
  77. // Remove the emoji
  78. await tester.tapButton(find.byType(RemoveEmojiButton));
  79. final emojiText = find.byWidgetPredicate(
  80. (widget) => widget is FlowyText && widget.text == '😀',
  81. );
  82. expect(emojiText, findsNothing);
  83. });
  84. testWidgets('create list of fields in row detail page', (tester) async {
  85. await tester.initializeAppFlowy();
  86. await tester.tapGoButton();
  87. // Create a new grid
  88. await tester.tapAddButton();
  89. await tester.tapCreateGridButton();
  90. // Hover first row and then open the row page
  91. await tester.openFirstRowDetailPage();
  92. for (final fieldType in [
  93. FieldType.Checklist,
  94. FieldType.DateTime,
  95. FieldType.Number,
  96. FieldType.URL,
  97. FieldType.MultiSelect,
  98. FieldType.LastEditedTime,
  99. FieldType.CreatedTime,
  100. FieldType.Checkbox,
  101. ]) {
  102. await tester.tapRowDetailPageCreatePropertyButton();
  103. await tester.renameField(fieldType.name);
  104. // Open the type option menu
  105. await tester.tapTypeOptionButton();
  106. await tester.selectFieldType(fieldType);
  107. await tester.dismissFieldEditor();
  108. // After update the field type, the cells should be updated
  109. await tester.findCellByFieldType(fieldType);
  110. await tester.scrollRowDetailByOffset(const Offset(0, -50));
  111. }
  112. });
  113. testWidgets('check document is exist in row detail page', (tester) async {
  114. await tester.initializeAppFlowy();
  115. await tester.tapGoButton();
  116. // Create a new grid
  117. await tester.tapAddButton();
  118. await tester.tapCreateGridButton();
  119. // Hover first row and then open the row page
  120. await tester.openFirstRowDetailPage();
  121. // Each row detail page should have a document
  122. await tester.assertDocumentExistInRowDetailPage();
  123. });
  124. testWidgets('update the content of the document and re-open it',
  125. (tester) async {
  126. await tester.initializeAppFlowy();
  127. await tester.tapGoButton();
  128. // Create a new grid
  129. await tester.tapAddButton();
  130. await tester.tapCreateGridButton();
  131. // Hover first row and then open the row page
  132. await tester.openFirstRowDetailPage();
  133. // Wait for the document to be loaded
  134. await tester.wait(500);
  135. // Focus on the editor
  136. final textBlock = find.byType(TextBlockComponentWidget);
  137. await tester.tapAt(tester.getCenter(textBlock));
  138. await tester.pumpAndSettle();
  139. // Input some text
  140. const inputText = 'Hello World';
  141. await tester.ime.insertText(inputText);
  142. expect(
  143. find.textContaining(inputText, findRichText: true),
  144. findsOneWidget,
  145. );
  146. // Tap outside to dismiss the field
  147. await tester.tapAt(Offset.zero);
  148. await tester.pumpAndSettle();
  149. // Re-open the document
  150. await tester.openFirstRowDetailPage();
  151. expect(
  152. find.textContaining(inputText, findRichText: true),
  153. findsOneWidget,
  154. );
  155. });
  156. testWidgets(
  157. 'check if the title wraps properly when a long text is inserted',
  158. (tester) async {
  159. await tester.initializeAppFlowy();
  160. await tester.tapGoButton();
  161. // Create a new grid
  162. await tester.tapAddButton();
  163. await tester.tapCreateGridButton();
  164. // Hover first row and then open the row page
  165. await tester.openFirstRowDetailPage();
  166. // Wait for the document to be loaded
  167. await tester.wait(500);
  168. // Focus on the editor
  169. final textField = find
  170. .descendant(
  171. of: find.byType(SimpleDialog),
  172. matching: find.byType(TextField),
  173. )
  174. .first;
  175. // Input a long text
  176. await tester.enterText(textField, 'Long text' * 25);
  177. await tester.pumpAndSettle();
  178. // Tap outside to dismiss the field
  179. await tester.tapAt(Offset.zero);
  180. await tester.pumpAndSettle();
  181. // Check if there is any overflow in the widget tree
  182. expect(tester.takeException(), isNull);
  183. // Re-open the document
  184. await tester.openFirstRowDetailPage();
  185. // Check again if there is any overflow in the widget tree
  186. expect(tester.takeException(), isNull);
  187. });
  188. testWidgets('delete row in row detail page', (tester) async {
  189. await tester.initializeAppFlowy();
  190. await tester.tapGoButton();
  191. // Create a new grid
  192. await tester.tapAddButton();
  193. await tester.tapCreateGridButton();
  194. // Hover first row and then open the row page
  195. await tester.openFirstRowDetailPage();
  196. await tester.tapRowDetailPageDeleteRowButton();
  197. await tester.tapEscButton();
  198. await tester.assertNumberOfRowsInGridPage(2);
  199. });
  200. testWidgets('duplicate row in row detail page', (tester) async {
  201. await tester.initializeAppFlowy();
  202. await tester.tapGoButton();
  203. // Create a new grid
  204. await tester.tapAddButton();
  205. await tester.tapCreateGridButton();
  206. // Hover first row and then open the row page
  207. await tester.openFirstRowDetailPage();
  208. await tester.tapRowDetailPageDuplicateRowButton();
  209. await tester.tapEscButton();
  210. await tester.assertNumberOfRowsInGridPage(4);
  211. });
  212. });
  213. }