zefyr

buttons_test.dart 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. // Copyright (c) 2018, the Zefyr project authors. Please see the AUTHORS file
  2. // for details. All rights reserved. Use of this source code is governed by a
  3. // BSD-style license that can be found in the LICENSE file.
  4. import 'dart:io';
  5. import 'package:flutter/material.dart';
  6. import 'package:flutter_test/flutter_test.dart';
  7. import 'package:zefyr/src/widgets/buttons.dart';
  8. import 'package:zefyr/zefyr.dart';
  9. import '../testing.dart';
  10. void main() {
  11. group('$ZefyrButton', () {
  12. testWidgets('toggle style', (tester) async {
  13. final editor = EditorSandBox(tester: tester);
  14. await editor.pumpAndTap();
  15. await editor.updateSelection(base: 5, extent: 10);
  16. await editor.tapButtonWithIcon(Icons.format_bold);
  17. LineNode line = editor.document.root.children.first;
  18. expect(line.childCount, 3);
  19. TextNode bold = line.children.elementAt(1);
  20. expect(bold.style.toJson(), NotusAttribute.bold.toJson());
  21. expect(bold.value, 'House');
  22. await editor.tapButtonWithIcon(Icons.format_bold);
  23. line = editor.document.root.children.first as LineNode;
  24. expect(line.childCount, 1);
  25. });
  26. testWidgets('toggle state for different styles of the same attribute',
  27. (tester) async {
  28. final editor = EditorSandBox(tester: tester);
  29. await editor.pumpAndTap();
  30. await editor.tapButtonWithIcon(Icons.format_list_bulleted);
  31. expect(editor.document.root.children.first, isInstanceOf<BlockNode>());
  32. var ul = editor.findButtonWithIcon(Icons.format_list_bulleted);
  33. var ol = editor.findButtonWithIcon(Icons.format_list_numbered);
  34. expect(ul.isToggled, isTrue);
  35. expect(ol.isToggled, isFalse);
  36. });
  37. });
  38. group('$HeadingButton', () {
  39. testWidgets('toggle menu', (tester) async {
  40. final editor = EditorSandBox(tester: tester);
  41. await editor.pumpAndTap();
  42. await editor.tapButtonWithIcon(Icons.format_size);
  43. expect(find.text('H1'), findsOneWidget);
  44. var h1 = editor.findButtonWithText('H1');
  45. expect(h1.action, ZefyrToolbarAction.headingLevel1);
  46. var h2 = editor.findButtonWithText('H2');
  47. expect(h2.action, ZefyrToolbarAction.headingLevel2);
  48. var h3 = editor.findButtonWithText('H3');
  49. expect(h3.action, ZefyrToolbarAction.headingLevel3);
  50. });
  51. testWidgets('toggle styles', (tester) async {
  52. final editor = EditorSandBox(tester: tester);
  53. await editor.pumpAndTap();
  54. await editor.tapButtonWithIcon(Icons.format_size);
  55. await editor.tapButtonWithText('H3');
  56. LineNode line = editor.document.root.children.first;
  57. expect(line.style.containsSame(NotusAttribute.heading.level3), isTrue);
  58. await editor.tapButtonWithText('H2');
  59. expect(line.style.containsSame(NotusAttribute.heading.level2), isTrue);
  60. });
  61. testWidgets('close overlay', (tester) async {
  62. final editor = EditorSandBox(tester: tester);
  63. await editor.pumpAndTap();
  64. await editor.tapButtonWithIcon(Icons.format_size);
  65. expect(find.text('H1'), findsOneWidget);
  66. await editor.tapButtonWithIcon(Icons.close);
  67. expect(find.text('H1'), findsNothing);
  68. });
  69. });
  70. group('$LinkButton', () {
  71. testWidgets('disabled when selection is collapsed', (tester) async {
  72. final editor = EditorSandBox(tester: tester);
  73. await editor.pumpAndTap();
  74. await editor.tapButtonWithIcon(Icons.link);
  75. expect(find.byIcon(Icons.link_off), findsNothing);
  76. });
  77. testWidgets('enabled and toggles menu with non-empty selection',
  78. (tester) async {
  79. final editor = EditorSandBox(tester: tester);
  80. await editor.pumpAndTap();
  81. await editor.updateSelection(base: 5, extent: 10);
  82. await editor.tapButtonWithIcon(Icons.link);
  83. expect(find.byIcon(Icons.link_off), findsOneWidget);
  84. });
  85. testWidgets('auto cancels edit on selection update', (tester) async {
  86. final editor = EditorSandBox(tester: tester);
  87. await editor.pumpAndTap();
  88. await editor.updateSelection(base: 5, extent: 10);
  89. await editor.tapButtonWithIcon(Icons.link);
  90. await tester
  91. .tap(find.widgetWithText(GestureDetector, 'Tap to edit link'));
  92. await tester.pumpAndSettle();
  93. expect(editor.focusNode.hasFocus, isFalse);
  94. await editor.updateSelection(base: 10, extent: 10);
  95. expect(find.byIcon(Icons.link_off), findsNothing);
  96. });
  97. testWidgets('editing link', (tester) async {
  98. final editor = EditorSandBox(tester: tester);
  99. await editor.pumpAndTap();
  100. await editor.updateSelection(base: 5, extent: 10);
  101. await editor.tapButtonWithIcon(Icons.link);
  102. await tester
  103. .tap(find.widgetWithText(GestureDetector, 'Tap to edit link'));
  104. await tester.pumpAndSettle();
  105. expect(find.byType(TextField), findsOneWidget);
  106. await tester.enterText(find.widgetWithText(TextField, 'https://').first,
  107. 'https://github.com');
  108. await tester.pumpAndSettle();
  109. expect(
  110. find.widgetWithText(TextField, 'https://github.com'), findsOneWidget);
  111. await editor.tapButtonWithIcon(Icons.check);
  112. expect(find.widgetWithText(ZefyrToolbarScaffold, 'https://github.com'),
  113. findsOneWidget);
  114. LineNode line = editor.document.root.children.first;
  115. expect(line.childCount, 3);
  116. TextNode link = line.children.elementAt(1);
  117. expect(link.value, 'House');
  118. expect(link.style.toJson(),
  119. NotusAttribute.link.fromString('https://github.com').toJson());
  120. // unlink
  121. await editor.updateSelection(base: 7, extent: 7);
  122. await editor.tapButtonWithIcon(Icons.link);
  123. await editor.tapButtonWithIcon(Icons.link_off);
  124. line = editor.document.root.children.first as LineNode;
  125. expect(line.childCount, 1);
  126. });
  127. });
  128. group('$ImageButton', () {
  129. testWidgets('toggle overlay', (tester) async {
  130. final editor = EditorSandBox(
  131. tester: tester,
  132. imageDelegate: _TestImageDelegate(),
  133. );
  134. await editor.pumpAndTap();
  135. await editor.tapButtonWithIcon(Icons.photo);
  136. expect(find.byIcon(Icons.photo_camera), findsOneWidget);
  137. await editor.tapButtonWithIcon(Icons.close);
  138. expect(find.byIcon(Icons.photo_camera), findsNothing);
  139. });
  140. testWidgets('pick from camera', (tester) async {
  141. final editor = EditorSandBox(
  142. tester: tester,
  143. imageDelegate: _TestImageDelegate(),
  144. );
  145. await editor.pumpAndTap();
  146. await editor.tapButtonWithIcon(Icons.photo);
  147. await editor.tapButtonWithIcon(Icons.photo_camera);
  148. expect(find.byType(ZefyrImage), findsOneWidget);
  149. });
  150. testWidgets('pick from gallery', (tester) async {
  151. final editor = EditorSandBox(
  152. tester: tester,
  153. imageDelegate: _TestImageDelegate(),
  154. );
  155. await editor.pumpAndTap();
  156. await editor.tapButtonWithIcon(Icons.photo);
  157. await editor.tapButtonWithIcon(Icons.photo_library);
  158. expect(find.byType(ZefyrImage), findsOneWidget);
  159. });
  160. });
  161. }
  162. class _TestImageDelegate implements ZefyrImageDelegate<String> {
  163. @override
  164. Widget buildImage(BuildContext context, String key) {
  165. return Image.file(File(key));
  166. }
  167. @override
  168. String get cameraSource => "camera";
  169. @override
  170. String get gallerySource => "gallery";
  171. @override
  172. Future<String> pickImage(String source) {
  173. return Future.value("file:///tmp/test.jpg");
  174. }
  175. @override
  176. Future<String> picked(list) async {
  177. return Future.value("file:///tmp/test.jpg");
  178. }
  179. }