or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-wojtekmaj--enzyme-adapter-react-17

Unofficial Enzyme adapter specifically designed for React 17 applications, enabling developers to use Enzyme's testing utilities with React 17's updated architecture.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@wojtekmaj/enzyme-adapter-react-17@0.8.x

To install, run

npx @tessl/cli install tessl/npm-wojtekmaj--enzyme-adapter-react-17@0.8.0

index.mddocs/

@wojtekmaj/enzyme-adapter-react-17

An unofficial Enzyme adapter specifically designed for React 17 applications, enabling developers to use Enzyme's testing utilities with React 17's updated architecture. This adapter acts as a bridge between Enzyme's testing framework and React 17's fiber reconciler, supporting shallow rendering, full DOM rendering, and static rendering of React components.

Package Information

  • Package Name: @wojtekmaj/enzyme-adapter-react-17
  • Package Type: npm
  • Language: JavaScript (with TypeScript definitions)
  • Installation: npm install --save-dev @wojtekmaj/enzyme-adapter-react-17

Core Imports

import Adapter from '@wojtekmaj/enzyme-adapter-react-17';

CommonJS:

const Adapter = require('@wojtekmaj/enzyme-adapter-react-17');

TypeScript:

import * as Adapter from '@wojtekmaj/enzyme-adapter-react-17';
// or
import Adapter = require('@wojtekmaj/enzyme-adapter-react-17');

Basic Usage

import Enzyme from 'enzyme';
import Adapter from '@wojtekmaj/enzyme-adapter-react-17';

// Configure Enzyme to use the React 17 adapter
Enzyme.configure({ adapter: new Adapter() });

// Now use Enzyme's standard API
import { shallow, mount, render } from 'enzyme';
import MyComponent from './MyComponent';

// Shallow rendering
const wrapper = shallow(<MyComponent prop="value" />);

// Full DOM rendering
const wrapper = mount(<MyComponent prop="value" />);

// Static rendering
const wrapper = render(<MyComponent prop="value" />);

Architecture

The adapter extends Enzyme's EnzymeAdapter class and provides React 17-specific implementations for:

  • Fiber Architecture Support: Handles React 17's internal fiber structure changes
  • Renderer Implementations: Provides mount, shallow, and string renderers
  • Event Simulation: Supports React 17's event system for testing
  • Context Handling: Works with React 17's updated context API
  • Concurrent Features: Compatible with React 17's concurrent rendering

Capabilities

ReactSeventeenAdapter Class

The main adapter class that extends EnzymeAdapter and provides React 17 compatibility.

/**
 * React 17 Enzyme Adapter class
 * Extends EnzymeAdapter to provide React 17 compatibility
 */
class ReactSeventeenAdapter extends EnzymeAdapter {
  constructor();
  
  // Renderer factory methods
  createMountRenderer(options: MountRendererOptions): MountRenderer;
  createShallowRenderer(options: ShallowRendererOptions): ShallowRenderer;
  createStringRenderer(options: StringRendererOptions): StringRenderer;
  createRenderer(options: RendererOptions): Renderer;
  
  // Element and node manipulation
  wrap(element: ReactElement): ReactWrapper;
  nodeToElement(node: EnzymeNode): ReactElement | null;
  elementToNode(element: ReactElement): EnzymeNode;
  nodeToHostNode(node: EnzymeNode, supportsArray?: boolean): Node | Node[];
  
  // Type checking and validation
  matchesElementType(node: EnzymeNode, matchingType: ComponentType): boolean;
  isValidElement(element: any): boolean;
  isValidElementType(object: any): boolean;
  isFragment(fragment: any): boolean;
  isCustomComponent(type: ComponentType): boolean;
  isContextConsumer(type: ComponentType): boolean;
  isCustomComponentElement(inst: any): boolean;
  
  // Utility methods
  displayNameOfNode(node: EnzymeNode): string | null;
  getProviderFromConsumer(Consumer: ComponentType): ComponentType | null;
  createElement(...args: any[]): ReactElement;
  wrapWithWrappingComponent(node: EnzymeNode, options: WrappingComponentOptions): EnzymeNode;
}

Mount Renderer

Full DOM rendering capabilities for integration and end-to-end testing.

