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.
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"
14 // See ui/events/keycodes/keyboard_codes.h
15 #define VKEY_UNKNOWN 0
18 #define VKEY_SPACE VK_SPACE
19 #define VKEY_RETURN VK_RETURN
20 #elif defined(OS_POSIX)
22 #define VKEY_SPACE 0x20
23 #define VKEY_RETURN 0x0D
25 #error "Unsupported platform"
28 #define TEXTFIELD_TEST(name) UI_THREAD_TEST(ViewsTextfieldTest, name)
29 #define TEXTFIELD_TEST_ASYNC(name) \
30 UI_THREAD_TEST_ASYNC(ViewsTextfieldTest, name)
34 void TextfieldContentsImpl() {
35 CefRefPtr<CefTextfield> textfield = CefTextfield::CreateTextfield(nullptr);
36 EXPECT_TRUE(textfield.get());
37 EXPECT_TRUE(textfield->AsTextfield().get());
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());
46 const char kText[] = "My test message!";
47 textfield->SetText(kText);
48 EXPECT_STREQ(kText, textfield->GetText().ToString().c_str());
50 size_t cursor_pos = sizeof(kText) - 1;
51 EXPECT_EQ(cursor_pos, textfield->GetCursorPosition());
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());
61 EXPECT_FALSE(textfield->HasSelection());
62 EXPECT_EQ(CefRange(static_cast<int>(cursor_pos),
63 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());
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());
78 cursor_pos = sizeof(kReplaceText) - 1;
79 EXPECT_EQ(cursor_pos, textfield->GetCursorPosition());
82 EXPECT_FALSE(textfield->HasSelection());
83 textfield->SelectAll(false);
84 EXPECT_TRUE(textfield->HasSelection());
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());
91 // Test clear selection.
92 textfield->ClearSelection();
93 EXPECT_FALSE(textfield->HasSelection());
94 EXPECT_EQ(CefRange(static_cast<int>(cursor_pos),
95 static_cast<int>(cursor_pos)),
96 textfield->GetSelectedRange());
97 EXPECT_EQ(cursor_pos, textfield->GetCursorPosition());
99 // Test selection with command.
100 EXPECT_TRUE(textfield->IsCommandEnabled(IDS_APP_SELECT_ALL));
101 textfield->ExecuteCommand(IDS_APP_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());
107 textfield->ClearEditHistory();
110 void TextfieldStyleImpl() {
111 CefRefPtr<CefTextfield> textfield = CefTextfield::CreateTextfield(nullptr);
112 EXPECT_TRUE(textfield.get());
115 EXPECT_FALSE(textfield->IsPasswordInput());
116 EXPECT_FALSE(textfield->IsReadOnly());
118 // Test password input.
119 textfield->SetPasswordInput(true);
120 EXPECT_TRUE(textfield->IsPasswordInput());
121 textfield->SetPasswordInput(false);
122 EXPECT_FALSE(textfield->IsPasswordInput());
125 textfield->SetReadOnly(true);
126 EXPECT_TRUE(textfield->IsReadOnly());
127 textfield->SetReadOnly(false);
128 EXPECT_FALSE(textfield->IsReadOnly());
131 const cef_color_t color = CefColorSetARGB(255, 255, 0, 255);
133 EXPECT_NE(color, textfield->GetTextColor());
134 textfield->SetTextColor(color);
135 EXPECT_EQ(color, textfield->GetTextColor());
137 EXPECT_NE(color, textfield->GetSelectionTextColor());
138 textfield->SetSelectionTextColor(color);
139 EXPECT_EQ(color, textfield->GetSelectionTextColor());
141 EXPECT_NE(color, textfield->GetSelectionBackgroundColor());
142 textfield->SetSelectionBackgroundColor(color);
143 EXPECT_EQ(color, textfield->GetSelectionBackgroundColor());
145 textfield->SetPlaceholderTextColor(color);
148 textfield->SetFontList("Arial, 14px");
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));
156 // Test placeholder text.
157 textfield->SetPlaceholderText(kText);
158 EXPECT_STREQ(kText, textfield->GetPlaceholderText().ToString().c_str());
160 textfield->SetAccessibleName("MyTextfield");
165 // Test Textfield getters/setters.
166 TEXTFIELD_TEST(TextfieldContents);
167 TEXTFIELD_TEST(TextfieldStyle);
172 const int kTextfieldID = 1;
174 // Contents need to be supported by the TranslateKey function.
175 const char kTestInputMessage[] = "Test Message";
177 void TranslateKey(int c, int* keycode, uint32* modifiers) {
178 *keycode = VKEY_UNKNOWN;
181 if (c >= 'a' && c <= 'z') {
182 *keycode = VKEY_A + (c - 'a');
183 } else if (c >= 'A' && c <= 'Z') {
184 *keycode = VKEY_A + (c - 'A');
185 *modifiers = EVENTFLAG_SHIFT_DOWN;
186 } else if (c == ' ') {
187 *keycode = VKEY_SPACE;
191 class TestTextfieldDelegate : public CefTextfieldDelegate {
193 TestTextfieldDelegate() {
196 bool OnKeyEvent(CefRefPtr<CefTextfield> textfield,
197 const CefKeyEvent& event) override {
198 EXPECT_TRUE(textfield.get());
199 EXPECT_EQ(textfield->GetID(), kTextfieldID);
201 if (event.type == KEYEVENT_RAWKEYDOWN &&
202 event.windows_key_code == VKEY_RETURN) {
203 // Got the whole string. Finish the test asynchronously.
205 base::Bind(&TestTextfieldDelegate::FinishTest, this, textfield));
209 if (event.type == KEYEVENT_CHAR) {
212 TranslateKey(kTestInputMessage[index_++], &keycode, &modifiers);
214 EXPECT_EQ(keycode, event.windows_key_code);
215 EXPECT_EQ(modifiers, event.modifiers);
221 void OnAfterUserAction(CefRefPtr<CefTextfield> textfield) override {
222 after_user_action_ct_++;
226 void FinishTest(CefRefPtr<CefTextfield> textfield) {
227 // OnAfterUserAction() should be called for each unhandled character.
228 EXPECT_EQ(sizeof(kTestInputMessage) - 1, after_user_action_ct_);
230 // Verify the completed contents.
231 EXPECT_STREQ(kTestInputMessage, textfield->GetText().ToString().c_str());
233 // Close the window to end the test.
234 textfield->GetWindow()->Close();
238 size_t after_user_action_ct_ = 0;
240 IMPLEMENT_REFCOUNTING(TestTextfieldDelegate);
241 DISALLOW_COPY_AND_ASSIGN(TestTextfieldDelegate);
244 void RunTextfieldKeyEvent(CefRefPtr<CefWindow> window) {
245 CefRefPtr<CefTextfield> textfield = CefTextfield::CreateTextfield(
246 new TestTextfieldDelegate());
247 textfield->SetID(kTextfieldID);
249 EXPECT_TRUE(textfield->AsTextfield());
250 EXPECT_EQ(kTextfieldID, textfield->GetID());
251 EXPECT_TRUE(textfield->IsVisible());
252 EXPECT_FALSE(textfield->IsDrawn());
254 window->AddChildView(textfield);
257 EXPECT_TRUE(window->IsSame(textfield->GetWindow()));
258 EXPECT_TRUE(window->IsSame(textfield->GetParentView()));
259 EXPECT_TRUE(textfield->IsSame(window->GetViewForID(kTextfieldID)));
260 EXPECT_TRUE(textfield->IsVisible());
261 EXPECT_TRUE(textfield->IsDrawn());
265 // Give input focus to the textfield.
266 textfield->RequestFocus();
268 // Send the contents of |kTestInputMessage| to the textfield.
269 for (size_t i = 0; i < sizeof(kTestInputMessage) - 1; ++i) {
272 TranslateKey(kTestInputMessage[i], &keycode, &modifiers);
273 window->SendKeyPress(keycode, modifiers);
276 // Send return to end the text input.
277 window->SendKeyPress(VKEY_RETURN, 0);
280 void TextfieldKeyEventImpl(CefRefPtr<CefWaitableEvent> event) {
281 TestWindowDelegate::Config config;
282 config.on_window_created = base::Bind(RunTextfieldKeyEvent);
283 config.close_window = false;
284 TestWindowDelegate::RunTest(event, config);
289 // Test Textfield input and events. This is primarily to exercise exposed CEF
290 // APIs and is not intended to comprehensively test Textfield-related behavior
291 // (which we presume that Chromium is testing).
292 TEXTFIELD_TEST_ASYNC(TextfieldKeyEvent);