Back to Repositories

Validating Module System Integration in GatsbyJS Configuration

This test suite validates ESM and CommonJS module support in Gatsby configuration files, ensuring proper integration of different module systems in Gatsby projects. The tests verify the functionality of gatsby-config.js and gatsby-config.mjs files with their respective module implementations.

Test Coverage Overview

The test suite provides comprehensive coverage of module system integration in Gatsby configurations.

Key areas tested include:
  • CommonJS module loading in gatsby-config.js
  • ESM module importing in gatsby-config.mjs
  • Local plugin integration with both module systems
  • Build process verification with different module types
  • Plugin option handling with ESM modules

Implementation Analysis

The testing approach uses Jest’s asynchronous testing capabilities to validate Gatsby’s build process with different module systems. The implementation leverages file system operations to set up test fixtures and verify build outputs, while using process execution to test actual Gatsby builds.

Notable patterns include:
  • Dynamic file copying for test setup
  • Environment variable configuration for production builds
  • Stdout parsing for build verification
  • Cleanup routines using afterEach hooks

Technical Details

Testing tools and configuration:
  • Jest as the primary testing framework
  • fs-extra for file system operations
  • execa for process execution
  • Custom fixture setup for both CJS and ESM modules
  • Extended timeout configuration (100000ms)
  • Environment variable management for build process

Best Practices Demonstrated

The test suite exemplifies high-quality testing practices through careful organization and thorough verification approaches.

Key practices include:
  • Isolated test environments with proper cleanup
  • Comprehensive assertion coverage
  • Efficient test grouping to minimize build time impact
  • Clear test case separation between CJS and ESM implementations
  • Robust error handling and resource cleanup

gatsbyjs/gatsby

integration-tests/esm-in-gatsby-files/__tests__/gatsby-config.test.js

            
import path from "path"
import fs from "fs-extra"
import execa from "execa"

jest.setTimeout(100000)

const fixtureRoot = path.resolve(__dirname, `fixtures`)
const siteRoot = path.resolve(__dirname, `..`)

const fixturePath = {
  cjs: path.join(fixtureRoot, `gatsby-config.js`),
  esm: path.join(fixtureRoot, `gatsby-config.mjs`),
}

const configPath = {
  cjs: path.join(siteRoot, `gatsby-config.js`),
  esm: path.join(siteRoot, `gatsby-config.mjs`),
}

const localPluginFixtureDir = path.join(fixtureRoot, `plugins`)
const localPluginTargetDir = path.join(siteRoot, `plugins`)

const gatsbyBin = path.join(`node_modules`, `gatsby`, `cli.js`)

async function build() {
  const { stdout } = await execa(process.execPath, [gatsbyBin, `build`], {
    env: {
      ...process.env,
      NODE_ENV: `production`,
    },
  })

  return stdout
}

// Tests include multiple assertions since running multiple builds is time consuming

describe(`gatsby-config.js`, () => {
  afterEach(async () => {
    await fs.rm(configPath.cjs)
    await fs.rm(localPluginTargetDir, { recursive: true })
  })

  it(`works with required CJS modules`, async () => {
    await fs.copyFile(fixturePath.cjs, configPath.cjs)

    await fs.ensureDir(localPluginTargetDir)
    await fs.copy(localPluginFixtureDir, localPluginTargetDir)

    const stdout = await build()

    // Build succeeded
    expect(stdout).toContain(`Done building`)

    // Requires work
    expect(stdout).toContain(`hello-default-cjs`)
    expect(stdout).toContain(`hello-named-cjs`)

    // Local gatsby-remark-plugin works
    expect(stdout).toContain(`gatsby-remark-cjs-gatsby-config-js`)
  })
})

describe(`gatsby-config.mjs`, () => {
  afterEach(async () => {
    await fs.rm(configPath.esm)
    await fs.rm(localPluginTargetDir, { recursive: true })
  })

  it(`works with imported ESM modules`, async () => {
    await fs.copyFile(fixturePath.esm, configPath.esm)

    await fs.ensureDir(localPluginTargetDir)
    await fs.copy(localPluginFixtureDir, localPluginTargetDir)

    const stdout = await build()

    // Build succeeded
    expect(stdout).toContain(`Done building`)

    // Imports work
    expect(stdout).toContain(`hello-default-esm`)
    expect(stdout).toContain(`hello-named-esm`)

    // Local plugin gatsby-config.mjs works
    expect(stdout).toContain(`a-local-plugin-gatsby-config-mjs`)

    // Local ESM gatsby-remark-plugin works
    expect(stdout).toContain(`gatsby-remark-esm-gatsby-config-mjs`)

    // Local plugin with an esm module passed via options works, this implicitly tests gatsby-node.mjs too
    expect(stdout).toContain(`a-local-plugin-using-passed-esm-module`)
  })
})