cef/tests/unittests/views/textfield_unittest.cc
Marshall Greenblatt 06e73fff15 Implement Views framework on Windows and Linux (issue #1749).
- Add Views header files in a new include/views directory.
- Add initial top-level window (CefWindow), control (CefBrowserView,
  CefLabelButton, CefMenuButton, CefPanel, CefScrollView,
  CefTextfield) and layout (CefBoxLayout, CefFlowLayout) support.
  See libcef/browser/views/view_impl.h comments for implementation
  details.
- Add Views example usage in cefclient and cefsimple and Views unit
  tests in cef_unittests. Pass the `--use-views` command-line flag to
  cefclient, cefsimple and cef_unittests to run using the Views
  framework instead of platform APIs. For cefclient and cefsimple
  this will create the browser window and all related functionality
  using the Views framework. For cef_unittests this will run all
  tests (except OSR tests) in a Views-based browser window. Views-
  specific unit tests (`--gtest_filter=Views*`) will be run even if
  the the `--use-views` flag is not specified.
- Pass the `--hide-frame` command-line flag to cefclient to demo a
  frameless Views-based browser window.
- Pass the `--hide-controls` command-line flag to cefclient to demo a
  browser window without top controls. This also works in non-Views
  mode.
- Pass the `--enable-high-dpi-support` command-line flag to
  cef_unittests on Windows to test high-DPI support on a display
  that supports it.
- Add CefImage for reading/writing image file formats.
- Add CefBrowser::DownloadImage() for downloading image URLs as a
  CefImage representation. This is primarily for loading favicons.
- Add CefMenuModel::CreateMenuModel() and CefMenuModelDelegate for
  creating custom menus. This is primarily for use with
  CefMenuButton.
- Add CefBrowser::TryCloseBrowser() helper for closing a browser.
  Also improve related documentation in cef_life_span_handler.h.
- Rename cef_page_range_t to cef_range_t. It is now also used by
  CefTextfield.
- Remove CefLifeSpanHandler::RunModal() which is never called.
- Add draggable regions example to cefclient.
2016-04-26 11:58:13 -04:00

274 lines
8.7 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(cursor_pos, cursor_pos), textfield->GetSelectedRange());
textfield->SelectRange(CefRange(0, cursor_pos));
EXPECT_TRUE(textfield->HasSelection());
EXPECT_EQ(CefRange(0, 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, cursor_pos), textfield->GetSelectedRange());
EXPECT_EQ(cursor_pos, textfield->GetCursorPosition());
// Test clear selection.
textfield->ClearSelection();
EXPECT_FALSE(textfield->HasSelection());
EXPECT_EQ(CefRange(cursor_pos, 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, 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());
EXPECT_NE(color, textfield->GetPlaceholderTextColor());
textfield->SetPlaceholderTextColor(color);
EXPECT_EQ(color, textfield->GetPlaceholderTextColor());
// 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);