269 lines
7.4 KiB
JavaScript
269 lines
7.4 KiB
JavaScript
/**
|
|
* Copyright 2013-2015, 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
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
var React;
|
|
var ReactDOM;
|
|
var ReactDOMServer;
|
|
var ReactInstanceMap;
|
|
var ReactMount;
|
|
|
|
var getTestDocument;
|
|
|
|
var testDocument;
|
|
|
|
var UNMOUNT_INVARIANT_MESSAGE =
|
|
'Invariant Violation: <html> tried to unmount. ' +
|
|
'Because of cross-browser quirks it is impossible to unmount some ' +
|
|
'top-level components (eg <html>, <head>, and <body>) reliably and ' +
|
|
'efficiently. To fix this, have a single top-level component that ' +
|
|
'never unmounts render these elements.';
|
|
|
|
describe('rendering React components at document', function() {
|
|
beforeEach(function() {
|
|
require('mock-modules').dumpCache();
|
|
|
|
React = require('React');
|
|
ReactDOM = require('ReactDOM');
|
|
ReactDOMServer = require('ReactDOMServer');
|
|
ReactInstanceMap = require('ReactInstanceMap');
|
|
ReactMount = require('ReactMount');
|
|
getTestDocument = require('getTestDocument');
|
|
|
|
testDocument = getTestDocument();
|
|
});
|
|
|
|
it('should be able to get root component id for document node', function() {
|
|
expect(testDocument).not.toBeUndefined();
|
|
|
|
var Root = React.createClass({
|
|
render: function() {
|
|
return (
|
|
<html>
|
|
<head>
|
|
<title>Hello World</title>
|
|
</head>
|
|
<body>
|
|
Hello world
|
|
</body>
|
|
</html>
|
|
);
|
|
},
|
|
});
|
|
|
|
var markup = ReactDOMServer.renderToString(<Root />);
|
|
testDocument = getTestDocument(markup);
|
|
var component = ReactDOM.render(<Root />, testDocument);
|
|
expect(testDocument.body.innerHTML).toBe('Hello world');
|
|
|
|
// TODO: This is a bad test. I have no idea what this is testing.
|
|
// Node IDs is an implementation detail and not part of the public API.
|
|
var componentID = ReactMount.getReactRootID(testDocument);
|
|
expect(componentID).toBe(ReactInstanceMap.get(component)._rootNodeID);
|
|
});
|
|
|
|
it('should not be able to unmount component from document node', function() {
|
|
expect(testDocument).not.toBeUndefined();
|
|
|
|
var Root = React.createClass({
|
|
render: function() {
|
|
return (
|
|
<html>
|
|
<head>
|
|
<title>Hello World</title>
|
|
</head>
|
|
<body>
|
|
Hello world
|
|
</body>
|
|
</html>
|
|
);
|
|
},
|
|
});
|
|
|
|
var markup = ReactDOMServer.renderToString(<Root />);
|
|
testDocument = getTestDocument(markup);
|
|
ReactDOM.render(<Root />, testDocument);
|
|
expect(testDocument.body.innerHTML).toBe('Hello world');
|
|
|
|
expect(function() {
|
|
ReactDOM.unmountComponentAtNode(testDocument);
|
|
}).toThrow(UNMOUNT_INVARIANT_MESSAGE);
|
|
|
|
expect(testDocument.body.innerHTML).toBe('Hello world');
|
|
});
|
|
|
|
it('should not be able to switch root constructors', function() {
|
|
expect(testDocument).not.toBeUndefined();
|
|
|
|
var Component = React.createClass({
|
|
render: function() {
|
|
return (
|
|
<html>
|
|
<head>
|
|
<title>Hello World</title>
|
|
</head>
|
|
<body>
|
|
Hello world
|
|
</body>
|
|
</html>
|
|
);
|
|
},
|
|
});
|
|
|
|
var Component2 = React.createClass({
|
|
render: function() {
|
|
return (
|
|
<html>
|
|
<head>
|
|
<title>Hello World</title>
|
|
</head>
|
|
<body>
|
|
Goodbye world
|
|
</body>
|
|
</html>
|
|
);
|
|
},
|
|
});
|
|
|
|
var markup = ReactDOMServer.renderToString(<Component />);
|
|
testDocument = getTestDocument(markup);
|
|
|
|
ReactDOM.render(<Component />, testDocument);
|
|
|
|
expect(testDocument.body.innerHTML).toBe('Hello world');
|
|
|
|
// Reactive update
|
|
expect(function() {
|
|
ReactDOM.render(<Component2 />, testDocument);
|
|
}).toThrow(UNMOUNT_INVARIANT_MESSAGE);
|
|
|
|
expect(testDocument.body.innerHTML).toBe('Hello world');
|
|
});
|
|
|
|
it('should be able to mount into document', function() {
|
|
expect(testDocument).not.toBeUndefined();
|
|
|
|
var Component = React.createClass({
|
|
render: function() {
|
|
return (
|
|
<html>
|
|
<head>
|
|
<title>Hello World</title>
|
|
</head>
|
|
<body>
|
|
{this.props.text}
|
|
</body>
|
|
</html>
|
|
);
|
|
},
|
|
});
|
|
|
|
var markup = ReactDOMServer.renderToString(
|
|
<Component text="Hello world" />
|
|
);
|
|
testDocument = getTestDocument(markup);
|
|
|
|
ReactDOM.render(<Component text="Hello world" />, testDocument);
|
|
|
|
expect(testDocument.body.innerHTML).toBe('Hello world');
|
|
});
|
|
|
|
it('should give helpful errors on state desync', function() {
|
|
expect(testDocument).not.toBeUndefined();
|
|
|
|
var Component = React.createClass({
|
|
render: function() {
|
|
return (
|
|
<html>
|
|
<head>
|
|
<title>Hello World</title>
|
|
</head>
|
|
<body>
|
|
{this.props.text}
|
|
</body>
|
|
</html>
|
|
);
|
|
},
|
|
});
|
|
|
|
var markup = ReactDOMServer.renderToString(
|
|
<Component text="Goodbye world" />
|
|
);
|
|
testDocument = getTestDocument(markup);
|
|
|
|
expect(function() {
|
|
// Notice the text is different!
|
|
ReactDOM.render(<Component text="Hello world" />, testDocument);
|
|
}).toThrow(
|
|
'Invariant Violation: ' +
|
|
'You\'re trying to render a component to the document using ' +
|
|
'server rendering but the checksum was invalid. This usually ' +
|
|
'means you rendered a different component type or props on ' +
|
|
'the client from the one on the server, or your render() methods ' +
|
|
'are impure. React cannot handle this case due to cross-browser ' +
|
|
'quirks by rendering at the document root. You should look for ' +
|
|
'environment dependent code in your components and ensure ' +
|
|
'the props are the same client and server side:\n' +
|
|
' (client) data-reactid=".0.1">Hello world</body></\n' +
|
|
' (server) data-reactid=".0.1">Goodbye world</body>'
|
|
);
|
|
});
|
|
|
|
it('should throw on full document render w/ no markup', function() {
|
|
expect(testDocument).not.toBeUndefined();
|
|
|
|
var container = testDocument;
|
|
|
|
var Component = React.createClass({
|
|
render: function() {
|
|
return (
|
|
<html>
|
|
<head>
|
|
<title>Hello World</title>
|
|
</head>
|
|
<body>
|
|
{this.props.text}
|
|
</body>
|
|
</html>
|
|
);
|
|
},
|
|
});
|
|
|
|
expect(function() {
|
|
ReactDOM.render(<Component />, container);
|
|
}).toThrow(
|
|
'Invariant Violation: You\'re trying to render a component to the ' +
|
|
'document but you didn\'t use server rendering. We can\'t do this ' +
|
|
'without using server rendering due to cross-browser quirks. See ' +
|
|
'ReactDOMServer.renderToString() for server rendering.'
|
|
);
|
|
});
|
|
|
|
it('supports findDOMNode on full-page components', function() {
|
|
var tree =
|
|
<html>
|
|
<head>
|
|
<title>Hello World</title>
|
|
</head>
|
|
<body>
|
|
Hello world
|
|
</body>
|
|
</html>;
|
|
|
|
var markup = ReactDOMServer.renderToString(tree);
|
|
testDocument = getTestDocument(markup);
|
|
var component = ReactDOM.render(tree, testDocument);
|
|
expect(testDocument.body.innerHTML).toBe('Hello world');
|
|
expect(ReactDOM.findDOMNode(component).tagName).toBe('HTML');
|
|
});
|
|
});
|