Back to Repositories

Testing Route Fetching Implementation in GatsbyJS Font Preloader

This test suite validates the route fetching functionality in Gatsby’s font preloading plugin. It ensures proper handling of GraphQL requests, route collection, and caching behavior for font preloading optimization.

Test Coverage Overview

The test suite provides comprehensive coverage of the route fetching mechanism with specific focus on edge cases and cache handling.

  • Empty route handling validation
  • Route array generation testing
  • Cache comparison logic verification
  • CI environment behavior testing

Implementation Analysis

The implementation uses Jest’s mocking capabilities to isolate the route fetching logic from external dependencies. The tests leverage mock implementations for GraphQL requests and logger functionality to validate different scenarios.

Key patterns include:
  • Mock function implementations for external dependencies
  • Async/await testing patterns
  • Expectation assertions with Jest matchers

Technical Details

Testing infrastructure includes:
  • Jest as the testing framework
  • graphql-request mocking
  • gatsby-core-utils mocking
  • Custom logger mock implementation
  • BeforeEach setup for cache and logger initialization

Best Practices Demonstrated

The test suite exemplifies several testing best practices for JavaScript applications.

  • Proper test isolation through beforeEach hooks
  • Explicit assertion counts using expect.assertions()
  • Comprehensive mock implementations
  • Clear test case descriptions
  • Efficient setup and teardown patterns

gatsbyjs/gatsby

packages/gatsby-plugin-preload-fonts/src/__tests__/fetch-routes.test.js

            
jest.mock(`graphql-request`, () => {
  return { request: jest.fn() }
})

jest.mock(`gatsby-core-utils`)

const { request } = require(`graphql-request`)
const { isCI, createContentDigest } = require(`gatsby-core-utils`)
const createMockLogger = require(`logger-mock`)
const fetchRoutes = require(`../prepare/fetch-routes`)

describe(`fetch-routes`, () => {
  const endpoint = `http://localhost:3000/___graphql`
  let cache
  let logger

  beforeEach(() => {
    cache = {
      timestamp: Date.now(),
      hash: `initial-run`,
      assets: {},
    }
    logger = createMockLogger()
  })

  it(`doesn't throw when no routes are present`, async () => {
    expect.assertions(2)

    request.mockImplementationOnce(() => {
      return {
        allSitePage: {
          nodes: [],
        },
      }
    })

    const routes = await fetchRoutes({ logger, endpoint, cache })

    expect(request).toHaveBeenCalled()
    expect(routes).toEqual([])
  })

  it(`generates an array of routes`, async () => {
    expect.assertions(1)

    request.mockImplementationOnce(() => {
      return {
        allSitePage: {
          nodes: [{ path: `/foo` }, { path: `/bar` }, { path: `/baz` }],
        },
      }
    })

    const routes = await fetchRoutes({ logger, endpoint, cache })

    expect(routes).toEqual([`/foo`, `/bar`, `/baz`])
  })

  it(`prompts the user when the list of routes has not changed since last run`, async () => {
    expect.assertions(1)

    request.mockImplementationOnce(() => {
      return {
        allSitePage: {
          nodes: [{ path: `/foo` }, { path: `/bar` }, { path: `/baz` }],
        },
      }
    })
    // don't crawl routes
    logger.confirm.mockImplementationOnce(() => Promise.resolve(false))
    createContentDigest.mockReturnValueOnce(cache.hash)

    await expect(fetchRoutes({ logger, endpoint, cache })).resolves.toEqual([])
  })

  it(`doesn't prompt the user when the list of routes has not changed since last run if run in CI`, async () => {
    expect.assertions(1)

    request.mockImplementationOnce(() => {
      return {
        allSitePage: {
          nodes: [{ path: `/foo` }, { path: `/bar` }, { path: `/baz` }],
        },
      }
    })

    cache.hash = `09f5b092fb87d859e0ac53dbae299a9e`
    createContentDigest.mockReturnValueOnce(cache.hash)
    isCI.mockReturnValueOnce(true)

    await expect(fetchRoutes({ logger, endpoint, cache })).resolves.toEqual([])
  })
})