mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
test: add test for image_node_widget and image_node_builder
This commit is contained in:
parent
012c3a851a
commit
3832af5fa8
@ -41,24 +41,20 @@ class ImageNodeBuilder extends NodeWidgetBuilder<Node> {
|
||||
});
|
||||
|
||||
Alignment _textToAlignment(String text) {
|
||||
if (text == 'center') {
|
||||
return Alignment.center;
|
||||
} else if (text == 'left') {
|
||||
if (text == 'left') {
|
||||
return Alignment.centerLeft;
|
||||
} else if (text == 'right') {
|
||||
return Alignment.centerRight;
|
||||
}
|
||||
throw UnimplementedError();
|
||||
return Alignment.center;
|
||||
}
|
||||
|
||||
String _alignmentToText(Alignment alignment) {
|
||||
if (alignment == Alignment.center) {
|
||||
return 'center';
|
||||
} else if (alignment == Alignment.centerLeft) {
|
||||
if (alignment == Alignment.centerLeft) {
|
||||
return 'left';
|
||||
} else if (alignment == Alignment.centerRight) {
|
||||
return 'right';
|
||||
}
|
||||
throw UnimplementedError();
|
||||
return 'center';
|
||||
}
|
||||
}
|
||||
|
@ -54,25 +54,7 @@ class _ImageNodeWidgetState extends State<ImageNodeWidget> {
|
||||
widget.src,
|
||||
width: imageWidth == null ? null : imageWidth! - _distance,
|
||||
loadingBuilder: (context, child, loadingProgress) =>
|
||||
loadingProgress == null
|
||||
? child
|
||||
: SizedBox(
|
||||
width: imageWidth,
|
||||
height: 300,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox.fromSize(
|
||||
size: const Size(18, 18),
|
||||
child: const CircularProgressIndicator(),
|
||||
),
|
||||
SizedBox.fromSize(
|
||||
size: const Size(10, 10),
|
||||
),
|
||||
const Text('Loading'),
|
||||
],
|
||||
),
|
||||
),
|
||||
loadingProgress == null ? child : _buildLoading(context),
|
||||
);
|
||||
if (imageWidth == null) {
|
||||
networkImage.image.resolve(const ImageConfiguration()).addListener(
|
||||
@ -111,16 +93,39 @@ class _ImageNodeWidgetState extends State<ImageNodeWidget> {
|
||||
},
|
||||
),
|
||||
if (_onFocus)
|
||||
_buildImageToolbar(
|
||||
context,
|
||||
ImageToolbar(
|
||||
top: 8,
|
||||
right: 8,
|
||||
height: 30,
|
||||
),
|
||||
alignment: widget.alignment,
|
||||
onAlign: widget.onAlign,
|
||||
onCopy: widget.onCopy,
|
||||
onDelete: widget.onDelete,
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildLoading(BuildContext context) {
|
||||
return SizedBox(
|
||||
width: imageWidth,
|
||||
height: 300,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox.fromSize(
|
||||
size: const Size(18, 18),
|
||||
child: const CircularProgressIndicator(),
|
||||
),
|
||||
SizedBox.fromSize(
|
||||
size: const Size(10, 10),
|
||||
),
|
||||
const Text('Loading'),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildEdgeGesture(
|
||||
BuildContext context, {
|
||||
double? top,
|
||||
@ -169,20 +174,34 @@ class _ImageNodeWidgetState extends State<ImageNodeWidget> {
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildImageToolbar(
|
||||
BuildContext context, {
|
||||
double? top,
|
||||
double? left,
|
||||
double? right,
|
||||
double? width,
|
||||
double? height,
|
||||
}) {
|
||||
@visibleForTesting
|
||||
class ImageToolbar extends StatelessWidget {
|
||||
const ImageToolbar({
|
||||
Key? key,
|
||||
required this.top,
|
||||
required this.right,
|
||||
required this.height,
|
||||
required this.alignment,
|
||||
required this.onCopy,
|
||||
required this.onDelete,
|
||||
required this.onAlign,
|
||||
}) : super(key: key);
|
||||
|
||||
final double top;
|
||||
final double right;
|
||||
final double height;
|
||||
final Alignment alignment;
|
||||
final VoidCallback onCopy;
|
||||
final VoidCallback onDelete;
|
||||
final void Function(Alignment alignment) onAlign;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Positioned(
|
||||
top: top,
|
||||
left: left,
|
||||
right: right,
|
||||
width: width,
|
||||
height: height,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
@ -205,12 +224,12 @@ class _ImageNodeWidgetState extends State<ImageNodeWidget> {
|
||||
padding: const EdgeInsets.fromLTRB(6.0, 4.0, 0.0, 4.0),
|
||||
icon: FlowySvg(
|
||||
name: 'image_toolbar/align_left',
|
||||
color: widget.alignment == Alignment.centerLeft
|
||||
color: alignment == Alignment.centerLeft
|
||||
? const Color(0xFF00BCF0)
|
||||
: null,
|
||||
),
|
||||
onPressed: () {
|
||||
widget.onAlign(Alignment.centerLeft);
|
||||
onAlign(Alignment.centerLeft);
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
@ -219,12 +238,12 @@ class _ImageNodeWidgetState extends State<ImageNodeWidget> {
|
||||
padding: const EdgeInsets.fromLTRB(0.0, 4.0, 0.0, 4.0),
|
||||
icon: FlowySvg(
|
||||
name: 'image_toolbar/align_center',
|
||||
color: widget.alignment == Alignment.center
|
||||
color: alignment == Alignment.center
|
||||
? const Color(0xFF00BCF0)
|
||||
: null,
|
||||
),
|
||||
onPressed: () {
|
||||
widget.onAlign(Alignment.center);
|
||||
onAlign(Alignment.center);
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
@ -233,12 +252,12 @@ class _ImageNodeWidgetState extends State<ImageNodeWidget> {
|
||||
padding: const EdgeInsets.fromLTRB(0.0, 4.0, 4.0, 4.0),
|
||||
icon: FlowySvg(
|
||||
name: 'image_toolbar/align_right',
|
||||
color: widget.alignment == Alignment.centerRight
|
||||
color: alignment == Alignment.centerRight
|
||||
? const Color(0xFF00BCF0)
|
||||
: null,
|
||||
),
|
||||
onPressed: () {
|
||||
widget.onAlign(Alignment.centerRight);
|
||||
onAlign(Alignment.centerRight);
|
||||
},
|
||||
),
|
||||
const Center(
|
||||
@ -254,7 +273,7 @@ class _ImageNodeWidgetState extends State<ImageNodeWidget> {
|
||||
name: 'image_toolbar/copy',
|
||||
),
|
||||
onPressed: () {
|
||||
widget.onCopy();
|
||||
onCopy();
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
@ -265,7 +284,7 @@ class _ImageNodeWidgetState extends State<ImageNodeWidget> {
|
||||
name: 'image_toolbar/delete',
|
||||
),
|
||||
onPressed: () {
|
||||
widget.onDelete();
|
||||
onDelete();
|
||||
},
|
||||
),
|
||||
],
|
||||
|
@ -0,0 +1,131 @@
|
||||
import 'package:appflowy_editor/src/render/image/image_node_widget.dart';
|
||||
import 'package:appflowy_editor/src/service/editor_service.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:network_image_mock/network_image_mock.dart';
|
||||
|
||||
import '../../infra/test_editor.dart';
|
||||
|
||||
void main() async {
|
||||
setUpAll(() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
});
|
||||
|
||||
group('image_node_builder.dart', () {
|
||||
testWidgets('render image node', (tester) async {
|
||||
mockNetworkImagesFor(() async {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
const src =
|
||||
'https://images.unsplash.com/photo-1471897488648-5eae4ac6686b?ixlib=rb-1.2.1&dl=sarah-dorweiler-QeVmJxZOv3k-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb';
|
||||
final editor = tester.editor
|
||||
..insertTextNode(text)
|
||||
..insertImageNode(src)
|
||||
..insertTextNode(text);
|
||||
await editor.startTesting();
|
||||
|
||||
expect(editor.documentLength, 3);
|
||||
expect(find.byType(Image), findsOneWidget);
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets('render image align', (tester) async {
|
||||
mockNetworkImagesFor(() async {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
const src =
|
||||
'https://images.unsplash.com/photo-1471897488648-5eae4ac6686b?ixlib=rb-1.2.1&dl=sarah-dorweiler-QeVmJxZOv3k-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb';
|
||||
final editor = tester.editor
|
||||
..insertTextNode(text)
|
||||
..insertImageNode(src, align: 'left')
|
||||
..insertImageNode(src, align: 'center')
|
||||
..insertImageNode(src, align: 'right')
|
||||
..insertTextNode(text);
|
||||
await editor.startTesting();
|
||||
|
||||
expect(editor.documentLength, 5);
|
||||
final imageFinder = find.byType(Image);
|
||||
expect(imageFinder, findsNWidgets(3));
|
||||
|
||||
final editorFinder = find.byType(AppFlowyEditor);
|
||||
final editorRect = tester.getRect(editorFinder);
|
||||
|
||||
final leftImageRect = tester.getRect(imageFinder.at(0));
|
||||
expect(leftImageRect.left, editorRect.left);
|
||||
final rightImageRect = tester.getRect(imageFinder.at(2));
|
||||
expect(rightImageRect.right, editorRect.right);
|
||||
final centerImageRect = tester.getRect(imageFinder.at(1));
|
||||
expect(centerImageRect.left,
|
||||
(leftImageRect.left + rightImageRect.left) / 2.0);
|
||||
expect(leftImageRect.size, centerImageRect.size);
|
||||
expect(rightImageRect.size, centerImageRect.size);
|
||||
|
||||
final imageNodeWidgetFinder = find.byType(ImageNodeWidget);
|
||||
|
||||
final leftImage =
|
||||
tester.firstWidget(imageNodeWidgetFinder) as ImageNodeWidget;
|
||||
|
||||
leftImage.onAlign(Alignment.center);
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
expect(
|
||||
tester.getRect(imageFinder.at(0)).left,
|
||||
centerImageRect.left,
|
||||
);
|
||||
|
||||
leftImage.onAlign(Alignment.centerRight);
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
expect(
|
||||
tester.getRect(imageFinder.at(0)).left,
|
||||
rightImageRect.left,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets('render image copy', (tester) async {
|
||||
mockNetworkImagesFor(() async {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
const src =
|
||||
'https://images.unsplash.com/photo-1471897488648-5eae4ac6686b?ixlib=rb-1.2.1&dl=sarah-dorweiler-QeVmJxZOv3k-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb';
|
||||
final editor = tester.editor
|
||||
..insertTextNode(text)
|
||||
..insertImageNode(src)
|
||||
..insertTextNode(text);
|
||||
await editor.startTesting();
|
||||
|
||||
expect(editor.documentLength, 3);
|
||||
final imageFinder = find.byType(Image);
|
||||
expect(imageFinder, findsOneWidget);
|
||||
|
||||
final imageNodeWidgetFinder = find.byType(ImageNodeWidget);
|
||||
final image =
|
||||
tester.firstWidget(imageNodeWidgetFinder) as ImageNodeWidget;
|
||||
image.onCopy();
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets('render image delete', (tester) async {
|
||||
mockNetworkImagesFor(() async {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
const src =
|
||||
'https://images.unsplash.com/photo-1471897488648-5eae4ac6686b?ixlib=rb-1.2.1&dl=sarah-dorweiler-QeVmJxZOv3k-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb';
|
||||
final editor = tester.editor
|
||||
..insertTextNode(text)
|
||||
..insertImageNode(src)
|
||||
..insertImageNode(src)
|
||||
..insertTextNode(text);
|
||||
await editor.startTesting();
|
||||
|
||||
expect(editor.documentLength, 4);
|
||||
final imageFinder = find.byType(Image);
|
||||
expect(imageFinder, findsNWidgets(2));
|
||||
|
||||
final imageNodeWidgetFinder = find.byType(ImageNodeWidget);
|
||||
final image =
|
||||
tester.firstWidget(imageNodeWidgetFinder) as ImageNodeWidget;
|
||||
image.onDelete();
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
expect(editor.documentLength, 3);
|
||||
expect(find.byType(Image), findsNWidgets(1));
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
@ -1,130 +1,79 @@
|
||||
import 'package:appflowy_editor/src/render/image/image_node_widget.dart';
|
||||
import 'package:appflowy_editor/src/service/editor_service.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:network_image_mock/network_image_mock.dart';
|
||||
|
||||
import '../../infra/test_editor.dart';
|
||||
|
||||
void main() async {
|
||||
setUpAll(() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
});
|
||||
|
||||
group('image_node_widget.dart', () {
|
||||
testWidgets('render image node', (tester) async {
|
||||
testWidgets('build the image node widget', (tester) async {
|
||||
mockNetworkImagesFor(() async {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
var onCopyHit = false;
|
||||
var onDeleteHit = false;
|
||||
var onAlignHit = false;
|
||||
const src =
|
||||
'https://images.unsplash.com/photo-1471897488648-5eae4ac6686b?ixlib=rb-1.2.1&dl=sarah-dorweiler-QeVmJxZOv3k-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb';
|
||||
final editor = tester.editor
|
||||
..insertTextNode(text)
|
||||
..insertImageNode(src)
|
||||
..insertTextNode(text);
|
||||
await editor.startTesting();
|
||||
|
||||
expect(editor.documentLength, 3);
|
||||
expect(find.byType(Image), findsOneWidget);
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets('render image align', (tester) async {
|
||||
mockNetworkImagesFor(() async {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
const src =
|
||||
'https://images.unsplash.com/photo-1471897488648-5eae4ac6686b?ixlib=rb-1.2.1&dl=sarah-dorweiler-QeVmJxZOv3k-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb';
|
||||
final editor = tester.editor
|
||||
..insertTextNode(text)
|
||||
..insertImageNode(src, align: 'left')
|
||||
..insertImageNode(src, align: 'center')
|
||||
..insertImageNode(src, align: 'right')
|
||||
..insertTextNode(text);
|
||||
await editor.startTesting();
|
||||
|
||||
expect(editor.documentLength, 5);
|
||||
final imageFinder = find.byType(Image);
|
||||
expect(imageFinder, findsNWidgets(3));
|
||||
|
||||
final editorFinder = find.byType(AppFlowyEditor);
|
||||
final editorRect = tester.getRect(editorFinder);
|
||||
|
||||
final leftImageRect = tester.getRect(imageFinder.at(0));
|
||||
expect(leftImageRect.left, editorRect.left);
|
||||
final rightImageRect = tester.getRect(imageFinder.at(2));
|
||||
expect(rightImageRect.right, editorRect.right);
|
||||
final centerImageRect = tester.getRect(imageFinder.at(1));
|
||||
expect(centerImageRect.left,
|
||||
(leftImageRect.left + rightImageRect.left) / 2.0);
|
||||
expect(leftImageRect.size, centerImageRect.size);
|
||||
expect(rightImageRect.size, centerImageRect.size);
|
||||
|
||||
final imageNodeWidgetFinder = find.byType(ImageNodeWidget);
|
||||
|
||||
final leftImage =
|
||||
tester.firstWidget(imageNodeWidgetFinder) as ImageNodeWidget;
|
||||
|
||||
leftImage.onAlign(Alignment.center);
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
expect(
|
||||
tester.getRect(imageFinder.at(0)).left,
|
||||
centerImageRect.left,
|
||||
final widget = ImageNodeWidget(
|
||||
src: src,
|
||||
alignment: Alignment.center,
|
||||
onCopy: () {
|
||||
onCopyHit = true;
|
||||
},
|
||||
onDelete: () {
|
||||
onDeleteHit = true;
|
||||
},
|
||||
onAlign: (alignment) {
|
||||
onAlignHit = true;
|
||||
},
|
||||
);
|
||||
|
||||
leftImage.onAlign(Alignment.centerRight);
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
expect(
|
||||
tester.getRect(imageFinder.at(0)).left,
|
||||
rightImageRect.left,
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Material(
|
||||
child: widget,
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
expect(find.byType(ImageNodeWidget), findsOneWidget);
|
||||
|
||||
testWidgets('render image copy', (tester) async {
|
||||
mockNetworkImagesFor(() async {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
const src =
|
||||
'https://images.unsplash.com/photo-1471897488648-5eae4ac6686b?ixlib=rb-1.2.1&dl=sarah-dorweiler-QeVmJxZOv3k-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb';
|
||||
final editor = tester.editor
|
||||
..insertTextNode(text)
|
||||
..insertImageNode(src)
|
||||
..insertTextNode(text);
|
||||
await editor.startTesting();
|
||||
final gesture =
|
||||
await tester.createGesture(kind: PointerDeviceKind.mouse);
|
||||
await gesture.addPointer(location: Offset.zero);
|
||||
|
||||
expect(editor.documentLength, 3);
|
||||
final imageFinder = find.byType(Image);
|
||||
expect(imageFinder, findsOneWidget);
|
||||
expect(find.byType(ImageToolbar), findsNothing);
|
||||
|
||||
final imageNodeWidgetFinder = find.byType(ImageNodeWidget);
|
||||
final image =
|
||||
tester.firstWidget(imageNodeWidgetFinder) as ImageNodeWidget;
|
||||
image.onCopy();
|
||||
});
|
||||
});
|
||||
addTearDown(gesture.removePointer);
|
||||
await tester.pump();
|
||||
await gesture.moveTo(tester.getCenter(find.byType(ImageNodeWidget)));
|
||||
await tester.pump();
|
||||
|
||||
testWidgets('render image delete', (tester) async {
|
||||
mockNetworkImagesFor(() async {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
const src =
|
||||
'https://images.unsplash.com/photo-1471897488648-5eae4ac6686b?ixlib=rb-1.2.1&dl=sarah-dorweiler-QeVmJxZOv3k-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb';
|
||||
final editor = tester.editor
|
||||
..insertTextNode(text)
|
||||
..insertImageNode(src)
|
||||
..insertImageNode(src)
|
||||
..insertTextNode(text);
|
||||
await editor.startTesting();
|
||||
expect(find.byType(ImageToolbar), findsOneWidget);
|
||||
|
||||
expect(editor.documentLength, 4);
|
||||
final imageFinder = find.byType(Image);
|
||||
expect(imageFinder, findsNWidgets(2));
|
||||
final iconFinder = find.byType(IconButton);
|
||||
expect(iconFinder, findsNWidgets(5));
|
||||
|
||||
final imageNodeWidgetFinder = find.byType(ImageNodeWidget);
|
||||
final image =
|
||||
tester.firstWidget(imageNodeWidgetFinder) as ImageNodeWidget;
|
||||
image.onDelete();
|
||||
await tester.tap(iconFinder.at(0));
|
||||
expect(onAlignHit, true);
|
||||
onAlignHit = false;
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
expect(editor.documentLength, 3);
|
||||
expect(find.byType(Image), findsNWidgets(1));
|
||||
await tester.tap(iconFinder.at(1));
|
||||
expect(onAlignHit, true);
|
||||
onAlignHit = false;
|
||||
|
||||
await tester.tap(iconFinder.at(2));
|
||||
expect(onAlignHit, true);
|
||||
onAlignHit = false;
|
||||
|
||||
await tester.tap(iconFinder.at(3));
|
||||
expect(onCopyHit, true);
|
||||
|
||||
await tester.tap(iconFinder.at(4));
|
||||
expect(onDeleteHit, true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user