| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 // | |
| 5 // The DomAutocompleteTests in this file are responsible for ensuring the | |
| 6 // abstract dom autocomplete framework is correctly responding to events and | |
| 7 // delegating to appropriate places. This means concrete implementations should | |
| 8 // focus only on testing the code actually written for that implementation and | |
| 9 // those tests should be completely decoupled from WebCore::Event. | |
| 10 | |
| 11 #include <string> | |
| 12 | |
| 13 #include "config.h" | |
| 14 | |
| 15 #include "base/compiler_specific.h" | |
| 16 | |
| 17 MSVC_PUSH_WARNING_LEVEL(0); | |
| 18 #include "HTMLInputElement.h" | |
| 19 #include "HTMLFormElement.h" | |
| 20 #include "Document.h" | |
| 21 #include "Frame.h" | |
| 22 #include "Editor.h" | |
| 23 #include "EventNames.h" | |
| 24 #include "Event.h" | |
| 25 #include "EventListener.h" | |
| 26 #include <wtf/Threading.h> | |
| 27 MSVC_POP_WARNING(); | |
| 28 | |
| 29 #undef LOG | |
| 30 | |
| 31 #include "webkit/glue/autocomplete_input_listener.h" | |
| 32 #include "webkit/glue/webframe.h" | |
| 33 #include "webkit/glue/webframe_impl.h" | |
| 34 #include "webkit/glue/webview.h" | |
| 35 #include "webkit/tools/test_shell/test_shell_test.h" | |
| 36 #include "testing/gtest/include/gtest/gtest.h" | |
| 37 | |
| 38 using WebCore::Event; | |
| 39 | |
| 40 namespace webkit_glue { | |
| 41 | |
| 42 class TestAutocompleteBodyListener : public AutocompleteBodyListener { | |
| 43 public: | |
| 44 TestAutocompleteBodyListener() { | |
| 45 } | |
| 46 | |
| 47 void SetCaretAtEnd(WebCore::HTMLInputElement* element, bool value) { | |
| 48 std::vector<WebCore::HTMLInputElement*>::iterator iter = | |
| 49 std::find(caret_at_end_elements_.begin(), caret_at_end_elements_.end(), | |
| 50 element); | |
| 51 if (value) { | |
| 52 if (iter == caret_at_end_elements_.end()) | |
| 53 caret_at_end_elements_.push_back(element); | |
| 54 } else { | |
| 55 if (iter != caret_at_end_elements_.end()) | |
| 56 caret_at_end_elements_.erase(iter); | |
| 57 } | |
| 58 } | |
| 59 | |
| 60 void ResetTestState() { | |
| 61 caret_at_end_elements_.clear(); | |
| 62 } | |
| 63 | |
| 64 protected: | |
| 65 // AutocompleteBodyListener override. | |
| 66 virtual bool IsCaretAtEndOfText(WebCore::HTMLInputElement* element, | |
| 67 size_t input_length, | |
| 68 size_t previous_length) const { | |
| 69 return std::find(caret_at_end_elements_.begin(), | |
| 70 caret_at_end_elements_.end(), | |
| 71 element) != caret_at_end_elements_.end(); | |
| 72 } | |
| 73 | |
| 74 private: | |
| 75 // List of elements for which the caret is at the end of the text. | |
| 76 std::vector<WebCore::HTMLInputElement*> caret_at_end_elements_; | |
| 77 }; | |
| 78 | |
| 79 class TestAutocompleteInputListener : public AutocompleteInputListener { | |
| 80 public: | |
| 81 TestAutocompleteInputListener() | |
| 82 : blurred_(false), | |
| 83 did_request_inline_autocomplete_(false) { | |
| 84 } | |
| 85 | |
| 86 void ResetTestState() { | |
| 87 blurred_ = false; | |
| 88 did_request_inline_autocomplete_ = false; | |
| 89 } | |
| 90 | |
| 91 bool blurred() const { return blurred_; } | |
| 92 bool did_request_inline_autocomplete() const { | |
| 93 return did_request_inline_autocomplete_; | |
| 94 } | |
| 95 | |
| 96 virtual void OnBlur(WebCore::HTMLInputElement* element, | |
| 97 const std::wstring& user_input) { | |
| 98 blurred_ = true; | |
| 99 } | |
| 100 virtual void OnInlineAutocompleteNeeded(WebCore::HTMLInputElement* element, | |
| 101 const std::wstring& user_input) { | |
| 102 did_request_inline_autocomplete_ = true; | |
| 103 } | |
| 104 | |
| 105 private: | |
| 106 bool blurred_; | |
| 107 bool did_request_inline_autocomplete_; | |
| 108 }; | |
| 109 | |
| 110 namespace { | |
| 111 | |
| 112 class DomAutocompleteTests : public TestShellTest { | |
| 113 public: | |
| 114 virtual void SetUp() { | |
| 115 TestShellTest::SetUp(); | |
| 116 // We need a document in order to create HTMLInputElements. | |
| 117 WebView* view = test_shell_->webView(); | |
| 118 WebFrameImpl* frame = static_cast<WebFrameImpl*>(view->GetMainFrame()); | |
| 119 document_ = frame->frame()->document(); | |
| 120 } | |
| 121 | |
| 122 void FireAndHandleInputEvent(AutocompleteBodyListener* listener, | |
| 123 WebCore::HTMLInputElement* element) { | |
| 124 RefPtr<Event> event(Event::create(WebCore::eventNames().inputEvent, | |
| 125 false, false)); | |
| 126 event->setTarget(element); | |
| 127 listener->handleEvent(event.get(), false); | |
| 128 } | |
| 129 | |
| 130 void SimulateTypedInput(TestAutocompleteBodyListener* listener, | |
| 131 WebCore::HTMLInputElement* element, | |
| 132 const std::wstring& new_input, | |
| 133 bool caret_at_end) { | |
| 134 element->setValue(StdWStringToString(new_input)); | |
| 135 listener->SetCaretAtEnd(element, caret_at_end); | |
| 136 FireAndHandleInputEvent(listener, element); | |
| 137 } | |
| 138 | |
| 139 WebCore::Document* document_; | |
| 140 }; | |
| 141 } // namespace | |
| 142 | |
| 143 TEST_F(DomAutocompleteTests, OnBlur) { | |
| 144 RefPtr<WebCore::HTMLInputElement> ignored_element = | |
| 145 new WebCore::HTMLInputElement(document_); | |
| 146 RefPtr<WebCore::HTMLInputElement> listened_element = | |
| 147 new WebCore::HTMLInputElement(document_); | |
| 148 RefPtr<TestAutocompleteBodyListener> body_listener = | |
| 149 new TestAutocompleteBodyListener; | |
| 150 TestAutocompleteInputListener* listener = new TestAutocompleteInputListener(); | |
| 151 // body_listener takes ownership of the listener. | |
| 152 body_listener->AddInputListener(listened_element.get(), listener); | |
| 153 | |
| 154 // Simulate a blur event to the element we are not listening to. | |
| 155 // Our listener should not be notified. | |
| 156 RefPtr<Event> event(Event::create(WebCore::eventNames().DOMFocusOutEvent, | |
| 157 false, false)); | |
| 158 event->setTarget(ignored_element.get()); | |
| 159 body_listener->handleEvent(event.get(), false); | |
| 160 EXPECT_FALSE(listener->blurred()); | |
| 161 | |
| 162 // Now simulate the event on the input element we are listening to. | |
| 163 event->setTarget(listened_element.get()); | |
| 164 body_listener->handleEvent(event.get(), false); | |
| 165 EXPECT_TRUE(listener->blurred()); | |
| 166 } | |
| 167 | |
| 168 TEST_F(DomAutocompleteTests, InlineAutocompleteTriggeredByInputEvent) { | |
| 169 RefPtr<WebCore::HTMLInputElement> ignored_element = | |
| 170 new WebCore::HTMLInputElement(document_); | |
| 171 RefPtr<WebCore::HTMLInputElement> listened_element = | |
| 172 new WebCore::HTMLInputElement(document_); | |
| 173 RefPtr<TestAutocompleteBodyListener> body_listener = | |
| 174 new TestAutocompleteBodyListener; | |
| 175 | |
| 176 TestAutocompleteInputListener* listener = new TestAutocompleteInputListener(); | |
| 177 body_listener->AddInputListener(listened_element.get(), listener); | |
| 178 | |
| 179 // Simulate an inputEvent by setting the value and artificially firing evt. | |
| 180 // The user typed 'g'. | |
| 181 SimulateTypedInput(body_listener.get(), ignored_element.get(), L"g", true); | |
| 182 EXPECT_FALSE(listener->did_request_inline_autocomplete()); | |
| 183 SimulateTypedInput(body_listener.get(), listened_element.get(), L"g", true); | |
| 184 EXPECT_TRUE(listener->did_request_inline_autocomplete()); | |
| 185 } | |
| 186 | |
| 187 TEST_F(DomAutocompleteTests, InlineAutocompleteHeuristics) { | |
| 188 RefPtr<WebCore::HTMLInputElement> input_element = | |
| 189 new WebCore::HTMLInputElement(document_); | |
| 190 RefPtr<TestAutocompleteBodyListener> body_listener = | |
| 191 new TestAutocompleteBodyListener(); | |
| 192 | |
| 193 TestAutocompleteInputListener* listener = new TestAutocompleteInputListener(); | |
| 194 body_listener->AddInputListener(input_element.get(), listener); | |
| 195 | |
| 196 // Simulate a user entering some text, and then backspacing to remove | |
| 197 // a character. | |
| 198 SimulateTypedInput(body_listener.get(), input_element.get(), L"g", true); | |
| 199 EXPECT_TRUE(listener->did_request_inline_autocomplete()); | |
| 200 listener->ResetTestState(); | |
| 201 body_listener->ResetTestState(); | |
| 202 | |
| 203 SimulateTypedInput(body_listener.get(), input_element.get(), L"go", true); | |
| 204 EXPECT_TRUE(listener->did_request_inline_autocomplete()); | |
| 205 listener->ResetTestState(); | |
| 206 body_listener->ResetTestState(); | |
| 207 | |
| 208 SimulateTypedInput(body_listener.get(), input_element.get(), L"g", true); | |
| 209 EXPECT_FALSE(listener->did_request_inline_autocomplete()); | |
| 210 listener->ResetTestState(); | |
| 211 body_listener->ResetTestState(); | |
| 212 | |
| 213 // Now simulate the user moving the cursor to a position other than the end, | |
| 214 // and adding text. | |
| 215 SimulateTypedInput(body_listener.get(), input_element.get(), L"og", false); | |
| 216 EXPECT_FALSE(listener->did_request_inline_autocomplete()); | |
| 217 listener->ResetTestState(); | |
| 218 body_listener->ResetTestState(); | |
| 219 | |
| 220 // Test that same input doesn't trigger autocomplete. | |
| 221 SimulateTypedInput(body_listener.get(), input_element.get(), L"og", true); | |
| 222 EXPECT_FALSE(listener->did_request_inline_autocomplete()); | |
| 223 listener->ResetTestState(); | |
| 224 body_listener->ResetTestState(); | |
| 225 } | |
| 226 | |
| 227 } // webkit_glue | |
| OLD | NEW |