1// Copyright (c) 2011 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#include "base/basictypes.h"
6#include "components/autofill/content/renderer/page_click_listener.h"
7#include "components/autofill/content/renderer/page_click_tracker.h"
8#include "content/public/renderer/render_view.h"
9#include "content/public/test/render_view_test.h"
10#include "testing/gtest/include/gtest/gtest.h"
11#include "third_party/WebKit/public/web/WebDocument.h"
12#include "third_party/WebKit/public/web/WebInputElement.h"
13#include "third_party/WebKit/public/web/WebTextAreaElement.h"
14#include "third_party/WebKit/public/web/WebView.h"
15#include "third_party/WebKit/public/platform/WebSize.h"
16#include "ui/events/keycodes/keyboard_codes.h"
17
18namespace autofill {
19
20class TestPageClickListener : public PageClickListener {
21 public:
22  TestPageClickListener()
23      : form_control_element_clicked_called_(false),
24        was_focused_(false) {}
25
26  virtual void FormControlElementClicked(
27      const blink::WebFormControlElement& element,
28      bool was_focused) OVERRIDE {
29    form_control_element_clicked_called_ = true;
30    form_control_element_clicked_ = element;
31    was_focused_ = was_focused;
32  }
33
34  void ClearResults() {
35    form_control_element_clicked_called_ = false;
36    form_control_element_clicked_.reset();
37    was_focused_ = false;
38  }
39
40  bool form_control_element_clicked_called_;
41  blink::WebFormControlElement form_control_element_clicked_;
42  bool was_focused_;
43};
44
45class PageClickTrackerTest : public content::RenderViewTest {
46 protected:
47  virtual void SetUp() OVERRIDE {
48    content::RenderViewTest::SetUp();
49
50    // RenderView creates PageClickTracker but it doesn't keep it around.
51    // Rather than make it do so for the test, we create a new object.
52    page_click_tracker_.reset(new PageClickTracker(view_, &test_listener_));
53
54    LoadHTML("<form>"
55             "  <input type='text' id='text_1'></input><br>"
56             "  <input type='text' id='text_2'></input><br>"
57             "  <textarea  id='textarea_1'></textarea><br>"
58             "  <textarea  id='textarea_2'></textarea><br>"
59             "  <input type='button' id='button'></input><br>"
60             "</form>");
61    GetWebWidget()->resize(blink::WebSize(500, 500));
62    GetWebWidget()->setFocus(true);
63    blink::WebDocument document = view_->GetWebView()->mainFrame()->document();
64    text_ = document.getElementById("text_1");
65    textarea_ = document.getElementById("textarea_1");
66    ASSERT_FALSE(text_.isNull());
67    ASSERT_FALSE(textarea_.isNull());
68  }
69
70  virtual void TearDown() OVERRIDE {
71    text_.reset();
72    textarea_.reset();
73    test_listener_.ClearResults();
74    page_click_tracker_.reset();
75    content::RenderViewTest::TearDown();
76  }
77
78  // Simulates a click on the given element and then waits for the stack
79  // to unwind.
80  void SendElementClick(const std::string& element_id) {
81    EXPECT_TRUE(SimulateElementClick(element_id));
82    ProcessPendingMessages();
83  }
84
85  // Send all the messages required for a complete key press.
86  void SendKeyPress(int key_code) {
87    blink::WebKeyboardEvent keyboard_event;
88    keyboard_event.windowsKeyCode = key_code;
89    keyboard_event.setKeyIdentifierFromWindowsKeyCode();
90
91    keyboard_event.type = blink::WebInputEvent::RawKeyDown;
92    SendWebKeyboardEvent(keyboard_event);
93
94    keyboard_event.type = blink::WebInputEvent::Char;
95    SendWebKeyboardEvent(keyboard_event);
96
97    keyboard_event.type = blink::WebInputEvent::KeyUp;
98    SendWebKeyboardEvent(keyboard_event);
99  }
100
101  scoped_ptr<PageClickTracker> page_click_tracker_;
102  TestPageClickListener test_listener_;
103  blink::WebElement text_;
104  blink::WebElement textarea_;
105};
106
107// Tests that PageClickTracker does notify correctly when an input
108// node is clicked.
109TEST_F(PageClickTrackerTest, PageClickTrackerInputClicked) {
110  EXPECT_NE(text_, text_.document().focusedElement());
111  // Click the text field once.
112  SendElementClick("text_1");
113  EXPECT_TRUE(test_listener_.form_control_element_clicked_called_);
114  EXPECT_FALSE(test_listener_.was_focused_);
115  EXPECT_TRUE(text_ == test_listener_.form_control_element_clicked_);
116  test_listener_.ClearResults();
117
118  // Click the text field again to test that was_focused_ is set correctly.
119  SendElementClick("text_1");
120  EXPECT_TRUE(test_listener_.form_control_element_clicked_called_);
121  EXPECT_TRUE(test_listener_.was_focused_);
122  EXPECT_TRUE(text_ == test_listener_.form_control_element_clicked_);
123  test_listener_.ClearResults();
124
125  // Click the button, no notification should happen (this is not a text-input).
126  SendElementClick("button");
127  EXPECT_FALSE(test_listener_.form_control_element_clicked_called_);
128}
129
130// Tests that PageClickTracker does notify correctly when a textarea
131// node is clicked.
132TEST_F(PageClickTrackerTest, PageClickTrackerTextAreaClicked) {
133  // Click the textarea field once.
134  SendElementClick("textarea_1");
135  EXPECT_TRUE(test_listener_.form_control_element_clicked_called_);
136  EXPECT_FALSE(test_listener_.was_focused_);
137  EXPECT_TRUE(textarea_ == test_listener_.form_control_element_clicked_);
138  test_listener_.ClearResults();
139
140  // Click the textarea field again to test that was_focused_ is set correctly.
141  SendElementClick("textarea_1");
142  EXPECT_TRUE(test_listener_.form_control_element_clicked_called_);
143  EXPECT_TRUE(test_listener_.was_focused_);
144  EXPECT_TRUE(textarea_ == test_listener_.form_control_element_clicked_);
145  test_listener_.ClearResults();
146
147  // Click the button, no notification should happen (this is not a text-input).
148  SendElementClick("button");
149  EXPECT_FALSE(test_listener_.form_control_element_clicked_called_);
150}
151
152}  // namespace autofill
153