Skip to content

Commit

Permalink
chore: sync latest tests from appflowy
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasXu0 committed Apr 6, 2023
1 parent 94025ab commit f55730d
Show file tree
Hide file tree
Showing 27 changed files with 597 additions and 229 deletions.
1 change: 0 additions & 1 deletion lib/appflowy_editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ export 'src/render/selection_menu/selection_menu_widget.dart';
export 'src/render/selection_menu/selection_menu_item_widget.dart';
export 'src/l10n/l10n.dart';
export 'src/render/style/plugin_styles.dart';
export 'src/render/style/editor_style.dart';
export 'src/plugins/markdown/encoder/delta_markdown_encoder.dart';
export 'src/plugins/markdown/encoder/document_markdown_encoder.dart';
export 'src/plugins/markdown/encoder/parser/node_parser.dart';
Expand Down
1 change: 0 additions & 1 deletion lib/src/render/toolbar/toolbar_item.dart
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,6 @@ void showLinkMenu(
},
onSubmitted: (text) async {
await editorState.formatLinkInText(
editorState,
text,
textNode: textNode,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ ShortcutEventHandler underscoreToItalicHandler = (editorState, event) {
return KeyEventResult.handled;
};

ShortcutEventHandler doubleAsteriskToBoldHanlder = (editorState, event) {
ShortcutEventHandler doubleAsteriskToBoldHandler = (editorState, event) {
final selectionService = editorState.service.selectionService;
final selection = selectionService.currentSelection.value;
final textNodes = selectionService.currentSelectedNodes.whereType<TextNode>();
Expand Down Expand Up @@ -367,7 +367,7 @@ ShortcutEventHandler doubleAsteriskToBoldHanlder = (editorState, event) {
};

//Implement in the same way as doubleAsteriskToBoldHanlder
ShortcutEventHandler doubleUnderscoreToBoldHanlder = (editorState, event) {
ShortcutEventHandler doubleUnderscoreToBoldHandler = (editorState, event) {
final selectionService = editorState.service.selectionService;
final selection = selectionService.currentSelection.value;
final textNodes = selectionService.currentSelectedNodes.whereType<TextNode>();
Expand Down
15 changes: 15 additions & 0 deletions lib/src/service/shortcut_event/built_in_shortcut_events.dart
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,21 @@ List<ShortcutEvent> builtInShortcutEvents = [
character: '_',
handler: doubleUnderscoreToBoldHandler,
),
ShortcutEvent(
key: 'Move cursor left one word',
command: 'alt+arrow left',
windowsCommand: 'alt+arrow left',
linuxCommand: 'alt+arrow left',
handler: cursorLeftWordMove,
),
ShortcutEvent(
key: 'Move cursor right one word',
command: 'alt+arrow right',
windowsCommand: 'alt+arrow right',
linuxCommand: 'alt+arrow right',
handler: cursorRightWordMove,
),

// https://github.com/flutter/flutter/issues/104944
// Workaround: Using space editing on the web platform often results in errors,
// so adding a shortcut event to handle the space input instead of using the
Expand Down
36 changes: 36 additions & 0 deletions test/command/command_extension_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter_test/flutter_test.dart';
import '../infra/test_editor.dart';

void main() {
group('command_extension.dart', () {
testWidgets('insert a new checkbox after an existing checkbox',
(tester) async {
final editor = tester.editor
..insertTextNode(
'Welcome',
)
..insertTextNode(
'to',
)
..insertTextNode(
'Appflowy 😁',
);
await editor.startTesting();
final selection = Selection(
start: Position(path: [2], offset: 5),
end: Position(path: [0], offset: 5),
);
await editor.updateSelection(selection);
final textNodes = editor
.editorState.service.selectionService.currentSelectedNodes
.whereType<TextNode>()
.toList(growable: false);
final texts = editor.editorState.getTextInSelection(
textNodes.normalized,
selection.normalized,
);
expect(texts, ['me', 'to', 'Appfl']);
});
});
}
24 changes: 24 additions & 0 deletions test/core/document/node_iterator_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,29 @@ void main() async {
}
expect(nodes.moveNext(), false);
});

test('toList - when we have at least three level nested nodes (children)',
() {
final root = Node(type: 'root'),
n1 = Node(type: 'node_1'),
n2 = Node(type: 'node_2');

root.insert(n1);
root.insert(n2);
n1.insert(Node(type: 'node_1_1'));
n1.insert(Node(type: 'node_1_2'));
n1.childAtIndex(0)?.insert(Node(type: 'node_1_1_1'));
n1.childAtIndex(1)?.insert(Node(type: 'node_1_2_1'));

final nodes = NodeIterator(
document: Document(root: root),
startNode: root.childAtPath([0])!,
endNode: root.childAtPath([1]),
).toList();

expect(nodes[0].id, n1.id);
expect(nodes[1].id, n1.childAtIndex(0)!.id);
expect(nodes[nodes.length - 1].id, n2.id);
});
});
}
4 changes: 0 additions & 4 deletions test/core/transform/operation_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,5 @@ void main() async {
expect(op.invert().invert(), op);
expect(op.copyWith(), op);
});

