From 13b3439bd631c385c6bdc53adc9f05a29c3e5af4 Mon Sep 17 00:00:00 2001 From: Mohammad Zolfaghari Date: Fri, 24 May 2024 16:47:35 +0330 Subject: [PATCH] fix: default text direction not synced (#5405) * fix: default text direction not synced * test: annotate visibleForTesting --- .../pages/settings_workspace_view.dart | 20 ++- .../widget_test/direction_setting_test.dart | 159 ++++++++++++++++++ 2 files changed, 172 insertions(+), 7 deletions(-) create mode 100644 frontend/appflowy_flutter/test/widget_test/direction_setting_test.dart diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_workspace_view.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_workspace_view.dart index 56e1bb93fc..8bf9415e3f 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_workspace_view.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_workspace_view.dart @@ -125,7 +125,7 @@ class SettingsWorkspaceView extends StatelessWidget { title: LocaleKeys.settings_workspacePage_textDirection_title.tr(), children: const [ - _TextDirectionSelect(), + TextDirectionSelect(), EnableRTLItemsSwitcher(), ], ), @@ -387,19 +387,25 @@ class _WorkspaceIconSetting extends StatelessWidget { } } -class _TextDirectionSelect extends StatelessWidget { - const _TextDirectionSelect(); +@visibleForTesting +class TextDirectionSelect extends StatelessWidget { + const TextDirectionSelect({super.key}); @override Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { - final selectedItem = state.textDirection ?? AppFlowyTextDirection.auto; + final selectedItem = state.textDirection ?? AppFlowyTextDirection.ltr; return SettingsRadioSelect( - onChanged: (item) => context - .read() - .setTextDirection(item.value), + onChanged: (item) { + context + .read() + .setTextDirection(item.value); + context + .read() + .syncDefaultTextDirection(item.value.name); + }, items: [ SettingsRadioItem( value: AppFlowyTextDirection.ltr, diff --git a/frontend/appflowy_flutter/test/widget_test/direction_setting_test.dart b/frontend/appflowy_flutter/test/widget_test/direction_setting_test.dart new file mode 100644 index 0000000000..34472193f9 --- /dev/null +++ b/frontend/appflowy_flutter/test/widget_test/direction_setting_test.dart @@ -0,0 +1,159 @@ +import 'package:appflowy/workspace/presentation/settings/pages/settings_workspace_view.dart'; +import 'package:appflowy/workspace/presentation/settings/shared/settings_radio_select.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flutter/material.dart'; +import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart'; +import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:bloc_test/bloc_test.dart'; +import 'package:appflowy_backend/protobuf/flowy-user/user_setting.pb.dart'; +import 'package:appflowy/user/application/user_settings_service.dart'; + +import '../util.dart'; + +class MockAppearanceSettingsBloc + extends MockBloc + implements AppearanceSettingsCubit {} + +class MockDocumentAppearanceCubit extends Mock + implements DocumentAppearanceCubit {} + +class MockDocumentAppearance extends Mock implements DocumentAppearance {} + +void main() { + late AppearanceSettingsPB appearanceSettings; + late DateTimeSettingsPB dateTimeSettings; + + setUp(() async { + await AppFlowyUnitTest.ensureInitialized(); + appearanceSettings = + await UserSettingsBackendService().getAppearanceSetting(); + dateTimeSettings = await UserSettingsBackendService().getDateTimeSettings(); + }); + + testWidgets('TextDirectionSelect update default text direction setting', + (WidgetTester tester) async { + final appearanceSettingsState = AppearanceSettingsState.initial( + AppTheme.fallback, + appearanceSettings.themeMode, + appearanceSettings.font, + appearanceSettings.monospaceFont, + appearanceSettings.layoutDirection, + appearanceSettings.textDirection, + appearanceSettings.enableRtlToolbarItems, + appearanceSettings.locale, + appearanceSettings.isMenuCollapsed, + appearanceSettings.menuOffset, + dateTimeSettings.dateFormat, + dateTimeSettings.timeFormat, + dateTimeSettings.timezoneId, + appearanceSettings.documentSetting.cursorColor.isEmpty + ? null + : Color( + int.parse(appearanceSettings.documentSetting.cursorColor), + ), + appearanceSettings.documentSetting.selectionColor.isEmpty + ? null + : Color( + int.parse( + appearanceSettings.documentSetting.selectionColor, + ), + ), + 1.0, + ); + final mockAppearanceSettingsBloc = MockAppearanceSettingsBloc(); + when(() => mockAppearanceSettingsBloc.state).thenReturn( + appearanceSettingsState, + ); + + final mockDocumentAppearanceCubit = MockDocumentAppearanceCubit(); + when(() => mockDocumentAppearanceCubit.stream).thenAnswer( + (_) => Stream.fromIterable([MockDocumentAppearance()]), + ); + + await tester.pumpWidget( + MultiBlocProvider( + providers: [ + BlocProvider.value( + value: mockAppearanceSettingsBloc, + ), + BlocProvider.value( + value: mockDocumentAppearanceCubit, + ), + ], + child: MaterialApp( + theme: appearanceSettingsState.lightTheme, + home: MultiBlocProvider( + providers: [ + BlocProvider.value( + value: mockAppearanceSettingsBloc, + ), + BlocProvider.value( + value: mockDocumentAppearanceCubit, + ), + ], + child: const Scaffold( + body: TextDirectionSelect(), + ), + ), + ), + ), + ); + await tester.pumpAndSettle(); + + expect( + find.text( + LocaleKeys.settings_workspacePage_textDirection_leftToRight.tr(), + ), + findsOne, + ); + expect( + find.text( + LocaleKeys.settings_workspacePage_textDirection_rightToLeft.tr(), + ), + findsOne, + ); + expect( + find.text( + LocaleKeys.settings_workspacePage_textDirection_auto.tr(), + ), + findsOne, + ); + + final radioSelectFinder = + find.byType(SettingsRadioSelect); + expect(radioSelectFinder, findsOne); + + when( + () => mockAppearanceSettingsBloc.setTextDirection( + any(), + ), + ).thenAnswer((_) async => {}); + when( + () => mockDocumentAppearanceCubit.syncDefaultTextDirection( + any(), + ), + ).thenAnswer((_) async {}); + + final radioSelect = tester.widget(radioSelectFinder) + as SettingsRadioSelect; + final rtlSelect = radioSelect.items + .firstWhere((select) => select.value == AppFlowyTextDirection.rtl); + radioSelect.onChanged(rtlSelect); + + verify( + () => mockAppearanceSettingsBloc.setTextDirection( + any(), + ), + ).called(1); + verify( + () => mockDocumentAppearanceCubit.syncDefaultTextDirection( + any(), + ), + ).called(1); + }); +}