@samitouri / QOS-React / commits / 9f16003e69

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 });