Jelajahi Sumber

test: test the toolbar_service, toolbar_*.dart

Lucas.Xu 2 tahun lalu
induk
melakukan
104b4cca9d

+ 1 - 2
frontend/app_flowy/packages/appflowy_editor/lib/src/render/toolbar/toolbar_item.dart

@@ -158,8 +158,6 @@ ToolbarShowValidator _showInTextSelection = (editorState) {
 OverlayEntry? _linkMenuOverlay;
 EditorState? _editorState;
 void _showLinkMenu(EditorState editorState, BuildContext context) {
-  _editorState = editorState;
-
   final rects = editorState.service.selectionService.selectionRects;
   var maxBottom = 0.0;
   late Rect matchRect;
@@ -171,6 +169,7 @@ void _showLinkMenu(EditorState editorState, BuildContext context) {
   }
 
   _dismissLinkMenu();
+  _editorState = editorState;
 
   // Since the link menu will only show in single text selection,
   // We get the text node directly instead of judging details again.

+ 3 - 0
frontend/app_flowy/packages/appflowy_editor/test/infra/test_raw_key_event.dart

@@ -115,6 +115,9 @@ extension on LogicalKeyboardKey {
     if (this == LogicalKeyboardKey.keyI) {
       return PhysicalKeyboardKey.keyI;
     }
+    if (this == LogicalKeyboardKey.keyK) {
+      return PhysicalKeyboardKey.keyK;
+    }
     if (this == LogicalKeyboardKey.keyS) {
       return PhysicalKeyboardKey.keyS;
     }

+ 46 - 0
frontend/app_flowy/packages/appflowy_editor/test/render/toolbar/toolbar_item_widget_test.dart

@@ -0,0 +1,46 @@
+import 'package:appflowy_editor/src/render/toolbar/toolbar_item.dart';
+import 'package:appflowy_editor/src/render/toolbar/toolbar_item_widget.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+void main() async {
+  setUpAll(() {
+    TestWidgetsFlutterBinding.ensureInitialized();
+  });
+
+  group('toolbar_item_widget.dart', () {
+    testWidgets('test single toolbar item widget', (tester) async {
+      final key = GlobalKey();
+      var hit = false;
+      final item = ToolbarItem(
+        id: 'appflowy.toolbar.test',
+        type: 1,
+        icon: const Icon(Icons.abc),
+        validator: (editorState) => true,
+        handler: (editorState, context) {},
+      );
+      final widget = ToolbarItemWidget(
+        key: key,
+        item: item,
+        onPressed: (() {
+          hit = true;
+        }),
+      );
+
+      await tester.pumpWidget(
+        MaterialApp(
+          home: Material(
+            child: widget,
+          ),
+        ),
+      );
+
+      expect(find.byKey(key), findsOneWidget);
+
+      await tester.tap(find.byKey(key));
+      await tester.pumpAndSettle();
+
+      expect(hit, true);
+    });
+  });
+}

+ 11 - 0
frontend/app_flowy/packages/appflowy_editor/test/render/toolbar/toolbar_widget_test.dart

@@ -0,0 +1,11 @@
+import 'package:flutter_test/flutter_test.dart';
+
+void main() async {
+  setUpAll(() {
+    TestWidgetsFlutterBinding.ensureInitialized();
+  });
+
+  group('toolbar_widget.dart', () {
+    testWidgets('test toolbar widget', (tester) async {});
+  });
+}

+ 79 - 0
frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/update_text_style_by_command_x_handler_test.dart

@@ -1,6 +1,10 @@
 import 'package:appflowy_editor/appflowy_editor.dart';
+import 'package:appflowy_editor/src/render/link_menu/link_menu.dart';
 import 'package:appflowy_editor/src/render/rich_text/rich_text_style.dart';
 import 'package:appflowy_editor/src/extensions/text_node_extensions.dart';
+import 'package:appflowy_editor/src/render/toolbar/toolbar_item.dart';
+import 'package:appflowy_editor/src/render/toolbar/toolbar_widget.dart';
+import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter_test/flutter_test.dart';
 import '../../infra/test_editor.dart';
@@ -54,6 +58,10 @@ void main() async {
         LogicalKeyboardKey.keyH,
       );
     });
