mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: add reorder bloc test (#1354)
* chore: add reorder bloc test * chore: add trash test Co-authored-by: nathan <nathan@appflowy.io>
This commit is contained in:
parent
6fb677d346
commit
67e4a759c7
@ -10,14 +10,16 @@ import 'package:app_flowy/plugins/trash/application/trash_listener.dart';
|
||||
part 'trash_bloc.freezed.dart';
|
||||
|
||||
class TrashBloc extends Bloc<TrashEvent, TrashState> {
|
||||
final TrashService service;
|
||||
final TrashListener listener;
|
||||
TrashBloc({required this.service, required this.listener})
|
||||
: super(TrashState.init()) {
|
||||
final TrashService _service;
|
||||
final TrashListener _listener;
|
||||
TrashBloc()
|
||||
: _service = TrashService(),
|
||||
_listener = TrashListener(),
|
||||
super(TrashState.init()) {
|
||||
on<TrashEvent>((event, emit) async {
|
||||
await event.map(initial: (e) async {
|
||||
listener.start(trashUpdated: _listenTrashUpdated);
|
||||
final result = await service.readTrash();
|
||||
_listener.start(trashUpdated: _listenTrashUpdated);
|
||||
final result = await _service.readTrash();
|
||||
emit(result.fold(
|
||||
(object) => state.copyWith(
|
||||
objects: object.items, successOrFailure: left(unit)),
|
||||
@ -26,17 +28,17 @@ class TrashBloc extends Bloc<TrashEvent, TrashState> {
|
||||
}, didReceiveTrash: (e) async {
|
||||
emit(state.copyWith(objects: e.trash));
|
||||
}, putback: (e) async {
|
||||
final result = await service.putback(e.trashId);
|
||||
final result = await _service.putback(e.trashId);
|
||||
await _handleResult(result, emit);
|
||||
}, delete: (e) async {
|
||||
final result =
|
||||
await service.deleteViews([Tuple2(e.trash.id, e.trash.ty)]);
|
||||
await _service.deleteViews([Tuple2(e.trash.id, e.trash.ty)]);
|
||||
await _handleResult(result, emit);
|
||||
}, deleteAll: (e) async {
|
||||
final result = await service.deleteAll();
|
||||
final result = await _service.deleteAll();
|
||||
await _handleResult(result, emit);
|
||||
}, restoreAll: (e) async {
|
||||
final result = await service.restoreAll();
|
||||
final result = await _service.restoreAll();
|
||||
await _handleResult(result, emit);
|
||||
});
|
||||
});
|
||||
@ -63,7 +65,7 @@ class TrashBloc extends Bloc<TrashEvent, TrashState> {
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
await listener.close();
|
||||
await _listener.close();
|
||||
return super.close();
|
||||
}
|
||||
}
|
||||
|
@ -92,14 +92,6 @@ void _resolveFolderDeps(GetIt getIt) {
|
||||
),
|
||||
);
|
||||
|
||||
//Menu
|
||||
getIt.registerFactoryParam<MenuBloc, UserProfilePB, String>(
|
||||
(user, workspaceId) => MenuBloc(
|
||||
workspaceId: workspaceId,
|
||||
listener: getIt<WorkspaceListener>(param1: user, param2: workspaceId),
|
||||
),
|
||||
);
|
||||
|
||||
getIt.registerFactoryParam<MenuUserBloc, UserProfilePB, void>(
|
||||
(user, _) => MenuUserBloc(user),
|
||||
);
|
||||
@ -123,10 +115,7 @@ void _resolveFolderDeps(GetIt getIt) {
|
||||
getIt.registerLazySingleton<TrashService>(() => TrashService());
|
||||
getIt.registerLazySingleton<TrashListener>(() => TrashListener());
|
||||
getIt.registerFactory<TrashBloc>(
|
||||
() => TrashBloc(
|
||||
service: getIt<TrashService>(),
|
||||
listener: getIt<TrashListener>(),
|
||||
),
|
||||
() => TrashBloc(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -39,9 +39,9 @@ class FlowyRunner {
|
||||
|
||||
// add task
|
||||
getIt<AppLauncher>().addTask(InitRustSDKTask());
|
||||
getIt<AppLauncher>().addTask(PluginLoadTask());
|
||||
|
||||
if (!env.isTest()) {
|
||||
getIt<AppLauncher>().addTask(PluginLoadTask());
|
||||
getIt<AppLauncher>().addTask(InitAppWidgetTask());
|
||||
getIt<AppLauncher>().addTask(InitPlatformServiceTask());
|
||||
}
|
||||
|
@ -18,11 +18,10 @@ import 'package:dartz/dartz.dart';
|
||||
part 'app_bloc.freezed.dart';
|
||||
|
||||
class AppBloc extends Bloc<AppEvent, AppState> {
|
||||
final AppPB app;
|
||||
final AppService appService;
|
||||
final AppListener appListener;
|
||||
|
||||
AppBloc({required this.app})
|
||||
AppBloc({required AppPB app})
|
||||
: appService = AppService(),
|
||||
appListener = AppListener(appId: app.id),
|
||||
super(AppState.initial(app)) {
|
||||
@ -34,8 +33,6 @@ class AppBloc extends Bloc<AppEvent, AppState> {
|
||||
await _createView(value, emit);
|
||||
}, loadViews: (_) async {
|
||||
await _loadViews(emit);
|
||||
}, didReceiveViewUpdated: (e) async {
|
||||
await _didReceiveViewUpdated(e.views, emit);
|
||||
}, delete: (e) async {
|
||||
await _deleteApp(emit);
|
||||
}, deleteView: (deletedView) async {
|
||||
@ -43,23 +40,26 @@ class AppBloc extends Bloc<AppEvent, AppState> {
|
||||
}, rename: (e) async {
|
||||
await _renameView(e, emit);
|
||||
}, appDidUpdate: (e) async {
|
||||
emit(state.copyWith(app: e.app));
|
||||
final latestCreatedView = state.latestCreatedView;
|
||||
final views = e.app.belongings.items;
|
||||
AppState newState = state.copyWith(
|
||||
views: views,
|
||||
app: e.app,
|
||||
);
|
||||
if (latestCreatedView != null) {
|
||||
final index =
|
||||
views.indexWhere((element) => element.id == latestCreatedView.id);
|
||||
if (index == -1) {
|
||||
newState = newState.copyWith(latestCreatedView: null);
|
||||
}
|
||||
}
|
||||
emit(newState);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void _startListening() {
|
||||
appListener.start(
|
||||
onViewsChanged: (result) {
|
||||
result.fold(
|
||||
(views) {
|
||||
if (!isClosed) {
|
||||
add(AppEvent.didReceiveViewUpdated(views));
|
||||
}
|
||||
},
|
||||
(error) => Log.error(error),
|
||||
);
|
||||
},
|
||||
onAppUpdated: (app) {
|
||||
if (!isClosed) {
|
||||
add(AppEvent.appDidUpdate(app));
|
||||
@ -69,7 +69,8 @@ class AppBloc extends Bloc<AppEvent, AppState> {
|
||||
}
|
||||
|
||||
Future<void> _renameView(Rename e, Emitter<AppState> emit) async {
|
||||
final result = await appService.updateApp(appId: app.id, name: e.newName);
|
||||
final result =
|
||||
await appService.updateApp(appId: state.app.id, name: e.newName);
|
||||
result.fold(
|
||||
(l) => emit(state.copyWith(successOrFailure: left(unit))),
|
||||
(error) => emit(state.copyWith(successOrFailure: right(error))),
|
||||
@ -78,7 +79,7 @@ class AppBloc extends Bloc<AppEvent, AppState> {
|
||||
|
||||
// Delete the current app
|
||||
Future<void> _deleteApp(Emitter<AppState> emit) async {
|
||||
final result = await appService.delete(appId: app.id);
|
||||
final result = await appService.delete(appId: state.app.id);
|
||||
result.fold(
|
||||
(unit) => emit(state.copyWith(successOrFailure: left(unit))),
|
||||
(error) => emit(state.copyWith(successOrFailure: right(error))),
|
||||
@ -95,7 +96,7 @@ class AppBloc extends Bloc<AppEvent, AppState> {
|
||||
|
||||
Future<void> _createView(CreateView value, Emitter<AppState> emit) async {
|
||||
final result = await appService.createView(
|
||||
appId: app.id,
|
||||
appId: state.app.id,
|
||||
name: value.name,
|
||||
desc: value.desc ?? "",
|
||||
dataFormatType: value.pluginBuilder.dataFormatType,
|
||||
@ -120,25 +121,8 @@ class AppBloc extends Bloc<AppEvent, AppState> {
|
||||
return super.close();
|
||||
}
|
||||
|
||||
Future<void> _didReceiveViewUpdated(
|
||||
List<ViewPB> views,
|
||||
Emitter<AppState> emit,
|
||||
) async {
|
||||
final latestCreatedView = state.latestCreatedView;
|
||||
AppState newState = state.copyWith(views: views);
|
||||
if (latestCreatedView != null) {
|
||||
final index =
|
||||
views.indexWhere((element) => element.id == latestCreatedView.id);
|
||||
if (index == -1) {
|
||||
newState = newState.copyWith(latestCreatedView: null);
|
||||
}
|
||||
}
|
||||
|
||||
emit(newState);
|
||||
}
|
||||
|
||||
Future<void> _loadViews(Emitter<AppState> emit) async {
|
||||
final viewsOrFailed = await appService.getViews(appId: app.id);
|
||||
final viewsOrFailed = await appService.getViews(appId: state.app.id);
|
||||
viewsOrFailed.fold(
|
||||
(views) => emit(state.copyWith(views: views)),
|
||||
(error) {
|
||||
@ -161,8 +145,6 @@ class AppEvent with _$AppEvent {
|
||||
const factory AppEvent.delete() = DeleteApp;
|
||||
const factory AppEvent.deleteView(String viewId) = DeleteView;
|
||||
const factory AppEvent.rename(String newName) = Rename;
|
||||
const factory AppEvent.didReceiveViewUpdated(List<ViewPB> views) =
|
||||
ReceiveViews;
|
||||
const factory AppEvent.appDidUpdate(AppPB app) = AppDidUpdate;
|
||||
}
|
||||
|
||||
|
@ -11,11 +11,11 @@ import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart';
|
||||
import 'package:flowy_sdk/rust_stream.dart';
|
||||
|
||||
typedef AppDidUpdateCallback = void Function(AppPB app);
|
||||
typedef ViewsDidChangeCallback = void Function(Either<List<ViewPB>, FlowyError> viewsOrFailed);
|
||||
typedef ViewsDidChangeCallback = void Function(
|
||||
Either<List<ViewPB>, FlowyError> viewsOrFailed);
|
||||
|
||||
class AppListener {
|
||||
StreamSubscription<SubscribeObject>? _subscription;
|
||||
ViewsDidChangeCallback? _viewsChanged;
|
||||
AppDidUpdateCallback? _updated;
|
||||
FolderNotificationParser? _parser;
|
||||
String appId;
|
||||
@ -24,26 +24,16 @@ class AppListener {
|
||||
required this.appId,
|
||||
});
|
||||
|
||||
void start({ViewsDidChangeCallback? onViewsChanged, AppDidUpdateCallback? onAppUpdated}) {
|
||||
_viewsChanged = onViewsChanged;
|
||||
void start({AppDidUpdateCallback? onAppUpdated}) {
|
||||
_updated = onAppUpdated;
|
||||
_parser = FolderNotificationParser(id: appId, callback: _bservableCallback);
|
||||
_subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable));
|
||||
_parser = FolderNotificationParser(id: appId, callback: _handleCallback);
|
||||
_subscription =
|
||||
RustStreamReceiver.listen((observable) => _parser?.parse(observable));
|
||||
}
|
||||
|
||||
void _bservableCallback(FolderNotification ty, Either<Uint8List, FlowyError> result) {
|
||||
void _handleCallback(
|
||||
FolderNotification ty, Either<Uint8List, FlowyError> result) {
|
||||
switch (ty) {
|
||||
case FolderNotification.AppViewsChanged:
|
||||
if (_viewsChanged != null) {
|
||||
result.fold(
|
||||
(payload) {
|
||||
final repeatedView = RepeatedViewPB.fromBuffer(payload);
|
||||
_viewsChanged!(left(repeatedView.items));
|
||||
},
|
||||
(error) => _viewsChanged!(right(error)),
|
||||
);
|
||||
}
|
||||
break;
|
||||
case FolderNotification.AppUpdated:
|
||||
if (_updated != null) {
|
||||
result.fold(
|
||||
@ -63,7 +53,6 @@ class AppListener {
|
||||
Future<void> stop() async {
|
||||
_parser = null;
|
||||
await _subscription?.cancel();
|
||||
_viewsChanged = null;
|
||||
_updated = null;
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_sdk/log.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-folder/app.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-folder/workspace.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
@ -13,16 +15,23 @@ part 'menu_bloc.freezed.dart';
|
||||
|
||||
class MenuBloc extends Bloc<MenuEvent, MenuState> {
|
||||
final WorkspaceService _workspaceService;
|
||||
final WorkspaceListener listener;
|
||||
final String workspaceId;
|
||||
final WorkspaceListener _listener;
|
||||
final UserProfilePB user;
|
||||
final WorkspacePB workspace;
|
||||
|
||||
MenuBloc({required this.workspaceId, required this.listener})
|
||||
: _workspaceService = WorkspaceService(workspaceId: workspaceId),
|
||||
super(MenuState.initial()) {
|
||||
MenuBloc({
|
||||
required this.user,
|
||||
required this.workspace,
|
||||
}) : _workspaceService = WorkspaceService(workspaceId: workspace.id),
|
||||
_listener = WorkspaceListener(
|
||||
user: user,
|
||||
workspaceId: workspace.id,
|
||||
),
|
||||
super(MenuState.initial(workspace)) {
|
||||
on<MenuEvent>((event, emit) async {
|
||||
await event.map(
|
||||
initial: (e) async {
|
||||
listener.start(appsChanged: _handleAppsOrFail);
|
||||
_listener.start(appsChanged: _handleAppsOrFail);
|
||||
await _fetchApps(emit);
|
||||
},
|
||||
openPage: (e) async {
|
||||
@ -55,7 +64,7 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> {
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
await listener.stop();
|
||||
await _listener.stop();
|
||||
return super.close();
|
||||
}
|
||||
|
||||
@ -110,8 +119,8 @@ class MenuState with _$MenuState {
|
||||
required Plugin plugin,
|
||||
}) = _MenuState;
|
||||
|
||||
factory MenuState.initial() => MenuState(
|
||||
apps: [],
|
||||
factory MenuState.initial(WorkspacePB workspace) => MenuState(
|
||||
apps: workspace.apps.items,
|
||||
successOrFailure: left(unit),
|
||||
plugin: makePlugin(pluginType: PluginType.blank),
|
||||
);
|
||||
|
@ -51,8 +51,10 @@ class HomeMenu extends StatelessWidget {
|
||||
providers: [
|
||||
BlocProvider<MenuBloc>(
|
||||
create: (context) {
|
||||
final menuBloc = getIt<MenuBloc>(
|
||||
param1: user, param2: workspaceSetting.workspace.id);
|
||||
final menuBloc = MenuBloc(
|
||||
user: user,
|
||||
workspace: workspaceSetting.workspace,
|
||||
);
|
||||
menuBloc.add(const MenuEvent.initial());
|
||||
return menuBloc;
|
||||
},
|
||||
@ -221,8 +223,7 @@ class MenuTopBar extends StatelessWidget {
|
||||
const Spacer(),
|
||||
Tooltip(
|
||||
richMessage: TextSpan(children: [
|
||||
TextSpan(
|
||||
text: "${LocaleKeys.sideBar_closeSidebar.tr()}\n"),
|
||||
TextSpan(text: "${LocaleKeys.sideBar_closeSidebar.tr()}\n"),
|
||||
TextSpan(
|
||||
text: Platform.isMacOS ? "⌘+\\" : "Ctrl+\\",
|
||||
style: const TextStyle(color: Colors.white60),
|
||||
|
@ -2,6 +2,7 @@ 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:app_flowy/workspace/application/menu/menu_view_section_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';
|
||||
@ -125,4 +126,64 @@ void main() {
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
group('$AppBloc', () {
|
||||
late AppPB app;
|
||||
setUpAll(() async {
|
||||
app = await test.createTestApp();
|
||||
});
|
||||
blocTest<AppBloc, AppState>(
|
||||
"create documents' order test",
|
||||
build: () => AppBloc(app: app)..add(const AppEvent.initial()),
|
||||
act: (bloc) async {
|
||||
bloc.add(AppEvent.createView("1", DocumentPluginBuilder()));
|
||||
await blocResponseFuture();
|
||||
bloc.add(AppEvent.createView("2", DocumentPluginBuilder()));
|
||||
await blocResponseFuture();
|
||||
bloc.add(AppEvent.createView("3", DocumentPluginBuilder()));
|
||||
await blocResponseFuture();
|
||||
},
|
||||
wait: blocResponseDuration(),
|
||||
verify: (bloc) {
|
||||
assert(bloc.state.views[0].name == '1');
|
||||
assert(bloc.state.views[1].name == '2');
|
||||
assert(bloc.state.views[2].name == '3');
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
group('$AppBloc', () {
|
||||
late AppPB app;
|
||||
setUpAll(() async {
|
||||
app = await test.createTestApp();
|
||||
});
|
||||
blocTest<AppBloc, AppState>(
|
||||
"reorder documents",
|
||||
build: () => AppBloc(app: app)..add(const AppEvent.initial()),
|
||||
act: (bloc) async {
|
||||
bloc.add(AppEvent.createView("1", DocumentPluginBuilder()));
|
||||
await blocResponseFuture();
|
||||
bloc.add(AppEvent.createView("2", DocumentPluginBuilder()));
|
||||
await blocResponseFuture();
|
||||
bloc.add(AppEvent.createView("3", DocumentPluginBuilder()));
|
||||
await blocResponseFuture();
|
||||
|
||||
final appViewData = AppViewDataContext(appId: app.id);
|
||||
appViewData.views = bloc.state.views;
|
||||
final viewSectionBloc = ViewSectionBloc(
|
||||
appViewData: appViewData,
|
||||
)..add(const ViewSectionEvent.initial());
|
||||
await blocResponseFuture();
|
||||
|
||||
viewSectionBloc.add(const ViewSectionEvent.moveView(0, 2));
|
||||
await blocResponseFuture();
|
||||
},
|
||||
wait: blocResponseDuration(),
|
||||
verify: (bloc) {
|
||||
assert(bloc.state.views[0].name == '2');
|
||||
assert(bloc.state.views[1].name == '3');
|
||||
assert(bloc.state.views[2].name == '1');
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -0,0 +1,66 @@
|
||||
import 'package:app_flowy/workspace/application/menu/menu_bloc.dart';
|
||||
import 'package:bloc_test/bloc_test.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../util.dart';
|
||||
|
||||
void main() {
|
||||
late AppFlowyUnitTest test;
|
||||
setUpAll(() async {
|
||||
test = await AppFlowyUnitTest.ensureInitialized();
|
||||
});
|
||||
|
||||
group('$MenuBloc', () {
|
||||
late MenuBloc menuBloc;
|
||||
setUp(() async {
|
||||
menuBloc = MenuBloc(
|
||||
user: test.userProfile,
|
||||
workspace: test.currentWorkspace,
|
||||
)..add(const MenuEvent.initial());
|
||||
|
||||
await blocResponseFuture();
|
||||
});
|
||||
blocTest<MenuBloc, MenuState>(
|
||||
"assert initial apps is the build-in app",
|
||||
build: () => menuBloc,
|
||||
wait: blocResponseDuration(),
|
||||
verify: (bloc) {
|
||||
assert(bloc.state.apps.length == 1);
|
||||
},
|
||||
);
|
||||
//
|
||||
blocTest<MenuBloc, MenuState>(
|
||||
"create apps",
|
||||
build: () => menuBloc,
|
||||
act: (bloc) async {
|
||||
bloc.add(const MenuEvent.createApp("App 1"));
|
||||
await blocResponseFuture();
|
||||
bloc.add(const MenuEvent.createApp("App 2"));
|
||||
await blocResponseFuture();
|
||||
bloc.add(const MenuEvent.createApp("App 3"));
|
||||
},
|
||||
wait: blocResponseDuration(),
|
||||
verify: (bloc) {
|
||||
// apps[0] is the build-in app
|
||||
assert(bloc.state.apps[1].name == 'App 1');
|
||||
assert(bloc.state.apps[2].name == 'App 2');
|
||||
assert(bloc.state.apps[3].name == 'App 3');
|
||||
},
|
||||
);
|
||||
blocTest<MenuBloc, MenuState>(
|
||||
"reorder apps",
|
||||
build: () => menuBloc,
|
||||
act: (bloc) async {
|
||||
bloc.add(const MenuEvent.moveApp(1, 3));
|
||||
},
|
||||
wait: blocResponseDuration(),
|
||||
verify: (bloc) {
|
||||
assert(bloc.state.apps[1].name == 'App 2');
|
||||
assert(bloc.state.apps[2].name == 'App 3');
|
||||
assert(bloc.state.apps[3].name == 'App 1');
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
//
|
||||
}
|
110
frontend/app_flowy/test/bloc_test/menu_test/trash_bloc_test.dart
Normal file
110
frontend/app_flowy/test/bloc_test/menu_test/trash_bloc_test.dart
Normal file
@ -0,0 +1,110 @@
|
||||
import 'package:app_flowy/plugins/doc/document.dart';
|
||||
import 'package:app_flowy/plugins/trash/application/trash_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/app/app_bloc.dart';
|
||||
import 'package:bloc_test/bloc_test.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 '../../util.dart';
|
||||
|
||||
void main() {
|
||||
late AppFlowyUnitTest test;
|
||||
late AppPB app;
|
||||
late AppBloc appBloc;
|
||||
late List<ViewPB> allViews;
|
||||
setUpAll(() async {
|
||||
test = await AppFlowyUnitTest.ensureInitialized();
|
||||
|
||||
/// Create a new app with three documents
|
||||
app = await test.createTestApp();
|
||||
appBloc = AppBloc(app: app)
|
||||
..add(const AppEvent.initial())
|
||||
..add(AppEvent.createView(
|
||||
"Document 1",
|
||||
DocumentPluginBuilder(),
|
||||
))
|
||||
..add(AppEvent.createView(
|
||||
"Document 2",
|
||||
DocumentPluginBuilder(),
|
||||
))
|
||||
..add(
|
||||
AppEvent.createView(
|
||||
"Document 3",
|
||||
DocumentPluginBuilder(),
|
||||
),
|
||||
);
|
||||
await blocResponseFuture(millisecond: 200);
|
||||
allViews = [...appBloc.state.app.belongings.items];
|
||||
assert(allViews.length == 3);
|
||||
});
|
||||
|
||||
group('$TrashBloc', () {
|
||||
late TrashBloc trashBloc;
|
||||
late ViewPB deletedView;
|
||||
|
||||
setUpAll(() {});
|
||||
|
||||
setUp(() async {
|
||||
trashBloc = TrashBloc()..add(const TrashEvent.initial());
|
||||
await blocResponseFuture();
|
||||
});
|
||||
|
||||
blocTest<TrashBloc, TrashState>(
|
||||
"delete view",
|
||||
build: () => trashBloc,
|
||||
act: (bloc) async {
|
||||
deletedView = appBloc.state.app.belongings.items[0];
|
||||
appBloc.add(AppEvent.deleteView(deletedView.id));
|
||||
},
|
||||
wait: blocResponseDuration(),
|
||||
verify: (bloc) {
|
||||
assert(appBloc.state.app.belongings.items.length == 2);
|
||||
assert(bloc.state.objects.length == 1);
|
||||
assert(bloc.state.objects.first.id == deletedView.id);
|
||||
},
|
||||
);
|
||||
|
||||
blocTest<TrashBloc, TrashState>(
|
||||
"delete all views",
|
||||
build: () => trashBloc,
|
||||
act: (bloc) async {
|
||||
for (final view in appBloc.state.app.belongings.items) {
|
||||
appBloc.add(AppEvent.deleteView(view.id));
|
||||
await blocResponseFuture();
|
||||
}
|
||||
},
|
||||
wait: blocResponseDuration(),
|
||||
verify: (bloc) {
|
||||
assert(bloc.state.objects[0].id == allViews[0].id);
|
||||
assert(bloc.state.objects[1].id == allViews[1].id);
|
||||
assert(bloc.state.objects[2].id == allViews[2].id);
|
||||
},
|
||||
);
|
||||
blocTest<TrashBloc, TrashState>(
|
||||
"put back",
|
||||
build: () => trashBloc,
|
||||
act: (bloc) async {
|
||||
bloc.add(TrashEvent.putback(allViews[0].id));
|
||||
},
|
||||
wait: blocResponseDuration(),
|
||||
verify: (bloc) {
|
||||
assert(appBloc.state.app.belongings.items.length == 1);
|
||||
assert(bloc.state.objects.length == 2);
|
||||
},
|
||||
);
|
||||
blocTest<TrashBloc, TrashState>(
|
||||
"put back all",
|
||||
build: () => trashBloc,
|
||||
act: (bloc) async {
|
||||
bloc.add(const TrashEvent.restoreAll());
|
||||
},
|
||||
wait: blocResponseDuration(),
|
||||
verify: (bloc) {
|
||||
assert(appBloc.state.app.belongings.items.length == 3);
|
||||
assert(bloc.state.objects.isEmpty);
|
||||
},
|
||||
);
|
||||
//
|
||||
});
|
||||
}
|
@ -113,10 +113,10 @@ class FlowyTestApp implements EntryPoint {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> blocResponseFuture() {
|
||||
return Future.delayed(const Duration(milliseconds: 100));
|
||||
Future<void> blocResponseFuture({int millisecond = 100}) {
|
||||
return Future.delayed(Duration(milliseconds: millisecond));
|
||||
}
|
||||
|
||||
Duration blocResponseDuration({int millseconds = 100}) {
|
||||
return Duration(milliseconds: millseconds);
|
||||
Duration blocResponseDuration({int milliseconds = 100}) {
|
||||
return Duration(milliseconds: milliseconds);
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ pub(crate) enum FolderNotification {
|
||||
WorkspaceAppsChanged = 14,
|
||||
WorkspaceSetting = 15,
|
||||
AppUpdated = 21,
|
||||
AppViewsChanged = 24,
|
||||
ViewUpdated = 31,
|
||||
ViewDeleted = 32,
|
||||
ViewRestored = 33,
|
||||
|
@ -1,5 +1,5 @@
|
||||
pub use crate::entities::view::ViewDataFormatPB;
|
||||
use crate::entities::{DeletedViewPB, ViewInfoPB, ViewLayoutTypePB};
|
||||
use crate::entities::{AppPB, DeletedViewPB, ViewInfoPB, ViewLayoutTypePB};
|
||||
use crate::manager::{ViewDataProcessor, ViewDataProcessorMap};
|
||||
use crate::{
|
||||
dart_notification::{send_dart_notification, FolderNotification},
|
||||
@ -531,16 +531,15 @@ fn notify_views_changed<'a>(
|
||||
trash_controller: Arc<TrashController>,
|
||||
transaction: &'a (dyn FolderPersistenceTransaction + 'a),
|
||||
) -> FlowyResult<()> {
|
||||
let items: Vec<ViewPB> = read_belonging_views_on_local(belong_to_id, trash_controller.clone(), transaction)?
|
||||
.into_iter()
|
||||
.map(|view_rev| view_rev.into())
|
||||
.collect();
|
||||
tracing::Span::current().record("view_count", &format!("{}", items.len()).as_str());
|
||||
let mut app_rev = transaction.read_app(belong_to_id)?;
|
||||
let trash_ids = trash_controller.read_trash_ids(transaction)?;
|
||||
app_rev.belongings.retain(|view| !trash_ids.contains(&view.id));
|
||||
let app: AppPB = app_rev.into();
|
||||
|
||||
let repeated_view = RepeatedViewPB { items };
|
||||
send_dart_notification(belong_to_id, FolderNotification::AppViewsChanged)
|
||||
.payload(repeated_view)
|
||||
send_dart_notification(belong_to_id, FolderNotification::AppUpdated)
|
||||
.payload(app)
|
||||
.send();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user