/* eslint-disable @typescript-eslint/no-unsafe-member-access */ import React from 'react'; import { Provider } from 'react-redux'; import ShallowRenderer from 'react-test-renderer/shallow'; import { describe, test, expect, vi } from 'vitest'; import FourOhFourPage from '../../src/pages/404'; import Certification from '../../src/pages/certification'; import Learn from '../../src/pages/learn'; import { createStore } from '../../src/redux/create-store'; import layoutSelector from './layout-selector'; vi.mock('../../src/analytics'); vi.mock('../../src/utils/get-words'); const store = createStore(); // TODO: rather than testing which props passed from layoutSelector to the // component it renders, test that the rendered component has the expected // features (i.e. has a footer or not, etc.). That should be possible in // react-testing-library. interface NameAndProps { props: Record; name: string; } function getComponentNameAndProps( elementType: React.JSXElementConstructor, pathname: string, pageContext?: { challengeMeta?: { block?: string; superBlock?: string } } ): NameAndProps { const utils = ShallowRenderer.createRenderer(); const LayoutReactComponent = layoutSelector({ element: { type: elementType, props: {}, key: '' }, props: { data: {}, location: { pathname }, pageContext, params: { '*': '' }, path: '' } }); utils.render({LayoutReactComponent}); const view = utils.getRenderOutput(); return { props: view.props.children.props as Record, // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment name: view.props.children.type.WrappedComponent.displayName // TODO: Revisit this when react-test-renderer is replaced with // react-testing-library }; } const challengePageContext = { challengeMeta: { block: 'Basic HTML and HTML5', superBlock: 'responsive-web-design' } }; describe('Layout selector', () => { test('Challenges should have DefaultLayout and no footer', () => { const challengePath = '/learn/responsive-web-design/basic-html-and-html5/say-hello-to-html-elements'; const componentObj = getComponentNameAndProps( Learn, challengePath, challengePageContext ); expect(componentObj.name).toEqual('DefaultLayout'); expect(componentObj.props.showFooter).toEqual(false); }); test('SuperBlock path should have DefaultLayout and footer', () => { const superBlockPath = '/learn/responsive-web-design/'; const componentObj = getComponentNameAndProps(Learn, superBlockPath); expect(componentObj.name).toEqual('DefaultLayout'); expect(componentObj.props.showFooter).toEqual(true); }); test('i18n challenge path should have DefaultLayout and no footer', () => { const challengePath = 'espanol/learn/responsive-web-design/basic-html-and-html5/say-hello-to-html-elements/'; const componentObj = getComponentNameAndProps( Learn, challengePath, challengePageContext ); expect(componentObj.name).toEqual('DefaultLayout'); expect(componentObj.props.showFooter).toEqual(false); }); test('i18n superBlock path should have DefaultLayout and footer', () => { const superBlockPath = '/learn/responsive-web-design/'; const componentObj = getComponentNameAndProps(Learn, superBlockPath); expect(componentObj.name).toEqual('DefaultLayout'); expect(componentObj.props.showFooter).toEqual(true); }); test('404 page should have DefaultLayout and footer', () => { const challengePath = '/espanol/learn/responsive-web-design/basic-html-and-html5/say-hello-to-html-elements/'; const componentObj = getComponentNameAndProps( FourOhFourPage, challengePath ); expect(componentObj.name).toEqual('DefaultLayout'); expect(componentObj.props.showFooter).toEqual(true); }); test('Certification path should have CertificationLayout', () => { const challengePath = '/certification/mot01/javascript-algorithms-and-data-structures/'; const componentObj = getComponentNameAndProps(Certification, challengePath); expect(componentObj.name).toEqual('CertificationLayout'); }); test('Status paths should return raw element without layout', () => { const TestComponent = () =>
Test
; const statusPath = '/status/version'; const result = layoutSelector({ element: { type: TestComponent, props: {}, key: '' }, props: { data: {}, location: { pathname: statusPath }, params: { '*': '' }, path: '' } }); // The result should be the element directly, not wrapped in a layout expect(result.type).toBe(TestComponent); }); });