From 89face4f02b3f309bd78497809294d7170173c25 Mon Sep 17 00:00:00 2001 From: "Lucas.Xu" <lucas.xu@appflowy.io> Date: Sat, 23 Sep 2023 10:55:05 +0800 Subject: [PATCH] test: add integration test for ltr/rtl mode --- .../document/document_test_runner.dart | 2 + .../document_text_direction_test.dart | 58 +++++++++++++++++++ .../integration_test/util/settings.dart | 33 +++++++++++ .../document/presentation/editor_page.dart | 23 ++++---- .../direction_setting.dart | 1 + 5 files changed, 107 insertions(+), 10 deletions(-) create mode 100644 frontend/appflowy_flutter/integration_test/document/document_text_direction_test.dart diff --git a/frontend/appflowy_flutter/integration_test/document/document_test_runner.dart b/frontend/appflowy_flutter/integration_test/document/document_test_runner.dart index 7f517678a9..a29f8df49d 100644 --- a/frontend/appflowy_flutter/integration_test/document/document_test_runner.dart +++ b/frontend/appflowy_flutter/integration_test/document/document_test_runner.dart @@ -5,6 +5,7 @@ import 'document_codeblock_paste_test.dart' as document_codeblock_paste_test; import 'document_copy_and_paste_test.dart' as document_copy_and_paste_test; import 'document_create_and_delete_test.dart' as document_create_and_delete_test; +import 'document_text_direction_test.dart' as document_text_direction_test; import 'document_with_cover_image_test.dart' as document_with_cover_image_test; import 'document_with_database_test.dart' as document_with_database_test; import 'document_with_inline_math_equation_test.dart' @@ -29,4 +30,5 @@ void startTesting() { document_copy_and_paste_test.main(); document_codeblock_paste_test.main(); document_alignment_test.main(); + document_text_direction_test.main(); } diff --git a/frontend/appflowy_flutter/integration_test/document/document_text_direction_test.dart b/frontend/appflowy_flutter/integration_test/document/document_text_direction_test.dart new file mode 100644 index 0000000000..5499143881 --- /dev/null +++ b/frontend/appflowy_flutter/integration_test/document/document_text_direction_test.dart @@ -0,0 +1,58 @@ +import 'package:appflowy/workspace/application/appearance.dart'; +import 'package:appflowy_editor/appflowy_editor.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; + +import '../util/util.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + group('text direction', () { + testWidgets( + '''no text direction items will be displayed in the default/LTR mode,and three text direction items will be displayed in the RTL mode.''', + (tester) async { + // combine the two tests into one to avoid the time-consuming process of initializing the app + await tester.initializeAppFlowy(); + await tester.tapGoButton(); + + final selection = Selection.single( + path: [0], + startOffset: 0, + endOffset: 1, + ); + // click the first line of the readme + await tester.editor.tapLineOfEditorAt(0); + await tester.editor.updateSelection(selection); + await tester.pumpAndSettle(); + + // because this icons are defined in the appflowy_editor package, we can't fetch the icons by SVG data. [textDirectionItems] + final textDirectionIconNames = [ + 'toolbar/text_direction_auto', + 'toolbar/text_direction_left', + 'toolbar/text_direction_right', + ]; + // no text direction items in default/LTR mode + var button = find.byWidgetPredicate( + (widget) => + widget is SVGIconItemWidget && + textDirectionIconNames.contains(widget.iconName), + ); + expect(button, findsNothing); + + // switch to the RTL mode + await tester.switchLayoutDirectionMode(LayoutDirection.rtlLayout); + + await tester.editor.tapLineOfEditorAt(0); + await tester.editor.updateSelection(selection); + await tester.pumpAndSettle(); + + button = find.byWidgetPredicate( + (widget) => + widget is SVGIconItemWidget && + textDirectionIconNames.contains(widget.iconName), + ); + expect(button, findsNWidgets(3)); + }); + }); +} diff --git a/frontend/appflowy_flutter/integration_test/util/settings.dart b/frontend/appflowy_flutter/integration_test/util/settings.dart index 1c6e4e919f..1fd885de0a 100644 --- a/frontend/appflowy_flutter/integration_test/util/settings.dart +++ b/frontend/appflowy_flutter/integration_test/util/settings.dart @@ -1,9 +1,11 @@ import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/workspace/application/appearance.dart'; import 'package:appflowy/workspace/application/settings/prelude.dart'; import 'package:appflowy/workspace/presentation/settings/settings_dialog.dart'; import 'package:appflowy/workspace/presentation/settings/widgets/settings_menu_element.dart'; import 'package:appflowy/workspace/presentation/settings/widgets/settings_user_view.dart'; import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'base.dart'; @@ -72,4 +74,35 @@ extension AppFlowySettings on WidgetTester { await testTextInput.receiveAction(TextInputAction.done); await pumpAndSettle(); } + + // go to settings page and switch the layout direction + Future<void> switchLayoutDirectionMode( + LayoutDirection layoutDirection, + ) async { + await openSettings(); + await openSettingsPage(SettingsPage.appearance); + + final button = find.byKey(const ValueKey('layout_direction_option_button')); + expect(button, findsOneWidget); + await tapButton(button); + + switch (layoutDirection) { + case LayoutDirection.ltrLayout: + final ltrButton = find.text( + LocaleKeys.settings_appearance_layoutDirection_ltr.tr(), + ); + await tapButton(ltrButton); + break; + case LayoutDirection.rtlLayout: + final rtlButton = find.text( + LocaleKeys.settings_appearance_layoutDirection_rtl.tr(), + ); + await tapButton(rtlButton); + break; + } + + // tap anywhere to close the settings page + await tapAt(Offset.zero); + await pumpAndSettle(); + } } diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_page.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_page.dart index 95e30ff5d9..a49263a8bf 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_page.dart @@ -160,16 +160,7 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> { LayoutDirection.rtlLayout; final layoutDirection = isRTL ? TextDirection.rtl : TextDirection.ltr; - // only show the rtl item when the layout direction is ltr. - for (final item in textDirectionItems) { - if (isRTL) { - if (toolbarItems.every((element) => element.id != item.id)) { - toolbarItems.add(item); - } - } else { - toolbarItems.removeWhere((element) => element.id == item.id); - } - } + _setRTLToolbarItems(isRTL); final editorScrollController = EditorScrollController( editorState: widget.editorState, @@ -475,4 +466,16 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> { customizeShortcuts, ); } + + void _setRTLToolbarItems(bool isRTL) { + final textDirectionItemIds = textDirectionItems.map((e) => e.id); + // clear all the text direction items + toolbarItems.removeWhere( + (item) => textDirectionItemIds.contains(item.id), + ); + // only show the rtl item when the layout direction is ltr. + if (isRTL) { + toolbarItems.addAll(textDirectionItems); + } + } } diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_appearance/direction_setting.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_appearance/direction_setting.dart index 36017493f8..d96e5e338f 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_appearance/direction_setting.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_appearance/direction_setting.dart @@ -25,6 +25,7 @@ class LayoutDirectionSetting extends StatelessWidget { hint: LocaleKeys.settings_appearance_layoutDirection_hint.tr(), trailing: [ ThemeValueDropDown( + key: const ValueKey('layout_direction_option_button'), currentValue: _layoutDirectionLabelText(currentLayoutDirection), popupBuilder: (context) => Column( mainAxisSize: MainAxisSize.min,