1
+/**
2
+ * Copyright 2016-present, Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under the BSD-style license found in the
6
+ * LICENSE file in the root directory of this source tree. An additional grant
7
+ * of patent rights can be found in the PATENTS file in the same directory.
8
+ *
9
+ * @emails react-core
10
+ */
11
+
12
+'use strict';
13
+
14
+describe('ReactDebugInstanceMap', function() {
15
+ var React;
16
+ var ReactDebugInstanceMap;
17
+ var ReactDOM;
18
+
19
+ beforeEach(function() {
20
+ jest.resetModuleRegistry();
21
+ React = require('React');
22
+ ReactDebugInstanceMap = require('ReactDebugInstanceMap');
23
+ ReactDOM = require('ReactDOM');
24
+ });
25
+
26
+ function createStubInstance() {
27
+ return { mountComponent: () => {} };
28
+ }
29
+
30
+ it('should register and unregister instances', function() {
31
+ var inst1 = createStubInstance();
32
+ var inst2 = createStubInstance();
33
+
34
+ expect(ReactDebugInstanceMap.isRegisteredInstance(inst1)).toBe(false);
35
+ expect(ReactDebugInstanceMap.isRegisteredInstance(inst2)).toBe(false);
36
+
37
+ ReactDebugInstanceMap.registerInstance(inst1);
38
+ expect(ReactDebugInstanceMap.isRegisteredInstance(inst1)).toBe(true);
39
+ expect(ReactDebugInstanceMap.isRegisteredInstance(inst2)).toBe(false);
40
+
41
+ ReactDebugInstanceMap.registerInstance(inst2);
42
+ expect(ReactDebugInstanceMap.isRegisteredInstance(inst1)).toBe(true);
43
+ expect(ReactDebugInstanceMap.isRegisteredInstance(inst2)).toBe(true);
44
+
45
+ ReactDebugInstanceMap.unregisterInstance(inst2);
46
+ expect(ReactDebugInstanceMap.isRegisteredInstance(inst1)).toBe(true);
47
+ expect(ReactDebugInstanceMap.isRegisteredInstance(inst2)).toBe(false);
48
+
49
+ ReactDebugInstanceMap.unregisterInstance(inst1);
50
+ expect(ReactDebugInstanceMap.isRegisteredInstance(inst1)).toBe(false);
51
+ expect(ReactDebugInstanceMap.isRegisteredInstance(inst2)).toBe(false);
52
+ });
53
+
54
+ it('should assign stable IDs', function() {
55
+ var inst1 = createStubInstance();
56
+ var inst2 = createStubInstance();
57
+
58
+ var inst1ID = ReactDebugInstanceMap.getIDForInstance(inst1);
59
+ var inst2ID = ReactDebugInstanceMap.getIDForInstance(inst2);
60
+ expect(typeof inst1ID).toBe('string');
61
+ expect(typeof inst2ID).toBe('string');
62
+ expect(inst1ID).not.toBe(inst2ID);
63
+
64
+ ReactDebugInstanceMap.registerInstance(inst1);
65
+ ReactDebugInstanceMap.registerInstance(inst2);
66
+ expect(ReactDebugInstanceMap.getIDForInstance(inst1)).toBe(inst1ID);
67
+ expect(ReactDebugInstanceMap.getIDForInstance(inst2)).toBe(inst2ID);
68
+
69
+ ReactDebugInstanceMap.unregisterInstance(inst1);
70
+ ReactDebugInstanceMap.unregisterInstance(inst2);
71
+ expect(ReactDebugInstanceMap.getIDForInstance(inst1)).toBe(inst1ID);
72
+ expect(ReactDebugInstanceMap.getIDForInstance(inst2)).toBe(inst2ID);
73
+ });
74
+
75
+ it('should retrieve registered instance by its ID', function() {
76
+ var inst1 = createStubInstance();
77
+ var inst2 = createStubInstance();
78
+
79
+ var inst1ID = ReactDebugInstanceMap.getIDForInstance(inst1);
80
+ var inst2ID = ReactDebugInstanceMap.getIDForInstance(inst2);
81
+ expect(ReactDebugInstanceMap.getInstanceByID(inst1ID)).toBe(null);
82
+ expect(ReactDebugInstanceMap.getInstanceByID(inst2ID)).toBe(null);
83
+
84
+ ReactDebugInstanceMap.registerInstance(inst1);
85
+ ReactDebugInstanceMap.registerInstance(inst2);
86
+ expect(ReactDebugInstanceMap.getInstanceByID(inst1ID)).toBe(inst1);
87
+ expect(ReactDebugInstanceMap.getInstanceByID(inst2ID)).toBe(inst2);
88
+
89
+ ReactDebugInstanceMap.unregisterInstance(inst1);
90
+ ReactDebugInstanceMap.unregisterInstance(inst2);
91
+ expect(ReactDebugInstanceMap.getInstanceByID(inst1ID)).toBe(null);
92
+ expect(ReactDebugInstanceMap.getInstanceByID(inst2ID)).toBe(null);
93
+ });
94
+
95
+ it('should warn when registering an instance twice', function() {
96
+ spyOn(console, 'error');
97
+
98
+ var inst = createStubInstance();
99
+ ReactDebugInstanceMap.registerInstance(inst);
100
+ expect(console.error.argsForCall.length).toBe(0);
101
+
102
+ ReactDebugInstanceMap.registerInstance(inst);
103
+ expect(console.error.argsForCall.length).toBe(1);
104
+ expect(console.error.argsForCall[0][0]).toContain(
105
+ 'There is an internal error in the React developer tools integration. ' +
106
+ 'A registered instance should not be registered again. ' +
107
+ 'Please report this as a bug in React.'
108
+ );
109
+
110
+ ReactDebugInstanceMap.unregisterInstance(inst);
111
+ ReactDebugInstanceMap.registerInstance(inst);
112
+ expect(console.error.argsForCall.length).toBe(1);
113
+ });
114
+
115
+ it('should warn when unregistering an instance twice', function() {
116
+ spyOn(console, 'error');
117
+ var inst = createStubInstance();
118
+
119
+ ReactDebugInstanceMap.unregisterInstance(inst);
120
+ expect(console.error.argsForCall.length).toBe(1);
121
+ expect(console.error.argsForCall[0][0]).toContain(
122
+ 'There is an internal error in the React developer tools integration. ' +
123
+ 'An unregistered instance should not be unregistered again. ' +
124
+ 'Please report this as a bug in React.'
125
+ );
126
+
127
+ ReactDebugInstanceMap.registerInstance(inst);
128
+ ReactDebugInstanceMap.unregisterInstance(inst);
129
+ expect(console.error.argsForCall.length).toBe(1);
130
+
131
+ ReactDebugInstanceMap.unregisterInstance(inst);
132
+ expect(console.error.argsForCall.length).toBe(2);
133
+ expect(console.error.argsForCall[1][0]).toContain(
134
+ 'There is an internal error in the React developer tools integration. ' +
135
+ 'An unregistered instance should not be unregistered again. ' +
136
+ 'Please report this as a bug in React.'
137
+ );
138
+ });
139
+
140
+ it('should warn about anything than is not an internal instance', function() {
141
+ class Foo extends React.Component {
142
+ render() {
143
+ return <div />;
144
+ }
145
+ }
146
+
147
+ spyOn(console, 'error');
148
+ var warningCount = 0;
149
+ var div = document.createElement('div');
150
+ var publicInst = ReactDOM.render(<Foo />, div);
151
+
152
+ [false, null, undefined, {}, div, publicInst].forEach(falsyValue => {
153
+ ReactDebugInstanceMap.registerInstance(falsyValue);
154
+ warningCount++;
155
+ expect(ReactDebugInstanceMap.getIDForInstance(falsyValue)).toBe(null);
156
+ warningCount++;
157
+ expect(ReactDebugInstanceMap.isRegisteredInstance(falsyValue)).toBe(false);
158
+ warningCount++;
159
+ ReactDebugInstanceMap.unregisterInstance(falsyValue);
160
+ warningCount++;
161
+ });
162
+
163
+ expect(console.error.argsForCall.length).toBe(warningCount);
164
+ for (var i = 0; i < warningCount.length; i++) {
165
+ // Ideally we could check for the more detailed error message here
166
+ // but it depends on the input type and is meant for internal bugs
167
+ // anyway so I don't think it's worth complicating the test with it.
168
+ expect(console.error.argsForCall[i][0]).toContain(
169
+ 'There is an internal error in the React developer tools integration.'
170
+ );
171
+ }
172
+ });
173
+});