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

Use a class for class based mock components #3

Open
k2snowman69 opened this issue Jan 1, 2023 · 1 comment
Open

Use a class for class based mock components #3

k2snowman69 opened this issue Jan 1, 2023 · 1 comment
Assignees

Comments

@k2snowman69
Copy link
Member

Right now we force cast a function component to class component for class based systems. However if we need to implement a class based mock for some reason, the following code should be close. However I want to hold off on this until we get a bug that tells us we need to.

import { jest } from "@jest/globals";
import React from "react";

const map = new Map<any, jest.Mock<NonNullable<React.Component<any>["shouldComponentUpdate"]>>>();

type CreateMockClassComponentOptions = {
  elementType: string;
};

/**
 * Generates a new mock component with the prop signature provided.
 * @param options The different configuration options you wish to use
 * @returns
 */
export function createMockClassComponent<TProps>({
  elementType = "div",
}: CreateMockClassComponentOptions): typeof React.Component<TProps> {
  const mockShouldComponentUpdate = jest.fn((props: TProps) => {
    return true;
  });
  class MockComponent extends React.Component<TProps> {
    public static mockClear = () => {
      mockShouldComponentUpdate.mockClear();
    };
    componentDidMount(): void {
      mockShouldComponentUpdate(this.props);
    }
    shouldComponentUpdate = mockShouldComponentUpdate;
    render() {
      return React.createElement(elementType, this.props);
    }
  }

  map.set(MockComponent, mockShouldComponentUpdate);

  return MockComponent;
}

export function getMockClassComponentPropCalls<TProps>(mockComponent: typeof React.Component<TProps>): TProps[] {
  const mockShouldComponentUpdate = map.get(mockComponent);
  if (mockShouldComponentUpdate == null) {
    throw new Error("getMockClassComponentPropCalls requires createMockClassComponent to have been called");
  }
  const propCalls = mockShouldComponentUpdate.mock.calls.map((value) => {
    return value[0];
  });
  return propCalls;
}
@k2snowman69 k2snowman69 self-assigned this Jan 1, 2023
@k2snowman69
Copy link
Member Author

Oh and options should be updated too:

const defaultOptions: Required<Options> = {
  elementType: "div",
  componentType: "function",
};

export type Options = {
  /**
   * The HTMLElement type to render. Default is div.
   */
  elementType?: string;
  /**
   * The render style of the mock component to create. Default is function.
   */
  componentType?: "class" | "function";
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant