Back to Repositories

Testing useDebugValue Hook Implementation in Preact

This test suite evaluates the useDebugValue hook implementation in Preact, focusing on its debugging and value formatting capabilities. The suite verifies the hook’s behavior both with and without options hooks, ensuring proper integration with Preact’s debugging infrastructure.

Test Coverage Overview

The test suite provides comprehensive coverage of the useDebugValue hook functionality:

  • Basic hook behavior without options hook present
  • Value passing to options hook
  • Custom formatter application
  • Integration with useState hook

Implementation Analysis

The testing approach employs Jest and Preact’s testing utilities to validate hook behavior. Tests utilize a combination of component rendering and spy functions to verify debug value handling. The implementation demonstrates proper setup/teardown patterns and isolated test cases.

Technical Details

Testing tools and configuration:

  • Jest test framework
  • Preact testing utilities (setupScratch, teardown)
  • Sinon for spy functionality
  • Custom test helpers for DOM manipulation
  • JSX transformation setup

Best Practices Demonstrated

The test suite exemplifies several testing best practices:

  • Proper test isolation through beforeEach/afterEach hooks
  • Clear test case organization and naming
  • Effective use of spy functions for behavior verification
  • Comprehensive edge case coverage
  • Clean setup and teardown procedures

preactjs/preact

hooks/test/browser/useDebugValue.test.js

            
import { createElement, render, options } from 'preact';
import { setupScratch, teardown } from '../../../test/_util/helpers';
import { useDebugValue, useState } from 'preact/hooks';

/** @jsx createElement */

describe('useDebugValue', () => {
	/** @type {HTMLDivElement} */
	let scratch;

	beforeEach(() => {
		scratch = setupScratch();
	});

	afterEach(() => {
		teardown(scratch);
		delete options.useDebugValue;
	});

	it('should do nothing when no options hook is present', () => {
		function useFoo() {
			useDebugValue('foo');
			return useState(0);
		}

		function App() {
			let [v] = useFoo();
			return <div>{v}</div>;
		}

		expect(() => render(<App />, scratch)).to.not.throw();
	});

	it('should call options hook with value', () => {
		let spy = (options.useDebugValue = sinon.spy());

		function useFoo() {
			useDebugValue('foo');
			return useState(0);
		}

		function App() {
			let [v] = useFoo();
			return <div>{v}</div>;
		}

		render(<App />, scratch);

		expect(spy).to.be.calledOnce;
		expect(spy).to.be.calledWith('foo');
	});

	it('should apply optional formatter', () => {
		let spy = (options.useDebugValue = sinon.spy());

		function useFoo() {
			useDebugValue('foo', x => x + 'bar');
			return useState(0);
		}

		function App() {
			let [v] = useFoo();
			return <div>{v}</div>;
		}

		render(<App />, scratch);

		expect(spy).to.be.calledOnce;
		expect(spy).to.be.calledWith('foobar');
	});
});