1 // Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4
5 #include "include/base/cef_bind.h"
6 #include "include/cef_pack_strings.h"
7 #include "include/views/cef_textfield.h"
8 #include "include/views/cef_textfield_delegate.h"
9 #include "include/wrapper/cef_closure_task.h"
10 #include "tests/ceftests/thread_helper.h"
11 #include "tests/ceftests/views/test_window_delegate.h"
12 #include "tests/gtest/include/gtest/gtest.h"
13
14 // See ui/events/keycodes/keyboard_codes.h
15 #define VKEY_UNKNOWN 0
16 #if defined(OS_WIN)
17 #define VKEY_A 'A'
18 #define VKEY_SPACE VK_SPACE
19 #define VKEY_RETURN VK_RETURN
20 #elif defined(OS_POSIX)
21 #define VKEY_A 0x41
22 #define VKEY_SPACE 0x20
23 #define VKEY_RETURN 0x0D
24 #else
25 #error "Unsupported platform"
26 #endif
27
28 #define TEXTFIELD_TEST(name) UI_THREAD_TEST(ViewsTextfieldTest, name)
29 #define TEXTFIELD_TEST_ASYNC(name) \
30 UI_THREAD_TEST_ASYNC(ViewsTextfieldTest, name)
31
32 namespace {
33
TextfieldContentsImpl()34 void TextfieldContentsImpl() {
35 CefRefPtr<CefTextfield> textfield = CefTextfield::CreateTextfield(nullptr);
36 EXPECT_TRUE(textfield.get());
37 EXPECT_TRUE(textfield->AsTextfield().get());
38
39 // Test defaults.
40 EXPECT_TRUE(textfield->GetText().empty());
41 EXPECT_FALSE(textfield->HasSelection());
42 EXPECT_EQ(CefRange(0, 0), textfield->GetSelectedRange());
43 EXPECT_EQ(0U, textfield->GetCursorPosition());
44
45 // Test set/get text.
46 const char kText[] = "My test message!";
47 textfield->SetText(kText);
48 EXPECT_STREQ(kText, textfield->GetText().ToString().c_str());
49
50 size_t cursor_pos = sizeof(kText) - 1;
51 EXPECT_EQ(cursor_pos, textfield->GetCursorPosition());
52
53 // Test append text.
54 const char kAppendText[] = " And more.";
55 textfield->AppendText(kAppendText);
56 EXPECT_STREQ((std::string(kText) + kAppendText).c_str(),
57 textfield->GetText().ToString().c_str());
58 EXPECT_EQ(cursor_pos, textfield->GetCursorPosition());
59
60 // Test select range.
61 EXPECT_FALSE(textfield->HasSelection());
62 EXPECT_EQ(
63 CefRange(static_cast<int>(cursor_pos), static_cast<int>(cursor_pos)),
64 textfield->GetSelectedRange());
65 textfield->SelectRange(CefRange(0, static_cast<int>(cursor_pos)));
66 EXPECT_TRUE(textfield->HasSelection());
67 EXPECT_EQ(CefRange(0, static_cast<int>(cursor_pos)),
68 textfield->GetSelectedRange());
69 EXPECT_STREQ(kText, textfield->GetSelectedText().ToString().c_str());
70 EXPECT_EQ(cursor_pos, textfield->GetCursorPosition());
71
72 // Test insert or replace.
73 const char kReplaceText[] = "Other text.";
74 textfield->InsertOrReplaceText(kReplaceText);
75 EXPECT_STREQ((std::string(kReplaceText) + kAppendText).c_str(),
76 textfield->GetText().ToString().c_str());
77
78 cursor_pos = sizeof(kReplaceText) - 1;
79 EXPECT_EQ(cursor_pos, textfield->GetCursorPosition());
80
81 // Test select all.
82 EXPECT_FALSE(textfield->HasSelection());
83 textfield->SelectAll(false);
84 EXPECT_TRUE(textfield->HasSelection());
85
86 cursor_pos = sizeof(kReplaceText) + sizeof(kAppendText) - 2;
87 EXPECT_EQ(CefRange(0, static_cast<int>(cursor_pos)),
88 textfield->GetSelectedRange());
89 EXPECT_EQ(cursor_pos, textfield->GetCursorPosition());
90
91 // Test clear selection.
92 textfield->ClearSelection();
93 EXPECT_FALSE(textfield->HasSelection());
94 EXPECT_EQ(
95 CefRange(static_cast<int>(cursor_pos), static_cast<int>(cursor_pos)),
96 textfield->GetSelectedRange());
97 EXPECT_EQ(cursor_pos, textfield->GetCursorPosition());
98
99 // Test selection with command.
100 EXPECT_TRUE(textfield->IsCommandEnabled(CEF_TFC_SELECT_ALL));
101 textfield->ExecuteCommand(CEF_TFC_SELECT_ALL);
102 EXPECT_TRUE(textfield->HasSelection());
103 EXPECT_EQ(CefRange(0, static_cast<int>(cursor_pos)),
104 textfield->GetSelectedRange());
105 EXPECT_EQ(cursor_pos, textfield->GetCursorPosition());
106
107 textfield->ClearEditHistory();
108 }
109
TextfieldStyleImpl()110 void TextfieldStyleImpl() {
111 CefRefPtr<CefTextfield> textfield = CefTextfield::CreateTextfield(nullptr);
112 EXPECT_TRUE(textfield.get());
113
114 // Test defaults.
115 EXPECT_FALSE(textfield->IsPasswordInput());
116 EXPECT_FALSE(textfield->IsReadOnly());
117
118 // Test password input.
119 textfield->SetPasswordInput(true);
120 EXPECT_TRUE(textfield->IsPasswordInput());
121 textfield->SetPasswordInput(false);
122 EXPECT_FALSE(textfield->IsPasswordInput());
123
124 // Test read only.
125 textfield->SetReadOnly(true);
126 EXPECT_TRUE(textfield->IsReadOnly());
127 textfield->SetReadOnly(false);
128 EXPECT_FALSE(textfield->IsReadOnly());
129
130 // Test colors.
131 const cef_color_t color = CefColorSetARGB(255, 255, 0, 255);
132
133 EXPECT_NE(color, textfield->GetTextColor());
134 textfield->SetTextColor(color);
135 EXPECT_EQ(color, textfield->GetTextColor());
136
137 EXPECT_NE(color, textfield->GetSelectionTextColor());
138 textfield->SetSelectionTextColor(color);
139 EXPECT_EQ(color, textfield->GetSelectionTextColor());
140
141 EXPECT_NE(color, textfield->GetSelectionBackgroundColor());
142 textfield->SetSelectionBackgroundColor(color);
143 EXPECT_EQ(color, textfield->GetSelectionBackgroundColor());
144
145 textfield->SetPlaceholderTextColor(color);
146
147 // Test fonts.
148 textfield->SetFontList("Arial, 14px");
149
150 // Test format ranges.
151 const char kText[] = "test text";
152 textfield->SetText(kText);
153 textfield->ApplyTextColor(color, CefRange(0, 5));
154 textfield->ApplyTextStyle(CEF_TEXT_STYLE_BOLD, true, CefRange(0, 5));
155
156 // Test placeholder text.
157 textfield->SetPlaceholderText(kText);
158 EXPECT_STREQ(kText, textfield->GetPlaceholderText().ToString().c_str());
159
160 textfield->SetAccessibleName("MyTextfield");
161 }
162
163 } // namespace
164
165 // Test Textfield getters/setters.
166 TEXTFIELD_TEST(TextfieldContents)
167 TEXTFIELD_TEST(TextfieldStyle)
168
169 namespace {
170
171 const int kTextfieldID = 1;
172
173 // Contents need to be supported by the TranslateKey function.
174 const char kTestInputMessage[] = "Test Message";
175
TranslateKey(int c,int * keycode,uint32 * modifiers)176 void TranslateKey(int c, int* keycode, uint32* modifiers) {
177 *keycode = VKEY_UNKNOWN;
178 *modifiers = 0;
179
180 if (c >= 'a' && c <= 'z') {
181 *keycode = VKEY_A + (c - 'a');
182 } else if (c >= 'A' && c <= 'Z') {
183 *keycode = VKEY_A + (c - 'A');
184 *modifiers = EVENTFLAG_SHIFT_DOWN;
185 } else if (c == ' ') {
186 *keycode = VKEY_SPACE;
187 }
188 }
189
190 class TestTextfieldDelegate : public CefTextfieldDelegate {
191 public:
TestTextfieldDelegate()192 TestTextfieldDelegate() {}
193
OnKeyEvent(CefRefPtr<CefTextfield> textfield,const CefKeyEvent & event)194 bool OnKeyEvent(CefRefPtr<CefTextfield> textfield,
195 const CefKeyEvent& event) override {
196 EXPECT_TRUE(textfield.get());
197 EXPECT_EQ(textfield->GetID(), kTextfieldID);
198
199 if (event.type == KEYEVENT_RAWKEYDOWN &&
200 event.windows_key_code == VKEY_RETURN) {
201 // Got the whole string. Finish the test asynchronously.
202 CefPostTask(TID_UI, base::Bind(&TestTextfieldDelegate::FinishTest, this,
203 textfield));
204 return true;
205 }
206
207 if (event.type == KEYEVENT_CHAR) {
208 int keycode;
209 uint32 modifiers;
210 TranslateKey(kTestInputMessage[index_++], &keycode, &modifiers);
211
212 EXPECT_EQ(keycode, event.windows_key_code);
213 EXPECT_EQ(modifiers, event.modifiers);
214 }
215
216 return false;
217 }
218
OnAfterUserAction(CefRefPtr<CefTextfield> textfield)219 void OnAfterUserAction(CefRefPtr<CefTextfield> textfield) override {
220 after_user_action_ct_++;
221 }
222
223 private:
FinishTest(CefRefPtr<CefTextfield> textfield)224 void FinishTest(CefRefPtr<CefTextfield> textfield) {
225 // OnAfterUserAction() should be called for each unhandled character.
226 EXPECT_EQ(sizeof(kTestInputMessage) - 1, after_user_action_ct_);
227
228 // Verify the completed contents.
229 EXPECT_STREQ(kTestInputMessage, textfield->GetText().ToString().c_str());
230
231 // Close the window to end the test.
232 textfield->GetWindow()->Close();
233 }
234
235 int index_ = 0;
236 size_t after_user_action_ct_ = 0;
237
238 IMPLEMENT_REFCOUNTING(TestTextfieldDelegate);
239 DISALLOW_COPY_AND_ASSIGN(TestTextfieldDelegate);
240 };
241
RunTextfieldKeyEvent(CefRefPtr<CefWindow> window)242 void RunTextfieldKeyEvent(CefRefPtr<CefWindow> window) {
243 CefRefPtr<CefTextfield> textfield =
244 CefTextfield::CreateTextfield(new TestTextfieldDelegate());
245 textfield->SetID(kTextfieldID);
246
247 EXPECT_TRUE(textfield->AsTextfield());
248 EXPECT_EQ(kTextfieldID, textfield->GetID());
249 EXPECT_TRUE(textfield->IsVisible());
250 EXPECT_FALSE(textfield->IsDrawn());
251
252 window->AddChildView(textfield);
253 window->Layout();
254
255 EXPECT_TRUE(window->IsSame(textfield->GetWindow()));
256 EXPECT_TRUE(window->IsSame(textfield->GetParentView()));
257 EXPECT_TRUE(textfield->IsSame(window->GetViewForID(kTextfieldID)));
258 EXPECT_TRUE(textfield->IsVisible());
259 EXPECT_TRUE(textfield->IsDrawn());
260
261 window->Show();
262
263 // Give input focus to the textfield.
264 textfield->RequestFocus();
265
266 // Send the contents of |kTestInputMessage| to the textfield.
267 for (size_t i = 0; i < sizeof(kTestInputMessage) - 1; ++i) {
268 int keycode;
269 uint32 modifiers;
270 TranslateKey(kTestInputMessage[i], &keycode, &modifiers);
271 window->SendKeyPress(keycode, modifiers);
272 }
273
274 // Send return to end the text input.
275 window->SendKeyPress(VKEY_RETURN, 0);
276 }
277
TextfieldKeyEventImpl(CefRefPtr<CefWaitableEvent> event)278 void TextfieldKeyEventImpl(CefRefPtr<CefWaitableEvent> event) {
279 TestWindowDelegate::Config config;
280 config.on_window_created = base::Bind(RunTextfieldKeyEvent);
281 config.close_window = false;
282 TestWindowDelegate::RunTest(event, config);
283 }
284
285 } // namespace
286
287 // Test Textfield input and events. This is primarily to exercise exposed CEF
288 // APIs and is not intended to comprehensively test Textfield-related behavior
289 // (which we presume that Chromium is testing).
290 TEXTFIELD_TEST_ASYNC(TextfieldKeyEvent)
291