|
1 <!DOCTYPE HTML> |
|
2 <html> |
|
3 <!-- |
|
4 https://bugzilla.mozilla.org/show_bug.cgi?id= |
|
5 --> |
|
6 <head> |
|
7 <meta charset="utf-8"> |
|
8 <title>Test for Bug </title> |
|
9 |
|
10 <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> |
|
11 <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"> |
|
12 <script type="application/javascript;version=1.8" src="inspector-helpers.js"></script> |
|
13 <script type="application/javascript;version=1.8"> |
|
14 Components.utils.import("resource://gre/modules/devtools/Loader.jsm"); |
|
15 const {Promise: promise} = Components.utils.import("resource://gre/modules/Promise.jsm", {}); |
|
16 |
|
17 const inspector = devtools.require("devtools/server/actors/inspector"); |
|
18 |
|
19 window.onload = function() { |
|
20 SimpleTest.waitForExplicitFinish(); |
|
21 runNextTest(); |
|
22 } |
|
23 |
|
24 var gInspectee = null; |
|
25 var gClient = null; |
|
26 var gWalker = null; |
|
27 var checkActorIDs = []; |
|
28 |
|
29 function assertOwnership() { |
|
30 assertOwnershipTrees(gWalker); |
|
31 } |
|
32 addTest(function setup() { |
|
33 let url = document.getElementById("inspectorContent").href; |
|
34 attachURL(url, function(err, client, tab, doc) { |
|
35 gInspectee = doc; |
|
36 let {InspectorFront} = devtools.require("devtools/server/actors/inspector"); |
|
37 let inspector = InspectorFront(client, tab); |
|
38 promiseDone(inspector.getWalker().then(walker => { |
|
39 ok(walker, "getWalker() should return an actor."); |
|
40 gClient = client; |
|
41 gWalker = walker; |
|
42 }).then(runNextTest)); |
|
43 }); |
|
44 }); |
|
45 |
|
46 addTest(function testWalkerRoot() { |
|
47 // Make sure that refetching the root document of the walker returns the same |
|
48 // actor as the getWalker returned. |
|
49 promiseDone(gWalker.document().then(root => { |
|
50 ok(root === gWalker.rootNode, "Re-fetching the document node should match the root document node."); |
|
51 checkActorIDs.push(root.actorID); |
|
52 assertOwnership(); |
|
53 }).then(runNextTest)); |
|
54 }); |
|
55 |
|
56 addTest(function testInnerHTML() { |
|
57 promiseDone(gWalker.documentElement().then(docElement => { |
|
58 return gWalker.innerHTML(docElement); |
|
59 }).then(longstring => { |
|
60 return longstring.string(); |
|
61 }).then(innerHTML => { |
|
62 ok(innerHTML === gInspectee.documentElement.innerHTML, "innerHTML should match"); |
|
63 }).then(runNextTest)); |
|
64 }); |
|
65 |
|
66 addTest(function testOuterHTML() { |
|
67 promiseDone(gWalker.documentElement().then(docElement => { |
|
68 return gWalker.outerHTML(docElement); |
|
69 }).then(longstring => { |
|
70 return longstring.string(); |
|
71 }).then(outerHTML => { |
|
72 ok(outerHTML === gInspectee.documentElement.outerHTML, "outerHTML should match"); |
|
73 }).then(runNextTest)); |
|
74 }); |
|
75 |
|
76 addTest(function testSetOuterHTMLNode() { |
|
77 let newHTML = "<p id=\"edit-html-done\">after edit</p>"; |
|
78 promiseDone(gWalker.querySelector(gWalker.rootNode, "#edit-html").then(node => { |
|
79 return gWalker.setOuterHTML(node, newHTML); |
|
80 }).then(() => { |
|
81 return gWalker.querySelector(gWalker.rootNode, "#edit-html-done"); |
|
82 }).then(node => { |
|
83 return gWalker.outerHTML(node); |
|
84 }).then(longstring => { |
|
85 return longstring.string(); |
|
86 }).then(outerHTML => { |
|
87 is(outerHTML, newHTML, "outerHTML has been updated"); |
|
88 }).then(() => { |
|
89 return gWalker.querySelector(gWalker.rootNode, "#edit-html"); |
|
90 }).then(node => { |
|
91 ok(!node, "The node with the old ID cannot be selected anymore"); |
|
92 }).then(runNextTest)); |
|
93 }); |
|
94 |
|
95 addTest(function testQuerySelector() { |
|
96 promiseDone(gWalker.querySelector(gWalker.rootNode, "#longlist").then(node => { |
|
97 is(node.getAttribute("data-test"), "exists", "should have found the right node"); |
|
98 assertOwnership(); |
|
99 }).then(() => { |
|
100 return gWalker.querySelector(gWalker.rootNode, "unknownqueryselector").then(node => { |
|
101 ok(!node, "Should not find a node here."); |
|
102 assertOwnership(); |
|
103 }); |
|
104 }).then(runNextTest)); |
|
105 }); |
|
106 |
|
107 addTest(function testQuerySelectors() { |
|
108 let nodeList = null; |
|
109 let firstNode = null; |
|
110 let nodeListID = null; |
|
111 promiseDone(gWalker.querySelectorAll(gWalker.rootNode, "#longlist div").then(list => { |
|
112 nodeList = list; |
|
113 is(nodeList.length, 26, "Expect 26 div children."); |
|
114 assertOwnership(); |
|
115 return nodeList.item(0); |
|
116 }).then(node => { |
|
117 firstNode = node; |
|
118 checkActorIDs.push(node.actorID); |
|
119 is(node.id, "a", "First child should be a"); |
|
120 assertOwnership(); |
|
121 return nodeList.items(); |
|
122 }).then(nodes => { |
|
123 is(nodes.length, 26, "Expect 26 nodes"); |
|
124 is(nodes[0], firstNode, "First node should be reused."); |
|
125 ok(nodes[0]._parent, "Parent node should be set."); |
|
126 ok(nodes[0]._next || nodes[0]._prev, "Siblings should be set."); |
|
127 ok(nodes[25]._next || nodes[25]._prev, "Siblings of " + nodes[25] + " should be set."); |
|
128 assertOwnership(); |
|
129 return nodeList.items(-1); |
|
130 }).then(nodes => { |
|
131 is(nodes.length, 1, "Expect 1 node") |
|
132 is(nodes[0].id, "z", "Expect it to be the last node."); |
|
133 checkActorIDs.push(nodes[0].actorID); |
|
134 // Save the node list ID so we can ensure it was destroyed. |
|
135 nodeListID = nodeList.actorID; |
|
136 assertOwnership(); |
|
137 return nodeList.release(); |
|
138 }).then(() => { |
|
139 ok(!nodeList.actorID, "Actor should have been destroyed."); |
|
140 assertOwnership(); |
|
141 return checkMissing(gClient, nodeListID); |
|
142 }).then(runNextTest)); |
|
143 }); |
|
144 |
|
145 // Helper to check the response of requests that return hasFirst/hasLast/nodes |
|
146 // node lists (like `children` and `siblings`) |
|
147 function nodeArrayChecker(first, last, ids) { |
|
148 return function(response) { |
|
149 is(response.hasFirst, first, "Should " + (first ? "" : "not ") + " have the first node."); |
|
150 is(response.hasLast, last, "Should " + (last ? "" : "not ") + " have the last node."); |
|
151 is(response.nodes.length, ids.length, "Should have " + ids.length + " children listed."); |
|
152 let responseIds = ''; |
|
153 for (node of response.nodes) { |
|
154 responseIds += node.id; |
|
155 } |
|
156 is(responseIds, ids, "Correct nodes were returned."); |
|
157 assertOwnership(); |
|
158 } |
|
159 } |
|
160 |
|
161 addTest(function testNoChildren() { |
|
162 promiseDone(gWalker.querySelector(gWalker.rootNode, "#empty").then(empty => { |
|
163 assertOwnership(); |
|
164 return gWalker.children(empty).then(nodeArrayChecker(true, true, "")); |
|
165 }).then(runNextTest)); |
|
166 }); |
|
167 |
|
168 addTest(function testLongListTraversal() { |
|
169 var longList; |
|
170 var allChildren; |
|
171 promiseDone(gWalker.querySelector(gWalker.rootNode, "#longlist").then(node => { |
|
172 longList = node; |
|
173 // First call with no options, expect all children. |
|
174 assertOwnership(); |
|
175 return gWalker.children(longList).then(response => { |
|
176 nodeArrayChecker(true, true, "abcdefghijklmnopqrstuvwxyz")(response); |
|
177 allChildren = response.nodes; |
|
178 assertOwnership(); |
|
179 }); |
|
180 }).then(() => { |
|
181 // maxNodes should limit us to the first 5 nodes. |
|
182 assertOwnership(); |
|
183 return gWalker.children(longList, { maxNodes: 5 }).then(nodeArrayChecker(true, false, 'abcde')); |
|
184 }).then(() => { |
|
185 assertOwnership(); |
|
186 // maxNodes with the second item centered should still give us the first 5 nodes. |
|
187 return gWalker.children(longList, { maxNodes: 5, center: allChildren[1] }).then( |
|
188 nodeArrayChecker(true, false, 'abcde') |
|
189 ); |
|
190 }).then(() => { |
|
191 // maxNodes with a center in the middle of the list should put that item in the middle |
|
192 let center = allChildren[13]; |
|
193 is(center.id, 'n', "Make sure I know how to count letters."); |
|
194 return gWalker.children(longList, { maxNodes: 5, center: center }).then( |
|
195 nodeArrayChecker(false, false, 'lmnop') |
|
196 ); |
|
197 }).then(() => { |
|
198 // maxNodes with the second-to-last item centered should give us the last 5 nodes. |
|
199 return gWalker.children(longList, { maxNodes: 5, center: allChildren[24] }).then( |
|
200 nodeArrayChecker(false, true, 'vwxyz') |
|
201 ); |
|
202 }).then(() => { |
|
203 // maxNodes with a start in the middle should start at that node and fetch 5 |
|
204 let start = allChildren[13]; |
|
205 is(start.id, 'n', "Make sure I know how to count letters.") |
|
206 return gWalker.children(longList, { maxNodes: 5, start: start }).then( |
|
207 nodeArrayChecker(false, false, 'nopqr') |
|
208 ); |
|
209 }).then(() => { |
|
210 // maxNodes near the end should only return what's left |
|
211 return gWalker.children(longList, { maxNodes: 5, start: allChildren[24] }).then( |
|
212 nodeArrayChecker(false, true, 'yz') |
|
213 ); |
|
214 }).then(runNextTest)); |
|
215 }); |
|
216 |
|
217 addTest(function testSiblings() { |
|
218 promiseDone(gWalker.querySelector(gWalker.rootNode, "#a").then(a => { |
|
219 return gWalker.siblings(a, { maxNodes: 5, center: a }).then(nodeArrayChecker(true, false, "abcde")); |
|
220 }).then(() => { |
|
221 return gWalker.siblings(gWalker.rootNode).then(response => { |
|
222 ok(response.hasFirst && response.hasLast, "Has first and last."); |
|
223 is(response.nodes.length, 1, "Has only the document element."); |
|
224 ok(response.nodes[0] === gWalker.rootNode, "Document element is its own sibling."); |
|
225 }); |
|
226 }).then(runNextTest)); |
|
227 }); |
|
228 |
|
229 addTest(function testNextSibling() { |
|
230 promiseDone(gWalker.querySelector(gWalker.rootNode, "#y").then(y => { |
|
231 is(y.id, "y", "Got the right node."); |
|
232 return gWalker.nextSibling(y); |
|
233 }).then(z => { |
|
234 is(z.id, "z", "nextSibling got the next node."); |
|
235 return gWalker.nextSibling(z); |
|
236 }).then(nothing => { |
|
237 is(nothing, null, "nextSibling on the last node returned null."); |
|
238 }).then(runNextTest)); |
|
239 }); |
|
240 |
|
241 addTest(function testPreviousSibling() { |
|
242 promiseDone(gWalker.querySelector(gWalker.rootNode, "#b").then(b => { |
|
243 is(b.id, "b", "Got the right node."); |
|
244 return gWalker.previousSibling(b); |
|
245 }).then(a => { |
|
246 is(a.id, "a", "nextSibling got the next node."); |
|
247 return gWalker.previousSibling(a); |
|
248 }).then(nothing => { |
|
249 is(nothing, null, "previousSibling on the first node returned null."); |
|
250 }).then(runNextTest)); |
|
251 }); |
|
252 |
|
253 |
|
254 addTest(function testFrameTraversal() { |
|
255 promiseDone(gWalker.querySelector(gWalker.rootNode, "#childFrame").then(childFrame => { |
|
256 return gWalker.children(childFrame); |
|
257 }).then(children => { |
|
258 let nodes = children.nodes; |
|
259 ok(nodes.length, 1, "There should be only one child of the iframe"); |
|
260 is(nodes[0].nodeType, Node.DOCUMENT_NODE, "iframe child should be a document node"); |
|
261 return gWalker.querySelector(nodes[0], "#z"); |
|
262 }).then(childDocumentZ => { |
|
263 return gWalker.parents(childDocumentZ); |
|
264 }).then(parents => { |
|
265 // Expected set of parent tag names for this item: |
|
266 let expectedParents = ['DIV', 'BODY', 'HTML', '#document', 'IFRAME', 'BODY', 'HTML', '#document']; |
|
267 for (let parent of parents) { |
|
268 let expected = expectedParents.shift(); |
|
269 is(parent.nodeName, expected, "Got expected parent"); |
|
270 } |
|
271 }).then(runNextTest)); |
|
272 }); |
|
273 |
|
274 addTest(function testLongValue() { |
|
275 const testSummaryLength = 10; |
|
276 inspector.setValueSummaryLength(testSummaryLength); |
|
277 SimpleTest.registerCleanupFunction(function() { |
|
278 inspector.setValueSummaryLength(inspector.DEFAULT_VALUE_SUMMARY_LENGTH); |
|
279 }); |
|
280 |
|
281 let longstringText = gInspectee.getElementById("longstring").firstChild.nodeValue; |
|
282 |
|
283 promiseDone(gWalker.querySelector(gWalker.rootNode, "#longstring").then(node => { |
|
284 // Now we need to get the text node child... |
|
285 return gWalker.children(node, { maxNodes: 1 }); |
|
286 }).then(children => { |
|
287 let textNode = children.nodes[0]; |
|
288 is(textNode.nodeType, Node.TEXT_NODE, "Value should be a text node"); |
|
289 is(textNode.shortValue.length, 10, "Value summary should be limited to the summary value length"); |
|
290 ok(textNode.incompleteValue, "Value should be incomplete"); |
|
291 return textNode; |
|
292 }).then(textNode => { |
|
293 return textNode.getNodeValue(); |
|
294 }).then(value => { |
|
295 return value.string(); |
|
296 }).then(valueStr => { |
|
297 is(valueStr, longstringText, "Full node value should match the string from the document."); |
|
298 }).then(runNextTest)); |
|
299 }); |
|
300 |
|
301 addTest(function testShortValue() { |
|
302 let shortstringText = gInspectee.getElementById("shortstring").firstChild.nodeValue; |
|
303 |
|
304 promiseDone(gWalker.querySelector(gWalker.rootNode, "#shortstring").then(node => { |
|
305 // Now we need to get the text node child... |
|
306 return gWalker.children(node, { maxNodes: 1 }); |
|
307 }).then(children => { |
|
308 let textNode = children.nodes[0]; |
|
309 is(textNode.nodeType, Node.TEXT_NODE, "Value should be a text node"); |
|
310 is(textNode.shortValue, shortstringText, "Value should be complete"); |
|
311 ok(!textNode.incompleteValue, "Value should be complete"); |
|
312 return textNode; |
|
313 }).then(textNode => { |
|
314 return textNode.getNodeValue(); |
|
315 }).then(value => { |
|
316 return value.string(); |
|
317 }).then(valueStr => { |
|
318 is(valueStr, shortstringText, "Full node value should match the string from the document."); |
|
319 }).then(runNextTest)); |
|
320 }); |
|
321 |
|
322 addTest(function testReleaseWalker() { |
|
323 checkActorIDs.push(gWalker.actorID); |
|
324 |
|
325 promiseDone(gWalker.release().then(() => { |
|
326 let promises = [checkMissing(gClient, id) for (id of checkActorIDs)]; |
|
327 return promise.all(promises) |
|
328 }).then(runNextTest)); |
|
329 }); |
|
330 |
|
331 addTest(function cleanup() { |
|
332 delete gWalker; |
|
333 delete gInspectee; |
|
334 delete gClient; |
|
335 runNextTest(); |
|
336 }); |
|
337 |
|
338 |
|
339 </script> |
|
340 </head> |
|
341 <body> |
|
342 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Mozilla Bug </a> |
|
343 <a id="inspectorContent" target="_blank" href="inspector-traversal-data.html">Test Document</a> |
|
344 <p id="display"></p> |
|
345 <div id="content" style="display: none"> |
|
346 |
|
347 </div> |
|
348 <pre id="test"> |
|
349 </pre> |
|
350 </body> |
|
351 </html> |