Skip to content
This repository has been archived by the owner on Sep 30, 2019. It is now read-only.

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

License

Notifications You must be signed in to change notification settings

mihar-22/preact-testing-library

Repository files navigation

Warning

This library has now been deprecated and moved to the official testing-library/preact repo.


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 Peact 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

WARNING: This library has been deprecated, please install @testing-library/preact.

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 preact-testing-library-next

This library has peerDependencies listings for preact.

πŸ’‘ 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.

Usage

render

import { render } from 'preact-testing-library-next'

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 'preact-testing-library-next'

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 'preact-testing-library-next'
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.

Contributors

Thanks goes to these people (emoji key):

Rahim Alwer
Rahim Alwer

πŸ’» πŸ“– ⚠️

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

LICENSE

MIT

About

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

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published