From 8a6f09b564d5d2f02d0a2605f6b52070a910aaa3 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Mon, 25 Apr 2022 12:57:12 +0200 Subject: chore: add a PageLayout component --- src/components/templates/page/page-layout.test.tsx | 90 ++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 src/components/templates/page/page-layout.test.tsx (limited to 'src/components/templates/page/page-layout.test.tsx') diff --git a/src/components/templates/page/page-layout.test.tsx b/src/components/templates/page/page-layout.test.tsx new file mode 100644 index 0000000..b8fff6a --- /dev/null +++ b/src/components/templates/page/page-layout.test.tsx @@ -0,0 +1,90 @@ +import { render, screen } from '@test-utils'; +import PageLayout from './page-layout'; + +const title = 'Incidunt ad earum'; +const breadcrumb = [ + { id: 'home', url: '#', name: 'Home' }, + { id: 'page', url: '#', name: title }, +]; +const children = + 'Reprehenderit aut quis aperiam magnam quia id. Vero enim animi placeat quia. Laborum sit odio minima. Dolores et debitis eaque iste quidem. Omnis aliquam illum porro ea non. Quaerat totam iste quos ex facilis officia accusantium.'; + +describe('PageLayout', () => { + it('renders the page title', () => { + render( + + {children} + + ); + expect( + screen.getByRole('heading', { level: 1, name: title }) + ).toBeInTheDocument(); + }); + + it('renders the page content', () => { + render( + + {children} + + ); + expect(screen.getByText(children)).toBeInTheDocument(); + }); + + it('renders the breadcrumb', () => { + render( + + {children} + + ); + expect( + screen.getByRole('navigation', { name: 'Breadcrumb' }) + ).toBeInTheDocument(); + }); + + it('renders the table of contents', () => { + render( + + {children} + + ); + expect( + screen.getByRole('heading', { level: 2, name: /Table of Contents/i }) + ).toBeInTheDocument(); + }); + + it('renders the comment form', () => { + render( + + {children} + + ); + expect( + screen.getByRole('form', { name: /Leave a comment/i }) + ).toBeInTheDocument(); + }); + + it('renders the comments list', () => { + const comments = [ + { + author: { + avatar: 'http://placeimg.com/640/480', + name: 'Author 1', + }, + content: + 'Voluptas ducimus inventore. Libero ut et doloribus. Earum nostrum ab. Aliquam rem dolores omnis voluptate. Sunt aut ut et.', + id: 1, + publication: '2021-04-03 18:04:11', + // @ts-ignore - Needed because of the placeholder image. + unoptimized: true, + }, + ]; + render( + + {children} + + ); + expect( + screen.getByRole('heading', { level: 2, name: /Comments/i }) + ).toBeInTheDocument(); + }); +}); -- cgit v1.2.3 From 2155550fa36a3bc3c8f66e0926530123b4018cd4 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Mon, 16 May 2022 12:46:38 +0200 Subject: refactor: use custom hook for breadcrumb items and schema --- src/components/templates/layout/layout.stories.tsx | 54 ++++++++--- src/components/templates/layout/layout.test.tsx | 12 ++- src/components/templates/layout/layout.tsx | 26 ++++- .../templates/page/page-layout.stories.tsx | 12 +++ src/components/templates/page/page-layout.test.tsx | 41 ++++++-- src/components/templates/page/page-layout.tsx | 11 ++- .../sectioned/sectioned-layout.stories.tsx | 24 +++-- .../templates/sectioned/sectioned-layout.test.tsx | 9 +- .../templates/sectioned/sectioned-layout.tsx | 8 +- src/pages/404.tsx | 16 ++-- src/pages/article/[slug].tsx | 24 ++--- src/pages/blog/index.tsx | 16 ++-- src/pages/contact.tsx | 22 ++--- src/pages/cv.tsx | 22 ++--- src/pages/index.tsx | 9 +- src/pages/mentions-legales.tsx | 22 ++--- src/pages/projets/[slug].tsx | 27 ++---- src/pages/projets/index.tsx | 22 ++--- src/pages/recherche/index.tsx | 22 ++--- src/pages/sujet/[slug].tsx | 22 ++--- src/pages/thematique/[slug].tsx | 22 ++--- src/utils/hooks/use-breadcrumb.tsx | 106 +++++++++++++++++++++ 22 files changed, 343 insertions(+), 206 deletions(-) create mode 100644 src/utils/hooks/use-breadcrumb.tsx (limited to 'src/components/templates/page/page-layout.test.tsx') diff --git a/src/components/templates/layout/layout.stories.tsx b/src/components/templates/layout/layout.stories.tsx index 2415412..105e808 100644 --- a/src/components/templates/layout/layout.stories.tsx +++ b/src/components/templates/layout/layout.stories.tsx @@ -1,5 +1,4 @@ import { ComponentMeta, ComponentStory } from '@storybook/react'; -import { IntlProvider } from 'react-intl'; import LayoutComponent from './layout'; /** @@ -8,6 +7,10 @@ import LayoutComponent from './layout'; export default { title: 'Templates/LayoutBase', component: LayoutComponent, + args: { + breadcrumbSchema: [], + isHome: false, + }, argTypes: { children: { control: { @@ -19,6 +22,31 @@ export default { required: true, }, }, + breadcrumbSchema: { + control: { + type: 'null', + }, + description: 'The JSON schema for breadcrumb items.', + type: { + name: 'object', + required: true, + value: {}, + }, + }, + isHome: { + control: { + type: 'boolean', + }, + description: 'Determine if it is the homepage.', + table: { + category: 'Options', + defaultValue: { summary: false }, + }, + type: { + name: 'boolean', + required: false, + }, + }, className: { control: { type: 'text', @@ -35,19 +63,17 @@ export default { }, decorators: [ (Story) => ( - -
- -
-
+
+ +
), ], parameters: { diff --git a/src/components/templates/layout/layout.test.tsx b/src/components/templates/layout/layout.test.tsx index 914e1cd..94145ec 100644 --- a/src/components/templates/layout/layout.test.tsx +++ b/src/components/templates/layout/layout.test.tsx @@ -1,34 +1,36 @@ import { render, screen } from '@test-utils'; +import { BreadcrumbList } from 'schema-dts'; import Layout from './layout'; const body = 'Sit dolorem eveniet. Sit sit odio nemo vitae corrupti modi sint est rerum. Pariatur quidem maiores distinctio. Quia et illum aspernatur est cum.'; +const breadcrumbSchema: BreadcrumbList['itemListElement'][] = []; describe('Layout', () => { it('renders the website header', () => { - render({body}); + render({body}); expect(screen.getByRole('banner')).toBeInTheDocument(); }); it('renders the website main content', () => { - render({body}); + render({body}); expect(screen.getByRole('main')).toBeInTheDocument(); }); it('renders the website footer', () => { - render({body}); + render({body}); expect(screen.getByRole('contentinfo')).toBeInTheDocument(); }); it('renders a skip to content link', () => { - render({body}); + render({body}); expect( screen.getByRole('link', { name: 'Skip to content' }) ).toBeInTheDocument(); }); it('renders an article', () => { - render({body}); + render({body}); expect(screen.getByRole('article')).toHaveTextContent(body); }); }); diff --git a/src/components/templates/layout/layout.tsx b/src/components/templates/layout/layout.tsx index bfb918b..9e9282b 100644 --- a/src/components/templates/layout/layout.tsx +++ b/src/components/templates/layout/layout.tsx @@ -13,7 +13,13 @@ import useSettings from '@utils/hooks/use-settings'; import Script from 'next/script'; import { FC, ReactNode } from 'react'; import { useIntl } from 'react-intl'; -import { Person, SearchAction, WebSite, WithContext } from 'schema-dts'; +import { + BreadcrumbList, + Person, + SearchAction, + WebSite, + WithContext, +} from 'schema-dts'; import styles from './layout.module.scss'; export type QueryAction = SearchAction & { @@ -21,6 +27,10 @@ export type QueryAction = SearchAction & { }; export type LayoutProps = Pick & { + /** + * The breadcrumb JSON schema. + */ + breadcrumbSchema: BreadcrumbList['itemListElement'][]; /** * The layout main content. */ @@ -36,7 +46,12 @@ export type LayoutProps = Pick & { * * Render the base layout used by all pages. */ -const Layout: FC = ({ children, isHome, ...props }) => { +const Layout: FC = ({ + breadcrumbSchema, + children, + isHome, + ...props +}) => { const intl = useIntl(); const { website } = useSettings(); const { baseline, copyright, locales, name, picture, url } = website; @@ -153,12 +168,17 @@ const Layout: FC = ({ children, isHome, ...props }) => { id="schema-layout" type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }} - > + />