CtrlK
BlogDocsLog inGet started
Tessl Logo

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.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

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

docs

index.md

tile.json