diff --git a/__tests__/universal/routes.spec.jsx b/__tests__/universal/routes.spec.jsx index 9bed012f8..8c514b97d 100644 --- a/__tests__/universal/routes.spec.jsx +++ b/__tests__/universal/routes.spec.jsx @@ -18,6 +18,7 @@ import ReactTestUtils from 'react-dom/test-utils'; import { fromJS } from 'immutable'; import createRoutes from '../../src/universal/routes'; +import hasChildRoutes from '../../src/universal/utils/hasChildRoutes'; jest.mock('holocron-module-route', () => () => null); jest.mock('@americanexpress/one-app-ducks/lib/errorReporting', () => ({ @@ -27,6 +28,7 @@ jest.mock('@americanexpress/one-app-ducks/lib/errorReporting', () => ({ meta, })), })); +jest.mock('../../src/universal/utils/hasChildRoutes'); describe('routes', () => { const store = { @@ -44,15 +46,23 @@ describe('routes', () => { beforeEach(() => jest.clearAllMocks()); - it('should set up the root module route first', () => { + it('should return array of length 2', () => { + const RootRoute = createRoutes(store); + expect(RootRoute.length).toBe(2); + }); + + it('should return RootRoute props with path if RootModule has no childroutes', () => { + hasChildRoutes.mockReturnValueOnce(false); const RootRoute = createRoutes(store)[0]; expect(ReactTestUtils.isElement(RootRoute)).toBe(true); - expect(RootRoute.props).toEqual({ moduleName: 'fakeRootModule', store }); + expect(RootRoute.props).toEqual({ moduleName: 'fakeRootModule', path: '/', store }); }); - it('should not define a path on the root module', () => { + it('should return RootRoute props without path if RootModule has childroutes', () => { + hasChildRoutes.mockReturnValueOnce(true); const RootRoute = createRoutes(store)[0]; - expect(RootRoute.props.path).toBe(undefined); + expect(ReactTestUtils.isElement(RootRoute)).toBe(true); + expect(RootRoute.props).toEqual({ moduleName: 'fakeRootModule', store }); }); it('should set up a default 404', () => { diff --git a/__tests__/universal/utils/hasChildRoutes.spec.js b/__tests__/universal/utils/hasChildRoutes.spec.js new file mode 100644 index 000000000..5a28e8919 --- /dev/null +++ b/__tests__/universal/utils/hasChildRoutes.spec.js @@ -0,0 +1,27 @@ +/* + * Copyright 2022 American Express Travel Related Services Company, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import hasChildRoutes from '../../../src/universal/utils/hasChildRoutes'; + +it('hasChildRoutes returns false', () => { + [undefined, null, '', [], {}].forEach((value) => { + expect(hasChildRoutes(value)).toBeFalsy(); + }); +}); + +it('hasChildRoutes returns true', () => { + expect(hasChildRoutes({ childRoutes: [] })).toBe(true); +}); diff --git a/docs/api/modules/Routing.md b/docs/api/modules/Routing.md index 47dbb40ba..e9dca738b 100644 --- a/docs/api/modules/Routing.md +++ b/docs/api/modules/Routing.md @@ -39,7 +39,7 @@ Enables components and modules to define their own child routes. `childRoutes` c route, array of routes or a function which accepts the Redux store as the sole argument and returns a single route or array of routes. -One App requires the Root Module to have at least one child route defined. This can be either `` or `` with a `path`. +`childRoutes` is optional for Root Module. `childRoutes` can be either `` or `` with a `path`. If `childRoutes` is not defined, the default path `/` is added to the root route. ```js const MyModule = () => { /* jsx */ }; diff --git a/src/universal/routes.jsx b/src/universal/routes.jsx index 990251ec7..f06e2b74a 100644 --- a/src/universal/routes.jsx +++ b/src/universal/routes.jsx @@ -22,11 +22,15 @@ import React from 'react'; import ModuleRoute from 'holocron-module-route'; import { Route } from '@americanexpress/one-app-router'; import { applicationError, clearError } from '@americanexpress/one-app-ducks'; +import { getModule } from 'holocron'; +import hasChildRoutes from './utils/hasChildRoutes'; const createRoutes = (store) => { const rootModuleName = store.getState().getIn(['config', 'rootModuleName']); + const rootHasChildRoutes = hasChildRoutes(getModule(rootModuleName)); + return [ - , + , 'Not found'} diff --git a/src/universal/utils/hasChildRoutes.js b/src/universal/utils/hasChildRoutes.js new file mode 100644 index 000000000..cd3b5547d --- /dev/null +++ b/src/universal/utils/hasChildRoutes.js @@ -0,0 +1,19 @@ +/* + * Copyright 2022 American Express Travel Related Services Company, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +const hasChildRoutes = (module) => module && !!module.childRoutes; + +export default hasChildRoutes;