# Configuration

Configure React Testing Library behavior globally or per-test.

## API

```typescript { .api }
function configure(config: Partial<Config> | ((existing: Config) => Partial<Config>)): void;
function getConfig(): Config;

interface Config {
  /**
   * Enable React.StrictMode wrapper by default for all renders
   * Default: false
   */
  reactStrictMode: boolean;

  /**
   * Attribute used for getByTestId and related queries
   * Default: 'data-testid'
   */
  testIdAttribute: string;

  /**
   * Default timeout for async utilities (waitFor, findBy, etc.) in milliseconds
   * Default: 1000
   */
  asyncUtilTimeout: number;

  /**
   * Custom function to compute accessibility names
   */
  computedStyleSupportsPseudoElements?: boolean;

  /**
   * Default hidden value for queries
   * Default: false
   */
  defaultHidden?: boolean;

  /**
   * Show original stack trace on errors
   * Default: false
   */
  showOriginalStackTrace?: boolean;

  /**
   * Throw errors on multiple elements found (for singular queries)
   * Default: true
   */
  throwSuggestions?: boolean;

  /**
   * Custom getElementError function for better error messages
   */
  getElementError?: (message: string | null, container: HTMLElement) => Error;

  /**
   * Wrapper for advancing timers in async operations
   */
  unstable_advanceTimersWrapper?: (callback: () => void) => void;

  /**
   * Wrapper for async operations
   */
  asyncWrapper?: (callback: () => Promise<any>) => Promise<any>;

  /**
   * Wrapper for event handlers
   */
  eventWrapper?: (callback: () => void) => void;
}
```

## Common Setup

### Test Setup File
```typescript
// test-setup.js
import { configure } from '@testing-library/react';
import '@testing-library/jest-dom';

configure({
  reactStrictMode: true,
  asyncUtilTimeout: 2000,
  testIdAttribute: 'data-testid',
});
```

Add to package.json or test config:
```json
{
  "jest": {
    "setupFilesAfterEnv": ["<rootDir>/test-setup.js"]
  }
}
```

## Configuration Options

### reactStrictMode

Enable React.StrictMode wrapper by default for all renders. Helps identify potential problems in components.

```typescript
configure({ reactStrictMode: true });

// Now all renders will be wrapped in StrictMode
render(<App />);

// Equivalent to:
render(<App />, { reactStrictMode: true });
```

Can override per-render:
```typescript
render(<App />, { reactStrictMode: false });
```

### testIdAttribute

Change the attribute used by `getByTestId` and related queries. Useful when using a different testing convention.

```typescript
// Use custom attribute
configure({ testIdAttribute: 'data-test' });

// Now this works:
render(<div data-test="custom-element">Content</div>);
const element = screen.getByTestId('custom-element');
```

### asyncUtilTimeout

Set the default timeout in milliseconds for async utilities like `waitFor` and `findBy*` queries.

```typescript
// Increase timeout for slower operations
configure({ asyncUtilTimeout: 3000 });

// Now all async operations use 3 second timeout by default
await screen.findByText('Async content'); // Waits up to 3s

// Can still override per-call
await waitFor(() => {
  expect(screen.getByText('Content')).toBeInTheDocument();
}, { timeout: 5000 }); // Override to 5s
```

### showOriginalStackTrace

Show original stack traces in errors instead of React Testing Library's cleaned-up versions.

```typescript
configure({ showOriginalStackTrace: true });
```

### throwSuggestions

Enable or disable helpful suggestions in error messages when queries fail.

```typescript
configure({ throwSuggestions: false });
```

### getElementError

Customize error messages when queries fail.

```typescript
import { configure } from '@testing-library/react';

configure({
  getElementError: (message, container) => {
    return new Error(`Custom error: ${message}\nContainer: ${container.innerHTML}`);
  },
});
```

## Common Patterns

### Environment-Specific Config
```typescript
if (process.env.CI) {
  configure({ asyncUtilTimeout: 5000 });  // Longer in CI
} else {
  configure({ asyncUtilTimeout: 1000 });  // Faster locally
}
```

