mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: add grid bloc test (#1289)
Co-authored-by: nathan <nathan@appflowy.io>
This commit is contained in:
parent
cbd84dfaad
commit
6a8c15899c
@ -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 {
|
||||
|
@ -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<GridEvent, GridState> {
|
||||
final GridDataController dataController;
|
||||
void Function()? _createRowOperation;
|
||||
|
||||
GridBloc({required ViewPB view})
|
||||
: dataController = GridDataController(view: view),
|
||||
@ -28,7 +30,19 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
||||
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<GridEvent, GridState> {
|
||||
Future<void> _loadGrid(Emitter<GridState> 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<GridEvent, GridState> {
|
||||
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<RowInfo> rows,
|
||||
RowsChangedReason listState,
|
||||
|
@ -64,6 +64,7 @@ class GridDataController {
|
||||
});
|
||||
}
|
||||
|
||||
// Loads the rows from each block
|
||||
Future<Either<Unit, FlowyError>> loadData() async {
|
||||
final result = await _gridFFIService.loadGrid();
|
||||
return Future(
|
||||
|
@ -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 {
|
||||
|
@ -118,11 +118,7 @@ void _resolveFolderDeps(GetIt getIt) {
|
||||
|
||||
// AppPB
|
||||
getIt.registerFactoryParam<AppBloc, AppPB, void>(
|
||||
(app, _) => AppBloc(
|
||||
app: app,
|
||||
appService: AppService(),
|
||||
appListener: AppListener(appId: app.id),
|
||||
),
|
||||
(app, _) => AppBloc(app: app),
|
||||
);
|
||||
|
||||
// trash
|
||||
|
@ -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 {
|
||||
|
@ -22,19 +22,24 @@ class AppBloc extends Bloc<AppEvent, AppState> {
|
||||
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<AppEvent>((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<AppEvent, AppState> {
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _deleteView(Emitter<AppState> emit) async {
|
||||
// Delete the current app
|
||||
Future<void> _deleteApp(Emitter<AppState> 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<AppEvent, AppState> {
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _deleteView(Emitter<AppState> 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<void> _createView(CreateView value, Emitter<AppState> 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<AppEvent, AppState> {
|
||||
}
|
||||
|
||||
Future<void> _didReceiveViewUpdated(
|
||||
List<ViewPB> views, Emitter<AppState> emit) async {
|
||||
List<ViewPB> views,
|
||||
Emitter<AppState> 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<ViewPB> 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),
|
||||
);
|
||||
}
|
||||
|
@ -18,17 +18,17 @@ class AppService {
|
||||
Future<Either<ViewPB, FlowyError>> 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<Either<Unit, FlowyError>> deleteView({required String viewId}) {
|
||||
final request = RepeatedViewIdPB.create()..items.add(viewId);
|
||||
return FolderEventDeleteView(request).send();
|
||||
}
|
||||
|
||||
Future<Either<Unit, FlowyError>> updateApp(
|
||||
{required String appId, String? name}) {
|
||||
UpdateAppPayloadPB payload = UpdateAppPayloadPB.create()..appId = appId;
|
||||
|
@ -31,12 +31,14 @@ class ViewBloc extends Bloc<ViewEvent, ViewState> {
|
||||
},
|
||||
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<ViewEvent, ViewState> {
|
||||
},
|
||||
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<ViewPB, FlowyError> result) = ViewDidUpdate;
|
||||
const factory ViewEvent.viewDidUpdate(Either<ViewPB, FlowyError> result) =
|
||||
ViewDidUpdate;
|
||||
}
|
||||
|
||||
@freezed
|
||||
|
@ -17,11 +17,11 @@ class WorkspaceService {
|
||||
required this.workspaceId,
|
||||
});
|
||||
Future<Either<AppPB, FlowyError>> 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();
|
||||
}
|
||||
|
||||
|
@ -104,13 +104,12 @@ class MenuAppHeader extends StatelessWidget {
|
||||
message: LocaleKeys.menuAppHeader_addPageTooltip.tr(),
|
||||
child: AddButton(
|
||||
onSelected: (pluginBuilder) {
|
||||
context.read<AppBloc>().add(AppEvent.createView(
|
||||
LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
|
||||
"",
|
||||
pluginBuilder.dataType,
|
||||
pluginBuilder.subDataType!,
|
||||
pluginBuilder.pluginType,
|
||||
));
|
||||
context.read<AppBloc>().add(
|
||||
AppEvent.createView(
|
||||
LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
|
||||
pluginBuilder,
|
||||
),
|
||||
);
|
||||
},
|
||||
).padding(right: MenuAppSizes.headerPadding),
|
||||
);
|
||||
|
@ -50,7 +50,6 @@ class _MenuAppState extends State<MenuApp> {
|
||||
},
|
||||
),
|
||||
BlocListener<AppBloc, AppState>(
|
||||
listenWhen: (p, c) => p.views != c.views,
|
||||
listener: (context, state) => viewDataContext.views = state.views,
|
||||
),
|
||||
],
|
||||
|
@ -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<GridBloc, GridState>(
|
||||
"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);
|
||||
});
|
||||
});
|
||||
}
|
44
frontend/app_flowy/test/bloc_test/grid_test/util.dart
Normal file
44
frontend/app_flowy/test/bloc_test/grid_test/util.dart
Normal file
@ -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<AppFlowyGridTest> ensureInitialized() async {
|
||||
final inner = await AppFlowyUnitTest.ensureInitialized();
|
||||
final test = AppFlowyGridTest(inner);
|
||||
await test._createTestGrid();
|
||||
return test;
|
||||
}
|
||||
|
||||
Future<void> _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<void> gridBlocResponseFuture({int millseconds = 100}) {
|
||||
return Future.delayed(gridBlocResponseDuration(millseconds: millseconds));
|
||||
}
|
||||
|
||||
Duration gridBlocResponseDuration({int millseconds = 100}) {
|
||||
return Duration(milliseconds: millseconds);
|
||||
}
|
104
frontend/app_flowy/test/bloc_test/menu_test/app_bloc_test.dart
Normal file
104
frontend/app_flowy/test/bloc_test/menu_test/app_bloc_test.dart
Normal file
@ -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<AppBloc, AppState>(
|
||||
"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<AppBloc, AppState>(
|
||||
"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<AppBloc, AppState>(
|
||||
"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<AppBloc, AppState>(
|
||||
"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<AppBloc, AppState>(
|
||||
"delete the document",
|
||||
build: () => AppBloc(app: app)..add(const AppEvent.initial()),
|
||||
act: (bloc) => bloc.add(AppEvent.deleteView(view.id)),
|
||||
);
|
||||
blocTest<AppBloc, AppState>(
|
||||
"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);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
@ -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<WelcomeBloc, WelcomeState>(
|
||||
"welcome screen init",
|
||||
build: () => getIt<WelcomeBloc>(param1: userInfo),
|
||||
act: (bloc) {
|
||||
bloc.add(const WelcomeEvent.initial());
|
||||
},
|
||||
wait: const Duration(seconds: 3),
|
||||
verify: (bloc) {
|
||||
assert(bloc.state.isLoading == false);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
@ -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<AppFlowyBlocTest> ensureInitialized() async {
|
||||
class AppFlowyUnitTest {
|
||||
late UserProfilePB userProfile;
|
||||
late UserService userService;
|
||||
late WorkspaceService workspaceService;
|
||||
late List<WorkspacePB> workspaces;
|
||||
|
||||
static Future<AppFlowyUnitTest> 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<void> _signIn() async {
|
||||
final authService = getIt<AuthService>();
|
||||
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<void> _loadWorkspace() async {
|
||||
final result = await userService.getWorkspaces();
|
||||
result.fold(
|
||||
(value) => workspaces = value,
|
||||
(error) {
|
||||
throw Exception(error);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _initialServices() async {
|
||||
workspaceService = WorkspaceService(workspaceId: currentWorkspace.id);
|
||||
}
|
||||
|
||||
Future<AppPB> 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<UserProfilePB> signIn() async {
|
||||
final authService = getIt<AuthService>();
|
||||
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);
|
||||
}
|
||||
|
@ -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<T: AsRef<str>>(&self, grid_id: T) -> FlowyResult<Arc<GridRevisionEditor>> {
|
||||
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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user