Hone logo
Hone
Problems

Jest setupFiles for Global Configuration

This challenge focuses on leveraging Jest's setupFiles option to execute code before your tests run. You'll learn how to use setupFiles to establish a consistent testing environment, such as mocking modules, setting up global variables, or initializing libraries that your tests depend on. This is a fundamental technique for efficient and maintainable Jest test suites.

Problem Description

Your task is to implement and demonstrate the use of Jest's setupFiles configuration option in a TypeScript project. You need to create a setup file that performs a specific action (e.g., defining a global variable, mocking a module) and then write a test that verifies this setup has been successfully applied.

What needs to be achieved:

  1. Create a separate TypeScript file that will serve as your setupFiles entry point.
  2. Within this setup file, perform a predefined action (you will choose one from the suggested options below).
  3. Configure your jest.config.ts (or jest.config.js) to include your setup file in the setupFiles array.
  4. Write a Jest test that asserts the action performed in the setup file has taken effect.

Key requirements:

  • The setup file must be written in TypeScript.
  • The configuration file must correctly point to the setup file.
  • The test must pass, proving the setup file executed as expected.

Suggested actions for the setup file (choose one):

  • Option A: Define a Global Variable: Define a global variable (e.g., global.MY_GLOBAL_SETTING = 'enabled';) that can be accessed by your tests.
  • Option B: Mock a Module: Use jest.mock() to mock a common Node.js module (e.g., fs) or a custom module you create.
  • Option C: Add a Utility Function to global: Add a simple utility function to the global scope (e.g., global.formatDate = (date: Date) => date.toISOString();).

Expected behavior:

When Jest runs, it should first execute the code in your specified setupFiles. Subsequently, your tests should be able to interact with or observe the results of this setup code.

Edge cases to consider:

  • Ensure the setup file path is correct relative to your project root.
  • If mocking a module, ensure the mock implementation is appropriate for your test.

Examples

Example 1: Using setupFiles to Define a Global Variable

Let's assume you want to set a global configuration flag.

File: src/globals.ts (The setup file)

// src/globals.ts
(global as any).APP_CONFIG = {
  apiUrl: 'https://api.example.com',
  featureFlags: {
    newDashboard: true,
  },
};
console.log('APP_CONFIG has been set globally.'); // For demonstration

File: jest.config.ts (The Jest configuration)

// jest.config.ts
export default {
  preset: 'ts-jest',
  testEnvironment: 'node',
  setupFiles: ['./src/globals.ts'], // Path to your setup file
  transform: {
    '^.+\\.ts$': 'ts-jest',
  },
  moduleFileExtensions: ['ts', 'js'],
};

File: src/app.test.ts (The test file)

// src/app.test.ts
describe('Global Configuration', () => {
  it('should have access to the globally defined APP_CONFIG', () => {
    expect((global as any).APP_CONFIG).toBeDefined();
    expect((global as any).APP_CONFIG.apiUrl).toBe('https://api.example.com');
    expect((global as any).APP_CONFIG.featureFlags.newDashboard).toBe(true);
    console.log('APP_CONFIG accessed in test.'); // For demonstration
  });
});

Explanation:

The globals.ts file defines APP_CONFIG on the global object. Jest's setupFiles ensures this file is executed before any tests run. The test in app.test.ts then successfully accesses and asserts properties of this global variable.

Example 2: Using setupFiles to Mock a Module

Let's say you want to mock the built-in fs module for tests that might otherwise try to access the file system.

File: src/file-utils.ts (A hypothetical module using fs)

// src/file-utils.ts
import * as fs from 'fs';

export function readFileContent(filePath: string): string {
  return fs.readFileSync(filePath, 'utf-8');
}

File: src/mocks/setup-fs.ts (The setup file)

// src/mocks/setup-fs.ts
import * as fs from 'fs';

// Mock the entire 'fs' module
jest.mock('fs', () => ({
  // Provide a mock implementation for readFileSync
  readFileSync: jest.fn((path: string) => {
    if (path === '/path/to/mocked/file.txt') {
      return 'Mocked file content!';
    }
    throw new Error('Unexpected file path in mock');
  }),
  // You can mock other fs methods if needed
  existsSync: jest.fn((path: string) => path === '/path/to/mocked/file.txt'),
}));

console.log('fs module has been mocked.'); // For demonstration

File: jest.config.ts (The Jest configuration)

// jest.config.ts
export default {
  preset: 'ts-jest',
  testEnvironment: 'node',
  setupFiles: ['./src/mocks/setup-fs.ts'], // Path to your setup file
  transform: {
    '^.+\\.ts$': 'ts-jest',
  },
  moduleFileExtensions: ['ts', 'js'],
};

File: src/file-utils.test.ts (The test file)

// src/file-utils.test.ts
import { readFileContent } from './file-utils';
import * as fs from 'fs'; // Import fs to access the mocked implementation

describe('File Utility with Mocked FS', () => {
  it('should read content from a mocked file', () => {
    const mockFilePath = '/path/to/mocked/file.txt';
    const content = readFileContent(mockFilePath);

    expect(content).toBe('Mocked file content!');
    expect(fs.readFileSync).toHaveBeenCalledWith(mockFilePath, 'utf-8'); // Verify mock was called
  });
});

Explanation:

The setup-fs.ts file uses jest.mock('fs', ...) to replace the actual fs module with a mock. The readFileSync function in the mock is defined to return specific content for a given path. The test file then imports readFileContent (which internally uses fs) and calls it. Because the fs module is mocked via setupFiles, readFileContent will use the mock implementation, and the test passes.

Constraints

  • The project must be set up to use TypeScript with Jest (e.g., ts-jest preset is recommended).
  • The setupFiles array in jest.config.ts should contain at least one entry pointing to a valid TypeScript setup file.
  • The chosen setup action should be clearly implemented and verifiable by a test.
  • Tests should be clear and concise, focusing on verifying the setup.

Notes

  • The setupFiles option is ideal for code that needs to run once before all tests in a suite. For code that needs to run before each test, consider setupFilesAfterEnv.
  • Be mindful of the order of execution. setupFiles run before setupFilesAfterEnv, which run before tests themselves.
  • When mocking modules in setupFiles, ensure your mock implementation covers the necessary aspects for your tests. You can still import the actual module in your test file (as shown in Example 2) to type-check or interact with the mocked API if needed.
  • For more complex setups or shared configurations across multiple projects, consider using globalSetup and globalTeardown for operations that run only once per Jest run, outside of any specific test suite.
Loading editor...
typescript