290 lines
8.5 KiB
HTML
290 lines
8.5 KiB
HTML
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
|
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
|
<!DOCTYPE HTML>
|
|
<html>
|
|
<!--
|
|
Test the rendering of a stack trace
|
|
-->
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>StackTrace component test</title>
|
|
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
|
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
|
</head>
|
|
<body>
|
|
<script src="head.js"></script>
|
|
<script>
|
|
"use strict";
|
|
|
|
window.onload = function() {
|
|
const ReactDOM = browserRequire("devtools/client/shared/vendor/react-dom");
|
|
const React = browserRequire("devtools/client/shared/vendor/react");
|
|
const SmartTrace = React.createFactory(
|
|
browserRequire("devtools/client/shared/components/SmartTrace"));
|
|
ok(SmartTrace, "Got the SmartTrace factory");
|
|
|
|
add_task(async function testHappyPath() {
|
|
const stacktrace = [
|
|
{
|
|
filename: "https://myfile.com/bundle.js",
|
|
lineNumber: 1,
|
|
columnNumber: 10,
|
|
},
|
|
{
|
|
functionName: "loadFunc",
|
|
filename: "https://myfile.com/bundle.js",
|
|
lineNumber: 2,
|
|
},
|
|
];
|
|
|
|
let onReadyCount = 0;
|
|
const props = {
|
|
stacktrace,
|
|
initialRenderDelay: 2000,
|
|
onViewSourceInDebugger: () => {},
|
|
onReady: () => {
|
|
onReadyCount++;
|
|
},
|
|
// A mock source map service.
|
|
sourceMapURLService: {
|
|
subscribeByLocation ({ line, column }, callback) {
|
|
const newLine = Number(line.toString().repeat(2));
|
|
// Resolve immediately.
|
|
callback({
|
|
url: "https://bugzilla.mozilla.org/original.js",
|
|
line: newLine,
|
|
column,
|
|
});
|
|
return () => {};
|
|
},
|
|
},
|
|
};
|
|
|
|
const trace = ReactDOM.render(SmartTrace(props),
|
|
window.document.body.querySelector("#s1"));
|
|
await forceRender(trace);
|
|
|
|
const traceEl = ReactDOM.findDOMNode(trace);
|
|
ok(traceEl, "Rendered SmartTrace has an element");
|
|
|
|
const frameEls = Array.from(traceEl.querySelectorAll(".frame"));
|
|
ok(frameEls, "Rendered SmartTrace has frames");
|
|
is(frameEls.length, 2, "SmartTrace has 2 frames");
|
|
|
|
checkSmartFrameString({
|
|
el: frameEls[0],
|
|
functionName: "<anonymous>",
|
|
location: "original.js:11",
|
|
tooltip: "View source in Debugger → https://bugzilla.mozilla.org/original.js:11",
|
|
});
|
|
|
|
checkSmartFrameString({
|
|
el: frameEls[1],
|
|
functionName: "loadFunc",
|
|
location: "original.js:22",
|
|
tooltip: "View source in Debugger → https://bugzilla.mozilla.org/original.js:22",
|
|
});
|
|
|
|
is(onReadyCount, 1, "onReady was called once");
|
|
});
|
|
|
|
add_task(async function testSlowSourcemapService() {
|
|
const stacktrace = [
|
|
{
|
|
filename: "https://myfile.com/bundle.js",
|
|
functionName: "last",
|
|
lineNumber: 1,
|
|
columnNumber: 10,
|
|
},
|
|
{
|
|
filename: "https://myfile.com/bundle.js",
|
|
functionName: "first",
|
|
lineNumber: 2,
|
|
columnNumber: 10,
|
|
},
|
|
];
|
|
|
|
const sourcemapTimeout = 2000;
|
|
const initialRenderDelay = 300;
|
|
let onReadyCount = 0;
|
|
|
|
const props = {
|
|
stacktrace,
|
|
initialRenderDelay,
|
|
onViewSourceInDebugger: () => {},
|
|
onReady: () => {
|
|
onReadyCount++;
|
|
},
|
|
// A mock source map service.
|
|
sourceMapURLService: {
|
|
subscribeByLocation ({ line, column }, callback) {
|
|
// Resolve after a while.
|
|
setTimeout(() => {
|
|
const newLine = Number(line.toString().repeat(2));
|
|
callback({
|
|
url: "https://myfile.com/react.js",
|
|
line: newLine,
|
|
column,
|
|
});
|
|
}, sourcemapTimeout)
|
|
|
|
return () => {};
|
|
},
|
|
},
|
|
};
|
|
|
|
const trace = ReactDOM.render(SmartTrace(props),
|
|
window.document.body.querySelector("#s2"));
|
|
|
|
let traceEl = ReactDOM.findDOMNode(trace);
|
|
ok(!traceEl, "Nothing was rendered at first");
|
|
is(onReadyCount, 0, "onReady isn't called if SmartTrace isn't rendered");
|
|
|
|
info("Wait for the initial delay to be over");
|
|
await new Promise(res => setTimeout(res, initialRenderDelay));
|
|
|
|
traceEl = ReactDOM.findDOMNode(trace);
|
|
ok(traceEl, "The trace was rendered");
|
|
|
|
let frameEls = Array.from(traceEl.querySelectorAll(".frame"));
|
|
ok(frameEls, "Rendered SmartTrace has frames");
|
|
is(frameEls.length, 2, "SmartTrace has 2 frames");
|
|
|
|
info("Check that the original frames are displayed after the initial delay");
|
|
checkSmartFrameString({
|
|
el: frameEls[0],
|
|
functionName: "last",
|
|
location: "https://myfile.com/bundle.js:1",
|
|
tooltip: "View source in Debugger → https://myfile.com/bundle.js:1",
|
|
});
|
|
|
|
checkSmartFrameString({
|
|
el: frameEls[1],
|
|
functionName: "first",
|
|
location: "https://myfile.com/bundle.js:2",
|
|
tooltip: "View source in Debugger → https://myfile.com/bundle.js:2",
|
|
});
|
|
|
|
is(onReadyCount, 1, "onReady was called once");
|
|
|
|
info("Check the the sourcemapped version is rendered after the sourcemapTimeout");
|
|
await waitFor(() => !!traceEl.querySelector(".frames-group"));
|
|
|
|
frameEls = Array.from(traceEl.querySelectorAll(".frame:not(.frames-group)"));
|
|
is(frameEls.length, 0, "SmartTrace has no frame");
|
|
|
|
const groups = Array.from(traceEl.querySelectorAll(".frames-group"));
|
|
is(groups.length, 1, "SmartTrace has a group");
|
|
is(groups[0].textContent.trim(), "React 2", "A collapsed React group is displayed");
|
|
|
|
is(onReadyCount, 1, "onReady was only called once");
|
|
});
|
|
|
|
add_task(async function testFlakySourcemapService() {
|
|
const stacktrace = [
|
|
{
|
|
filename: "https://myfile.com/bundle.js",
|
|
functionName: "last",
|
|
lineNumber: 1,
|
|
columnNumber: 10,
|
|
},
|
|
{
|
|
filename: "https://myfile.com/bundle.js",
|
|
functionName: "pending",
|
|
lineNumber: 2,
|
|
columnNumber: 10,
|
|
},
|
|
{
|
|
filename: "https://myfile.com/bundle.js",
|
|
functionName: "first",
|
|
lineNumber: 3,
|
|
columnNumber: 10,
|
|
},
|
|
];
|
|
|
|
const initialRenderDelay = 300;
|
|
const onSourceMapResultDebounceDelay = 50;
|
|
let onReadyCount = 0;
|
|
|
|
const props = {
|
|
stacktrace,
|
|
initialRenderDelay,
|
|
onSourceMapResultDebounceDelay,
|
|
onViewSourceInDebugger: () => {},
|
|
onReady: () => {
|
|
onReadyCount++;
|
|
},
|
|
// A mock source map service.
|
|
sourceMapURLService: {
|
|
subscribeByLocation ({ line, column }, callback) {
|
|
// Don't call the callback for the second frame to simulate a flaky sourcemap
|
|
// service request.
|
|
if (line === 2) {
|
|
return () => {};
|
|
}
|
|
|
|
const newLine = Number(line.toString().repeat(2));
|
|
callback({
|
|
url: `https://myfile.com/file-${line}.js`,
|
|
line: newLine,
|
|
column,
|
|
});
|
|
return () => {};
|
|
},
|
|
},
|
|
};
|
|
|
|
const trace = ReactDOM.render(SmartTrace(props),
|
|
window.document.body.querySelector("#s3"));
|
|
|
|
let traceEl = ReactDOM.findDOMNode(trace);
|
|
ok(!traceEl, "Nothing was rendered at first");
|
|
is(onReadyCount, 0, "onReady isn't called if SmartTrace isn't rendered");
|
|
|
|
info("Wait for the initial delay + debounce to be over");
|
|
await waitFor(() => {
|
|
const el = ReactDOM.findDOMNode(trace)
|
|
return el && el.textContent.includes("file-1.js");
|
|
});
|
|
|
|
traceEl = ReactDOM.findDOMNode(trace);
|
|
ok(traceEl, "The trace was rendered");
|
|
|
|
const frameEls = Array.from(traceEl.querySelectorAll(".frame"));
|
|
ok(frameEls, "Rendered SmartTrace has frames");
|
|
is(frameEls.length, 3, "SmartTrace has 3 frames");
|
|
|
|
info("Check that the original frames are displayed even if there's no sourcemap " +
|
|
"response for some frames");
|
|
checkSmartFrameString({
|
|
el: frameEls[0],
|
|
functionName: "last",
|
|
location: "file-1.js:11",
|
|
tooltip: "View source in Debugger → https://myfile.com/file-1.js:11",
|
|
});
|
|
|
|
checkSmartFrameString({
|
|
el: frameEls[1],
|
|
functionName: "pending",
|
|
location: "bundle.js:2",
|
|
tooltip: "View source in Debugger → https://myfile.com/bundle.js:2",
|
|
});
|
|
|
|
checkSmartFrameString({
|
|
el: frameEls[2],
|
|
functionName: "first",
|
|
location: "file-3.js:33",
|
|
tooltip: "View source in Debugger → https://myfile.com/file-3.js:33",
|
|
});
|
|
|
|
is(onReadyCount, 1, "onReady was only called once");
|
|
});
|
|
|
|
};
|
|
</script>
|
|
<section id=s1></section>
|
|
<section id=s2></section>
|
|
<section id=s3></section>
|
|
</body>
|
|
</html>
|