Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
fl_accessible_text_field_test.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Included first as it collides with the X11 headers.
6#include "gtest/gtest.h"
7
8#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
9#include "flutter/shell/platform/linux/fl_accessible_text_field.h"
10#include "flutter/shell/platform/linux/fl_engine_private.h"
11#include "flutter/shell/platform/linux/public/flutter_linux/fl_standard_message_codec.h"
12#include "flutter/shell/platform/linux/testing/fl_test.h"
13#include "flutter/shell/platform/linux/testing/mock_signal_handler.h"
14
15// MOCK_ENGINE_PROC is leaky by design
16// NOLINTBEGIN(clang-analyzer-core.StackAddressEscape)
17
18static FlValue* decode_semantic_data(const uint8_t* data, size_t data_length) {
19 g_autoptr(GBytes) bytes = g_bytes_new(data, data_length);
20 g_autoptr(FlStandardMessageCodec) codec = fl_standard_message_codec_new();
21 return fl_message_codec_decode_message(FL_MESSAGE_CODEC(codec), bytes,
22 nullptr);
23}
24
25// Tests that semantic node value updates from Flutter emit AtkText::text-insert
26// and AtkText::text-remove signals as expected.
27TEST(FlAccessibleTextFieldTest, SetValue) {
28 g_autoptr(FlEngine) engine = make_mock_engine();
29 g_autoptr(FlAccessibleNode) node = fl_accessible_text_field_new(engine, 1);
30
31 // "" -> "Flutter"
32 {
34 "text-insert");
35 flutter::testing::MockSignalHandler text_removed(node, "text-remove");
36
37 EXPECT_SIGNAL2(text_inserted, ::testing::Eq(0), ::testing::Eq(7));
38 EXPECT_SIGNAL(text_removed).Times(0);
39
40 fl_accessible_node_set_value(node, "Flutter");
41 }
42
43 // "Flutter" -> "Flutter"
44 {
45 flutter::testing::MockSignalHandler text_inserted(node, "text-insert");
46 flutter::testing::MockSignalHandler text_removed(node, "text-remove");
47
48 EXPECT_SIGNAL(text_inserted).Times(0);
49 EXPECT_SIGNAL(text_removed).Times(0);
50
51 fl_accessible_node_set_value(node, "Flutter");
52 }
53
54 // "Flutter" -> "engine"
55 {
57 "text-insert");
59 "text-remove");
60
61 EXPECT_SIGNAL2(text_inserted, ::testing::Eq(0), ::testing::Eq(6));
62 EXPECT_SIGNAL2(text_removed, ::testing::Eq(0), ::testing::Eq(7));
63
64 fl_accessible_node_set_value(node, "engine");
65 }
66
67 // "engine" -> ""
68 {
69 flutter::testing::MockSignalHandler text_inserted(node, "text-insert");
71 "text-remove");
72
73 EXPECT_SIGNAL(text_inserted).Times(0);
74 EXPECT_SIGNAL2(text_removed, ::testing::Eq(0), ::testing::Eq(6));
75
77 }
78}
79
80// Tests that semantic node selection updates from Flutter emit
81// AtkText::text-selection-changed and AtkText::text-caret-moved signals as
82// expected.
83TEST(FlAccessibleTextFieldTest, SetTextSelection) {
84 g_autoptr(FlEngine) engine = make_mock_engine();
85 g_autoptr(FlAccessibleNode) node = fl_accessible_text_field_new(engine, 1);
86
87 // [-1,-1] -> [2,3]
88 {
89 flutter::testing::MockSignalHandler text_selection_changed(
90 node, "text-selection-changed");
92 node, "text-caret-moved");
93
94 EXPECT_SIGNAL(text_selection_changed);
95 EXPECT_SIGNAL1(text_caret_moved, ::testing::Eq(3));
96
98 }
99
100 // [2,3] -> [3,3]
101 {
102 flutter::testing::MockSignalHandler text_selection_changed(
103 node, "text-selection-changed");
104 flutter::testing::MockSignalHandler text_caret_moved(node,
105 "text-caret-moved");
106
107 EXPECT_SIGNAL(text_selection_changed);
108 EXPECT_SIGNAL(text_caret_moved).Times(0);
109
111 }
112
113 // [3,3] -> [3,3]
114 {
115 flutter::testing::MockSignalHandler text_selection_changed(
116 node, "text-selection-changed");
117 flutter::testing::MockSignalHandler text_caret_moved(node,
118 "text-caret-moved");
119
120 EXPECT_SIGNAL(text_selection_changed).Times(0);
121 EXPECT_SIGNAL(text_caret_moved).Times(0);
122
124 }
125
126 // [3,3] -> [4,4]
127 {
128 flutter::testing::MockSignalHandler text_selection_changed(
129 node, "text-selection-changed");
131 node, "text-caret-moved");
132
133 EXPECT_SIGNAL(text_selection_changed).Times(0);
134 EXPECT_SIGNAL1(text_caret_moved, ::testing::Eq(4));
135
137 }
138}
139
140// Tests that fl_accessible_text_field_perform_action() passes the required
141// "expandSelection" argument for semantic cursor move actions.
142TEST(FlAccessibleTextFieldTest, PerformAction) {
143 g_autoptr(GPtrArray) action_datas = g_ptr_array_new_with_free_func(
144 reinterpret_cast<GDestroyNotify>(fl_value_unref));
145
146 g_autoptr(FlEngine) engine = make_mock_engine();
149 DispatchSemanticsAction,
150 ([&action_datas](auto engine, uint64_t id,
151 FlutterSemanticsAction action, const uint8_t* data,
152 size_t data_length) {
153 g_ptr_array_add(action_datas,
154 decode_semantic_data(data, data_length));
155 return kSuccess;
156 }));
157
158 g_autoptr(FlAccessibleNode) node = fl_accessible_text_field_new(engine, 1);
160 node, static_cast<FlutterSemanticsAction>(
165
166 g_autoptr(FlValue) expand_selection = fl_value_new_bool(false);
167
168 for (int i = 0; i < 4; ++i) {
169 atk_action_do_action(ATK_ACTION(node), i);
170
171 FlValue* data = static_cast<FlValue*>(g_ptr_array_index(action_datas, i));
172 EXPECT_NE(data, nullptr);
173 EXPECT_TRUE(fl_value_equal(data, expand_selection));
174 }
175}
176
177// Tests AtkText::get_character_count.
178TEST(FlAccessibleTextFieldTest, GetCharacterCount) {
179 g_autoptr(FlEngine) engine = make_mock_engine();
180 g_autoptr(FlAccessibleNode) node = fl_accessible_text_field_new(engine, 1);
181
182 EXPECT_EQ(atk_text_get_character_count(ATK_TEXT(node)), 0);
183
184 fl_accessible_node_set_value(node, "Flutter!");
185
186 EXPECT_EQ(atk_text_get_character_count(ATK_TEXT(node)), 8);
187}
188
189// Tests AtkText::get_text.
190TEST(FlAccessibleTextFieldTest, GetText) {
191 g_autoptr(FlEngine) engine = make_mock_engine();
192 g_autoptr(FlAccessibleNode) node = fl_accessible_text_field_new(engine, 1);
193
194 g_autofree gchar* empty = atk_text_get_text(ATK_TEXT(node), 0, -1);
195 EXPECT_STREQ(empty, "");
196
197 flutter::testing::MockSignalHandler text_inserted(node, "text-insert");
198 EXPECT_SIGNAL(text_inserted).Times(1);
199
200 fl_accessible_node_set_value(node, "Flutter!");
201
202 g_autofree gchar* flutter = atk_text_get_text(ATK_TEXT(node), 0, -1);
203 EXPECT_STREQ(flutter, "Flutter!");
204
205 g_autofree gchar* tt = atk_text_get_text(ATK_TEXT(node), 3, 5);
206 EXPECT_STREQ(tt, "tt");
207}
208
209// Tests AtkText::get_caret_offset.
210TEST(FlAccessibleTextFieldTest, GetCaretOffset) {
211 g_autoptr(FlEngine) engine = make_mock_engine();
212 g_autoptr(FlAccessibleNode) node = fl_accessible_text_field_new(engine, 1);
213
214 EXPECT_EQ(atk_text_get_caret_offset(ATK_TEXT(node)), -1);
215
217
218 EXPECT_EQ(atk_text_get_caret_offset(ATK_TEXT(node)), 2);
219}
220
221// Tests AtkText::set_caret_offset.
222TEST(FlAccessibleTextFieldTest, SetCaretOffset) {
223 int base = -1;
224 int extent = -1;
225
226 g_autoptr(FlEngine) engine = make_mock_engine();
229 DispatchSemanticsAction,
230 ([&base, &extent](auto engine, uint64_t id,
231 FlutterSemanticsAction action, const uint8_t* data,
232 size_t data_length) {
234 g_autoptr(FlValue) value = decode_semantic_data(data, data_length);
237 extent = fl_value_get_int(fl_value_lookup_string(value, "extent"));
238 return kSuccess;
239 }));
240
241 g_autoptr(FlAccessibleNode) node = fl_accessible_text_field_new(engine, 1);
242
243 EXPECT_TRUE(atk_text_set_caret_offset(ATK_TEXT(node), 3));
244 EXPECT_EQ(base, 3);
245 EXPECT_EQ(extent, 3);
246}
247
248// Tests AtkText::get_n_selections.
249TEST(FlAccessibleTextFieldTest, GetNSelections) {
250 g_autoptr(FlEngine) engine = make_mock_engine();
251 g_autoptr(FlAccessibleNode) node = fl_accessible_text_field_new(engine, 1);
252
253 EXPECT_EQ(atk_text_get_n_selections(ATK_TEXT(node)), 0);
254
256
257 EXPECT_EQ(atk_text_get_n_selections(ATK_TEXT(node)), 1);
258}
259
260// Tests AtkText::get_selection.
261TEST(FlAccessibleTextFieldTest, GetSelection) {
262 g_autoptr(FlEngine) engine = make_mock_engine();
263 g_autoptr(FlAccessibleNode) node = fl_accessible_text_field_new(engine, 1);
264
265 EXPECT_EQ(atk_text_get_selection(ATK_TEXT(node), 0, nullptr, nullptr),
266 nullptr);
267
268 fl_accessible_node_set_value(node, "Flutter");
270
271 gint start, end;
272 g_autofree gchar* selection =
273 atk_text_get_selection(ATK_TEXT(node), 0, &start, &end);
274 EXPECT_STREQ(selection, "utt");
275 EXPECT_EQ(start, 2);
276 EXPECT_EQ(end, 5);
277
278 // reverse
280 g_autofree gchar* reverse =
281 atk_text_get_selection(ATK_TEXT(node), 0, &start, &end);
282 EXPECT_STREQ(reverse, "utt");
283 EXPECT_EQ(start, 2);
284 EXPECT_EQ(end, 5);
285
286 // empty
288 EXPECT_EQ(atk_text_get_selection(ATK_TEXT(node), 0, &start, &end), nullptr);
289
290 // selection num != 0
291 EXPECT_EQ(atk_text_get_selection(ATK_TEXT(node), 1, &start, &end), nullptr);
292}
293
294// Tests AtkText::add_selection.
295TEST(FlAccessibleTextFieldTest, AddSelection) {
296 int base = -1;
297 int extent = -1;
298
299 g_autoptr(FlEngine) engine = make_mock_engine();
302 DispatchSemanticsAction,
303 ([&base, &extent](auto engine, uint64_t id,
304 FlutterSemanticsAction action, const uint8_t* data,
305 size_t data_length) {
307 g_autoptr(FlValue) value = decode_semantic_data(data, data_length);
310 extent = fl_value_get_int(fl_value_lookup_string(value, "extent"));
311 return kSuccess;
312 }));
313
314 g_autoptr(FlAccessibleNode) node = fl_accessible_text_field_new(engine, 1);
315
316 EXPECT_TRUE(atk_text_add_selection(ATK_TEXT(node), 2, 4));
317 EXPECT_EQ(base, 2);
318 EXPECT_EQ(extent, 4);
319
321
322 // already has selection
323 EXPECT_FALSE(atk_text_add_selection(ATK_TEXT(node), 6, 7));
324 EXPECT_EQ(base, 2);
325 EXPECT_EQ(extent, 4);
326}
327
328// Tests AtkText::remove_selection.
329TEST(FlAccessibleTextFieldTest, RemoveSelection) {
330 int base = -1;
331 int extent = -1;
332
333 g_autoptr(FlEngine) engine = make_mock_engine();
336 DispatchSemanticsAction,
337 ([&base, &extent](auto engine, uint64_t id,
338 FlutterSemanticsAction action, const uint8_t* data,
339 size_t data_length) {
341 g_autoptr(FlValue) value = decode_semantic_data(data, data_length);
344 extent = fl_value_get_int(fl_value_lookup_string(value, "extent"));
345 return kSuccess;
346 }));
347
348 g_autoptr(FlAccessibleNode) node = fl_accessible_text_field_new(engine, 1);
349
350 // no selection
351 EXPECT_FALSE(atk_text_remove_selection(ATK_TEXT(node), 0));
352 EXPECT_EQ(base, -1);
353 EXPECT_EQ(extent, -1);
354
356
357 // selection num != 0
358 EXPECT_FALSE(atk_text_remove_selection(ATK_TEXT(node), 1));
359 EXPECT_EQ(base, -1);
360 EXPECT_EQ(extent, -1);
361
362 // ok, collapses selection
363 EXPECT_TRUE(atk_text_remove_selection(ATK_TEXT(node), 0));
364 EXPECT_EQ(base, 4);
365 EXPECT_EQ(extent, 4);
366}
367
368// Tests AtkText::set_selection.
369TEST(FlAccessibleTextFieldTest, SetSelection) {
370 int base = -1;
371 int extent = -1;
372
373 g_autoptr(FlEngine) engine = make_mock_engine();
376 DispatchSemanticsAction,
377 ([&base, &extent](auto engine, uint64_t id,
378 FlutterSemanticsAction action, const uint8_t* data,
379 size_t data_length) {
381 g_autoptr(FlValue) value = decode_semantic_data(data, data_length);
384 extent = fl_value_get_int(fl_value_lookup_string(value, "extent"));
385 return kSuccess;
386 }));
387
388 g_autoptr(FlAccessibleNode) node = fl_accessible_text_field_new(engine, 1);
389
390 // selection num != 0
391 EXPECT_FALSE(atk_text_set_selection(ATK_TEXT(node), 1, 2, 4));
392 EXPECT_EQ(base, -1);
393 EXPECT_EQ(extent, -1);
394
395 EXPECT_TRUE(atk_text_set_selection(ATK_TEXT(node), 0, 2, 4));
396 EXPECT_EQ(base, 2);
397 EXPECT_EQ(extent, 4);
398
399 EXPECT_TRUE(atk_text_set_selection(ATK_TEXT(node), 0, 5, 1));
400 EXPECT_EQ(base, 5);
401 EXPECT_EQ(extent, 1);
402}
403
404// Tests AtkEditableText::set_text_contents.
405TEST(FlAccessibleTextFieldTest, SetTextContents) {
406 g_autofree gchar* text = nullptr;
407
408 g_autoptr(FlEngine) engine = make_mock_engine();
411 DispatchSemanticsAction,
412 ([&text](auto engine, uint64_t id, FlutterSemanticsAction action,
413 const uint8_t* data, size_t data_length) {
415 g_autoptr(FlValue) value = decode_semantic_data(data, data_length);
417 text = g_strdup(fl_value_get_string(value));
418 return kSuccess;
419 }));
420
421 g_autoptr(FlAccessibleNode) node = fl_accessible_text_field_new(engine, 1);
422
423 atk_editable_text_set_text_contents(ATK_EDITABLE_TEXT(node), "Flutter");
424 EXPECT_STREQ(text, "Flutter");
425}
426
427// Tests AtkEditableText::insert/delete_text.
428TEST(FlAccessibleTextFieldTest, InsertDeleteText) {
429 g_autofree gchar* text = nullptr;
430 int base = -1;
431 int extent = -1;
432
433 g_autoptr(FlEngine) engine = make_mock_engine();
436 DispatchSemanticsAction,
437 ([&text, &base, &extent](auto engine, uint64_t id,
439 const uint8_t* data, size_t data_length) {
440 EXPECT_THAT(action,
441 ::testing::AnyOf(kFlutterSemanticsActionSetText,
444 g_autoptr(FlValue) value =
445 decode_semantic_data(data, data_length);
447 g_free(text);
448 text = g_strdup(fl_value_get_string(value));
449 } else {
450 g_autoptr(FlValue) value =
451 decode_semantic_data(data, data_length);
454 extent =
456 }
457 return kSuccess;
458 }));
459
460 g_autoptr(FlAccessibleNode) node = fl_accessible_text_field_new(engine, 1);
461 fl_accessible_node_set_value(node, "Fler");
462
463 gint pos = 2;
464 atk_editable_text_insert_text(ATK_EDITABLE_TEXT(node), "utt", 3, &pos);
465 EXPECT_EQ(pos, 5);
466 EXPECT_STREQ(text, "Flutter");
467 EXPECT_EQ(base, pos);
468 EXPECT_EQ(extent, pos);
469
470 atk_editable_text_delete_text(ATK_EDITABLE_TEXT(node), 2, 5);
471 EXPECT_STREQ(text, "Fler");
472 EXPECT_EQ(base, 2);
473 EXPECT_EQ(extent, 2);
474}
475
476// Tests AtkEditableText::copy/cut/paste_text.
477TEST(FlAccessibleTextFieldTest, CopyCutPasteText) {
478 int base = -1;
479 int extent = -1;
481
482 g_autoptr(FlEngine) engine = make_mock_engine();
485 DispatchSemanticsAction,
486 ([&act, &base, &extent](auto engine, uint64_t id,
488 const uint8_t* data, size_t data_length) {
489 EXPECT_THAT(action,
490 ::testing::AnyOf(kFlutterSemanticsActionCut,
494 act = action;
496 g_autoptr(FlValue) value =
497 decode_semantic_data(data, data_length);
500 extent =
502 }
503 return kSuccess;
504 }));
505
506 g_autoptr(FlAccessibleNode) node = fl_accessible_text_field_new(engine, 1);
507
508 atk_editable_text_copy_text(ATK_EDITABLE_TEXT(node), 2, 5);
509 EXPECT_EQ(base, 2);
510 EXPECT_EQ(extent, 5);
511 EXPECT_EQ(act, kFlutterSemanticsActionCopy);
512
513 atk_editable_text_cut_text(ATK_EDITABLE_TEXT(node), 1, 4);
514 EXPECT_EQ(base, 1);
515 EXPECT_EQ(extent, 4);
516 EXPECT_EQ(act, kFlutterSemanticsActionCut);
517
518 atk_editable_text_paste_text(ATK_EDITABLE_TEXT(node), 3);
519 EXPECT_EQ(base, 3);
520 EXPECT_EQ(extent, 3);
521 EXPECT_EQ(act, kFlutterSemanticsActionPaste);
522}
523
524TEST(FlAccessibleTextFieldTest, TextBoundary) {
525 g_autoptr(FlEngine) engine = make_mock_engine();
526 g_autoptr(FlAccessibleNode) node = fl_accessible_text_field_new(engine, 1);
527
529 "Lorem ipsum.\nDolor sit amet. Praesent commodo?"
530 "\n\nPraesent et felis dui.");
531
532 // |Lorem
533 gint start_offset = -1, end_offset = -1;
534 g_autofree gchar* lorem_char = atk_text_get_string_at_offset(
535 ATK_TEXT(node), 0, ATK_TEXT_GRANULARITY_CHAR, &start_offset, &end_offset);
536 EXPECT_STREQ(lorem_char, "L");
537 EXPECT_EQ(start_offset, 0);
538 EXPECT_EQ(end_offset, 1);
539
540 g_autofree gchar* lorem_word = atk_text_get_string_at_offset(
541 ATK_TEXT(node), 0, ATK_TEXT_GRANULARITY_WORD, &start_offset, &end_offset);
542 EXPECT_STREQ(lorem_word, "Lorem");
543 EXPECT_EQ(start_offset, 0);
544 EXPECT_EQ(end_offset, 5);
545
546 g_autofree gchar* lorem_sentence = atk_text_get_string_at_offset(
547 ATK_TEXT(node), 0, ATK_TEXT_GRANULARITY_SENTENCE, &start_offset,
548 &end_offset);
549 EXPECT_STREQ(lorem_sentence, "Lorem ipsum.");
550 EXPECT_EQ(start_offset, 0);
551 EXPECT_EQ(end_offset, 12);
552
553 g_autofree gchar* lorem_line = atk_text_get_string_at_offset(
554 ATK_TEXT(node), 0, ATK_TEXT_GRANULARITY_LINE, &start_offset, &end_offset);
555 EXPECT_STREQ(lorem_line, "Lorem ipsum.");
556 EXPECT_EQ(start_offset, 0);
557 EXPECT_EQ(end_offset, 12);
558
559 g_autofree gchar* lorem_paragraph = atk_text_get_string_at_offset(
560 ATK_TEXT(node), 0, ATK_TEXT_GRANULARITY_PARAGRAPH, &start_offset,
561 &end_offset);
562 EXPECT_STREQ(lorem_paragraph,
563 "Lorem ipsum.\nDolor sit amet. Praesent commodo?");
564 EXPECT_EQ(start_offset, 0);
565 EXPECT_EQ(end_offset, 46);
566
567 // Pra|esent
568 g_autofree gchar* praesent_char = atk_text_get_string_at_offset(
569 ATK_TEXT(node), 32, ATK_TEXT_GRANULARITY_CHAR, &start_offset,
570 &end_offset);
571 EXPECT_STREQ(praesent_char, "e");
572 EXPECT_EQ(start_offset, 32);
573 EXPECT_EQ(end_offset, 33);
574
575 g_autofree gchar* praesent_word = atk_text_get_string_at_offset(
576 ATK_TEXT(node), 32, ATK_TEXT_GRANULARITY_WORD, &start_offset,
577 &end_offset);
578 EXPECT_STREQ(praesent_word, "Praesent");
579 EXPECT_EQ(start_offset, 29);
580 EXPECT_EQ(end_offset, 37);
581
582 g_autofree gchar* praesent_sentence = atk_text_get_string_at_offset(
583 ATK_TEXT(node), 32, ATK_TEXT_GRANULARITY_SENTENCE, &start_offset,
584 &end_offset);
585 EXPECT_STREQ(praesent_sentence, "Praesent commodo?");
586 EXPECT_EQ(start_offset, 29);
587 EXPECT_EQ(end_offset, 46);
588
589 g_autofree gchar* praesent_line = atk_text_get_string_at_offset(
590 ATK_TEXT(node), 32, ATK_TEXT_GRANULARITY_LINE, &start_offset,
591 &end_offset);
592 EXPECT_STREQ(praesent_line, "Dolor sit amet. Praesent commodo?");
593 EXPECT_EQ(start_offset, 13);
594 EXPECT_EQ(end_offset, 46);
595
596 g_autofree gchar* praesent_paragraph = atk_text_get_string_at_offset(
597 ATK_TEXT(node), 32, ATK_TEXT_GRANULARITY_PARAGRAPH, &start_offset,
598 &end_offset);
599 EXPECT_STREQ(praesent_paragraph,
600 "Lorem ipsum.\nDolor sit amet. Praesent commodo?");
601 EXPECT_EQ(start_offset, 0);
602 EXPECT_EQ(end_offset, 46);
603
604 // feli|s
605 g_autofree gchar* felis_char = atk_text_get_string_at_offset(
606 ATK_TEXT(node), 64, ATK_TEXT_GRANULARITY_CHAR, &start_offset,
607 &end_offset);
608 EXPECT_STREQ(felis_char, "s");
609 EXPECT_EQ(start_offset, 64);
610 EXPECT_EQ(end_offset, 65);
611
612 g_autofree gchar* felis_word = atk_text_get_string_at_offset(
613 ATK_TEXT(node), 64, ATK_TEXT_GRANULARITY_WORD, &start_offset,
614 &end_offset);
615 EXPECT_STREQ(felis_word, "felis");
616 EXPECT_EQ(start_offset, 60);
617 EXPECT_EQ(end_offset, 65);
618
619 g_autofree gchar* felis_sentence = atk_text_get_string_at_offset(
620 ATK_TEXT(node), 64, ATK_TEXT_GRANULARITY_SENTENCE, &start_offset,
621 &end_offset);
622 EXPECT_STREQ(felis_sentence, "Praesent et felis dui.");
623 EXPECT_EQ(start_offset, 48);
624 EXPECT_EQ(end_offset, 70);
625
626 g_autofree gchar* felis_line = atk_text_get_string_at_offset(
627 ATK_TEXT(node), 64, ATK_TEXT_GRANULARITY_LINE, &start_offset,
628 &end_offset);
629 EXPECT_STREQ(felis_line, "Praesent et felis dui.");
630 EXPECT_EQ(start_offset, 48);
631 EXPECT_EQ(end_offset, 70);
632
633 g_autofree gchar* felis_paragraph = atk_text_get_string_at_offset(
634 ATK_TEXT(node), 64, ATK_TEXT_GRANULARITY_PARAGRAPH, &start_offset,
635 &end_offset);
636 EXPECT_STREQ(felis_paragraph, "\nPraesent et felis dui.");
637 EXPECT_EQ(start_offset, 47);
638 EXPECT_EQ(end_offset, 70);
639}
640
641// NOLINTEND(clang-analyzer-core.StackAddressEscape)
#define TEST(S, s, D, expected)
SkPoint pos
@ kSuccess
Definition embedder.h:73
FlutterSemanticsAction
Definition embedder.h:113
@ kFlutterSemanticsActionMoveCursorForwardByCharacter
Move the cursor forward by one character.
Definition embedder.h:140
@ kFlutterSemanticsActionMoveCursorBackwardByCharacter
Move the cursor backward by one character.
Definition embedder.h:142
@ kFlutterSemanticsActionMoveCursorForwardByWord
Move the cursor forward by one word.
Definition embedder.h:160
@ kFlutterSemanticsActionSetSelection
Set the text selection to the given range.
Definition embedder.h:144
@ kFlutterSemanticsActionPaste
Paste the current content of the clipboard.
Definition embedder.h:150
@ kFlutterSemanticsActionCut
Cut the current selection and place it in the clipboard.
Definition embedder.h:148
@ kFlutterSemanticsActionCustomAction
Indicate that the user has invoked a custom accessibility action.
Definition embedder.h:156
@ kFlutterSemanticsActionCopy
Copy the current selection to the clipboard.
Definition embedder.h:146
@ kFlutterSemanticsActionMoveCursorBackwardByWord
Move the cursor backward by one word.
Definition embedder.h:162
@ kFlutterSemanticsActionSetText
Replace the current text in the text field.
Definition embedder.h:164
FlutterEngine engine
Definition main.cc:68
EMSCRIPTEN_KEEPALIVE void empty()
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)
glong glong end
FlAccessibleNode * fl_accessible_text_field_new(FlEngine *engine, int32_t id)
static FlValue * decode_semantic_data(const uint8_t *data, size_t data_length)
FlutterEngineProcTable * fl_engine_get_embedder_api(FlEngine *self)
Definition fl_engine.cc:579
static FlEngine * make_mock_engine()
G_MODULE_EXPORT FlValue * fl_message_codec_decode_message(FlMessageCodec *self, GBytes *message, GError **error)
uint8_t value
G_MODULE_EXPORT FlStandardMessageCodec * fl_standard_message_codec_new()
G_MODULE_EXPORT FlValue * fl_value_lookup_string(FlValue *self, const gchar *key)
Definition fl_value.cc:811
G_MODULE_EXPORT int64_t fl_value_get_int(FlValue *self)
Definition fl_value.cc:668
G_MODULE_EXPORT void fl_value_unref(FlValue *self)
Definition fl_value.cc:400
G_MODULE_EXPORT FlValueType fl_value_get_type(FlValue *self)
Definition fl_value.cc:466
G_MODULE_EXPORT FlValue * fl_value_new_bool(bool value)
Definition fl_value.cc:255
G_MODULE_EXPORT const gchar * fl_value_get_string(FlValue *self)
Definition fl_value.cc:682
G_MODULE_EXPORT bool fl_value_equal(FlValue *a, FlValue *b)
Definition fl_value.cc:471
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition fl_value.h:42
@ FL_VALUE_TYPE_STRING
Definition fl_value.h:69
@ FL_VALUE_TYPE_MAP
Definition fl_value.h:75
std::u16string text
#define EXPECT_SIGNAL(mock)
#define EXPECT_SIGNAL2(mock, a1, a2)
#define EXPECT_SIGNAL1(mock, a1)
#define MOCK_ENGINE_PROC(proc, mock_impl)
FlutterEngineDispatchSemanticsActionFnPtr DispatchSemanticsAction
Definition embedder.h:3343
#define EXPECT_TRUE(handle)
Definition unit_test.h:685