Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ class _EditorSelectionAndFocusPolicyState extends State<EditorSelectionAndFocusP
widget.editor.execute([
ChangeSelectionRequest(
restoredSelection,
SelectionChangeType.placeCaret,
restoredSelection.isCollapsed ? SelectionChangeType.placeCaret : SelectionChangeType.expandSelection,
SelectionReason.contentChange,
),
]);
Expand Down
115 changes: 113 additions & 2 deletions super_editor/test/super_editor/supereditor_focus_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,112 @@ void main() {
}, variant: inputAndGestureVariants);
});

group("restores selection after re-focus", () {
testWidgetsOnAllPlatforms("when selection is collapsed", (tester) async {
final focusNode = FocusNode();
await _pumpFocusChangeLayoutWithSingleParagraph(tester, editorFocusNode: focusNode);

// Place caret in the middle of a word.
await tester.placeCaretInParagraph('1', 8);
expect(
SuperEditorInspector.findDocumentSelection(),
const DocumentSelection.collapsed(
position: DocumentPosition(
nodeId: '1',
nodePosition: TextNodePosition(offset: 8),
),
),
);

// Focus the textfield.
await tester.tap(find.byType(TextField));
await tester.pumpAndSettle();

// Ensure selection was cleared.
expect(SuperEditorInspector.findDocumentSelection(), isNull);

// Focus the editor.
focusNode.requestFocus();
await tester.pumpAndSettle();

// Ensure selection was restored.
expect(
SuperEditorInspector.findDocumentSelection(),
const DocumentSelection.collapsed(
position: DocumentPosition(
nodeId: '1',
nodePosition: TextNodePosition(offset: 8),
),
),
);
});

testWidgetsOnAllPlatforms("when selection is expanded", (tester) async {
final editorFocusNode = FocusNode();
final testContext = await _pumpFocusChangeLayoutWithSingleParagraph(tester, editorFocusNode: editorFocusNode);

// Tap on editor to give it focus.
await tester.placeCaretInParagraph('1', 0);

// Select some text.
testContext.editor.execute([
const ChangeSelectionRequest(
DocumentSelection(
base: DocumentPosition(
nodeId: '1',
nodePosition: TextNodePosition(offset: 0),
),
extent: DocumentPosition(
nodeId: '1',
nodePosition: TextNodePosition(offset: 8),
),
),
SelectionChangeType.expandSelection,
SelectionReason.userInteraction,
),
]);
expect(
SuperEditorInspector.findDocumentSelection(),
const DocumentSelection(
base: DocumentPosition(
nodeId: '1',
nodePosition: TextNodePosition(offset: 0),
),
extent: DocumentPosition(
nodeId: '1',
nodePosition: TextNodePosition(offset: 8),
),
),
);

// Focus the textfield.
await tester.tap(find.byType(TextField));
await tester.pumpAndSettle();

// Ensure selection was cleared.
expect(SuperEditorInspector.findDocumentSelection(), isNull);

// Focus the editor.
editorFocusNode.requestFocus();
await tester.pumpAndSettle();

// Ensure selection was restored.
expect(
SuperEditorInspector.findDocumentSelection(),
const DocumentSelection(
base: DocumentPosition(
nodeId: '1',
nodePosition: TextNodePosition(offset: 0),
),
extent: DocumentPosition(
nodeId: '1',
nodePosition: TextNodePosition(offset: 8),
),
),
);
});
});

group("throws away stale selection after re-focus", () {
group("with caret", () {
testWidgetsOnAllPlatforms("when content type changes", (tester) async {
Expand Down Expand Up @@ -155,7 +261,7 @@ void main() {
nodePosition: TextNodePosition(offset: 8),
),
),
SelectionChangeType.placeCaret,
SelectionChangeType.expandSelection,
SelectionReason.userInteraction,
),
]);
Expand Down Expand Up @@ -219,7 +325,7 @@ void main() {
nodePosition: TextNodePosition(offset: 8),
),
),
SelectionChangeType.placeCaret,
SelectionChangeType.expandSelection,
SelectionReason.userInteraction,
),
]);
Expand Down Expand Up @@ -591,6 +697,11 @@ Future<TestDocumentContext> _pumpFocusChangeLayoutWithSingleParagraph(
.withSingleParagraph()
.withInputSource(TextInputSource.ime)
.withFocusNode(editorFocusNode)
// We include StableTagPlugin because its reaction checks the selection change type,
// and at one point (#2792) Super Editor was reporting "place caret" when restoring
// an expanded selection. This broke the plugin. So while we don't actually care about
// this plugin for this test suite, we want to ensure that it doesn't throw any exceptions.
.withPlugin(StableTagPlugin())
.withCustomWidgetTreeBuilder(
(superEditor) => MaterialApp(
home: Scaffold(
Expand Down