6 #include "gtest/gtest.h"
8 #include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
12 #include "flutter/shell/platform/linux/testing/mock_signal_handler.h"
18 g_autoptr(GBytes) bytes = g_bytes_new(data, data_length);
26 TEST(FlAccessibleTextFieldTest, SetValue) {
34 flutter::testing::MockSignalHandler2<int, int> text_inserted(node,
36 flutter::testing::MockSignalHandler text_removed(node,
"text-remove");
38 EXPECT_SIGNAL2(text_inserted, ::testing::Eq(0), ::testing::Eq(7));
39 EXPECT_SIGNAL(text_removed).Times(0);
46 flutter::testing::MockSignalHandler text_inserted(node,
"text-insert");
47 flutter::testing::MockSignalHandler text_removed(node,
"text-remove");
49 EXPECT_SIGNAL(text_inserted).Times(0);
50 EXPECT_SIGNAL(text_removed).Times(0);
57 flutter::testing::MockSignalHandler2<int, int> text_inserted(node,
59 flutter::testing::MockSignalHandler2<int, int> text_removed(node,
62 EXPECT_SIGNAL2(text_inserted, ::testing::Eq(0), ::testing::Eq(6));
63 EXPECT_SIGNAL2(text_removed, ::testing::Eq(0), ::testing::Eq(7));
70 flutter::testing::MockSignalHandler text_inserted(node,
"text-insert");
71 flutter::testing::MockSignalHandler2<int, int> text_removed(node,
74 EXPECT_SIGNAL(text_inserted).Times(0);
75 EXPECT_SIGNAL2(text_removed, ::testing::Eq(0), ::testing::Eq(6));
84 TEST(FlAccessibleTextFieldTest, SetTextSelection) {
92 flutter::testing::MockSignalHandler text_selection_changed(
93 node,
"text-selection-changed");
94 flutter::testing::MockSignalHandler1<int> text_caret_moved(
95 node,
"text-caret-moved");
97 EXPECT_SIGNAL(text_selection_changed);
98 EXPECT_SIGNAL1(text_caret_moved, ::testing::Eq(3));
105 flutter::testing::MockSignalHandler text_selection_changed(
106 node,
"text-selection-changed");
107 flutter::testing::MockSignalHandler text_caret_moved(node,
110 EXPECT_SIGNAL(text_selection_changed);
111 EXPECT_SIGNAL(text_caret_moved).Times(0);
118 flutter::testing::MockSignalHandler text_selection_changed(
119 node,
"text-selection-changed");
120 flutter::testing::MockSignalHandler text_caret_moved(node,
123 EXPECT_SIGNAL(text_selection_changed).Times(0);
124 EXPECT_SIGNAL(text_caret_moved).Times(0);
131 flutter::testing::MockSignalHandler text_selection_changed(
132 node,
"text-selection-changed");
133 flutter::testing::MockSignalHandler1<int> text_caret_moved(
134 node,
"text-caret-moved");
136 EXPECT_SIGNAL(text_selection_changed).Times(0);
137 EXPECT_SIGNAL1(text_caret_moved, ::testing::Eq(4));
145 TEST(FlAccessibleTextFieldTest, PerformAction) {
146 g_autoptr(GPtrArray) action_datas = g_ptr_array_new_with_free_func(
154 EXPECT_EQ(
error,
nullptr);
158 ([&action_datas](
auto engine,
159 const FlutterSendSemanticsActionInfo* info) {
160 g_ptr_array_add(action_datas,
168 node,
static_cast<FlutterSemanticsAction
>(
169 kFlutterSemanticsActionMoveCursorForwardByCharacter |
170 kFlutterSemanticsActionMoveCursorBackwardByCharacter |
171 kFlutterSemanticsActionMoveCursorForwardByWord |
172 kFlutterSemanticsActionMoveCursorBackwardByWord));
176 for (
int i = 0;
i < 4; ++
i) {
177 atk_action_do_action(ATK_ACTION(node),
i);
179 FlValue* data =
static_cast<FlValue*
>(g_ptr_array_index(action_datas,
i));
180 EXPECT_NE(data,
nullptr);
186 TEST(FlAccessibleTextFieldTest, GetCharacterCount) {
192 EXPECT_EQ(atk_text_get_character_count(ATK_TEXT(node)), 0);
196 EXPECT_EQ(atk_text_get_character_count(ATK_TEXT(node)), 8);
200 TEST(FlAccessibleTextFieldTest, GetText) {
206 g_autofree gchar* empty = atk_text_get_text(ATK_TEXT(node), 0, -1);
207 EXPECT_STREQ(empty,
"");
209 flutter::testing::MockSignalHandler text_inserted(node,
"text-insert");
210 EXPECT_SIGNAL(text_inserted).Times(1);
214 g_autofree gchar*
flutter = atk_text_get_text(ATK_TEXT(node), 0, -1);
215 EXPECT_STREQ(
flutter,
"Flutter!");
217 g_autofree gchar* tt = atk_text_get_text(ATK_TEXT(node), 3, 5);
218 EXPECT_STREQ(tt,
"tt");
222 TEST(FlAccessibleTextFieldTest, GetTextBoundsChecking) {
231 g_autofree gchar* beyond = atk_text_get_text(ATK_TEXT(node), 100, -1);
232 EXPECT_STREQ(beyond,
"");
235 g_autofree gchar* end_beyond = atk_text_get_text(ATK_TEXT(node), 2, 100);
236 EXPECT_STREQ(end_beyond,
"llo");
239 g_autofree gchar* both_beyond = atk_text_get_text(ATK_TEXT(node), 50, 100);
240 EXPECT_STREQ(both_beyond,
"");
244 g_autofree gchar* empty_beyond = atk_text_get_text(ATK_TEXT(node), 5, 10);
245 EXPECT_STREQ(empty_beyond,
"");
249 TEST(FlAccessibleTextFieldTest, GetCaretOffset) {
255 EXPECT_EQ(atk_text_get_caret_offset(ATK_TEXT(node)), -1);
259 EXPECT_EQ(atk_text_get_caret_offset(ATK_TEXT(node)), 2);
263 TEST(FlAccessibleTextFieldTest, SetCaretOffset) {
272 EXPECT_EQ(
error,
nullptr);
276 ([&base, &extent](
auto engine,
277 const FlutterSendSemanticsActionInfo* info) {
278 EXPECT_EQ(info->action, kFlutterSemanticsActionSetSelection);
290 EXPECT_TRUE(atk_text_set_caret_offset(ATK_TEXT(node), 3));
292 EXPECT_EQ(extent, 3);
296 TEST(FlAccessibleTextFieldTest, GetNSelections) {
302 EXPECT_EQ(atk_text_get_n_selections(ATK_TEXT(node)), 0);
306 EXPECT_EQ(atk_text_get_n_selections(ATK_TEXT(node)), 1);
310 TEST(FlAccessibleTextFieldTest, GetSelection) {
316 EXPECT_EQ(atk_text_get_selection(ATK_TEXT(node), 0,
nullptr,
nullptr),
323 g_autofree gchar* selection =
324 atk_text_get_selection(ATK_TEXT(node), 0, &
start, &
end);
325 EXPECT_STREQ(selection,
"utt");
331 g_autofree gchar* reverse =
332 atk_text_get_selection(ATK_TEXT(node), 0, &
start, &
end);
333 EXPECT_STREQ(reverse,
"utt");
339 EXPECT_EQ(atk_text_get_selection(ATK_TEXT(node), 0, &
start, &
end),
nullptr);
342 EXPECT_EQ(atk_text_get_selection(ATK_TEXT(node), 1, &
start, &
end),
nullptr);
346 TEST(FlAccessibleTextFieldTest, AddSelection) {
355 EXPECT_EQ(
error,
nullptr);
359 ([&base, &extent](
auto engine,
360 const FlutterSendSemanticsActionInfo* info) {
361 EXPECT_EQ(info->action, kFlutterSemanticsActionSetSelection);
373 EXPECT_TRUE(atk_text_add_selection(ATK_TEXT(node), 2, 4));
375 EXPECT_EQ(extent, 4);
380 EXPECT_FALSE(atk_text_add_selection(ATK_TEXT(node), 6, 7));
382 EXPECT_EQ(extent, 4);
386 TEST(FlAccessibleTextFieldTest, RemoveSelection) {
395 EXPECT_EQ(
error,
nullptr);
399 ([&base, &extent](
auto engine,
400 const FlutterSendSemanticsActionInfo* info) {
401 EXPECT_EQ(info->action, kFlutterSemanticsActionSetSelection);
414 EXPECT_FALSE(atk_text_remove_selection(ATK_TEXT(node), 0));
416 EXPECT_EQ(extent, -1);
421 EXPECT_FALSE(atk_text_remove_selection(ATK_TEXT(node), 1));
423 EXPECT_EQ(extent, -1);
426 EXPECT_TRUE(atk_text_remove_selection(ATK_TEXT(node), 0));
428 EXPECT_EQ(extent, 4);
432 TEST(FlAccessibleTextFieldTest, SetSelection) {
441 EXPECT_EQ(
error,
nullptr);
445 ([&base, &extent](
auto engine,
446 const FlutterSendSemanticsActionInfo* info) {
447 EXPECT_EQ(info->action, kFlutterSemanticsActionSetSelection);
460 EXPECT_FALSE(atk_text_set_selection(ATK_TEXT(node), 1, 2, 4));
462 EXPECT_EQ(extent, -1);
464 EXPECT_TRUE(atk_text_set_selection(ATK_TEXT(node), 0, 2, 4));
466 EXPECT_EQ(extent, 4);
468 EXPECT_TRUE(atk_text_set_selection(ATK_TEXT(node), 0, 5, 1));
470 EXPECT_EQ(extent, 1);
474 TEST(FlAccessibleTextFieldTest, SetTextContents) {
475 g_autofree gchar* text =
nullptr;
482 EXPECT_EQ(
error,
nullptr);
486 ([&text](
auto engine,
const FlutterSendSemanticsActionInfo* info) {
487 EXPECT_EQ(info->action, kFlutterSemanticsActionSetText);
498 atk_editable_text_set_text_contents(ATK_EDITABLE_TEXT(node),
"Flutter");
499 EXPECT_STREQ(text,
"Flutter");
503 TEST(FlAccessibleTextFieldTest, InsertDeleteText) {
504 g_autofree gchar* text =
nullptr;
513 EXPECT_EQ(
error,
nullptr);
517 ([&text, &base, &extent](
auto engine,
518 const FlutterSendSemanticsActionInfo* info) {
519 EXPECT_THAT(info->action,
520 ::testing::AnyOf(kFlutterSemanticsActionSetText,
521 kFlutterSemanticsActionSetSelection));
522 if (info->action == kFlutterSemanticsActionSetText) {
543 atk_editable_text_insert_text(ATK_EDITABLE_TEXT(node),
"utt", 3, &pos);
545 EXPECT_STREQ(text,
"Flutter");
546 EXPECT_EQ(base, pos);
547 EXPECT_EQ(extent, pos);
549 atk_editable_text_delete_text(ATK_EDITABLE_TEXT(node), 2, 5);
550 EXPECT_STREQ(text,
"Fler");
552 EXPECT_EQ(extent, 2);
556 TEST(FlAccessibleTextFieldTest, CopyCutPasteText) {
559 FlutterSemanticsAction act = kFlutterSemanticsActionCustomAction;
566 EXPECT_EQ(
error,
nullptr);
570 ([&act, &base, &extent](
auto engine,
571 const FlutterSendSemanticsActionInfo* info) {
572 EXPECT_THAT(info->action,
573 ::testing::AnyOf(kFlutterSemanticsActionCut,
574 kFlutterSemanticsActionCopy,
575 kFlutterSemanticsActionPaste,
576 kFlutterSemanticsActionSetSelection));
578 if (info->action == kFlutterSemanticsActionSetSelection) {
591 atk_editable_text_copy_text(ATK_EDITABLE_TEXT(node), 2, 5);
593 EXPECT_EQ(extent, 5);
594 EXPECT_EQ(act, kFlutterSemanticsActionCopy);
596 atk_editable_text_cut_text(ATK_EDITABLE_TEXT(node), 1, 4);
598 EXPECT_EQ(extent, 4);
599 EXPECT_EQ(act, kFlutterSemanticsActionCut);
601 atk_editable_text_paste_text(ATK_EDITABLE_TEXT(node), 3);
603 EXPECT_EQ(extent, 3);
604 EXPECT_EQ(act, kFlutterSemanticsActionPaste);
607 TEST(FlAccessibleTextFieldTest, TextBoundary) {
614 "Lorem ipsum.\nDolor sit amet. Praesent commodo?"
615 "\n\nPraesent et felis dui.");
618 gint start_offset = -1, end_offset = -1;
619 g_autofree gchar* lorem_char = atk_text_get_string_at_offset(
620 ATK_TEXT(node), 0, ATK_TEXT_GRANULARITY_CHAR, &start_offset, &end_offset);
621 EXPECT_STREQ(lorem_char,
"L");
622 EXPECT_EQ(start_offset, 0);
623 EXPECT_EQ(end_offset, 1);
625 g_autofree gchar* lorem_word = atk_text_get_string_at_offset(
626 ATK_TEXT(node), 0, ATK_TEXT_GRANULARITY_WORD, &start_offset, &end_offset);
627 EXPECT_STREQ(lorem_word,
"Lorem");
628 EXPECT_EQ(start_offset, 0);
629 EXPECT_EQ(end_offset, 5);
631 g_autofree gchar* lorem_sentence = atk_text_get_string_at_offset(
632 ATK_TEXT(node), 0, ATK_TEXT_GRANULARITY_SENTENCE, &start_offset,
634 EXPECT_STREQ(lorem_sentence,
"Lorem ipsum.");
635 EXPECT_EQ(start_offset, 0);
636 EXPECT_EQ(end_offset, 12);
638 g_autofree gchar* lorem_line = atk_text_get_string_at_offset(
639 ATK_TEXT(node), 0, ATK_TEXT_GRANULARITY_LINE, &start_offset, &end_offset);
640 EXPECT_STREQ(lorem_line,
"Lorem ipsum.");
641 EXPECT_EQ(start_offset, 0);
642 EXPECT_EQ(end_offset, 12);
644 g_autofree gchar* lorem_paragraph = atk_text_get_string_at_offset(
645 ATK_TEXT(node), 0, ATK_TEXT_GRANULARITY_PARAGRAPH, &start_offset,
647 EXPECT_STREQ(lorem_paragraph,
648 "Lorem ipsum.\nDolor sit amet. Praesent commodo?");
649 EXPECT_EQ(start_offset, 0);
650 EXPECT_EQ(end_offset, 46);
653 g_autofree gchar* praesent_char = atk_text_get_string_at_offset(
654 ATK_TEXT(node), 32, ATK_TEXT_GRANULARITY_CHAR, &start_offset,
656 EXPECT_STREQ(praesent_char,
"e");
657 EXPECT_EQ(start_offset, 32);
658 EXPECT_EQ(end_offset, 33);
660 g_autofree gchar* praesent_word = atk_text_get_string_at_offset(
661 ATK_TEXT(node), 32, ATK_TEXT_GRANULARITY_WORD, &start_offset,
663 EXPECT_STREQ(praesent_word,
"Praesent");
664 EXPECT_EQ(start_offset, 29);
665 EXPECT_EQ(end_offset, 37);
667 g_autofree gchar* praesent_sentence = atk_text_get_string_at_offset(
668 ATK_TEXT(node), 32, ATK_TEXT_GRANULARITY_SENTENCE, &start_offset,
670 EXPECT_STREQ(praesent_sentence,
"Praesent commodo?");
671 EXPECT_EQ(start_offset, 29);
672 EXPECT_EQ(end_offset, 46);
674 g_autofree gchar* praesent_line = atk_text_get_string_at_offset(
675 ATK_TEXT(node), 32, ATK_TEXT_GRANULARITY_LINE, &start_offset,
677 EXPECT_STREQ(praesent_line,
"Dolor sit amet. Praesent commodo?");
678 EXPECT_EQ(start_offset, 13);
679 EXPECT_EQ(end_offset, 46);
681 g_autofree gchar* praesent_paragraph = atk_text_get_string_at_offset(
682 ATK_TEXT(node), 32, ATK_TEXT_GRANULARITY_PARAGRAPH, &start_offset,
684 EXPECT_STREQ(praesent_paragraph,
685 "Lorem ipsum.\nDolor sit amet. Praesent commodo?");
686 EXPECT_EQ(start_offset, 0);
687 EXPECT_EQ(end_offset, 46);
690 g_autofree gchar* felis_char = atk_text_get_string_at_offset(
691 ATK_TEXT(node), 64, ATK_TEXT_GRANULARITY_CHAR, &start_offset,
693 EXPECT_STREQ(felis_char,
"s");
694 EXPECT_EQ(start_offset, 64);
695 EXPECT_EQ(end_offset, 65);
697 g_autofree gchar* felis_word = atk_text_get_string_at_offset(
698 ATK_TEXT(node), 64, ATK_TEXT_GRANULARITY_WORD, &start_offset,
700 EXPECT_STREQ(felis_word,
"felis");
701 EXPECT_EQ(start_offset, 60);
702 EXPECT_EQ(end_offset, 65);
704 g_autofree gchar* felis_sentence = atk_text_get_string_at_offset(
705 ATK_TEXT(node), 64, ATK_TEXT_GRANULARITY_SENTENCE, &start_offset,
707 EXPECT_STREQ(felis_sentence,
"Praesent et felis dui.");
708 EXPECT_EQ(start_offset, 48);
709 EXPECT_EQ(end_offset, 70);
711 g_autofree gchar* felis_line = atk_text_get_string_at_offset(
712 ATK_TEXT(node), 64, ATK_TEXT_GRANULARITY_LINE, &start_offset,
714 EXPECT_STREQ(felis_line,
"Praesent et felis dui.");
715 EXPECT_EQ(start_offset, 48);
716 EXPECT_EQ(end_offset, 70);
718 g_autofree gchar* felis_paragraph = atk_text_get_string_at_offset(
719 ATK_TEXT(node), 64, ATK_TEXT_GRANULARITY_PARAGRAPH, &start_offset,
721 EXPECT_STREQ(felis_paragraph,
"\nPraesent et felis dui.");
722 EXPECT_EQ(start_offset, 47);
723 EXPECT_EQ(end_offset, 70);
727 TEST(FlAccessibleTextFieldTest, TextBoundaryOffsetBeyondEnd) {
737 gint start_offset = -1, end_offset = -1;
738 g_autofree gchar* char_result = atk_text_get_string_at_offset(
739 ATK_TEXT(node), 100, ATK_TEXT_GRANULARITY_CHAR, &start_offset,
741 EXPECT_NE(char_result,
nullptr);
742 EXPECT_GE(start_offset, 0);
743 EXPECT_LE(end_offset, 5);
745 g_autofree gchar* word_result = atk_text_get_string_at_offset(
746 ATK_TEXT(node), 100, ATK_TEXT_GRANULARITY_WORD, &start_offset,
748 EXPECT_NE(word_result,
nullptr);
749 EXPECT_GE(start_offset, 0);
750 EXPECT_LE(end_offset, 5);
752 g_autofree gchar* sentence_result = atk_text_get_string_at_offset(
753 ATK_TEXT(node), 100, ATK_TEXT_GRANULARITY_SENTENCE, &start_offset,
755 EXPECT_NE(sentence_result,
nullptr);
756 EXPECT_GE(start_offset, 0);
757 EXPECT_LE(end_offset, 5);
761 TEST(FlAccessibleTextFieldTest, TextBoundaryOffsetAtStart) {
770 gint start_offset = -1, end_offset = -1;
771 g_autofree gchar* char_result = atk_text_get_string_at_offset(
772 ATK_TEXT(node), 0, ATK_TEXT_GRANULARITY_CHAR, &start_offset, &end_offset);
773 EXPECT_NE(char_result,
nullptr);
774 EXPECT_EQ(start_offset, 0);
775 EXPECT_EQ(end_offset, 1);
776 EXPECT_STREQ(char_result,
"H");
778 g_autofree gchar* word_result = atk_text_get_string_at_offset(
779 ATK_TEXT(node), 0, ATK_TEXT_GRANULARITY_WORD, &start_offset, &end_offset);
780 EXPECT_NE(word_result,
nullptr);
781 EXPECT_EQ(start_offset, 0);
782 EXPECT_EQ(end_offset, 5);
783 EXPECT_STREQ(word_result,
"Hello");
787 TEST(FlAccessibleTextFieldTest, TextBoundaryEmptyText) {
794 gint start_offset = -1, end_offset = -1;
795 g_autofree gchar* char_result = atk_text_get_string_at_offset(
796 ATK_TEXT(node), 0, ATK_TEXT_GRANULARITY_CHAR, &start_offset, &end_offset);
797 EXPECT_NE(char_result,
nullptr);
798 EXPECT_EQ(start_offset, 0);
799 EXPECT_STREQ(char_result,
"");
801 g_autofree gchar* word_result = atk_text_get_string_at_offset(
802 ATK_TEXT(node), 0, ATK_TEXT_GRANULARITY_WORD, &start_offset, &end_offset);
803 EXPECT_NE(word_result,
nullptr);
804 EXPECT_EQ(start_offset, 0);
805 EXPECT_STREQ(word_result,
"");
809 TEST(FlAccessibleTextFieldTest, TextBoundaryOffsetAtEnd) {
818 gint char_count = atk_text_get_character_count(ATK_TEXT(node));
819 EXPECT_EQ(char_count, 11);
821 gint start_offset = -1, end_offset = -1;
822 g_autofree gchar* char_result = atk_text_get_string_at_offset(
823 ATK_TEXT(node), char_count, ATK_TEXT_GRANULARITY_CHAR, &start_offset,
825 EXPECT_NE(char_result,
nullptr);
826 EXPECT_GE(start_offset, 0);
827 EXPECT_LE(end_offset, char_count);
829 g_autofree gchar* word_result = atk_text_get_string_at_offset(
830 ATK_TEXT(node), char_count, ATK_TEXT_GRANULARITY_WORD, &start_offset,
832 EXPECT_NE(word_result,
nullptr);
833 EXPECT_GE(start_offset, 0);
834 EXPECT_LE(end_offset, char_count);
g_autoptr(FlEngine) engine
void fl_accessible_node_set_text_selection(FlAccessibleNode *self, gint base, gint extent)
void fl_accessible_node_set_actions(FlAccessibleNode *self, FlutterSemanticsAction actions)
void fl_accessible_node_set_value(FlAccessibleNode *self, const gchar *value)
FlAccessibleNode * fl_accessible_text_field_new(FlEngine *engine, FlutterViewId view_id, int32_t id)
static FlValue * decode_semantic_data(const uint8_t *data, size_t data_length)
TEST(FlAccessibleTextFieldTest, SetValue)
G_MODULE_EXPORT FlDartProject * fl_dart_project_new()
FlutterEngineProcTable * fl_engine_get_embedder_api(FlEngine *self)
gboolean fl_engine_start(FlEngine *self, GError **error)
G_MODULE_EXPORT FlEngine * fl_engine_new(FlDartProject *project)
G_MODULE_EXPORT FlValue * fl_message_codec_decode_message(FlMessageCodec *self, GBytes *message, GError **error)
const uint8_t uint32_t uint32_t GError ** error
G_MODULE_EXPORT FlStandardMessageCodec * fl_standard_message_codec_new()
G_MODULE_EXPORT FlValue * fl_value_lookup_string(FlValue *self, const gchar *key)
G_MODULE_EXPORT int64_t fl_value_get_int(FlValue *self)
G_MODULE_EXPORT void fl_value_unref(FlValue *self)
G_MODULE_EXPORT FlValueType fl_value_get_type(FlValue *self)
G_MODULE_EXPORT FlValue * fl_value_new_bool(bool value)
G_MODULE_EXPORT bool fl_value_equal(FlValue *a, FlValue *b)
G_MODULE_EXPORT const gchar * fl_value_get_string(FlValue *self)
typedefG_BEGIN_DECLS struct _FlValue FlValue