+
+    testWidgets('Presses Command + K to trigger link menu', (tester) async {
+      await _testLinkMenuInSingleTextSelection(tester);
+    });
   });
 }
 
@@ -171,3 +179,74 @@ Future<void> _testUpdateTextStyleByCommandX(
     );
   }
 }
+
+Future<void> _testLinkMenuInSingleTextSelection(WidgetTester tester) async {
+  const link = 'appflowy.io';
+  const text = 'Welcome to Appflowy 😁';
+  final editor = tester.editor
+    ..insertTextNode(text)
+    ..insertTextNode(text)
+    ..insertTextNode(text);
+  await editor.startTesting();
+
+  final selection =
+      Selection.single(path: [1], startOffset: 0, endOffset: text.length);
+  await editor.updateSelection(selection);
+
+  // show toolbar
+  expect(find.byType(ToolbarWidget), findsOneWidget);
+
+  final item = defaultToolbarItems
+      .where((item) => item.id == 'appflowy.toolbar.link')
+      .first;
+  expect(find.byWidget(item.icon), findsOneWidget);
+
+  // trigger the link menu
+  await editor.pressLogicKey(LogicalKeyboardKey.keyK, isMetaPressed: true);
+
+  expect(find.byType(LinkMenu), findsOneWidget);
+
+  await tester.enterText(find.byType(TextField), link);
+  await tester.testTextInput.receiveAction(TextInputAction.done);
+  await tester.pumpAndSettle();
+
+  expect(find.byType(LinkMenu), findsNothing);
+
+  final node = editor.nodeAtPath([1]) as TextNode;
+  expect(
+      node.allSatisfyInSelection(
+        StyleKey.href,
+        selection,
+        (value) => value == link,
+      ),
+      true);
+
+  await editor.updateSelection(selection);
+  await editor.pressLogicKey(LogicalKeyboardKey.keyK, isMetaPressed: true);
+  expect(find.byType(LinkMenu), findsOneWidget);
+  expect(
+      find.text(link, findRichText: true, skipOffstage: false), findsOneWidget);
+
+  // Copy link
+  final copyLink = find.text('Copy link');
+  expect(copyLink, findsOneWidget);
+  await tester.tap(copyLink);
+  await tester.pumpAndSettle();
+  expect(find.byType(LinkMenu), findsNothing);
+
+  // Remove link
+  await editor.pressLogicKey(LogicalKeyboardKey.keyK, isMetaPressed: true);
+  final removeLink = find.text('Remove link');
+  expect(removeLink, findsOneWidget);
+  await tester.tap(removeLink);
+  await tester.pumpAndSettle();
+  expect(find.byType(LinkMenu), findsNothing);
+
+  expect(
+      node.allSatisfyInSelection(
+        StyleKey.href,
+        selection,
+        (value) => value == link,
+      ),
+      false);
+}

+ 36 - 0
frontend/app_flowy/packages/appflowy_editor/test/service/toolbar_service_test.dart

@@ -0,0 +1,36 @@
+import 'package:appflowy_editor/appflowy_editor.dart';
+import 'package:appflowy_editor/src/render/toolbar/toolbar_item.dart';
+import 'package:appflowy_editor/src/render/toolbar/toolbar_widget.dart';
+import 'package:flutter_test/flutter_test.dart';
+import '../infra/test_editor.dart';
+
+void main() async {
+  setUpAll(() {
+    TestWidgetsFlutterBinding.ensureInitialized();
+  });
+
+  group('toolbar_service.dart', () {
+    testWidgets('Test toolbar service in multi text selection', (tester) async {
+      const text = 'Welcome to Appflowy 😁';
+      final editor = tester.editor
+        ..insertTextNode(text)
+        ..insertTextNode(text)
+        ..insertTextNode(text);
+      await editor.startTesting();
+
+      final selection = Selection(
+        start: Position(path: [0], offset: 0),
+        end: Position(path: [1], offset: text.length),
+      );
+      await editor.updateSelection(selection);
+
+      expect(find.byType(ToolbarWidget), findsOneWidget);
+
+      // no link item
+      final item = defaultToolbarItems
+          .where((item) => item.id == 'appflowy.toolbar.link')
+          .first;
+      expect(find.byWidget(item.icon), findsNothing);
+    });
+  });
+}