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 { CONFIG } from '../../config'; import { PAGINATED_ROUTE_PREFIX, ROUTES } from '../../constants'; import { capitalize, trimTrailingChars } from '../../helpers'; import { useBreadcrumbs } from './use-breadcrumbs'; const AllProviders = ({ children }: { children: ReactNode }) => ( {children} ); 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': trimTrailingChars(CONFIG.url, '/'), name: 'Home', }, position: 1, }, { '@type': 'ListItem', item: { '@id': `${trimTrailingChars(CONFIG.url, '/')}${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, }); }); });