Rich text editor for Flutter
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.
 
 
 
 
 

144 lines
4.3 KiB

import 'dart:convert' show jsonDecode;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_quill/flutter_quill.dart';
import 'package:flutter_quill_test/flutter_quill_test.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
late QuillController controller;
var didCopy = false;
setUp(() {
controller = QuillController.basic();
});
tearDown(() {
controller.dispose();
});
group('QuillEditor', () {
testWidgets('Keyboard entered text is stored in document', (tester) async {
await tester.pumpWidget(
MaterialApp(
home: QuillEditor.basic(
// ignore: avoid_redundant_argument_values
configurations: QuillEditorConfigurations(
controller: controller,
// ignore: avoid_redundant_argument_values
readOnly: false,
),
),
),
);
await tester.quillEnterText(find.byType(QuillEditor), 'test\n');
expect(controller.document.toPlainText(), 'test\n');
});
testWidgets('insertContent is handled correctly', (tester) async {
String? latestUri;
await tester.pumpWidget(
MaterialApp(
home: QuillEditor(
focusNode: FocusNode(),
scrollController: ScrollController(),
configurations: QuillEditorConfigurations(
controller: controller,
// ignore: avoid_redundant_argument_values
readOnly: false,
autoFocus: true,
expands: true,
contentInsertionConfiguration: ContentInsertionConfiguration(
onContentInserted: (content) {
latestUri = content.uri;
},
allowedMimeTypes: <String>['image/gif'],
),
),
),
),
);
await tester.tap(find.byType(QuillEditor));
await tester.quillEnterText(find.byType(QuillEditor), 'test\n');
await tester.idle();
const uri =
'content://com.google.android.inputmethod.latin.fileprovider/test.gif';
final messageBytes =
const JSONMessageCodec().encodeMessage(<String, dynamic>{
'args': <dynamic>[
-1,
'TextInputAction.commitContent',
jsonDecode(
'{"mimeType": "image/gif", "data": [0,1,0,1,0,1,0,0,0], "uri": "$uri"}'),
],
'method': 'TextInputClient.performAction',
});
Object? error;
try {
await tester.binding.defaultBinaryMessenger
.handlePlatformMessage('flutter/textinput', messageBytes, (_) {});
} catch (e) {
error = e;
}
expect(error, isNull);
expect(latestUri, equals(uri));
});
Widget customBuilder(BuildContext context, QuillRawEditorState state) {
return AdaptiveTextSelectionToolbar(
anchors: state.contextMenuAnchors,
children: [
Container(
height: 50,
color: Colors.white,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
IconButton(
onPressed: () {
didCopy = true;
},
icon: const Icon(Icons.copy),
),
],
),
),
],
);
}
testWidgets('custom context menu builder', (tester) async {
await tester.pumpWidget(
MaterialApp(
home: QuillEditor(
focusNode: FocusNode(),
scrollController: ScrollController(),
// ignore: avoid_redundant_argument_values
configurations: QuillEditorConfigurations(
controller: controller,
// ignore: avoid_redundant_argument_values
readOnly: false,
autoFocus: true,
expands: true,
contextMenuBuilder: customBuilder,
),
),
),
);
// Long press to show menu
await tester.longPress(find.byType(QuillEditor));
await tester.pumpAndSettle();
// Verify custom widget shows
expect(find.byIcon(Icons.copy), findsOneWidget);
await tester.tap(find.byIcon(Icons.copy));
expect(didCopy, isTrue);
});
});
}