UNPKG

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