next/headの導入
それなりに大きなNext.jsのプロジェクトにnext/headを導入するにあたってやったことなどのメモ。
共通Headコンポーネント
下記では色々と簡略化してるけど、各ページ共通で使うtitleやmetaタグなどをまとめてprops経由で設定できるようにする。
// Head.tsx import NextHead from 'next/head'; export type Props = { title: string; description?: string; }; export const Head = ({ title, description = 'Test description' }: Props): JSX.Element => { return ( <NextHead> <title>{title}</title> <meta property="description" content={description} /> </NextHead> ); };
<Head title="Test" />
的な感じで利用できる。
参考にしたのは下記のページ。
テスト
Jest + React Testing Libraryを利用しており、単にHeadコンポーネントをrender
してもbody
タグしか表示されないので、少し工夫する必要があった。結果が下記のコード。
import { render } from '@testing-library/react'; import { Head } from '../'; jest.mock('next/head', () => 'Head'); describe('Head', () => { it('default', () => { render(<Head title="Test title" />, { container: document.head, }); expect(document.title).toBe('Test title'); expect( document .querySelector("meta[property='description']") ?.attributes.getNamedItem('content')?.value ).toBe('Test description'); }); });
こちらのページを参考にした。next/headをモックする必要があり、最初は参考ページと同じコードを書いてみた。
jest.mock('next/head', () => { return { __esModule: true, default: ({ children }: { children: Array<React.ReactElement> }) => { return <>{children}</>; }, }; });
この方法だと、自分の環境ではテスト実行時にbabel関連の参照エラーが発生してしまった。
ReferenceError: /dev/head/__tests__/head.test.tsx: The module factory of `jest.mock()` is not allowed to reference any out-of-scope variables. Invalid variable access: jsx_runtime_1 ... Note: This is a precaution to guard against uninitialized mock variables. If it is ensured that the mock is required lazily, variable names prefixed with `mock` (case insensitive) are permitted. 6 | __esModule: true, 7 | default: ({ children }) => { > 8 | return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children }, void 0); | ^^^^^^^^^^^^^ 9 | }, 10 | }; 11 | }); ...
いくらか調べてみたが、有効そうな解決方法が見当たらなかったので、シンプルにファクトリ関数にモジュール名を指定してみたところうまくモックができた。
なぜエラーが発生したのかについてはまだ詳しくわかってない。先ほどのコードでdoMock
を試してみたら参照エラーは無くなったが、今度はrender
した結果が空だった...という経緯があった。
ひとまず、これで共通で使えるコンポーネントとテストができるようになった。やったぜ。