Assert that unmounted instances are in the tree until purged
Dan Abramov committed
Apr 24, 2016 at 01:53 UTC
9f16003e69fd1e24a8bf98a8905c4e4c0d595154
2 files changed
+106
-17
src/isomorphic/devtools/ReactComponentTreeDevtool.js
+1
-1
@@ -119,7 +119,7 @@ var ReactComponentTreeDevtool = {
119
unmountedContainerIDs.push(nativeContainerID);
120
},
121
122
- purgeComponentsFromUnmountedContainers() {
122
+ purgeUnmountedComponents() {
123
var unmountedIDs = Object.keys(tree).filter(id =>
124
unmountedContainerIDs.indexOf(tree[id].nativeContainerID) !== -1
125
);
src/isomorphic/devtools/__tests__/ReactComponentTreeDevtool-test.js
+105
-16
@@ -42,34 +42,43 @@ describe('ReactComponentTreeDevtool', () => {
42
.map(ReactComponentTreeDevtool.getDisplayName);
43
}
44
45
- function getTree(rootID, includeOwner = false, expectedParentID = null) {
45
+ function getTree(rootID, options = {}) {
46
+ var {
47
+ includeOwnerDisplayName = false,
48
+ includeParentDisplayName = false,
49
+ expectedParentID = null,
50
+ } = options;
51
+
52
var result = {
53
isComposite: ReactComponentTreeDevtool.isComposite(rootID),
54
displayName: ReactComponentTreeDevtool.getDisplayName(rootID),
55
};
56
57
+ var ownerID = ReactComponentTreeDevtool.getOwnerID(rootID);
58
var parentID = ReactComponentTreeDevtool.getParentID(rootID);
59
expect(parentID).toBe(expectedParentID);
60
61
+ if (includeParentDisplayName && parentID) {
62
+ result.parentDisplayName = ReactComponentTreeDevtool.getDisplayName(parentID);
63
+ }
64
+ if (includeOwnerDisplayName && ownerID) {
65
+ result.ownerDisplayName = ReactComponentTreeDevtool.getDisplayName(ownerID);
66
+ }
67
+
68
var childIDs = ReactComponentTreeDevtool.getChildIDs(rootID);
69
var text = ReactComponentTreeDevtool.getText(rootID);
70
if (text != null) {
71
result.text = text;
72
} else {
73
result.children = childIDs.map(childID =>
60
- getTree(childID, includeOwner, rootID)
74
+ getTree(childID, {...options, expectedParentID: rootID })
75
);
76
}
77
64
- var ownerID = ReactComponentTreeDevtool.getOwnerID(rootID);
65
- if (includeOwner && ownerID) {
66
- result.ownerDisplayName = ReactComponentTreeDevtool.getDisplayName(ownerID);
67
- }
68
-
78
return result;
79
}
80
72
- function assertTreeMatches(pairs, includeOwner) {
81
+ function assertTreeMatches(pairs, options) {
82
if (!Array.isArray(pairs[0])) {
83
pairs = [pairs];
84
}
@@ -85,23 +94,31 @@ describe('ReactComponentTreeDevtool', () => {
94
}
95
}
96
97
+ function getActualTree() {
98
+ return getTree(rootInstance._debugID, options).children[0];
99
+ }
100
+
101
pairs.forEach(([element, expectedTree]) => {
102
currentElement = element;
103
ReactDOM.render(<Wrapper />, node);
91
- expect(
92
- getTree(rootInstance._debugID, includeOwner).children[0]
93
- ).toEqual(expectedTree);
104
+ expect(getActualTree()).toEqual(expectedTree);
105
});
106
ReactDOM.unmountComponentAtNode(node);
107
+
108
+ var lastExpectedTree = pairs[pairs.length - 1][1];
109
+ expect(getActualTree()).toEqual(lastExpectedTree);
110
+
111
+ ReactComponentTreeDevtool.purgeUnmountedComponents();
112
+ expect(getActualTree()).toBe(undefined);
113
expect(getRegisteredDisplayNames()).toEqual([]);
114
115
pairs.forEach(([element, expectedTree]) => {
116
currentElement = element;
117
ReactDOMServer.renderToString(<Wrapper />);
101
- expect(
102
- getTree(rootInstance._debugID, includeOwner).children[0]
103
- ).toEqual(expectedTree);
104
- ReactComponentTreeDevtool.purgeComponentsFromUnmountedContainers();
118
+ expect(getActualTree()).toEqual(expectedTree);
119
+
120
+ ReactComponentTreeDevtool.purgeUnmountedComponents();
121
+ expect(getActualTree()).toBe(undefined);
122
expect(getRegisteredDisplayNames()).toEqual([]);
123
});
124
}
@@ -1820,7 +1837,77 @@ describe('ReactComponentTreeDevtool', () => {
1837
}],
1838
}],
1839
};
1823
- assertTreeMatches([element, tree], true);
1840
+ assertTreeMatches([element, tree], {includeOwnerDisplayName: true});
1841
+ });
1842
+
1843
+ it.only('preserves unmounted components until purge', () => {
1844
+ var node = document.createElement('div');
1845
+ var renderBar = true;
1846
+ var fooInstance;
1847
+ var barInstance;
1848
+
1849
+ class Foo extends React.Component {
1850
+ render() {
1851
+ fooInstance = ReactInstanceMap.get(this);
1852
+ return renderBar ? <Bar /> : null;
1853
+ }
1854
+ }
1855
+
1856
+ class Bar extends React.Component {
1857
+ render() {
1858
+ barInstance = ReactInstanceMap.get(this);
1859
+ return null;
1860
+ }
1861
+ }
1862
+
1863
+ ReactDOM.render(<Foo />, node);
1864
+ expect(
1865
+ getTree(barInstance._debugID, {
1866
+ includeParentDisplayName: true,
1867
+ expectedParentID: fooInstance._debugID
1868
+ })
1869
+ ).toEqual({
1870
+ isComposite: true,
1871
+ displayName: 'Bar',
1872
+ parentDisplayName: 'Foo',
1873
+ children: [],
1874
+ });
1875
+
1876
+ renderBar = false;
1877
+ ReactDOM.render(<Foo />, node);
1878
+ expect(
1879
+ getTree(barInstance._debugID, {
1880
+ includeParentDisplayName: true,
1881
+ expectedParentID: fooInstance._debugID
1882
+ })
1883
+ ).toEqual({
1884
+ isComposite: true,
1885
+ displayName: 'Bar',
1886
+ parentDisplayName: 'Foo',
1887
+ children: [],
1888
+ });
1889
+
1890
+ ReactDOM.unmountComponentAtNode(node);
1891
+ expect(
1892
+ getTree(barInstance._debugID, {
1893
+ includeParentDisplayName: true,
1894
+ expectedParentID: fooInstance._debugID,
1895
+ })
1896
+ ).toEqual({
1897
+ isComposite: true,
1898
+ displayName: 'Bar',
1899
+ parentDisplayName: 'Foo',
1900
+ children: [],
1901
+ });
1902
+
1903
+ ReactComponentTreeDevtool.purgeUnmountedComponents();
1904
+ expect(
1905
+ getTree(barInstance._debugID, {includeParentDisplayName: true})
1906
+ ).toEqual({
1907
+ isComposite: false,
1908
+ displayName: 'Unknown',
1909
+ children: [],
1910
+ });
1911
});
1912
1913
it('ignores top-level wrapper', () => {
@@ -1830,6 +1917,8 @@ describe('ReactComponentTreeDevtool', () => {
1917
ReactDOM.render(<div className="b" />, node);
1918
expect(getRegisteredDisplayNames()).toEqual(['div']);
1919
ReactDOM.unmountComponentAtNode(node);
1920
+ expect(getRegisteredDisplayNames()).toEqual(['div']);
1921
+ ReactComponentTreeDevtool.purgeUnmountedComponents();
1922
expect(getRegisteredDisplayNames()).toEqual([]);
1923
});
1924
});