OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2012 Google Inc. All rights reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions are | |
6 * met: | |
7 * | |
8 * * Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * * Redistributions in binary form must reproduce the above | |
11 * copyright notice, this list of conditions and the following disclaimer | |
12 * in the documentation and/or other materials provided with the | |
13 * distribution. | |
14 * * Neither the name of Google Inc. nor the names of its | |
15 * contributors may be used to endorse or promote products derived from | |
16 * this software without specific prior written permission. | |
17 * | |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 */ | |
30 | |
31 #include "config.h" | |
32 | |
33 #include "FrameTestHelpers.h" | |
34 #include "URLTestHelpers.h" | |
35 #include "WebDOMEvent.h" | |
36 #include "WebDOMEventListener.h" | |
37 #include "WebDOMMutationEvent.h" | |
38 #include "WebDocument.h" | |
39 #include "WebElement.h" | |
40 #include "WebFrame.h" | |
41 #include "WebScriptSource.h" | |
42 #include "WebView.h" | |
43 #include <gtest/gtest.h> | |
44 #include <public/Platform.h> | |
45 #include <public/WebUnitTestSupport.h> | |
46 | |
47 using namespace WebKit; | |
48 | |
49 namespace { | |
50 | |
51 class TestWebDOMEventListener : public WebDOMEventListener { | |
52 public: | |
53 TestWebDOMEventListener() { } | |
54 virtual ~TestWebDOMEventListener() { } | |
55 | |
56 virtual void handleEvent(const WebDOMEvent& event) OVERRIDE | |
57 { | |
58 m_events.push_back(event); | |
59 } | |
60 | |
61 size_t eventCount() const { return m_events.size(); } | |
62 | |
63 WebDOMEvent eventAt(int index) const { return m_events.at(index); } | |
64 | |
65 void clearEvents() { m_events.clear(); } | |
66 | |
67 private: | |
68 std::vector<WebDOMEvent> m_events; | |
69 }; | |
70 | |
71 class WebDOMEventListenerTest : public testing::Test { | |
72 public: | |
73 WebDOMEventListenerTest() | |
74 : m_webView(0) | |
75 { | |
76 } | |
77 | |
78 virtual void SetUp() OVERRIDE | |
79 { | |
80 std::string baseURL("http://www.example.com/"); | |
81 std::string fileName("listener/mutation_event_listener.html"); | |
82 bool executeScript = true; | |
83 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(baseURL
.c_str()), WebString::fromUTF8(fileName.c_str())); | |
84 m_webView = FrameTestHelpers::createWebViewAndLoad(baseURL + fileName, e
xecuteScript); | |
85 } | |
86 | |
87 virtual void TearDown() OVERRIDE | |
88 { | |
89 m_webView->close(); | |
90 Platform::current()->unitTestSupport()->unregisterAllMockedURLs(); | |
91 } | |
92 | |
93 WebFrame* mainFrame() const | |
94 { | |
95 return m_webView->mainFrame(); | |
96 } | |
97 | |
98 WebDocument document() const | |
99 { | |
100 return mainFrame()->document(); | |
101 } | |
102 | |
103 void executeScript(const char* code) | |
104 { | |
105 mainFrame()->executeScript(WebScriptSource(WebString::fromUTF8(code))); | |
106 } | |
107 | |
108 | |
109 static WebString GetNodeID(const WebNode& node) | |
110 { | |
111 if (node.nodeType() != WebNode::ElementNode) | |
112 return WebString(); | |
113 WebElement element = node.toConst<WebElement>(); | |
114 return element.getAttribute("id"); | |
115 } | |
116 | |
117 protected: | |
118 WebView* m_webView; | |
119 }; | |
120 | |
121 | |
122 // Tests that the right mutation events are fired when a node is added/removed. | |
123 // Note that the DOMSubtreeModified event is fairly vage, it only tells you | |
124 // something changed for the target node. | |
125 TEST_F(WebDOMEventListenerTest, NodeAddedRemovedMutationEvent) | |
126 { | |
127 TestWebDOMEventListener eventListener; | |
128 document().addEventListener("DOMSubtreeModified", &eventListener, false); | |
129 | |
130 // Test adding a node. | |
131 executeScript("addElement('newNode')"); | |
132 ASSERT_EQ(1U, eventListener.eventCount()); | |
133 WebDOMEvent event = eventListener.eventAt(0); | |
134 ASSERT_TRUE(event.isMutationEvent()); | |
135 // No need to check any of the MutationEvent, WebKit does not set any. | |
136 EXPECT_EQ("DIV", event.target().nodeName()); | |
137 EXPECT_EQ("topDiv", GetNodeID(event.target())); | |
138 eventListener.clearEvents(); | |
139 | |
140 // Test removing a node. | |
141 executeScript("removeNode('div1')"); | |
142 ASSERT_EQ(1U, eventListener.eventCount()); | |
143 event = eventListener.eventAt(0); | |
144 ASSERT_TRUE(event.isMutationEvent()); | |
145 EXPECT_EQ("DIV", event.target().nodeName()); | |
146 EXPECT_EQ("topDiv", GetNodeID(event.target())); | |
147 } | |
148 | |
149 // Tests the right mutation event is fired when a text node is modified. | |
150 TEST_F(WebDOMEventListenerTest, TextNodeModifiedMutationEvent) | |
151 { | |
152 TestWebDOMEventListener eventListener; | |
153 document().addEventListener("DOMSubtreeModified", &eventListener, false); | |
154 executeScript("changeText('div2', 'Hello')"); | |
155 ASSERT_EQ(1U, eventListener.eventCount()); | |
156 WebDOMEvent event = eventListener.eventAt(0); | |
157 ASSERT_TRUE(event.isMutationEvent()); | |
158 ASSERT_EQ(WebNode::TextNode, event.target().nodeType()); | |
159 } | |
160 | |
161 // Tests the right mutation events are fired when an attribute is added/removed. | |
162 TEST_F(WebDOMEventListenerTest, AttributeMutationEvent) | |
163 { | |
164 TestWebDOMEventListener eventListener; | |
165 document().addEventListener("DOMSubtreeModified", &eventListener, false); | |
166 executeScript("document.getElementById('div2').setAttribute('myAttr'," | |
167 "'some value')"); | |
168 ASSERT_EQ(1U, eventListener.eventCount()); | |
169 WebDOMEvent event = eventListener.eventAt(0); | |
170 ASSERT_TRUE(event.isMutationEvent()); | |
171 EXPECT_EQ("DIV", event.target().nodeName()); | |
172 EXPECT_EQ("div2", GetNodeID(event.target())); | |
173 eventListener.clearEvents(); | |
174 | |
175 executeScript("document.getElementById('div2').removeAttribute('myAttr')"); | |
176 ASSERT_EQ(1U, eventListener.eventCount()); | |
177 event = eventListener.eventAt(0); | |
178 ASSERT_TRUE(event.isMutationEvent()); | |
179 EXPECT_EQ("DIV", event.target().nodeName()); | |
180 EXPECT_EQ("div2", GetNodeID(event.target())); | |
181 } | |
182 | |
183 // Tests destroying WebDOMEventListener and triggering events, we shouldn't | |
184 // crash. | |
185 TEST_F(WebDOMEventListenerTest, FireEventDeletedListener) | |
186 { | |
187 TestWebDOMEventListener* eventListener = new TestWebDOMEventListener(); | |
188 document().addEventListener("DOMSubtreeModified", eventListener, false); | |
189 delete eventListener; | |
190 executeScript("addElement('newNode')"); // That should fire an event. | |
191 } | |
192 | |
193 // Tests registering several events on the same WebDOMEventListener and | |
194 // triggering events. | |
195 TEST_F(WebDOMEventListenerTest, SameListenerMultipleEvents) | |
196 { | |
197 TestWebDOMEventListener eventListener; | |
198 const WebString kDOMSubtreeModifiedType("DOMSubtreeModified"); | |
199 const WebString kDOMNodeRemovedType("DOMNodeRemoved"); | |
200 document().addEventListener(kDOMSubtreeModifiedType, &eventListener, false); | |
201 WebElement div1Elem = document().getElementById("div1"); | |
202 div1Elem.addEventListener(kDOMNodeRemovedType, &eventListener, false); | |
203 | |
204 // Trigger a DOMSubtreeModified event by adding a node. | |
205 executeScript("addElement('newNode')"); | |
206 ASSERT_EQ(1U, eventListener.eventCount()); | |
207 WebDOMEvent event = eventListener.eventAt(0); | |
208 ASSERT_TRUE(event.isMutationEvent()); | |
209 EXPECT_EQ("DIV", event.target().nodeName()); | |
210 EXPECT_EQ("topDiv", GetNodeID(event.target())); | |
211 eventListener.clearEvents(); | |
212 | |
213 // Trigger for both event listener by removing the div1 node. | |
214 executeScript("removeNode('div1')"); | |
215 ASSERT_EQ(2U, eventListener.eventCount()); | |
216 // Not sure if the order of the events is important. Assuming no specific | |
217 // order. | |
218 WebString type1 = eventListener.eventAt(0).type(); | |
219 WebString type2 = eventListener.eventAt(1).type(); | |
220 EXPECT_TRUE(type1 == kDOMSubtreeModifiedType || type1 == kDOMNodeRemovedType
); | |
221 EXPECT_TRUE(type2 == kDOMSubtreeModifiedType || type2 == kDOMNodeRemovedType
); | |
222 EXPECT_TRUE(type1 != type2); | |
223 } | |
224 | |
225 // Tests removing event listeners. | |
226 TEST_F(WebDOMEventListenerTest, RemoveEventListener) | |
227 { | |
228 TestWebDOMEventListener eventListener; | |
229 const WebString kDOMSubtreeModifiedType("DOMSubtreeModified"); | |
230 // Adding twice the same listener for the same event, should be supported. | |
231 document().addEventListener(kDOMSubtreeModifiedType, &eventListener, false); | |
232 document().addEventListener(kDOMSubtreeModifiedType, &eventListener, false); | |
233 | |
234 // Add a node, that should trigger 2 events. | |
235 executeScript("addElement('newNode')"); | |
236 EXPECT_EQ(2U, eventListener.eventCount()); | |
237 eventListener.clearEvents(); | |
238 | |
239 // Remove one listener and trigger an event again. | |
240 document().removeEventListener( | |
241 kDOMSubtreeModifiedType, &eventListener, false); | |
242 executeScript("addElement('newerNode')"); | |
243 EXPECT_EQ(1U, eventListener.eventCount()); | |
244 eventListener.clearEvents(); | |
245 | |
246 // Remove the last listener and trigger yet another event. | |
247 document().removeEventListener( | |
248 kDOMSubtreeModifiedType, &eventListener, false); | |
249 executeScript("addElement('newererNode')"); | |
250 EXPECT_EQ(0U, eventListener.eventCount()); | |
251 } | |
252 | |
253 } // namespace | |
OLD | NEW |