skip to Main Content

According to Gatsby docs, components that use static queries need to be split into variants: one being a pure component and the other that actually uses the static query, passing results to the pure component.

Given an example component:

import React from "react";
import { Helmet } from "react-helmet";
import { useStaticQuery, graphql } from "gatsby";

export const PureSEO = ({
  description = ``,
  lang = `en`,
  meta = [],
  title = ``,
  image = ``,
  ...metaData
}): JSX.Element => {
  const metaDescription = description;

  return (
    <Helmet
      htmlAttributes={{
        lang,
      }}
      title={title}
      titleTemplate={`%s | ${title}`}
      meta={[
        {
          name: `description`,
          content: metaDescription,
        },
        {
          property: `og:title`,
          content: title,
        },
        {
          property: `og:description`,
          content: metaDescription,
        },
        {
          property: `og:type`,
          content: `website`,
        },
        {
          name: `twitter:card`,
          content: `summary`,
        },
        {
          name: `twitter:creator`,
          content: metaData.author,
        },
        {
          name: `twitter:title`,
          content: title,
        },
        {
          name: `twitter:description`,
          content: metaDescription,
        },
        {
          name: `og:image`,
          content: image,
        },
        {
          name: `twitter:image`,
          content: image,
        },
        {
          name: `image`,
          content: image,
        },
      ].concat(meta)}
    />
  );
};

const SEO: React.FC<Props> = ({
  description = ``,
  lang = `en`,
  meta = [],
  title = ``,
}): JSX.Element => {
  const { site, image } = useStaticQuery(
    graphql`
      query {
        site {
          siteMetadata {
            title
            description
            author
            rootDir
          }
        }
        image: file(relativePath: { eq: "favicon.png" }) {
          childImageSharp {
            fixed(width: 400) {
              ...GatsbyImageSharpFixed
            }
          }
        }
      }
    `
  );

  return (
    <PureSEO
      {...site.siteMetadata}
      description={description}
      image={image}
      lang={lang}
      meta={meta}
      title={title}
    />
  );
};

interface Props {
  description?: string;
  lang?: string;
  meta?: HTMLMetaElement[];
  title: string;
}

export default SEO;

I don’t get full test coverage because SEO is not tested; but I don’t think I should be testing that component, since the only logical difference is that it is using static queries.

How can I achieve better or 100% test coverage for my components, given this pattern?

2

Answers


  1. Problem

    I understand the intention of the Gatsby documentation avoid executing useStaticQuery, but the approach implicitly recommends leaving code uncovered.

    Recommendation

    To achieve code coverage, the most logical thing to do would be to either mock useStaticQuery or better yet use MockProvider.

    GraphQL Testing: MockProvider – https://www.apollographql.com/docs/react/development-testing/testing/#mockedprovider

    Login or Signup to reply.
  2. This problem is quite similar to how you would do unit testing of a backend component that communicates with some kind of external service, such as an SQL database.

    You could of course mock useStaticQuery which will give you higher coverage, but it will not actually make you any surer that your code will work. What you want to test revolves around the correctness of your GraphQL query and whether the response format is what you expect, which is not something you can unit test.

    So if you want to be certain that your code works you’d need to perform integration testing, e.g. by running Cypress tests against the built website.

    Theoretically, you could also use contract testing to check that your query itself performs as expected, but it seems like an unnecessarily complicated solution for this usecase.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search