V
V
vovashaplin2021-01-10 18:31:58
React
vovashaplin, 2021-01-10 18:31:58

Trouble testing alert component with redux?

Testing an Alert that closes after 1 second. But when I do tests, it doesn't hide. I think the problem is in the hide function, which for some reason does not hide alert in tests.
This is alert.ts

import { hide } from "@/store/actions/alert";
import { getAlertInfo } from "@/store/selectors";

const Alert: React.FC = () => {
  const { text, type, isNotClose } = useSelector(getAlertInfo);
  const dispatch = useDispatch();

  useEffect(() => {
    if (isNotClose) {
      return;
    }
    setTimeout(hideHandler, 1000);
  }, [text]);

  const hideHandler = () => {
    dispatch(hide());
  };

  if (!text) return null;

  return (
    <Wrapper data-testid="alert">
      <Content type={type}>
        <Close onClick={hideHandler} />
        <Text>{text}</Text>
        <button onClick={() => hide()}>hide</button>
      </Content>
    </Wrapper>
  );
};

These are tests in which the last line gives an error, because the alert is not hidden
import Alert from "./index";
import { alertReducer as reducer } from "@/store/reducers/alert";

jest.useFakeTimers();
afterEach(cleanup);

const renderWithRedux = (
  ui: React.ReactElement,
  { state, store = createStore(reducer, state) }: any = {}
) => {
  return {
    ...render(<Provider store={store}>{ui}</Provider>),
    store,
  };
};

// ...some code

  it("last test + close alert after 1000ms", async () => {
    const expectedText = "Hello, I'm Alert!";
    renderWithRedux(<Alert />, {
      state: {
        alert: {
          text: expectedText,
          typeOf: "success",
          IsNotClose: false,
        },
      },
    });

    const item = await screen.findByText(expectedText);
    expect(item).toBeInTheDocument();
    expect(screen.getByTestId("alert")).toBeInTheDocument();

    jest.advanceTimersByTime(1200);

    screen.debug();
    expect(screen.queryByTestId("alert")).not.toBeInTheDocument();
  });

Reducer with @/store/reducers/alert path:
import { PropertiesType } from '@/types/action';
import * as actions from './../actions/alert';

const initialState = {
    text: null as string | null,
    typeOf: 'success' as "success" | "warning" | "error",
    IsNotClose: false
};

type InititalStateType = typeof initialState;

type AlertActionsTypes = ReturnType<PropertiesType<typeof actions>>

export const alertReducer = (state = initialState, action: AlertActionsTypes): InititalStateType => {
    switch (action.type) {
        case 'ALERT_SHOW':
            return { ...state, text: action.text, typeOf: action.typeOf, IsNotClose: action?.IsNotClose ? true : false }
        case 'ALERT_HIDE':
            return { ...state, text: null }
        default:
            return state;
    }
}

Actions with @/store/actions/alert path
export type typeOfType = 'success' | 'warning' | 'error'
export const hide = () => ({ type: 'ALERT_HIDE' } as const);
export const show = (text: string, typeOf: typeOfType = 'success', IsNotClose?: boolean) => ({ type: 'ALERT_SHOW', text, typeOf, IsNotClose } as const);

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question