| // Copyright 2014 The Chromium 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 "third_party/blink/renderer/core/html/forms/text_control_element.h" |
| |
| #include <memory> |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/blink/renderer/core/dom/document.h" |
| #include "third_party/blink/renderer/core/dom/node_computed_style.h" |
| #include "third_party/blink/renderer/core/dom/text.h" |
| #include "third_party/blink/renderer/core/editing/frame_selection.h" |
| #include "third_party/blink/renderer/core/editing/position.h" |
| #include "third_party/blink/renderer/core/frame/local_frame_view.h" |
| #include "third_party/blink/renderer/core/html/forms/html_input_element.h" |
| #include "third_party/blink/renderer/core/html/forms/html_text_area_element.h" |
| #include "third_party/blink/renderer/core/loader/empty_clients.h" |
| #include "third_party/blink/renderer/core/testing/dummy_page_holder.h" |
| #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" |
| |
| namespace blink { |
| |
| class TextControlElementTest : public testing::Test { |
| protected: |
| void SetUp() override; |
| |
| DummyPageHolder& Page() const { return *dummy_page_holder_; } |
| Document& GetDocument() const { return *document_; } |
| TextControlElement& TextControl() const { return *text_control_; } |
| HTMLInputElement& Input() const { return *input_; } |
| |
| void UpdateAllLifecyclePhases() { |
| GetDocument().View()->UpdateAllLifecyclePhasesForTest(); |
| } |
| |
| private: |
| std::unique_ptr<DummyPageHolder> dummy_page_holder_; |
| |
| Persistent<Document> document_; |
| Persistent<TextControlElement> text_control_; |
| Persistent<HTMLInputElement> input_; |
| }; |
| |
| void TextControlElementTest::SetUp() { |
| Page::PageClients page_clients; |
| FillWithEmptyClients(page_clients); |
| dummy_page_holder_ = |
| std::make_unique<DummyPageHolder>(IntSize(800, 600), &page_clients); |
| |
| document_ = &dummy_page_holder_->GetDocument(); |
| document_->documentElement()->setInnerHTML( |
| "<body><textarea id=textarea></textarea><input id=input /></body>"); |
| UpdateAllLifecyclePhases(); |
| text_control_ = ToTextControl(document_->getElementById("textarea")); |
| text_control_->focus(); |
| input_ = To<HTMLInputElement>(document_->getElementById("input")); |
| } |
| |
| TEST_F(TextControlElementTest, SetSelectionRange) { |
| EXPECT_EQ(0u, TextControl().selectionStart()); |
| EXPECT_EQ(0u, TextControl().selectionEnd()); |
| |
| TextControl().SetInnerEditorValue("Hello, text form."); |
| EXPECT_EQ(0u, TextControl().selectionStart()); |
| EXPECT_EQ(0u, TextControl().selectionEnd()); |
| |
| TextControl().SetSelectionRange(1, 3); |
| EXPECT_EQ(1u, TextControl().selectionStart()); |
| EXPECT_EQ(3u, TextControl().selectionEnd()); |
| } |
| |
| TEST_F(TextControlElementTest, SetSelectionRangeDoesNotCauseLayout) { |
| Input().focus(); |
| Input().setValue("Hello, input form."); |
| Input().SetSelectionRange(1, 1); |
| |
| // Force layout if document().updateStyleAndLayoutIgnorePendingStylesheets() |
| // is called. |
| GetDocument().body()->AppendChild(GetDocument().createTextNode("foo")); |
| unsigned start_layout_count = Page().GetFrameView().LayoutCountForTesting(); |
| EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdate()); |
| Input().SetSelectionRange(2, 2); |
| EXPECT_EQ(start_layout_count, Page().GetFrameView().LayoutCountForTesting()); |
| } |
| |
| TEST_F(TextControlElementTest, IndexForPosition) { |
| Input().setValue("Hello"); |
| HTMLElement* inner_editor = Input().InnerEditorElement(); |
| EXPECT_EQ(5u, TextControlElement::IndexForPosition( |
| inner_editor, |
| Position(inner_editor, PositionAnchorType::kAfterAnchor))); |
| } |
| |
| TEST_F(TextControlElementTest, ReadOnlyAttributeChangeEditability) { |
| Input().setAttribute(html_names::kStyleAttr, "all:initial"); |
| Input().setAttribute(html_names::kReadonlyAttr, ""); |
| UpdateAllLifecyclePhases(); |
| EXPECT_EQ(EUserModify::kReadOnly, |
| Input().InnerEditorElement()->GetComputedStyle()->UserModify()); |
| |
| Input().removeAttribute(html_names::kReadonlyAttr); |
| UpdateAllLifecyclePhases(); |
| EXPECT_EQ(EUserModify::kReadWritePlaintextOnly, |
| Input().InnerEditorElement()->GetComputedStyle()->UserModify()); |
| } |
| |
| TEST_F(TextControlElementTest, DisabledAttributeChangeEditability) { |
| Input().setAttribute(html_names::kStyleAttr, "all:initial"); |
| Input().setAttribute(html_names::kDisabledAttr, ""); |
| UpdateAllLifecyclePhases(); |
| EXPECT_EQ(EUserModify::kReadOnly, |
| Input().InnerEditorElement()->GetComputedStyle()->UserModify()); |
| |
| Input().removeAttribute(html_names::kDisabledAttr); |
| UpdateAllLifecyclePhases(); |
| EXPECT_EQ(EUserModify::kReadWritePlaintextOnly, |
| Input().InnerEditorElement()->GetComputedStyle()->UserModify()); |
| } |
| |
| } // namespace blink |