diff --git a/src/components/routing/nested-routes.test.tsx b/src/components/routing/nested-routes.test.tsx
new file mode 100644
index 0000000..e9a5924
--- /dev/null
+++ b/src/components/routing/nested-routes.test.tsx
@@ -0,0 +1,113 @@
+import React from "react";
+import { NestedRoutes } from "./nested-routes";
+import { createMemoryHistory } from "history";
+import { render } from "@testing-library/react";
+import { Router } from "react-router-dom";
+import { RouteDefinition } from "../../interfaces/route-definition";
+import { Factory } from "rosie";
+import { FactoryType } from "../../tests/factories/factory-type";
+import faker from "faker";
+
+describe("NestedRoutes", () => {
+ let nonExistentRoute: string;
+ const HomePage = () =>
Home
;
+ const NotFoundPage = () => 404
;
+
+ const homeRoute: RouteDefinition = Factory.build(
+ FactoryType.RouteDefinition.Default,
+ { path: "/", component: HomePage }
+ );
+
+ const nestedRoutes: RouteDefinition[] = Factory.buildList(
+ FactoryType.RouteDefinition.Nested,
+ 3
+ );
+
+ const notFoundRoute = Factory.build(
+ FactoryType.RouteDefinition.Default,
+ { path: "/404", component: NotFoundPage }
+ );
+
+ let routes: RouteDefinition[] = [];
+
+ beforeEach(() => {
+ nonExistentRoute = [
+ "", // Preprends a / before the route
+ faker.random.alphaNumeric(5),
+ faker.random.alphaNumeric(5),
+ faker.random.alphaNumeric(5),
+ ].join("/");
+
+ routes = [...nestedRoutes, homeRoute, notFoundRoute];
+ });
+
+ // -----------------------------------------------------------------------------------------
+ // #region redirectToIfNotFound
+ // -----------------------------------------------------------------------------------------
+
+ describe("when pathname does not match any route path", () => {
+ describe("given redirectToIfNotFound has a value", () => {
+ test("it redirects to the redirectToIfNotFound route", () => {
+ // Arrange
+ const history = createMemoryHistory();
+ // This should have no effect on whether or not the user is redirected for a non-existent route
+ const isAuthenticated = faker.random.boolean();
+ const redirectToIfNotFound = notFoundRoute.path; // This is the important setup
+
+ const App = () => (
+
+
+
+ );
+
+ // Act
+ history.push(nonExistentRoute);
+ const { getByRole } = render();
+
+ // Assert
+ expect(getByRole("heading")).toHaveTextContent("404");
+ expect(history.location.pathname).toBe(redirectToIfNotFound);
+ });
+ });
+
+ describe("given redirectToIfNotFound is null or empty", () => {
+ test("it does not redirect", () => {
+ // Arrange
+ const history = createMemoryHistory();
+ // This should have no effect on whether or not the user is redirected for a non-existent route
+ const isAuthenticated = faker.random.boolean();
+ // This is the important setup
+ const redirectToIfNotFound:
+ | string
+ | undefined = faker.random.arrayElement([
+ undefined,
+ null,
+ "",
+ ]);
+
+ const App = () => (
+
+
+
+ );
+
+ // Act
+ history.push(nonExistentRoute);
+ render();
+
+ // Assert
+ expect(history.location.pathname).toBe(nonExistentRoute);
+ });
+ });
+ });
+
+ // #endregion redirectToIfNotFound
+});
diff --git a/src/components/routing/nested-routes.tsx b/src/components/routing/nested-routes.tsx
index 6da32d5..e89157f 100644
--- a/src/components/routing/nested-routes.tsx
+++ b/src/components/routing/nested-routes.tsx
@@ -1,6 +1,6 @@
-import { CollectionUtils } from "andculturecode-javascript-core";
+import { CollectionUtils, StringUtils } from "andculturecode-javascript-core";
import { NestedRoute } from "./nested-route";
-import { Redirect } from "react-router-dom";
+import { Redirect, Switch } from "react-router-dom";
import React from "react";
import { RouteDefinition } from "../../interfaces/route-definition";
import { UnmatchedRoute } from "../../interfaces/unmatched-route";
@@ -27,12 +27,7 @@ interface NestedRoutesProps extends UnmatchedRoute, AuthenticatedRoute {
const NestedRoutes: React.FC = (
props: NestedRoutesProps
) => {
- const {
- isAuthenticated,
- redirectToIfNotFound,
- redirectToIfUnauthenticated,
- routes,
- } = props;
+ const { redirectToIfNotFound, routes } = props;
if (CollectionUtils.isEmpty(routes)) {
return null;
@@ -41,17 +36,14 @@ const NestedRoutes: React.FC = (
// TODO: Remove Fragment when issue fixed https://github.com/microsoft/TypeScript/issues/21699
return (
- {props.routes.map((route: RouteDefinition, i: number) => (
-
- ))}
- {redirectToIfNotFound != null && (
-
- )}
+
+ {routes.map((route: RouteDefinition, i: number) => (
+
+ ))}
+ {StringUtils.hasValue(redirectToIfNotFound) && (
+
+ )}
+
);
};
diff --git a/src/tests/factories/route-definition-factory.ts b/src/tests/factories/route-definition-factory.ts
index 0fd7608..9391117 100644
--- a/src/tests/factories/route-definition-factory.ts
+++ b/src/tests/factories/route-definition-factory.ts
@@ -13,7 +13,7 @@ const RouteDefinitionFactory = Factory.define(
.sequence("authRequired", () => false)
.sequence("component", () => React.Fragment)
.sequence("exact", () => true)
- .sequence("path", (i: number) => `path${i}/`)
+ .sequence("path", (i: number) => `/path${i}`)
.sequence("routes", () => {});
const RouteDefinitionNestedFactory = Factory.define(
@@ -22,7 +22,7 @@ const RouteDefinitionNestedFactory = Factory.define(
.sequence("authRequired", () => false)
.sequence("component", () => React.Fragment)
.sequence("exact", () => true)
- .sequence("path", (i: number) => `path${i}/`)
+ .sequence("path", (i: number) => `/path${i}`)
.sequence("routes", () => {
return {
nestedRoute: Factory.build(