test: implement update text style by command X test

This commit is contained in:
Lucas.Xu 2022-08-15 18:57:59 +08:00
parent c732f4e908
commit f762a78ac0
5 changed files with 177 additions and 34 deletions

View File

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

View File

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

View File

@ -91,12 +91,27 @@ extension on LogicalKeyboardKey {
if (this == LogicalKeyboardKey.pageUp) { if (this == LogicalKeyboardKey.pageUp) {
return PhysicalKeyboardKey.pageUp; return PhysicalKeyboardKey.pageUp;
} }
if (this == LogicalKeyboardKey.keyZ) { if (this == LogicalKeyboardKey.slash) {
return PhysicalKeyboardKey.keyZ; return PhysicalKeyboardKey.slash;
}
if (this == LogicalKeyboardKey.arrowDown) {
return PhysicalKeyboardKey.arrowDown;
} }
if (this == LogicalKeyboardKey.keyA) { if (this == LogicalKeyboardKey.keyA) {
return PhysicalKeyboardKey.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(); throw UnimplementedError();
} }
} }

View File

@ -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);
});
});
}

View File

@ -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);
}