UNPKG

@before.js/server

Version:

Enables data fetching with any React SSR app that uses React Router 5

189 lines (176 loc) 5.14 kB
'use strict'; /* eslint react/prop-types: 0 */ const React = require('react'); const DummyComponent = () => <span>Hi there!</span>; function dummyAsyncComponent({ LoadableComponent, loader }) { let Component = null; const AsyncRouteComponent = props => { return <LoadableComponent {...props} />; }; AsyncRouteComponent.load = async () => { const loaderFn = loader.requireAsync || loader; return loaderFn().then(component => { Component = component.default || component; return Component; }); }; AsyncRouteComponent.getInitialProps = async context => { const component = Component || (await AsyncRouteComponent.load()); return component.getInitialProps ? component.getInitialProps(context) : Promise.resolve(null); }; return AsyncRouteComponent; } beforeEach(() => { global.window = undefined; global.document = undefined; process.browser = undefined; }); afterEach(() => { delete global.window; delete global.document; delete process.browser; }); test('should use the default document', async () => { const mockLoader = jest.fn().mockResolvedValue(DummyComponent); const mockRoutes = [ { path: '/', exact: true, component: dummyAsyncComponent({ loader: mockLoader, LoadableComponent: DummyComponent }) } ]; const options = { req: { path: '/', originalUrl: 'https://test.com', query: {} }, res: { redirect: jest.fn(), status: jest.fn() }, routes: mockRoutes, assets: { client: {} } }; const { render } = require('./render'); const html = await render(options); expect(html).toBeDefined(); expect(html).toContain('<!doctype html>'); expect(html).not.toContain('BEFORE.JS-DATA'); }); test('should return a 404', async () => { const mockLoader = jest.fn().mockResolvedValue(DummyComponent); const mockRoutes = [ { path: '**', exact: true, component: dummyAsyncComponent({ loader: mockLoader, LoadableComponent: DummyComponent }) } ]; const options = { req: { path: '/', originalUrl: 'https://test.com' }, res: { redirect: jest.fn(), status: jest.fn() }, routes: mockRoutes, assets: { client: {} } }; const { render } = require('./render'); await render(options); expect(options.res.status).toHaveBeenCalledWith(404); }); test('should redirect to given path', async () => { const mockLoader = jest.fn().mockResolvedValue(DummyComponent); const mockRoutes = [ { path: '/home', exact: true, component: dummyAsyncComponent({ loader: mockLoader, LoadableComponent: DummyComponent }), redirectTo: '/path-to-redirect' } ]; const options = { req: { path: '/home', originalUrl: 'https://test.com/home' }, res: { redirect: jest.fn(), status: jest.fn() }, routes: mockRoutes, assets: { client: {} } }; const { render } = require('./render'); await render(options); expect(options.res.redirect).toHaveBeenCalledWith(301, 'https://test.com/path-to-redirect'); }); test('should throw an error if can not load route component initial props', async () => { const InitialPropsComponent = () => <span />; InitialPropsComponent.getInitialProps = jest.fn().mockRejectedValue(new Error('mock error')); const ErrorComponent = ({ error }) => <span>{error.message}</span>; const mockLoader = jest.fn().mockResolvedValue(InitialPropsComponent); const mockRoutes = [ { path: '/home', exact: true, component: dummyAsyncComponent({ loader: mockLoader, LoadableComponent: InitialPropsComponent }), redirectTo: '/path-to-redirect' } ]; const options = { req: { path: '/home', originalUrl: 'https://test.com/home' }, res: { redirect: jest.fn(), status: jest.fn() }, routes: mockRoutes, assets: { client: {} }, errorComponent: ErrorComponent }; const { render } = require('./render'); const html = await render(options); expect(InitialPropsComponent.getInitialProps).toHaveBeenCalled(); expect(html).toContain('<span>mock error</span>'); }); test('should use given Document component', async () => { const mockLoader = jest.fn().mockResolvedValue(DummyComponent); const CustomDocument = ({ text }) => <p>{text}</p>; CustomDocument.getInitialProps = jest .fn() .mockResolvedValue({ text: 'This is a custom document' }); const mockRoutes = [ { path: '/test', exact: true, component: dummyAsyncComponent({ loader: mockLoader, LoadableComponent: DummyComponent }) } ]; const options = { req: { path: '/test', originalUrl: 'https://test.com/test' }, res: { redirect: jest.fn(), status: jest.fn() }, routes: mockRoutes, assets: { client: {} }, document: CustomDocument }; const { render } = require('./render'); const html = await render(options); expect(CustomDocument.getInitialProps).toHaveBeenCalled(); expect(html).toEqual('<!doctype html><p>This is a custom document</p>'); });