10 #include "flutter/shell/platform/linux/testing/fl_mock_binary_messenger.h"
11 #include "flutter/shell/platform/linux/testing/fl_test.h"
12 #include "flutter/shell/platform/linux/testing/mock_im_context.h"
13 #include "flutter/shell/platform/linux/testing/mock_text_input_view_delegate.h"
14 #include "flutter/testing/testing.h"
16 #include "gmock/gmock.h"
17 #include "gtest/gtest.h"
21 for (
auto it =
args.begin(); it !=
args.end(); ++it) {
29 for (
auto it =
args.begin(); it !=
args.end(); ++it) {
102 gboolean called = FALSE;
104 fl_mock_binary_messenger_invoke_json_method(
105 messenger,
"flutter/textinput",
"TextInput.setClient",
args,
106 [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
108 gboolean* called =
static_cast<gboolean*
>(
user_data);
111 EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
115 FL_METHOD_SUCCESS_RESPONSE(response)),
124 gboolean called = FALSE;
126 fl_mock_binary_messenger_invoke_json_method(
127 messenger,
"flutter/textinput",
"TextInput.setEditingState",
args,
128 [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
130 gboolean* called =
static_cast<gboolean*
>(
user_data);
133 EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
137 FL_METHOD_SUCCESS_RESPONSE(response)),
147 GdkEvent* gdk_event = gdk_event_new(GDK_KEY_PRESS);
148 gdk_event->key.keyval = keyval;
149 gdk_event->key.state =
state;
155 g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
156 ::testing::NiceMock<flutter::testing::MockIMContext> context;
157 ::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
160 FL_BINARY_MESSENGER(messenger), context, delegate);
161 EXPECT_NE(handler,
nullptr);
164 fl_mock_binary_messenger_has_handler(messenger,
"flutter/textinput"));
169 TEST(FlTextInputHandlerTest, SetClient) {
170 g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
171 ::testing::NiceMock<flutter::testing::MockIMContext> context;
172 ::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
175 FL_BINARY_MESSENGER(messenger), context, delegate);
176 EXPECT_NE(handler,
nullptr);
183 TEST(FlTextInputHandlerTest, Show) {
184 g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
185 ::testing::NiceMock<flutter::testing::MockIMContext> context;
186 ::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
189 FL_BINARY_MESSENGER(messenger), context, delegate);
190 EXPECT_NE(handler,
nullptr);
193 gtk_im_context_focus_in(::testing::Eq<GtkIMContext*>(context)));
195 gboolean called = FALSE;
196 fl_mock_binary_messenger_invoke_json_method(
197 messenger,
"flutter/textinput",
"TextInput.show",
nullptr,
198 [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
200 gboolean* called =
static_cast<gboolean*
>(
user_data);
203 EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
207 FL_METHOD_SUCCESS_RESPONSE(response)),
216 TEST(FlTextInputHandlerTest, Hide) {
217 g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
218 ::testing::NiceMock<flutter::testing::MockIMContext> context;
219 ::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
222 FL_BINARY_MESSENGER(messenger), context, delegate);
223 EXPECT_NE(handler,
nullptr);
226 gtk_im_context_focus_out(::testing::Eq<GtkIMContext*>(context)));
228 gboolean called = FALSE;
229 fl_mock_binary_messenger_invoke_json_method(
230 messenger,
"flutter/textinput",
"TextInput.hide",
nullptr,
231 [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
233 gboolean* called =
static_cast<gboolean*
>(
user_data);
236 EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
240 FL_METHOD_SUCCESS_RESPONSE(response)),
249 TEST(FlTextInputHandlerTest, ClearClient) {
250 g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
251 ::testing::NiceMock<flutter::testing::MockIMContext> context;
252 ::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
255 FL_BINARY_MESSENGER(messenger), context, delegate);
256 EXPECT_NE(handler,
nullptr);
258 gboolean called = FALSE;
259 fl_mock_binary_messenger_invoke_json_method(
260 messenger,
"flutter/textinput",
"TextInput.clearClient",
nullptr,
261 [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
263 gboolean* called =
static_cast<gboolean*
>(
user_data);
266 EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
270 FL_METHOD_SUCCESS_RESPONSE(response)),
279 TEST(FlTextInputHandlerTest, PerformAction) {
280 g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
281 ::testing::NiceMock<flutter::testing::MockIMContext> context;
282 ::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
285 FL_BINARY_MESSENGER(messenger), context, delegate);
286 EXPECT_NE(handler,
nullptr);
290 .input_type =
"TextInputType.multiline",
291 .input_action =
"TextInputAction.newline",
296 .selection_extent = 7,
301 fl_mock_binary_messenger_set_json_method_channel(
302 messenger,
"flutter/textinput",
303 [](FlMockBinaryMessenger* messenger, GTask* task,
const gchar* name,
305 int* call_count =
static_cast<int*
>(
user_data);
307 if (strcmp(name,
"TextInputClient.updateEditingState") == 0) {
313 .selection_extent = 8,
317 EXPECT_EQ(*call_count, 0);
319 }
else if (strcmp(name,
"TextInputClient.performAction") == 0) {
325 EXPECT_EQ(*call_count, 1);
334 EXPECT_EQ(call_count, 2);
340 TEST(FlTextInputHandlerTest, MultilineWithSendAction) {
341 g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
342 ::testing::NiceMock<flutter::testing::MockIMContext> context;
343 ::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
346 FL_BINARY_MESSENGER(messenger), context, delegate);
347 EXPECT_NE(handler,
nullptr);
351 .input_type =
"TextInputType.multiline",
352 .input_action =
"TextInputAction.send",
357 .selection_extent = 7,
366 fl_mock_binary_messenger_set_json_method_channel(
367 messenger,
"flutter/textinput",
368 [](FlMockBinaryMessenger* messenger, GTask* task,
const gchar* name,
370 int* call_count =
static_cast<int*
>(
user_data);
372 EXPECT_STREQ(name,
"TextInputClient.performAction");
373 g_autoptr(
FlValue) expected_args =
nullptr;
374 switch (*call_count) {
383 g_assert_not_reached();
394 EXPECT_EQ(call_count, 1);
399 TEST(FlTextInputHandlerTest, MoveCursor) {
400 g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
401 ::testing::NiceMock<flutter::testing::MockIMContext> context;
402 ::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
405 FL_BINARY_MESSENGER(messenger), context, delegate);
406 EXPECT_NE(handler,
nullptr);
412 .selection_extent = 4,
416 fl_mock_binary_messenger_set_json_method_channel(
417 messenger,
"flutter/textinput",
418 [](FlMockBinaryMessenger* messenger, GTask* task,
const gchar* name,
420 int* call_count =
static_cast<int*
>(
user_data);
422 EXPECT_STREQ(name,
"TextInputClient.updateEditingState");
423 g_autoptr(
FlValue) expected_args =
nullptr;
424 switch (*call_count) {
432 .selection_extent = 0,
443 .selection_extent = 7,
448 g_assert_not_reached();
460 EXPECT_EQ(call_count, 2);
465 TEST(FlTextInputHandlerTest, Select) {
466 g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
467 ::testing::NiceMock<flutter::testing::MockIMContext> context;
468 ::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
471 FL_BINARY_MESSENGER(messenger), context, delegate);
472 EXPECT_NE(handler,
nullptr);
478 .selection_extent = 4,
482 fl_mock_binary_messenger_set_json_method_channel(
483 messenger,
"flutter/textinput",
484 [](FlMockBinaryMessenger* messenger, GTask* task,
const gchar* name,
486 int* call_count =
static_cast<int*
>(
user_data);
488 EXPECT_STREQ(name,
"TextInputClient.updateEditingState");
489 g_autoptr(
FlValue) expected_args =
nullptr;
490 switch (*call_count) {
498 .selection_extent = 7,
509 .selection_extent = 0,
514 g_assert_not_reached();
526 EXPECT_EQ(call_count, 2);
531 TEST(FlTextInputHandlerTest, Composing) {
532 g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
533 ::testing::NiceMock<flutter::testing::MockIMContext> context;
534 ::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
537 FL_BINARY_MESSENGER(messenger), context, delegate);
538 EXPECT_NE(handler,
nullptr);
542 gtk_im_context_get_preedit_string(
543 ::testing::Eq<GtkIMContext*>(context),
544 ::testing::A<gchar**>(), ::testing::_, ::testing::A<gint*>()))
546 ::testing::DoAll(::testing::SetArgPointee<1>(g_strdup(
"Flutter")),
547 ::testing::SetArgPointee<3>(0)));
550 fl_mock_binary_messenger_set_json_method_channel(
551 messenger,
"flutter/textinput",
552 [](FlMockBinaryMessenger* messenger, GTask* task,
const gchar* name,
554 int* call_count =
static_cast<int*
>(
user_data);
556 EXPECT_STREQ(name,
"TextInputClient.updateEditingState");
557 g_autoptr(
FlValue) expected_args =
nullptr;
558 switch (*call_count) {
565 .selection_extent = 0,
567 .composing_extent = 7,
578 .selection_extent = 6,
589 .selection_extent = 6,
594 g_assert_not_reached();
604 g_signal_emit_by_name(context,
"preedit-start",
nullptr);
605 g_signal_emit_by_name(context,
"preedit-changed",
nullptr);
606 g_signal_emit_by_name(context,
"commit",
"engine",
nullptr);
607 g_signal_emit_by_name(context,
"preedit-end",
nullptr);
608 EXPECT_EQ(call_count, 3);
613 TEST(FlTextInputHandlerTest, SurroundingText) {
614 g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
615 ::testing::NiceMock<flutter::testing::MockIMContext> context;
616 ::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
619 FL_BINARY_MESSENGER(messenger), context, delegate);
620 EXPECT_NE(handler,
nullptr);
626 .selection_extent = 3,
630 EXPECT_CALL(context, gtk_im_context_set_surrounding(
631 ::testing::Eq<GtkIMContext*>(context),
632 ::testing::StrEq(
"Flutter"), 7, 3));
634 gboolean retrieved =
false;
635 g_signal_emit_by_name(context,
"retrieve-surrounding", &retrieved,
nullptr);
636 EXPECT_TRUE(retrieved);
639 fl_mock_binary_messenger_set_json_method_channel(
640 messenger,
"flutter/textinput",
641 [](FlMockBinaryMessenger* messenger, GTask* task,
const gchar* name,
643 int* call_count =
static_cast<int*
>(
user_data);
645 EXPECT_STREQ(name,
"TextInputClient.updateEditingState");
646 g_autoptr(
FlValue) expected_args =
nullptr;
647 switch (*call_count) {
655 .selection_extent = 3,
660 g_assert_not_reached();
670 gboolean deleted =
false;
671 g_signal_emit_by_name(context,
"delete-surrounding", 1, 2, &deleted,
nullptr);
672 EXPECT_TRUE(deleted);
673 EXPECT_EQ(call_count, 1);
678 TEST(FlTextInputHandlerTest, SetMarkedTextRect) {
679 g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
680 ::testing::NiceMock<flutter::testing::MockIMContext> context;
681 ::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
684 FL_BINARY_MESSENGER(messenger), context, delegate);
685 EXPECT_NE(handler,
nullptr);
687 g_signal_emit_by_name(context,
"preedit-start",
nullptr);
713 gboolean called = FALSE;
714 fl_mock_binary_messenger_invoke_json_method(
715 messenger,
"flutter/textinput",
"TextInput.setEditableSizeAndTransform",
717 [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
719 gboolean* called =
static_cast<gboolean*
>(
user_data);
722 EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
726 FL_METHOD_SUCCESS_RESPONSE(response)),
733 ::testing::Eq<FlTextInputViewDelegate*>(delegate),
734 ::testing::Eq(27), ::testing::Eq(32), ::testing::_,
736 .WillOnce(::testing::DoAll(::testing::SetArgPointee<3>(123),
737 ::testing::SetArgPointee<4>(456)));
739 EXPECT_CALL(context, gtk_im_context_set_cursor_location(
740 ::testing::Eq<GtkIMContext*>(context),
741 ::testing::Pointee(::testing::AllOf(
742 ::testing::Field(&GdkRectangle::x, 123),
743 ::testing::Field(&GdkRectangle::y, 456),
755 fl_mock_binary_messenger_invoke_json_method(
756 messenger,
"flutter/textinput",
"TextInput.setMarkedTextRect", rect,
757 [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
759 gboolean* called =
static_cast<gboolean*
>(
user_data);
762 EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
766 FL_METHOD_SUCCESS_RESPONSE(response)),
775 TEST(FlTextInputHandlerTest, TextInputTypeNone) {
776 g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
777 ::testing::NiceMock<flutter::testing::MockIMContext> context;
778 ::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
781 FL_BINARY_MESSENGER(messenger), context, delegate);
782 EXPECT_NE(handler,
nullptr);
786 .input_type =
"TextInputType.none",
790 gtk_im_context_focus_in(::testing::Eq<GtkIMContext*>(context)))
793 gtk_im_context_focus_out(::testing::Eq<GtkIMContext*>(context)));
795 gboolean called = FALSE;
796 fl_mock_binary_messenger_invoke_json_method(
797 messenger,
"flutter/textinput",
"TextInput.show",
nullptr,
798 [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
800 gboolean* called =
static_cast<gboolean*
>(
user_data);
803 EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
807 FL_METHOD_SUCCESS_RESPONSE(response)),
816 TEST(FlTextInputHandlerTest, TextEditingDelta) {
817 g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
818 ::testing::NiceMock<flutter::testing::MockIMContext> context;
819 ::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
822 FL_BINARY_MESSENGER(messenger), context, delegate);
823 EXPECT_NE(handler,
nullptr);
827 .enable_delta_model =
true,
832 .selection_extent = 7,
837 fl_mock_binary_messenger_set_json_method_channel(
838 messenger,
"flutter/textinput",
839 [](FlMockBinaryMessenger* messenger, GTask* task,
const gchar* name,
841 int* call_count =
static_cast<int*
>(
user_data);
843 EXPECT_STREQ(name,
"TextInputClient.updateEditingStateWithDeltas");
844 g_autoptr(
FlValue) expected_args =
nullptr;
845 switch (*call_count) {
853 .old_text =
"Flutter",
854 .delta_text =
"Flutter",
858 .selection_extent = 0,
865 g_assert_not_reached();
876 EXPECT_EQ(call_count, 1);
881 TEST(FlTextInputHandlerTest, ComposingDelta) {
882 g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
883 ::testing::NiceMock<flutter::testing::MockIMContext> context;
884 ::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
887 FL_BINARY_MESSENGER(messenger), context, delegate);
888 EXPECT_NE(handler,
nullptr);
893 .enable_delta_model =
true,
896 g_signal_emit_by_name(context,
"preedit-start",
nullptr);
900 gtk_im_context_get_preedit_string(
901 ::testing::Eq<GtkIMContext*>(context),
902 ::testing::A<gchar**>(), ::testing::_, ::testing::A<gint*>()))
904 ::testing::DoAll(::testing::SetArgPointee<1>(g_strdup(
"Flutter ")),
905 ::testing::SetArgPointee<3>(8)));
908 fl_mock_binary_messenger_set_json_method_channel(
909 messenger,
"flutter/textinput",
910 [](FlMockBinaryMessenger* messenger, GTask* task,
const gchar* name,
912 int* call_count =
static_cast<int*
>(
user_data);
914 EXPECT_STREQ(name,
"TextInputClient.updateEditingStateWithDeltas");
915 g_autoptr(
FlValue) expected_args =
nullptr;
916 switch (*call_count) {
925 .delta_text =
"Flutter ",
929 .selection_extent = 8,
931 .composing_extent = 8,
945 .old_text =
"Flutter ",
946 .delta_text =
"Flutter engine",
949 .selection_base = 14,
950 .selection_extent = 14,
951 .composing_base = -1,
952 .composing_extent = -1,
966 .old_text =
"Flutter engine",
967 .selection_base = 14,
968 .selection_extent = 14,
975 g_assert_not_reached();
985 g_signal_emit_by_name(context,
"preedit-changed",
nullptr);
986 g_signal_emit_by_name(context,
"commit",
"Flutter engine",
nullptr);
987 g_signal_emit_by_name(context,
"preedit-end",
nullptr);
988 EXPECT_EQ(call_count, 3);
993 TEST(FlTextInputHandlerTest, NonComposingDelta) {
994 g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
995 ::testing::NiceMock<flutter::testing::MockIMContext> context;
996 ::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
999 FL_BINARY_MESSENGER(messenger), context, delegate);
1000 EXPECT_NE(handler,
nullptr);
1005 .enable_delta_model =
true,
1009 fl_mock_binary_messenger_set_json_method_channel(
1010 messenger,
"flutter/textinput",
1011 [](FlMockBinaryMessenger* messenger, GTask* task,
const gchar* name,
1013 int* call_count =
static_cast<int*
>(
user_data);
1015 EXPECT_STREQ(name,
"TextInputClient.updateEditingStateWithDeltas");
1016 g_autoptr(
FlValue) expected_args =
nullptr;
1017 switch (*call_count) {
1030 .selection_base = 1,
1031 .selection_extent = 1,
1032 .composing_base = -1,
1033 .composing_extent = -1,
1051 .selection_base = 2,
1052 .selection_extent = 2,
1053 .composing_base = -1,
1054 .composing_extent = -1,
1072 .selection_base = 3,
1073 .selection_extent = 3,
1074 .composing_base = -1,
1075 .composing_extent = -1,
1093 .selection_base = 4,
1094 .selection_extent = 4,
1095 .composing_base = -1,
1096 .composing_extent = -1,
1114 .selection_base = 5,
1115 .selection_extent = 5,
1116 .composing_base = -1,
1117 .composing_extent = -1,
1131 .old_text =
"Flutt",
1135 .selection_base = 6,
1136 .selection_extent = 6,
1137 .composing_base = -1,
1138 .composing_extent = -1,
1152 .old_text =
"Flutte",
1156 .selection_base = 7,
1157 .selection_extent = 7,
1158 .composing_base = -1,
1159 .composing_extent = -1,
1166 g_assert_not_reached();
1176 g_signal_emit_by_name(context,
"commit",
"F",
nullptr);
1177 g_signal_emit_by_name(context,
"commit",
"l",
nullptr);
1178 g_signal_emit_by_name(context,
"commit",
"u",
nullptr);
1179 g_signal_emit_by_name(context,
"commit",
"t",
nullptr);
1180 g_signal_emit_by_name(context,
"commit",
"t",
nullptr);
1181 g_signal_emit_by_name(context,
"commit",
"e",
nullptr);
1182 g_signal_emit_by_name(context,
"commit",
"r",
nullptr);
1183 EXPECT_EQ(call_count, 7);