From 6a8c15899c4e029591a9b8a457e014c791e644db Mon Sep 17 00:00:00 2001 From: "Nathan.fooo" <86001920+appflowy@users.noreply.github.com> Date: Sun, 16 Oct 2022 16:51:21 +0800 Subject: [PATCH] chore: add grid bloc test (#1289) Co-authored-by: nathan --- .../app_flowy/lib/plugins/board/board.dart | 2 +- .../plugins/grid/application/grid_bloc.dart | 29 ++++- .../application/grid_data_controller.dart | 1 + frontend/app_flowy/lib/plugins/grid/grid.dart | 2 +- .../app_flowy/lib/startup/deps_resolver.dart | 6 +- .../app_flowy/lib/startup/plugin/plugin.dart | 2 +- .../workspace/application/app/app_bloc.dart | 54 +++++---- .../application/app/app_service.dart | 13 ++- .../workspace/application/view/view_bloc.dart | 10 +- .../workspace/workspace_service.dart | 4 +- .../home/menu/app/header/header.dart | 13 +-- .../presentation/home/menu/app/menu_app.dart | 1 - .../bloc_test/grid_test/grid_bloc_test.dart | 44 ++++++++ .../test/bloc_test/grid_test/util.dart | 44 ++++++++ .../bloc_test/menu_test/app_bloc_test.dart | 104 ++++++++++++++++++ .../test/bloc_test/workspace_bloc_test.dart | 29 ----- frontend/app_flowy/test/util.dart | 90 +++++++++++---- frontend/rust-lib/flowy-grid/src/manager.rs | 3 +- 18 files changed, 348 insertions(+), 103 deletions(-) create mode 100644 frontend/app_flowy/test/bloc_test/grid_test/grid_bloc_test.dart create mode 100644 frontend/app_flowy/test/bloc_test/grid_test/util.dart create mode 100644 frontend/app_flowy/test/bloc_test/menu_test/app_bloc_test.dart delete mode 100644 frontend/app_flowy/test/bloc_test/workspace_bloc_test.dart diff --git a/frontend/app_flowy/lib/plugins/board/board.dart b/frontend/app_flowy/lib/plugins/board/board.dart index a53739f00a..e22677b9eb 100644 --- a/frontend/app_flowy/lib/plugins/board/board.dart +++ b/frontend/app_flowy/lib/plugins/board/board.dart @@ -27,7 +27,7 @@ class BoardPluginBuilder implements PluginBuilder { ViewDataTypePB get dataType => ViewDataTypePB.Database; @override - ViewLayoutTypePB? get subDataType => ViewLayoutTypePB.Board; + ViewLayoutTypePB? get layoutType => ViewLayoutTypePB.Board; } class BoardPluginConfig implements PluginConfig { diff --git a/frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart index 0d679c831f..597e686b69 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart @@ -12,10 +12,12 @@ import 'grid_data_controller.dart'; import 'row/row_cache.dart'; import 'dart:collection'; +import 'row/row_service.dart'; part 'grid_bloc.freezed.dart'; class GridBloc extends Bloc { final GridDataController dataController; + void Function()? _createRowOperation; GridBloc({required ViewPB view}) : dataController = GridDataController(view: view), @@ -28,7 +30,19 @@ class GridBloc extends Bloc { await _loadGrid(emit); }, createRow: () { - dataController.createRow(); + state.loadingState.when( + loading: () { + _createRowOperation = () => dataController.createRow(); + }, + finish: (_) => dataController.createRow(), + ); + }, + deleteRow: (rowInfo) async { + final rowService = RowFFIService( + blockId: rowInfo.rowPB.blockId, + gridId: rowInfo.gridId, + ); + await rowService.deleteRow(rowInfo.rowPB.id); }, didReceiveGridUpdate: (grid) { emit(state.copyWith(grid: Some(grid))); @@ -84,9 +98,15 @@ class GridBloc extends Bloc { Future _loadGrid(Emitter emit) async { final result = await dataController.loadData(); result.fold( - (grid) => emit( - state.copyWith(loadingState: GridLoadingState.finish(left(unit))), - ), + (grid) { + if (_createRowOperation != null) { + _createRowOperation?.call(); + _createRowOperation = null; + } + emit( + state.copyWith(loadingState: GridLoadingState.finish(left(unit))), + ); + }, (err) => emit( state.copyWith(loadingState: GridLoadingState.finish(right(err))), ), @@ -98,6 +118,7 @@ class GridBloc extends Bloc { class GridEvent with _$GridEvent { const factory GridEvent.initial() = InitialGrid; const factory GridEvent.createRow() = _CreateRow; + const factory GridEvent.deleteRow(RowInfo rowInfo) = _DeleteRow; const factory GridEvent.didReceiveRowUpdate( List rows, RowsChangedReason listState, diff --git a/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart b/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart index a8e1a27c39..aafaeb3774 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart @@ -64,6 +64,7 @@ class GridDataController { }); } + // Loads the rows from each block Future> loadData() async { final result = await _gridFFIService.loadGrid(); return Future( diff --git a/frontend/app_flowy/lib/plugins/grid/grid.dart b/frontend/app_flowy/lib/plugins/grid/grid.dart index 5d7f4b3bdb..91f6ca5063 100644 --- a/frontend/app_flowy/lib/plugins/grid/grid.dart +++ b/frontend/app_flowy/lib/plugins/grid/grid.dart @@ -29,7 +29,7 @@ class GridPluginBuilder implements PluginBuilder { ViewDataTypePB get dataType => ViewDataTypePB.Database; @override - ViewLayoutTypePB? get subDataType => ViewLayoutTypePB.Grid; + ViewLayoutTypePB? get layoutType => ViewLayoutTypePB.Grid; } class GridPluginConfig implements PluginConfig { diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index 7a53237dac..bd33115cde 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -118,11 +118,7 @@ void _resolveFolderDeps(GetIt getIt) { // AppPB getIt.registerFactoryParam( - (app, _) => AppBloc( - app: app, - appService: AppService(), - appListener: AppListener(appId: app.id), - ), + (app, _) => AppBloc(app: app), ); // trash diff --git a/frontend/app_flowy/lib/startup/plugin/plugin.dart b/frontend/app_flowy/lib/startup/plugin/plugin.dart index a8f58562fb..8e7f88768f 100644 --- a/frontend/app_flowy/lib/startup/plugin/plugin.dart +++ b/frontend/app_flowy/lib/startup/plugin/plugin.dart @@ -51,7 +51,7 @@ abstract class PluginBuilder { ViewDataTypePB get dataType => ViewDataTypePB.Text; - ViewLayoutTypePB? get subDataType => ViewLayoutTypePB.Document; + ViewLayoutTypePB? get layoutType => ViewLayoutTypePB.Document; } abstract class PluginConfig { diff --git a/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart b/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart index 61db9a0cdf..fa2a9555bc 100644 --- a/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart @@ -22,19 +22,24 @@ class AppBloc extends Bloc { final AppService appService; final AppListener appListener; - AppBloc( - {required this.app, required this.appService, required this.appListener}) - : super(AppState.initial(app)) { + AppBloc({required this.app}) + : appService = AppService(), + appListener = AppListener(appId: app.id), + super(AppState.initial(app)) { on((event, emit) async { await event.map(initial: (e) async { _startListening(); await _loadViews(emit); }, createView: (CreateView value) async { await _createView(value, emit); + }, loadViews: (_) async { + await _loadViews(emit); }, didReceiveViewUpdated: (e) async { await _didReceiveViewUpdated(e.views, emit); }, delete: (e) async { - await _deleteView(emit); + await _deleteApp(emit); + }, deleteView: (deletedView) async { + await _deleteView(emit, deletedView.viewId); }, rename: (e) async { await _renameView(e, emit); }, appDidUpdate: (e) async { @@ -71,7 +76,8 @@ class AppBloc extends Bloc { ); } - Future _deleteView(Emitter emit) async { +// Delete the current app + Future _deleteApp(Emitter emit) async { final result = await appService.delete(appId: app.id); result.fold( (unit) => emit(state.copyWith(successOrFailure: left(unit))), @@ -79,16 +85,24 @@ class AppBloc extends Bloc { ); } + Future _deleteView(Emitter emit, String viewId) async { + final result = await appService.deleteView(viewId: viewId); + result.fold( + (unit) => emit(state.copyWith(successOrFailure: left(unit))), + (error) => emit(state.copyWith(successOrFailure: right(error))), + ); + } + Future _createView(CreateView value, Emitter emit) async { - final viewOrFailed = await appService.createView( + final result = await appService.createView( appId: app.id, name: value.name, - desc: value.desc, - dataType: value.dataType, - pluginType: value.pluginType, - layout: value.layout, + desc: value.desc ?? "", + dataType: value.pluginBuilder.dataType, + pluginType: value.pluginBuilder.pluginType, + layoutType: value.pluginBuilder.layoutType!, ); - viewOrFailed.fold( + result.fold( (view) => emit(state.copyWith( latestCreatedView: view, successOrFailure: left(unit), @@ -107,7 +121,9 @@ class AppBloc extends Bloc { } Future _didReceiveViewUpdated( - List views, Emitter emit) async { + List views, + Emitter emit, + ) async { final latestCreatedView = state.latestCreatedView; AppState newState = state.copyWith(views: views); if (latestCreatedView != null) { @@ -138,12 +154,12 @@ class AppEvent with _$AppEvent { const factory AppEvent.initial() = Initial; const factory AppEvent.createView( String name, - String desc, - ViewDataTypePB dataType, - ViewLayoutTypePB layout, - PluginType pluginType, - ) = CreateView; - const factory AppEvent.delete() = Delete; + PluginBuilder pluginBuilder, { + String? desc, + }) = CreateView; + const factory AppEvent.loadViews() = LoadApp; + const factory AppEvent.delete() = DeleteApp; + const factory AppEvent.deleteView(String viewId) = DeleteView; const factory AppEvent.rename(String newName) = Rename; const factory AppEvent.didReceiveViewUpdated(List views) = ReceiveViews; @@ -161,7 +177,7 @@ class AppState with _$AppState { factory AppState.initial(AppPB app) => AppState( app: app, - views: [], + views: app.belongings.items, successOrFailure: left(unit), ); } diff --git a/frontend/app_flowy/lib/workspace/application/app/app_service.dart b/frontend/app_flowy/lib/workspace/application/app/app_service.dart index 9f64a68326..ab35c3338d 100644 --- a/frontend/app_flowy/lib/workspace/application/app/app_service.dart +++ b/frontend/app_flowy/lib/workspace/application/app/app_service.dart @@ -18,17 +18,17 @@ class AppService { Future> createView({ required String appId, required String name, - required String desc, + String? desc, required ViewDataTypePB dataType, required PluginType pluginType, - required ViewLayoutTypePB layout, + required ViewLayoutTypePB layoutType, }) { var payload = CreateViewPayloadPB.create() ..belongToId = appId ..name = name - ..desc = desc + ..desc = desc ?? "" ..dataType = dataType - ..layout = layout; + ..layout = layoutType; return FolderEventCreateView(payload).send(); } @@ -49,6 +49,11 @@ class AppService { return FolderEventDeleteApp(request).send(); } + Future> deleteView({required String viewId}) { + final request = RepeatedViewIdPB.create()..items.add(viewId); + return FolderEventDeleteView(request).send(); + } + Future> updateApp( {required String appId, String? name}) { UpdateAppPayloadPB payload = UpdateAppPayloadPB.create()..appId = appId; diff --git a/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart b/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart index bf3cfee6e3..e343b6f9fe 100644 --- a/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart @@ -31,12 +31,14 @@ class ViewBloc extends Bloc { }, viewDidUpdate: (e) { e.result.fold( - (view) => emit(state.copyWith(view: view, successOrFailure: left(unit))), + (view) => + emit(state.copyWith(view: view, successOrFailure: left(unit))), (error) => emit(state.copyWith(successOrFailure: right(error))), ); }, rename: (e) async { - final result = await service.updateView(viewId: view.id, name: e.newName); + final result = + await service.updateView(viewId: view.id, name: e.newName); emit( result.fold( (l) => state.copyWith(successOrFailure: left(unit)), @@ -46,7 +48,6 @@ class ViewBloc extends Bloc { }, delete: (e) async { final result = await service.delete(viewId: view.id); - await service.updateView(viewId: view.id); emit( result.fold( (l) => state.copyWith(successOrFailure: left(unit)), @@ -81,7 +82,8 @@ class ViewEvent with _$ViewEvent { const factory ViewEvent.rename(String newName) = Rename; const factory ViewEvent.delete() = Delete; const factory ViewEvent.duplicate() = Duplicate; - const factory ViewEvent.viewDidUpdate(Either result) = ViewDidUpdate; + const factory ViewEvent.viewDidUpdate(Either result) = + ViewDidUpdate; } @freezed diff --git a/frontend/app_flowy/lib/workspace/application/workspace/workspace_service.dart b/frontend/app_flowy/lib/workspace/application/workspace/workspace_service.dart index 295b7c3af7..c6b7d4cba3 100644 --- a/frontend/app_flowy/lib/workspace/application/workspace/workspace_service.dart +++ b/frontend/app_flowy/lib/workspace/application/workspace/workspace_service.dart @@ -17,11 +17,11 @@ class WorkspaceService { required this.workspaceId, }); Future> createApp( - {required String name, required String desc}) { + {required String name, String? desc}) { final payload = CreateAppPayloadPB.create() ..name = name ..workspaceId = workspaceId - ..desc = desc; + ..desc = desc ?? ""; return FolderEventCreateApp(payload).send(); } diff --git a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart index afaecdbd45..d887b3417e 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart @@ -104,13 +104,12 @@ class MenuAppHeader extends StatelessWidget { message: LocaleKeys.menuAppHeader_addPageTooltip.tr(), child: AddButton( onSelected: (pluginBuilder) { - context.read().add(AppEvent.createView( - LocaleKeys.menuAppHeader_defaultNewPageName.tr(), - "", - pluginBuilder.dataType, - pluginBuilder.subDataType!, - pluginBuilder.pluginType, - )); + context.read().add( + AppEvent.createView( + LocaleKeys.menuAppHeader_defaultNewPageName.tr(), + pluginBuilder, + ), + ); }, ).padding(right: MenuAppSizes.headerPadding), ); diff --git a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/menu_app.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/menu_app.dart index c7ee59d03e..b4a2e3532c 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/menu_app.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/menu_app.dart @@ -50,7 +50,6 @@ class _MenuAppState extends State { }, ), BlocListener( - listenWhen: (p, c) => p.views != c.views, listener: (context, state) => viewDataContext.views = state.views, ), ], diff --git a/frontend/app_flowy/test/bloc_test/grid_test/grid_bloc_test.dart b/frontend/app_flowy/test/bloc_test/grid_test/grid_bloc_test.dart new file mode 100644 index 0000000000..de7ba7ee9c --- /dev/null +++ b/frontend/app_flowy/test/bloc_test/grid_test/grid_bloc_test.dart @@ -0,0 +1,44 @@ +import 'package:app_flowy/plugins/grid/application/grid_bloc.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:bloc_test/bloc_test.dart'; +import 'util.dart'; + +void main() { + late AppFlowyGridTest gridTest; + setUpAll(() async { + gridTest = await AppFlowyGridTest.ensureInitialized(); + }); + + group('GridBloc', () { + blocTest( + "Create row", + build: () => + GridBloc(view: gridTest.gridView)..add(const GridEvent.initial()), + act: (bloc) => bloc.add(const GridEvent.createRow()), + wait: const Duration(milliseconds: 300), + verify: (bloc) { + assert(bloc.state.rowInfos.length == 4); + }, + ); + }); + + group('GridBloc', () { + late GridBloc gridBloc; + setUpAll(() async { + gridBloc = GridBloc(view: gridTest.gridView) + ..add(const GridEvent.initial()); + await gridBlocResponseFuture(); + }); + + // The initial number of rows is three + test('', () async { + assert(gridBloc.state.rowInfos.length == 3); + }); + + test('delete row', () async { + gridBloc.add(GridEvent.deleteRow(gridBloc.state.rowInfos.last)); + await gridBlocResponseFuture(); + assert(gridBloc.state.rowInfos.length == 2); + }); + }); +} diff --git a/frontend/app_flowy/test/bloc_test/grid_test/util.dart b/frontend/app_flowy/test/bloc_test/grid_test/util.dart new file mode 100644 index 0000000000..339fb1c12a --- /dev/null +++ b/frontend/app_flowy/test/bloc_test/grid_test/util.dart @@ -0,0 +1,44 @@ +import 'package:app_flowy/plugins/grid/grid.dart'; +import 'package:app_flowy/workspace/application/app/app_service.dart'; +import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart'; + +import '../../util.dart'; + +/// Create a empty Grid for test +class AppFlowyGridTest { + // ignore: unused_field + final AppFlowyUnitTest _inner; + late ViewPB gridView; + AppFlowyGridTest(AppFlowyUnitTest unitTest) : _inner = unitTest; + + static Future ensureInitialized() async { + final inner = await AppFlowyUnitTest.ensureInitialized(); + final test = AppFlowyGridTest(inner); + await test._createTestGrid(); + return test; + } + + Future _createTestGrid() async { + final app = await _inner.createTestApp(); + final builder = GridPluginBuilder(); + final result = await AppService().createView( + appId: app.id, + name: "Test Grid", + dataType: builder.dataType, + pluginType: builder.pluginType, + layoutType: builder.layoutType!, + ); + result.fold( + (view) => gridView = view, + (error) {}, + ); + } +} + +Future gridBlocResponseFuture({int millseconds = 100}) { + return Future.delayed(gridBlocResponseDuration(millseconds: millseconds)); +} + +Duration gridBlocResponseDuration({int millseconds = 100}) { + return Duration(milliseconds: millseconds); +} diff --git a/frontend/app_flowy/test/bloc_test/menu_test/app_bloc_test.dart b/frontend/app_flowy/test/bloc_test/menu_test/app_bloc_test.dart new file mode 100644 index 0000000000..e7c0477636 --- /dev/null +++ b/frontend/app_flowy/test/bloc_test/menu_test/app_bloc_test.dart @@ -0,0 +1,104 @@ +import 'package:app_flowy/plugins/board/board.dart'; +import 'package:app_flowy/plugins/doc/document.dart'; +import 'package:app_flowy/plugins/grid/grid.dart'; +import 'package:app_flowy/workspace/application/app/app_bloc.dart'; +import 'package:flowy_sdk/protobuf/flowy-folder/app.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:bloc_test/bloc_test.dart'; +import '../../util.dart'; + +void main() { + late AppFlowyUnitTest test; + setUpAll(() async { + test = await AppFlowyUnitTest.ensureInitialized(); + }); + + group( + 'AppBloc', + () { + late AppPB app; + setUp(() async { + app = await test.createTestApp(); + }); + + blocTest( + "Create a document", + build: () => AppBloc(app: app)..add(const AppEvent.initial()), + act: (bloc) { + bloc.add( + AppEvent.createView("Test document", DocumentPluginBuilder())); + }, + wait: blocResponseDuration(), + verify: (bloc) { + assert(bloc.state.views.length == 1); + assert(bloc.state.views.last.name == "Test document"); + assert(bloc.state.views.last.layout == ViewLayoutTypePB.Document); + }, + ); + + blocTest( + "Create a grid", + build: () => AppBloc(app: app)..add(const AppEvent.initial()), + act: (bloc) { + bloc.add(AppEvent.createView("Test grid", GridPluginBuilder())); + }, + wait: blocResponseDuration(), + verify: (bloc) { + assert(bloc.state.views.length == 1); + assert(bloc.state.views.last.name == "Test grid"); + assert(bloc.state.views.last.layout == ViewLayoutTypePB.Grid); + }, + ); + + blocTest( + "Create a Kanban board", + build: () => AppBloc(app: app)..add(const AppEvent.initial()), + act: (bloc) { + bloc.add(AppEvent.createView("Test board", BoardPluginBuilder())); + }, + wait: const Duration(milliseconds: 100), + verify: (bloc) { + assert(bloc.state.views.length == 1); + assert(bloc.state.views.last.name == "Test board"); + assert(bloc.state.views.last.layout == ViewLayoutTypePB.Board); + }, + ); + }, + ); + + group('AppBloc', () { + late ViewPB view; + late AppPB app; + setUpAll(() async { + app = await test.createTestApp(); + }); + + blocTest( + "create a document", + build: () => AppBloc(app: app)..add(const AppEvent.initial()), + act: (bloc) { + bloc.add(AppEvent.createView("Test document", DocumentPluginBuilder())); + }, + wait: blocResponseDuration(), + verify: (bloc) { + assert(bloc.state.views.length == 1); + view = bloc.state.views.last; + }, + ); + blocTest( + "delete the document", + build: () => AppBloc(app: app)..add(const AppEvent.initial()), + act: (bloc) => bloc.add(AppEvent.deleteView(view.id)), + ); + blocTest( + "verify the document is exist", + build: () => AppBloc(app: app)..add(const AppEvent.initial()), + act: (bloc) => bloc.add(const AppEvent.loadViews()), + wait: blocResponseDuration(), + verify: (bloc) { + assert(bloc.state.views.isEmpty); + }, + ); + }); +} diff --git a/frontend/app_flowy/test/bloc_test/workspace_bloc_test.dart b/frontend/app_flowy/test/bloc_test/workspace_bloc_test.dart deleted file mode 100644 index 100611b73b..0000000000 --- a/frontend/app_flowy/test/bloc_test/workspace_bloc_test.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/workspace/application/workspace/welcome_bloc.dart'; -import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:bloc_test/bloc_test.dart'; - -import '../util.dart'; - -void main() { - UserProfilePB? userInfo; - setUpAll(() async { - await AppFlowyBlocTest.ensureInitialized(); - userInfo = await signIn(); - }); - - group('WelcomeBloc', () { - blocTest( - "welcome screen init", - build: () => getIt(param1: userInfo), - act: (bloc) { - bloc.add(const WelcomeEvent.initial()); - }, - wait: const Duration(seconds: 3), - verify: (bloc) { - assert(bloc.state.isLoading == false); - }, - ); - }); -} diff --git a/frontend/app_flowy/test/util.dart b/frontend/app_flowy/test/util.dart index b65469a9ab..b8367f90fe 100644 --- a/frontend/app_flowy/test/util.dart +++ b/frontend/app_flowy/test/util.dart @@ -1,7 +1,11 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/user/application/auth_service.dart'; +import 'package:app_flowy/user/application/user_service.dart'; +import 'package:app_flowy/workspace/application/workspace/workspace_service.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/uuid.dart'; +import 'package:flowy_sdk/protobuf/flowy-folder/app.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-folder/workspace.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -19,19 +23,73 @@ class AppFlowyIntegrateTest { } } -class AppFlowyBlocTest { - static Future ensureInitialized() async { +class AppFlowyUnitTest { + late UserProfilePB userProfile; + late UserService userService; + late WorkspaceService workspaceService; + late List workspaces; + + static Future ensureInitialized() async { TestWidgetsFlutterBinding.ensureInitialized(); SharedPreferences.setMockInitialValues({}); - pathProviderInitialized(); + _pathProviderInitialized(); await EasyLocalization.ensureInitialized(); await FlowyRunner.run(FlowyTestApp()); - return AppFlowyBlocTest(); + + final test = AppFlowyUnitTest(); + await test._signIn(); + await test._loadWorkspace(); + + await test._initialServices(); + return test; + } + + Future _signIn() async { + final authService = getIt(); + const password = "AppFlowy123@"; + final uid = uuid(); + final userEmail = "$uid@appflowy.io"; + final result = await authService.signUp( + name: "TestUser", + password: password, + email: userEmail, + ); + return result.fold( + (user) { + userProfile = user; + userService = UserService(userId: userProfile.id); + }, + (error) {}, + ); + } + + WorkspacePB get currentWorkspace => workspaces[0]; + + Future _loadWorkspace() async { + final result = await userService.getWorkspaces(); + result.fold( + (value) => workspaces = value, + (error) { + throw Exception(error); + }, + ); + } + + Future _initialServices() async { + workspaceService = WorkspaceService(workspaceId: currentWorkspace.id); + } + + Future createTestApp() async { + final result = await workspaceService.createApp(name: "Test App"); + return result.fold( + (app) => app, + (error) => throw Exception(error), + ); } } -void pathProviderInitialized() { +void _pathProviderInitialized() { const MethodChannel channel = MethodChannel('plugins.flutter.io/path_provider'); channel.setMockMethodCallHandler((MethodCall methodCall) async { @@ -39,27 +97,13 @@ void pathProviderInitialized() { }); } -Future signIn() async { - final authService = getIt(); - const password = "AppFlowy123@"; - final uid = uuid(); - final userEmail = "$uid@appflowy.io"; - final result = await authService.signUp( - name: "FlowyTestUser", - password: password, - email: userEmail, - ); - return result.fold( - (user) => user, - (error) { - throw StateError("$error"); - }, - ); -} - class FlowyTestApp implements EntryPoint { @override Widget create() { return Container(); } } + +Duration blocResponseDuration({int millseconds = 100}) { + return Duration(milliseconds: millseconds); +} diff --git a/frontend/rust-lib/flowy-grid/src/manager.rs b/frontend/rust-lib/flowy-grid/src/manager.rs index 24811ca889..fcc6c7c9d2 100644 --- a/frontend/rust-lib/flowy-grid/src/manager.rs +++ b/frontend/rust-lib/flowy-grid/src/manager.rs @@ -93,10 +93,9 @@ impl GridManager { Ok(()) } - #[tracing::instrument(level = "debug", skip_all, fields(grid_id), err)] + #[tracing::instrument(level = "debug", skip_all, err)] pub async fn open_grid>(&self, grid_id: T) -> FlowyResult> { let grid_id = grid_id.as_ref(); - tracing::Span::current().record("grid_id", &grid_id); let _ = self.migration.run_v1_migration(grid_id).await; self.get_or_create_grid_editor(grid_id).await }