From 60267e674ec699be30dff4c9f6c8250095e1c07c Mon Sep 17 00:00:00 2001 From: nathan Date: Sun, 27 Nov 2022 15:38:02 +0800 Subject: [PATCH 1/2] chore: refactor grid test directory --- .../grid_test/create_filter_test.dart | 146 ------------- .../edit_field_change_filter_test.dart | 56 ----- .../grid_test/edit_field_edit_test.dart | 102 --------- .../grid_test/select_option_bloc_test.dart | 201 ------------------ .../test/bloc_test/grid_test/util.dart | 16 +- 5 files changed, 8 insertions(+), 513 deletions(-) delete mode 100644 frontend/app_flowy/test/bloc_test/grid_test/create_filter_test.dart delete mode 100644 frontend/app_flowy/test/bloc_test/grid_test/edit_field_change_filter_test.dart delete mode 100644 frontend/app_flowy/test/bloc_test/grid_test/edit_field_edit_test.dart delete mode 100644 frontend/app_flowy/test/bloc_test/grid_test/select_option_bloc_test.dart diff --git a/frontend/app_flowy/test/bloc_test/grid_test/create_filter_test.dart b/frontend/app_flowy/test/bloc_test/grid_test/create_filter_test.dart deleted file mode 100644 index 374c60faac..0000000000 --- a/frontend/app_flowy/test/bloc_test/grid_test/create_filter_test.dart +++ /dev/null @@ -1,146 +0,0 @@ -import 'package:app_flowy/plugins/grid/application/filter/filter_service.dart'; -import 'package:app_flowy/plugins/grid/application/grid_bloc.dart'; -import 'package:app_flowy/plugins/grid/application/grid_data_controller.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_filter.pbenum.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/text_filter.pb.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'util.dart'; - -void main() { - late AppFlowyGridTest gridTest; - setUpAll(() async { - gridTest = await AppFlowyGridTest.ensureInitialized(); - }); - - test('create a text filter)', () async { - final context = await gridTest.createTestGrid(); - final service = FilterFFIService(viewId: context.gridView.id); - final textField = context.textFieldContext(); - service.insertTextFilter( - fieldId: textField.id, - condition: TextFilterCondition.TextIsEmpty, - content: ""); - await gridResponseFuture(); - assert(context.fieldController.filterInfos.length == 1); - }); - - test('delete a text filter)', () async { - final context = await gridTest.createTestGrid(); - final service = FilterFFIService(viewId: context.gridView.id); - final textField = context.textFieldContext(); - service.insertTextFilter( - fieldId: textField.id, - condition: TextFilterCondition.TextIsEmpty, - content: ""); - await gridResponseFuture(); - - final filterInfo = context.fieldController.filterInfos.first; - service.deleteFilter( - fieldId: textField.id, - filterId: filterInfo.filter.id, - fieldType: textField.fieldType, - ); - await gridResponseFuture(); - - assert(context.fieldController.filterInfos.isEmpty); - }); - - test('filter rows with condition: text is empty', () async { - final context = await gridTest.createTestGrid(); - final service = FilterFFIService(viewId: context.gridView.id); - final gridController = GridController(view: context.gridView); - final gridBloc = GridBloc( - view: context.gridView, - gridController: gridController, - )..add(const GridEvent.initial()); - await gridResponseFuture(); - - final textField = context.textFieldContext(); - service.insertTextFilter( - fieldId: textField.id, - condition: TextFilterCondition.TextIsEmpty, - content: ""); - await gridResponseFuture(); - - assert(gridBloc.state.rowInfos.length == 3); - }); - - test('filter rows with condition: text is empty(After edit the row)', - () async { - final context = await gridTest.createTestGrid(); - final service = FilterFFIService(viewId: context.gridView.id); - final gridController = GridController(view: context.gridView); - final gridBloc = GridBloc( - view: context.gridView, - gridController: gridController, - )..add(const GridEvent.initial()); - await gridResponseFuture(); - - final textField = context.textFieldContext(); - service.insertTextFilter( - fieldId: textField.id, - condition: TextFilterCondition.TextIsEmpty, - content: ""); - await gridResponseFuture(); - - final controller = await context.makeTextCellController(); - controller.saveCellData("edit text cell content"); - await gridResponseFuture(); - assert(gridBloc.state.rowInfos.length == 2); - - controller.saveCellData(""); - await gridResponseFuture(); - assert(gridBloc.state.rowInfos.length == 3); - }); - - test('filter rows with condition: text is not empty', () async { - final context = await gridTest.createTestGrid(); - final service = FilterFFIService(viewId: context.gridView.id); - final textField = context.textFieldContext(); - await gridResponseFuture(); - service.insertTextFilter( - fieldId: textField.id, - condition: TextFilterCondition.TextIsNotEmpty, - content: ""); - await gridResponseFuture(); - assert(context.rowInfos.isEmpty); - }); - - test('filter rows with condition: checkbox uncheck', () async { - final context = await gridTest.createTestGrid(); - final checkboxField = context.checkboxFieldContext(); - final service = FilterFFIService(viewId: context.gridView.id); - final gridController = GridController(view: context.gridView); - final gridBloc = GridBloc( - view: context.gridView, - gridController: gridController, - )..add(const GridEvent.initial()); - - await gridResponseFuture(); - service.insertCheckboxFilter( - fieldId: checkboxField.id, - condition: CheckboxFilterCondition.IsUnChecked, - ); - await gridResponseFuture(); - assert(gridBloc.state.rowInfos.length == 3); - }); - - test('filter rows with condition: checkbox check', () async { - final context = await gridTest.createTestGrid(); - final checkboxField = context.checkboxFieldContext(); - final service = FilterFFIService(viewId: context.gridView.id); - final gridController = GridController(view: context.gridView); - final gridBloc = GridBloc( - view: context.gridView, - gridController: gridController, - )..add(const GridEvent.initial()); - - await gridResponseFuture(); - service.insertCheckboxFilter( - fieldId: checkboxField.id, - condition: CheckboxFilterCondition.IsChecked, - ); - await gridResponseFuture(); - assert(gridBloc.state.rowInfos.isEmpty); - }); -} diff --git a/frontend/app_flowy/test/bloc_test/grid_test/edit_field_change_filter_test.dart b/frontend/app_flowy/test/bloc_test/grid_test/edit_field_change_filter_test.dart deleted file mode 100644 index 1a8c3edf06..0000000000 --- a/frontend/app_flowy/test/bloc_test/grid_test/edit_field_change_filter_test.dart +++ /dev/null @@ -1,56 +0,0 @@ -import 'package:app_flowy/plugins/grid/application/field/field_editor_bloc.dart'; -import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart'; -import 'package:app_flowy/plugins/grid/application/filter/filter_menu_bloc.dart'; -import 'package:app_flowy/plugins/grid/application/filter/filter_service.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/text_filter.pb.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'util.dart'; - -void main() { - late AppFlowyGridTest gridTest; - setUpAll(() async { - gridTest = await AppFlowyGridTest.ensureInitialized(); - }); - - test("create a text filter and then alter the filter's field)", () async { - final context = await gridTest.createTestGrid(); - final service = FilterFFIService(viewId: context.gridView.id); - final textField = context.textFieldContext(); - - // Create the filter menu bloc - final menuBloc = GridFilterMenuBloc( - fieldController: context.fieldController, - viewId: context.gridView.id, - )..add(const GridFilterMenuEvent.initial()); - - // Insert filter for the text field - service.insertTextFilter( - fieldId: textField.id, - condition: TextFilterCondition.TextIsEmpty, - content: ""); - await gridResponseFuture(); - assert(menuBloc.state.filters.length == 1); - - // Edit the text field - final loader = FieldTypeOptionLoader( - gridId: context.gridView.id, - field: textField.field, - ); - - final editorBloc = FieldEditorBloc( - gridId: context.gridView.id, - fieldName: textField.field.name, - isGroupField: false, - loader: loader, - )..add(const FieldEditorEvent.initial()); - await gridResponseFuture(); - - // Alter the field type to Number - editorBloc.add(const FieldEditorEvent.switchToField(FieldType.Number)); - await gridResponseFuture(); - - // Check the number of filters - assert(menuBloc.state.filters.isEmpty); - }); -} diff --git a/frontend/app_flowy/test/bloc_test/grid_test/edit_field_edit_test.dart b/frontend/app_flowy/test/bloc_test/grid_test/edit_field_edit_test.dart deleted file mode 100644 index 5a8173b7bd..0000000000 --- a/frontend/app_flowy/test/bloc_test/grid_test/edit_field_edit_test.dart +++ /dev/null @@ -1,102 +0,0 @@ -import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart'; -import 'package:app_flowy/plugins/grid/application/prelude.dart'; -import 'package:bloc_test/bloc_test.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'util.dart'; - -Future createEditorBloc(AppFlowyGridTest gridTest) async { - final context = await gridTest.createTestGrid(); - final fieldInfo = context.singleSelectFieldContext(); - final loader = FieldTypeOptionLoader( - gridId: context.gridView.id, - field: fieldInfo.field, - ); - - return FieldEditorBloc( - gridId: context.gridView.id, - fieldName: fieldInfo.name, - isGroupField: fieldInfo.isGroupField, - loader: loader, - )..add(const FieldEditorEvent.initial()); -} - -void main() { - late AppFlowyGridTest gridTest; - - setUpAll(() async { - gridTest = await AppFlowyGridTest.ensureInitialized(); - }); - - group('$FieldEditorBloc', () { - late FieldEditorBloc editorBloc; - - setUp(() async { - final context = await gridTest.createTestGrid(); - final fieldInfo = context.singleSelectFieldContext(); - final loader = FieldTypeOptionLoader( - gridId: context.gridView.id, - field: fieldInfo.field, - ); - - editorBloc = FieldEditorBloc( - gridId: context.gridView.id, - fieldName: fieldInfo.name, - isGroupField: fieldInfo.isGroupField, - loader: loader, - )..add(const FieldEditorEvent.initial()); - - await gridResponseFuture(); - }); - - blocTest( - "rename field", - build: () => editorBloc, - act: (bloc) async { - editorBloc.add(const FieldEditorEvent.updateName('Hello world')); - }, - wait: gridResponseDuration(), - verify: (bloc) { - bloc.state.field.fold( - () => throw Exception("The field should not be none"), - (field) { - assert(field.name == 'Hello world'); - }, - ); - }, - ); - - blocTest( - "switch to text field", - build: () => editorBloc, - act: (bloc) async { - editorBloc - .add(const FieldEditorEvent.switchToField(FieldType.RichText)); - }, - wait: gridResponseDuration(), - verify: (bloc) { - bloc.state.field.fold( - () => throw Exception("The field should not be none"), - (field) { - // The default length of the fields is 3. The length of the fields - // should not change after switching to other field type - // assert(gridTest.fieldContexts.length == 3); - assert(field.fieldType == FieldType.RichText); - }, - ); - }, - ); - - blocTest( - "delete field", - build: () => editorBloc, - act: (bloc) async { - editorBloc.add(const FieldEditorEvent.deleteField()); - }, - wait: gridResponseDuration(), - verify: (bloc) { - // assert(gridTest.fieldContexts.length == 2); - }, - ); - }); -} diff --git a/frontend/app_flowy/test/bloc_test/grid_test/select_option_bloc_test.dart b/frontend/app_flowy/test/bloc_test/grid_test/select_option_bloc_test.dart deleted file mode 100644 index fef80e2181..0000000000 --- a/frontend/app_flowy/test/bloc_test/grid_test/select_option_bloc_test.dart +++ /dev/null @@ -1,201 +0,0 @@ -import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; -import 'package:app_flowy/plugins/grid/application/cell/select_option_editor_bloc.dart'; -import 'package:app_flowy/plugins/grid/application/prelude.dart'; -import 'package:dartz/dartz.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:bloc_test/bloc_test.dart'; -import 'util.dart'; - -void main() { - late AppFlowyGridCellTest cellTest; - setUpAll(() async { - cellTest = await AppFlowyGridCellTest.ensureInitialized(); - }); - - group('SingleSelectOptionBloc', () { - late GridSelectOptionCellController cellController; - setUp(() async { - await cellTest.createTestGrid(); - await cellTest.createTestRow(); - cellController = await cellTest.makeCellController( - FieldType.SingleSelect, - ); - }); - - blocTest( - "delete options", - build: () { - final bloc = SelectOptionCellEditorBloc(cellController: cellController); - bloc.add(const SelectOptionEditorEvent.initial()); - return bloc; - }, - act: (bloc) async { - bloc.add(const SelectOptionEditorEvent.newOption("A")); - await Future.delayed(gridResponseDuration()); - bloc.add(const SelectOptionEditorEvent.newOption("B")); - await Future.delayed(gridResponseDuration()); - bloc.add(const SelectOptionEditorEvent.newOption("C")); - await Future.delayed(gridResponseDuration()); - bloc.add(const SelectOptionEditorEvent.deleteAllOptions()); - }, - wait: gridResponseDuration(), - verify: (bloc) { - assert(bloc.state.options.isEmpty); - }, - ); - - blocTest( - "create option", - build: () { - final bloc = SelectOptionCellEditorBloc(cellController: cellController); - bloc.add(const SelectOptionEditorEvent.initial()); - return bloc; - }, - act: (bloc) async { - bloc.add(const SelectOptionEditorEvent.newOption("A")); - }, - wait: gridResponseDuration(), - verify: (bloc) { - expect(bloc.state.options.length, 1); - expect(bloc.state.options[0].name, "A"); - }, - ); - - blocTest( - "delete option", - build: () { - final bloc = SelectOptionCellEditorBloc(cellController: cellController); - bloc.add(const SelectOptionEditorEvent.initial()); - return bloc; - }, - act: (bloc) async { - bloc.add(const SelectOptionEditorEvent.newOption("A")); - await Future.delayed(gridResponseDuration()); - bloc.add(SelectOptionEditorEvent.deleteOption(bloc.state.options[0])); - }, - wait: gridResponseDuration(), - verify: (bloc) { - assert(bloc.state.options.isEmpty); - }, - ); - - blocTest( - "update option", - build: () { - final bloc = SelectOptionCellEditorBloc(cellController: cellController); - bloc.add(const SelectOptionEditorEvent.initial()); - return bloc; - }, - act: (bloc) async { - bloc.add(const SelectOptionEditorEvent.newOption("A")); - await Future.delayed(gridResponseDuration()); - SelectOptionPB optionUpdate = bloc.state.options[0] - ..color = SelectOptionColorPB.Aqua - ..name = "B"; - bloc.add(SelectOptionEditorEvent.updateOption(optionUpdate)); - }, - wait: gridResponseDuration(), - verify: (bloc) { - assert(bloc.state.options.length == 1); - expect(bloc.state.options[0].color, SelectOptionColorPB.Aqua); - expect(bloc.state.options[0].name, "B"); - }, - ); - - blocTest( - "select/unselect option", - build: () { - final bloc = SelectOptionCellEditorBloc(cellController: cellController); - bloc.add(const SelectOptionEditorEvent.initial()); - return bloc; - }, - act: (bloc) async { - bloc.add(const SelectOptionEditorEvent.newOption("A")); - await Future.delayed(gridResponseDuration()); - expect(bloc.state.selectedOptions.length, 1); - final optionId = bloc.state.options[0].id; - bloc.add(SelectOptionEditorEvent.unSelectOption(optionId)); - await Future.delayed(gridResponseDuration()); - assert(bloc.state.selectedOptions.isEmpty); - bloc.add(SelectOptionEditorEvent.selectOption(optionId)); - }, - wait: gridResponseDuration(), - verify: (bloc) { - assert(bloc.state.selectedOptions.length == 1); - expect(bloc.state.selectedOptions[0].name, "A"); - }, - ); - - blocTest( - "select an option or create one", - build: () { - final bloc = SelectOptionCellEditorBloc(cellController: cellController); - bloc.add(const SelectOptionEditorEvent.initial()); - return bloc; - }, - act: (bloc) async { - bloc.add(const SelectOptionEditorEvent.newOption("A")); - await Future.delayed(gridResponseDuration()); - bloc.add(const SelectOptionEditorEvent.trySelectOption("B")); - await Future.delayed(gridResponseDuration()); - bloc.add(const SelectOptionEditorEvent.trySelectOption("A")); - }, - wait: gridResponseDuration(), - verify: (bloc) { - assert(bloc.state.selectedOptions.length == 1); - assert(bloc.state.options.length == 2); - expect(bloc.state.selectedOptions[0].name, "A"); - }, - ); - - blocTest( - "select multiple options", - build: () { - final bloc = SelectOptionCellEditorBloc(cellController: cellController); - bloc.add(const SelectOptionEditorEvent.initial()); - return bloc; - }, - act: (bloc) async { - bloc.add(const SelectOptionEditorEvent.newOption("A")); - await Future.delayed(gridResponseDuration()); - bloc.add(const SelectOptionEditorEvent.newOption("B")); - await Future.delayed(gridResponseDuration()); - bloc.add(const SelectOptionEditorEvent.selectMultipleOptions( - ["A", "B", "C"], "x")); - }, - wait: gridResponseDuration(), - verify: (bloc) { - assert(bloc.state.selectedOptions.length == 1); - expect(bloc.state.selectedOptions[0].name, "A"); - expect(bloc.state.filter, const Some("x")); - }, - ); - - blocTest( - "filter options", - build: () { - final bloc = SelectOptionCellEditorBloc(cellController: cellController); - bloc.add(const SelectOptionEditorEvent.initial()); - return bloc; - }, - act: (bloc) async { - bloc.add(const SelectOptionEditorEvent.newOption("abcd")); - await Future.delayed(gridResponseDuration()); - bloc.add(const SelectOptionEditorEvent.newOption("aaaa")); - await Future.delayed(gridResponseDuration()); - bloc.add(const SelectOptionEditorEvent.newOption("defg")); - await Future.delayed(gridResponseDuration()); - bloc.add(const SelectOptionEditorEvent.filterOption("a")); - }, - wait: gridResponseDuration(), - verify: (bloc) { - expect(bloc.state.options.length, 2); - expect(bloc.state.allOptions.length, 3); - expect(bloc.state.createOption, const Some("a")); - expect(bloc.state.filter, const Some("a")); - }, - ); - }); -} diff --git a/frontend/app_flowy/test/bloc_test/grid_test/util.dart b/frontend/app_flowy/test/bloc_test/grid_test/util.dart index 8e9dd16fec..27c111a8f3 100644 --- a/frontend/app_flowy/test/bloc_test/grid_test/util.dart +++ b/frontend/app_flowy/test/bloc_test/grid_test/util.dart @@ -18,26 +18,26 @@ import '../../util.dart'; class GridTestContext { final ViewPB gridView; - final GridController _gridController; + final GridController gridController; - GridTestContext(this.gridView, this._gridController); + GridTestContext(this.gridView, this.gridController); List get rowInfos { - return _gridController.rowInfos; + return gridController.rowInfos; } UnmodifiableMapView get blocks { - return _gridController.blocks; + return gridController.blocks; } List get fieldContexts => fieldController.fieldInfos; GridFieldController get fieldController { - return _gridController.fieldController; + return gridController.fieldController; } Future createRow() async { - return _gridController.createRow(); + return gridController.createRow(); } FieldEditorBloc createFieldEditor({ @@ -71,7 +71,7 @@ class GridTestContext { final RowInfo rowInfo = rowInfos.last; final blockCache = blocks[rowInfo.rowPB.blockId]; final rowCache = blockCache?.rowCache; - final fieldController = _gridController.fieldController; + final fieldController = gridController.fieldController; final rowDataController = GridRowDataController( rowInfo: rowInfo, @@ -171,7 +171,7 @@ class AppFlowyGridTest { return result.fold( (view) async { final context = GridTestContext(view, GridController(view: view)); - final result = await context._gridController.openGrid(); + final result = await context.gridController.openGrid(); result.fold((l) => null, (r) => throw Exception(r)); return context; }, From b6773a732b9e4e3573b21f7ff5195053ec446a2f Mon Sep 17 00:00:00 2001 From: nathan Date: Sun, 27 Nov 2022 16:53:42 +0800 Subject: [PATCH 2/2] chore: add filter tests --- .../board/application/card/card_bloc.dart | 1 - .../board/presentation/board_page.dart | 1 - .../grid/application/row/row_cache.dart | 3 - .../cell/select_option_cell_test.dart | 200 ++++++++++++++++++ .../grid_test/field/edit_field_test.dart | 102 +++++++++ .../grid_test/filter/create_filter_test.dart | 148 +++++++++++++ .../filter/edit_filter_field_test.dart | 57 +++++ .../grid_test/filter/filter_menu_test.dart | 61 ++++++ .../grid_test/filter/filter_rows_test.dart | 99 +++++++++ .../grid_test/filter/filter_util.dart | 42 ++++ .../test/bloc_test/grid_test/util.dart | 24 ++- 11 files changed, 722 insertions(+), 16 deletions(-) create mode 100644 frontend/app_flowy/test/bloc_test/grid_test/cell/select_option_cell_test.dart create mode 100644 frontend/app_flowy/test/bloc_test/grid_test/field/edit_field_test.dart create mode 100644 frontend/app_flowy/test/bloc_test/grid_test/filter/create_filter_test.dart create mode 100644 frontend/app_flowy/test/bloc_test/grid_test/filter/edit_filter_field_test.dart create mode 100644 frontend/app_flowy/test/bloc_test/grid_test/filter/filter_menu_test.dart create mode 100644 frontend/app_flowy/test/bloc_test/grid_test/filter/filter_rows_test.dart create mode 100644 frontend/app_flowy/test/bloc_test/grid_test/filter/filter_util.dart diff --git a/frontend/app_flowy/lib/plugins/board/application/card/card_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/card/card_bloc.dart index 0f383432bd..4902e77555 100644 --- a/frontend/app_flowy/lib/plugins/board/application/card/card_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/card/card_bloc.dart @@ -66,7 +66,6 @@ class BoardCardBloc extends Bloc { state.cells.map((cell) => cell.identifier.fieldInfo).toList(), ), rowPB: state.rowPB, - visible: true, ); } diff --git a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart index 816feb76de..0ec834c526 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart @@ -287,7 +287,6 @@ class _BoardContentState extends State { gridId: gridId, fields: UnmodifiableListView(fieldController.fieldInfos), rowPB: rowPB, - visible: true, ); final dataController = GridRowDataController( diff --git a/frontend/app_flowy/lib/plugins/grid/application/row/row_cache.dart b/frontend/app_flowy/lib/plugins/grid/application/row/row_cache.dart index 79634168c0..07e426b385 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/row/row_cache.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/row/row_cache.dart @@ -39,7 +39,6 @@ class GridRowCache { UnmodifiableListView get visibleRows { var visibleRows = [..._rowList.rows]; - visibleRows.retainWhere((element) => element.visible); return UnmodifiableListView(visibleRows); } @@ -236,7 +235,6 @@ class GridRowCache { gridId: gridId, fields: _fieldNotifier.fields, rowPB: rowPB, - visible: true, ); } } @@ -264,7 +262,6 @@ class RowInfo with _$RowInfo { required String gridId, required UnmodifiableListView fields, required RowPB rowPB, - required bool visible, }) = _RowInfo; } diff --git a/frontend/app_flowy/test/bloc_test/grid_test/cell/select_option_cell_test.dart b/frontend/app_flowy/test/bloc_test/grid_test/cell/select_option_cell_test.dart new file mode 100644 index 0000000000..8ec4dd9159 --- /dev/null +++ b/frontend/app_flowy/test/bloc_test/grid_test/cell/select_option_cell_test.dart @@ -0,0 +1,200 @@ +import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; +import 'package:app_flowy/plugins/grid/application/cell/select_option_editor_bloc.dart'; +import 'package:app_flowy/plugins/grid/application/prelude.dart'; +import 'package:dartz/dartz.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:bloc_test/bloc_test.dart'; +import '../util.dart'; + +void main() { + late AppFlowyGridCellTest cellTest; + setUpAll(() async { + cellTest = await AppFlowyGridCellTest.ensureInitialized(); + }); + + group('SingleSelectOptionBloc', () { + late GridSelectOptionCellController cellController; + setUp(() async { + await cellTest.createTestGrid(); + await cellTest.createTestRow(); + cellController = + await cellTest.makeCellController(FieldType.SingleSelect, 0); + }); + + blocTest( + "delete options", + build: () { + final bloc = SelectOptionCellEditorBloc(cellController: cellController); + bloc.add(const SelectOptionEditorEvent.initial()); + return bloc; + }, + act: (bloc) async { + bloc.add(const SelectOptionEditorEvent.newOption("A")); + await Future.delayed(gridResponseDuration()); + bloc.add(const SelectOptionEditorEvent.newOption("B")); + await Future.delayed(gridResponseDuration()); + bloc.add(const SelectOptionEditorEvent.newOption("C")); + await Future.delayed(gridResponseDuration()); + bloc.add(const SelectOptionEditorEvent.deleteAllOptions()); + }, + wait: gridResponseDuration(), + verify: (bloc) { + assert(bloc.state.options.isEmpty); + }, + ); + + blocTest( + "create option", + build: () { + final bloc = SelectOptionCellEditorBloc(cellController: cellController); + bloc.add(const SelectOptionEditorEvent.initial()); + return bloc; + }, + act: (bloc) async { + bloc.add(const SelectOptionEditorEvent.newOption("A")); + }, + wait: gridResponseDuration(), + verify: (bloc) { + expect(bloc.state.options.length, 1); + expect(bloc.state.options[0].name, "A"); + }, + ); + + blocTest( + "delete option", + build: () { + final bloc = SelectOptionCellEditorBloc(cellController: cellController); + bloc.add(const SelectOptionEditorEvent.initial()); + return bloc; + }, + act: (bloc) async { + bloc.add(const SelectOptionEditorEvent.newOption("A")); + await Future.delayed(gridResponseDuration()); + bloc.add(SelectOptionEditorEvent.deleteOption(bloc.state.options[0])); + }, + wait: gridResponseDuration(), + verify: (bloc) { + assert(bloc.state.options.isEmpty); + }, + ); + + blocTest( + "update option", + build: () { + final bloc = SelectOptionCellEditorBloc(cellController: cellController); + bloc.add(const SelectOptionEditorEvent.initial()); + return bloc; + }, + act: (bloc) async { + bloc.add(const SelectOptionEditorEvent.newOption("A")); + await Future.delayed(gridResponseDuration()); + SelectOptionPB optionUpdate = bloc.state.options[0] + ..color = SelectOptionColorPB.Aqua + ..name = "B"; + bloc.add(SelectOptionEditorEvent.updateOption(optionUpdate)); + }, + wait: gridResponseDuration(), + verify: (bloc) { + assert(bloc.state.options.length == 1); + expect(bloc.state.options[0].color, SelectOptionColorPB.Aqua); + expect(bloc.state.options[0].name, "B"); + }, + ); + + blocTest( + "select/unselect option", + build: () { + final bloc = SelectOptionCellEditorBloc(cellController: cellController); + bloc.add(const SelectOptionEditorEvent.initial()); + return bloc; + }, + act: (bloc) async { + bloc.add(const SelectOptionEditorEvent.newOption("A")); + await Future.delayed(gridResponseDuration()); + expect(bloc.state.selectedOptions.length, 1); + final optionId = bloc.state.options[0].id; + bloc.add(SelectOptionEditorEvent.unSelectOption(optionId)); + await Future.delayed(gridResponseDuration()); + assert(bloc.state.selectedOptions.isEmpty); + bloc.add(SelectOptionEditorEvent.selectOption(optionId)); + }, + wait: gridResponseDuration(), + verify: (bloc) { + assert(bloc.state.selectedOptions.length == 1); + expect(bloc.state.selectedOptions[0].name, "A"); + }, + ); + + blocTest( + "select an option or create one", + build: () { + final bloc = SelectOptionCellEditorBloc(cellController: cellController); + bloc.add(const SelectOptionEditorEvent.initial()); + return bloc; + }, + act: (bloc) async { + bloc.add(const SelectOptionEditorEvent.newOption("A")); + await Future.delayed(gridResponseDuration()); + bloc.add(const SelectOptionEditorEvent.trySelectOption("B")); + await Future.delayed(gridResponseDuration()); + bloc.add(const SelectOptionEditorEvent.trySelectOption("A")); + }, + wait: gridResponseDuration(), + verify: (bloc) { + assert(bloc.state.selectedOptions.length == 1); + assert(bloc.state.options.length == 2); + expect(bloc.state.selectedOptions[0].name, "A"); + }, + ); + + blocTest( + "select multiple options", + build: () { + final bloc = SelectOptionCellEditorBloc(cellController: cellController); + bloc.add(const SelectOptionEditorEvent.initial()); + return bloc; + }, + act: (bloc) async { + bloc.add(const SelectOptionEditorEvent.newOption("A")); + await Future.delayed(gridResponseDuration()); + bloc.add(const SelectOptionEditorEvent.newOption("B")); + await Future.delayed(gridResponseDuration()); + bloc.add(const SelectOptionEditorEvent.selectMultipleOptions( + ["A", "B", "C"], "x")); + }, + wait: gridResponseDuration(), + verify: (bloc) { + assert(bloc.state.selectedOptions.length == 1); + expect(bloc.state.selectedOptions[0].name, "A"); + expect(bloc.state.filter, const Some("x")); + }, + ); + + blocTest( + "filter options", + build: () { + final bloc = SelectOptionCellEditorBloc(cellController: cellController); + bloc.add(const SelectOptionEditorEvent.initial()); + return bloc; + }, + act: (bloc) async { + bloc.add(const SelectOptionEditorEvent.newOption("abcd")); + await Future.delayed(gridResponseDuration()); + bloc.add(const SelectOptionEditorEvent.newOption("aaaa")); + await Future.delayed(gridResponseDuration()); + bloc.add(const SelectOptionEditorEvent.newOption("defg")); + await Future.delayed(gridResponseDuration()); + bloc.add(const SelectOptionEditorEvent.filterOption("a")); + }, + wait: gridResponseDuration(), + verify: (bloc) { + expect(bloc.state.options.length, 2); + expect(bloc.state.allOptions.length, 3); + expect(bloc.state.createOption, const Some("a")); + expect(bloc.state.filter, const Some("a")); + }, + ); + }); +} diff --git a/frontend/app_flowy/test/bloc_test/grid_test/field/edit_field_test.dart b/frontend/app_flowy/test/bloc_test/grid_test/field/edit_field_test.dart new file mode 100644 index 0000000000..33b15372a2 --- /dev/null +++ b/frontend/app_flowy/test/bloc_test/grid_test/field/edit_field_test.dart @@ -0,0 +1,102 @@ +import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart'; +import 'package:app_flowy/plugins/grid/application/prelude.dart'; +import 'package:bloc_test/bloc_test.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; +import 'package:flutter_test/flutter_test.dart'; +import '../util.dart'; + +Future createEditorBloc(AppFlowyGridTest gridTest) async { + final context = await gridTest.createTestGrid(); + final fieldInfo = context.singleSelectFieldContext(); + final loader = FieldTypeOptionLoader( + gridId: context.gridView.id, + field: fieldInfo.field, + ); + + return FieldEditorBloc( + gridId: context.gridView.id, + fieldName: fieldInfo.name, + isGroupField: fieldInfo.isGroupField, + loader: loader, + )..add(const FieldEditorEvent.initial()); +} + +void main() { + late AppFlowyGridTest gridTest; + + setUpAll(() async { + gridTest = await AppFlowyGridTest.ensureInitialized(); + }); + + group('$FieldEditorBloc', () { + late FieldEditorBloc editorBloc; + + setUp(() async { + final context = await gridTest.createTestGrid(); + final fieldInfo = context.singleSelectFieldContext(); + final loader = FieldTypeOptionLoader( + gridId: context.gridView.id, + field: fieldInfo.field, + ); + + editorBloc = FieldEditorBloc( + gridId: context.gridView.id, + fieldName: fieldInfo.name, + isGroupField: fieldInfo.isGroupField, + loader: loader, + )..add(const FieldEditorEvent.initial()); + + await gridResponseFuture(); + }); + + blocTest( + "rename field", + build: () => editorBloc, + act: (bloc) async { + editorBloc.add(const FieldEditorEvent.updateName('Hello world')); + }, + wait: gridResponseDuration(), + verify: (bloc) { + bloc.state.field.fold( + () => throw Exception("The field should not be none"), + (field) { + assert(field.name == 'Hello world'); + }, + ); + }, + ); + + blocTest( + "switch to text field", + build: () => editorBloc, + act: (bloc) async { + editorBloc + .add(const FieldEditorEvent.switchToField(FieldType.RichText)); + }, + wait: gridResponseDuration(), + verify: (bloc) { + bloc.state.field.fold( + () => throw Exception("The field should not be none"), + (field) { + // The default length of the fields is 3. The length of the fields + // should not change after switching to other field type + // assert(gridTest.fieldContexts.length == 3); + assert(field.fieldType == FieldType.RichText); + }, + ); + }, + ); + + blocTest( + "delete field", + build: () => editorBloc, + act: (bloc) async { + editorBloc.add(const FieldEditorEvent.deleteField()); + }, + wait: gridResponseDuration(), + verify: (bloc) { + // assert(gridTest.fieldContexts.length == 2); + }, + ); + }); +} diff --git a/frontend/app_flowy/test/bloc_test/grid_test/filter/create_filter_test.dart b/frontend/app_flowy/test/bloc_test/grid_test/filter/create_filter_test.dart new file mode 100644 index 0000000000..db9dfdccab --- /dev/null +++ b/frontend/app_flowy/test/bloc_test/grid_test/filter/create_filter_test.dart @@ -0,0 +1,148 @@ +import 'package:app_flowy/plugins/grid/application/filter/filter_service.dart'; +import 'package:app_flowy/plugins/grid/application/grid_bloc.dart'; +import 'package:app_flowy/plugins/grid/application/grid_data_controller.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_filter.pbenum.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/text_filter.pb.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../util.dart'; + +void main() { + late AppFlowyGridTest gridTest; + setUpAll(() async { + gridTest = await AppFlowyGridTest.ensureInitialized(); + }); + + test('create a text filter)', () async { + final context = await gridTest.createTestGrid(); + final service = FilterFFIService(viewId: context.gridView.id); + final textField = context.textFieldContext(); + await service.insertTextFilter( + fieldId: textField.id, + condition: TextFilterCondition.TextIsEmpty, + content: ""); + await gridResponseFuture(); + + assert(context.fieldController.filterInfos.length == 1); + }); + + test('delete a text filter)', () async { + final context = await gridTest.createTestGrid(); + final service = FilterFFIService(viewId: context.gridView.id); + final textField = context.textFieldContext(); + await service.insertTextFilter( + fieldId: textField.id, + condition: TextFilterCondition.TextIsEmpty, + content: ""); + await gridResponseFuture(); + + final filterInfo = context.fieldController.filterInfos.first; + await service.deleteFilter( + fieldId: textField.id, + filterId: filterInfo.filter.id, + fieldType: textField.fieldType, + ); + await gridResponseFuture(); + + assert(context.fieldController.filterInfos.isEmpty); + }); + + test('filter rows with condition: text is empty', () async { + final context = await gridTest.createTestGrid(); + final service = FilterFFIService(viewId: context.gridView.id); + final gridController = GridController(view: context.gridView); + final gridBloc = GridBloc( + view: context.gridView, + gridController: gridController, + )..add(const GridEvent.initial()); + await gridResponseFuture(); + + final textField = context.textFieldContext(); + service.insertTextFilter( + fieldId: textField.id, + condition: TextFilterCondition.TextIsEmpty, + content: ""); + await gridResponseFuture(); + + assert(gridBloc.state.rowInfos.length == 3); + }); + + test('filter rows with condition: text is empty(After edit the row)', + () async { + final context = await gridTest.createTestGrid(); + final service = FilterFFIService(viewId: context.gridView.id); + final gridController = GridController(view: context.gridView); + final gridBloc = GridBloc( + view: context.gridView, + gridController: gridController, + )..add(const GridEvent.initial()); + await gridResponseFuture(); + + final textField = context.textFieldContext(); + await service.insertTextFilter( + fieldId: textField.id, + condition: TextFilterCondition.TextIsEmpty, + content: ""); + await gridResponseFuture(); + + final controller = await context.makeTextCellController(0); + controller.saveCellData("edit text cell content"); + await gridResponseFuture(); + assert(gridBloc.state.rowInfos.length == 2); + + controller.saveCellData(""); + await gridResponseFuture(); + assert(gridBloc.state.rowInfos.length == 3); + }); + + test('filter rows with condition: text is not empty', () async { + final context = await gridTest.createTestGrid(); + final service = FilterFFIService(viewId: context.gridView.id); + final textField = context.textFieldContext(); + await gridResponseFuture(); + await service.insertTextFilter( + fieldId: textField.id, + condition: TextFilterCondition.TextIsNotEmpty, + content: ""); + await gridResponseFuture(); + assert(context.rowInfos.isEmpty); + }); + + test('filter rows with condition: checkbox uncheck', () async { + final context = await gridTest.createTestGrid(); + final checkboxField = context.checkboxFieldContext(); + final service = FilterFFIService(viewId: context.gridView.id); + final gridController = GridController(view: context.gridView); + final gridBloc = GridBloc( + view: context.gridView, + gridController: gridController, + )..add(const GridEvent.initial()); + + await gridResponseFuture(); + await service.insertCheckboxFilter( + fieldId: checkboxField.id, + condition: CheckboxFilterCondition.IsUnChecked, + ); + await gridResponseFuture(); + assert(gridBloc.state.rowInfos.length == 3); + }); + + test('filter rows with condition: checkbox check', () async { + final context = await gridTest.createTestGrid(); + final checkboxField = context.checkboxFieldContext(); + final service = FilterFFIService(viewId: context.gridView.id); + final gridController = GridController(view: context.gridView); + final gridBloc = GridBloc( + view: context.gridView, + gridController: gridController, + )..add(const GridEvent.initial()); + + await gridResponseFuture(); + await service.insertCheckboxFilter( + fieldId: checkboxField.id, + condition: CheckboxFilterCondition.IsChecked, + ); + await gridResponseFuture(); + assert(gridBloc.state.rowInfos.isEmpty); + }); +} diff --git a/frontend/app_flowy/test/bloc_test/grid_test/filter/edit_filter_field_test.dart b/frontend/app_flowy/test/bloc_test/grid_test/filter/edit_filter_field_test.dart new file mode 100644 index 0000000000..d1e6263b24 --- /dev/null +++ b/frontend/app_flowy/test/bloc_test/grid_test/filter/edit_filter_field_test.dart @@ -0,0 +1,57 @@ +import 'package:app_flowy/plugins/grid/application/field/field_editor_bloc.dart'; +import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart'; +import 'package:app_flowy/plugins/grid/application/filter/filter_menu_bloc.dart'; +import 'package:app_flowy/plugins/grid/application/filter/filter_service.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/text_filter.pb.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../util.dart'; + +void main() { + late AppFlowyGridTest gridTest; + setUpAll(() async { + gridTest = await AppFlowyGridTest.ensureInitialized(); + }); + + test("create a text filter and then alter the filter's field)", () async { + final context = await gridTest.createTestGrid(); + final service = FilterFFIService(viewId: context.gridView.id); + final textField = context.textFieldContext(); + + // Create the filter menu bloc + final menuBloc = GridFilterMenuBloc( + fieldController: context.fieldController, + viewId: context.gridView.id, + )..add(const GridFilterMenuEvent.initial()); + + // Insert filter for the text field + await service.insertTextFilter( + fieldId: textField.id, + condition: TextFilterCondition.TextIsEmpty, + content: ""); + await gridResponseFuture(); + assert(menuBloc.state.filters.length == 1); + + // Edit the text field + final loader = FieldTypeOptionLoader( + gridId: context.gridView.id, + field: textField.field, + ); + + final editorBloc = FieldEditorBloc( + gridId: context.gridView.id, + fieldName: textField.field.name, + isGroupField: false, + loader: loader, + )..add(const FieldEditorEvent.initial()); + await gridResponseFuture(); + + // Alter the field type to Number + editorBloc.add(const FieldEditorEvent.switchToField(FieldType.Number)); + await gridResponseFuture(); + + // Check the number of filters + assert(menuBloc.state.filters.isEmpty); + }); +} diff --git a/frontend/app_flowy/test/bloc_test/grid_test/filter/filter_menu_test.dart b/frontend/app_flowy/test/bloc_test/grid_test/filter/filter_menu_test.dart new file mode 100644 index 0000000000..604b09d93d --- /dev/null +++ b/frontend/app_flowy/test/bloc_test/grid_test/filter/filter_menu_test.dart @@ -0,0 +1,61 @@ +import 'package:app_flowy/plugins/grid/application/filter/filter_menu_bloc.dart'; +import 'package:app_flowy/plugins/grid/application/filter/filter_service.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/text_filter.pb.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../util.dart'; + +void main() { + late AppFlowyGridTest gridTest; + setUpAll(() async { + gridTest = await AppFlowyGridTest.ensureInitialized(); + }); + + test('test filter menu after create a text filter)', () async { + final context = await gridTest.createTestGrid(); + final menuBloc = GridFilterMenuBloc( + viewId: context.gridView.id, fieldController: context.fieldController) + ..add(const GridFilterMenuEvent.initial()); + await gridResponseFuture(); + assert(menuBloc.state.creatableFields.length == 1); + + final service = FilterFFIService(viewId: context.gridView.id); + final textField = context.textFieldContext(); + await service.insertTextFilter( + fieldId: textField.id, + condition: TextFilterCondition.TextIsEmpty, + content: ""); + await gridResponseFuture(); + assert(menuBloc.state.creatableFields.isEmpty); + }); + + test('test filter menu after update existing text filter)', () async { + final context = await gridTest.createTestGrid(); + final menuBloc = GridFilterMenuBloc( + viewId: context.gridView.id, fieldController: context.fieldController) + ..add(const GridFilterMenuEvent.initial()); + await gridResponseFuture(); + + final service = FilterFFIService(viewId: context.gridView.id); + final textField = context.textFieldContext(); + + // Create filter + await service.insertTextFilter( + fieldId: textField.id, + condition: TextFilterCondition.TextIsEmpty, + content: ""); + await gridResponseFuture(); + + final textFilter = context.fieldController.filterInfos.first; + // Update the existing filter + await service.insertTextFilter( + fieldId: textField.id, + filterId: textFilter.filter.id, + condition: TextFilterCondition.Is, + content: "ABC"); + await gridResponseFuture(); + assert(menuBloc.state.filters.first.textFilter()!.condition == + TextFilterCondition.Is); + assert(menuBloc.state.filters.first.textFilter()!.content == "ABC"); + }); +} diff --git a/frontend/app_flowy/test/bloc_test/grid_test/filter/filter_rows_test.dart b/frontend/app_flowy/test/bloc_test/grid_test/filter/filter_rows_test.dart new file mode 100644 index 0000000000..4644c76ac3 --- /dev/null +++ b/frontend/app_flowy/test/bloc_test/grid_test/filter/filter_rows_test.dart @@ -0,0 +1,99 @@ +import 'package:app_flowy/plugins/grid/application/filter/filter_service.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/text_filter.pb.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../util.dart'; +import 'filter_util.dart'; + +void main() { + late AppFlowyGridTest gridTest; + setUpAll(() async { + gridTest = await AppFlowyGridTest.ensureInitialized(); + }); + + test('filter rows by text is empty or is not empty condition)', () async { + final context = await createTestFilterGrid(gridTest); + + final service = FilterFFIService(viewId: context.gridView.id); + final textField = context.textFieldContext(); + // create a new filter + await service.insertTextFilter( + fieldId: textField.id, + condition: TextFilterCondition.TextIsEmpty, + content: ""); + await gridResponseFuture(); + assert(context.fieldController.filterInfos.length == 1, + "expect 1 but receive ${context.fieldController.filterInfos.length}"); + assert(context.rowInfos.length == 1, + "expect 1 but receive ${context.rowInfos.length}"); + + // Update the existing filter + final textFilter = context.fieldController.filterInfos.first; + await service.insertTextFilter( + fieldId: textField.id, + filterId: textFilter.filter.id, + condition: TextFilterCondition.TextIsNotEmpty, + content: ""); + await gridResponseFuture(); + assert(context.rowInfos.length == 2); + + // delete the filter + await service.deleteFilter( + fieldId: textField.id, + filterId: textFilter.filter.id, + fieldType: textField.fieldType, + ); + await gridResponseFuture(); + assert(context.rowInfos.length == 3); + }); + + test('filter rows by text is condition)', () async { + final context = await createTestFilterGrid(gridTest); + + final service = FilterFFIService(viewId: context.gridView.id); + final textField = context.textFieldContext(); + // create a new filter + await service.insertTextFilter( + fieldId: textField.id, condition: TextFilterCondition.Is, content: "A"); + await gridResponseFuture(); + assert(context.rowInfos.length == 1, + "expect 1 but receive ${context.rowInfos.length}"); + + // Update the existing filter's content from 'A' to 'B' + final textFilter = context.fieldController.filterInfos.first; + await service.insertTextFilter( + fieldId: textField.id, + filterId: textFilter.filter.id, + condition: TextFilterCondition.Is, + content: "B"); + await gridResponseFuture(); + assert(context.rowInfos.length == 1); + + // Update the existing filter's content from 'B' to 'b' + await service.insertTextFilter( + fieldId: textField.id, + filterId: textFilter.filter.id, + condition: TextFilterCondition.Is, + content: "b"); + await gridResponseFuture(); + assert(context.rowInfos.length == 1); + + // Update the existing filter with content 'C' + await service.insertTextFilter( + fieldId: textField.id, + filterId: textFilter.filter.id, + condition: TextFilterCondition.Is, + content: "C"); + await gridResponseFuture(); + assert(context.rowInfos.isEmpty); + + // delete the filter + await service.deleteFilter( + fieldId: textField.id, + filterId: textFilter.filter.id, + fieldType: textField.fieldType, + ); + await gridResponseFuture(); + assert(context.rowInfos.length == 3); + }); +} diff --git a/frontend/app_flowy/test/bloc_test/grid_test/filter/filter_util.dart b/frontend/app_flowy/test/bloc_test/grid_test/filter/filter_util.dart new file mode 100644 index 0000000000..0a07e25309 --- /dev/null +++ b/frontend/app_flowy/test/bloc_test/grid_test/filter/filter_util.dart @@ -0,0 +1,42 @@ +import 'package:app_flowy/plugins/grid/application/grid_data_controller.dart'; +import 'package:app_flowy/plugins/grid/grid.dart'; +import 'package:app_flowy/workspace/application/app/app_service.dart'; + +import '../util.dart'; + +Future createTestFilterGrid(AppFlowyGridTest gridTest) async { + final app = await gridTest.unitTest.createTestApp(); + final builder = GridPluginBuilder(); + final context = await AppService() + .createView( + appId: app.id, + name: "Filter Grid", + dataFormatType: builder.dataFormatType, + pluginType: builder.pluginType, + layoutType: builder.layoutType!, + ) + .then((result) { + return result.fold( + (view) async { + final context = GridTestContext(view, GridController(view: view)); + final result = await context.gridController.openGrid(); + + await editCells(context); + await gridResponseFuture(milliseconds: 500); + result.fold((l) => null, (r) => throw Exception(r)); + return context; + }, + (error) => throw Exception(), + ); + }); + + return context; +} + +Future editCells(GridTestContext context) async { + final controller0 = await context.makeTextCellController(0); + final controller1 = await context.makeTextCellController(1); + + controller0.saveCellData('A'); + controller1.saveCellData('B'); +} diff --git a/frontend/app_flowy/test/bloc_test/grid_test/util.dart b/frontend/app_flowy/test/bloc_test/grid_test/util.dart index 27c111a8f3..e361a8f39b 100644 --- a/frontend/app_flowy/test/bloc_test/grid_test/util.dart +++ b/frontend/app_flowy/test/bloc_test/grid_test/util.dart @@ -60,15 +60,17 @@ class GridTestContext { return editorBloc; } - Future makeCellController(String fieldId) async { - final builder = await makeCellControllerBuilder(fieldId); + Future makeCellController( + String fieldId, int rowIndex) async { + final builder = await makeCellControllerBuilder(fieldId, rowIndex); return builder.build(); } Future makeCellControllerBuilder( String fieldId, + int rowIndex, ) async { - final RowInfo rowInfo = rowInfos.last; + final RowInfo rowInfo = rowInfos[rowIndex]; final blockCache = blocks[rowInfo.rowPB.blockId]; final rowCache = blockCache?.rowCache; final fieldController = gridController.fieldController; @@ -125,22 +127,22 @@ class GridTestContext { } Future makeSelectOptionCellController( - FieldType fieldType) async { + FieldType fieldType, int rowIndex) async { assert(fieldType == FieldType.SingleSelect || fieldType == FieldType.MultiSelect); final field = fieldContexts.firstWhere((element) => element.fieldType == fieldType); - final cellController = - await makeCellController(field.id) as GridSelectOptionCellController; + final cellController = await makeCellController(field.id, rowIndex) + as GridSelectOptionCellController; return cellController; } - Future makeTextCellController() async { + Future makeTextCellController(int rowIndex) async { final field = fieldContexts .firstWhere((element) => element.fieldType == FieldType.RichText); final cellController = - await makeCellController(field.id) as GridCellController; + await makeCellController(field.id, rowIndex) as GridCellController; return cellController; } } @@ -205,12 +207,12 @@ class AppFlowyGridCellTest { } Future makeCellController( - FieldType fieldType) async { - return context.makeSelectOptionCellController(fieldType); + FieldType fieldType, int rowIndex) async { + return context.makeSelectOptionCellController(fieldType, rowIndex); } } -Future gridResponseFuture({int milliseconds = 500}) { +Future gridResponseFuture({int milliseconds = 200}) { return Future.delayed(gridResponseDuration(milliseconds: milliseconds)); }