JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 81967
  • Score
    100M100P100Q160581F
  • License MIT

Simple and complete Preact DOM testing utilities that encourage good testing practices.

Package Exports

  • @testing-library/preact

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@testing-library/preact) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Preact Testing Library

poodle

Simple and complete Preact DOM testing utilities that encourage good testing practices.

Inspired completely by react-testing-library

Build Status Code Coverage All Contributors PRs Welcome Code of Conduct version downloads MIT License Preact Slack Community Commitzen


Table of Contents

The Problem

You want to write maintainable tests for your Preact components. As a part of this goal, you want your tests to avoid including implementation details of your components and rather focus on making your tests give you the confidence for which they are intended. As part of this, you want your testbase to be maintainable in the long run so refactors of your components (changes to implementation but not functionality) don't break your tests and slow you and your team down.

The Solution

The Preact Testing Library is a very lightweight solution for testing Preact components. It provides light utility functions on top of preact/test-utils, in a way that encourages better testing practices. Its primary guiding principle is:

The more your tests resemble the way your software is used, the more confidence they can give you.

Installation

This module is distributed via npm which is bundled with node and should be installed as one of your project's devDependencies:

npm install --save-dev @testing-library/preact

This library has peerDependencies listings for preact >= 10.

💡 You may also be interested in installing @testing-library/jest-dom so you can use the custom jest matchers.

📝 This library supports Preact X (10.x). It takes advantage of the act test utility in preact/test-utils to enable both Preact Hook and Class components to be easily tested.

📝 If you're looking for a solution for Preact 8.x then install preact-testing-library.

Usage

render

import { render } from '@testing-library/preact'

const { returns } = render(<YourComponent />, { arguments })
Arguments Description Default
container The HTML element the component is mounted to. baseElement
baseElement The root HTML element to which the container is appended to. document.body
queries Queries to bind to the baseElement. See getQueriesForElement. null
hydrate Used when the component has already been mounted and requires a rerender. Not needed for most people. The rerender function passed back to you does this already. false
wrapper A parent component to wrap YourComponent. null
Returns Description
container The HTML element the component is mounted to.
baseElement The root HTML element to which the container is appended to.
debug Logs the baseElement using prettyDom.
unmount Unmounts the component from the container.
rerender Calls render again passing in the original arguments and sets hydrate to true.
asFragment Returns the innerHTML of the container.
...queries Returns all query functions to be used on the baseElement. If you pass in query arguments than this will be those, otherwise all.

cleanup

Unmounts the component from the container and destroys the container.

📝 When you import anything from the library, this automatically runs after each test. If you'd like to disable this then set process.env.PTL_SKIP_AUTO_CLEANUP to true when running your tests.

import { render, cleanup } from '@testing-library/preact'

afterEach(() => {
  cleanup
}) // Default on import: runs it after each test.

render(<YourComponent />)

cleanup() // Or like this for more control.

act

Just a convenience export that points to preact/test-utils/act. All renders and events being fired are wrapped in act, so you don't really need this. It's responsible for flushing all effects and rerenders after invoking it.

📝 If you'd love to learn more, checkout this explanation. Even thought it's for React, it gives you an idea of why it's needed.

fireEvent

Passes it to the @testing-library/dom fireEvent. It's also wrapped in act so you don't need to worry about doing it.

📝 Keep in mind mainly when using h / Preact.createElement that React uses a Synthetic event system, and Preact uses the browser's native addEventListener for event handling. This means events like onChange and onDoubleClick in React, are onInput and onDblClick in Preact. The double click example will give you an idea of how to test using those functions.

const cb = jest.fn();

function Counter() {
    useEffect(cb);

    const [count, setCount] = useState(0);

    return <button onClick={() => setCount(count + 1)}>{count}</button>;
}

const { container: { firstChild: buttonNode }, } = render(<Counter />);

