Browse Source

test: implement update text style by command X test

Lucas.Xu 2 years ago
parent
commit
f762a78ac0

+ 19 - 11
frontend/app_flowy/packages/flowy_editor/lib/src/service/internal_key_event_handlers/slash_handler.dart

@@ -11,6 +11,9 @@ import 'package:flowy_editor/src/extensions/node_extensions.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 
+@visibleForTesting
+List<PopupListItem> get popupListItems => _popupListItems;
+
 final List<PopupListItem> _popupListItems = [
   PopupListItem(
     text: 'Text',
@@ -94,6 +97,14 @@ FlowyKeyEventHandler slashShortcutHandler = (editorState, event) {
   _editorState = editorState;
   WidgetsBinding.instance.addPostFrameCallback((_) {
     _selectionChangeBySlash = false;
+
+    editorState.service.selectionService.currentSelection
+        .removeListener(clearPopupList);
+    editorState.service.selectionService.currentSelection
+        .addListener(clearPopupList);
+
+    editorState.service.scrollService?.disable();
+
     showPopupList(context, editorState, selectionRects.first.bottomRight);
   });
 
@@ -115,23 +126,20 @@ void showPopupList(
   );
 
   Overlay.of(context)?.insert(_popupListOverlay!);
-
-  editorState.service.selectionService.currentSelection
-      .removeListener(clearPopupList);
-  editorState.service.selectionService.currentSelection
-      .addListener(clearPopupList);
-
-  editorState.service.scrollService?.disable();
 }
 
 void clearPopupList() {
   if (_popupListOverlay == null || _editorState == null) {
     return;
   }
-  final selection =
-      _editorState?.service.selectionService.currentSelection.value;
-  if (selection == null) {
-    return;
+  final isSelectionDisposed =
+      _editorState?.service.selectionServiceKey.currentState != null;
+  if (isSelectionDisposed) {
+    final selection =
+        _editorState?.service.selectionService.currentSelection.value;
+    if (selection == null) {
+      return;
+    }
   }
   if (_selectionChangeBySlash) {
     _selectionChangeBySlash = false;

+ 15 - 21
frontend/app_flowy/packages/flowy_editor/lib/src/service/internal_key_event_handlers/update_text_style_by_command_x_handler.dart

@@ -3,9 +3,10 @@ import 'package:flutter/material.dart';
 import 'package:flowy_editor/src/document/node.dart';
 import 'package:flowy_editor/src/service/default_text_operations/format_rich_text_style.dart';
 import 'package:flowy_editor/src/service/keyboard_service.dart';
+import 'package:flutter/services.dart';
 
 FlowyKeyEventHandler updateTextStyleByCommandXHandler = (editorState, event) {
-  if (!event.isMetaPressed || event.character == null) {
+  if (!event.isMetaPressed) {
     return KeyEventResult.ignored;
   }
 
@@ -17,26 +18,19 @@ FlowyKeyEventHandler updateTextStyleByCommandXHandler = (editorState, event) {
     return KeyEventResult.ignored;
   }
 
-  switch (event.character!) {
-    // bold
-    case 'B':
-    case 'b':
-      formatBold(editorState);
-      return KeyEventResult.handled;
-    case 'I':
-    case 'i':
-      formatItalic(editorState);
-      return KeyEventResult.handled;
-    case 'U':
-    case 'u':
-      formatUnderline(editorState);
-      return KeyEventResult.handled;
-    case 'S':
-    case 's':
-      formatStrikethrough(editorState);
-      return KeyEventResult.handled;
-    default:
-      break;
+  if (event.logicalKey == LogicalKeyboardKey.keyB) {
+    formatBold(editorState);
+    return KeyEventResult.handled;
+  } else if (event.logicalKey == LogicalKeyboardKey.keyI) {
+    formatItalic(editorState);
+    return KeyEventResult.handled;
+  } else if (event.logicalKey == LogicalKeyboardKey.keyU) {
+    formatUnderline(editorState);
+    return KeyEventResult.handled;
+  } else if (event.logicalKey == LogicalKeyboardKey.keyS &&
+      event.isShiftPressed) {
+    formatStrikethrough(editorState);
+    return KeyEventResult.handled;
   }
 
   return KeyEventResult.ignored;

+ 17 - 2
frontend/app_flowy/packages/flowy_editor/test/infra/test_raw_key_event.dart

@@ -91,12 +91,27 @@ extension on LogicalKeyboardKey {
     if (this == LogicalKeyboardKey.pageUp) {
       return PhysicalKeyboardKey.pageUp;
     }
-    if (this == LogicalKeyboardKey.keyZ) {
-      return PhysicalKeyboardKey.keyZ;
+    if (this == LogicalKeyboardKey.slash) {
+      return PhysicalKeyboardKey.slash;
+    }
+    if (this == LogicalKeyboardKey.arrowDown) {
+      return PhysicalKeyboardKey.arrowDown;
     }
     if (this == LogicalKeyboardKey.keyA) {
       return PhysicalKeyboardKey.keyA;
     }
+    if (this == LogicalKeyboardKey.keyB) {
+      return PhysicalKeyboardKey.keyB;
+    }
+    if (this == LogicalKeyboardKey.keyI) {
+      return PhysicalKeyboardKey.keyI;
+    }
+    if (this == LogicalKeyboardKey.keyS) {
+      return PhysicalKeyboardKey.keyS;
+    }
+    if (this == LogicalKeyboardKey.keyU) {
+      return PhysicalKeyboardKey.keyU;
+    }
     throw UnimplementedError();
   }
 }

+ 39 - 0
frontend/app_flowy/packages/flowy_editor/test/service/internal_key_event_handlers/slash_handler_test.dart

@@ -0,0 +1,39 @@
+import 'package:flowy_editor/flowy_editor.dart';
+import 'package:flowy_editor/src/service/internal_key_event_handlers/slash_handler.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_test/flutter_test.dart';
+import '../../infra/test_editor.dart';
+
+void main() async {
+  setUpAll(() {
+    TestWidgetsFlutterBinding.ensureInitialized();
+  });
+
+  group('slash_handler.dart', () {
+    testWidgets('Presses / to trigger popup list ', (tester) async {
+      const text = 'Welcome to Appflowy 😁';
+      const lines = 3;
+      final editor = tester.editor;
+      for (var i = 0; i < lines; i++) {
+        editor.insertTextNode(text);
+      }
+      await editor.startTesting();
+      await editor.updateSelection(Selection.single(path: [1], startOffset: 0));
+      await editor.pressLogicKey(LogicalKeyboardKey.slash);
+
+      await tester.pumpAndSettle(const Duration(milliseconds: 1000));
+
+      expect(find.byType(PopupListWidget, skipOffstage: false), findsOneWidget);
+
+      for (final item in popupListItems) {
+        expect(find.byWidget(item.icon), findsOneWidget);
+      }
+
+      await editor.updateSelection(Selection.single(path: [1], startOffset: 0));
+
+      await tester.pumpAndSettle(const Duration(milliseconds: 200));
+
+      expect(find.byType(PopupListWidget, skipOffstage: false), findsNothing);
+    });
+  });
+}

+ 87 - 0
frontend/app_flowy/packages/flowy_editor/test/service/internal_key_event_handlers/update_text_style_by_command_x_handler_test.dart

@@ -0,0 +1,87 @@
+import 'package:flowy_editor/flowy_editor.dart';
+import 'package:flowy_editor/src/render/rich_text/rich_text_style.dart';
+import 'package:flowy_editor/src/extensions/text_node_extensions.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_test/flutter_test.dart';
+import '../../infra/test_editor.dart';
+
+void main() async {
+  setUpAll(() {
+    TestWidgetsFlutterBinding.ensureInitialized();
+  });
+
+  group('update_text_style_by_command_x_handler.dart', () {
+    testWidgets('Presses Command + B to update text style', (tester) async {
+      await _testUpdateTextStyleByCommandX(
+        tester,
+        StyleKey.bold,
+        LogicalKeyboardKey.keyB,
+      );
+    });
+
+    testWidgets('Presses Command + I to update text style', (tester) async {
+      await _testUpdateTextStyleByCommandX(
+        tester,
+        StyleKey.bold,
+        LogicalKeyboardKey.keyI,
+      );
+    });
+
+    testWidgets('Presses Command + U to update text style', (tester) async {
+      await _testUpdateTextStyleByCommandX(
+        tester,
+        StyleKey.bold,
+        LogicalKeyboardKey.keyU,
+      );
+    });
+
+    testWidgets('Presses Command + S to update text style', (tester) async {
+      await _testUpdateTextStyleByCommandX(
+        tester,
+        StyleKey.bold,
+        LogicalKeyboardKey.keyS,
+      );
+    });
+  });
+}
+
+Future<void> _testUpdateTextStyleByCommandX(
+    WidgetTester tester, String matchStyle, LogicalKeyboardKey key) async {
+  const text = 'Welcome to Appflowy 😁';
+  final editor = tester.editor
+    ..insertTextNode(text)
+    ..insertTextNode(text)
+    ..insertTextNode(text);
+  await editor.startTesting();
+
+  var selection =
+      Selection.single(path: [1], startOffset: 2, endOffset: text.length - 2);
+  await editor.updateSelection(selection);
+  await editor.pressLogicKey(
+    key,
+    isShiftPressed: key == LogicalKeyboardKey.keyS,
+    isMetaPressed: true,
+  );
+  var textNode = editor.nodeAtPath([1]) as TextNode;
+  expect(textNode.allSatisfyInSelection(matchStyle, selection), true);
+
+  selection =
+      Selection.single(path: [1], startOffset: 0, endOffset: text.length);
+  await editor.updateSelection(selection);
+  await editor.pressLogicKey(
+    key,
+    isShiftPressed: key == LogicalKeyboardKey.keyS,
+    isMetaPressed: true,
+  );
+  textNode = editor.nodeAtPath([1]) as TextNode;
+  expect(textNode.allSatisfyInSelection(matchStyle, selection), true);
+
+  await editor.updateSelection(selection);
+  await editor.pressLogicKey(
+    key,
+    isShiftPressed: key == LogicalKeyboardKey.keyS,
+    isMetaPressed: true,
+  );
+  textNode = editor.nodeAtPath([1]) as TextNode;
+  expect(textNode.allSatisfyInSelection(matchStyle, selection), false);
+}