summaryrefslogtreecommitdiffstats
path: root/devtools/client/memory/test/chrome
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /devtools/client/memory/test/chrome
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'devtools/client/memory/test/chrome')
-rw-r--r--devtools/client/memory/test/chrome/chrome.ini20
-rw-r--r--devtools/client/memory/test/chrome/head.js354
-rw-r--r--devtools/client/memory/test/chrome/test_CensusTreeItem_01.html65
-rw-r--r--devtools/client/memory/test/chrome/test_DominatorTreeItem_01.html46
-rw-r--r--devtools/client/memory/test/chrome/test_DominatorTree_01.html52
-rw-r--r--devtools/client/memory/test/chrome/test_DominatorTree_02.html52
-rw-r--r--devtools/client/memory/test/chrome/test_DominatorTree_03.html77
-rw-r--r--devtools/client/memory/test/chrome/test_Heap_01.html51
-rw-r--r--devtools/client/memory/test/chrome/test_Heap_02.html78
-rw-r--r--devtools/client/memory/test/chrome/test_Heap_03.html79
-rw-r--r--devtools/client/memory/test/chrome/test_Heap_04.html122
-rw-r--r--devtools/client/memory/test/chrome/test_Heap_05.html133
-rw-r--r--devtools/client/memory/test/chrome/test_List_01.html73
-rw-r--r--devtools/client/memory/test/chrome/test_ShortestPaths_01.html112
-rw-r--r--devtools/client/memory/test/chrome/test_ShortestPaths_02.html46
-rw-r--r--devtools/client/memory/test/chrome/test_SnapshotListItem_01.html53
-rw-r--r--devtools/client/memory/test/chrome/test_Toolbar_01.html48
-rw-r--r--devtools/client/memory/test/chrome/test_TreeMap_01.html44
18 files changed, 1505 insertions, 0 deletions
diff --git a/devtools/client/memory/test/chrome/chrome.ini b/devtools/client/memory/test/chrome/chrome.ini
new file mode 100644
index 0000000000..7803bcda35
--- /dev/null
+++ b/devtools/client/memory/test/chrome/chrome.ini
@@ -0,0 +1,20 @@
+[DEFAULT]
+support-files =
+ head.js
+
+[test_CensusTreeItem_01.html]
+[test_DominatorTree_01.html]
+[test_DominatorTree_02.html]
+[test_DominatorTree_03.html]
+[test_DominatorTreeItem_01.html]
+[test_Heap_01.html]
+[test_Heap_02.html]
+[test_Heap_03.html]
+[test_Heap_04.html]
+[test_Heap_05.html]
+[test_List_01.html]
+[test_ShortestPaths_01.html]
+[test_ShortestPaths_02.html]
+[test_SnapshotListItem_01.html]
+[test_Toolbar_01.html]
+[test_TreeMap_01.html]
diff --git a/devtools/client/memory/test/chrome/head.js b/devtools/client/memory/test/chrome/head.js
new file mode 100644
index 0000000000..685fa62928
--- /dev/null
+++ b/devtools/client/memory/test/chrome/head.js
@@ -0,0 +1,354 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+var { BrowserLoader } = ChromeUtils.import(
+ "resource://devtools/shared/loader/browser-loader.js"
+);
+var { require } = BrowserLoader({
+ baseURI: "resource://devtools/client/memory/",
+ window,
+});
+var { Assert } = ChromeUtils.importESModule(
+ "resource://testing-common/Assert.sys.mjs"
+);
+
+var EXPECTED_DTU_ASSERT_FAILURE_COUNT = 0;
+
+SimpleTest.registerCleanupFunction(function () {
+ if (
+ DevToolsUtils.assertionFailureCount !== EXPECTED_DTU_ASSERT_FAILURE_COUNT
+ ) {
+ ok(
+ false,
+ "Should have had the expected number of DevToolsUtils.assert() failures." +
+ "Expected " +
+ EXPECTED_DTU_ASSERT_FAILURE_COUNT +
+ ", got " +
+ DevToolsUtils.assertionFailureCount
+ );
+ }
+});
+
+var DevToolsUtils = require("resource://devtools/shared/DevToolsUtils.js");
+var { immutableUpdate } = DevToolsUtils;
+
+var constants = require("resource://devtools/client/memory/constants.js");
+var {
+ censusDisplays,
+ diffingState,
+ labelDisplays,
+ dominatorTreeState,
+ snapshotState,
+ viewState,
+ censusState,
+} = constants;
+
+const { L10N } = require("resource://devtools/client/memory/utils.js");
+
+var models = require("resource://devtools/client/memory/models.js");
+
+var Immutable = require("resource://devtools/client/shared/vendor/immutable.js");
+var React = require("resource://devtools/client/shared/vendor/react.js");
+const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js");
+var ReactDOM = require("resource://devtools/client/shared/vendor/react-dom.js");
+var { createFactory } = React;
+var Heap = createFactory(
+ require("resource://devtools/client/memory/components/Heap.js")
+);
+var CensusTreeItem = createFactory(
+ require("resource://devtools/client/memory/components/CensusTreeItem.js")
+);
+var DominatorTreeComponent = createFactory(
+ require("resource://devtools/client/memory/components/DominatorTree.js")
+);
+var DominatorTreeItem = createFactory(
+ require("resource://devtools/client/memory/components/DominatorTreeItem.js")
+);
+var ShortestPaths = createFactory(
+ require("resource://devtools/client/memory/components/ShortestPaths.js")
+);
+var TreeMap = createFactory(
+ require("resource://devtools/client/memory/components/TreeMap.js")
+);
+var SnapshotListItem = createFactory(
+ require("resource://devtools/client/memory/components/SnapshotListItem.js")
+);
+var List = createFactory(
+ require("resource://devtools/client/memory/components/List.js")
+);
+var Toolbar = createFactory(
+ require("resource://devtools/client/memory/components/Toolbar.js")
+);
+
+// All tests are asynchronous.
+SimpleTest.waitForExplicitFinish();
+
+var noop = () => {};
+
+var TEST_CENSUS_TREE_ITEM_PROPS = Object.freeze({
+ item: Object.freeze({
+ bytes: 10,
+ count: 1,
+ totalBytes: 10,
+ totalCount: 1,
+ name: "foo",
+ children: [
+ Object.freeze({
+ bytes: 10,
+ count: 1,
+ totalBytes: 10,
+ totalCount: 1,
+ name: "bar",
+ }),
+ ],
+ }),
+ depth: 0,
+ arrow: ">",
+ focused: true,
+ getPercentBytes: () => 50,
+ getPercentCount: () => 50,
+ showSign: false,
+ onViewSourceInDebugger: noop,
+ inverted: false,
+});
+
+// Counter for mock DominatorTreeNode ids.
+var TEST_NODE_ID_COUNTER = 0;
+
+/**
+ * Create a mock DominatorTreeNode for testing, with sane defaults. Override any
+ * property by providing it on `opts`. Optionally pass child nodes as well.
+ *
+ * @param {Object} opts
+ * @param {Array<DominatorTreeNode>?} children
+ *
+ * @returns {DominatorTreeNode}
+ */
+function makeTestDominatorTreeNode(opts, children) {
+ const nodeId = TEST_NODE_ID_COUNTER++;
+
+ const node = Object.assign(
+ {
+ nodeId,
+ label: ["other", "SomeType"],
+ shallowSize: 1,
+ retainedSize: (children || []).reduce(
+ (size, c) => size + c.retainedSize,
+ 1
+ ),
+ parentId: undefined,
+ children,
+ moreChildrenAvailable: true,
+ },
+ opts
+ );
+
+ if (children && children.length) {
+ children.map(c => {
+ c.parentId = node.nodeId;
+ });
+ }
+
+ return node;
+}
+
+var TEST_DOMINATOR_TREE = Object.freeze({
+ dominatorTreeId: 666,
+ root: (function makeTree(depth = 0) {
+ let children;
+ if (depth <= 3) {
+ children = [
+ makeTree(depth + 1),
+ makeTree(depth + 1),
+ makeTree(depth + 1),
+ ];
+ }
+ return makeTestDominatorTreeNode({}, children);
+ })(),
+ expanded: new Set(),
+ focused: null,
+ error: null,
+ display: labelDisplays.coarseType,
+ activeFetchRequestCount: null,
+ state: dominatorTreeState.LOADED,
+});
+
+var TEST_DOMINATOR_TREE_PROPS = Object.freeze({
+ dominatorTree: TEST_DOMINATOR_TREE,
+ onLoadMoreSiblings: noop,
+ onViewSourceInDebugger: noop,
+ onExpand: noop,
+ onCollapse: noop,
+});
+
+var TEST_SHORTEST_PATHS_PROPS = Object.freeze({
+ graph: Object.freeze({
+ nodes: [
+ { id: 1, label: ["other", "SomeType"] },
+ { id: 2, label: ["other", "SomeType"] },
+ { id: 3, label: ["other", "SomeType"] },
+ ],
+ edges: [
+ { from: 1, to: 2, name: "1->2" },
+ { from: 1, to: 3, name: "1->3" },
+ { from: 2, to: 3, name: "2->3" },
+ ],
+ }),
+});
+
+var TEST_SNAPSHOT = Object.freeze({
+ id: 1337,
+ selected: true,
+ path: "/fake/path/to/snapshot",
+ census: Object.freeze({
+ report: Object.freeze({
+ objects: Object.freeze({ count: 4, bytes: 400 }),
+ scripts: Object.freeze({ count: 3, bytes: 300 }),
+ strings: Object.freeze({ count: 2, bytes: 200 }),
+ other: Object.freeze({ count: 1, bytes: 100 }),
+ }),
+ display: Object.freeze({
+ displayName: "Test Display",
+ tooltip: "Test display tooltup",
+ inverted: false,
+ breakdown: Object.freeze({
+ by: "coarseType",
+ objects: Object.freeze({ by: "count", count: true, bytes: true }),
+ scripts: Object.freeze({ by: "count", count: true, bytes: true }),
+ strings: Object.freeze({ by: "count", count: true, bytes: true }),
+ other: Object.freeze({ by: "count", count: true, bytes: true }),
+ }),
+ }),
+ state: censusState.SAVED,
+ inverted: false,
+ filter: null,
+ expanded: new Set(),
+ focused: null,
+ parentMap: Object.freeze(Object.create(null)),
+ }),
+ dominatorTree: TEST_DOMINATOR_TREE,
+ error: null,
+ imported: false,
+ creationTime: 0,
+ state: snapshotState.READ,
+});
+
+var TEST_HEAP_PROPS = Object.freeze({
+ onSnapshotClick: noop,
+ onLoadMoreSiblings: noop,
+ onCensusExpand: noop,
+ onCensusCollapse: noop,
+ onDominatorTreeExpand: noop,
+ onDominatorTreeCollapse: noop,
+ onCensusFocus: noop,
+ onDominatorTreeFocus: noop,
+ onViewSourceInDebugger: noop,
+ diffing: null,
+ view: { state: viewState.CENSUS },
+ snapshot: TEST_SNAPSHOT,
+ sizes: Object.freeze({ shortestPathsSize: 0.5 }),
+ onShortestPathsResize: noop,
+});
+
+var TEST_TOOLBAR_PROPS = Object.freeze({
+ censusDisplays: [
+ censusDisplays.coarseType,
+ censusDisplays.allocationStack,
+ censusDisplays.invertedAllocationStack,
+ ],
+ censusDisplay: censusDisplays.coarseType,
+ onTakeSnapshotClick: noop,
+ onImportClick: noop,
+ onCensusDisplayChange: noop,
+ onToggleRecordAllocationStacks: noop,
+ allocations: models.allocations,
+ onToggleInverted: noop,
+ inverted: false,
+ filterString: null,
+ setFilterString: noop,
+ diffing: null,
+ onToggleDiffing: noop,
+ view: { state: viewState.CENSUS },
+ onViewChange: noop,
+ labelDisplays: [labelDisplays.coarseType, labelDisplays.allocationStack],
+ labelDisplay: labelDisplays.coarseType,
+ onLabelDisplayChange: noop,
+ snapshots: [],
+});
+
+function makeTestCensusNode() {
+ return {
+ name: "Function",
+ bytes: 100,
+ totalBytes: 100,
+ count: 100,
+ totalCount: 100,
+ children: [],
+ };
+}
+
+var TEST_TREE_MAP_PROPS = Object.freeze({
+ treeMap: Object.freeze({
+ report: {
+ name: null,
+ bytes: 0,
+ totalBytes: 400,
+ count: 0,
+ totalCount: 400,
+ children: [
+ {
+ name: "objects",
+ bytes: 0,
+ totalBytes: 200,
+ count: 0,
+ totalCount: 200,
+ children: [makeTestCensusNode(), makeTestCensusNode()],
+ },
+ {
+ name: "other",
+ bytes: 0,
+ totalBytes: 200,
+ count: 0,
+ totalCount: 200,
+ children: [makeTestCensusNode(), makeTestCensusNode()],
+ },
+ ],
+ },
+ }),
+});
+
+var TEST_SNAPSHOT_LIST_ITEM_PROPS = Object.freeze({
+ onClick: noop,
+ onSave: noop,
+ onDelete: noop,
+ item: TEST_SNAPSHOT,
+ index: 1234,
+});
+
+function onNextAnimationFrame(fn) {
+ return () => requestAnimationFrame(() => requestAnimationFrame(fn));
+}
+
+/**
+ * Render the provided ReactElement in the provided HTML container.
+ * Returns a Promise that will resolve the rendered element as a React
+ * component.
+ */
+function renderComponent(element, container) {
+ return new Promise(resolve => {
+ const component = ReactDOM.render(
+ element,
+ container,
+ onNextAnimationFrame(() => {
+ dumpn("Rendered = " + container.innerHTML);
+ resolve(component);
+ })
+ );
+ });
+}
+
+function dumpn(msg) {
+ dump(`MEMORY-TEST: ${msg}\n`);
+}
diff --git a/devtools/client/memory/test/chrome/test_CensusTreeItem_01.html b/devtools/client/memory/test/chrome/test_CensusTreeItem_01.html
new file mode 100644
index 0000000000..21d900b668
--- /dev/null
+++ b/devtools/client/memory/test/chrome/test_CensusTreeItem_01.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Test that children pointers show up at the correct times.
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tree 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>
+ <!-- Give the container height so that the whole tree is rendered. -->
+ <div id="container" style="height: 900px;"></div>
+
+ <pre id="test">
+ <script src="head.js" type="application/javascript"></script>
+ <script type="application/javascript">
+ "use strict";
+ window.onload = async function() {
+ try {
+ const container = document.getElementById("container");
+
+ await renderComponent(CensusTreeItem(immutableUpdate(TEST_CENSUS_TREE_ITEM_PROPS, {
+ inverted: true,
+ depth: 0,
+ })), container);
+
+ ok(!container.querySelector(".children-pointer"),
+ "Don't show children pointer for roots when we are inverted");
+
+ await renderComponent(CensusTreeItem(immutableUpdate(TEST_CENSUS_TREE_ITEM_PROPS, {
+ inverted: true,
+ depth: 1,
+ })), container);
+
+ ok(container.querySelector(".children-pointer"),
+ "Do show children pointer for non-roots when we are inverted");
+
+ await renderComponent(CensusTreeItem(immutableUpdate(TEST_CENSUS_TREE_ITEM_PROPS, {
+ inverted: false,
+ item: immutableUpdate(TEST_CENSUS_TREE_ITEM_PROPS.item, { children: undefined }),
+ })), container);
+
+ ok(!container.querySelector(".children-pointer"),
+ "Don't show children pointer when non-inverted and no children");
+
+ await renderComponent(CensusTreeItem(immutableUpdate(TEST_CENSUS_TREE_ITEM_PROPS, {
+ inverted: false,
+ depth: 0,
+ item: immutableUpdate(TEST_CENSUS_TREE_ITEM_PROPS.item, { children: [{}] }),
+ })), container);
+
+ ok(container.querySelector(".children-pointer"),
+ "Do show children pointer when non-inverted and have children");
+ } catch (e) {
+ ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
+ } finally {
+ SimpleTest.finish();
+ }
+ };
+ </script>
+ </pre>
+</body>
+</html>
diff --git a/devtools/client/memory/test/chrome/test_DominatorTreeItem_01.html b/devtools/client/memory/test/chrome/test_DominatorTreeItem_01.html
new file mode 100644
index 0000000000..c8cb6b6036
--- /dev/null
+++ b/devtools/client/memory/test/chrome/test_DominatorTreeItem_01.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Test that we don't display `JS::ubi::RootList` for the root, and instead show "GC Roots".
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tree 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>
+ <!-- Give the container height so that the whole tree is rendered. -->
+ <div id="container" style="height: 900px;"></div>
+
+ <pre id="test">
+ <script src="head.js" type="application/javascript"></script>
+ <script type="application/javascript">
+ "use strict";
+ window.onload = async function() {
+ try {
+ const container = document.getElementById("container");
+
+ await renderComponent(DominatorTreeItem({
+ item: makeTestDominatorTreeNode({ label: ["other", "JS::ubi::RootList"] }),
+ depth: 0,
+ arrow: dom.div(),
+ focused: true,
+ getPercentSize: _ => 50,
+ onViewSourceInDebugger: _ => { },
+ }), container);
+
+ ok(!container.textContent.includes("JS::ubi::RootList"),
+ "Should not display `JS::ubi::RootList`");
+ ok(container.textContent.includes("GC Roots"),
+ "Should display `GC Roots` instead");
+ } catch (e) {
+ ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
+ } finally {
+ SimpleTest.finish();
+ }
+ };
+ </script>
+ </pre>
+</body>
+</html>
diff --git a/devtools/client/memory/test/chrome/test_DominatorTree_01.html b/devtools/client/memory/test/chrome/test_DominatorTree_01.html
new file mode 100644
index 0000000000..0067a0f412
--- /dev/null
+++ b/devtools/client/memory/test/chrome/test_DominatorTree_01.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Test that we show a place holder for a subtree we are lazily fetching.
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tree 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>
+ <!-- Give the container height so that the whole tree is rendered. -->
+ <div id="container" style="height: 900px;"></div>
+
+ <pre id="test">
+ <script src="head.js" type="application/javascript"></script>
+ <script type="application/javascript">
+ "use strict";
+ window.onload = async function() {
+ try {
+ const container = document.getElementById("container");
+
+ const root = makeTestDominatorTreeNode({ moreChildrenAvailable: true});
+ ok(!root.children);
+
+ const expanded = new Set();
+ expanded.add(root.nodeId);
+
+ await renderComponent(DominatorTreeComponent(immutableUpdate(
+ TEST_DOMINATOR_TREE_PROPS, {
+ dominatorTree: immutableUpdate(TEST_DOMINATOR_TREE_PROPS.dominatorTree, {
+ expanded,
+ root,
+ state: dominatorTreeState.INCREMENTAL_FETCHING,
+ activeFetchRequestCount: 1,
+ }),
+ })), container);
+
+ ok(container.querySelector(".subtree-fetching"),
+ "Expanded nodes with more children available, but no children " +
+ "loaded, should get a placeholder");
+ } catch (e) {
+ ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
+ } finally {
+ SimpleTest.finish();
+ }
+ };
+ </script>
+ </pre>
+</body>
+</html>
diff --git a/devtools/client/memory/test/chrome/test_DominatorTree_02.html b/devtools/client/memory/test/chrome/test_DominatorTree_02.html
new file mode 100644
index 0000000000..66aad95296
--- /dev/null
+++ b/devtools/client/memory/test/chrome/test_DominatorTree_02.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Test that we show a link to load more children when some (but not all) are loaded.
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tree 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>
+ <!-- Give the container height so that the whole tree is rendered. -->
+ <div id="container" style="height: 900px;"></div>
+
+ <pre id="test">
+ <script src="head.js" type="application/javascript"></script>
+ <script type="application/javascript">
+ "use strict";
+ window.onload = async function() {
+ try {
+ const container = document.getElementById("container");
+
+ const root = makeTestDominatorTreeNode({ moreChildrenAvailable: true }, [
+ makeTestDominatorTreeNode({}),
+ ]);
+ ok(root.children);
+ ok(root.moreChildrenAvailable);
+
+ const expanded = new Set();
+ expanded.add(root.nodeId);
+
+ await renderComponent(DominatorTreeComponent(immutableUpdate(
+ TEST_DOMINATOR_TREE_PROPS, {
+ dominatorTree: immutableUpdate(TEST_DOMINATOR_TREE_PROPS.dominatorTree, {
+ expanded,
+ root,
+ }),
+ })), container);
+
+ ok(container.querySelector(".more-children"),
+ "Should get a link to load more children");
+ } catch (e) {
+ ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
+ } finally {
+ SimpleTest.finish();
+ }
+ };
+ </script>
+ </pre>
+</body>
+</html>
diff --git a/devtools/client/memory/test/chrome/test_DominatorTree_03.html b/devtools/client/memory/test/chrome/test_DominatorTree_03.html
new file mode 100644
index 0000000000..6fcfa3d577
--- /dev/null
+++ b/devtools/client/memory/test/chrome/test_DominatorTree_03.html
@@ -0,0 +1,77 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Test that expanded DominatorTreeItems are correctly rendered and updated
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tree 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>
+ <!-- Give the container height so that the whole tree is rendered. -->
+ <div id="container" style="height: 900px;"></div>
+
+ <pre id="test">
+ <script src="head.js" type="application/javascript"></script>
+ <script type="application/javascript">
+ "use strict";
+ window.onload = async function() {
+ try {
+ const container = document.getElementById("container");
+
+ // simple tree with one root and one child
+ const root = makeTestDominatorTreeNode(
+ { moreChildrenAvailable: false },
+ [
+ makeTestDominatorTreeNode({ moreChildrenAvailable: false }),
+ ]);
+ ok(root.children);
+
+ // root node is expanded
+ const expanded = new Set();
+ expanded.add(root.nodeId);
+
+ await renderComponent(
+ DominatorTreeComponent(immutableUpdate(
+ TEST_DOMINATOR_TREE_PROPS,
+ {
+ dominatorTree: immutableUpdate(
+ TEST_DOMINATOR_TREE_PROPS.dominatorTree,
+ { expanded, root }
+ ),
+ })), container);
+ ok(true, "Dominator tree rendered");
+
+ is(container.querySelectorAll(".tree-node").length, 2,
+ "Should display two rows");
+ is(container.querySelectorAll(".arrow.open").length, 1,
+ "Should display one expanded arrow");
+
+ await renderComponent(
+ DominatorTreeComponent(immutableUpdate(
+ TEST_DOMINATOR_TREE_PROPS,
+ {
+ dominatorTree: immutableUpdate(
+ TEST_DOMINATOR_TREE_PROPS.dominatorTree,
+ { expanded: new Set(), root }
+ ),
+ })), container);
+
+ ok(true, "Dominator tree props updated to collapse all nodes");
+
+ is(container.querySelectorAll(".tree-node").length, 1,
+ "Should display only one row");
+ is(container.querySelectorAll(".arrow.open").length, 0,
+ "Should display no expanded arrow");
+ } catch (e) {
+ ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
+ } finally {
+ SimpleTest.finish();
+ }
+ };
+ </script>
+ </pre>
+</body>
+</html>
diff --git a/devtools/client/memory/test/chrome/test_Heap_01.html b/devtools/client/memory/test/chrome/test_Heap_01.html
new file mode 100644
index 0000000000..2facc3d221
--- /dev/null
+++ b/devtools/client/memory/test/chrome/test_Heap_01.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Test that rendering a dominator tree error is handled correctly.
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tree 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>
+ <div id="container"></div>
+ <pre id="test">
+ <script src="head.js" type="application/javascript"></script>
+
+ <script type="application/javascript">
+ "use strict";
+ window.onload = async function() {
+ try {
+ ok(React, "Should get React");
+ ok(Heap, "Should get Heap");
+
+ const errorMessage = "Something went wrong!";
+ const container = document.getElementById("container");
+
+ const props = immutableUpdate(TEST_HEAP_PROPS, {
+ view: { state: viewState.DOMINATOR_TREE },
+ snapshot: immutableUpdate(TEST_HEAP_PROPS.snapshot, {
+ dominatorTree: {
+ error: new Error(errorMessage),
+ state: dominatorTreeState.ERROR,
+ },
+ }),
+ });
+
+ await renderComponent(Heap(props), container);
+
+ ok(container.querySelector(".error"), "Should render an error view");
+ ok(container.textContent.includes(errorMessage),
+ "Should see our error message");
+ } catch (e) {
+ ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
+ } finally {
+ SimpleTest.finish();
+ }
+ };
+ </script>
+ </pre>
+</body>
+</html>
diff --git a/devtools/client/memory/test/chrome/test_Heap_02.html b/devtools/client/memory/test/chrome/test_Heap_02.html
new file mode 100644
index 0000000000..343ee66714
--- /dev/null
+++ b/devtools/client/memory/test/chrome/test_Heap_02.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Test that the currently selected view is rendered.
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tree 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>
+ <div id="container"></div>
+ <pre id="test">
+ <script src="head.js" type="application/javascript"></script>
+ <script type="application/javascript">
+ "use strict";
+ window.onload = async function() {
+ try {
+ ok(React, "Should get React");
+ ok(Heap, "Should get Heap");
+
+ const container = document.getElementById("container");
+
+ // Dominator tree view.
+
+ await renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
+ view: { state: viewState.DOMINATOR_TREE },
+ })), container);
+
+ ok(container.querySelector(`[data-state=${dominatorTreeState.LOADED}]`),
+ "Should render the dominator tree.");
+
+ // Census view.
+
+ await renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
+ view: { state: viewState.CENSUS },
+ })), container);
+
+ ok(container.querySelector(`[data-state=${censusState.SAVED}]`),
+ "Should render the census.");
+
+ // Diffing view.
+
+ await renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
+ view: { state: viewState.DIFFING },
+ snapshot: null,
+ diffing: {
+ firstSnapshotId: null,
+ secondSnapshotId: null,
+ census: null,
+ error: null,
+ state: diffingState.SELECTING,
+ },
+ })), container);
+
+ ok(container.querySelector(`[data-state=${diffingState.SELECTING}]`),
+ "Should render the diffing.");
+
+ // Initial view.
+
+ await renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
+ snapshot: null,
+ diffing: null,
+ })), container);
+
+ ok(container.querySelector("[data-state=initial]"),
+ "With no snapshot, nor a diffing, should render initial prompt.");
+ } catch (e) {
+ ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
+ } finally {
+ SimpleTest.finish();
+ }
+ };
+ </script>
+ </pre>
+</body>
+</html>
diff --git a/devtools/client/memory/test/chrome/test_Heap_03.html b/devtools/client/memory/test/chrome/test_Heap_03.html
new file mode 100644
index 0000000000..69f95f4275
--- /dev/null
+++ b/devtools/client/memory/test/chrome/test_Heap_03.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Test that we show a throbber while computing and fetching dominator trees,
+but not in other dominator tree states.
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tree 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>
+ <div id="container"></div>
+ <pre id="test">
+ <script src="head.js" type="application/javascript"></script>
+ <script type="application/javascript">
+ "use strict";
+ window.onload = async function() {
+ try {
+ const container = document.getElementById("container");
+
+ for (const state of [dominatorTreeState.COMPUTING, dominatorTreeState.FETCHING]) {
+ await renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
+ view: { state: viewState.DOMINATOR_TREE },
+ snapshot: immutableUpdate(TEST_HEAP_PROPS.snapshot, {
+ dominatorTree: immutableUpdate(TEST_HEAP_PROPS.snapshot.dominatorTree, {
+ state,
+ root: null,
+ dominatorTreeId: state === dominatorTreeState.FETCHING ? 1 : null,
+ }),
+ }),
+ })), container);
+
+ ok(container.querySelector(".devtools-throbber"),
+ `Should show a throbber for state = ${state}`);
+ }
+
+ for (
+ const state of [
+ dominatorTreeState.LOADED, dominatorTreeState.INCREMENTAL_FETCHING,
+ ]) {
+ await renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
+ view: { state: viewState.DOMINATOR_TREE },
+ snapshot: immutableUpdate(TEST_HEAP_PROPS.snapshot, {
+ dominatorTree: immutableUpdate(TEST_HEAP_PROPS.snapshot.dominatorTree, {
+ state,
+ activeFetchRequestCount:
+ state === dominatorTreeState.INCREMENTAL_FETCHING ? 1 : undefined,
+ }),
+ }),
+ })), container);
+
+ ok(!container.querySelector(".devtools-throbber"),
+ `Should not show a throbber for state = ${state}`);
+ }
+
+ await renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
+ view: { state: viewState.DOMINATOR_TREE },
+ snapshot: immutableUpdate(TEST_HEAP_PROPS.snapshot, {
+ dominatorTree: {
+ state: dominatorTreeState.ERROR,
+ error: new Error("example error for testing"),
+ },
+ }),
+ })), container);
+
+ ok(!container.querySelector(".devtools-throbber"),
+ `Should not show a throbber for ERROR state`);
+ } catch (e) {
+ ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
+ } finally {
+ SimpleTest.finish();
+ }
+ };
+ </script>
+ </pre>
+</body>
+</html>
diff --git a/devtools/client/memory/test/chrome/test_Heap_04.html b/devtools/client/memory/test/chrome/test_Heap_04.html
new file mode 100644
index 0000000000..76de5e4826
--- /dev/null
+++ b/devtools/client/memory/test/chrome/test_Heap_04.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Test that we show the "hey you're not recording allocation stacks" message at the appropriate times.
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tree 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>
+ <div id="container"></div>
+ <pre id="test">
+ <script src="head.js" type="application/javascript"></script>
+ <script type="application/javascript">
+ "use strict";
+ window.onload = async function() {
+ try {
+ const container = document.getElementById("container");
+
+ await renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
+ snapshot: immutableUpdate(TEST_HEAP_PROPS.snapshot, {
+ census: immutableUpdate(TEST_HEAP_PROPS.snapshot.census, {
+ report: {
+ bytes: 1,
+ totalBytes: 1,
+ count: 1,
+ totalCount: 1,
+ id: 1,
+ parent: undefined,
+ children: [
+ {
+ name: "noStack",
+ bytes: 1,
+ totalBytes: 1,
+ count: 1,
+ totalCount: 1,
+ children: undefined,
+ id: 3,
+ parent: 1,
+ },
+ ],
+ },
+ display: censusDisplays.allocationStack,
+ }),
+ }),
+ })), container);
+
+ ok(container.querySelector(".no-allocation-stacks"),
+ "When there are no allocation stacks, we should show the message");
+
+ await renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
+ snapshot: immutableUpdate(TEST_HEAP_PROPS.snapshot, {
+ census: immutableUpdate(TEST_HEAP_PROPS.snapshot.census, {
+ report: {
+ bytes: 1,
+ totalBytes: 1,
+ count: 1,
+ totalCount: 1,
+ id: 1,
+ parent: undefined,
+ children: [
+ {
+ name: Cu.getJSTestingFunctions().saveStack(),
+ bytes: 1,
+ totalBytes: 1,
+ count: 1,
+ totalCount: 1,
+ children: undefined,
+ id: 2,
+ parent: 1,
+ },
+ {
+ name: "noStack",
+ bytes: 1,
+ totalBytes: 1,
+ count: 1,
+ totalCount: 1,
+ children: undefined,
+ id: 3,
+ parent: 1,
+ },
+ ],
+ },
+ display: censusDisplays.allocationStack,
+ }),
+ }),
+ })), container);
+
+ ok(!container.querySelector(".no-allocation-stacks"),
+ "When there are allocation stacks, we should not show the message");
+
+ await renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
+ snapshot: immutableUpdate(TEST_HEAP_PROPS.snapshot, {
+ census: immutableUpdate(TEST_HEAP_PROPS.snapshot.census, {
+ report: {
+ bytes: 1,
+ totalBytes: 1,
+ count: 1,
+ totalCount: 1,
+ id: 1,
+ parent: undefined,
+ children: undefined,
+ },
+ display: censusDisplays.allocationStack,
+ }),
+ }),
+ })), container);
+
+ ok(!container.querySelector(".no-allocation-stacks"),
+ "When there isn't census data, we should not show the message");
+ } catch (e) {
+ ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
+ } finally {
+ SimpleTest.finish();
+ }
+ };
+ </script>
+ </pre>
+</body>
+</html>
diff --git a/devtools/client/memory/test/chrome/test_Heap_05.html b/devtools/client/memory/test/chrome/test_Heap_05.html
new file mode 100644
index 0000000000..bd3fc393cc
--- /dev/null
+++ b/devtools/client/memory/test/chrome/test_Heap_05.html
@@ -0,0 +1,133 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Test that we show a message when the census results are empty.
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tree 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>
+ <div id="container"></div>
+ <pre id="test">
+ <script src="head.js" type="application/javascript"></script>
+ <script type="application/javascript">
+ "use strict";
+ window.onload = async function() {
+ try {
+ const container = document.getElementById("container");
+
+ await renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
+ snapshot: immutableUpdate(TEST_HEAP_PROPS.snapshot, {
+ census: immutableUpdate(TEST_HEAP_PROPS.snapshot.census, {
+ report: {
+ bytes: 1,
+ totalBytes: 1,
+ count: 1,
+ totalCount: 1,
+ id: 1,
+ parent: undefined,
+ children: [
+ {
+ name: Cu.getJSTestingFunctions().saveStack(),
+ bytes: 1,
+ totalBytes: 1,
+ count: 1,
+ totalCount: 1,
+ children: undefined,
+ id: 2,
+ parent: 1,
+ },
+ {
+ name: "noStack",
+ bytes: 1,
+ totalBytes: 1,
+ count: 1,
+ totalCount: 1,
+ children: undefined,
+ id: 3,
+ parent: 1,
+ },
+ ],
+ },
+ display: censusDisplays.allocationStack,
+ }),
+ }),
+ })), container);
+
+ ok(!container.querySelector(".empty"),
+ "When the report is not empty, we should not show the empty message");
+
+ // Empty Census Report
+
+ const emptyCensus = {
+ report: {
+ bytes: 0,
+ totalBytes: 0,
+ count: 0,
+ totalCount: 0,
+ id: 1,
+ parent: undefined,
+ children: undefined,
+ },
+ parentMap: Object.create(null),
+ display: censusDisplays.allocationStack,
+ filter: null,
+ expanded: new Immutable.Set(),
+ focused: null,
+ state: censusState.SAVED,
+ };
+
+ await renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
+ snapshot: immutableUpdate(TEST_HEAP_PROPS.snapshot, {
+ census: immutableUpdate(TEST_HEAP_PROPS.snapshot.census, emptyCensus),
+ }),
+ })), container);
+
+ ok(container.querySelector(".empty"),
+ "When the report is empty in census view, we show the empty message");
+ ok(container.textContent.includes(L10N.getStr("heapview.empty")));
+
+ // Empty Diffing Report
+
+ await renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
+ view: { state: viewState.DIFFING },
+ diffing: {
+ firstSnapshotId: 1,
+ secondSnapshotId: 2,
+ census: emptyCensus,
+ state: diffingState.TOOK_DIFF,
+ },
+ snapshot: null,
+ })), container);
+
+ ok(container.querySelector(".empty"),
+ "When the report is empty in diffing view, the empty message is shown");
+ ok(container.textContent.includes(L10N.getStr("heapview.no-difference")));
+
+ // Empty Filtered Census
+
+ await renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
+ snapshot: immutableUpdate(TEST_HEAP_PROPS.snapshot, {
+ census: immutableUpdate(
+ TEST_HEAP_PROPS.snapshot.census, immutableUpdate(emptyCensus, {
+ filter: "zzzz",
+ })),
+ }),
+ })), container);
+
+ ok(container.querySelector(".empty"),
+ "When the report is empty in census view w/ filter, we show the empty message");
+ ok(container.textContent.includes(L10N.getStr("heapview.none-match")));
+ } catch (e) {
+ ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
+ } finally {
+ SimpleTest.finish();
+ }
+ };
+ </script>
+ </pre>
+</body>
+</html>
diff --git a/devtools/client/memory/test/chrome/test_List_01.html b/devtools/client/memory/test/chrome/test_List_01.html
new file mode 100644
index 0000000000..4ffab49620
--- /dev/null
+++ b/devtools/client/memory/test/chrome/test_List_01.html
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Test to verify the delete button calls the onDelete handler for an item
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tree 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>
+ <div id="container"></div>
+
+ <pre id="test">
+ <script src="head.js" type="application/javascript"></script>
+ <script type="application/javascript">
+ "use strict";
+ window.onload = async function() {
+ try {
+ const container = document.getElementById("container");
+
+ const deletedSnapshots = [];
+
+ const snapshots = [ TEST_SNAPSHOT, TEST_SNAPSHOT, TEST_SNAPSHOT ]
+ .map((snapshot, index) => immutableUpdate(snapshot, {
+ index: snapshot.index + index,
+ }));
+
+ await renderComponent(
+ List({
+ itemComponent: SnapshotListItem,
+ onClick: noop,
+ onDelete: (item) => deletedSnapshots.push(item),
+ items: snapshots,
+ }),
+ container
+ );
+
+ const deleteButtons = container.querySelectorAll(".delete");
+
+ is(container.querySelectorAll(".snapshot-list-item").length, 3,
+ "There are 3 list items\n");
+ is(deletedSnapshots.length, 0,
+ "Not snapshots have been deleted\n");
+
+ deleteButtons[1].click();
+
+ is(deletedSnapshots.length, 1, "One snapshot was deleted\n");
+ is(deletedSnapshots[0], snapshots[1],
+ "Deleted snapshot was added to the deleted list\n");
+
+ deleteButtons[0].click();
+
+ is(deletedSnapshots.length, 2, "Two snapshots were deleted\n");
+ is(deletedSnapshots[1], snapshots[0],
+ "Deleted snapshot was added to the deleted list\n");
+
+ deleteButtons[2].click();
+
+ is(deletedSnapshots.length, 3, "Three snapshots were deleted\n");
+ is(deletedSnapshots[2], snapshots[2],
+ "Deleted snapshot was added to the deleted list\n");
+ } catch (e) {
+ ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
+ } finally {
+ SimpleTest.finish();
+ }
+ };
+ </script>
+ </pre>
+</body>
+</html>
diff --git a/devtools/client/memory/test/chrome/test_ShortestPaths_01.html b/devtools/client/memory/test/chrome/test_ShortestPaths_01.html
new file mode 100644
index 0000000000..29905bfaca
--- /dev/null
+++ b/devtools/client/memory/test/chrome/test_ShortestPaths_01.html
@@ -0,0 +1,112 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Test that the ShortestPaths component properly renders a graph of the merged shortest paths.
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tree 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">
+
+ <script type="application/javascript"
+ src="chrome://global/content/third_party/d3/d3.js">
+ </script>
+ <script type="application/javascript"
+ src="chrome://devtools/content/shared/vendor/dagre-d3.js">
+ </script>
+</head>
+<body>
+ <!-- Give the container height so that the whole tree is rendered. -->
+ <div id="container" style="height: 900px;"></div>
+
+ <pre id="test">
+ <script src="head.js" type="application/javascript"></script>
+ <script type="application/javascript">
+ "use strict";
+ window.onload = async function() {
+ try {
+ const container = document.getElementById("container");
+
+ await renderComponent(ShortestPaths(TEST_SHORTEST_PATHS_PROPS), container);
+
+ let found1 = false;
+ let found2 = false;
+ let found3 = false;
+
+ let found1to2 = false;
+ let found1to3 = false;
+ let found2to3 = false;
+
+ const tspans = [...container.querySelectorAll("tspan")];
+ for (const el of tspans) {
+ const text = el.textContent.trim();
+ dumpn("tspan's text = " + text);
+
+ switch (text) {
+ // Nodes
+
+ case "other › SomeType @ 0x1": {
+ ok(!found1, "Should only find node 1 once");
+ found1 = true;
+ break;
+ }
+
+ case "other › SomeType @ 0x2": {
+ ok(!found2, "Should only find node 2 once");
+ found2 = true;
+ break;
+ }
+
+ case "other › SomeType @ 0x3": {
+ ok(!found3, "Should only find node 3 once");
+ found3 = true;
+ break;
+ }
+
+ // Edges
+
+ case "1->2": {
+ ok(!found1to2, "Should only find edge 1->2 once");
+ found1to2 = true;
+ break;
+ }
+
+ case "1->3": {
+ ok(!found1to3, "Should only find edge 1->3 once");
+ found1to3 = true;
+ break;
+ }
+
+ case "2->3": {
+ ok(!found2to3, "Should only find edge 2->3 once");
+ found2to3 = true;
+ break;
+ }
+
+ // Unexpected
+
+ default: {
+ ok(false, `Unexpected tspan: ${text}`);
+ break;
+ }
+ }
+ }
+
+ ok(found1, "Should have rendered node 1");
+ ok(found2, "Should have rendered node 2");
+ ok(found3, "Should have rendered node 3");
+
+ ok(found1to2, "Should have rendered edge 1->2");
+ ok(found1to3, "Should have rendered edge 1->3");
+ ok(found2to3, "Should have rendered edge 2->3");
+ } catch (e) {
+ ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
+ } finally {
+ SimpleTest.finish();
+ }
+ };
+ </script>
+ </pre>
+</body>
+</html>
diff --git a/devtools/client/memory/test/chrome/test_ShortestPaths_02.html b/devtools/client/memory/test/chrome/test_ShortestPaths_02.html
new file mode 100644
index 0000000000..cbf0370d22
--- /dev/null
+++ b/devtools/client/memory/test/chrome/test_ShortestPaths_02.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Test that the ShortestPaths component renders a suggestion to select a node when there is no graph.
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tree 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">
+
+ <script type="application/javascript"
+ src="chrome://global/content/third_party/d3/d3.js">
+ </script>
+ <script type="application/javascript"
+ src="chrome://devtools/content/shared/vendor/dagre-d3.js">
+ </script>
+</head>
+<body>
+ <!-- Give the container height so that the whole tree is rendered. -->
+ <div id="container" style="height: 900px;"></div>
+
+ <pre id="test">
+ <script src="head.js" type="application/javascript"></script>
+ <script type="application/javascript">
+ "use strict";
+ window.onload = async function() {
+ try {
+ const container = document.getElementById("container");
+
+ await renderComponent(ShortestPaths(immutableUpdate(TEST_SHORTEST_PATHS_PROPS,
+ { graph: null })),
+ container);
+
+ ok(container.textContent.includes(L10N.getStr("shortest-paths.select-node")),
+ "The node selection prompt is displayed");
+ } catch (e) {
+ ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
+ } finally {
+ SimpleTest.finish();
+ }
+ };
+ </script>
+ </pre>
+</body>
+</html>
diff --git a/devtools/client/memory/test/chrome/test_SnapshotListItem_01.html b/devtools/client/memory/test/chrome/test_SnapshotListItem_01.html
new file mode 100644
index 0000000000..20fc137479
--- /dev/null
+++ b/devtools/client/memory/test/chrome/test_SnapshotListItem_01.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Test to verify that the delete button only shows up for a snapshot when it has a
+path.
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tree 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>
+ <div id="container"></div>
+
+ <pre id="test">
+ <script src="head.js" type="application/javascript"></script>
+ <script type="application/javascript">
+ "use strict";
+ window.onload = async function() {
+ try {
+ const container = document.getElementById("container");
+
+ await renderComponent(
+ SnapshotListItem(TEST_SNAPSHOT_LIST_ITEM_PROPS),
+ container
+ );
+
+ ok(container.querySelector(".delete"),
+ "Should have delete button when there is a path");
+
+ const pathlessProps = immutableUpdate(
+ TEST_SNAPSHOT_LIST_ITEM_PROPS,
+ {item: immutableUpdate(TEST_SNAPSHOT, {path: null})}
+ );
+
+ await renderComponent(
+ SnapshotListItem(pathlessProps),
+ container
+ );
+
+ ok(!container.querySelector(".delete"),
+ "No delete button should be found if there is no path\n");
+ } catch (e) {
+ ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
+ } finally {
+ SimpleTest.finish();
+ }
+ };
+ </script>
+ </pre>
+</body>
+</html>
diff --git a/devtools/client/memory/test/chrome/test_Toolbar_01.html b/devtools/client/memory/test/chrome/test_Toolbar_01.html
new file mode 100644
index 0000000000..3bf934c77c
--- /dev/null
+++ b/devtools/client/memory/test/chrome/test_Toolbar_01.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Test that the Toolbar component shows the view switcher only at the appropriate times.
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tree 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>
+ <div id="container"></div>
+ <pre id="test">
+ <script src="head.js" type="application/javascript"></script>
+ <script type="application/javascript">
+ "use strict";
+ window.onload = async function() {
+ try {
+ const container = document.getElementById("container");
+
+ // Census and dominator tree views.
+
+ for (const view of [viewState.CENSUS, viewState.DOMINATOR_TREE]) {
+ await renderComponent(Toolbar(immutableUpdate(TEST_TOOLBAR_PROPS, {
+ view: { state: view },
+ })), container);
+
+ ok(container.querySelector("#select-view"),
+ `The view selector is shown in view = ${view}`);
+ }
+
+ await renderComponent(Toolbar(immutableUpdate(TEST_TOOLBAR_PROPS, {
+ view: { state: viewState.DIFFING },
+ })), container);
+
+ ok(!container.querySelector("#select-view"),
+ "The view selector is NOT shown in the DIFFING view");
+ } catch (e) {
+ ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
+ } finally {
+ SimpleTest.finish();
+ }
+ };
+ </script>
+ </pre>
+</body>
+</html>
diff --git a/devtools/client/memory/test/chrome/test_TreeMap_01.html b/devtools/client/memory/test/chrome/test_TreeMap_01.html
new file mode 100644
index 0000000000..7b8b98b9a7
--- /dev/null
+++ b/devtools/client/memory/test/chrome/test_TreeMap_01.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Test that the Tree Map correctly renders onto 2 managed canvases.
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tree 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">
+
+ <script type="application/javascript"
+ src="chrome://global/content/third_party/d3/d3.js">
+ </script>
+</head>
+<body>
+ <!-- Give the container height so that the whole tree is rendered. -->
+ <div id="container" style="height: 900px;"></div>
+
+ <pre id="test">
+ <script src="head.js" type="application/javascript"></script>
+ <script type="application/javascript">
+ "use strict";
+ window.onload = async function() {
+ try {
+ const container = document.getElementById("container");
+
+ await renderComponent(TreeMap(TEST_TREE_MAP_PROPS), container);
+
+ const treeMapContainer = container.querySelector(".tree-map-container");
+ ok(treeMapContainer, "Component creates a container");
+
+ const canvases = treeMapContainer.querySelectorAll("canvas");
+ is(canvases.length, 2, "Creates 2 canvases");
+ } catch (e) {
+ ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
+ } finally {
+ SimpleTest.finish();
+ }
+ };
+ </script>
+ </pre>
+</body>
+</html>