mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
test: implement simple redo/undo test for no-styled text
This commit is contained in:
parent
f5cc886b6e
commit
e926c89548
@ -28,10 +28,12 @@ List<String> defaultListToolbarEventNames = [
|
||||
'H1',
|
||||
'H2',
|
||||
'H3',
|
||||
// 'B-List',
|
||||
// 'N-List',
|
||||
];
|
||||
|
||||
mixin ToolBarMixin<T extends StatefulWidget> on State<T> {
|
||||
void hide();
|
||||
}
|
||||
|
||||
class ToolbarWidget extends StatefulWidget {
|
||||
const ToolbarWidget({
|
||||
Key? key,
|
||||
@ -50,7 +52,7 @@ class ToolbarWidget extends StatefulWidget {
|
||||
State<ToolbarWidget> createState() => _ToolbarWidgetState();
|
||||
}
|
||||
|
||||
class _ToolbarWidgetState extends State<ToolbarWidget> {
|
||||
class _ToolbarWidgetState extends State<ToolbarWidget> with ToolBarMixin {
|
||||
final GlobalKey _listToolbarKey = GlobalKey();
|
||||
|
||||
final toolbarHeight = 32.0;
|
||||
@ -63,21 +65,6 @@ class _ToolbarWidgetState extends State<ToolbarWidget> {
|
||||
|
||||
OverlayEntry? _listToolbarOverlay;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
widget.editorState.service.selectionService.currentSelection
|
||||
.addListener(_onSelectionChange);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
widget.editorState.service.selectionService.currentSelection
|
||||
.removeListener(_onSelectionChange);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Positioned(
|
||||
@ -92,6 +79,12 @@ class _ToolbarWidgetState extends State<ToolbarWidget> {
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void hide() {
|
||||
_listToolbarOverlay?.remove();
|
||||
_listToolbarOverlay = null;
|
||||
}
|
||||
|
||||
Widget _buildToolbar(BuildContext context) {
|
||||
return Material(
|
||||
borderRadius: BorderRadius.circular(cornerRadius),
|
||||
@ -212,9 +205,4 @@ class _ToolbarWidgetState extends State<ToolbarWidget> {
|
||||
}
|
||||
assert(false, 'Could not find the event handler for $eventName');
|
||||
}
|
||||
|
||||
void _onSelectionChange() {
|
||||
_listToolbarOverlay?.remove();
|
||||
_listToolbarOverlay = null;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flowy_editor/flowy_editor.dart';
|
||||
import 'package:flowy_editor/src/render/selection/toolbar_widget.dart';
|
||||
import 'package:flowy_editor/src/extensions/object_extensions.dart';
|
||||
|
||||
abstract class FlowyToolbarService {
|
||||
/// Show the toolbar widget beside the offset.
|
||||
@ -28,12 +29,15 @@ class FlowyToolbar extends StatefulWidget {
|
||||
class _FlowyToolbarState extends State<FlowyToolbar>
|
||||
implements FlowyToolbarService {
|
||||
OverlayEntry? _toolbarOverlay;
|
||||
final _toolbarWidgetKey = GlobalKey(debugLabel: '_toolbar_widget');
|
||||
|
||||
@override
|
||||
void showInOffset(Offset offset, LayerLink layerLink) {
|
||||
_toolbarOverlay?.remove();
|
||||
hide();
|
||||
|
||||
_toolbarOverlay = OverlayEntry(
|
||||
builder: (context) => ToolbarWidget(
|
||||
key: _toolbarWidgetKey,
|
||||
editorState: widget.editorState,
|
||||
layerLink: layerLink,
|
||||
offset: offset.translate(0, -37.0),
|
||||
@ -45,6 +49,7 @@ class _FlowyToolbarState extends State<FlowyToolbar>
|
||||
|
||||
@override
|
||||
void hide() {
|
||||
_toolbarWidgetKey.currentState?.unwrapOrNull<ToolBarMixin>()?.hide();
|
||||
_toolbarOverlay?.remove();
|
||||
_toolbarOverlay = null;
|
||||
}
|
||||
@ -55,4 +60,11 @@ class _FlowyToolbarState extends State<FlowyToolbar>
|
||||
child: widget.child,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
hide();
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
@ -72,8 +72,20 @@ class EditorWidgetTester {
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
Future<void> pressLogicKey(LogicalKeyboardKey key) async {
|
||||
final testRawKeyEventData = TestRawKeyEventData(logicalKey: key).toKeyEvent;
|
||||
Future<void> pressLogicKey(
|
||||
LogicalKeyboardKey key, {
|
||||
bool isControlPressed = false,
|
||||
bool isShiftPressed = false,
|
||||
bool isAltPressed = false,
|
||||
bool isMetaPressed = false,
|
||||
}) async {
|
||||
final testRawKeyEventData = TestRawKeyEventData(
|
||||
logicalKey: key,
|
||||
isControlPressed: isControlPressed,
|
||||
isShiftPressed: isShiftPressed,
|
||||
isAltPressed: isAltPressed,
|
||||
isMetaPressed: isMetaPressed,
|
||||
).toKeyEvent;
|
||||
_editorState.service.keyboardService!.onKey(testRawKeyEventData);
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
@ -1,7 +1,25 @@
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class TestRawKeyEvent extends RawKeyDownEvent {
|
||||
const TestRawKeyEvent({required super.data});
|
||||
const TestRawKeyEvent({
|
||||
required super.data,
|
||||
this.isControlPressed = false,
|
||||
this.isShiftPressed = false,
|
||||
this.isAltPressed = false,
|
||||
this.isMetaPressed = false,
|
||||
});
|
||||
|
||||
@override
|
||||
final bool isControlPressed;
|
||||
|
||||
@override
|
||||
final bool isShiftPressed;
|
||||
|
||||
@override
|
||||
final bool isAltPressed;
|
||||
|
||||
@override
|
||||
final bool isMetaPressed;
|
||||
}
|
||||
|
||||
class TestRawKeyEventData extends RawKeyEventData {
|
||||
@ -46,7 +64,13 @@ class TestRawKeyEventData extends RawKeyEventData {
|
||||
String get keyLabel => throw UnimplementedError();
|
||||
|
||||
RawKeyEvent get toKeyEvent {
|
||||
return TestRawKeyEvent(data: this);
|
||||
return TestRawKeyEvent(
|
||||
data: this,
|
||||
isAltPressed: isAltPressed,
|
||||
isControlPressed: isControlPressed,
|
||||
isMetaPressed: isMetaPressed,
|
||||
isShiftPressed: isShiftPressed,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,6 +91,9 @@ extension on LogicalKeyboardKey {
|
||||
if (this == LogicalKeyboardKey.pageUp) {
|
||||
return PhysicalKeyboardKey.pageUp;
|
||||
}
|
||||
if (this == LogicalKeyboardKey.keyZ) {
|
||||
return PhysicalKeyboardKey.keyZ;
|
||||
}
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,60 @@
|
||||
import 'package:flowy_editor/flowy_editor.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('redo_undo_handler_test.dart', () {
|
||||
// TODO: need to test more cases.
|
||||
testWidgets('Redo, Undo for backspace key, and selection is downward',
|
||||
(tester) async {
|
||||
await _testBackspaceUndoRedo(tester, true);
|
||||
});
|
||||
|
||||
testWidgets('Redo, Undo for backspace key, and selection is forward',
|
||||
(tester) async {
|
||||
await _testBackspaceUndoRedo(tester, false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _testBackspaceUndoRedo(
|
||||
WidgetTester tester, bool isDownwardSelection) async {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
final editor = tester.editor
|
||||
..insertTextNode(text)
|
||||
..insertTextNode(text)
|
||||
..insertTextNode(text);
|
||||
await editor.startTesting();
|
||||
|
||||
final start = Position(path: [0], offset: text.length);
|
||||
final end = Position(path: [1], offset: text.length);
|
||||
final selection = Selection(
|
||||
start: isDownwardSelection ? start : end,
|
||||
end: isDownwardSelection ? end : start,
|
||||
);
|
||||
await editor.updateSelection(selection);
|
||||
await editor.pressLogicKey(LogicalKeyboardKey.backspace);
|
||||
expect(editor.documentLength, 2);
|
||||
|
||||
await editor.pressLogicKey(
|
||||
LogicalKeyboardKey.keyZ,
|
||||
isMetaPressed: true,
|
||||
);
|
||||
|
||||
expect(editor.documentLength, 3);
|
||||
expect((editor.nodeAtPath([1]) as TextNode).toRawString(), text);
|
||||
expect(editor.documentSelection, selection);
|
||||
|
||||
await editor.pressLogicKey(
|
||||
LogicalKeyboardKey.keyZ,
|
||||
isMetaPressed: true,
|
||||
isShiftPressed: true,
|
||||
);
|
||||
|
||||
expect(editor.documentLength, 2);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user