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

Vertical version is not working in unit tests. #108

Open
huseyindeniz opened this issue Jan 13, 2023 · 6 comments
Open

Vertical version is not working in unit tests. #108

huseyindeniz opened this issue Jan 13, 2023 · 6 comments

Comments

@huseyindeniz
Copy link

Hi and thanks for this beautiful package. I'm having trouble with unit testing of my component which uses vertical steps. Here is a simple demonstration:

import { Box, ChakraProvider } from "@chakra-ui/react";
import { render } from "@testing-library/react";
import { Steps, Step } from "chakra-ui-steps";

import { theme } from "../../../../ui/components/Layout/Theme/theme";

import { Modal } from "./Modal";

describe("Feature: Wallet", () => {
  describe("Component: ConnectionModal/Modal", () => {
    const onClickSpy = jest.fn();

    describe("Scenario: CheckWallet", () => {
      it("should show correct step", () => {
        // Arrange
        // Act
        const { debug } = render(
          <Box>
            <Steps colorScheme="green" activeStep={0} orientation="vertical">
              <Step label="Step 1" />
              <Step label="Step 2" />
              <Step label="Step 3" />
            </Steps>
          </Box>
        );
        // Assert
      });
    });
  });
});

This test fails with the famous error: TypeError: Cannot read properties of undefined (reading 'width')

But if I only remove orientation="vertical" or make it orientation="horizontal", it works fine. Steps is correctly defined in my theme configuration on both application and test-utils file.

@jeanverster
Copy link
Owner

Hey @huseyindeniz - that error usually means that the Steps component doesn't have access to the StepsTheme object. I may be missing some code, but in the snippet above it seems like you're importing render directly from rtl, so I suspect the test itself does not have access to the chakra ui theme provider? the theme being imported is also unused.. What happens if you wrap the test with ChakraProvider ?

describe("Feature: Wallet", () => {
  describe("Component: ConnectionModal/Modal", () => {
    const onClickSpy = jest.fn();

    describe("Scenario: CheckWallet", () => {
      it("should show correct step", () => {
        // Arrange
        // Act
        const { debug } = render(
          <ChakraProvider theme={theme}>
            <Steps colorScheme="green" activeStep={0} orientation="vertical">
              <Step label="Step 1" />
              <Step label="Step 2" />
              <Step label="Step 3" />
            </Steps>
          </ChakraProvider>
        );
        // Assert
      });
    });
  });
});

@huseyindeniz
Copy link
Author

hi @jeanverster thanks for the quick feedback. My example is a modified version of my original test. Original test is more complicated and depends on lots of things. But as you can see in the modified version, I'm able to make it work by only removing orientation. My chakraprovider and it's theme correctly applied in this test. I can also see it in the debug logs. And additionally, I modified my original component and it accepts orientation prop now. I'm able to test it by setting orientation as horizontal. I'll continue with this hacky solution. But I can also show you my configuration:

test-utils.ts => basically it injects chakra provider to all my tests

import { ChakraProvider } from '@chakra-ui/react';
import { render, RenderOptions } from '@testing-library/react';
import i18n from 'i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import * as React from 'react';
import { initReactI18next, I18nextProvider } from 'react-i18next';

import { theme } from './features/ui/components/Layout/Theme/theme';

// eslint-disable-next-line import/no-named-as-default-member
i18n
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    debug: false,
    fallbackLng: 'en',
    keySeparator: false,
    nonExplicitSupportedLngs: true,
    returnEmptyString: false,
    resources: { en: {} },
  });

const AllProviders = ({ children }: { children?: React.ReactNode }) => (
  <ChakraProvider theme={theme}>
    <I18nextProvider i18n={i18n}>{children}</I18nextProvider>
  </ChakraProvider>
);

const customRender = (ui: React.ReactElement, options?: RenderOptions) =>
  render(ui, { wrapper: AllProviders, ...options });

export { customRender as render };

export { i18n };

and this my theme.ts file:

import { extendTheme } from '@chakra-ui/react';
import { StepsTheme as Steps } from 'chakra-ui-steps';

export const theme = extendTheme({
  config: {
    initialColorMode: 'system',
  },
  components: {
    Steps,
  },
  fonts: {
    heading: `'Open Sans', sans-serif`,
    body: `'Raleway', sans-serif`,
  },
});

@jeanverster
Copy link
Owner

Ah, that makes more sense! Ok I will have a look at this, thanks for raising :)

