skip to Main Content

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)

enter image description here

2

Answers


  1. 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.

    Login or Signup to reply.
  2. in JS

    jest.mock('next/head', () => {
      return {
        __esModule: true,
        default: ({ children }) => {
          return children;
        }
      };
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search