I am trying to test my SEO component which looks like this:
export const Seo: React.FC<Props> = ({ seo, title, excerpt, heroImage }) => { const description = seo?.description || excerpt const pageTitle = seo?.title || title const router = useRouter() return ( <NextSeo // https://www.npmjs.com/package/next-seo canonical={seo?.canonical} nofollow={seo?.nofollow} noindex={seo?.noindex} title={pageTitle} description={description} openGraph={{ title, description, type: "article", ...
and my test is like so:
describe("Seo", () => { it("should render the meta tags", async () => { const props = { title: "title page", excerpt: "string", seo: { title: "seo title", description: "meta description", }, heroImage: { src: "url", alt: "alt text", width: 300, height: 400, }, } function getMeta(metaName: string) { const metas = document.getElementsByTagName("meta") for (let i = 0; i < metas.length; i += 1) { if (metas[i].getAttribute("name") === metaName) { return metas[i].getAttribute("content") } } return "" } render(<Seo {...props} />) await waitFor(() => expect(getMeta("title")).toEqual("title page")) }) })
however the test is failing: (it looks like the head element is empty)
Advertisement
Answer
I was having the same issue, but I found this answer on GitHub.
So basically you need to mock next/head
, pass document.head
to the container property of render
‘s options and finally access the document
.
Your test would end up like this:
jest.mock('next/head', () => { return { __esModule: true, default: ({ children }: { children: Array<React.ReactElement> }) => { return <>{children}</>; }, }; }); describe("Seo", () => { it("should render the meta tags", () => { const props = { title: "title page", excerpt: "string", seo: { title: "seo title", description: "meta description", }, heroImage: { src: "url", alt: "alt text", width: 300, height: 400, }, } render(<Seo {...props} />, { container: document.head }) expect(document.title).toBe("title page") }) })
In my case I didn’t test it with that getMeta
function but I believe it would work too.