CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-inferno-test-utils

Suite of utilities for testing Inferno applications with comprehensive tree traversal, element finding, and Jest snapshot integration.

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

rendering.mddocs/

Rendering Utilities API

Utilities for rendering components into test environments and working with VNodes in testing scenarios. These functions provide the foundation for setting up test environments and extracting useful information from rendered components.

Rendering Functions

renderIntoContainer

/**
 * Renders input into a detached DOM container and returns the rendered tree
 * @param input - VNode, component, or other renderable content to render
 * @returns Rendered component tree or VNode suitable for testing
 */
function renderIntoContainer(input: boolean | VNode | InfernoChild | InfernoFragment | null | undefined): Component<any, any> | VNode

This is the primary function for setting up test environments. It creates a detached DOM element, renders your component into it, and returns the rendered tree for testing.

import { renderIntoContainer } from 'inferno-test-utils';
import { Component } from 'inferno';

// Simple DOM element rendering
const simpleVNode = <div className="test">Hello World</div>;
const renderedSimple = renderIntoContainer(simpleVNode);

// Component rendering
class TestComponent extends Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }
  
  render() {
    return (
      <div className="component">
        <p>Count: {this.state.count}</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Increment
        </button>
      </div>
    );
  }
}

const renderedComponent = renderIntoContainer(<TestComponent />);

// Functional component rendering
function FunctionalComponent({ name }) {
  return <div className="functional">Hello {name}</div>;
}

const renderedFunctional = renderIntoContainer(<FunctionalComponent name="World" />);

// Complex nested structure
const complexVNode = (
  <div className="app">
    <header>
      <h1>My App</h1>
    </header>
    <main>
      <TestComponent />
      <FunctionalComponent name="User" />
    </main>
  </div>
);

const renderedComplex = renderIntoContainer(complexVNode);

Return Value Behavior

The function returns different types based on what was rendered:

import { renderIntoContainer, isRenderedClassComponent } from 'inferno-test-utils';
import { Component } from 'inferno';

class MyClassComponent extends Component {
  render() { return <div>Class Component</div>; }
}

function MyFunctionalComponent() {
  return <div>Functional Component</div>;
}

// Class component returns the component instance
const classResult = renderIntoContainer(<MyClassComponent />);
console.log(isRenderedClassComponent(classResult)); // true

// Functional component returns the VNode
const functionalResult = renderIntoContainer(<MyFunctionalComponent />);
console.log(isRenderedClassComponent(functionalResult)); // false

// DOM element returns the VNode
const domResult = renderIntoContainer(<div>DOM Element</div>);
console.log(isRenderedClassComponent(domResult)); // false

Working with Props and State

import { renderIntoContainer, findRenderedDOMElementWithTag, isRenderedClassComponent } from 'inferno-test-utils';
import { Component } from 'inferno';

class StatefulComponent extends Component {
  constructor(props) {
    super(props);
    this.state = { isVisible: props.initialVisible || false };
  }
  
  toggle = () => {
    this.setState({ isVisible: !this.state.isVisible });
  }
  
  render() {
    return (
      <div>
        <button onClick={this.toggle}>Toggle</button>
        {this.state.isVisible && <p>Visible content</p>}
      </div>
    );
  }
}

// Render with props
const rendered = renderIntoContainer(<StatefulComponent initialVisible={true} />);

// Access the component instance (for class components)
if (isRenderedClassComponent(rendered)) {
  console.log(rendered.state.isVisible); // true
  console.log(rendered.props.initialVisible); // true
  
  // Trigger state changes
  rendered.toggle();
  console.log(rendered.state.isVisible); // false
}

// Find elements in the rendered output
const button = findRenderedDOMElementWithTag(rendered, 'button');
console.log(button.textContent); // "Toggle"

Utility Functions

getTagNameOfVNode

/**
 * Gets the lowercase tag name of a DOM VNode
 * @param vNode - VNode representing a DOM element
 * @returns Lowercase tag name of the DOM element, or undefined if not a DOM VNode
 */
function getTagNameOfVNode(vNode: VNode): string | undefined
import { getTagNameOfVNode, scryRenderedVNodesWithType, renderIntoContainer } from 'inferno-test-utils';

const vNodeTree = (
  <div>
    <h1>Heading</h1>
    <p>Paragraph</p>
    <button>Button</button>
  </div>
);

const rendered = renderIntoContainer(vNodeTree);

// Find all DOM VNodes and get their tag names
const h1VNodes = scryRenderedVNodesWithType(rendered, 'h1');
const pVNodes = scryRenderedVNodesWithType(rendered, 'p');
const buttonVNodes = scryRenderedVNodesWithType(rendered, 'button');

console.log(getTagNameOfVNode(h1VNodes[0])); // "h1"
console.log(getTagNameOfVNode(pVNodes[0])); // "p" 
console.log(getTagNameOfVNode(buttonVNodes[0])); // "button"

