mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: add grid header bloc test (#1341)
Co-authored-by: nathan <nathan@appflowy.io>
This commit is contained in:
parent
aa58c79dbb
commit
96b1c6a540
@ -11,9 +11,16 @@ class FieldActionSheetBloc
|
|||||||
extends Bloc<FieldActionSheetEvent, FieldActionSheetState> {
|
extends Bloc<FieldActionSheetEvent, FieldActionSheetState> {
|
||||||
final FieldService fieldService;
|
final FieldService fieldService;
|
||||||
|
|
||||||
FieldActionSheetBloc({required FieldPB field, required this.fieldService})
|
FieldActionSheetBloc({required GridFieldCellContext fieldCellContext})
|
||||||
: super(FieldActionSheetState.initial(
|
: fieldService = FieldService(
|
||||||
FieldTypeOptionDataPB.create()..field_2 = field)) {
|
gridId: fieldCellContext.gridId,
|
||||||
|
fieldId: fieldCellContext.field.id,
|
||||||
|
),
|
||||||
|
super(
|
||||||
|
FieldActionSheetState.initial(
|
||||||
|
FieldTypeOptionDataPB.create()..field_2 = fieldCellContext.field,
|
||||||
|
),
|
||||||
|
) {
|
||||||
on<FieldActionSheetEvent>(
|
on<FieldActionSheetEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
await event.map(
|
await event.map(
|
||||||
@ -31,6 +38,13 @@ class FieldActionSheetBloc
|
|||||||
(err) => Log.error(err),
|
(err) => Log.error(err),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
showField: (_ShowField value) async {
|
||||||
|
final result = await fieldService.updateField(visibility: true);
|
||||||
|
result.fold(
|
||||||
|
(l) => null,
|
||||||
|
(err) => Log.error(err),
|
||||||
|
);
|
||||||
|
},
|
||||||
deleteField: (_DeleteField value) async {
|
deleteField: (_DeleteField value) async {
|
||||||
final result = await fieldService.deleteField();
|
final result = await fieldService.deleteField();
|
||||||
result.fold(
|
result.fold(
|
||||||
@ -62,6 +76,7 @@ class FieldActionSheetEvent with _$FieldActionSheetEvent {
|
|||||||
const factory FieldActionSheetEvent.updateFieldName(String name) =
|
const factory FieldActionSheetEvent.updateFieldName(String name) =
|
||||||
_UpdateFieldName;
|
_UpdateFieldName;
|
||||||
const factory FieldActionSheetEvent.hideField() = _HideField;
|
const factory FieldActionSheetEvent.hideField() = _HideField;
|
||||||
|
const factory FieldActionSheetEvent.showField() = _ShowField;
|
||||||
const factory FieldActionSheetEvent.duplicateField() = _DuplicateField;
|
const factory FieldActionSheetEvent.duplicateField() = _DuplicateField;
|
||||||
const factory FieldActionSheetEvent.deleteField() = _DeleteField;
|
const factory FieldActionSheetEvent.deleteField() = _DeleteField;
|
||||||
const factory FieldActionSheetEvent.saveField() = _SaveField;
|
const factory FieldActionSheetEvent.saveField() = _SaveField;
|
||||||
|
@ -16,8 +16,7 @@ class _GridFieldNotifier extends ChangeNotifier {
|
|||||||
List<GridFieldContext> _fieldContexts = [];
|
List<GridFieldContext> _fieldContexts = [];
|
||||||
|
|
||||||
set fieldContexts(List<GridFieldContext> fieldContexts) {
|
set fieldContexts(List<GridFieldContext> fieldContexts) {
|
||||||
_fieldContexts =
|
_fieldContexts = fieldContexts;
|
||||||
fieldContexts.where((element) => element.visibility).toList();
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,13 @@ class GridHeaderBloc extends Bloc<GridHeaderEvent, GridHeaderState> {
|
|||||||
_startListening();
|
_startListening();
|
||||||
},
|
},
|
||||||
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
|
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
|
||||||
emit(state.copyWith(fields: value.fields));
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
fields: value.fields
|
||||||
|
.where((element) => element.visibility)
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
moveField: (_MoveField value) async {
|
moveField: (_MoveField value) async {
|
||||||
await _moveField(value, emit);
|
await _moveField(value, emit);
|
||||||
|
@ -158,10 +158,7 @@ void _resolveGridDeps(GetIt getIt) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
getIt.registerFactoryParam<FieldActionSheetBloc, GridFieldCellContext, void>(
|
getIt.registerFactoryParam<FieldActionSheetBloc, GridFieldCellContext, void>(
|
||||||
(data, _) => FieldActionSheetBloc(
|
(data, _) => FieldActionSheetBloc(fieldCellContext: data),
|
||||||
field: data.field,
|
|
||||||
fieldService: FieldService(gridId: data.gridId, fieldId: data.field.id),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
getIt.registerFactoryParam<TextCellBloc, GridCellController, void>(
|
getIt.registerFactoryParam<TextCellBloc, GridCellController, void>(
|
||||||
|
@ -0,0 +1,125 @@
|
|||||||
|
import 'package:app_flowy/plugins/grid/application/field/field_action_sheet_bloc.dart';
|
||||||
|
import 'package:app_flowy/plugins/grid/application/grid_header_bloc.dart';
|
||||||
|
import 'package:bloc_test/bloc_test.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
import 'util.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
late AppFlowyGridTest gridTest;
|
||||||
|
|
||||||
|
setUpAll(() async {
|
||||||
|
gridTest = await AppFlowyGridTest.ensureInitialized();
|
||||||
|
});
|
||||||
|
|
||||||
|
group('GridHeaderBloc', () {
|
||||||
|
late FieldActionSheetBloc actionSheetBloc;
|
||||||
|
setUp(() async {
|
||||||
|
await gridTest.createTestGrid();
|
||||||
|
actionSheetBloc = FieldActionSheetBloc(
|
||||||
|
fieldCellContext: gridTest.singleSelectFieldCellContext(),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
blocTest<GridHeaderBloc, GridHeaderState>(
|
||||||
|
"hides property",
|
||||||
|
build: () {
|
||||||
|
final bloc = GridHeaderBloc(
|
||||||
|
gridId: gridTest.gridView.id,
|
||||||
|
fieldController: gridTest.fieldController,
|
||||||
|
)..add(const GridHeaderEvent.initial());
|
||||||
|
return bloc;
|
||||||
|
},
|
||||||
|
act: (bloc) async {
|
||||||
|
actionSheetBloc.add(const FieldActionSheetEvent.hideField());
|
||||||
|
await Future.delayed(gridResponseDuration());
|
||||||
|
},
|
||||||
|
wait: gridResponseDuration(),
|
||||||
|
verify: (bloc) {
|
||||||
|
assert(bloc.state.fields.length == 2);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
blocTest<GridHeaderBloc, GridHeaderState>(
|
||||||
|
"shows property",
|
||||||
|
build: () {
|
||||||
|
final bloc = GridHeaderBloc(
|
||||||
|
gridId: gridTest.gridView.id,
|
||||||
|
fieldController: gridTest.fieldController,
|
||||||
|
)..add(const GridHeaderEvent.initial());
|
||||||
|
return bloc;
|
||||||
|
},
|
||||||
|
act: (bloc) async {
|
||||||
|
actionSheetBloc.add(const FieldActionSheetEvent.hideField());
|
||||||
|
await Future.delayed(gridResponseDuration());
|
||||||
|
actionSheetBloc.add(const FieldActionSheetEvent.showField());
|
||||||
|
await Future.delayed(gridResponseDuration());
|
||||||
|
},
|
||||||
|
wait: gridResponseDuration(),
|
||||||
|
verify: (bloc) {
|
||||||
|
assert(bloc.state.fields.length == 3);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
blocTest<GridHeaderBloc, GridHeaderState>(
|
||||||
|
"duplicate property",
|
||||||
|
build: () {
|
||||||
|
final bloc = GridHeaderBloc(
|
||||||
|
gridId: gridTest.gridView.id,
|
||||||
|
fieldController: gridTest.fieldController,
|
||||||
|
)..add(const GridHeaderEvent.initial());
|
||||||
|
return bloc;
|
||||||
|
},
|
||||||
|
act: (bloc) async {
|
||||||
|
actionSheetBloc.add(const FieldActionSheetEvent.duplicateField());
|
||||||
|
await Future.delayed(gridResponseDuration());
|
||||||
|
},
|
||||||
|
wait: gridResponseDuration(),
|
||||||
|
verify: (bloc) {
|
||||||
|
assert(bloc.state.fields.length == 4);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
blocTest<GridHeaderBloc, GridHeaderState>(
|
||||||
|
"delete property",
|
||||||
|
build: () {
|
||||||
|
final bloc = GridHeaderBloc(
|
||||||
|
gridId: gridTest.gridView.id,
|
||||||
|
fieldController: gridTest.fieldController,
|
||||||
|
)..add(const GridHeaderEvent.initial());
|
||||||
|
return bloc;
|
||||||
|
},
|
||||||
|
act: (bloc) async {
|
||||||
|
actionSheetBloc.add(const FieldActionSheetEvent.deleteField());
|
||||||
|
await Future.delayed(gridResponseDuration());
|
||||||
|
},
|
||||||
|
wait: gridResponseDuration(),
|
||||||
|
verify: (bloc) {
|
||||||
|
assert(bloc.state.fields.length == 2);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
blocTest<GridHeaderBloc, GridHeaderState>(
|
||||||
|
"update name",
|
||||||
|
build: () {
|
||||||
|
final bloc = GridHeaderBloc(
|
||||||
|
gridId: gridTest.gridView.id,
|
||||||
|
fieldController: gridTest.fieldController,
|
||||||
|
)..add(const GridHeaderEvent.initial());
|
||||||
|
return bloc;
|
||||||
|
},
|
||||||
|
act: (bloc) async {
|
||||||
|
actionSheetBloc
|
||||||
|
.add(const FieldActionSheetEvent.updateFieldName("Hello world"));
|
||||||
|
await Future.delayed(gridResponseDuration());
|
||||||
|
},
|
||||||
|
wait: gridResponseDuration(),
|
||||||
|
verify: (bloc) {
|
||||||
|
final field = bloc.state.fields.firstWhere(
|
||||||
|
(element) => element.id == actionSheetBloc.fieldService.fieldId);
|
||||||
|
|
||||||
|
assert(field.name == "Hello world");
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
@ -1,4 +1,8 @@
|
|||||||
|
import 'dart:collection';
|
||||||
|
import 'package:app_flowy/plugins/grid/application/block/block_cache.dart';
|
||||||
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
|
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
|
||||||
|
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
|
||||||
|
import 'package:app_flowy/plugins/grid/application/field/field_service.dart';
|
||||||
import 'package:app_flowy/plugins/grid/application/grid_data_controller.dart';
|
import 'package:app_flowy/plugins/grid/application/grid_data_controller.dart';
|
||||||
import 'package:app_flowy/plugins/grid/application/row/row_bloc.dart';
|
import 'package:app_flowy/plugins/grid/application/row/row_bloc.dart';
|
||||||
import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
|
import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
|
||||||
@ -12,9 +16,10 @@ import '../../util.dart';
|
|||||||
|
|
||||||
/// Create a empty Grid for test
|
/// Create a empty Grid for test
|
||||||
class AppFlowyGridTest {
|
class AppFlowyGridTest {
|
||||||
// ignore: unused_field
|
|
||||||
final AppFlowyUnitTest _inner;
|
final AppFlowyUnitTest _inner;
|
||||||
late ViewPB gridView;
|
late ViewPB gridView;
|
||||||
|
late GridDataController _dataController;
|
||||||
|
|
||||||
AppFlowyGridTest(AppFlowyUnitTest unitTest) : _inner = unitTest;
|
AppFlowyGridTest(AppFlowyUnitTest unitTest) : _inner = unitTest;
|
||||||
|
|
||||||
static Future<AppFlowyGridTest> ensureInitialized() async {
|
static Future<AppFlowyGridTest> ensureInitialized() async {
|
||||||
@ -22,6 +27,31 @@ class AppFlowyGridTest {
|
|||||||
return AppFlowyGridTest(inner);
|
return AppFlowyGridTest(inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<RowInfo> get rowInfos => _dataController.rowInfos;
|
||||||
|
|
||||||
|
UnmodifiableMapView<String, GridBlockCache> get blocks =>
|
||||||
|
_dataController.blocks;
|
||||||
|
|
||||||
|
List<GridFieldContext> get fieldContexts =>
|
||||||
|
_dataController.fieldController.fieldContexts;
|
||||||
|
|
||||||
|
GridFieldController get fieldController => _dataController.fieldController;
|
||||||
|
|
||||||
|
Future<void> createRow() async {
|
||||||
|
await _dataController.createRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
GridFieldContext singleSelectFieldContext() {
|
||||||
|
final fieldContext = fieldContexts
|
||||||
|
.firstWhere((element) => element.fieldType == FieldType.SingleSelect);
|
||||||
|
return fieldContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
GridFieldCellContext singleSelectFieldCellContext() {
|
||||||
|
final field = singleSelectFieldContext().field;
|
||||||
|
return GridFieldCellContext(gridId: gridView.id, field: field);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> createTestGrid() async {
|
Future<void> createTestGrid() async {
|
||||||
final app = await _inner.createTestApp();
|
final app = await _inner.createTestApp();
|
||||||
final builder = GridPluginBuilder();
|
final builder = GridPluginBuilder();
|
||||||
@ -32,13 +62,63 @@ class AppFlowyGridTest {
|
|||||||
pluginType: builder.pluginType,
|
pluginType: builder.pluginType,
|
||||||
layoutType: builder.layoutType!,
|
layoutType: builder.layoutType!,
|
||||||
);
|
);
|
||||||
result.fold(
|
await result.fold(
|
||||||
(view) => gridView = view,
|
(view) async {
|
||||||
|
gridView = view;
|
||||||
|
_dataController = GridDataController(view: view);
|
||||||
|
final result = await _dataController.loadData();
|
||||||
|
result.fold((l) => null, (r) => throw Exception(r));
|
||||||
|
},
|
||||||
(error) {},
|
(error) {},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a new Grid for cell test
|
||||||
|
class AppFlowyGridCellTest {
|
||||||
|
final AppFlowyGridTest _gridTest;
|
||||||
|
AppFlowyGridCellTest(AppFlowyGridTest gridTest) : _gridTest = gridTest;
|
||||||
|
|
||||||
|
static Future<AppFlowyGridCellTest> ensureInitialized() async {
|
||||||
|
final gridTest = await AppFlowyGridTest.ensureInitialized();
|
||||||
|
return AppFlowyGridCellTest(gridTest);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> createTestRow() async {
|
||||||
|
await _gridTest.createRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> createTestGrid() async {
|
||||||
|
await _gridTest.createTestGrid();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<GridCellControllerBuilder> cellControllerBuilder(
|
||||||
|
String fieldId,
|
||||||
|
) async {
|
||||||
|
final RowInfo rowInfo = _gridTest.rowInfos.last;
|
||||||
|
final blockCache = _gridTest.blocks[rowInfo.rowPB.blockId];
|
||||||
|
final rowCache = blockCache?.rowCache;
|
||||||
|
|
||||||
|
final rowDataController = GridRowDataController(
|
||||||
|
rowInfo: rowInfo,
|
||||||
|
fieldController: _gridTest._dataController.fieldController,
|
||||||
|
rowCache: rowCache!,
|
||||||
|
);
|
||||||
|
|
||||||
|
final rowBloc = RowBloc(
|
||||||
|
rowInfo: rowInfo,
|
||||||
|
dataController: rowDataController,
|
||||||
|
)..add(const RowEvent.initial());
|
||||||
|
await gridResponseFuture();
|
||||||
|
|
||||||
|
return GridCellControllerBuilder(
|
||||||
|
cellId: rowBloc.state.gridCellMap[fieldId]!,
|
||||||
|
cellCache: rowCache.cellCache,
|
||||||
|
delegate: rowDataController,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class AppFlowyGridSelectOptionCellTest {
|
class AppFlowyGridSelectOptionCellTest {
|
||||||
final AppFlowyGridCellTest _gridCellTest;
|
final AppFlowyGridCellTest _gridCellTest;
|
||||||
|
|
||||||
@ -63,8 +143,7 @@ class AppFlowyGridSelectOptionCellTest {
|
|||||||
assert(fieldType == FieldType.SingleSelect ||
|
assert(fieldType == FieldType.SingleSelect ||
|
||||||
fieldType == FieldType.MultiSelect);
|
fieldType == FieldType.MultiSelect);
|
||||||
|
|
||||||
final fieldContexts =
|
final fieldContexts = _gridCellTest._gridTest.fieldContexts;
|
||||||
_gridCellTest._dataController.fieldController.fieldContexts;
|
|
||||||
final field =
|
final field =
|
||||||
fieldContexts.firstWhere((element) => element.fieldType == fieldType);
|
fieldContexts.firstWhere((element) => element.fieldType == fieldType);
|
||||||
final builder = await _gridCellTest.cellControllerBuilder(field.id);
|
final builder = await _gridCellTest.cellControllerBuilder(field.id);
|
||||||
@ -73,55 +152,6 @@ class AppFlowyGridSelectOptionCellTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new Grid for cell test
|
|
||||||
class AppFlowyGridCellTest {
|
|
||||||
final AppFlowyGridTest _gridTest;
|
|
||||||
late GridDataController _dataController;
|
|
||||||
AppFlowyGridCellTest(AppFlowyGridTest gridTest) : _gridTest = gridTest;
|
|
||||||
|
|
||||||
static Future<AppFlowyGridCellTest> ensureInitialized() async {
|
|
||||||
final gridTest = await AppFlowyGridTest.ensureInitialized();
|
|
||||||
return AppFlowyGridCellTest(gridTest);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> createTestRow() async {
|
|
||||||
await _dataController.createRow();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> createTestGrid() async {
|
|
||||||
await _gridTest.createTestGrid();
|
|
||||||
_dataController = GridDataController(view: _gridTest.gridView);
|
|
||||||
final result = await _dataController.loadData();
|
|
||||||
result.fold((l) => null, (r) => throw Exception(r));
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<GridCellControllerBuilder> cellControllerBuilder(
|
|
||||||
String fieldId,
|
|
||||||
) async {
|
|
||||||
final RowInfo rowInfo = _dataController.rowInfos.last;
|
|
||||||
final blockCache = _dataController.blocks[rowInfo.rowPB.blockId];
|
|
||||||
final rowCache = blockCache?.rowCache;
|
|
||||||
|
|
||||||
final rowDataController = GridRowDataController(
|
|
||||||
rowInfo: rowInfo,
|
|
||||||
fieldController: _dataController.fieldController,
|
|
||||||
rowCache: rowCache!,
|
|
||||||
);
|
|
||||||
|
|
||||||
final rowBloc = RowBloc(
|
|
||||||
rowInfo: rowInfo,
|
|
||||||
dataController: rowDataController,
|
|
||||||
)..add(const RowEvent.initial());
|
|
||||||
await gridResponseFuture();
|
|
||||||
|
|
||||||
return GridCellControllerBuilder(
|
|
||||||
cellId: rowBloc.state.gridCellMap[fieldId]!,
|
|
||||||
cellCache: rowCache.cellCache,
|
|
||||||
delegate: rowDataController,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> gridResponseFuture() {
|
Future<void> gridResponseFuture() {
|
||||||
return Future.delayed(gridResponseDuration(milliseconds: 200));
|
return Future.delayed(gridResponseDuration(milliseconds: 200));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user