interface MountRenderer {
  /**
   * Renders a React element to the DOM
   * @param el - React element to render
   * @param context - Optional context for the element
   * @param callback - Optional callback after rendering
   */
  render(el: ReactElement, context?: any, callback?: () => void): void;
  
  /**
   * Unmounts the rendered component from the DOM
   */
  unmount(): void;
  
  /**
   * Gets the rendered component tree as EnzymeNode
   * @returns The root node of the rendered tree
   */
  getNode(): EnzymeNode;
  
  /**
   * Simulates an error in the component tree
   * @param nodeHierarchy - Array of nodes representing the error hierarchy
   * @param rootNode - Root node of the component tree
   * @param error - Error object to simulate
   */
  simulateError(nodeHierarchy: EnzymeNode[], rootNode: EnzymeNode, error: Error): void;
  
  /**
   * Simulates a DOM event on a component node
   * @param node - Target node for the event
   * @param event - Event name (e.g., 'click', 'change')
   * @param mock - Mock event object
   */
  simulateEvent(node: EnzymeNode, event: string, mock: any): void;
  
  /**
   * Batches React updates for optimal performance
   * @param fn - Function containing React updates
   */
  batchedUpdates(fn: () => void): void;
  
  /**
   * Gets renderer for wrapping components
   * @returns Renderer for wrapping components
   */
  getWrappingComponentRenderer(): any;
}

interface MountRendererOptions {
  mode?: 'mount';
  attachTo?: Element;
  hydrateIn?: Element;
  wrappingComponentProps?: any;
  // Note: suspenseFallback is NOT supported by mount renderer
  [key: string]: any;
}

Shallow Renderer

Shallow rendering for unit testing individual components in isolation.

interface ShallowRenderer {
  /**
   * Renders a React element shallowly (one level deep)
   * @param el - React element to render
   * @param unmaskedContext - Context object for the element
   * @param options - Additional rendering options
   */
  render(el: ReactElement, unmaskedContext?: any, options?: ShallowRenderOptions): void;
  
  /**
   * Unmounts the shallow rendered component
   */
  unmount(): void;
  
  /**
   * Gets the shallow rendered component tree
   * @returns The root node of the shallow rendered tree
   */
  getNode(): EnzymeNode;
  
  /**
   * Simulates an error in the shallow component tree
   * @param nodeHierarchy - Array of nodes representing the error hierarchy
   * @param rootNode - Root node of the component tree
   * @param error - Error object to simulate
   */
  simulateError(nodeHierarchy: EnzymeNode[], rootNode: EnzymeNode, error: Error): void;
  
  /**
   * Simulates events on shallow rendered components
   * @param node - Target node for the event
   * @param event - Event name
   * @param args - Event arguments
   */
  simulateEvent(node: EnzymeNode, event: string, ...args: any[]): void;
  
  /**
   * Batches updates for shallow rendering
   * @param fn - Function containing updates
   */
  batchedUpdates(fn: () => void): void;
  
  /**
   * Validates component prop types
   * @param typeSpecs - PropTypes specification object
   * @param values - Actual prop values
   * @param location - Location string for error reporting
   * @param hierarchy - Component hierarchy for stack traces
   */
  checkPropTypes(typeSpecs: any, values: any, location: string, hierarchy: EnzymeNode[]): void;
}

interface ShallowRendererOptions {
  mode?: 'shallow';
  suspenseFallback?: boolean; // Must be boolean or undefined
  [key: string]: any;
}

interface ShallowRenderOptions {
  providerValues?: Map<any, any>;
  [key: string]: any;
}

String Renderer

Server-side rendering capabilities for static HTML generation.

interface StringRenderer {
  /**
   * Renders a React element to a static HTML string
   * @param el - React element to render
   * @param context - Optional context for server-side rendering
   * @returns HTML string representation
   */
  render(el: ReactElement, context?: any): string;
}

interface StringRendererOptions {
  mode?: 'string';
  // Note: suspenseFallback is NOT supported by string renderer
  [key: string]: any;
}

Configuration Options

Options that can be passed to the adapter and its renderers.

interface RendererOptions {
  /**
   * Rendering mode: 'mount', 'shallow', or 'string'
   */
  mode: 'mount' | 'shallow' | 'string';
  
