* change toolbar and added export so developer can modify according to its need * revert some chages from examples * html to document convertion added * test added * code formated * node to html added image parameter * toolbar color and elevation added in editor stylee * code formated * remove duplicated exports * fix test improts and formating
429 lines
14 KiB
Dart
429 lines
14 KiB
Dart
import 'package:appflowy_editor/appflowy_editor.dart';
|
|
import 'package:appflowy_editor/src/render/toolbar/toolbar_item_widget.dart';
|
|
import 'package:appflowy_editor/src/render/toolbar/toolbar_widget.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import '../../infra/test_editor.dart';
|
|
|
|
void main() async {
|
|
setUpAll(() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
});
|
|
|
|
const singleLineText = "One Line Of Text";
|
|
|
|
group(
|
|
'toolbar, heading',
|
|
(() {
|
|
testWidgets('Select Text, Click toolbar and set style for h1 heading',
|
|
(tester) async {
|
|
final editor = tester.editor..insertTextNode(singleLineText);
|
|
await editor.startTesting();
|
|
|
|
final h1 = Selection(
|
|
start: Position(path: [0], offset: 0),
|
|
end: Position(path: [0], offset: singleLineText.length),
|
|
);
|
|
|
|
await editor.updateSelection(h1);
|
|
|
|
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
|
expect(find.byType(ToolbarWidget), findsOneWidget);
|
|
|
|
final h1Button = find.byWidgetPredicate((widget) {
|
|
if (widget is ToolbarItemWidget) {
|
|
return widget.item.id == 'appflowy.toolbar.h1';
|
|
}
|
|
return false;
|
|
});
|
|
|
|
expect(h1Button, findsOneWidget);
|
|
await tester.tap(h1Button);
|
|
await tester.pumpAndSettle();
|
|
|
|
final node = editor.nodeAtPath([0]) as TextNode;
|
|
expect(node.attributes.heading, 'h1');
|
|
});
|
|
|
|
testWidgets('Select Text, Click toolbar and set style for h2 heading',
|
|
(tester) async {
|
|
final editor = tester.editor..insertTextNode(singleLineText);
|
|
await editor.startTesting();
|
|
|
|
final h2 = Selection(
|
|
start: Position(path: [0], offset: 0),
|
|
end: Position(path: [0], offset: singleLineText.length),
|
|
);
|
|
|
|
await editor.updateSelection(h2);
|
|
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
|
expect(find.byType(ToolbarWidget), findsOneWidget);
|
|
|
|
final h2Button = find.byWidgetPredicate((widget) {
|
|
if (widget is ToolbarItemWidget) {
|
|
return widget.item.id == 'appflowy.toolbar.h2';
|
|
}
|
|
return false;
|
|
});
|
|
expect(h2Button, findsOneWidget);
|
|
await tester.tap(h2Button);
|
|
await tester.pumpAndSettle();
|
|
final node = editor.nodeAtPath([0]) as TextNode;
|
|
expect(node.attributes.heading, 'h2');
|
|
});
|
|
|
|
testWidgets('Select Text, Click toolbar and set style for h3 heading',
|
|
(tester) async {
|
|
final editor = tester.editor..insertTextNode(singleLineText);
|
|
await editor.startTesting();
|
|
|
|
final h3 = Selection(
|
|
start: Position(path: [0], offset: 0),
|
|
end: Position(path: [0], offset: singleLineText.length),
|
|
);
|
|
|
|
await editor.updateSelection(h3);
|
|
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
|
expect(find.byType(ToolbarWidget), findsOneWidget);
|
|
|
|
final h3Button = find.byWidgetPredicate((widget) {
|
|
if (widget is ToolbarItemWidget) {
|
|
return widget.item.id == 'appflowy.toolbar.h3';
|
|
}
|
|
return false;
|
|
});
|
|
expect(h3Button, findsOneWidget);
|
|
await tester.tap(h3Button);
|
|
await tester.pumpAndSettle();
|
|
final node = editor.nodeAtPath([0]) as TextNode;
|
|
expect(node.attributes.heading, 'h3');
|
|
});
|
|
}),
|
|
);
|
|
|
|
group(
|
|
'toolbar, underline',
|
|
(() {
|
|
testWidgets('Select text, click toolbar and set style for underline',
|
|
(tester) async {
|
|
final editor = tester.editor..insertTextNode(singleLineText);
|
|
await editor.startTesting();
|
|
|
|
final underline = Selection(
|
|
start: Position(path: [0], offset: 0),
|
|
end: Position(path: [0], offset: singleLineText.length),
|
|
);
|
|
|
|
await editor.updateSelection(underline);
|
|
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
|
expect(find.byType(ToolbarWidget), findsOneWidget);
|
|
final underlineButton = find.byWidgetPredicate((widget) {
|
|
if (widget is ToolbarItemWidget) {
|
|
return widget.item.id == 'appflowy.toolbar.underline';
|
|
}
|
|
return false;
|
|
});
|
|
|
|
expect(underlineButton, findsOneWidget);
|
|
await tester.tap(underlineButton);
|
|
await tester.pumpAndSettle();
|
|
final node = editor.nodeAtPath([0]) as TextNode;
|
|
// expect(node.attributes.underline, true);
|
|
expect(node.allSatisfyUnderlineInSelection(underline), true);
|
|
});
|
|
}),
|
|
);
|
|
|
|
group(
|
|
'toolbar, bold',
|
|
(() {
|
|
testWidgets('Select Text, Click Toolbar and set style for bold',
|
|
(tester) async {
|
|
final editor = tester.editor..insertTextNode(singleLineText);
|
|
await editor.startTesting();
|
|
|
|
final bold = Selection(
|
|
start: Position(path: [0], offset: 0),
|
|
end: Position(path: [0], offset: singleLineText.length),
|
|
);
|
|
|
|
await editor.updateSelection(bold);
|
|
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
|
expect(find.byType(ToolbarWidget), findsOneWidget);
|
|
final boldButton = find.byWidgetPredicate((widget) {
|
|
if (widget is ToolbarItemWidget) {
|
|
return widget.item.id == 'appflowy.toolbar.bold';
|
|
}
|
|
return false;
|
|
});
|
|
|
|
expect(boldButton, findsOneWidget);
|
|
await tester.tap(boldButton);
|
|
await tester.pumpAndSettle();
|
|
final node = editor.nodeAtPath([0]) as TextNode;
|
|
expect(node.allSatisfyBoldInSelection(bold), true);
|
|
});
|
|
}),
|
|
);
|
|
|
|
group(
|
|
'toolbar, italic',
|
|
(() {
|
|
testWidgets('Select Text, Click Toolbar and set style for italic',
|
|
(tester) async {
|
|
final editor = tester.editor..insertTextNode(singleLineText);
|
|
await editor.startTesting();
|
|
|
|
final italic = Selection(
|
|
start: Position(path: [0], offset: 0),
|
|
end: Position(path: [0], offset: singleLineText.length),
|
|
);
|
|
|
|
await editor.updateSelection(italic);
|
|
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
|
expect(find.byType(ToolbarWidget), findsOneWidget);
|
|
final italicButton = find.byWidgetPredicate((widget) {
|
|
if (widget is ToolbarItemWidget) {
|
|
return widget.item.id == 'appflowy.toolbar.italic';
|
|
}
|
|
return false;
|
|
});
|
|
|
|
expect(italicButton, findsOneWidget);
|
|
await tester.tap(italicButton);
|
|
await tester.pumpAndSettle();
|
|
final node = editor.nodeAtPath([0]) as TextNode;
|
|
expect(node.allSatisfyItalicInSelection(italic), true);
|
|
});
|
|
}),
|
|
);
|
|
|
|
group(
|
|
'toolbar, strikethrough',
|
|
(() {
|
|
testWidgets('Select Text, Click Toolbar and set style for strikethrough',
|
|
(tester) async {
|
|
final editor = tester.editor..insertTextNode(singleLineText);
|
|
await editor.startTesting();
|
|
|
|
final strikeThrough = Selection(
|
|
start: Position(path: [0], offset: 0),
|
|
end: Position(path: [0], offset: singleLineText.length),
|
|
);
|
|
|
|
await editor.updateSelection(strikeThrough);
|
|
|
|
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
|
expect(find.byType(ToolbarWidget), findsOneWidget);
|
|
final strikeThroughButton = find.byWidgetPredicate((widget) {
|
|
if (widget is ToolbarItemWidget) {
|
|
return widget.item.id == 'appflowy.toolbar.strikethrough';
|
|
}
|
|
return false;
|
|
});
|
|
|
|
expect(strikeThroughButton, findsOneWidget);
|
|
await tester.tap(strikeThroughButton);
|
|
await tester.pumpAndSettle();
|
|
final node = editor.nodeAtPath([0]) as TextNode;
|
|
expect(node.allSatisfyStrikethroughInSelection(strikeThrough), true);
|
|
});
|
|
}),
|
|
);
|
|
|
|
group(
|
|
'toolbar, code',
|
|
(() {
|
|
testWidgets('Select Text, Click Toolbar and set style for code',
|
|
(tester) async {
|
|
final editor = tester.editor..insertTextNode(singleLineText);
|
|
await editor.startTesting();
|
|
|
|
final code = Selection(
|
|
start: Position(path: [0], offset: 0),
|
|
end: Position(path: [0], offset: singleLineText.length),
|
|
);
|
|
|
|
await editor.updateSelection(code);
|
|
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
|
expect(find.byType(ToolbarWidget), findsOneWidget);
|
|
final codeButton = find.byWidgetPredicate((widget) {
|
|
if (widget is ToolbarItemWidget) {
|
|
return widget.item.id == 'appflowy.toolbar.code';
|
|
}
|
|
return false;
|
|
});
|
|
|
|
expect(codeButton, findsOneWidget);
|
|
await tester.tap(codeButton);
|
|
await tester.pumpAndSettle();
|
|
final node = editor.nodeAtPath([0]) as TextNode;
|
|
expect(
|
|
node.allSatisfyInSelection(
|
|
code,
|
|
BuiltInAttributeKey.code,
|
|
(value) => value == true,
|
|
),
|
|
true,
|
|
);
|
|
});
|
|
}),
|
|
);
|
|
|
|
group(
|
|
'toolbar, quote',
|
|
(() {
|
|
testWidgets('Select Text, Click Toolbar and set style for quote',
|
|
(tester) async {
|
|
final editor = tester.editor..insertTextNode(singleLineText);
|
|
await editor.startTesting();
|
|
|
|
final quote = Selection(
|
|
start: Position(path: [0], offset: 0),
|
|
end: Position(path: [0], offset: singleLineText.length),
|
|
);
|
|
|
|
await editor.updateSelection(quote);
|
|
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
|
expect(find.byType(ToolbarWidget), findsOneWidget);
|
|
final quoteButton = find.byWidgetPredicate((widget) {
|
|
if (widget is ToolbarItemWidget) {
|
|
return widget.item.id == 'appflowy.toolbar.quote';
|
|
}
|
|
return false;
|
|
});
|
|
expect(quoteButton, findsOneWidget);
|
|
await tester.tap(quoteButton);
|
|
await tester.pumpAndSettle();
|
|
final node = editor.nodeAtPath([0]) as TextNode;
|
|
expect(node.subtype, 'quote');
|
|
});
|
|
}),
|
|
);
|
|
|
|
group(
|
|
'toolbar, bullet list',
|
|
(() {
|
|
testWidgets('Select Text, Click Toolbar and set style for bullet',
|
|
(tester) async {
|
|
final editor = tester.editor..insertTextNode(singleLineText);
|
|
await editor.startTesting();
|
|
|
|
final bulletList = Selection(
|
|
start: Position(path: [0], offset: 0),
|
|
end: Position(path: [0], offset: singleLineText.length),
|
|
);
|
|
|
|
await editor.updateSelection(bulletList);
|
|
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
|
expect(find.byType(ToolbarWidget), findsOneWidget);
|
|
final bulletListButton = find.byWidgetPredicate((widget) {
|
|
if (widget is ToolbarItemWidget) {
|
|
return widget.item.id == 'appflowy.toolbar.bulleted_list';
|
|
}
|
|
return false;
|
|
});
|
|
|
|
expect(bulletListButton, findsOneWidget);
|
|
await tester.tap(bulletListButton);
|
|
await tester.pumpAndSettle();
|
|
final node = editor.nodeAtPath([0]) as TextNode;
|
|
expect(node.subtype, 'bulleted-list');
|
|
});
|
|
}),
|
|
);
|
|
|
|
group(
|
|
'toolbar, highlight',
|
|
(() {
|
|
testWidgets(
|
|
'Select Text, Click Toolbar and set style for highlighted text',
|
|
(tester) async {
|
|
// FIXME: Use a const value instead of the magic string.
|
|
const blue = '0x6000BCF0';
|
|
final editor = tester.editor..insertTextNode(singleLineText);
|
|
await editor.startTesting();
|
|
|
|
final node = editor.nodeAtPath([0]) as TextNode;
|
|
final selection = Selection(
|
|
start: Position(path: [0], offset: 0),
|
|
end: Position(path: [0], offset: singleLineText.length),
|
|
);
|
|
|
|
await editor.updateSelection(selection);
|
|
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
|
expect(find.byType(ToolbarWidget), findsOneWidget);
|
|
final highlightButton = find.byWidgetPredicate((widget) {
|
|
if (widget is ToolbarItemWidget) {
|
|
return widget.item.id == 'appflowy.toolbar.highlight';
|
|
}
|
|
return false;
|
|
});
|
|
expect(highlightButton, findsOneWidget);
|
|
await tester.tap(highlightButton);
|
|
await tester.pumpAndSettle();
|
|
expect(
|
|
node.allSatisfyInSelection(
|
|
selection,
|
|
BuiltInAttributeKey.backgroundColor,
|
|
(value) {
|
|
return value == blue;
|
|
},
|
|
),
|
|
true,
|
|
);
|
|
});
|
|
}),
|
|
);
|
|
|
|
group(
|
|
'toolbar, color picker',
|
|
(() {
|
|
testWidgets(
|
|
'Select Text, Click Toolbar and set color for the selected text',
|
|
(tester) async {
|
|
final editor = tester.editor..insertTextNode(singleLineText);
|
|
await editor.startTesting();
|
|
|
|
final node = editor.nodeAtPath([0]) as TextNode;
|
|
final selection = Selection(
|
|
start: Position(path: [0], offset: 0),
|
|
end: Position(path: [0], offset: singleLineText.length),
|
|
);
|
|
|
|
await editor.updateSelection(selection);
|
|
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
|
expect(find.byType(ToolbarWidget), findsOneWidget);
|
|
final colorButton = find.byWidgetPredicate((widget) {
|
|
if (widget is ToolbarItemWidget) {
|
|
return widget.item.id == 'appflowy.toolbar.color';
|
|
}
|
|
return false;
|
|
});
|
|
expect(colorButton, findsOneWidget);
|
|
await tester.tap(colorButton);
|
|
await tester.pumpAndSettle();
|
|
// select a yellow color
|
|
final yellowButton = find.text('Yellow');
|
|
await tester.tap(yellowButton);
|
|
await tester.pumpAndSettle();
|
|
expect(
|
|
node.allSatisfyInSelection(
|
|
selection,
|
|
BuiltInAttributeKey.color,
|
|
(value) {
|
|
return value == Colors.yellow.toHex();
|
|
},
|
|
),
|
|
true,
|
|
);
|
|
});
|
|
}),
|
|
);
|
|
}
|
|
|
|
extension on Color {
|
|
String toHex() {
|
|
return '0x${value.toRadixString(16)}';
|
|
}
|
|
}
|