feat: mobile tool bar basic features (#161)
* refactor: refactor mobile toolbar * feat: add text decoration icon in AFMobileIcons * chore: update mobile parameter * feat: add text decoration basic feature * chore: replace text by AppFlowyEditorLocalizations * feat: add code toolbar item * chore: refactor code - add hasMenu in MToolbarItem - add const size * feat: add line input menu * chore: create toolbar items draft file * refactor: textDecorationMToolbarItem refactor * fix: add key to ensures MToolbarWidget is rebuilt whenever the selection changes * feat: add link toolbar item and the way to close item menu * chore: replace m by mobile * chore:replace BuiltInAttributeKey by FlowyRichTextKeys * chore: replace m by mobile * refactor: refactor MobileToolbarWidget * refactor: add MobileToolbarStyle to control all cosmetic parameters * refactor: refactor MobileToolbarItemMenuBtn to stateless widget * feat: add heading menu * fix: fix open the wrong menu * feat: add heading icon * feat: add todo list and list toolbar item * feat: add quote toolbar item * fix: fix selection service error * test: add mobile toolbar basic elements test * test: add item menu button test and helper widgets * test: add text decoration mobile toolbar item test * test: add code mobile toolbar item test * test: add heading mobile toolbar item test * test: add list mobile toolbar item test * chore: fix typo * test: add quote mobile toolbar item test * test: add todo list mobile toolbar item test * test: add link mobile toolbar item test * chore: update name and add Material widget * fix: flutter analyze * fix: flutter analyze in test mobile toolbar * chore: dart format test code * refactor: improve code * fix: fix refactor error * chore: move all the tests in mobile to test/mobile * chore: move toolbar/items to toolbar/desktop/items * chore: remove the mobileToolbarItemMenuStateKey * chore: add some comments * test: update testing --------- Co-authored-by: Lucas.Xu <lucas.xu@appflowy.io>
This commit is contained in:
parent
c0dbd025e0
commit
6a4a8ae818
13 changed files with 1574 additions and 125 deletions
27
test/mobile/toolbar/mobile/mobile_toolbar_item_test.dart
Normal file
27
test/mobile/toolbar/mobile/mobile_toolbar_item_test.dart
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
void main() {
|
||||
group('MobileToolbarItem', () {
|
||||
test('action item should not have a menu', () {
|
||||
final item = MobileToolbarItem.action(
|
||||
itemIcon: const Icon(Icons.format_bold),
|
||||
actionHandler: (editorState, selection) {},
|
||||
);
|
||||
|
||||
expect(item.hasMenu, false);
|
||||
});
|
||||
|
||||
test('menu item should have a menu', () {
|
||||
final item = MobileToolbarItem.withMenu(
|
||||
itemIcon: const Icon(Icons.format_color_text),
|
||||
itemMenuBuilder: (editorState, selection, _) {
|
||||
return Container();
|
||||
},
|
||||
);
|
||||
|
||||
expect(item.hasMenu, true);
|
||||
});
|
||||
});
|
||||
}
|
||||
37
test/mobile/toolbar/mobile/mobile_toolbar_style_test.dart
Normal file
37
test/mobile/toolbar/mobile/mobile_toolbar_style_test.dart
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:appflowy_editor/src/editor/toolbar/mobile/mobile_toolbar_style.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('MobileToolbarStyle should have correct values',
|
||||
(WidgetTester tester) async {
|
||||
const backgroundColor = Colors.white;
|
||||
const foregroundColor = Colors.black;
|
||||
const itemHighlightColor = Colors.blue;
|
||||
const itemOutlineColor = Colors.grey;
|
||||
const toolbarHeight = 50.0;
|
||||
const borderRadius = 10.0;
|
||||
|
||||
await tester.pumpWidget(
|
||||
const MobileToolbarStyle(
|
||||
backgroundColor: backgroundColor,
|
||||
foregroundColor: foregroundColor,
|
||||
itemHighlightColor: itemHighlightColor,
|
||||
itemOutlineColor: itemOutlineColor,
|
||||
toolbarHeight: toolbarHeight,
|
||||
borderRadius: borderRadius,
|
||||
child: SizedBox(),
|
||||
),
|
||||
);
|
||||
|
||||
final mobileToolbarStyle =
|
||||
MobileToolbarStyle.of(tester.element(find.byType(MobileToolbarStyle)));
|
||||
|
||||
expect(mobileToolbarStyle.backgroundColor, equals(backgroundColor));
|
||||
expect(mobileToolbarStyle.foregroundColor, equals(foregroundColor));
|
||||
expect(mobileToolbarStyle.itemHighlightColor, equals(itemHighlightColor));
|
||||
expect(mobileToolbarStyle.itemOutlineColor, equals(itemOutlineColor));
|
||||
expect(mobileToolbarStyle.toolbarHeight, equals(toolbarHeight));
|
||||
expect(mobileToolbarStyle.borderRadius, equals(borderRadius));
|
||||
});
|
||||
}
|
||||
53
test/mobile/toolbar/mobile/mobile_toolbar_test.dart
Normal file
53
test/mobile/toolbar/mobile/mobile_toolbar_test.dart
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import '../../../new/infra/testable_editor.dart';
|
||||
import 'test_helpers/mobile_app_with_toolbar_widget.dart';
|
||||
|
||||
void main() {
|
||||
setUpAll(() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
});
|
||||
group('MobileToolbar', () {
|
||||
testWidgets('return SizeBox when it is no selection', (tester) async {
|
||||
final editor = tester.editor;
|
||||
await editor.startTesting();
|
||||
|
||||
final toolbarItems = [
|
||||
textDecorationMobileToolbarItem,
|
||||
linkMobileToolbarItem,
|
||||
];
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: MobileToolbar(
|
||||
editorState: editor.editorState,
|
||||
toolbarItems: toolbarItems,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.byType(SizedBox), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('show MobileToolbarWidget when some text is selected ',
|
||||
(tester) async {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
final editor = tester.editor..addParagraphs(3, initialText: text);
|
||||
await editor.startTesting();
|
||||
|
||||
var selection = Selection.single(
|
||||
path: [1],
|
||||
startOffset: 2,
|
||||
endOffset: text.length - 2,
|
||||
);
|
||||
await editor.updateSelection(selection);
|
||||
|
||||
await tester.pumpWidget(
|
||||
MobileAppWithToolbarWidget(editorState: editor.editorState),
|
||||
);
|
||||
|
||||
expect(find.byType(MobileToolbarWidget), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
|
||||
/// Used in testing mobile app with toolbar
|
||||
class MobileAppWithToolbarWidget extends StatelessWidget {
|
||||
const MobileAppWithToolbarWidget({
|
||||
required this.editorState,
|
||||
this.toolbarItems,
|
||||
super.key,
|
||||
});
|
||||
final EditorState editorState;
|
||||
final List<MobileToolbarItem>? toolbarItems;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scrollController = ScrollController();
|
||||
final localToolbarItems = toolbarItems ??
|
||||
[
|
||||
textDecorationMobileToolbarItem,
|
||||
headingMobileToolbarItem,
|
||||
todoListMobileToolbarItem,
|
||||
listMobileToolbarItem,
|
||||
linkMobileToolbarItem,
|
||||
quoteMobileToolbarItem,
|
||||
codeMobileToolbarItem,
|
||||
];
|
||||
return MaterialApp(
|
||||
home: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: AppFlowyEditor.standard(
|
||||
editorStyle: const EditorStyle.mobile(),
|
||||
editorState: editorState,
|
||||
scrollController: scrollController,
|
||||
),
|
||||
),
|
||||
MobileToolbar(
|
||||
editorState: editorState,
|
||||
toolbarItems: localToolbarItems,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
|
||||
/// Used in testing mobile app with toolbar
|
||||
class MobileToolbarStyleTestWidget extends StatelessWidget {
|
||||
const MobileToolbarStyleTestWidget({
|
||||
required this.child,
|
||||
super.key,
|
||||
this.backgroundColor = Colors.white,
|
||||
this.foregroundColor = Colors.black,
|
||||
this.itemHighlightColor = Colors.blue,
|
||||
this.itemOutlineColor = Colors.grey,
|
||||
this.toolbarHeight = 50.0,
|
||||
this.borderRadius = 10.0,
|
||||
});
|
||||
final Widget child;
|
||||
|
||||
final Color backgroundColor;
|
||||
final Color foregroundColor;
|
||||
final Color itemHighlightColor;
|
||||
final Color itemOutlineColor;
|
||||
final double toolbarHeight;
|
||||
final double borderRadius;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
home: MobileToolbarStyle(
|
||||
backgroundColor: backgroundColor,
|
||||
foregroundColor: foregroundColor,
|
||||
itemHighlightColor: itemHighlightColor,
|
||||
itemOutlineColor: itemOutlineColor,
|
||||
toolbarHeight: toolbarHeight,
|
||||
borderRadius: borderRadius,
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import '../../../../new/infra/testable_editor.dart';
|
||||
import '../test_helpers/mobile_app_with_toolbar_widget.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('codeMobileToolbarItem', (WidgetTester tester) async {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
final editor = tester.editor..addParagraphs(3, initialText: text);
|
||||
await editor.startTesting();
|
||||
|
||||
var selection = Selection.single(
|
||||
path: [1],
|
||||
startOffset: 2,
|
||||
endOffset: text.length - 2,
|
||||
);
|
||||
|
||||
await editor.updateSelection(selection);
|
||||
await tester.pumpWidget(
|
||||
MobileAppWithToolbarWidget(
|
||||
editorState: editor.editorState,
|
||||
toolbarItems: [
|
||||
codeMobileToolbarItem,
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
// Tap code toolbar item
|
||||
final codeBtn = find.byType(IconButton).first;
|
||||
await tester.tap(codeBtn);
|
||||
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
||||
// Check if the text becomes code format
|
||||
final node = editor.editorState.getNodeAtPath([1]);
|
||||
expect(
|
||||
node?.allSatisfyInSelection(selection, (delta) {
|
||||
return delta.whereType<TextInsert>().every(
|
||||
(element) => element.attributes?[FlowyRichTextKeys.code] == true,
|
||||
);
|
||||
}),
|
||||
true,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import '../../../../new/infra/testable_editor.dart';
|
||||
import '../test_helpers/mobile_app_with_toolbar_widget.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('headingMobileToolbarItem', (WidgetTester tester) async {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
final editor = tester.editor..addParagraphs(3, initialText: text);
|
||||
await editor.startTesting();
|
||||
|
||||
var selection = Selection.single(
|
||||
path: [1],
|
||||
startOffset: 2,
|
||||
endOffset: text.length - 2,
|
||||
);
|
||||
|
||||
await editor.updateSelection(selection);
|
||||
await tester.pumpWidget(
|
||||
MobileAppWithToolbarWidget(
|
||||
editorState: editor.editorState,
|
||||
toolbarItems: [
|
||||
headingMobileToolbarItem,
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
// Tap text decoration toolbar item
|
||||
await tester.tap(find.byType(IconButton).first);
|
||||
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
||||
|
||||
// Show its menu and it has 3 buttons
|
||||
expect(find.byType(MobileToolbarItemMenu), findsOneWidget);
|
||||
expect(find.text('Heading 1'), findsOneWidget);
|
||||
expect(find.text('Heading 2'), findsOneWidget);
|
||||
expect(find.text('Heading 3'), findsOneWidget);
|
||||
|
||||
// Test Heading 1 button
|
||||
await tester
|
||||
.tap(find.widgetWithText(MobileToolbarItemMenuBtn, 'Heading 1'));
|
||||
var node = editor.editorState.getNodeAtPath([1]);
|
||||
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
||||
expect(
|
||||
node?.type == 'heading' && node?.attributes['level'] == 1,
|
||||
true,
|
||||
);
|
||||
|
||||
// Test Heading 2 button
|
||||
await tester
|
||||
.tap(find.widgetWithText(MobileToolbarItemMenuBtn, 'Heading 2'));
|
||||
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
||||
//Get updated node
|
||||
node = editor.editorState.getNodeAtPath([1]);
|
||||
expect(
|
||||
node?.type == 'heading' && node?.attributes['level'] == 2,
|
||||
true,
|
||||
);
|
||||
|
||||
// Test Heading 3 button
|
||||
await tester
|
||||
.tap(find.widgetWithText(MobileToolbarItemMenuBtn, 'Heading 3'));
|
||||
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
||||
//Get updated node
|
||||
node = editor.editorState.getNodeAtPath([1]);
|
||||
expect(
|
||||
node?.type == 'heading' && node?.attributes['level'] == 3,
|
||||
true,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import '../../../../new/infra/testable_editor.dart';
|
||||
import '../test_helpers/mobile_app_with_toolbar_widget.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('linkMobileToolbarItem', (WidgetTester tester) async {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
final editor = tester.editor..addParagraphs(3, initialText: text);
|
||||
await editor.startTesting();
|
||||
|
||||
var selection = Selection.single(
|
||||
path: [1],
|
||||
startOffset: 2,
|
||||
endOffset: text.length - 2,
|
||||
);
|
||||
|
||||
await editor.updateSelection(selection);
|
||||
await tester.pumpWidget(
|
||||
MobileAppWithToolbarWidget(
|
||||
editorState: editor.editorState,
|
||||
toolbarItems: [
|
||||
linkMobileToolbarItem,
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
// Tap link toolbar item
|
||||
await tester.tap(find.byType(IconButton).first);
|
||||
await tester.pumpAndSettle();
|
||||
// Show its menu
|
||||
expect(find.byType(MobileToolbarItemMenu), findsOneWidget);
|
||||
|
||||
// Enter link address
|
||||
const linkAddress = 'www.google.com';
|
||||
final textField = find.byType(TextField);
|
||||
await tester.enterText(textField, linkAddress);
|
||||
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
||||
await tester.testTextInput.receiveAction(TextInputAction.done);
|
||||
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
||||
|
||||
// Check if the text becomes a link
|
||||
final node = editor.editorState.getNodeAtPath([1]);
|
||||
expect(
|
||||
node?.allSatisfyInSelection(selection, (delta) {
|
||||
return delta.whereType<TextInsert>().every(
|
||||
(element) =>
|
||||
element.attributes?[FlowyRichTextKeys.href] == linkAddress,
|
||||
);
|
||||
}),
|
||||
true,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import '../../../../new/infra/testable_editor.dart';
|
||||
import '../test_helpers/mobile_app_with_toolbar_widget.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('listMobileToolbarItem', (WidgetTester tester) async {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
final editor = tester.editor..addParagraphs(3, initialText: text);
|
||||
await editor.startTesting();
|
||||
|
||||
var selection = Selection.single(
|
||||
path: [1],
|
||||
startOffset: 2,
|
||||
endOffset: text.length - 2,
|
||||
);
|
||||
|
||||
await editor.updateSelection(selection);
|
||||
await tester.pumpWidget(
|
||||
MobileAppWithToolbarWidget(
|
||||
editorState: editor.editorState,
|
||||
toolbarItems: [
|
||||
listMobileToolbarItem,
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
// Tap text decoration toolbar item
|
||||
await tester.tap(find.byType(IconButton).first);
|
||||
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
||||
|
||||
// Show its menu and it has 2 buttons
|
||||
expect(find.byType(MobileToolbarItemMenu), findsOneWidget);
|
||||
expect(find.text('Bulleted List'), findsOneWidget);
|
||||
expect(find.text('Numbered List'), findsOneWidget);
|
||||
|
||||
// Test Bulleted List button
|
||||
await tester
|
||||
.tap(find.widgetWithText(MobileToolbarItemMenuBtn, 'Bulleted List'));
|
||||
var node = editor.editorState.getNodeAtPath([1]);
|
||||
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
||||
expect(
|
||||
node?.type == 'bulleted_list',
|
||||
true,
|
||||
);
|
||||
|
||||
// Test Numbered List button
|
||||
await tester
|
||||
.tap(find.widgetWithText(MobileToolbarItemMenuBtn, 'Numbered List'));
|
||||
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
||||
//Get updated node
|
||||
node = editor.editorState.getNodeAtPath([1]);
|
||||
expect(
|
||||
node?.type == 'numbered_list',
|
||||
true,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import '../../../../new/infra/testable_editor.dart';
|
||||
import '../test_helpers/mobile_app_with_toolbar_widget.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('quoteMobileToolbarItem', (WidgetTester tester) async {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
final editor = tester.editor..addParagraphs(3, initialText: text);
|
||||
await editor.startTesting();
|
||||
|
||||
var selection = Selection.single(
|
||||
path: [1],
|
||||
startOffset: 2,
|
||||
endOffset: text.length - 2,
|
||||
);
|
||||
|
||||
await editor.updateSelection(selection);
|
||||
await tester.pumpWidget(
|
||||
MobileAppWithToolbarWidget(
|
||||
editorState: editor.editorState,
|
||||
toolbarItems: [
|
||||
quoteMobileToolbarItem,
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
// Tap quote toolbar item
|
||||
final quoteBtn = find.byType(IconButton).first;
|
||||
await tester.tap(quoteBtn);
|
||||
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
||||
// Check if the text becomes quote node
|
||||
final node = editor.editorState.getNodeAtPath([1]);
|
||||
expect(
|
||||
node?.type == 'quote',
|
||||
true,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import '../../../../new/infra/testable_editor.dart';
|
||||
import '../test_helpers/mobile_app_with_toolbar_widget.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('textDecorationMobileToolbarItem', (WidgetTester tester) async {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
final editor = tester.editor..addParagraphs(3, initialText: text);
|
||||
await editor.startTesting();
|
||||
|
||||
var selection = Selection.single(
|
||||
path: [1],
|
||||
startOffset: 2,
|
||||
endOffset: text.length - 2,
|
||||
);
|
||||
|
||||
await editor.updateSelection(selection);
|
||||
await tester.pumpWidget(
|
||||
MobileAppWithToolbarWidget(
|
||||
editorState: editor.editorState,
|
||||
toolbarItems: [
|
||||
textDecorationMobileToolbarItem,
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
// Tap text decoration toolbar item
|
||||
await tester.tap(find.byType(IconButton).first);
|
||||
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
||||
|
||||
// Show its menu and it has 4 buttons
|
||||
expect(find.byType(MobileToolbarItemMenu), findsOneWidget);
|
||||
expect(find.text('Bold'), findsOneWidget);
|
||||
expect(find.text('Italic'), findsOneWidget);
|
||||
expect(find.text('Underline'), findsOneWidget);
|
||||
expect(find.text('Strikethrough'), findsOneWidget);
|
||||
|
||||
// Test bold button
|
||||
await tester.tap(find.widgetWithText(MobileToolbarItemMenuBtn, 'Bold'));
|
||||
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
||||
final node = editor.editorState.getNodeAtPath([1]);
|
||||
expect(
|
||||
node?.allSatisfyInSelection(selection, (delta) {
|
||||
return delta.whereType<TextInsert>().every(
|
||||
(element) => element.attributes?[FlowyRichTextKeys.bold] == true,
|
||||
);
|
||||
}),
|
||||
true,
|
||||
);
|
||||
|
||||
// Test Italic button
|
||||
await tester.tap(find.widgetWithText(MobileToolbarItemMenuBtn, 'Italic'));
|
||||
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
||||
expect(
|
||||
node?.allSatisfyInSelection(selection, (delta) {
|
||||
return delta.whereType<TextInsert>().every(
|
||||
(element) =>
|
||||
element.attributes?[FlowyRichTextKeys.italic] == true,
|
||||
);
|
||||
}),
|
||||
true,
|
||||
);
|
||||
|
||||
// Test Underline button
|
||||
await tester
|
||||
.tap(find.widgetWithText(MobileToolbarItemMenuBtn, 'Underline'));
|
||||
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
||||
expect(
|
||||
node?.allSatisfyInSelection(selection, (delta) {
|
||||
return delta.whereType<TextInsert>().every(
|
||||
(element) =>
|
||||
element.attributes?[FlowyRichTextKeys.underline] == true,
|
||||
);
|
||||
}),
|
||||
true,
|
||||
);
|
||||
|
||||
// Test Strikethrough button
|
||||
await tester
|
||||
.tap(find.widgetWithText(MobileToolbarItemMenuBtn, 'Strikethrough'));
|
||||
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
||||
expect(
|
||||
node?.allSatisfyInSelection(selection, (delta) {
|
||||
return delta.whereType<TextInsert>().every(
|
||||
(element) =>
|
||||
element.attributes?[FlowyRichTextKeys.strikethrough] == true,
|
||||
);
|
||||
}),
|
||||
true,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import '../../../../new/infra/testable_editor.dart';
|
||||
import '../test_helpers/mobile_app_with_toolbar_widget.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('todoListMobileToolbarItem', (WidgetTester tester) async {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
final editor = tester.editor..addParagraphs(3, initialText: text);
|
||||
await editor.startTesting();
|
||||
|
||||
var selection = Selection.single(
|
||||
path: [1],
|
||||
startOffset: 2,
|
||||
endOffset: text.length - 2,
|
||||
);
|
||||
|
||||
await editor.updateSelection(selection);
|
||||
await tester.pumpWidget(
|
||||
MobileAppWithToolbarWidget(
|
||||
editorState: editor.editorState,
|
||||
toolbarItems: [
|
||||
todoListMobileToolbarItem,
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
// Tap todoList toolbar item
|
||||
final todoListBtn = find.byType(IconButton).first;
|
||||
await tester.tap(todoListBtn);
|
||||
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
||||
// Check if the text becomes quote node
|
||||
final node = editor.editorState.getNodeAtPath([1]);
|
||||
expect(
|
||||
node?.type == 'todo_list',
|
||||
true,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import '../test_helpers/mobile_toolbar_style_test_widget.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('MobileToolbarItemMenuBtn should display label and icon',
|
||||
(WidgetTester tester) async {
|
||||
const icon = Icon(Icons.add);
|
||||
const label = 'Add';
|
||||
|
||||
await tester.pumpWidget(
|
||||
MobileToolbarStyleTestWidget(
|
||||
child: MobileToolbarItemMenuBtn(
|
||||
onPressed: () {},
|
||||
icon: icon,
|
||||
label: label,
|
||||
isSelected: false,
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(find.byIcon(Icons.add), findsOneWidget);
|
||||
expect(find.text('Add'), findsOneWidget);
|
||||
});
|
||||
}
|
||||
Loading…
Reference in a new issue