248 lines
6.6 KiB
JavaScript
248 lines
6.6 KiB
JavaScript
/**
|
|
* Copyright 2013-2014, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD-style license found in the
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*
|
|
* @emails react-core
|
|
*/
|
|
|
|
// This test doesn't really have a good home yet. I'm leaving it here since this
|
|
// behavior belongs to the old propTypes system yet is currently implemented
|
|
// in the core ReactCompositeComponent. It should technically live in core's
|
|
// test suite but I'll leave it here to indicate that this is an issue that
|
|
// needs to be fixed.
|
|
|
|
'use strict';
|
|
|
|
var React;
|
|
var ReactTestUtils;
|
|
|
|
var reactComponentExpect;
|
|
var mocks;
|
|
|
|
describe('ReactContextValidator', function() {
|
|
beforeEach(function() {
|
|
require('mock-modules').dumpCache();
|
|
|
|
React = require('React');
|
|
ReactTestUtils = require('ReactTestUtils');
|
|
reactComponentExpect = require('reactComponentExpect');
|
|
mocks = require('mocks');
|
|
|
|
spyOn(console, 'warn');
|
|
});
|
|
|
|
// TODO: This behavior creates a runtime dependency on propTypes. We should
|
|
// ensure that this is not required for ES6 classes with Flow.
|
|
|
|
it('should filter out context not in contextTypes', function() {
|
|
var Component = React.createClass({
|
|
contextTypes: {
|
|
foo: React.PropTypes.string
|
|
},
|
|
|
|
render: function() {
|
|
return <div />;
|
|
}
|
|
});
|
|
|
|
var ComponentInFooBarContext = React.createClass({
|
|
childContextTypes: {
|
|
foo: React.PropTypes.string,
|
|
bar: React.PropTypes.number
|
|
},
|
|
|
|
getChildContext: function() {
|
|
return {
|
|
foo: 'abc',
|
|
bar: 123
|
|
};
|
|
},
|
|
|
|
render: function() {
|
|
return <Component />;
|
|
}
|
|
});
|
|
|
|
var instance = ReactTestUtils.renderIntoDocument(<ComponentInFooBarContext />);
|
|
reactComponentExpect(instance).expectRenderedChild().scalarContextEqual({foo: 'abc'});
|
|
});
|
|
|
|
it('should filter context properly in callbacks', function() {
|
|
var actualComponentWillReceiveProps;
|
|
var actualShouldComponentUpdate;
|
|
var actualComponentWillUpdate;
|
|
var actualComponentDidUpdate;
|
|
|
|
var Parent = React.createClass({
|
|
childContextTypes: {
|
|
foo: React.PropTypes.string.isRequired,
|
|
bar: React.PropTypes.string.isRequired
|
|
},
|
|
|
|
getChildContext: function() {
|
|
return {
|
|
foo: this.props.foo,
|
|
bar: "bar"
|
|
};
|
|
},
|
|
|
|
render: function() {
|
|
return <Component />;
|
|
}
|
|
});
|
|
|
|
var Component = React.createClass({
|
|
contextTypes: {
|
|
foo: React.PropTypes.string
|
|
},
|
|
|
|
componentWillReceiveProps: function(nextProps, nextContext) {
|
|
actualComponentWillReceiveProps = nextContext;
|
|
return true;
|
|
},
|
|
|
|
shouldComponentUpdate: function(nextProps, nextState, nextContext) {
|
|
actualShouldComponentUpdate = nextContext;
|
|
return true;
|
|
},
|
|
|
|
componentWillUpdate: function(nextProps, nextState, nextContext) {
|
|
actualComponentWillUpdate = nextContext;
|
|
},
|
|
|
|
componentDidUpdate: function(prevProps, prevState, prevContext) {
|
|
actualComponentDidUpdate = prevContext;
|
|
},
|
|
|
|
render: function() {
|
|
return <div />;
|
|
}
|
|
});
|
|
|
|
var instance = <Parent foo="abc" />;
|
|
instance = ReactTestUtils.renderIntoDocument(instance);
|
|
instance.replaceProps({foo: "def"});
|
|
expect(actualComponentWillReceiveProps).toEqual({foo: 'def'});
|
|
expect(actualShouldComponentUpdate).toEqual({foo: 'def'});
|
|
expect(actualComponentWillUpdate).toEqual({foo: 'def'});
|
|
expect(actualComponentDidUpdate).toEqual({foo: 'abc'});
|
|
});
|
|
|
|
it('should check context types', function() {
|
|
var Component = React.createClass({
|
|
contextTypes: {
|
|
foo: React.PropTypes.string.isRequired
|
|
},
|
|
|
|
render: function() {
|
|
return <div />;
|
|
}
|
|
});
|
|
|
|
ReactTestUtils.renderIntoDocument(<Component />);
|
|
|
|
expect(console.warn.argsForCall.length).toBe(1);
|
|
expect(console.warn.argsForCall[0][0]).toBe(
|
|
'Warning: Required context `foo` was not specified in `Component`.'
|
|
);
|
|
|
|
var ComponentInFooStringContext = React.createClass({
|
|
childContextTypes: {
|
|
foo: React.PropTypes.string
|
|
},
|
|
|
|
getChildContext: function() {
|
|
return {
|
|
foo: this.props.fooValue
|
|
};
|
|
},
|
|
|
|
render: function() {
|
|
return <Component />;
|
|
}
|
|
});
|
|
|
|
ReactTestUtils.renderIntoDocument(
|
|
<ComponentInFooStringContext fooValue={'bar'} />
|
|
);
|
|
|
|
// Previous call should not error
|
|
expect(console.warn.argsForCall.length).toBe(1);
|
|
|
|
var ComponentInFooNumberContext = React.createClass({
|
|
childContextTypes: {
|
|
foo: React.PropTypes.number
|
|
},
|
|
|
|
getChildContext: function() {
|
|
return {
|
|
foo: this.props.fooValue
|
|
};
|
|
},
|
|
|
|
render: function() {
|
|
return <Component />;
|
|
}
|
|
});
|
|
|
|
ReactTestUtils.renderIntoDocument(<ComponentInFooNumberContext fooValue={123} />);
|
|
|
|
expect(console.warn.argsForCall.length).toBe(2);
|
|
expect(console.warn.argsForCall[1][0]).toBe(
|
|
'Warning: Invalid context `foo` of type `number` supplied ' +
|
|
'to `Component`, expected `string`.' +
|
|
' Check the render method of `ComponentInFooNumberContext`.'
|
|
);
|
|
});
|
|
|
|
it('should check child context types', function() {
|
|
var Component = React.createClass({
|
|
childContextTypes: {
|
|
foo: React.PropTypes.string.isRequired,
|
|
bar: React.PropTypes.number
|
|
},
|
|
|
|
getChildContext: function() {
|
|
return this.props.testContext;
|
|
},
|
|
|
|
render: function() {
|
|
return <div />;
|
|
}
|
|
});
|
|
|
|
ReactTestUtils.renderIntoDocument(<Component testContext={{bar: 123}} />);
|
|
expect(console.warn.argsForCall.length).toBe(2);
|
|
expect(console.warn.argsForCall[0][0]).toBe(
|
|
'Warning: Required child context `foo` was not specified in `Component`.'
|
|
);
|
|
expect(console.warn.argsForCall[1][0]).toBe(
|
|
'Warning: Required child context `foo` was not specified in `Component`.'
|
|
);
|
|
|
|
ReactTestUtils.renderIntoDocument(<Component testContext={{foo: 123}} />);
|
|
|
|
expect(console.warn.argsForCall.length).toBe(4);
|
|
expect(console.warn.argsForCall[3][0]).toBe(
|
|
'Warning: Invalid child context `foo` of type `number` ' +
|
|
'supplied to `Component`, expected `string`.'
|
|
);
|
|
|
|
ReactTestUtils.renderIntoDocument(
|
|
<Component testContext={{foo: 'foo', bar: 123}} />
|
|
);
|
|
|
|
ReactTestUtils.renderIntoDocument(
|
|
<Component testContext={{foo: 'foo'}} />
|
|
);
|
|
|
|
// Previous calls should not log errors
|
|
expect(console.warn.argsForCall.length).toBe(4);
|
|
});
|
|
|
|
});
|