UNPKG

6.88 kBJavaScriptView Raw
1/**
2 * Copyright (c) 2013-present, Facebook, Inc.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 */
8
9'use strict';
10
11var _prodInvariant = require('./reactProdInvariant'),
12 _assign = require('object-assign');
13
14var ReactInstanceMap = require('./ReactInstanceMap');
15var ReactTestUtils = require('./ReactTestUtils');
16
17var invariant = require('fbjs/lib/invariant');
18
19function reactComponentExpect(instance) {
20 if (instance instanceof reactComponentExpectInternal) {
21 return instance;
22 }
23
24 if (!(this instanceof reactComponentExpect)) {
25 return new reactComponentExpect(instance);
26 }
27
28 expect(instance).not.toBeNull();
29 expect(instance).not.toBeUndefined();
30
31 !ReactTestUtils.isCompositeComponent(instance) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'reactComponentExpect(...): instance must be a composite component') : _prodInvariant('15') : void 0;
32 var internalInstance = ReactInstanceMap.get(instance);
33
34 expect(typeof internalInstance).toBe('object');
35 expect(typeof internalInstance.constructor).toBe('function');
36 expect(ReactTestUtils.isElement(internalInstance)).toBe(false);
37
38 return new reactComponentExpectInternal(internalInstance);
39}
40
41function reactComponentExpectInternal(internalInstance) {
42 this._instance = internalInstance;
43}
44
45_assign(reactComponentExpectInternal.prototype, {
46 // Getters -------------------------------------------------------------------
47
48 /**
49 * @instance: Retrieves the backing instance.
50 */
51 instance: function () {
52 return this._instance.getPublicInstance();
53 },
54
55 /**
56 * There are two types of components in the world.
57 * - A component created via React.createClass() - Has a single child
58 * subComponent - the return value from the .render() function. This
59 * function @subComponent expects that this._instance is component created
60 * with React.createClass().
61 * - A primitive DOM component - which has many renderedChildren, each of
62 * which may have a name that is unique with respect to its siblings. This
63 * method will fail if this._instance is a primitive component.
64 *
65 * TL;DR: An instance may have a subComponent (this._renderedComponent) or
66 * renderedChildren, but never both. Neither will actually show up until you
67 * render the component (simply instantiating is not enough).
68 */
69 expectRenderedChild: function () {
70 this.toBeCompositeComponent();
71 var child = this._instance._renderedComponent;
72 // TODO: Hide ReactEmptyComponent instances here?
73 return new reactComponentExpectInternal(child);
74 },
75
76 /**
77 * The nth child of a DOMish component instance that is not falsy.
78 */
79 expectRenderedChildAt: function (childIndex) {
80 // Currently only dom components have arrays of children, but that will
81 // change soon.
82 this.toBeDOMComponent();
83 var renderedChildren = this._instance._renderedChildren || {};
84 for (var name in renderedChildren) {
85 if (!renderedChildren.hasOwnProperty(name)) {
86 continue;
87 }
88 if (renderedChildren[name]) {
89 if (renderedChildren[name]._mountIndex === childIndex) {
90 return new reactComponentExpectInternal(renderedChildren[name]);
91 }
92 }
93 }
94 throw new Error('Child:' + childIndex + ' is not found');
95 },
96
97 toBeDOMComponentWithChildCount: function (count) {
98 this.toBeDOMComponent();
99 var renderedChildren = this._instance._renderedChildren;
100 expect(renderedChildren).toBeTruthy();
101 expect(Object.keys(renderedChildren).length).toBe(count);
102 return this;
103 },
104
105 toBeDOMComponentWithNoChildren: function () {
106 this.toBeDOMComponent();
107 expect(this._instance._renderedChildren).toBeFalsy();
108 return this;
109 },
110
111 // Matchers ------------------------------------------------------------------
112
113 toBeComponentOfType: function (constructor) {
114 expect(this._instance._currentElement.type === constructor).toBe(true);
115 return this;
116 },
117
118 /**
119 * A component that is created with React.createClass. Just duck typing
120 * here.
121 */
122 toBeCompositeComponent: function () {
123 expect(typeof this.instance() === 'object' && typeof this.instance().render === 'function').toBe(true);
124 return this;
125 },
126
127 toBeCompositeComponentWithType: function (constructor) {
128 this.toBeCompositeComponent();
129 expect(this._instance._currentElement.type === constructor).toBe(true);
130 return this;
131 },
132
133 toBeTextComponentWithValue: function (val) {
134 var elementType = typeof this._instance._currentElement;
135 expect(elementType === 'string' || elementType === 'number').toBe(true);
136 expect(this._instance._stringText).toBe(val);
137 return this;
138 },
139
140 toBeEmptyComponent: function () {
141 var element = this._instance._currentElement;
142 return element === null || element === false;
143 },
144
145 toBePresent: function () {
146 expect(this.instance()).toBeTruthy();
147 return this;
148 },
149
150 /**
151 * A terminal type of component representing some virtual dom node. Just duck
152 * typing here.
153 */
154 toBeDOMComponent: function () {
155 expect(ReactTestUtils.isDOMComponent(this.instance())).toBe(true);
156 return this;
157 },
158
159 /**
160 * @deprecated
161 * @see toBeComponentOfType
162 */
163 toBeDOMComponentWithTag: function (tag) {
164 this.toBeDOMComponent();
165 expect(this.instance().tagName).toBe(tag.toUpperCase());
166 return this;
167 },
168
169 /**
170 * Check that internal state values are equal to a state of expected values.
171 */
172 scalarStateEqual: function (stateNameToExpectedValue) {
173 expect(this.instance()).toBeTruthy();
174 for (var stateName in stateNameToExpectedValue) {
175 if (!stateNameToExpectedValue.hasOwnProperty(stateName)) {
176 continue;
177 }
178 expect(this.instance().state[stateName]).toEqual(stateNameToExpectedValue[stateName]);
179 }
180 return this;
181 },
182
183 /**
184 * Check a set of props are equal to a set of expected values - only works
185 * with scalars.
186 */
187 scalarPropsEqual: function (propNameToExpectedValue) {
188 expect(this.instance()).toBeTruthy();
189 for (var propName in propNameToExpectedValue) {
190 if (!propNameToExpectedValue.hasOwnProperty(propName)) {
191 continue;
192 }
193 expect(this.instance().props[propName]).toEqual(propNameToExpectedValue[propName]);
194 }
195 return this;
196 },
197
198 /**
199 * Check a set of props are equal to a set of expected values - only works
200 * with scalars.
201 */
202 scalarContextEqual: function (contextNameToExpectedValue) {
203 expect(this.instance()).toBeTruthy();
204 for (var contextName in contextNameToExpectedValue) {
205 if (!contextNameToExpectedValue.hasOwnProperty(contextName)) {
206 continue;
207 }
208 expect(this.instance().context[contextName]).toEqual(contextNameToExpectedValue[contextName]);
209 }
210 return this;
211 }
212});
213
214module.exports = reactComponentExpect;
\No newline at end of file