chore: add app setting test (#1361)

This commit is contained in:
Nathan.fooo 2022-10-25 17:30:57 +08:00 committed by GitHub
parent 67e4a759c7
commit 18185cc90c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 163 additions and 48 deletions

View File

@ -19,9 +19,9 @@ class InitAppWidgetTask extends LaunchTask {
Future<void> initialize(LaunchContext context) async {
final widget = context.getIt<EntryPoint>().create();
final setting = await SettingsFFIService().getAppearanceSetting();
final settingModel = AppearanceSetting(setting);
final appearanceSetting = AppearanceSetting(setting);
final app = ApplicationWidget(
settingModel: settingModel,
appearanceSetting: appearanceSetting,
child: widget,
);
Bloc.observer = ApplicationBlocObserver();
@ -61,23 +61,23 @@ class InitAppWidgetTask extends LaunchTask {
class ApplicationWidget extends StatelessWidget {
final Widget child;
final AppearanceSetting settingModel;
final AppearanceSetting appearanceSetting;
const ApplicationWidget({
Key? key,
required this.child,
required this.settingModel,
required this.appearanceSetting,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider.value(
value: settingModel,
value: appearanceSetting,
builder: (context, _) {
const ratio = 1.73;
const minWidth = 600.0;
setWindowMinSize(const Size(minWidth, minWidth / ratio));
settingModel.readLocaleWhenAppLaunch(context);
appearanceSetting.readLocaleWhenAppLaunch(context);
AppTheme theme = context.select<AppearanceSetting, AppTheme>(
(value) => value.theme,
);

View File

@ -13,7 +13,6 @@ class AppearanceSetting extends ChangeNotifier with EquatableMixin {
final AppearanceSettingsPB _setting;
AppTheme _theme;
Locale _locale;
Timer? _debounceSaveOperation;
AppearanceSetting(AppearanceSettingsPB setting)
: _setting = setting,
@ -83,10 +82,17 @@ class AppearanceSetting extends ChangeNotifier with EquatableMixin {
} else {
_setting.settingKeyValue[key] = value;
}
_saveAppearSetting();
notifyListeners();
}
_saveAppearSetting();
notifyListeners();
}
String? getValue(String key) {
if (key.isEmpty) {
Log.warn("The key should not be empty");
return null;
}
return _setting.settingKeyValue[key];
}
/// Called when the application launch.
@ -103,15 +109,12 @@ class AppearanceSetting extends ChangeNotifier with EquatableMixin {
}
Future<void> _saveAppearSetting() async {
_debounceSaveOperation?.cancel();
_debounceSaveOperation = Timer(
const Duration(seconds: 1),
() {
SettingsFFIService().setAppearanceSetting(_setting).then((result) {
result.fold((l) => null, (error) => Log.error(error));
});
},
);
SettingsFFIService().setAppearanceSetting(_setting).then((result) {
result.fold(
(l) => null,
(error) => Log.error(error),
);
});
}
@override

View File

@ -0,0 +1,43 @@
import 'package:app_flowy/user/application/user_settings_service.dart';
import 'package:app_flowy/workspace/application/appearance.dart';
import 'package:flowy_infra/theme.dart';
import 'package:flutter_test/flutter_test.dart';
import '../../util.dart';
void main() {
// ignore: unused_local_variable
late AppFlowyUnitTest context;
setUpAll(() async {
context = await AppFlowyUnitTest.ensureInitialized();
});
group('$AppearanceSetting', () {
late AppearanceSetting appearanceSetting;
setUp(() async {
final setting = await SettingsFFIService().getAppearanceSetting();
appearanceSetting = AppearanceSetting(setting);
await blocResponseFuture();
});
test('default theme', () {
expect(appearanceSetting.theme.ty, ThemeType.light);
});
test('save key/value', () async {
appearanceSetting.setKeyValue("123", "456");
});
test('read key/value', () {
expect(appearanceSetting.getValue("123"), "456");
});
test('remove key/value', () {
appearanceSetting.setKeyValue("123", null);
});
test('read key/value', () {
expect(appearanceSetting.getValue("123"), null);
});
});
}

View File

@ -12,38 +12,42 @@ void main() {
late AppFlowyUnitTest test;
late AppPB app;
late AppBloc appBloc;
late List<ViewPB> allViews;
late TrashBloc trashBloc;
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);
});
// 1. Create three views
// 2. Delete a view and check the state
// 3. Delete all views and check the state
// 4. Put back a view
// 5. Put back all views
group('$TrashBloc', () {
late TrashBloc trashBloc;
late ViewPB deletedView;
setUpAll(() {});
late List<ViewPB> allViews;
setUpAll(() async {
/// 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);
});
setUp(() async {
trashBloc = TrashBloc()..add(const TrashEvent.initial());
@ -51,7 +55,7 @@ void main() {
});
blocTest<TrashBloc, TrashState>(
"delete view",
"delete a view",
build: () => trashBloc,
act: (bloc) async {
deletedView = appBloc.state.app.belongings.items[0];
@ -82,7 +86,7 @@ void main() {
},
);
blocTest<TrashBloc, TrashState>(
"put back",
"put back a trash",
build: () => trashBloc,
act: (bloc) async {
bloc.add(TrashEvent.putback(allViews[0].id));
@ -94,7 +98,7 @@ void main() {
},
);
blocTest<TrashBloc, TrashState>(
"put back all",
"put back all trash",
build: () => trashBloc,
act: (bloc) async {
bloc.add(const TrashEvent.restoreAll());
@ -107,4 +111,69 @@ void main() {
);
//
});
// 1. Create three views
// 2. Delete a trash permanently and check the state
// 3. Delete all views permanently
group('$TrashBloc', () {
setUpAll(() async {
/// 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);
});
setUp(() async {
trashBloc = TrashBloc()..add(const TrashEvent.initial());
await blocResponseFuture();
});
blocTest<TrashBloc, TrashState>(
"delete a view permanently",
build: () => trashBloc,
act: (bloc) async {
final view = appBloc.state.app.belongings.items[0];
appBloc.add(AppEvent.deleteView(view.id));
await blocResponseFuture();
trashBloc.add(TrashEvent.delete(trashBloc.state.objects[0]));
},
wait: blocResponseDuration(),
verify: (bloc) {
assert(appBloc.state.app.belongings.items.length == 2);
assert(bloc.state.objects.isEmpty);
},
);
blocTest<TrashBloc, TrashState>(
"delete all view permanently",
build: () => trashBloc,
act: (bloc) async {
for (final view in appBloc.state.app.belongings.items) {
appBloc.add(AppEvent.deleteView(view.id));
}
await blocResponseFuture();
trashBloc.add(const TrashEvent.deleteAll());
},
wait: blocResponseDuration(),
verify: (bloc) {
assert(appBloc.state.app.belongings.items.isEmpty);
assert(bloc.state.objects.isEmpty);
},
);
});
}