// Returns undefined for non-DOM VNodes
function MyComponent() { return <div />; }
const componentVNodes = scryRenderedVNodesWithType(rendered, MyComponent);
console.log(getTagNameOfVNode(componentVNodes[0])); // undefined

Test Wrapper Component

Wrapper Class

/**
 * Test wrapper component that renders its children
 * Useful for wrapping components that need a parent context
 */
class Wrapper<P, S> extends Component<P, S> {
  public render(): InfernoNode
}

The Wrapper component is primarily used internally but can be useful for testing scenarios where you need to wrap components.

import { Wrapper, renderIntoContainer, findRenderedDOMElementWithClass, findRenderedDOMElementWithTag } from 'inferno-test-utils';
import { Component } from 'inferno';

// Custom wrapper usage
class TestWrapper extends Wrapper {
  render() {
    return (
      <div className="test-wrapper">
        {this.props.children}
      </div>
    );
  }
}

function MyComponent() {
  return <p>Component content</p>;
}

// Wrap component for testing
const wrappedComponent = (
  <TestWrapper>
    <MyComponent />
  </TestWrapper>
);

const rendered = renderIntoContainer(wrappedComponent);

// The wrapper provides additional structure for testing
const wrapperDiv = findRenderedDOMElementWithClass(rendered, 'test-wrapper');
const componentP = findRenderedDOMElementWithTag(rendered, 'p');
console.log(componentP.textContent); // "Component content"

Advanced Rendering Patterns

Testing with Context

import { renderIntoContainer, findRenderedVNodeWithType } from 'inferno-test-utils';
import { Component, createContext } from 'inferno';

const ThemeContext = createContext('light');

class ThemedComponent extends Component {
  static contextType = ThemeContext;
  
  render() {
    return <div className={`theme-${this.context}`}>Themed content</div>;
  }
}

// Render with context provider
const rendered = renderIntoContainer(
  <ThemeContext.Provider value="dark">
    <ThemedComponent />
  </ThemeContext.Provider>
);

const themedComponent = findRenderedVNodeWithType(rendered, ThemedComponent);
// Test that the component received the correct context

Testing with Refs

import { renderIntoContainer, findRenderedDOMElementWithTag, isRenderedClassComponent } from 'inferno-test-utils';
import { Component, createRef } from 'inferno';

class ComponentWithRef extends Component {
  constructor(props) {
    super(props);
    this.inputRef = createRef();
  }
  
  focus = () => {
    this.inputRef.current.focus();
  }
  
  render() {
    return (
      <div>
        <input ref={this.inputRef} type="text" />
        <button onClick={this.focus}>Focus Input</button>
      </div>
    );
  }
}

const rendered = renderIntoContainer(<ComponentWithRef />);

// Access the component instance to test ref functionality
if (isRenderedClassComponent(rendered)) {
  const input = findRenderedDOMElementWithTag(rendered, 'input');
  
  // Test that ref is properly assigned
  console.log(rendered.inputRef.current === input); // true
  
  // Test ref functionality
  rendered.focus();
  console.log(document.activeElement === input); // true
}

Testing Event Handlers

import { renderIntoContainer, findRenderedDOMElementWithTag, isRenderedClassComponent } from 'inferno-test-utils';
import { Component } from 'inferno';

class ClickableComponent extends Component {
  constructor(props) {
    super(props);
    this.state = { clicked: false };
  }
  
  handleClick = () => {
    this.setState({ clicked: true });
    if (this.props.onClick) {
      this.props.onClick();
    }
  }
  
  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.clicked ? 'Clicked!' : 'Click me'}
      </button>
    );
  }
}

// Test with mock callback
let callbackCalled = false;
const mockCallback = () => { callbackCalled = true; };

const rendered = renderIntoContainer(<ClickableComponent onClick={mockCallback} />);
const button = findRenderedDOMElementWithTag(rendered, 'button');

// Simulate click
button.click();

// Check that state updated and callback was called
if (isRenderedClassComponent(rendered)) {
  console.log(rendered.state.clicked); // true
}
console.log(callbackCalled); // true
console.log(button.textContent); // "Clicked!"

Integration with DOM Testing

import { renderIntoContainer, scryRenderedDOMElementsWithTag, findRenderedDOMElementWithTag } from 'inferno-test-utils';

function FormComponent() {
  return (
    <form>
      <input name="username" type="text" />
      <input name="password" type="password" />
      <button type="submit">Submit</button>
    </form>
  );
}

const rendered = renderIntoContainer(<FormComponent />);

// Get all form inputs
const inputs = scryRenderedDOMElementsWithTag(rendered, 'input');

// Test form interactions
inputs[0].value = 'testuser';
inputs[1].value = 'testpass';

console.log(inputs[0].value); // "testuser"
console.log(inputs[1].value); // "testpass"

// Test form submission
const form = findRenderedDOMElementWithTag(rendered, 'form');
const submitEvent = new Event('submit');
form.dispatchEvent(submitEvent);

docs

index.md

jest-integration.md

rendering.md

tree-traversal.md

type-checking.md

tile.json