1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/devtools/server/tests/mochitest/test_inspector-traversal.html Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,351 @@ 1.4 +<!DOCTYPE HTML> 1.5 +<html> 1.6 +<!-- 1.7 +https://bugzilla.mozilla.org/show_bug.cgi?id= 1.8 +--> 1.9 +<head> 1.10 + <meta charset="utf-8"> 1.11 + <title>Test for Bug </title> 1.12 + 1.13 + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> 1.14 + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"> 1.15 + <script type="application/javascript;version=1.8" src="inspector-helpers.js"></script> 1.16 + <script type="application/javascript;version=1.8"> 1.17 +Components.utils.import("resource://gre/modules/devtools/Loader.jsm"); 1.18 +const {Promise: promise} = Components.utils.import("resource://gre/modules/Promise.jsm", {}); 1.19 + 1.20 +const inspector = devtools.require("devtools/server/actors/inspector"); 1.21 + 1.22 +window.onload = function() { 1.23 + SimpleTest.waitForExplicitFinish(); 1.24 + runNextTest(); 1.25 +} 1.26 + 1.27 +var gInspectee = null; 1.28 +var gClient = null; 1.29 +var gWalker = null; 1.30 +var checkActorIDs = []; 1.31 + 1.32 +function assertOwnership() { 1.33 + assertOwnershipTrees(gWalker); 1.34 +} 1.35 +addTest(function setup() { 1.36 + let url = document.getElementById("inspectorContent").href; 1.37 + attachURL(url, function(err, client, tab, doc) { 1.38 + gInspectee = doc; 1.39 + let {InspectorFront} = devtools.require("devtools/server/actors/inspector"); 1.40 + let inspector = InspectorFront(client, tab); 1.41 + promiseDone(inspector.getWalker().then(walker => { 1.42 + ok(walker, "getWalker() should return an actor."); 1.43 + gClient = client; 1.44 + gWalker = walker; 1.45 + }).then(runNextTest)); 1.46 + }); 1.47 +}); 1.48 + 1.49 +addTest(function testWalkerRoot() { 1.50 + // Make sure that refetching the root document of the walker returns the same 1.51 + // actor as the getWalker returned. 1.52 + promiseDone(gWalker.document().then(root => { 1.53 + ok(root === gWalker.rootNode, "Re-fetching the document node should match the root document node."); 1.54 + checkActorIDs.push(root.actorID); 1.55 + assertOwnership(); 1.56 + }).then(runNextTest)); 1.57 +}); 1.58 + 1.59 +addTest(function testInnerHTML() { 1.60 + promiseDone(gWalker.documentElement().then(docElement => { 1.61 + return gWalker.innerHTML(docElement); 1.62 + }).then(longstring => { 1.63 + return longstring.string(); 1.64 + }).then(innerHTML => { 1.65 + ok(innerHTML === gInspectee.documentElement.innerHTML, "innerHTML should match"); 1.66 + }).then(runNextTest)); 1.67 +}); 1.68 + 1.69 +addTest(function testOuterHTML() { 1.70 + promiseDone(gWalker.documentElement().then(docElement => { 1.71 + return gWalker.outerHTML(docElement); 1.72 + }).then(longstring => { 1.73 + return longstring.string(); 1.74 + }).then(outerHTML => { 1.75 + ok(outerHTML === gInspectee.documentElement.outerHTML, "outerHTML should match"); 1.76 + }).then(runNextTest)); 1.77 +}); 1.78 + 1.79 +addTest(function testSetOuterHTMLNode() { 1.80 + let newHTML = "<p id=\"edit-html-done\">after edit</p>"; 1.81 + promiseDone(gWalker.querySelector(gWalker.rootNode, "#edit-html").then(node => { 1.82 + return gWalker.setOuterHTML(node, newHTML); 1.83 + }).then(() => { 1.84 + return gWalker.querySelector(gWalker.rootNode, "#edit-html-done"); 1.85 + }).then(node => { 1.86 + return gWalker.outerHTML(node); 1.87 + }).then(longstring => { 1.88 + return longstring.string(); 1.89 + }).then(outerHTML => { 1.90 + is(outerHTML, newHTML, "outerHTML has been updated"); 1.91 + }).then(() => { 1.92 + return gWalker.querySelector(gWalker.rootNode, "#edit-html"); 1.93 + }).then(node => { 1.94 + ok(!node, "The node with the old ID cannot be selected anymore"); 1.95 + }).then(runNextTest)); 1.96 +}); 1.97 + 1.98 +addTest(function testQuerySelector() { 1.99 + promiseDone(gWalker.querySelector(gWalker.rootNode, "#longlist").then(node => { 1.100 + is(node.getAttribute("data-test"), "exists", "should have found the right node"); 1.101 + assertOwnership(); 1.102 + }).then(() => { 1.103 + return gWalker.querySelector(gWalker.rootNode, "unknownqueryselector").then(node => { 1.104 + ok(!node, "Should not find a node here."); 1.105 + assertOwnership(); 1.106 + }); 1.107 + }).then(runNextTest)); 1.108 +}); 1.109 + 1.110 +addTest(function testQuerySelectors() { 1.111 + let nodeList = null; 1.112 + let firstNode = null; 1.113 + let nodeListID = null; 1.114 + promiseDone(gWalker.querySelectorAll(gWalker.rootNode, "#longlist div").then(list => { 1.115 + nodeList = list; 1.116 + is(nodeList.length, 26, "Expect 26 div children."); 1.117 + assertOwnership(); 1.118 + return nodeList.item(0); 1.119 + }).then(node => { 1.120 + firstNode = node; 1.121 + checkActorIDs.push(node.actorID); 1.122 + is(node.id, "a", "First child should be a"); 1.123 + assertOwnership(); 1.124 + return nodeList.items(); 1.125 + }).then(nodes => { 1.126 + is(nodes.length, 26, "Expect 26 nodes"); 1.127 + is(nodes[0], firstNode, "First node should be reused."); 1.128 + ok(nodes[0]._parent, "Parent node should be set."); 1.129 + ok(nodes[0]._next || nodes[0]._prev, "Siblings should be set."); 1.130 + ok(nodes[25]._next || nodes[25]._prev, "Siblings of " + nodes[25] + " should be set."); 1.131 + assertOwnership(); 1.132 + return nodeList.items(-1); 1.133 + }).then(nodes => { 1.134 + is(nodes.length, 1, "Expect 1 node") 1.135 + is(nodes[0].id, "z", "Expect it to be the last node."); 1.136 + checkActorIDs.push(nodes[0].actorID); 1.137 + // Save the node list ID so we can ensure it was destroyed. 1.138 + nodeListID = nodeList.actorID; 1.139 + assertOwnership(); 1.140 + return nodeList.release(); 1.141 + }).then(() => { 1.142 + ok(!nodeList.actorID, "Actor should have been destroyed."); 1.143 + assertOwnership(); 1.144 + return checkMissing(gClient, nodeListID); 1.145 + }).then(runNextTest)); 1.146 +}); 1.147 + 1.148 +// Helper to check the response of requests that return hasFirst/hasLast/nodes 1.149 +// node lists (like `children` and `siblings`) 1.150 +function nodeArrayChecker(first, last, ids) { 1.151 + return function(response) { 1.152 + is(response.hasFirst, first, "Should " + (first ? "" : "not ") + " have the first node."); 1.153 + is(response.hasLast, last, "Should " + (last ? "" : "not ") + " have the last node."); 1.154 + is(response.nodes.length, ids.length, "Should have " + ids.length + " children listed."); 1.155 + let responseIds = ''; 1.156 + for (node of response.nodes) { 1.157 + responseIds += node.id; 1.158 + } 1.159 + is(responseIds, ids, "Correct nodes were returned."); 1.160 + assertOwnership(); 1.161 + } 1.162 +} 1.163 + 1.164 +addTest(function testNoChildren() { 1.165 + promiseDone(gWalker.querySelector(gWalker.rootNode, "#empty").then(empty => { 1.166 + assertOwnership(); 1.167 + return gWalker.children(empty).then(nodeArrayChecker(true, true, "")); 1.168 + }).then(runNextTest)); 1.169 +}); 1.170 + 1.171 +addTest(function testLongListTraversal() { 1.172 + var longList; 1.173 + var allChildren; 1.174 + promiseDone(gWalker.querySelector(gWalker.rootNode, "#longlist").then(node => { 1.175 + longList = node; 1.176 + // First call with no options, expect all children. 1.177 + assertOwnership(); 1.178 + return gWalker.children(longList).then(response => { 1.179 + nodeArrayChecker(true, true, "abcdefghijklmnopqrstuvwxyz")(response); 1.180 + allChildren = response.nodes; 1.181 + assertOwnership(); 1.182 + }); 1.183 + }).then(() => { 1.184 + // maxNodes should limit us to the first 5 nodes. 1.185 + assertOwnership(); 1.186 + return gWalker.children(longList, { maxNodes: 5 }).then(nodeArrayChecker(true, false, 'abcde')); 1.187 + }).then(() => { 1.188 + assertOwnership(); 1.189 + // maxNodes with the second item centered should still give us the first 5 nodes. 1.190 + return gWalker.children(longList, { maxNodes: 5, center: allChildren[1] }).then( 1.191 + nodeArrayChecker(true, false, 'abcde') 1.192 + ); 1.193 + }).then(() => { 1.194 + // maxNodes with a center in the middle of the list should put that item in the middle 1.195 + let center = allChildren[13]; 1.196 + is(center.id, 'n', "Make sure I know how to count letters."); 1.197 + return gWalker.children(longList, { maxNodes: 5, center: center }).then( 1.198 + nodeArrayChecker(false, false, 'lmnop') 1.199 + ); 1.200 + }).then(() => { 1.201 + // maxNodes with the second-to-last item centered should give us the last 5 nodes. 1.202 + return gWalker.children(longList, { maxNodes: 5, center: allChildren[24] }).then( 1.203 + nodeArrayChecker(false, true, 'vwxyz') 1.204 + ); 1.205 + }).then(() => { 1.206 + // maxNodes with a start in the middle should start at that node and fetch 5 1.207 + let start = allChildren[13]; 1.208 + is(start.id, 'n', "Make sure I know how to count letters.") 1.209 + return gWalker.children(longList, { maxNodes: 5, start: start }).then( 1.210 + nodeArrayChecker(false, false, 'nopqr') 1.211 + ); 1.212 + }).then(() => { 1.213 + // maxNodes near the end should only return what's left 1.214 + return gWalker.children(longList, { maxNodes: 5, start: allChildren[24] }).then( 1.215 + nodeArrayChecker(false, true, 'yz') 1.216 + ); 1.217 + }).then(runNextTest)); 1.218 +}); 1.219 + 1.220 +addTest(function testSiblings() { 1.221 + promiseDone(gWalker.querySelector(gWalker.rootNode, "#a").then(a => { 1.222 + return gWalker.siblings(a, { maxNodes: 5, center: a }).then(nodeArrayChecker(true, false, "abcde")); 1.223 + }).then(() => { 1.224 + return gWalker.siblings(gWalker.rootNode).then(response => { 1.225 + ok(response.hasFirst && response.hasLast, "Has first and last."); 1.226 + is(response.nodes.length, 1, "Has only the document element."); 1.227 + ok(response.nodes[0] === gWalker.rootNode, "Document element is its own sibling."); 1.228 + }); 1.229 + }).then(runNextTest)); 1.230 +}); 1.231 + 1.232 +addTest(function testNextSibling() { 1.233 + promiseDone(gWalker.querySelector(gWalker.rootNode, "#y").then(y => { 1.234 + is(y.id, "y", "Got the right node."); 1.235 + return gWalker.nextSibling(y); 1.236 + }).then(z => { 1.237 + is(z.id, "z", "nextSibling got the next node."); 1.238 + return gWalker.nextSibling(z); 1.239 + }).then(nothing => { 1.240 + is(nothing, null, "nextSibling on the last node returned null."); 1.241 + }).then(runNextTest)); 1.242 +}); 1.243 + 1.244 +addTest(function testPreviousSibling() { 1.245 + promiseDone(gWalker.querySelector(gWalker.rootNode, "#b").then(b => { 1.246 + is(b.id, "b", "Got the right node."); 1.247 + return gWalker.previousSibling(b); 1.248 + }).then(a => { 1.249 + is(a.id, "a", "nextSibling got the next node."); 1.250 + return gWalker.previousSibling(a); 1.251 + }).then(nothing => { 1.252 + is(nothing, null, "previousSibling on the first node returned null."); 1.253 + }).then(runNextTest)); 1.254 +}); 1.255 + 1.256 + 1.257 +addTest(function testFrameTraversal() { 1.258 + promiseDone(gWalker.querySelector(gWalker.rootNode, "#childFrame").then(childFrame => { 1.259 + return gWalker.children(childFrame); 1.260 + }).then(children => { 1.261 + let nodes = children.nodes; 1.262 + ok(nodes.length, 1, "There should be only one child of the iframe"); 1.263 + is(nodes[0].nodeType, Node.DOCUMENT_NODE, "iframe child should be a document node"); 1.264 + return gWalker.querySelector(nodes[0], "#z"); 1.265 + }).then(childDocumentZ => { 1.266 + return gWalker.parents(childDocumentZ); 1.267 + }).then(parents => { 1.268 + // Expected set of parent tag names for this item: 1.269 + let expectedParents = ['DIV', 'BODY', 'HTML', '#document', 'IFRAME', 'BODY', 'HTML', '#document']; 1.270 + for (let parent of parents) { 1.271 + let expected = expectedParents.shift(); 1.272 + is(parent.nodeName, expected, "Got expected parent"); 1.273 + } 1.274 + }).then(runNextTest)); 1.275 +}); 1.276 + 1.277 +addTest(function testLongValue() { 1.278 + const testSummaryLength = 10; 1.279 + inspector.setValueSummaryLength(testSummaryLength); 1.280 + SimpleTest.registerCleanupFunction(function() { 1.281 + inspector.setValueSummaryLength(inspector.DEFAULT_VALUE_SUMMARY_LENGTH); 1.282 + }); 1.283 + 1.284 + let longstringText = gInspectee.getElementById("longstring").firstChild.nodeValue; 1.285 + 1.286 + promiseDone(gWalker.querySelector(gWalker.rootNode, "#longstring").then(node => { 1.287 + // Now we need to get the text node child... 1.288 + return gWalker.children(node, { maxNodes: 1 }); 1.289 + }).then(children => { 1.290 + let textNode = children.nodes[0]; 1.291 + is(textNode.nodeType, Node.TEXT_NODE, "Value should be a text node"); 1.292 + is(textNode.shortValue.length, 10, "Value summary should be limited to the summary value length"); 1.293 + ok(textNode.incompleteValue, "Value should be incomplete"); 1.294 + return textNode; 1.295 + }).then(textNode => { 1.296 + return textNode.getNodeValue(); 1.297 + }).then(value => { 1.298 + return value.string(); 1.299 + }).then(valueStr => { 1.300 + is(valueStr, longstringText, "Full node value should match the string from the document."); 1.301 + }).then(runNextTest)); 1.302 +}); 1.303 + 1.304 +addTest(function testShortValue() { 1.305 + let shortstringText = gInspectee.getElementById("shortstring").firstChild.nodeValue; 1.306 + 1.307 + promiseDone(gWalker.querySelector(gWalker.rootNode, "#shortstring").then(node => { 1.308 + // Now we need to get the text node child... 1.309 + return gWalker.children(node, { maxNodes: 1 }); 1.310 + }).then(children => { 1.311 + let textNode = children.nodes[0]; 1.312 + is(textNode.nodeType, Node.TEXT_NODE, "Value should be a text node"); 1.313 + is(textNode.shortValue, shortstringText, "Value should be complete"); 1.314 + ok(!textNode.incompleteValue, "Value should be complete"); 1.315 + return textNode; 1.316 + }).then(textNode => { 1.317 + return textNode.getNodeValue(); 1.318 + }).then(value => { 1.319 + return value.string(); 1.320 + }).then(valueStr => { 1.321 + is(valueStr, shortstringText, "Full node value should match the string from the document."); 1.322 + }).then(runNextTest)); 1.323 +}); 1.324 + 1.325 +addTest(function testReleaseWalker() { 1.326 + checkActorIDs.push(gWalker.actorID); 1.327 + 1.328 + promiseDone(gWalker.release().then(() => { 1.329 + let promises = [checkMissing(gClient, id) for (id of checkActorIDs)]; 1.330 + return promise.all(promises) 1.331 + }).then(runNextTest)); 1.332 +}); 1.333 + 1.334 +addTest(function cleanup() { 1.335 + delete gWalker; 1.336 + delete gInspectee; 1.337 + delete gClient; 1.338 + runNextTest(); 1.339 +}); 1.340 + 1.341 + 1.342 + </script> 1.343 +</head> 1.344 +<body> 1.345 +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Mozilla Bug </a> 1.346 +<a id="inspectorContent" target="_blank" href="inspector-traversal-data.html">Test Document</a> 1.347 +<p id="display"></p> 1.348 +<div id="content" style="display: none"> 1.349 + 1.350 +</div> 1.351 +<pre id="test"> 1.352 +</pre> 1.353 +</body> 1.354 +</html>