• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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