database_cell_test.dart 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum.dart';
  2. import 'package:flutter_test/flutter_test.dart';
  3. import 'package:integration_test/integration_test.dart';
  4. import 'package:intl/intl.dart';
  5. import 'util/database_test_op.dart';
  6. import 'util/util.dart';
  7. void main() {
  8. IntegrationTestWidgetsFlutterBinding.ensureInitialized();
  9. group('grid cell', () {
  10. const location = 'appflowy';
  11. setUp(() async {
  12. await TestFolder.cleanTestLocation(location);
  13. await TestFolder.setTestLocation(location);
  14. });
  15. tearDown(() async {
  16. await TestFolder.cleanTestLocation(location);
  17. });
  18. tearDownAll(() async {
  19. await TestFolder.cleanTestLocation(null);
  20. });
  21. testWidgets('edit text cell', (tester) async {
  22. await tester.initializeAppFlowy();
  23. await tester.tapGoButton();
  24. await tester.tapAddButton();
  25. await tester.tapCreateGridButton();
  26. await tester.editCell(
  27. rowIndex: 0,
  28. fieldType: FieldType.RichText,
  29. input: 'hello world',
  30. );
  31. await tester.assertCellContent(
  32. rowIndex: 0,
  33. fieldType: FieldType.RichText,
  34. content: 'hello world',
  35. );
  36. await tester.pumpAndSettle();
  37. });
  38. testWidgets('edit number cell', (tester) async {
  39. await tester.initializeAppFlowy();
  40. await tester.tapGoButton();
  41. await tester.tapAddButton();
  42. await tester.tapCreateGridButton();
  43. const fieldType = FieldType.Number;
  44. // Create a number field
  45. await tester.createField(fieldType, fieldType.name);
  46. await tester.editCell(
  47. rowIndex: 0,
  48. fieldType: fieldType,
  49. input: '-1',
  50. );
  51. // edit the next cell to force the previous cell at row 0 to lose focus
  52. await tester.editCell(
  53. rowIndex: 1,
  54. fieldType: fieldType,
  55. input: '0.2',
  56. );
  57. // -1 -> -1
  58. await tester.assertCellContent(
  59. rowIndex: 0,
  60. fieldType: fieldType,
  61. content: '-1',
  62. );
  63. // edit the next cell to force the previous cell at row 1 to lose focus
  64. await tester.editCell(
  65. rowIndex: 2,
  66. fieldType: fieldType,
  67. input: '.1',
  68. );
  69. // 0.2 -> 0.2
  70. await tester.assertCellContent(
  71. rowIndex: 1,
  72. fieldType: fieldType,
  73. content: '0.2',
  74. );
  75. // edit the next cell to force the previous cell at row 2 to lose focus
  76. await tester.editCell(
  77. rowIndex: 0,
  78. fieldType: fieldType,
  79. input: '',
  80. );
  81. // .1 -> 0.1
  82. await tester.assertCellContent(
  83. rowIndex: 2,
  84. fieldType: fieldType,
  85. content: '0.1',
  86. );
  87. await tester.pumpAndSettle();
  88. });
  89. testWidgets('edit checkbox cell', (tester) async {
  90. await tester.initializeAppFlowy();
  91. await tester.tapGoButton();
  92. await tester.tapAddButton();
  93. await tester.tapCreateGridButton();
  94. await tester.assertCheckboxCell(rowIndex: 0, isSelected: false);
  95. await tester.tapCheckboxCellInGrid(rowIndex: 0);
  96. await tester.assertCheckboxCell(rowIndex: 0, isSelected: true);
  97. await tester.tapCheckboxCellInGrid(rowIndex: 1);
  98. await tester.tapCheckboxCellInGrid(rowIndex: 2);
  99. await tester.assertCheckboxCell(rowIndex: 1, isSelected: true);
  100. await tester.assertCheckboxCell(rowIndex: 2, isSelected: true);
  101. await tester.pumpAndSettle();
  102. });
  103. testWidgets('edit create time cell', (tester) async {
  104. await tester.initializeAppFlowy();
  105. await tester.tapGoButton();
  106. await tester.tapAddButton();
  107. await tester.tapCreateGridButton();
  108. const fieldType = FieldType.CreatedTime;
  109. // Create a create time field
  110. // The create time field is not editable
  111. await tester.createField(fieldType, fieldType.name);
  112. await tester.tapCellInGrid(rowIndex: 0, fieldType: fieldType);
  113. await tester.findDateEditor(findsNothing);
  114. await tester.pumpAndSettle();
  115. });
  116. testWidgets('edit last time cell', (tester) async {
  117. await tester.initializeAppFlowy();
  118. await tester.tapGoButton();
  119. await tester.tapAddButton();
  120. await tester.tapCreateGridButton();
  121. const fieldType = FieldType.LastEditedTime;
  122. // Create a last time field
  123. // The last time field is not editable
  124. await tester.createField(fieldType, fieldType.name);
  125. await tester.tapCellInGrid(rowIndex: 0, fieldType: fieldType);
  126. await tester.findDateEditor(findsNothing);
  127. await tester.pumpAndSettle();
  128. });
  129. testWidgets('edit time cell', (tester) async {
  130. await tester.initializeAppFlowy();
  131. await tester.tapGoButton();
  132. await tester.tapAddButton();
  133. await tester.tapCreateGridButton();
  134. const fieldType = FieldType.DateTime;
  135. await tester.createField(fieldType, fieldType.name);
  136. // Tap the cell to invoke the field editor
  137. await tester.tapCellInGrid(rowIndex: 0, fieldType: fieldType);
  138. await tester.findDateEditor(findsOneWidget);
  139. // Toggle include time
  140. await tester.toggleIncludeTime();
  141. // Dismiss the cell editor
  142. await tester.dismissCellEditor();
  143. await tester.tapCellInGrid(rowIndex: 0, fieldType: fieldType);
  144. await tester.findDateEditor(findsOneWidget);
  145. // Turn off include time
  146. await tester.toggleIncludeTime();
  147. // Select a date
  148. final today = DateTime.now();
  149. await tester.selectDay(content: today.day);
  150. await tester.dismissCellEditor();
  151. await tester.assertDateCellInGrid(
  152. rowIndex: 0,
  153. fieldType: fieldType,
  154. content: DateFormat('MMM d, y').format(today),
  155. );
  156. await tester.tapCellInGrid(rowIndex: 0, fieldType: fieldType);
  157. await tester.findDateEditor(findsOneWidget);
  158. // Toggle include time
  159. final now = DateTime.now();
  160. await tester.toggleIncludeTime();
  161. await tester.dismissCellEditor();
  162. await tester.assertDateCellInGrid(
  163. rowIndex: 0,
  164. fieldType: fieldType,
  165. content: DateFormat('MMM d, y HH:mm').format(now),
  166. );
  167. await tester.tapCellInGrid(rowIndex: 0, fieldType: fieldType);
  168. await tester.findDateEditor(findsOneWidget);
  169. // Change date format
  170. await tester.changeDateFormat();
  171. await tester.dismissCellEditor();
  172. await tester.assertDateCellInGrid(
  173. rowIndex: 0,
  174. fieldType: fieldType,
  175. content: DateFormat('dd/MM/y HH:mm').format(now),
  176. );
  177. await tester.tapCellInGrid(rowIndex: 0, fieldType: fieldType);
  178. await tester.findDateEditor(findsOneWidget);
  179. // Change time format
  180. await tester.changeTimeFormat();
  181. await tester.dismissCellEditor();
  182. await tester.assertDateCellInGrid(
  183. rowIndex: 0,
  184. fieldType: fieldType,
  185. content: DateFormat('dd/MM/y hh:mm a').format(now),
  186. );
  187. await tester.pumpAndSettle();
  188. });
  189. testWidgets('edit single select cell', (tester) async {
  190. await tester.initializeAppFlowy();
  191. await tester.tapGoButton();
  192. const fieldType = FieldType.SingleSelect;
  193. await tester.tapAddButton();
  194. // When create a grid, it will create a single select field by default
  195. await tester.tapCreateGridButton();
  196. // Tap the cell to invoke the selection option editor
  197. await tester.tapSelectOptionCellInGrid(rowIndex: 0, fieldType: fieldType);
  198. await tester.findSelectOptionEditor(findsOneWidget);
  199. // Create a new select option
  200. await tester.createOption(name: 'tag 1');
  201. await tester.dismissCellEditor();
  202. // Make sure the option is created and displayed in the cell
  203. await tester.findSelectOptionWithNameInGrid(
  204. rowIndex: 0,
  205. name: 'tag 1',
  206. );
  207. await tester.tapSelectOptionCellInGrid(rowIndex: 0, fieldType: fieldType);
  208. await tester.findSelectOptionEditor(findsOneWidget);
  209. // Create another select option
  210. await tester.createOption(name: 'tag 2');
  211. await tester.dismissCellEditor();
  212. await tester.findSelectOptionWithNameInGrid(
  213. rowIndex: 0,
  214. name: 'tag 2',
  215. );
  216. await tester.assertNumberOfSelectedOptionsInGrid(
  217. rowIndex: 0,
  218. matcher: findsOneWidget,
  219. );
  220. await tester.tapSelectOptionCellInGrid(rowIndex: 0, fieldType: fieldType);
  221. await tester.findSelectOptionEditor(findsOneWidget);
  222. // switch to first option
  223. await tester.selectOption(name: 'tag 1');
  224. await tester.dismissCellEditor();
  225. await tester.findSelectOptionWithNameInGrid(
  226. rowIndex: 0,
  227. name: 'tag 1',
  228. );
  229. await tester.assertNumberOfSelectedOptionsInGrid(
  230. rowIndex: 0,
  231. matcher: findsOneWidget,
  232. );
  233. await tester.tapSelectOptionCellInGrid(rowIndex: 0, fieldType: fieldType);
  234. await tester.findSelectOptionEditor(findsOneWidget);
  235. // Deselect the currently-selected option
  236. await tester.selectOption(name: 'tag 1');
  237. await tester.dismissCellEditor();
  238. await tester.assertNumberOfSelectedOptionsInGrid(
  239. rowIndex: 0,
  240. matcher: findsNothing,
  241. );
  242. await tester.pumpAndSettle();
  243. });
  244. testWidgets('edit multi select cell', (tester) async {
  245. final tags = [
  246. 'tag 1',
  247. 'tag 2',
  248. 'tag 3',
  249. 'tag 4',
  250. ];
  251. await tester.initializeAppFlowy();
  252. await tester.tapGoButton();
  253. await tester.tapAddButton();
  254. await tester.tapCreateGridButton();
  255. const fieldType = FieldType.MultiSelect;
  256. await tester.createField(fieldType, fieldType.name);
  257. // Tap the cell to invoke the selection option editor
  258. await tester.tapSelectOptionCellInGrid(rowIndex: 0, fieldType: fieldType);
  259. await tester.findSelectOptionEditor(findsOneWidget);
  260. // Create a new select option
  261. await tester.createOption(name: tags.first);
  262. await tester.dismissCellEditor();
  263. // Make sure the option is created and displayed in the cell
  264. await tester.findSelectOptionWithNameInGrid(
  265. rowIndex: 0,
  266. name: tags.first,
  267. );
  268. await tester.tapSelectOptionCellInGrid(rowIndex: 0, fieldType: fieldType);
  269. await tester.findSelectOptionEditor(findsOneWidget);
  270. // Create some other select options
  271. await tester.createOption(name: tags[1]);
  272. await tester.createOption(name: tags[2]);
  273. await tester.createOption(name: tags[3]);
  274. await tester.dismissCellEditor();
  275. for (final tag in tags) {
  276. await tester.findSelectOptionWithNameInGrid(
  277. rowIndex: 0,
  278. name: tag,
  279. );
  280. }
  281. await tester.assertNumberOfSelectedOptionsInGrid(
  282. rowIndex: 0,
  283. matcher: findsNWidgets(4),
  284. );
  285. await tester.tapSelectOptionCellInGrid(rowIndex: 0, fieldType: fieldType);
  286. await tester.findSelectOptionEditor(findsOneWidget);
  287. // Deselect all options
  288. for (final tag in tags) {
  289. await tester.selectOption(name: tag);
  290. }
  291. await tester.dismissCellEditor();
  292. await tester.assertNumberOfSelectedOptionsInGrid(
  293. rowIndex: 0,
  294. matcher: findsNothing,
  295. );
  296. await tester.tapSelectOptionCellInGrid(rowIndex: 0, fieldType: fieldType);
  297. await tester.findSelectOptionEditor(findsOneWidget);
  298. // Select some options
  299. await tester.selectOption(name: tags[1]);
  300. await tester.selectOption(name: tags[3]);
  301. await tester.dismissCellEditor();
  302. await tester.findSelectOptionWithNameInGrid(
  303. rowIndex: 0,
  304. name: tags[1],
  305. );
  306. await tester.findSelectOptionWithNameInGrid(
  307. rowIndex: 0,
  308. name: tags[3],
  309. );
  310. await tester.assertNumberOfSelectedOptionsInGrid(
  311. rowIndex: 0,
  312. matcher: findsNWidgets(2),
  313. );
  314. await tester.pumpAndSettle();
  315. });
  316. });
  317. }