diff options
| author | Armand Philippot <git@armandphilippot.com> | 2023-12-12 18:50:03 +0100 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2023-12-12 18:50:03 +0100 |
| commit | 85c4c42bd601270d7be0f34a0767a34bb85e29bb (patch) | |
| tree | 16a07a89cf209139672592fd6988f0c028acb7e9 /src/utils/hooks/use-breadcrumbs/use-breadcrumbs.test.tsx | |
| parent | 93f87c10783e3d76f1dec667779aedffcae33a39 (diff) | |
refactor(hooks): rewrite useBreadcrumbs hook
* use next/router to get the slug instead of using props
* handle cases where the current page title is not provided
* update JSON-LD schema to match the example in documentation
* add tests
Diffstat (limited to 'src/utils/hooks/use-breadcrumbs/use-breadcrumbs.test.tsx')
| -rw-r--r-- | src/utils/hooks/use-breadcrumbs/use-breadcrumbs.test.tsx | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/src/utils/hooks/use-breadcrumbs/use-breadcrumbs.test.tsx b/src/utils/hooks/use-breadcrumbs/use-breadcrumbs.test.tsx new file mode 100644 index 0000000..9778aed --- /dev/null +++ b/src/utils/hooks/use-breadcrumbs/use-breadcrumbs.test.tsx @@ -0,0 +1,232 @@ +import { describe, expect, it } from '@jest/globals'; +import { act, renderHook } from '@testing-library/react'; +import nextRouterMock from 'next-router-mock'; +import { MemoryRouterProvider } from 'next-router-mock/MemoryRouterProvider'; +import type { ReactNode } from 'react'; +import { IntlProvider } from 'react-intl'; +import { PAGINATED_ROUTE_PREFIX, ROUTES } from '../../constants'; +import { capitalize } from '../../helpers'; +import { useBreadcrumbs } from './use-breadcrumbs'; + +const AllProviders = ({ children }: { children: ReactNode }) => ( + <IntlProvider defaultLocale="en" locale="en"> + <MemoryRouterProvider>{children}</MemoryRouterProvider> + </IntlProvider> +); + +describe('useBreadcrumbs', () => { + it('returns the breadcrumbs items and its schema', async () => { + const currentSlug = '/current-slug'; + const label = capitalize( + (currentSlug.split('/').pop() ?? currentSlug).replaceAll('-', ' ') + ); + + await act(async () => nextRouterMock.push(currentSlug)); + + const { result } = renderHook(() => useBreadcrumbs(), { + wrapper: AllProviders, + }); + + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + expect.assertions(4); + + expect(result.current.items).toHaveLength(2); + expect(result.current.items[0]).toStrictEqual({ + id: '/', + label: 'Home', + slug: '/', + }); + expect(result.current.items[1]).toStrictEqual({ + id: currentSlug, + label, + slug: currentSlug, + }); + expect(result.current.schema).toStrictEqual({ + '@type': 'BreadcrumbList', + '@id': 'breadcrumbs', + itemListElement: [ + { + '@type': 'ListItem', + item: { + '@id': ROUTES.HOME, + name: 'Home', + }, + position: 1, + }, + { + '@type': 'ListItem', + item: { + '@id': currentSlug, + name: label, + }, + position: 2, + }, + ], + }); + }); + + it('can render the items for the 404 page', async () => { + await act(async () => nextRouterMock.push(ROUTES.NOT_FOUND)); + + const { result } = renderHook(() => useBreadcrumbs(), { + wrapper: AllProviders, + }); + + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + expect.assertions(3); + + expect(result.current.items).toHaveLength(2); + expect(result.current.items[0]).toStrictEqual({ + id: '/', + label: 'Home', + slug: '/', + }); + expect(result.current.items[1]).toStrictEqual({ + id: ROUTES.NOT_FOUND, + label: '404: Not found', + slug: ROUTES.NOT_FOUND, + }); + }); + + it('can render the items for the Blog page', async () => { + await act(async () => nextRouterMock.push(ROUTES.BLOG)); + + const { result } = renderHook(() => useBreadcrumbs(), { + wrapper: AllProviders, + }); + + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + expect.assertions(3); + + expect(result.current.items).toHaveLength(2); + expect(result.current.items[0]).toStrictEqual({ + id: '/', + label: 'Home', + slug: '/', + }); + expect(result.current.items[1]).toStrictEqual({ + id: ROUTES.BLOG, + label: 'Blog', + slug: ROUTES.BLOG, + }); + }); + + it('can render the items for the paginated routes', async () => { + const pageNumber = 3; + const currentSlug = `${ROUTES.BLOG}${PAGINATED_ROUTE_PREFIX}/${pageNumber}`; + await act(async () => nextRouterMock.push(currentSlug)); + + const { result } = renderHook(() => useBreadcrumbs(), { + wrapper: AllProviders, + }); + + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + expect.assertions(4); + + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + expect(result.current.items).toHaveLength(3); + expect(result.current.items[0]).toStrictEqual({ + id: '/', + label: 'Home', + slug: '/', + }); + expect(result.current.items[1]).toStrictEqual({ + id: ROUTES.BLOG, + label: 'Blog', + slug: ROUTES.BLOG, + }); + expect(result.current.items[2]).toStrictEqual({ + id: currentSlug, + label: `Page ${pageNumber}`, + slug: currentSlug, + }); + }); + + it('can render the items for the Projects page', async () => { + await act(async () => nextRouterMock.push(ROUTES.PROJECTS)); + + const { result } = renderHook(() => useBreadcrumbs(), { + wrapper: AllProviders, + }); + + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + expect.assertions(3); + + expect(result.current.items).toHaveLength(2); + expect(result.current.items[0]).toStrictEqual({ + id: '/', + label: 'Home', + slug: '/', + }); + expect(result.current.items[1]).toStrictEqual({ + id: ROUTES.PROJECTS, + label: 'Projects', + slug: ROUTES.PROJECTS, + }); + }); + + it('can render the items for the Search page', async () => { + const query = 'similique'; + const currentSlug = `${ROUTES.SEARCH}?s=${query}`; + await act(async () => nextRouterMock.push(currentSlug)); + + const { result } = renderHook(() => useBreadcrumbs(), { + wrapper: AllProviders, + }); + + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + expect.assertions(4); + + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + expect(result.current.items).toHaveLength(3); + expect(result.current.items[0]).toStrictEqual({ + id: '/', + label: 'Home', + slug: '/', + }); + expect(result.current.items[1]).toStrictEqual({ + id: ROUTES.SEARCH, + label: 'Search', + slug: ROUTES.SEARCH, + }); + expect(result.current.items[2]).toStrictEqual({ + id: currentSlug, + label: `Search results for "${query}"`, + slug: currentSlug, + }); + }); + + it('can render the items for the Articles page', async () => { + const article = { + slug: '/the-article-slug', + title: 'qui ducimus rerum', + }; + const currentSlug = `${ROUTES.ARTICLE}${article.slug}`; + await act(async () => nextRouterMock.push(currentSlug)); + + const { result } = renderHook(() => useBreadcrumbs(article.title), { + wrapper: AllProviders, + }); + + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + expect.assertions(4); + + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + expect(result.current.items).toHaveLength(3); + expect(result.current.items[0]).toStrictEqual({ + id: '/', + label: 'Home', + slug: '/', + }); + expect(result.current.items[1]).toStrictEqual({ + id: ROUTES.BLOG, + label: 'Blog', + slug: ROUTES.BLOG, + }); + expect(result.current.items[2]).toStrictEqual({ + id: currentSlug, + label: article.title, + slug: currentSlug, + }); + }); +}); |