  /**
   * Whether to use fallback content for Suspense components
   * @default false
   */
  suspenseFallback?: boolean;
  
  /**
   * Additional context for rendering
   */
  context?: any;
  
  /**
   * Provider values for context testing
   */
  providerValues?: Map<any, any>;
  
  /**
   * Additional options specific to each renderer
   */
  [key: string]: any;
}

interface WrappingComponentOptions {
  /**
   * Wrapping component for enhanced testing scenarios
   */
  wrappingComponent?: ComponentType;
  
  /**
   * Props to pass to the wrapping component
   */
  wrappingComponentProps?: any;
  
  [key: string]: any;
}

Types

Core types used throughout the adapter API.

/**
 * React element type (imported from React)
 */
type ReactElement = import('react').ReactElement;

/**
 * React component type
 */
type ComponentType = import('react').ComponentType;

/**
 * Enzyme's internal node representation
 */
interface EnzymeNode {
  nodeType: string;
  type: ComponentType | string;
  props: any;
  key: string | null;
  ref: any;
  instance: any;
  rendered: EnzymeNode | EnzymeNode[] | null;
}

/**
 * React wrapper for mount rendering
 */
interface ReactWrapper {
  find(selector: string): ReactWrapper;
  props(): any;
  state(): any;
  simulate(event: string, ...args: any[]): ReactWrapper;
  setProps(props: any): ReactWrapper;
  setState(state: any): ReactWrapper;
  unmount(): ReactWrapper;
  update(): ReactWrapper;
  [key: string]: any;
}

React 17 Features Support

Concurrent Features

  • Compatible with React 17's concurrent rendering
  • Supports Suspense boundaries and fallback content
  • Handles concurrent mode components correctly

Modern React Patterns

  • React.memo(): Full support for memoized components
  • React.lazy(): Code splitting and dynamic imports
  • React.Suspense: Loading states and error boundaries
  • Context API: Provider/Consumer pattern testing
  • Hooks: All React hooks work with the adapter
  • Forward Refs: Reference forwarding in components

Event System

  • Updated event handling for React 17's event delegation changes
  • Proper event simulation with React's SyntheticEvent system
  • Support for both legacy and modern event patterns

Error Handling

The adapter handles various error scenarios gracefully:

// Error boundary testing
const wrapper = mount(
  <ErrorBoundary>
    <ComponentThatThrows />
  </ErrorBoundary>
);

// Simulate errors for testing error boundaries
wrapper.find('ComponentThatThrows').simulateError(new Error('Test error'));

Common Usage Patterns

Testing Hooks with mount()

import { mount } from 'enzyme';
import { useState } from 'react';

function HookComponent() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <span>{count}</span>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

const wrapper = mount(<HookComponent />);
expect(wrapper.find('span').text()).toBe('0');
wrapper.find('button').simulate('click');
expect(wrapper.find('span').text()).toBe('1');

Testing Context Providers

import { mount } from 'enzyme';
import { createContext, useContext } from 'react';

const ThemeContext = createContext('light');

function ThemedComponent() {
  const theme = useContext(ThemeContext);
  return <div className={theme}>Themed content</div>;
}

const wrapper = mount(
  <ThemeContext.Provider value="dark">
    <ThemedComponent />
  </ThemeContext.Provider>
);
expect(wrapper.find('div').hasClass('dark')).toBe(true);

Testing Suspense Components

import { mount } from 'enzyme';
import { Suspense } from 'react';

const LazyComponent = React.lazy(() => import('./LazyComponent'));

const wrapper = mount(
  <Suspense fallback={<div>Loading...</div>}>
    <LazyComponent />
  </Suspense>,
  { suspenseFallback: true }
);

// Test fallback content
expect(wrapper.find('div').text()).toBe('Loading...');

Peer Dependencies

The adapter requires these peer dependencies to be installed:

  • enzyme: ^3.0.0 - The main Enzyme testing library
  • react: ^17.0.0-0 - React 17.x
  • react-dom: ^17.0.0-0 - React DOM 17.x

Installation example:

npm install --save-dev enzyme @wojtekmaj/enzyme-adapter-react-17 react@^17 react-dom@^17