Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

renderHook does not work with React Magnetic DI wrapper #917

Open
haskellcamargo opened this issue Oct 26, 2022 · 1 comment
Open

renderHook does not work with React Magnetic DI wrapper #917

haskellcamargo opened this issue Oct 26, 2022 · 1 comment
Labels
bug Something isn't working

Comments

@haskellcamargo
Copy link

  • react-hooks-testing-library version: 8.0.1
  • react version: 16.13.1
  • react-dom version: 16.13.1

React Magnetic DI is a library that allows dependency injection in React components and functions for testing purposes.

It looks like the wrappers for renderHook and render (from @testing-library/react) behave quite differently. While render works with custom providers other than the React context, somehow renderHook fails to do so.

renderHook does not work when a React Magnetic DI provider is used as a wrapper.

Reproducible example

import React, { type ReactElement, type ComponentType, type ReactNode } from 'react';
import { render } from '@testing-library/react';
import { renderHook } from '@testing-library/react-hooks';
import { injectable, di, DiProvider, type Dependency } from 'react-magnetic-di';

const createRtlDiWrapper =
    (use: Dependency[]): ComponentType<{ children: ReactNode }> =>
    (props: { children: ReactNode }) =>
        <DiProvider use={use}>{props.children}</DiProvider>;

const renderHookWithDi = <TProps, TResult>(
    callback: (props: TProps) => TResult,
    dependencies: Dependency[] = [],
) =>
    renderHook<TProps, TResult>(callback, {
        wrapper: createRtlDiWrapper(dependencies) as unknown as ComponentType<TProps>,
    });

const renderWithDi = (element: ReactElement, dependencies: Dependency[] = []) =>
    render(element, {
        wrapper: createRtlDiWrapper(dependencies),
    });

const exampleDependency = () => 1;

describe('renderHook vs render', () => {
    const deps = [injectable(exampleDependency, () => 2)];

    it('should inject dependency using renderHook (but fails)', () => {
        const useExample = () => {
            di(exampleDependency);
            return { value: exampleDependency() };
        };

        const { result } = renderHookWithDi(() => useExample(), deps);

        expect(result.current).toEqual({ value: 2 });
    });

    it('should inject dependency using render', () => {
        const Example = () => {
            di(exampleDependency);
            return <span>{exampleDependency()}</span>;
        };

        const { asFragment } = renderWithDi(<Example />, deps);

        expect(asFragment()).toMatchInlineSnapshot(`
            <span>
              2
            </span>
        `);
    });
});

Expectation

Both tests would pass as the dependency should be properly injected using the DI wrapper.

Actual Behaviour

Only the second test, using render, passes, as the dependency is properly injected. The first one fails because it uses the actual implementation instead.

@haskellcamargo haskellcamargo added the bug Something isn't working label Oct 26, 2022
@andyl-ioki
Copy link

andyl-ioki commented Mar 15, 2024

@haskellcamargo
I know you opened this ticket a long while ago, but maybe it will still help others.

Your code contains a mistake:

const renderHookWithDi = <TProps, TResult>(
    callback: (props: TProps) => TResult,
    dependencies: Dependency[] = [],
) =>
    // The generics of renderHook were switched, this is the correct way:
    renderHook<TResult, TProps>(callback, {
        // No type assertion needed anymore
        wrapper: createRtlDiWrapper(dependencies),
    });

renderHook generics are first the type for the result and then followed by the type of the props. As a refactoring result your type assertion of the wrapper should not be necessary anymore. Maybe it also unreveals some other bug in your code? 🤔

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants
@haskellcamargo @andyl-ioki and others