### Per-Test Config
```typescript
describe('slow tests', () => {
  let originalConfig;

  beforeEach(() => {
    originalConfig = getConfig();
    configure({ asyncUtilTimeout: 5000 });
  });

  afterEach(() => {
    configure(originalConfig);
  });

  test('slow operation', async () => {
    // Uses 5s timeout
  });
});
```

### Function Form
Modify based on current config:

```typescript
configure((current) => ({
  asyncUtilTimeout: current.asyncUtilTimeout * 2,
}));
```

## Global vs Per-Render

Some options can be set globally or per-render:

```typescript
// Global
configure({ reactStrictMode: true });

// Per-render (overrides global)
render(<App />, { reactStrictMode: false });
```

## Custom Error Messages

```typescript
configure({
  getElementError: (message, container) => {
    return new Error(`Custom: ${message}\n${container.innerHTML}`);
  },
});
```

## Advanced Configuration

### Custom Async Wrapper

Control how async operations are wrapped:

```typescript
import { configure, act } from '@testing-library/react';

configure({
  asyncWrapper: async (callback) => {
    // Custom async handling
    console.log('Before async operation');
    const result = await callback();
    console.log('After async operation');
    return result;
  },
});
```

### Custom Event Wrapper

Control how events are wrapped:

```typescript
import { configure, act } from '@testing-library/react';

configure({
  eventWrapper: (callback) => {
    // Custom event handling
    act(() => {
      console.log('Firing event');
      callback();
    });
  },
});
```

### Timer Advancement Wrapper

Control timer advancement in async operations:

```typescript
import { configure, act } from '@testing-library/react';

configure({
  unstable_advanceTimersWrapper: (callback) => {
    act(() => {
      callback();
    });
  },
});
```

## Important Notes

### Global vs Per-Render Configuration

Some options can be set globally via `configure()` or per-render via options:

```typescript
// Global
configure({ reactStrictMode: true });

// Per-render (overrides global)
render(<App />, { reactStrictMode: false });
```

### Configuration Persistence

Configuration changes persist across tests. Always restore original configuration if changing it temporarily:

```typescript
const originalConfig = getConfig();

// Modify config
configure({ asyncUtilTimeout: 5000 });

// ... tests ...

// Restore
configure(originalConfig);
```

### Partial Configuration

When using `configure()`, only specified options are updated. Other options remain unchanged:

```typescript
configure({ reactStrictMode: true }); // Only changes reactStrictMode
configure({ asyncUtilTimeout: 2000 }); // Only changes timeout, reactStrictMode stays true
```

### Function Form

Use the function form to modify configuration based on current values:

```typescript
configure((current) => ({
  asyncUtilTimeout: current.asyncUtilTimeout * 2,
}));
```

## Relationship with @testing-library/dom Configuration

React Testing Library's `configure()` function extends @testing-library/dom's configuration. All dom configuration options are available:

- `testIdAttribute`
- `asyncUtilTimeout`
- `showOriginalStackTrace`
- `throwSuggestions`
- `getElementError`
- And others from @testing-library/dom

React Testing Library adds:

- `reactStrictMode` (React-specific)
- React-specific wrappers for `asyncWrapper`, `eventWrapper`, and `unstable_advanceTimersWrapper`

## Best Practices

1. **Set in test setup** - Configure once in setup file
2. **Restore after changes** - Save/restore when temporarily changing
3. **Use per-render overrides** - For exceptions, override at render time
4. **Match environment** - Adjust timeouts for CI vs local
5. **Enable StrictMode** - Catch issues early in development

## Default Values

```typescript
const defaultConfig = {
  reactStrictMode: false,
  testIdAttribute: 'data-testid',
  asyncUtilTimeout: 1000,
  showOriginalStackTrace: false,
  throwSuggestions: true,
  defaultHidden: false,
  computedStyleSupportsPseudoElements: false,
};
```
