Skip to content

Commit

Permalink
feat(custom-render): called a custom renderer when provided
Browse files Browse the repository at this point in the history
  • Loading branch information
travi committed Dec 17, 2018
1 parent 345b4c8 commit 86298c3
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 22 deletions.
16 changes: 5 additions & 11 deletions src/router-wrapper.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import React from 'react';
import {renderToString} from 'react-dom/server';
import {RouterContext} from 'react-router';
import Boom from 'boom';
import {MOVED_PERMANENTLY, MOVED_TEMPORARILY} from 'http-status-codes';
import matchRoute from './route-matcher';
import fetchData from './data-fetcher';
import defaultRenderFactory from './default-render-factory';

export default async function renderThroughReactRouter(request, h, {routes, respond, Root, store}) {
export default async function renderThroughReactRouter(request, h, {render, routes, respond, Root, store}) {
try {
const {renderProps, status, redirectLocation} = await matchRoute(request.raw.req.url, routes);

Expand All @@ -24,16 +22,12 @@ export default async function renderThroughReactRouter(request, h, {routes, resp
} else {
await fetchData({renderProps, store});

const defaultRender = defaultRenderFactory(request, store, renderProps, Root);

return respond(h, {
store,
status,
renderedContent: {
html: renderToString((
<Root request={request} store={store}>
<RouterContext {...renderProps} />
</Root>
))
}
renderedContent: render ? render(defaultRender) : {html: defaultRender()}
});
}
} catch (e) {
Expand Down
35 changes: 24 additions & 11 deletions test/unit/router-wrapper-test.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import React from 'react';
import {RouterContext} from 'react-router';
import domServer from 'react-dom/server';
import {MOVED_TEMPORARILY, MOVED_PERMANENTLY} from 'http-status-codes';
import {MOVED_PERMANENTLY, MOVED_TEMPORARILY} from 'http-status-codes';
import sinon from 'sinon';
import {assert} from 'chai';
import any from '@travi/any';
import Boom from 'boom';
import renderThroughReactRouter from '../../src/router-wrapper';
import * as defaultRenderFactory from '../../src/default-render-factory';
import * as routeMatcher from '../../src/route-matcher';
import * as dataFetcher from '../../src/data-fetcher';

Expand All @@ -25,8 +23,7 @@ suite('router-wrapper', () => {
sandbox.stub(routeMatcher, 'default');
sandbox.stub(dataFetcher, 'default');
sandbox.stub(Boom, 'wrap');
sandbox.stub(React, 'createElement');
sandbox.stub(domServer, 'renderToString');
sandbox.stub(defaultRenderFactory, 'default');
});

teardown(() => sandbox.restore());
Expand All @@ -36,20 +33,36 @@ suite('router-wrapper', () => {
const reply = sinon.spy();
const renderProps = any.simpleObject();
const status = any.integer();
const context = any.simpleObject();
const rootComponent = any.simpleObject();
const html = any.string();
const response = any.string();
const defaultRender = sinon.stub();
routeMatcher.default.withArgs(url, routes).resolves({renderProps, status});
dataFetcher.default.withArgs({renderProps, store, status}).resolves({renderProps, status});
React.createElement.withArgs(RouterContext, sinon.match(renderProps)).returns(context);
React.createElement.withArgs(Root, {request, store}).returns(rootComponent);
domServer.renderToString.withArgs(rootComponent).returns(html);
defaultRender.returns(html);
defaultRenderFactory.default.withArgs(request, store, renderProps, Root).returns(defaultRender);
respond.withArgs(reply, {renderedContent: {html}, store, status}).returns(response);

return assert.becomes(renderThroughReactRouter(request, reply, {routes, respond, Root, store}), response);
});

test('that response contains the custom-rendered content when a custom renderer is provided', async () => {
const respond = sinon.stub();
const reply = sinon.spy();
const renderProps = any.simpleObject();
const status = any.integer();
const response = any.string();
const render = sinon.stub();
const renderedContent = any.simpleObject();
const defaultRender = () => undefined;
routeMatcher.default.withArgs(url, routes).resolves({renderProps, status});
dataFetcher.default.withArgs({renderProps, store, status}).resolves({renderProps, status});
respond.withArgs(reply, {renderedContent, store, status}).returns(response);
defaultRenderFactory.default.withArgs(request, store, renderProps, Root).returns(defaultRender);
render.withArgs(defaultRender).returns(renderedContent);

assert.equal(await renderThroughReactRouter(request, reply, {render, routes, respond, Root, store}), response);
});

test('that a temporary redirect results when a redirectLocation is defined with a 302 status', () => {
const respond = sinon.stub();
const redirect = sinon.stub();
Expand Down

0 comments on commit 86298c3

Please sign in to comment.