test('Operation.fromJson throws', () {
expect(() => Operation.fromJson(), throwsA(isA<UnimplementedError>()));
});
});
}
206 changes: 206 additions & 0 deletions test/core/transform/transaction_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter_test/flutter_test.dart';
import '../../infra/test_editor.dart';

Document createEmptyDocument() {
return Document(
root: Node(
type: 'editor',
),
);
}

void main() async {
group('transaction.dart', () {
testWidgets('test replaceTexts, textNodes.length == texts.length',
(tester) async {
TestWidgetsFlutterBinding.ensureInitialized();

final editor = tester.editor
..insertTextNode('0123456789')
..insertTextNode('0123456789')
..insertTextNode('0123456789')
..insertTextNode('0123456789');
await editor.startTesting();
await tester.pumpAndSettle();

expect(editor.documentLength, 4);

final selection = Selection(
start: Position(path: [0], offset: 4),
end: Position(path: [3], offset: 4),
);
final transaction = editor.editorState.transaction;
var textNodes = [0, 1, 2, 3]
.map((e) => editor.nodeAtPath([e])!)
.whereType<TextNode>()
.toList(growable: false);
final texts = ['ABC', 'ABC', 'ABC', 'ABC'];
transaction.replaceTexts(textNodes, selection, texts);
editor.editorState.apply(transaction);
await tester.pumpAndSettle();

expect(editor.documentLength, 4);
textNodes = [0, 1, 2, 3]
.map((e) => editor.nodeAtPath([e])!)
.whereType<TextNode>()
.toList(growable: false);
expect(textNodes[0].toPlainText(), '0123ABC');
expect(textNodes[1].toPlainText(), 'ABC');
expect(textNodes[2].toPlainText(), 'ABC');
expect(textNodes[3].toPlainText(), 'ABC456789');
});

testWidgets('test replaceTexts, textNodes.length > texts.length',
(tester) async {
TestWidgetsFlutterBinding.ensureInitialized();

final editor = tester.editor
..insertTextNode('0123456789')
..insertTextNode('0123456789')
..insertTextNode('0123456789')
..insertTextNode('0123456789')
..insertTextNode('0123456789');
await editor.startTesting();
await tester.pumpAndSettle();

expect(editor.documentLength, 5);

final selection = Selection(
start: Position(path: [0], offset: 4),
end: Position(path: [4], offset: 4),
);
final transaction = editor.editorState.transaction;
var textNodes = [0, 1, 2, 3, 4]
.map((e) => editor.nodeAtPath([e])!)
.whereType<TextNode>()
.toList(growable: false);
final texts = ['ABC', 'ABC', 'ABC', 'ABC'];
transaction.replaceTexts(textNodes, selection, texts);
editor.editorState.apply(transaction);
await tester.pumpAndSettle();

expect(editor.documentLength, 4);
textNodes = [0, 1, 2, 3]
.map((e) => editor.nodeAtPath([e])!)
.whereType<TextNode>()
.toList(growable: false);
expect(textNodes[0].toPlainText(), '0123ABC');
expect(textNodes[1].toPlainText(), 'ABC');
expect(textNodes[2].toPlainText(), 'ABC');
expect(textNodes[3].toPlainText(), 'ABC456789');
});

testWidgets('test replaceTexts, textNodes.length >> texts.length',
(tester) async {
TestWidgetsFlutterBinding.ensureInitialized();

final editor = tester.editor
..insertTextNode('0123456789')
..insertTextNode('0123456789')
..insertTextNode('0123456789')
..insertTextNode('0123456789')
..insertTextNode('0123456789');
await editor.startTesting();
await tester.pumpAndSettle();

expect(editor.documentLength, 5);

final selection = Selection(
start: Position(path: [0], offset: 4),
end: Position(path: [4], offset: 4),
);
final transaction = editor.editorState.transaction;
var textNodes = [0, 1, 2, 3, 4]
.map((e) => editor.nodeAtPath([e])!)
.whereType<TextNode>()
.toList(growable: false);
final texts = ['ABC'];
transaction.replaceTexts(textNodes, selection, texts);
editor.editorState.apply(transaction);
await tester.pumpAndSettle();

expect(editor.documentLength, 1);
textNodes = [0]
.map((e) => editor.nodeAtPath([e])!)
.whereType<TextNode>()
.toList(growable: false);
expect(textNodes[0].toPlainText(), '0123ABC456789');
});

testWidgets('test replaceTexts, textNodes.length < texts.length',
(tester) async {
TestWidgetsFlutterBinding.ensureInitialized();

final editor = tester.editor
..insertTextNode('0123456789')
..insertTextNode('0123456789')
..insertTextNode('0123456789');
await editor.startTesting();
await tester.pumpAndSettle();

expect(editor.documentLength, 3);

final selection = Selection(
start: Position(path: [0], offset: 4),
end: Position(path: [2], offset: 4),
);
final transaction = editor.editorState.transaction;
var textNodes = [0, 1, 2]
.map((e) => editor.nodeAtPath([e])!)
.whereType<TextNode>()
.toList(growable: false);
final texts = ['ABC', 'ABC', 'ABC', 'ABC'];
transaction.replaceTexts(textNodes, selection, texts);
editor.editorState.apply(transaction);
await tester.pumpAndSettle();

expect(editor.documentLength, 4);
textNodes = [0, 1, 2, 3]
.map((e) => editor.nodeAtPath([e])!)
.whereType<TextNode>()
.toList(growable: false);
expect(textNodes[0].toPlainText(), '0123ABC');
expect(textNodes[1].toPlainText(), 'ABC');
expect(textNodes[2].toPlainText(), 'ABC');
expect(textNodes[3].toPlainText(), 'ABC456789');
});

testWidgets('test replaceTexts, textNodes.length << texts.length',
(tester) async {
TestWidgetsFlutterBinding.ensureInitialized();

final editor = tester.editor..insertTextNode('Welcome to AppFlowy!');
await editor.startTesting();
await tester.pumpAndSettle();

expect(editor.documentLength, 1);

// select 'to'
final selection = Selection(
start: Position(path: [0], offset: 8),
end: Position(path: [0], offset: 10),
);
final transaction = editor.editorState.transaction;
var textNodes = [0]
.map((e) => editor.nodeAtPath([e])!)
.whereType<TextNode>()
.toList(growable: false);
final texts = ['ABC1', 'ABC2', 'ABC3', 'ABC4', 'ABC5'];
transaction.replaceTexts(textNodes, selection, texts);
editor.editorState.apply(transaction);
await tester.pumpAndSettle();

expect(editor.documentLength, 5);
textNodes = [0, 1, 2, 3, 4]
.map((e) => editor.nodeAtPath([e])!)
.whereType<TextNode>()
.toList(growable: false);
expect(textNodes[0].toPlainText(), 'Welcome ABC1');
expect(textNodes[1].toPlainText(), 'ABC2');
expect(textNodes[2].toPlainText(), 'ABC3');
expect(textNodes[3].toPlainText(), 'ABC4');
expect(textNodes[4].toPlainText(), 'ABC5 AppFlowy!');
});
});
}
11 changes: 7 additions & 4 deletions test/infra/test_editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,9 @@ class EditorWidgetTester {
await tester.pumpAndSettle();
}

Future<void> pressLogicKey(
LogicalKeyboardKey key, {
Future<void> pressLogicKey({
String? character,
LogicalKeyboardKey? key,
bool isControlPressed = false,
bool isShiftPressed = false,
bool isAltPressed = false,
Expand All @@ -134,11 +135,13 @@ class EditorWidgetTester {
if (!isControlPressed &&
!isShiftPressed &&
!isAltPressed &&
!isMetaPressed) {
!isMetaPressed &&
key != null) {
await tester.sendKeyDownEvent(key);
} else {
final testRawKeyEventData = TestRawKeyEventData(
logicalKey: key,
logicalKey: key ?? LogicalKeyboardKey.nonConvert,
character: character,
isControlPressed: isControlPressed,
isShiftPressed: isShiftPressed,
isAltPressed: isAltPressed,
Expand Down
Loading

0 comments on commit f55730d

Please sign in to comment.