Skip to content

Commit

Permalink
[minor] pass location with query string to routes (#854)
Browse files Browse the repository at this point in the history
  • Loading branch information
jchip committed Jul 9, 2018
1 parent 20a5934 commit 33b2688
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

const Path = require("path");
const assert = require("assert");
const Url = require("url");
const optionalRequire = require("optional-require")(require);
const React = optionalRequire("react");
const ReactDomServer = optionalRequire("react-dom/server");
Expand Down Expand Up @@ -63,40 +64,40 @@ class ReduxRouterEngine {
this._routesComponent = renderRoutes(this._routes);
}

async render(req, options) {
const location = req.path || (req.url && req.url.path);
async render(req, options = {}) {
const location = options.location || req.url || Url.parse(req.path);

try {
const match = this._matchRoute(req, this._routes, location);

if (match.length === 0) {
return {
status: 404,
message: `${pkg.name}: Path ${location} not found`
message: `${pkg.name}: Path ${location.path} not found`
};
}

const methods = match[0].methods || "get";

if (methods.toLowerCase().indexOf(req.method.toLowerCase()) < 0) {
throw new Error(`${pkg.name}: ${location} doesn't allow request method ${req.method}`);
throw new Error(`${pkg.name}: ${location.path} doesn't allow request method ${req.method}`);
}

return await this._handleRender(req, location, match, options || {});
return await this._handleRender(req, location, match, options);
} catch (err) {
this.options.logError.call(this, req, err);
return {
status: err.status || 500, // eslint-disable-line
message: err.message,
path: err.path || location,
path: err.path || location.path,
_err: err
};
}
}

//
_matchRoute(req, routes, location) {
return matchRoutes(routes, location);
return matchRoutes(routes, location.pathname);
}

async _handleRender(req, location, match, options) {
Expand Down
1 change: 1 addition & 0 deletions packages/electrode-redux-router-engine/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"babel-preset-stage-0": "^6.0.15",
"babel-register": "^6.5.2",
"electrode-archetype-njs-module-dev": "^2.1.0",
"electrode-server": "^1.5.1",
"react": "^16.0.0 || ^15.3.1 || ^0.14.8",
"react-dom": "^16.0.0 || ^15.3.1 || ^0.14.8",
"test-init-nm": "./test/nm/test-init-nm",
Expand Down
4 changes: 3 additions & 1 deletion packages/electrode-redux-router-engine/test/routes.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import { renderFlatRoutes } from "./render-flat-routes";

class Home extends React.Component {
render() {
return <div>Home</div>;
const { search } = this.props.location;
const query = search ? ` - Query: ${search}` : "";
return <div>Home{query}</div>;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"use strict";

const ReduxRouterEngine = require("../..");
const expect = require("chai").expect;
const electrodeServer = require("electrode-server");

require("babel-register");

const routes = require("../routes.jsx").default;

describe("electrode server (Hapi) integration", function() {
let server;
let engine;

before(async () => {
server = await electrodeServer({
electrode: { logLevel: "none" },
connections: { default: { port: 0 } }
});
server.route({
method: "get",
path: "/test",
handler: async (request, reply) => {
if (!engine) engine = new ReduxRouterEngine({ routes });
const result = await engine.render(request);
reply(result);
}
});
});

after(done => {
server.stop(done);
});

it("should render basic test route", () => {
return server.inject("/test").then(resp => {
expect(resp.result).to.deep.equal({
status: 200,
html: "<div>Page<div>Home</div></div>",
prefetch: "window.__PRELOADED_STATE__ = {};"
});
});
});

it("should render with URL query", () => {
return server.inject("/test?foo=bar").then(resp => {
expect(resp.result).to.deep.equal({
status: 200,
html: "<div>Page<div>Home - Query: ?foo=bar</div></div>",
prefetch: "window.__PRELOADED_STATE__ = {};"
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const Path = require("path");
const ReduxRouterEngine = require("../..");
const xstdout = require("xstdout");
const Url = require("url");

const expect = require("chai").expect;

Expand All @@ -17,14 +18,13 @@ describe("redux-router-engine", function() {
testReq = {
method: "get",
log: () => {},
app: {},
url: {}
app: {}
};
});

it("should return 404 for unknown index route", () => {
const engine = new ReduxRouterEngine({ routes });
testReq.url.path = "/oop/blah";
testReq.url = Url.parse("/oop/blah");

return engine.render(testReq).then(result => {
expect(result.status).to.equal(404);
Expand All @@ -34,7 +34,7 @@ describe("redux-router-engine", function() {
it("should return string error", () => {
const intercept = xstdout.intercept(true);
const engine = new ReduxRouterEngine({ routes });
testReq.url.path = "/test/init-not-found";
testReq.url = Url.parse("/test/init-not-found");

return engine.render(testReq).then(result => {
intercept.restore();
Expand All @@ -46,7 +46,7 @@ describe("redux-router-engine", function() {
it("should return Error error", () => {
const intercept = xstdout.intercept(true);
const engine = new ReduxRouterEngine({ routes, routesHandlerPath: Path.join(__dirname, "..") });
testReq.url.path = "/throw-error";
testReq.url = Url.parse("/throw-error");

return engine.render(testReq).then(result => {
intercept.restore();
Expand All @@ -61,7 +61,7 @@ describe("redux-router-engine", function() {
routes,
renderToString: () => Promise.resolve(testHtml)
});
testReq.url.path = "/test";
testReq.url = Url.parse("/test");

return engine.render(testReq).then(result => {
expect(result.html).to.equal(testHtml);
Expand All @@ -70,7 +70,7 @@ describe("redux-router-engine", function() {

it("should resolve index route", () => {
const engine = new ReduxRouterEngine({ routes, routesHandlerPath: "test" });
testReq.url.path = "/test";
testReq.url = Url.parse("/test");

return engine.render(testReq).then(result => {
expect(result.status).to.equal(200);
Expand All @@ -79,9 +79,31 @@ describe("redux-router-engine", function() {
});
});

it("should parse req.path if req.url is missing", () => {
const engine = new ReduxRouterEngine({ routes, routesHandlerPath: "test" });
testReq.path = "/test?foo=bar";

return engine.render(testReq).then(result => {
expect(result.status).to.equal(200);
expect(result.html).to.equal("<div>Page<div>Home - Query: ?foo=bar</div></div>");
expect(result.prefetch).to.equal("window.__PRELOADED_STATE__ = {};");
});
});

it("should use options.location", () => {
const engine = new ReduxRouterEngine({ routes, routesHandlerPath: "test" });
testReq.url = Url.parse("/test?foo=bar");

return engine.render(testReq, { location: Url.parse("/test?a=1") }).then(result => {
expect(result.status).to.equal(200);
expect(result.html).to.equal("<div>Page<div>Home - Query: ?a=1</div></div>");
expect(result.prefetch).to.equal("window.__PRELOADED_STATE__ = {};");
});
});

it("should load init without leading . from node_modules", () => {
const engine = new ReduxRouterEngine({ routes, routesHandlerPath: "test" });
testReq.url.path = "/test-init-nm";
testReq.url = Url.parse("/test-init-nm");

return engine.render(testReq).then(result => {
expect(result.status).to.equal(200);
Expand All @@ -95,7 +117,7 @@ describe("redux-router-engine", function() {
routes: Path.resolve(__dirname, "../routes"),
routesHandlerPath: "./test"
});
testReq.url.path = "/top-reducer/init";
testReq.url = Url.parse("/top-reducer/init");

return engine.render(testReq).then(result => {
expect(result.status).to.equal(200);
Expand All @@ -108,7 +130,7 @@ describe("redux-router-engine", function() {

it("should take routes as name of module", () => {
const engine = new ReduxRouterEngine({ routes: "./test/routes" });
testReq.url.path = "/test";
testReq.url = Url.parse("/test");

return engine.render(testReq).then(result => {
expect(result.status).to.equal(200);
Expand All @@ -119,7 +141,7 @@ describe("redux-router-engine", function() {

it("should resolve skip SSR if disabled", () => {
const engine = new ReduxRouterEngine({ routes });
testReq.url.path = "/test";
testReq.url = Url.parse("/test");
testReq.app.disableSSR = true;

return engine.render(testReq).then(result => {
Expand All @@ -129,7 +151,7 @@ describe("redux-router-engine", function() {

it("escapes troublesome characters in the state", () => {
const engine = new ReduxRouterEngine({ routes, routesHandlerPath: Path.join(__dirname, "..") });
testReq.url.path = "/escape-chars";
testReq.url = Url.parse("/escape-chars");

return engine.render(testReq).then(result => {
expect(result.prefetch).to.contain(
Expand All @@ -142,7 +164,7 @@ describe("redux-router-engine", function() {

it("should return 302 for router Redirect component", () => {
const engine = new ReduxRouterEngine({ routes, componentRedirect: true });
testReq.url.path = "/test/component-redirect";
testReq.url = Url.parse("/test/component-redirect");

return engine.render(testReq).then(result => {
expect(result.status).to.equal(302);
Expand All @@ -154,7 +176,7 @@ describe("redux-router-engine", function() {
it("should return 500 for invalid component", () => {
const intercept = xstdout.intercept(true);
const engine = new ReduxRouterEngine({ routes });
testReq.url.path = "/invalid-component";
testReq.url = Url.parse("/invalid-component");

return engine.render(testReq).then(result => {
intercept.restore();
Expand All @@ -166,7 +188,7 @@ describe("redux-router-engine", function() {
it("should return 404 if component throws 404", () => {
const intercept = xstdout.intercept(true);
const engine = new ReduxRouterEngine({ routes });
testReq.url.path = "/error-component";
testReq.url = Url.parse("/error-component");

return engine.render(testReq).then(result => {
intercept.restore();
Expand All @@ -177,7 +199,7 @@ describe("redux-router-engine", function() {

it("should populate react-id when requested", () => {
const engine = new ReduxRouterEngine({ routes, withIds: true });
testReq.url.path = "/test";
testReq.url = Url.parse("/test");

return engine.render(testReq).then(result => {
expect(result.html).to.contain("data-reactroot");
Expand All @@ -186,7 +208,7 @@ describe("redux-router-engine", function() {

it("should not populate react-id by default", () => {
const engine = new ReduxRouterEngine({ routes });
testReq.url.path = "/test";
testReq.url = Url.parse("/test");

return engine.render(testReq).then(result => {
expect(result.html).to.not.contain("data-reactroot");
Expand All @@ -199,7 +221,7 @@ describe("redux-router-engine", function() {
stringifyPreloadedState: () => `window.__TEST_STATE__`,
renderToString: () => "test"
});
testReq.url.path = "/test";
testReq.url = Url.parse("/test");

return engine.render(testReq).then(result => {
expect(result.prefetch).to.equal(`window.__TEST_STATE__`);
Expand All @@ -208,7 +230,7 @@ describe("redux-router-engine", function() {

it("should use optional logError", () => {
let error;
testReq.url.path = "/test/init-not-found";
testReq.url = Url.parse("/test/init-not-found");

return new ReduxRouterEngine({
routes,
Expand All @@ -225,7 +247,7 @@ describe("redux-router-engine", function() {

it("render options should override constructor options", () => {
const engine = new ReduxRouterEngine({ routes, withIds: true });
testReq.url.path = "/test";
testReq.url = Url.parse("/test");

return engine.render(testReq, { withIds: false }).then(result => {
expect(result.html).to.not.contain("data-reactroot");
Expand All @@ -239,7 +261,7 @@ describe("redux-router-engine", function() {
method: "post",
log: () => {},
app: {},
url: {}
url: Url.parse("/post-only")
};

const engine = new ReduxRouterEngine({ routes });
Expand All @@ -257,7 +279,7 @@ describe("redux-router-engine", function() {
method: "get",
log: () => {},
app: {},
url: {}
url: Url.parse("/test/init")
};

const engine = new ReduxRouterEngine({
Expand All @@ -277,7 +299,7 @@ describe("redux-router-engine", function() {
method: "get",
log: () => {},
app: {},
url: {}
url: Url.parse("/top-wait/init")
};

const engine = new ReduxRouterEngine({
Expand Down Expand Up @@ -309,7 +331,7 @@ describe("redux-router-engine", function() {
method: "get",
log: () => {},
app: {},
url: {}
url: Url.parse("/test-init2")
};

const engine = new ReduxRouterEngine({
Expand All @@ -329,7 +351,7 @@ describe("redux-router-engine", function() {
method: "get",
log: () => {},
app: {},
url: {}
url: Url.parse("/test/redux")
};

const engine = new ReduxRouterEngine({
Expand Down

0 comments on commit 33b2688

Please sign in to comment.