@huseyindeniz
Copy link
Author

thank you @jeanverster

@ChukwurahVictor
Copy link

Hi @jeanverster and @huseyindeniz , I keep getting
● Test suite failed to run
Cannot find module 'chakra-ui-steps' from 'src/utils/themes.ts'
whenever I try to run tests with jest.

Can you please point me to what I'm doing wrong or any resource for using chakra-ui-steps with jest?

my themes.ts file

import { extendTheme, theme } from '@chakra-ui/react';
import { StepsTheme as Steps } from 'chakra-ui-steps';

const colors = Object.freeze({
  bg: {
    white: '#fff'
  },
  brand: {
    main: '#CFE5FF',
    green: '#34D1BF',
    white: '#fff',
    gray: '#9FA2B4'
  },
  typography: {
    black: '#000',
    lightGray: '#6B7280',
    gray: '#9FA2B4',
    neutral: '#414141',
    red: '#FF0000',
    darkGray: '#757575',
    green: '#34D1BF',
    blue: '#178CD0',
    lightBlue: '#0F63FF14',
    darkBlue: '#0F63FF'
  }
});

const fontSizes = Object.freeze({
  ...theme.fontSizes,
  small: '1.2rem',
  label: '1.4rem',
  paragraph: '1.6rem',
  heading6: '1.6rem',
  heading5: '1.9rem',
  heading4: '2.4rem',
  heading3: '2.9rem',
  heading2: '3.5rem',
  heading1: '4.3rem'
});

const fontWeights = Object.freeze({
  ...theme.fontWeights,
  regular: 500,
  medium: 550,
  semiBold: 600,
  bold: 700,
  bolder: 800,
  extraBold: 900
});

const breakpoints = Object.freeze({
  '2xs': '320px', //@media(min-width:320px)
  xs: '375px', //@media(min-width:375px)
  sm: '530px', //@media(min-width:480px)
  md: '840px', //@media(min-width:770px)
  lg: '1024px', //@media(min-width:1024px)
  xl: '1200px', //@media(min-width:1200px)
  '2xl': '1600px', //@media(min-width:1600px)
  '3xl': '1900px' //@media(min-width:1900px)
});

const styles = Object.freeze({
  global: {
    html: {
      fontSize: '62.5%'
    },
    body: {
      fontFamily: "'Montserrat', sans-serif",
      color: '#000',
      backgroundColor: '#fff',
      fontSize: '1.6rem',
      lineHeight: '1.6',
      fontWeight: '500'
    },
    '*, *::before, *::after': {
      margin: '0',
      padding: '0',
      boxSizing: 'border-box'
    }
  }
});

const components = {
  Switch: {
    baseStyle: {
      track: {
        bg: 'gray',
        _checked: {
          bg: '#34D1BF'
        }
      }
    }
  }
};

export default extendTheme({
  breakpoints,
  colors,
  styles,
  fontWeights,
  fontSizes,
  components: {
    ...components,
    Steps
  }
});

my login.test.tsx file

import { QueryClientProvider, QueryClient } from '@tanstack/react-query';
import { ChakraProvider } from '@chakra-ui/react';
import { render, screen } from '@testing-library/react';
import Login from 'src/pages/auth/login';
import themes from 'src/utils/themes';
import { RouterContext } from 'next/dist/shared/lib/router-context';
import { createMockRouter } from 'src/utils/test/createMockRouter';


Object.defineProperty(window, 'matchMedia', {
  writable: true,
  value: jest.fn().mockImplementation(query => ({
    matches: false,
    media: query,
    onchange: null,
    addListener: jest.fn(), // deprecated
    removeListener: jest.fn(), // deprecated
    addEventListener: jest.fn(),
    removeEventListener: jest.fn(),
    dispatchEvent: jest.fn()
  }))
});

describe('Login Page - Rendering', () => {
  it('should have Login to Your Account text', () => {
    const queryClient = new QueryClient();

    render(
      <QueryClientProvider client={queryClient}>
        <ChakraProvider theme={themes}>
          <RouterContext.Provider value={createMockRouter()}>
            <Login />
          </RouterContext.Provider>
        </ChakraProvider>
      </QueryClientProvider>
    );

    const loginText = screen.getByText(/Login to Your Account/i);
    expect(loginText).toBeInTheDocument();
  });
});

@huseyindeniz
Copy link
Author

I believe you need to add some code into test-utils.ts file. You can see it in my previous comment.

#108 (comment)

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

3 participants