Files
react/src/test/reactComponentExpect.js
T
Paul O’Shannessy 75897c2dcd Initial public release
2013-05-29 12:54:02 -07:00

191 lines
5.7 KiB
JavaScript

/**
* Copyright 2013 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @providesModule reactComponentExpect
* @nolint
*/
var ReactComponent = require('ReactComponent');
var ReactTestUtils = require('ReactTestUtils');
var copyProperties = require('copyProperties');
function reactComponentExpect(instance) {
if (instance instanceof reactComponentExpect) {
return instance;
}
if (!(this instanceof reactComponentExpect)) {
return new reactComponentExpect(instance);
}
this._instance = instance;
this.toBeValidReactComponent();
}
copyProperties(reactComponentExpect.prototype, {
// Getters -------------------------------------------------------------------
/**
* @instance: Retrieves the backing instance.
*/
instance: function() {
return this._instance;
},
/**
* There are two types of components in the world.
* - A component created via React.createClass() - Has a single child
* subComponent - the return value from the .render() function. This
* function @subComponent expects that this._instance is component created
* with React.createClass().
* - A primitive DOM component - which has many renderedChildren, each of
* which may have a name that is unique with respect to its siblings. This
* method will fail if this._instance is a primitive component.
*
* TL;DR: An instance may have a subComponent (this._renderedComponent) or
* renderedChildren, but never both. Neither will actually show up until you
* render the component (simply instantiating is not enough).
*/
expectRenderedChild: function() {
this.toBeCompositeComponent();
return new reactComponentExpect(this.instance()._renderedComponent);
},
/**
* The nth child of a DOMish component instance that is not falsy.
*/
expectRenderedChildAt: function(childIndex) {
// Currently only dom components have arrays of children, but that will
// change soon.
this.toBeDOMComponent();
var renderedChildren = this.instance()._renderedChildren || {};
var nonEmptyCount = 0;
var name;
for (name in renderedChildren) {
if (!renderedChildren.hasOwnProperty(name)) {
continue;
}
if (renderedChildren[name]) {
if (nonEmptyCount === childIndex) {
return new reactComponentExpect(renderedChildren[name]);
}
nonEmptyCount++;
}
}
throw new Error('Child:' + childIndex + ' is not found');
},
toBeDOMComponentWithChildCount: function(n) {
this.toBeDOMComponent();
expect(this.instance()._renderedChildren).toBeTruthy();
var len = Object.keys(this.instance()._renderedChildren).length;
expect(len).toBe(n);
return this;
},
toBeDOMComponentWithNoChildren: function() {
this.toBeDOMComponent();
expect(this.instance()._renderedChildren).toBeFalsy();
return this;
},
// Matchers ------------------------------------------------------------------
/**
* A component that is created with React.createClass. Just duck typing
* here.
*/
toBeCompositeComponent: function() {
this.toBeValidReactComponent();
expect(ReactTestUtils.isCompositeComponent(this.instance())).toBe(true);
return this;
},
toBeCompositeComponentWithType: function(convenienceConstructor) {
expect(ReactTestUtils.isCompositeComponentWithType(
this.instance(),
convenienceConstructor
)).toBe(true);
return this;
},
toBeTextComponent: function() {
expect(ReactTestUtils.isTextComponent(this.instance())).toBe(true);
return this;
},
/**
* Falsy values are valid components - the vanished component that is.
*/
toBeValidReactComponent: function() {
expect(ReactComponent.isValidComponent(this.instance())).toBe(true);
return this;
},
toBePresent: function() {
expect(this.instance()).toBeTruthy();
return this;
},
/**
* A terminal type of component representing some virtual dom node. Just duck
* typing here.
*/
toBeDOMComponent: function() {
expect(ReactTestUtils.isDOMComponent(this.instance())).toBe(true);
return this;
},
toBeDOMComponentWithTag: function(tag) {
this.toBeDOMComponent();
expect(this.instance().tagName).toBe(tag.toUpperCase());
return this;
},
/**
* Check that internal state values are equal to a state of expected values.
*/
scalarStateEqual: function(stateNameToExpectedValue) {
expect(this.instance()).toBeTruthy();
for (var stateName in stateNameToExpectedValue) {
if (!stateNameToExpectedValue.hasOwnProperty(stateName)) {
continue;
}
expect(this.instance().state[stateName])
.toEqual(stateNameToExpectedValue[stateName]);
}
return this;
},
/**
* Check a set of props are equal to a set of expected values - only works
* with scalars.
*/
scalarPropsEqual: function(propNameToExpectedValue) {
expect(this.instance()).toBeTruthy();
for (var propName in propNameToExpectedValue) {
if (!propNameToExpectedValue.hasOwnProperty(propName)) {
continue;
}
expect(this.instance().props[propName])
.toEqual(propNameToExpectedValue[propName]);
}
return this;
}
});
module.exports = reactComponentExpect;