Hone logo
Hone
Problems

Testing useContext with Jest and TypeScript

Testing components that utilize useContext can be tricky because you need to mock the context value to isolate the component being tested. This challenge focuses on creating a Jest test suite for a React component that consumes a context, ensuring that the component renders correctly based on different mocked context values. This is crucial for verifying component behavior and ensuring it reacts appropriately to changes in context.

Problem Description

You are tasked with creating a Jest test suite for a React component called MyComponent that consumes a context called MyContext. MyContext provides a theme property, which is a string representing the current theme (e.g., "light", "dark"). MyComponent displays a message based on the current theme.

Your test suite should:

  1. Mock MyContext: Use jest.mock to mock the MyContext context.
  2. Render MyComponent: Render MyComponent with different mocked context values.
  3. Assert Correct Rendering: Assert that MyComponent renders the expected message based on the mocked theme value.
  4. Handle Edge Cases: Include a test case where the theme is an unexpected value (e.g., null, undefined, or a number) to ensure the component handles it gracefully (e.g., by displaying a default message).

Key Requirements:

  • The test suite must be written in TypeScript.
  • The tests must use jest.mock to mock the context.
  • The tests must use appropriate Jest assertions to verify the component's rendering.
  • The tests must cover the specified edge case.

Expected Behavior:

The test suite should pass if it correctly mocks the context, renders the component with different context values, and asserts that the component displays the expected message for each value. The edge case test should verify that a default message is displayed when the theme is an unexpected value.

Examples

Example 1:

Input: Mocked context value: { theme: "light" }
Output: The component renders the message "The theme is light."
Explanation: The component receives the "light" theme and displays the corresponding message.

Example 2:

Input: Mocked context value: { theme: "dark" }
Output: The component renders the message "The theme is dark."
Explanation: The component receives the "dark" theme and displays the corresponding message.

Example 3:

Input: Mocked context value: { theme: null }
Output: The component renders the message "The theme is unknown."
Explanation: The component receives a null theme value and displays the default "unknown" message.

Constraints

  • You must use jest.mock to mock the context. Directly modifying the context provider is not allowed.
  • The component MyComponent is provided below. You should not modify it.
  • The context MyContext is provided below. You should not modify it.
  • The test suite should be concise and readable.
  • All tests must pass.

Notes

Consider using screen.getByText or similar methods from @testing-library/react to query the rendered component and make assertions. Think about how to effectively mock the context provider to control the theme value during testing. Remember to import the necessary modules from Jest and React Testing Library. The component is designed to handle unexpected theme values gracefully, so your tests should reflect that.

// MyContext.tsx
import { createContext, useContext } from 'react';

interface MyContextType {
  theme: string;
}

const MyContext = createContext<MyContextType | undefined>(undefined);

export const MyContextProvider = ({ children, theme }: { children: React.ReactNode; theme: string }) => {
  return (
    <MyContext.Provider value={{ theme }}>
      {children}
    </MyContext.Provider>
  );
};

export const useMyContext = () => {
  const context = useContext(MyContext);
  if (!context) {
    throw new Error("useMyContext must be used within a MyContextProvider");
  }
  return context;
};

// MyComponent.tsx
import React from 'react';
import { useMyContext } from './MyContext';

const MyComponent: React.FC = () => {
  const { theme } = useMyContext();

  let message: string;
  if (theme === "light") {
    message = "The theme is light.";
  } else if (theme === "dark") {
    message = "The theme is dark.";
  } else {
    message = "The theme is unknown.";
  }

  return <div>{message}</div>;
};

export default MyComponent;
Loading editor...
typescript