A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/reactwg/react-18/discussions/17 below:

Testing with Reusable State with StrictMode · reactwg/react-18 · Discussion #17 · GitHub

Overview

If you have not yet read the previous post about "How to support Reusable State in Effects", you can find it here.

StrictMode can be enabled for tests too. Tests that assert things about effects are somewhat uncommon, but the most common types of assertions are covered below (along with suggestions for how to update them).

Verifying an effect occurred at least once (e.g. on mount).

If the primary purpose of your test is to verify that a side effect is called on-mount, you can avoid asserting on the number of times that it’s called.

// If the code you're testing looks like this...
function Example({ mountCallback }) {
  useEffect(() => {
    mountCallback();
  }, [mountCallback]);
  // ...
}

render(<ComponentYouAreTesting mountCallback={mountCallback} />);

// Won't work (unless a ref is used) ✘
expect(mountCallback).toHaveBeenCalledTimes(1);

// Will work ✓
expect(mountCallback).toHaveBeenCalled();
Counting the number of times a component rendered.

Tests that count renders to prevent cascading updates can make use of the Profiler API. (The Profiler’s commit hooks are called once per commit.)

// If the code you're testing looks like this...
function Example({ mountCallback }) {
  useEffect(() => {
    mountCallback();
  }, [mountCallback]);
  // ...
}

// Won't work (unless a ref is used) ✘
render(<Example mountCallback={mountCallback} {...props} />);
expect(mountCallback).toHaveBeenCalledTimes(1);

// Will work ✓
const onRender = jest.fn();
render(
  <Profiler id="test" onRender={onRender}>
    <Example {...props} />
  </Profiler>
);
expect(onRender).toHaveBeenCalledTimes(1);
Counting how often an effect has run.

Tests that count the specific number of times a side effect is called (e.g. that it’s called only when some condition changes) can be written, but require special consideration for mounting.

// If the code you're testing looks like this...
function SomeComponent({ someEffect, someConditional }) {
  useEffect(() => {
    someEffect();
  }, [someConditional, someEffect]);

  // ...
}

const someEffect = jest.fn();

// The effect is expected to be called on mount.
// It will be called more than once if React runs the effect more than once.
render(<SomeComponent someEffect={someEffect} someConditional={1} />);

// Ignore mount for simplicity (since React calls the effect twice on mount).
someEffect.mockReset();

// Confirm the effect is not called after update if condition doesn't change.
render(<SomeComponent someEffect={someEffect} someConditional={1} />);
expect(someEffect).not.toBeCalled();

// Confirm the effect is called on update if condition does change.
render(<SomeComponent someEffect={someEffect} someConditional={2} />);
expect(someEffect).toBeCalledTimes(1);

If it’s important for the effect to only run once on mount, a ref can be used as shown above and our test can be written to verify that behavior.

function SomeComponent({ someEffect, someConditional }) {
  const prevConditionalRef = useRef({});

  useEffect(() => {
    // Only call our callback once when a value changes.
    if (prevConditionalRef.current !== someConditional) {
      prevConditionalRef.current = someConditional;

      someEffect();
    }
  }, [someConditional, someEffect]);

  // ...
}

const someEffect = jest.fn();

render(<SomeComponent someEffect={someEffect} someConditional={1} />);
expect(someEffect).toBeCalledTimes(1);

If your test doesn’t match one of the patterns shown above– ask us and we’ll help.

Related posts

For more information on supporting Reusable State in StrictMode, see:


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4