tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

browser_inspector-traversal.js (12444B)


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