// Clear the first call to useEffect that the initial render triggers.
cb.mockClear();

// Fire event Option 1.
fireEvent.click(buttonNode);

// Fire event Option 2.
fireEvent(
button,
new Event('MouseEvent', {
  bubbles: true,
  cancelable: true,
  button: 0,
});

expect(buttonNode).toHaveTextContent('1');
expect(cb).toHaveBeenCalledTimes(1);
const handler = jest.fn()

const {
  container: { firstChild: input },
} = render(<input type="text" onInput={handler} />)

fireEvent.input(input, { target: { value: 'a' } })

expect(handler).toHaveBeenCalledTimes(1)
const ref = createRef()
const spy = jest.fn()

render(
  h(elementType, {
    onDblClick: spy,
    ref,
  }),
)

fireEvent['onDblClick'](ref.current)

expect(spy).toHaveBeenCalledTimes(1)

@testing-library/dom

This library re-exports everything from @testing-library/dom. See the documentation to see what goodies you can use. The helper functions like wait can be particularly useful.

Example

Component

Note: Preact Testing Library works with both Preact Hooks and Classes. Your tests will be the same however you write your components.

function HiddenMessage({ children }) {
  const [showMessage, setShowMessage] = useState(false)

  return (
    <div>
      <label htmlFor="toggle">Show Message</label>
      <input
        id="toggle"
        type="checkbox"
        onChange={e => setShowMessage(e.target.checked)}
        checked={showMessage}
      />
      {showMessage ? children : null}
    </div>
  )
}

Test

// NOTE: jest-dom adds handy assertions to Jest and it is recommended, but not required.
import '@testing-library/jest-dom/extend-expect'

import { h } from 'preact'
import { render, fireEvent } from '@testing-library/preact'
import HiddenMessage from '../hidden-message'

test('shows the children when the checkbox is checked', () => {
  const testMessage = 'Test Message'

  const { queryByText, getByLabelText, getByText } = render(
    <HiddenMessage>{testMessage}</HiddenMessage>,
  )

  // query* functions will return the element or null if it cannot be found.
  // get* functions will return the element or throw an error if it cannot be found.
  expect(queryByText(testMessage)).toBeNull()

  // The queries can accept a regex to make your selectors more resilient to content tweaks and changes.
  fireEvent.click(getByLabelText(/show/i))

  // .toBeInTheDocument() is an assertion that comes from jest-dom.
  // Otherwise you could use .toBeDefined().
  expect(getByText(testMessage)).toBeInTheDocument()
})

Hooks

If you are interested in testing a custom hook, the preact-hooks-testing-library will be coming soon.

It is not recommended to test single-use custom hooks in isolation from the components where it's being used. It's better to test the component that's using the hook rather than the hook itself. The preact-hooks-testing-library will be intended to be used for reusable hooks/libraries.

Guiding Principles

We try to only expose methods and utilities that encourage you to write tests that closely resemble how your Preact components are used.

Utilities are included in this project based on the following guiding principles.

Docs

For more information checkout:

Even though they are all React based examples, it should be close to identical in Preact. Take note of the differences between React and Preact.

Issues

Looking to contribute? Look for the Good First Issue label.

🐛 Bugs

Please file an issue for bugs, missing documentation, or unexpected behavior.

See Bugs

💡 Feature Requests

Please file an issue to suggest new features. Vote on feature requests by adding a 👍. This helps maintainers prioritize what to work on.

See Feature Requests

❓ Questions

For questions related to using the library, please visit a support community instead of filing an issue on GitHub.

Contributors

Thanks goes to these people (emoji key):

Kent C. Dodds
Kent C. Dodds

💻 📖 ⚠️
Ants Martian
Ants Martian

💻 📖 ⚠️
Rahim Alwer
Rahim Alwer

💻 📖 ⚠️ 🚇

This project follows the all-contributors specification. Contributions of any kind welcome!

LICENSE

MIT