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,