cef/tests/unittests/views/textfield_unittest.cc

279 lines
8.8 KiB
C++

// Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "include/cef_pack_strings.h"
#include "include/views/cef_textfield.h"
#include "include/views/cef_textfield_delegate.h"
#include "include/wrapper/cef_closure_task.h"
#include "tests/unittests/thread_helper.h"
#include "tests/unittests/views/test_window_delegate.h"
#include "base/bind.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/keycodes/keyboard_codes.h"
#define TEXTFIELD_TEST(name) UI_THREAD_TEST(ViewsTextfieldTest, name)
#define TEXTFIELD_TEST_ASYNC(name) \
UI_THREAD_TEST_ASYNC(ViewsTextfieldTest, name)
namespace {
void TextfieldContentsImpl() {
CefRefPtr<CefTextfield> textfield = CefTextfield::CreateTextfield(nullptr);
EXPECT_TRUE(textfield.get());
EXPECT_TRUE(textfield->AsTextfield().get());
// Test defaults.
EXPECT_TRUE(textfield->GetText().empty());
EXPECT_FALSE(textfield->HasSelection());
EXPECT_EQ(CefRange(0, 0), textfield->GetSelectedRange());
EXPECT_EQ(0U, textfield->GetCursorPosition());
// Test set/get text.
const char kText[] = "My test message!";
textfield->SetText(kText);
EXPECT_STREQ(kText, textfield->GetText().ToString().c_str());
size_t cursor_pos = sizeof(kText) - 1;
EXPECT_EQ(cursor_pos, textfield->GetCursorPosition());
// Test append text.
const char kAppendText[] = " And more.";
textfield->AppendText(kAppendText);
EXPECT_STREQ((std::string(kText) + kAppendText).c_str(),
textfield->GetText().ToString().c_str());
EXPECT_EQ(cursor_pos, textfield->GetCursorPosition());
// Test select range.
EXPECT_FALSE(textfield->HasSelection());
EXPECT_EQ(CefRange(static_cast<int>(cursor_pos),
static_cast<int>(cursor_pos)),
textfield->GetSelectedRange());
textfield->SelectRange(CefRange(0, static_cast<int>(cursor_pos)));
EXPECT_TRUE(textfield->HasSelection());
EXPECT_EQ(CefRange(0, static_cast<int>(cursor_pos)),
textfield->GetSelectedRange());
EXPECT_STREQ(kText, textfield->GetSelectedText().ToString().c_str());
EXPECT_EQ(cursor_pos, textfield->GetCursorPosition());
// Test insert or replace.
const char kReplaceText[] = "Other text.";
textfield->InsertOrReplaceText(kReplaceText);
EXPECT_STREQ((std::string(kReplaceText) + kAppendText).c_str(),
textfield->GetText().ToString().c_str());
cursor_pos = sizeof(kReplaceText) - 1;
EXPECT_EQ(cursor_pos, textfield->GetCursorPosition());
// Test select all.
EXPECT_FALSE(textfield->HasSelection());
textfield->SelectAll(false);
EXPECT_TRUE(textfield->HasSelection());
cursor_pos = sizeof(kReplaceText) + sizeof(kAppendText) - 2;
EXPECT_EQ(CefRange(0, static_cast<int>(cursor_pos)),
textfield->GetSelectedRange());
EXPECT_EQ(cursor_pos, textfield->GetCursorPosition());
// Test clear selection.
textfield->ClearSelection();
EXPECT_FALSE(textfield->HasSelection());
EXPECT_EQ(CefRange(static_cast<int>(cursor_pos),
static_cast<int>(cursor_pos)),
textfield->GetSelectedRange());
EXPECT_EQ(cursor_pos, textfield->GetCursorPosition());
// Test selection with command.
EXPECT_TRUE(textfield->IsCommandEnabled(IDS_APP_SELECT_ALL));
textfield->ExecuteCommand(IDS_APP_SELECT_ALL);
EXPECT_TRUE(textfield->HasSelection());
EXPECT_EQ(CefRange(0, static_cast<int>(cursor_pos)),
textfield->GetSelectedRange());
EXPECT_EQ(cursor_pos, textfield->GetCursorPosition());
textfield->ClearEditHistory();
}
void TextfieldStyleImpl() {
CefRefPtr<CefTextfield> textfield = CefTextfield::CreateTextfield(nullptr);
EXPECT_TRUE(textfield.get());
// Test defaults.
EXPECT_FALSE(textfield->IsPasswordInput());
EXPECT_FALSE(textfield->IsReadOnly());
// Test password input.
textfield->SetPasswordInput(true);
EXPECT_TRUE(textfield->IsPasswordInput());
textfield->SetPasswordInput(false);
EXPECT_FALSE(textfield->IsPasswordInput());
// Test read only.
textfield->SetReadOnly(true);
EXPECT_TRUE(textfield->IsReadOnly());
textfield->SetReadOnly(false);
EXPECT_FALSE(textfield->IsReadOnly());
// Test colors.
const cef_color_t color = CefColorSetARGB(255, 255, 0, 255);
EXPECT_NE(color, textfield->GetTextColor());
textfield->SetTextColor(color);
EXPECT_EQ(color, textfield->GetTextColor());
EXPECT_NE(color, textfield->GetSelectionTextColor());
textfield->SetSelectionTextColor(color);
EXPECT_EQ(color, textfield->GetSelectionTextColor());
EXPECT_NE(color, textfield->GetSelectionBackgroundColor());
textfield->SetSelectionBackgroundColor(color);
EXPECT_EQ(color, textfield->GetSelectionBackgroundColor());
textfield->SetPlaceholderTextColor(color);
// Test fonts.
textfield->SetFontList("Arial, 14px");
// Test format ranges.
const char kText[] = "test text";
textfield->SetText(kText);
textfield->ApplyTextColor(color, CefRange(0, 5));
textfield->ApplyTextStyle(CEF_TEXT_STYLE_BOLD, true, CefRange(0, 5));
// Test placeholder text.
textfield->SetPlaceholderText(kText);
EXPECT_STREQ(kText, textfield->GetPlaceholderText().ToString().c_str());
textfield->SetAccessibleName("MyTextfield");
}
} // namespace
// Test Textfield getters/setters.
TEXTFIELD_TEST(TextfieldContents);
TEXTFIELD_TEST(TextfieldStyle);
namespace {
const int kTextfieldID = 1;
// Contents need to be supported by the TranslateKey function.
const char kTestInputMessage[] = "Test Message";
void TranslateKey(int c, int* keycode, uint32* modifiers) {
*keycode = ui::VKEY_UNKNOWN;
*modifiers = 0;
if (c >= 'a' && c <= 'z') {
*keycode = ui::VKEY_A + (c - 'a');
} else if (c >= 'A' && c <= 'Z') {
*keycode = ui::VKEY_A + (c - 'A');
*modifiers = EVENTFLAG_SHIFT_DOWN;
} else if (c == ' ') {
*keycode = ui::VKEY_SPACE;
}
}
class TestTextfieldDelegate : public CefTextfieldDelegate {
public:
TestTextfieldDelegate() {
}
bool OnKeyEvent(CefRefPtr<CefTextfield> textfield,
const CefKeyEvent& event) override {
EXPECT_TRUE(textfield.get());
EXPECT_EQ(textfield->GetID(), kTextfieldID);
if (event.type == KEYEVENT_RAWKEYDOWN &&
event.windows_key_code == ui::VKEY_RETURN) {
// Got the whole string. Finish the test asynchronously.
CefPostTask(TID_UI,
base::Bind(&TestTextfieldDelegate::FinishTest, this, textfield));
return true;
}
if (event.type == KEYEVENT_CHAR) {
int keycode;
uint32 modifiers;
TranslateKey(kTestInputMessage[index_++], &keycode, &modifiers);
EXPECT_EQ(keycode, event.windows_key_code);
EXPECT_EQ(modifiers, event.modifiers);
}
return false;
}
void OnAfterUserAction(CefRefPtr<CefTextfield> textfield) override {
after_user_action_ct_++;
}
private:
void FinishTest(CefRefPtr<CefTextfield> textfield) {
// OnAfterUserAction() should be called for each unhandled character.
EXPECT_EQ(sizeof(kTestInputMessage) - 1, after_user_action_ct_);
// Verify the completed contents.
EXPECT_STREQ(kTestInputMessage, textfield->GetText().ToString().c_str());
// Close the window to end the test.
textfield->GetWindow()->Close();
}
int index_ = 0;
size_t after_user_action_ct_ = 0;
IMPLEMENT_REFCOUNTING(TestTextfieldDelegate);
DISALLOW_COPY_AND_ASSIGN(TestTextfieldDelegate);
};
void RunTextfieldKeyEvent(CefRefPtr<CefWindow> window) {
CefRefPtr<CefTextfield> textfield = CefTextfield::CreateTextfield(
new TestTextfieldDelegate());
textfield->SetID(kTextfieldID);
EXPECT_TRUE(textfield->AsTextfield());
EXPECT_EQ(kTextfieldID, textfield->GetID());
EXPECT_TRUE(textfield->IsVisible());
EXPECT_FALSE(textfield->IsDrawn());
window->AddChildView(textfield);
window->Layout();
EXPECT_TRUE(window->IsSame(textfield->GetWindow()));
EXPECT_TRUE(window->IsSame(textfield->GetParentView()));
EXPECT_TRUE(textfield->IsSame(window->GetViewForID(kTextfieldID)));
EXPECT_TRUE(textfield->IsVisible());
EXPECT_TRUE(textfield->IsDrawn());
window->Show();
// Give input focus to the textfield.
textfield->RequestFocus();
// Send the contents of |kTestInputMessage| to the textfield.
for (size_t i = 0; i < sizeof(kTestInputMessage) - 1; ++i) {
int keycode;
uint32 modifiers;
TranslateKey(kTestInputMessage[i], &keycode, &modifiers);
window->SendKeyPress(keycode, modifiers);
}
// Send return to end the text input.
window->SendKeyPress(ui::VKEY_RETURN, 0);
}
void TextfieldKeyEventImpl(base::WaitableEvent* event) {
TestWindowDelegate::RunTest(event,
base::Bind(RunTextfieldKeyEvent), false, false);
}
} // namespace
// Test Textfield input and events. This is primarily to exercise exposed CEF
// APIs and is not intended to comprehensively test Textfield-related behavior
// (which we presume that Chromium is testing).
TEXTFIELD_TEST_ASYNC(TextfieldKeyEvent);