react / react-0.13.3 / examples / basic-commonjs / node_modules / reactify / node_modules / react-tools / src / core / __tests__ / ReactElement-test.js
81155 views/**1* Copyright 2013-2014, Facebook, Inc.2* All rights reserved.3*4* This source code is licensed under the BSD-style license found in the5* LICENSE file in the root directory of this source tree. An additional grant6* of patent rights can be found in the PATENTS file in the same directory.7*8* @emails react-core9*/1011"use strict";1213var React;14var ReactElement;15var ReactTestUtils;1617describe('ReactElement', function() {18var ComponentFactory;19var ComponentClass;2021beforeEach(function() {22React = require('React');23ReactElement = require('ReactElement');24ReactTestUtils = require('ReactTestUtils');25ComponentFactory = React.createClass({26render: function() { return <div />; }27});28ComponentClass = ComponentFactory.type;29});3031it('returns a complete element according to spec', function() {32var element = React.createFactory(ComponentFactory)();33expect(element.type).toBe(ComponentClass);34expect(element.key).toBe(null);35expect(element.ref).toBe(null);36expect(element.props).toEqual({});37});3839it('allows a string to be passed as the type', function() {40var element = React.createFactory('div')();41expect(element.type).toBe('div');42expect(element.key).toBe(null);43expect(element.ref).toBe(null);44expect(element.props).toEqual({});45});4647it('returns an immutable element', function() {48var element = React.createFactory(ComponentFactory)();49expect(() => element.type = 'div').toThrow();50});5152it('does not reuse the original config object', function() {53var config = { foo: 1 };54var element = React.createFactory(ComponentFactory)(config);55expect(element.props.foo).toBe(1);56config.foo = 2;57expect(element.props.foo).toBe(1);58});5960it('extracts key and ref from the config', function() {61var element = React.createFactory(ComponentFactory)({62key: '12',63ref: '34',64foo: '56'65});66expect(element.type).toBe(ComponentClass);67expect(element.key).toBe('12');68expect(element.ref).toBe('34');69expect(element.props).toEqual({foo:'56'});70});7172it('coerces the key to a string', function() {73var element = React.createFactory(ComponentFactory)({74key: 12,75foo: '56'76});77expect(element.type).toBe(ComponentClass);78expect(element.key).toBe('12');79expect(element.ref).toBe(null);80expect(element.props).toEqual({foo:'56'});81});8283it('treats a null key as omitted but warns', function() {84spyOn(console, 'warn');85var element = React.createFactory(ComponentFactory)({86key: null,87foo: '56'88});89expect(element.type).toBe(ComponentClass);90expect(element.key).toBe(null); // as opposed to string 'null'91expect(element.ref).toBe(null);92expect(element.props).toEqual({foo:'56'});93expect(console.warn.argsForCall.length).toBe(1);94expect(console.warn.argsForCall[0][0]).toContain(95'will be treated as equivalent to the string \'null\''96);97});9899it('preserves the context on the element', function() {100var Component = React.createFactory(ComponentFactory);101var element;102103var Wrapper = React.createClass({104childContextTypes: {105foo: React.PropTypes.string106},107getChildContext: function() {108return { foo: 'bar' };109},110render: function() {111element = Component();112return element;113}114});115116ReactTestUtils.renderIntoDocument(<Wrapper />);117118expect(element._context).toEqual({ foo: 'bar' });119});120121it('preserves the owner on the element', function() {122var Component = React.createFactory(ComponentFactory);123var element;124125var Wrapper = React.createClass({126childContextTypes: {127foo: React.PropTypes.string128},129getChildContext: function() {130return { foo: 'bar' };131},132render: function() {133element = Component();134return element;135}136});137138var instance = ReactTestUtils.renderIntoDocument(<Wrapper />);139140expect(element._owner).toBe(instance);141});142143it('merges an additional argument onto the children prop', function() {144spyOn(console, 'warn');145var a = 1;146var element = React.createFactory(ComponentFactory)({147children: 'text'148}, a);149expect(element.props.children).toBe(a);150expect(console.warn.argsForCall.length).toBe(0);151});152153it('does not override children if no rest args are provided', function() {154spyOn(console, 'warn');155var element = React.createFactory(ComponentFactory)({156children: 'text'157});158expect(element.props.children).toBe('text');159expect(console.warn.argsForCall.length).toBe(0);160});161162it('overrides children if null is provided as an argument', function() {163spyOn(console, 'warn');164var element = React.createFactory(ComponentFactory)({165children: 'text'166}, null);167expect(element.props.children).toBe(null);168expect(console.warn.argsForCall.length).toBe(0);169});170171it('merges rest arguments onto the children prop in an array', function() {172spyOn(console, 'warn');173var a = 1, b = 2, c = 3;174var element = React.createFactory(ComponentFactory)(null, a, b, c);175expect(element.props.children).toEqual([1, 2, 3]);176expect(console.warn.argsForCall.length).toBe(0);177});178179it('warns for keys for arrays of elements in rest args', function() {180spyOn(console, 'warn');181var Component = React.createFactory(ComponentFactory);182183Component(null, [ Component(), Component() ]);184185expect(console.warn.argsForCall.length).toBe(1);186expect(console.warn.argsForCall[0][0]).toContain(187'Each child in an array should have a unique "key" prop'188);189});190191it('does not warn when the element is directly in rest args', function() {192spyOn(console, 'warn');193var Component = React.createFactory(ComponentFactory);194195Component(null, Component(), Component());196197expect(console.warn.argsForCall.length).toBe(0);198});199200it('does not warn when the array contains a non-element', function() {201spyOn(console, 'warn');202var Component = React.createFactory(ComponentFactory);203204Component(null, [ {}, {} ]);205206expect(console.warn.argsForCall.length).toBe(0);207});208209it('allows static methods to be called using the type property', function() {210spyOn(console, 'warn');211212var ComponentClass = React.createClass({213statics: {214someStaticMethod: function() {215return 'someReturnValue';216}217},218getInitialState: function() {219return {valueToReturn: 'hi'};220},221render: function() {222return <div></div>;223}224});225226var element = <ComponentClass />;227expect(element.type.someStaticMethod()).toBe('someReturnValue');228expect(console.warn.argsForCall.length).toBe(0);229});230231it('identifies valid elements', function() {232var Component = React.createClass({233render: function() {234return <div />;235}236});237238expect(ReactElement.isValidElement(<div />)).toEqual(true);239expect(ReactElement.isValidElement(<Component />)).toEqual(true);240241expect(ReactElement.isValidElement(null)).toEqual(false);242expect(ReactElement.isValidElement(true)).toEqual(false);243expect(ReactElement.isValidElement({})).toEqual(false);244expect(ReactElement.isValidElement("string")).toEqual(false);245expect(ReactElement.isValidElement(React.DOM.div)).toEqual(false);246expect(ReactElement.isValidElement(Component)).toEqual(false);247});248249it('warns but allow a plain function in a factory to be invoked', function() {250spyOn(console, 'warn');251// This is a temporary helper to allow JSX with plain functions.252// This allow you to track down these callers and replace them with regular253// function calls.254var factory = React.createFactory(function (x) {255return 21 + x;256});257expect(factory(21)).toBe(42);258expect(console.warn.argsForCall.length).toBe(1);259expect(console.warn.argsForCall[0][0]).toContain(260'This JSX uses a plain function.'261);262});263264it('warns but allow a plain function to be immediately invoked', function() {265spyOn(console, 'warn');266var result = React.createElement(function (x, y) {267return 21 + x + y;268}, 11, 10);269expect(result).toBe(42);270expect(console.warn.argsForCall.length).toBe(1);271expect(console.warn.argsForCall[0][0]).toContain(272'This JSX uses a plain function.'273);274});275276it('warns but does not fail on undefined results', function() {277spyOn(console, 'warn');278var fn = function () { };279var result = React.createElement(fn, 1, 2, null);280expect(result).toBe(undefined);281expect(console.warn.argsForCall.length).toBe(1);282expect(console.warn.argsForCall[0][0]).toContain(283'This JSX uses a plain function.'284);285});286287288it('should expose the underlying class from a legacy factory', function() {289var Legacy = React.createClass({ render: function() { } });290var factory = React.createFactory(Legacy);291expect(factory.type).toBe(Legacy.type);292expect(factory().type).toBe(Legacy.type);293});294295it('allows the use of PropTypes validators in statics', function() {296var Component = React.createClass({297render: () => null,298statics: {299specialType: React.PropTypes.shape({monkey: React.PropTypes.any})300}301});302303expect(typeof Component.specialType).toBe("function");304expect(typeof Component.specialType.isRequired).toBe("function");305});306307it('allows a DOM element to be used with a string', function() {308var element = React.createElement('div', { className: 'foo' });309var instance = ReactTestUtils.renderIntoDocument(element);310expect(instance.getDOMNode().tagName).toBe('DIV');311});312313it('is indistinguishable from a plain object', function() {314var element = React.createElement('div', { className: 'foo' });315var object = {};316expect(element.constructor).toBe(object.constructor);317});318319});320321322