From c008f3369cf532a07243aea54959d2dc5d5a591e Mon Sep 17 00:00:00 2001 From: "Lucas.Xu" Date: Mon, 15 Aug 2022 12:13:02 +0800 Subject: [PATCH] test: implement backspace key test for styled text --- .../example/test/widget_test.dart | 24 +---- .../delete_text_handler.dart | 4 +- .../flowy_editor/test/infra/test_editor.dart | 8 +- .../test/infra/test_raw_key_event.dart | 15 ++- .../delete_text_handler_test.dart | 97 +++++++++++++++++++ 5 files changed, 115 insertions(+), 33 deletions(-) create mode 100644 frontend/app_flowy/packages/flowy_editor/test/service/internal_key_event_handlers/delete_text_handler_test.dart diff --git a/frontend/app_flowy/packages/flowy_editor/example/test/widget_test.dart b/frontend/app_flowy/packages/flowy_editor/example/test/widget_test.dart index 092d222f7e..2a2b819285 100644 --- a/frontend/app_flowy/packages/flowy_editor/example/test/widget_test.dart +++ b/frontend/app_flowy/packages/flowy_editor/example/test/widget_test.dart @@ -5,26 +5,4 @@ // gestures. You can also use WidgetTester to find child widgets in the widget // tree, read text, and verify that the values of widget properties are correct. -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:example/main.dart'; - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -} +void main() {} diff --git a/frontend/app_flowy/packages/flowy_editor/lib/src/service/internal_key_event_handlers/delete_text_handler.dart b/frontend/app_flowy/packages/flowy_editor/lib/src/service/internal_key_event_handlers/delete_text_handler.dart index 92f5e9afb9..afef57cceb 100644 --- a/frontend/app_flowy/packages/flowy_editor/lib/src/service/internal_key_event_handlers/delete_text_handler.dart +++ b/frontend/app_flowy/packages/flowy_editor/lib/src/service/internal_key_event_handlers/delete_text_handler.dart @@ -72,7 +72,9 @@ KeyEventResult _handleBackspace(EditorState editorState, RawKeyEvent event) { _deleteNodes(transactionBuilder, textNodes, selection); } - transactionBuilder.commit(); + if (transactionBuilder.operations.isNotEmpty) { + transactionBuilder.commit(); + } return KeyEventResult.handled; } diff --git a/frontend/app_flowy/packages/flowy_editor/test/infra/test_editor.dart b/frontend/app_flowy/packages/flowy_editor/test/infra/test_editor.dart index 3f780412c4..b6aebeaa41 100644 --- a/frontend/app_flowy/packages/flowy_editor/test/infra/test_editor.dart +++ b/frontend/app_flowy/packages/flowy_editor/test/infra/test_editor.dart @@ -73,13 +73,7 @@ class EditorWidgetTester { } Future pressLogicKey(LogicalKeyboardKey key) async { - late RawKeyEvent testRawKeyEventData; - if (key == LogicalKeyboardKey.enter) { - testRawKeyEventData = const TestRawKeyEventData( - logicalKey: LogicalKeyboardKey.enter, - physicalKey: PhysicalKeyboardKey.enter, - ).toKeyEvent; - } + final testRawKeyEventData = TestRawKeyEventData(logicalKey: key).toKeyEvent; _editorState.service.keyboardService!.onKey(testRawKeyEventData); await tester.pumpAndSettle(); } diff --git a/frontend/app_flowy/packages/flowy_editor/test/infra/test_raw_key_event.dart b/frontend/app_flowy/packages/flowy_editor/test/infra/test_raw_key_event.dart index 2cb3fa0fd9..aa98781d7d 100644 --- a/frontend/app_flowy/packages/flowy_editor/test/infra/test_raw_key_event.dart +++ b/frontend/app_flowy/packages/flowy_editor/test/infra/test_raw_key_event.dart @@ -7,7 +7,6 @@ class TestRawKeyEvent extends RawKeyDownEvent { class TestRawKeyEventData extends RawKeyEventData { const TestRawKeyEventData({ required this.logicalKey, - required this.physicalKey, this.isControlPressed = false, this.isShiftPressed = false, this.isAltPressed = false, @@ -30,7 +29,7 @@ class TestRawKeyEventData extends RawKeyEventData { final LogicalKeyboardKey logicalKey; @override - final PhysicalKeyboardKey physicalKey; + PhysicalKeyboardKey get physicalKey => logicalKey.toPhysicalKey; @override KeyboardSide? getModifierSide(ModifierKey key) { @@ -50,3 +49,15 @@ class TestRawKeyEventData extends RawKeyEventData { return TestRawKeyEvent(data: this); } } + +extension on LogicalKeyboardKey { + PhysicalKeyboardKey get toPhysicalKey { + if (this == LogicalKeyboardKey.enter) { + return PhysicalKeyboardKey.enter; + } + if (this == LogicalKeyboardKey.backspace) { + return PhysicalKeyboardKey.backspace; + } + throw UnimplementedError(); + } +} diff --git a/frontend/app_flowy/packages/flowy_editor/test/service/internal_key_event_handlers/delete_text_handler_test.dart b/frontend/app_flowy/packages/flowy_editor/test/service/internal_key_event_handlers/delete_text_handler_test.dart new file mode 100644 index 0000000000..4a42ac2c47 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_editor/test/service/internal_key_event_handlers/delete_text_handler_test.dart @@ -0,0 +1,97 @@ +import 'package:flowy_editor/flowy_editor.dart'; +import 'package:flowy_editor/src/render/rich_text/rich_text_style.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('delete_text_handler.dart', () { + testWidgets('Presses backspace key in empty document', (tester) async { + // Before + // + // [Empty Line] + // + // After + // + // [Empty Line] + // + final editor = tester.editor..insertEmptyTextNode(); + await editor.startTesting(); + await editor.updateSelection( + Selection.single(path: [0], startOffset: 0), + ); + // Pressing the backspace key continuously. + for (int i = 1; i <= 1; i++) { + await editor.pressLogicKey( + LogicalKeyboardKey.backspace, + ); + expect(editor.documentLength, 1); + expect(editor.documentSelection, + Selection.single(path: [0], startOffset: 0)); + } + }); + }); + + // Before + // + // Welcome to Appflowy 😁 + // [Style] Welcome to Appflowy 😁 + // [Style] Welcome to Appflowy 😁 + // + // After + // + // Welcome to Appflowy 😁 + // [Style] Welcome to Appflowy 😁Welcome to Appflowy 😁 + // + testWidgets('Presses backspace key in styled text', (tester) async { + await _deleteStyledText(tester, StyleKey.checkbox); + }); +} + +Future _deleteStyledText(WidgetTester tester, String style) async { + const text = 'Welcome to Appflowy 😁'; + Attributes attributes = { + StyleKey.subtype: style, + }; + if (style == StyleKey.checkbox) { + attributes[StyleKey.checkbox] = true; + } else if (style == StyleKey.numberList) { + attributes[StyleKey.number] = 1; + } + final editor = tester.editor + ..insertTextNode(text) + ..insertTextNode(text, attributes: attributes) + ..insertTextNode(text, attributes: attributes); + + await editor.startTesting(); + await editor.updateSelection( + Selection.single(path: [2], startOffset: 0), + ); + await editor.pressLogicKey( + LogicalKeyboardKey.backspace, + ); + expect(editor.documentSelection, Selection.single(path: [2], startOffset: 0)); + + await editor.pressLogicKey( + LogicalKeyboardKey.backspace, + ); + expect(editor.documentLength, 2); + expect(editor.documentSelection, + Selection.single(path: [1], startOffset: text.length)); + expect(editor.nodeAtPath([1])?.subtype, style); + expect((editor.nodeAtPath([1]) as TextNode).toRawString(), text * 2); + + await editor.updateSelection( + Selection.single(path: [1], startOffset: 0), + ); + await editor.pressLogicKey( + LogicalKeyboardKey.backspace, + ); + expect(editor.documentLength, 2); + expect(editor.documentSelection, Selection.single(path: [1], startOffset: 0)); + expect(editor.nodeAtPath([1])?.subtype, null); +}