diff --git a/index.js b/index.js index d25e416..ded21df 100644 --- a/index.js +++ b/index.js @@ -1,14 +1,11 @@ 'use strict'; -var React = require('react'), - PropTypes = require('prop-types'), - withSideEffect = require('react-side-effect'); +var React = require('react'); +var PropTypes = require('prop-types'); +var withSideEffect = require('react-side-effect'); function reducePropsToState(propsList) { - var innermostProps = propsList[propsList.length - 1]; - if (innermostProps) { - return innermostProps.title; - } + return DocumentTitle.join(propsList.map(function (e) { return e.title; })); } function handleStateChangeOnClient(title) { @@ -18,15 +15,15 @@ function handleStateChangeOnClient(title) { } } -function DocumentTitle() {} -DocumentTitle.prototype = Object.create(React.Component.prototype); +function DocumentTitleBase() {} +DocumentTitleBase.prototype = Object.create(React.Component.prototype); -DocumentTitle.displayName = 'DocumentTitle'; -DocumentTitle.propTypes = { +DocumentTitleBase.displayName = 'DocumentTitle'; +DocumentTitleBase.propTypes = { title: PropTypes.string.isRequired }; -DocumentTitle.prototype.render = function() { +DocumentTitleBase.prototype.render = function() { if (this.props.children) { return React.Children.only(this.props.children); } else { @@ -34,7 +31,11 @@ DocumentTitle.prototype.render = function() { } }; -module.exports = withSideEffect( +var DocumentTitle = module.exports = withSideEffect( reducePropsToState, handleStateChangeOnClient -)(DocumentTitle); +)(DocumentTitleBase); + +DocumentTitle.join = function (tokens) { + return tokens.pop(); +}; diff --git a/test/browser.js b/test/browser.js index 043f16b..9a68e53 100644 --- a/test/browser.js +++ b/test/browser.js @@ -2,27 +2,29 @@ /*global global, describe, it, afterEach, before, after */ 'use strict'; -var expect = require('expect.js'), - jsdom = require('mocha-jsdom'), - React = require('react'), - ReactDOM = require('react-dom'), - createReactClass = require('create-react-class'), - DocumentTitle = require('../'); +var expect = require('expect.js'); +var jsdom = require('mocha-jsdom'); +var React = require('react'); +var ReactDOM = require('react-dom'); +var createReactClass = require('create-react-class'); +var DocumentTitle = require('../'); jsdom(); describe('DocumentTitle (in a browser)', function () { + var container; - beforeEach(function() { + beforeEach(function () { container = document.createElement('div'); + DocumentTitle.canUseDOM = true; }); afterEach(function () { ReactDOM.unmountComponentAtNode(container); delete global.document.title; + DocumentTitle.canUseDOM = false; + DocumentTitle.rewind(); }); - before(function () { - DocumentTitle.canUseDOM = true; - }); + it('changes the document title on mount', function (done) { var title = 'hello world'; var Component = createReactClass({ diff --git a/test/common.js b/test/common.js index f17c49b..03ffd2f 100644 --- a/test/common.js +++ b/test/common.js @@ -1,17 +1,21 @@ /*jshint newcap: false */ /*global describe, it, before */ 'use strict'; -var expect = require('expect.js'), - React = require('react'), - ReactDOMServer = require('react-dom/server'), - createReactClass = require('create-react-class'), - DocumentTitle = require('../'); +var expect = require('expect.js'); +var React = require('react'); +var ReactDOMServer = require('react-dom/server'); +var createReactClass = require('create-react-class'); +var DocumentTitle = require('../'); describe('DocumentTitle', function () { before(function () { DocumentTitle.canUseDOM = false; }); + after(function () { + DocumentTitle.rewind(); + }); + it('has a displayName', function () { var el = React.createElement(DocumentTitle); expect(el.type.displayName).to.be.a('string'); @@ -81,33 +85,32 @@ describe('DocumentTitle', function () { }); }); -describe('DocumentTitle.rewind', function () { - it('clears the mounted instances', function () { - ReactDOMServer.renderToStaticMarkup( - React.createElement(DocumentTitle, {title: 'a'}, - React.createElement(DocumentTitle, {title: 'b'}, React.createElement(DocumentTitle, {title: 'c'})) - ) - ); - expect(DocumentTitle.peek()).to.equal('c'); - DocumentTitle.rewind(); - expect(DocumentTitle.peek()).to.equal(undefined); +describe('DocumentTitle.join', function () { // tested via DocumentTitle.rewind + var origJoin = DocumentTitle.join; + afterEach(function () { + DocumentTitle.join = origJoin; }); - it('returns the latest document title', function () { + + it('returns the last document title by default', function () { var title = 'cheese'; ReactDOMServer.renderToStaticMarkup( React.createElement(DocumentTitle, {title: 'a'}, React.createElement(DocumentTitle, {title: 'b'}, React.createElement(DocumentTitle, {title: title})) ) ); - expect(DocumentTitle.rewind()).to.equal(title); + expect(DocumentTitle.rewind()).to.equal('cheese'); }); - it('returns undefined if no mounted instances exist', function () { + + it('can be overriden for custom behavior, using all the tokens', function () { + var title = 'cheese'; + DocumentTitle.join = function (tokens) { + return tokens.join(' | '); + }; ReactDOMServer.renderToStaticMarkup( React.createElement(DocumentTitle, {title: 'a'}, - React.createElement(DocumentTitle, {title: 'b'}, React.createElement(DocumentTitle, {title: 'c'})) + React.createElement(DocumentTitle, {title: 'b'}, React.createElement(DocumentTitle, {title: title})) ) ); - DocumentTitle.rewind(); - expect(DocumentTitle.peek()).to.equal(undefined); + expect(DocumentTitle.rewind()).to.equal('a | b | cheese'); }); });