dartlangeditorflutterflutter-appsflutter-examplesflutter-packageflutter-widgetquillquill-deltaquilljsreactquillrich-textrich-text-editorwysiwygwysiwyg-editor
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
7.4 KiB
190 lines
7.4 KiB
import 'package:flutter/material.dart'; |
|
import 'package:flutter_quill/flutter_quill.dart'; |
|
import 'package:flutter_quill/quill_delta.dart'; |
|
import 'package:test/test.dart'; |
|
|
|
void main() { |
|
WidgetsFlutterBinding.ensureInitialized(); |
|
|
|
group('copy', () { |
|
const testDocumentContents = 'data'; |
|
late QuillController controller; |
|
|
|
setUp(() { |
|
controller = QuillController.basic() |
|
..compose(Delta()..insert(testDocumentContents), |
|
const TextSelection.collapsed(offset: 0), ChangeSource.local); |
|
}); |
|
|
|
test('clipboardSelection empty', () { |
|
expect(controller.clipboardSelection(true), false, |
|
reason: 'No effect when no selection'); |
|
expect(controller.clipboardSelection(false), false); |
|
}); |
|
|
|
test('clipboardSelection', () { |
|
controller |
|
..replaceText(0, 4, 'bold plain italic', null) |
|
..formatText(0, 4, Attribute.bold) |
|
..formatText(11, 17, Attribute.italic) |
|
..updateSelection(const TextSelection(baseOffset: 2, extentOffset: 14), |
|
ChangeSource.local); |
|
// |
|
expect(controller.clipboardSelection(true), true); |
|
expect(controller.document.length, 18, |
|
reason: 'Copy does not change the document'); |
|
expect(controller.clipboardSelection(false), true); |
|
expect(controller.document.length, 6, reason: 'Cut changes the document'); |
|
// |
|
controller |
|
..readOnly = true |
|
..updateSelection(const TextSelection(baseOffset: 2, extentOffset: 4), |
|
ChangeSource.local); |
|
expect(controller.selection.isCollapsed, false); |
|
expect(controller.clipboardSelection(true), true); |
|
expect(controller.document.length, 6); |
|
expect(controller.clipboardSelection(false), false); |
|
expect(controller.document.length, 6, |
|
reason: 'Cut not permitted on readOnly document'); |
|
}); |
|
}); |
|
|
|
group('paste', () { |
|
test('Plain', () async { |
|
final controller = QuillController.basic() |
|
..compose(Delta()..insert('[]'), |
|
const TextSelection.collapsed(offset: 0), ChangeSource.local) |
|
..updateSelection( |
|
const TextSelection.collapsed(offset: 1), ChangeSource.local); |
|
// |
|
expect(controller.document.toPlainText(), '[]\n'); |
|
expect(controller.pasteUsingPlainOrDelta('insert'), true); |
|
expect(controller.document.toPlainText(), '[insert]\n'); |
|
}); |
|
|
|
test('Plain lines', () async { |
|
final controller = QuillController.basic() |
|
..compose(Delta()..insert('[]'), |
|
const TextSelection.collapsed(offset: 0), ChangeSource.local) |
|
..updateSelection( |
|
const TextSelection.collapsed(offset: 1), ChangeSource.local); |
|
// |
|
expect(controller.document.toPlainText(), '[]\n'); |
|
expect(controller.pasteUsingPlainOrDelta('1\n2\n3\n'), true); |
|
expect(controller.document.toPlainText(), '[1\n2\n3\n]\n'); |
|
}); |
|
|
|
test('Paste from external', () async { |
|
final source = QuillController.basic() |
|
..compose(Delta()..insert('Plain text'), |
|
const TextSelection.collapsed(offset: 0), ChangeSource.local) |
|
..updateSelection(const TextSelection(baseOffset: 4, extentOffset: 8), |
|
ChangeSource.local); |
|
assert(source.clipboardSelection(true)); |
|
expect(source.pastePlainText, 'n te'); |
|
// |
|
final controller = QuillController.basic() |
|
..compose(Delta()..insert('[]'), |
|
const TextSelection.collapsed(offset: 0), ChangeSource.local) |
|
..updateSelection( |
|
const TextSelection.collapsed(offset: 1), ChangeSource.local); |
|
// |
|
expect(controller.pasteUsingPlainOrDelta('insert'), true, |
|
reason: 'External paste'); |
|
expect(controller.document.toPlainText(), '[insert]\n'); |
|
}); |
|
|
|
test('Delta simple', () async { |
|
final source = QuillController.basic() |
|
..compose(Delta()..insert('Plain text'), |
|
const TextSelection.collapsed(offset: 0), ChangeSource.local) |
|
..formatText(6, 8, Attribute.bold) |
|
..updateSelection(const TextSelection(baseOffset: 4, extentOffset: 8), |
|
ChangeSource.local); |
|
assert(source.clipboardSelection(true)); |
|
expect(source.pastePlainText, 'n te'); |
|
expect( |
|
source.pasteDelta, |
|
Delta() |
|
..insert('n ') |
|
..insert('te', {'bold': true})); |
|
// |
|
final controller = QuillController.basic() |
|
..compose(Delta()..insert('[]'), |
|
const TextSelection.collapsed(offset: 0), ChangeSource.local) |
|
..updateSelection( |
|
const TextSelection.collapsed(offset: 1), ChangeSource.local); |
|
// |
|
expect(controller.pasteUsingPlainOrDelta('n te'), true, |
|
reason: 'Internal paste'); |
|
expect(controller.document.toPlainText(), '[n te]\n'); |
|
expect( |
|
controller.document.toDelta(), |
|
Delta() |
|
..insert('[n ') |
|
..insert('te', {'bold': true}) |
|
..insert(']\n')); |
|
expect(controller.selection, const TextSelection.collapsed(offset: 5)); |
|
}); |
|
|
|
test('Delta multi line', () async { |
|
const blockAttribute = Attribute.ol; |
|
const plainSelection = 'BC\nDEF\nGHI\nJK'; |
|
final source = QuillController.basic() |
|
..compose(Delta()..insert('ABC\nDEF\nGHI\nJKL'), |
|
const TextSelection.collapsed(offset: 0), ChangeSource.local) |
|
..formatText(1, 1, Attribute.underline) // ABC with B underlined |
|
..formatText(4, 0, blockAttribute) // 1. DEF with E in italic |
|
..formatText(5, 1, Attribute.italic) |
|
..formatText(8, 0, blockAttribute) // 2. GHI with H as inline code |
|
..formatText(9, 1, Attribute.inlineCode) |
|
..formatText(13, 1, Attribute.strikeThrough) // JKL with K strikethrough |
|
..updateSelection(const TextSelection(baseOffset: 1, extentOffset: 14), |
|
ChangeSource.local); |
|
// |
|
assert(source.clipboardSelection(true)); |
|
expect(source.pastePlainText, plainSelection); |
|
expect( |
|
source.pasteDelta, |
|
Delta() |
|
..insert('B', {'underline': true}) |
|
..insert('C\nD') |
|
..insert('E', {'italic': true}) |
|
..insert('F') |
|
..insert('\n', {'list': 'ordered'}) |
|
..insert('G') |
|
..insert('H', {'code': true}) |
|
..insert('I') |
|
..insert('\n', {'list': 'ordered'}) |
|
..insert('J') |
|
..insert('K', {'strike': true})); |
|
// |
|
final controller = QuillController.basic() |
|
..compose(Delta()..insert('[]'), |
|
const TextSelection.collapsed(offset: 0), ChangeSource.local) |
|
..updateSelection( |
|
const TextSelection.collapsed(offset: 1), ChangeSource.local); |
|
// |
|
expect(controller.pasteUsingPlainOrDelta(plainSelection), true, |
|
reason: 'Internal paste'); |
|
expect(controller.document.toPlainText(), '[$plainSelection]\n'); |
|
expect( |
|
controller.document.toDelta(), |
|
Delta() |
|
..insert('[') |
|
..insert('B', {'underline': true}) |
|
..insert('C\nD') |
|
..insert('E', {'italic': true}) |
|
..insert('F') |
|
..insert('\n', {'list': 'ordered'}) |
|
..insert('G') |
|
..insert('H', {'code': true}) |
|
..insert('I') |
|
..insert('\n', {'list': 'ordered'}) |
|
..insert('J') |
|
..insert('K', {'strike': true}) |
|
..insert(']\n')); |
|
expect(controller.selection, const TextSelection.collapsed(offset: 14)); |
|
}); |
|
}); |
|
}
|
|
|