tor-browser

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

test_smart-trace-source-maps.html (8738B)


      1 <!-- This Source Code Form is subject to the terms of the Mozilla Public
      2   - License, v. 2.0. If a copy of the MPL was not distributed with this
      3   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
      4 <!DOCTYPE HTML>
      5 <html>
      6 <!--
      7 Test the rendering of a stack trace
      8 -->
      9 <head>
     10  <meta charset="utf-8">
     11  <title>StackTrace component test</title>
     12  <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
     13  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
     14 </head>
     15 <body>
     16 <script src="head.js"></script>
     17 <script>
     18 "use strict";
     19 
     20 window.onload = function() {
     21  const ReactDOM = browserRequire("devtools/client/shared/vendor/react-dom");
     22  const React = browserRequire("devtools/client/shared/vendor/react");
     23  const SmartTrace = React.createFactory(
     24    browserRequire("devtools/client/shared/components/SmartTrace"));
     25  ok(SmartTrace, "Got the SmartTrace factory");
     26 
     27  add_task(async function testHappyPath() {
     28    const stacktrace = [
     29      {
     30        filename: "https://myfile.com/bundle.js",
     31        lineNumber: 1,
     32        columnNumber: 10,
     33      },
     34      {
     35        functionName: "loadFunc",
     36        filename: "https://myfile.com/bundle.js",
     37        lineNumber: 2,
     38      },
     39    ];
     40 
     41    let onReadyCount = 0;
     42    const props = {
     43      stacktrace,
     44      initialRenderDelay: 2000,
     45      onViewSourceInDebugger: () => {},
     46      onReady: () => {
     47        onReadyCount++;
     48      },
     49      // A mock source map service.
     50      sourceMapURLService: {
     51       subscribeByLocation ({ line, column }, callback) {
     52         const newLine = Number(line.toString().repeat(2));
     53         // Resolve immediately.
     54          callback({
     55            url: "https://bugzilla.mozilla.org/original.js",
     56            line: newLine,
     57            column,
     58          });
     59          return () => {};
     60       },
     61      },
     62    };
     63 
     64    const trace = ReactDOM.render(SmartTrace(props),
     65      window.document.body.querySelector("#s1"));
     66    await forceRender(trace);
     67 
     68    const traceEl = ReactDOM.findDOMNode(trace);
     69    ok(traceEl, "Rendered SmartTrace has an element");
     70 
     71    const frameEls = Array.from(traceEl.querySelectorAll(".frame"));
     72    ok(frameEls, "Rendered SmartTrace has frames");
     73    is(frameEls.length, 2, "SmartTrace has 2 frames");
     74 
     75    checkSmartFrameString({
     76      el: frameEls[0],
     77      functionName: "<anonymous>",
     78      location: "original.js:11",
     79      tooltip: "View source in Debugger → https://bugzilla.mozilla.org/original.js:11",
     80    });
     81 
     82    checkSmartFrameString({
     83      el: frameEls[1],
     84      functionName: "loadFunc",
     85      location: "original.js:22",
     86      tooltip: "View source in Debugger → https://bugzilla.mozilla.org/original.js:22",
     87    });
     88 
     89    is(onReadyCount, 1, "onReady was called once");
     90  });
     91 
     92  add_task(async function testSlowSourcemapService() {
     93    const stacktrace = [
     94      {
     95        filename: "https://myfile.com/bundle.js",
     96        functionName: "last",
     97        lineNumber: 1,
     98        columnNumber: 10,
     99      },
    100      {
    101        filename: "https://myfile.com/bundle.js",
    102        functionName: "first",
    103        lineNumber: 2,
    104        columnNumber: 10,
    105      },
    106    ];
    107 
    108    const sourcemapTimeout = 2000;
    109    const initialRenderDelay = 300;
    110    let onReadyCount = 0;
    111 
    112    const props = {
    113      stacktrace,
    114      initialRenderDelay,
    115      onViewSourceInDebugger: () => {},
    116      onReady: () => {
    117        onReadyCount++;
    118      },
    119      // A mock source map service.
    120      sourceMapURLService: {
    121        subscribeByLocation ({ line, column }, callback) {
    122          // Resolve after a while.
    123          setTimeout(() => {
    124            const newLine = Number(line.toString().repeat(2));
    125            callback({
    126              url: "https://myfile.com/react.js",
    127              line: newLine,
    128              column,
    129            });
    130          }, sourcemapTimeout)
    131 
    132          return () => {};
    133        },
    134      },
    135    };
    136 
    137    const trace = ReactDOM.render(SmartTrace(props),
    138      window.document.body.querySelector("#s2"));
    139 
    140    let traceEl = ReactDOM.findDOMNode(trace);
    141    ok(!traceEl, "Nothing was rendered at first");
    142    is(onReadyCount, 0, "onReady isn't called if SmartTrace isn't rendered");
    143 
    144    info("Wait for the initial delay to be over");
    145    await new Promise(res => setTimeout(res, initialRenderDelay));
    146 
    147    traceEl = ReactDOM.findDOMNode(trace);
    148    ok(traceEl, "The trace was rendered");
    149 
    150    let frameEls = Array.from(traceEl.querySelectorAll(".frame"));
    151    ok(frameEls, "Rendered SmartTrace has frames");
    152    is(frameEls.length, 2, "SmartTrace has 2 frames");
    153 
    154    info("Check that the original frames are displayed after the initial delay");
    155    checkSmartFrameString({
    156      el: frameEls[0],
    157      functionName: "last",
    158      location: "https://myfile.com/bundle.js:1",
    159      tooltip: "View source in Debugger → https://myfile.com/bundle.js:1",
    160    });
    161 
    162    checkSmartFrameString({
    163      el: frameEls[1],
    164      functionName: "first",
    165      location: "https://myfile.com/bundle.js:2",
    166      tooltip: "View source in Debugger → https://myfile.com/bundle.js:2",
    167    });
    168 
    169    is(onReadyCount, 1, "onReady was called once");
    170 
    171    info("Check the the sourcemapped version is rendered after the sourcemapTimeout");
    172    await waitFor(() => !!traceEl.querySelector(".frames-group"));
    173 
    174    frameEls = Array.from(traceEl.querySelectorAll(".frame:not(.frames-group)"));
    175    is(frameEls.length, 0, "SmartTrace has no frame");
    176 
    177    const groups = Array.from(traceEl.querySelectorAll(".frames-group"));
    178    is(groups.length, 1, "SmartTrace has a group");
    179    is(groups[0].textContent.trim(), "React 2", "A collapsed React group is displayed");
    180 
    181    is(onReadyCount, 1, "onReady was only called once");
    182  });
    183 
    184  add_task(async function testFlakySourcemapService() {
    185    const stacktrace = [
    186      {
    187        filename: "https://myfile.com/bundle.js",
    188        functionName: "last",
    189        lineNumber: 1,
    190        columnNumber: 10,
    191      },
    192      {
    193        filename: "https://myfile.com/bundle.js",
    194        functionName: "pending",
    195        lineNumber: 2,
    196        columnNumber: 10,
    197      },
    198      {
    199        filename: "https://myfile.com/bundle.js",
    200        functionName: "first",
    201        lineNumber: 3,
    202        columnNumber: 10,
    203      },
    204    ];
    205 
    206    const initialRenderDelay = 300;
    207    const onSourceMapResultDebounceDelay = 50;
    208    let onReadyCount = 0;
    209 
    210    const props = {
    211      stacktrace,
    212      initialRenderDelay,
    213      onSourceMapResultDebounceDelay,
    214      onViewSourceInDebugger: () => {},
    215      onReady: () => {
    216        onReadyCount++;
    217      },
    218      // A mock source map service.
    219      sourceMapURLService: {
    220        subscribeByLocation ({ line, column }, callback) {
    221          // Don't call the callback for the second frame to simulate a flaky sourcemap
    222          // service request.
    223          if (line === 2) {
    224            return () => {};
    225          }
    226 
    227          const newLine = Number(line.toString().repeat(2));
    228          callback({
    229            url: `https://myfile.com/file-${line}.js`,
    230            line: newLine,
    231            column,
    232          });
    233          return () => {};
    234        },
    235      },
    236    };
    237 
    238    const trace = ReactDOM.render(SmartTrace(props),
    239      window.document.body.querySelector("#s3"));
    240 
    241    let traceEl = ReactDOM.findDOMNode(trace);
    242    ok(!traceEl, "Nothing was rendered at first");
    243    is(onReadyCount, 0, "onReady isn't called if SmartTrace isn't rendered");
    244 
    245    info("Wait for the initial delay + debounce to be over");
    246    await waitFor(() => {
    247      const  el = ReactDOM.findDOMNode(trace)
    248      return el && el.textContent.includes("file-1.js");
    249    });
    250 
    251    traceEl = ReactDOM.findDOMNode(trace);
    252    ok(traceEl, "The trace was rendered");
    253 
    254    const frameEls = Array.from(traceEl.querySelectorAll(".frame"));
    255    ok(frameEls, "Rendered SmartTrace has frames");
    256    is(frameEls.length, 3, "SmartTrace has 3 frames");
    257 
    258    info("Check that the original frames are displayed even if there's no sourcemap " +
    259      "response for some frames");
    260    checkSmartFrameString({
    261      el: frameEls[0],
    262      functionName: "last",
    263      location: "file-1.js:11",
    264      tooltip: "View source in Debugger → https://myfile.com/file-1.js:11",
    265    });
    266 
    267    checkSmartFrameString({
    268      el: frameEls[1],
    269      functionName: "pending",
    270      location: "bundle.js:2",
    271      tooltip: "View source in Debugger → https://myfile.com/bundle.js:2",
    272    });
    273 
    274    checkSmartFrameString({
    275      el: frameEls[2],
    276      functionName: "first",
    277      location: "file-3.js:33",
    278      tooltip: "View source in Debugger → https://myfile.com/file-3.js:33",
    279    });
    280 
    281    is(onReadyCount, 1, "onReady was only called once");
    282  });
    283 
    284 };
    285 </script>
    286 <section id=s1></section>
    287 <section id=s2></section>
    288 <section id=s3></section>
    289 </body>
    290 </html>