获取错误- TypeError:(0,_reactRedux.connect)不是函数

ddarikpa  于 2023-10-19  发布在  React
关注(0)|答案(1)|浏览(99)

我正在为react文件编写测试用例。这里是react文件。

import React, { useEffect } from 'react';
import Layout from 'components/Layout';
import Section from 'components/Section/section';
import PropTypes from 'prop-types';
import { ReactComponent as CrownIcon } from 'assets/images/crown.svg';
import { ReactComponent as LeaderboardLayout } from 'assets/images/leaderboard/leaderboard.svg';
import { useSelector } from 'react-redux';
import { useGetAnalyticsOverviewQuery } from 'app/services/home';
import Snackbar from 'components/Snackbar';
import { convertDate } from 'utils/utilities';
import * as microsoftTeams from '@microsoft/teams-js';
import { identify, track } from 'utils/segment';
import EmptyLeaderboardState from 'components/EmptyLeaderboardState';
import { useGetLeaderboardQuery } from 'app/services/leaderboard';
import Standings from './Standings';
import styles from './styles.module.scss';

let overview;
const Leaderboard = (props) => {
  const { isPublic, taskModule, workspace } = props;
  const { data: leaderboard = { lastUpdatedAt: '' } } = useGetLeaderboardQuery();

  if (!isPublic) {
    const { data, isFetching } = useGetAnalyticsOverviewQuery();
    if (!isFetching) {
      overview = data;
    }
  }

  useEffect(() => {
    microsoftTeams.initialize();
    microsoftTeams.appInitialization.notifySuccess();
  }, []);

  const userDetails = useSelector((state) => state.user);
  const neverUsedTrivia = !overview?.gamesPlayed;

  if (!userDetails.loading) {
    const { _id, loggedUsersCount = 0 } = userDetails;

    if (_id) {
      identify(_id, { 'Unique Logged In Users': loggedUsersCount });
      track('Visit Dashboard', {
        distinct_id: _id,
        Page: 'Leaderboard',
        Date: new Date(),
        'Unique Logged In Users': loggedUsersCount
      });
    }
  }

  return (
    <Layout name='Leaderboard' isPublic={isPublic}>
      {isPublic && !taskModule && (
        <Snackbar
          text='You need to login to view your rankings'
          actionText='Login now'
          type='info'
          performAction={() => {
            window.location.href = `${
              window.location.pathname.includes('/tabs') ? '/tabs' : ''
            }/login`;
          }}
        />
      )}
      {!(overview && neverUsedTrivia && !isPublic) && (
        <div className={styles.title}>
          <CrownIcon />
          Leaderboard
        </div>
      )}
      <Section
        title=''
        noBorder
        style={{
          marginTop: 0,
          flexGrow: 1,
          marginBottom: '5rem',
          padding: neverUsedTrivia && !isPublic && '0',
          margin: neverUsedTrivia && !isPublic && '0'
        }}
      >
        {overview && neverUsedTrivia && !isPublic && (
          <div className={styles.neverUsed}>
            <EmptyLeaderboardState plan={userDetails.plan} teamId={userDetails?.user?.workspace} />
            <LeaderboardLayout width='100%' height='100%' />
          </div>
        )}

        {(!neverUsedTrivia || isPublic) && (
          <div className={styles.standingsWrapper}>
            {userDetails.plan === 'BASIC' && leaderboard.lastUpdatedAt && (
              <div className={styles.header}>
                <div className={styles.lastUpdatedDate}>
                  ⚠️ Your Leaderboard was last updated on ({convertDate(leaderboard.lastUpdatedAt)})
                </div>
              </div>
            )}
            <Standings plan={userDetails.plan} isPublic={isPublic} workspace={workspace} />
          </div>
        )}
      </Section>
    </Layout>
  );
};

Leaderboard.propTypes = {
  workspace: PropTypes.string,
  isPublic: PropTypes.bool,
  taskModule: PropTypes.bool
};

Leaderboard.defaultProps = {
  workspace: '',
  isPublic: false,
  taskModule: false
};

export default Leaderboard;

这是React代码文件。
下面是我编写的测试代码文件。

import React from 'react';
import { render, screen, act } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom';
import { Provider, useSelector, connect } from 'react-redux';
import store from 'app/store';
import Leaderboard from 'pages/Leaderboard';
import { configureStore } from '@reduxjs/toolkit';
import { identify, track } from 'utils/segment';

jest.mock('components/Layout', () => ({ children }) => <div data-testid='layout'>{children}</div>);
jest.mock('components/Snackbar', () => ({ text, actionText, type, performAction }) => (
  <div data-testid='snackbar'>
    {text} {actionText} {type}
    <button onClick={performAction}>Login now</button>
  </div>
));

jest.mock('components/EmptyLeaderboardState', () => {
  return () => <div data-testid="empty-leaderboard-state-mock">Mocked EmptyLeaderboardState</div>;
});

jest.mock('assets/images/leaderboard/leaderboard.svg', () => {
  return () => <div data-testid="leaderboard-layout-mock">Mocked LeaderboardLayout</div>;
});

jest.mock('assets/images/crown.svg', () => {
  const React = require('react');
  return {
    ReactComponent: () => <svg data-testid='crown-icon'></svg>
  };
});

jest.mock('utils/segment', () => ({
  identify: jest.fn(),
  track: jest.fn()
}));

jest.mock('react-redux', () => ({
  useSelector: jest.fn(),
}));

describe('Leaderboard Component', () => {
  const mockStore = {
    user: {
      _id: 'user123',
      loggedUsersCount: 5,
      plan: 'BASIC'
    }
  };

  beforeEach(() => {
    jest.clearAllMocks();
  });

  it('renders without crashing', () => {
    render(
      <Provider store={store}>
        <Leaderboard />
      </Provider>
    );
    expect(screen.getByTestId('layout')).toBeInTheDocument();
  });

  it(`renders Snackbar component if isPublic === true and taskModule === false`, () => {
    render(
      <Provider store={store}>
        <Leaderboard isPublic={true} taskModule={false} />
      </Provider>
    );

    expect(screen.getByTestId('snackbar')).toBeInTheDocument();

    userEvent.click(screen.getByText('Login now'));
    expect(window.location.href).toContain(`http://localhost/`);
  });

  it(`Renders Crown Icon and 'Leaderboard' according to specified conditions`, () => {
    render(
      <Provider store={store}>
        <Leaderboard overview={{ gamesPlayed: 0 }} />
      </Provider>
    );
    expect(screen.getByTestId('crown-icon')).toBeInTheDocument();
    expect(screen.getByText('Leaderboard')).toBeInTheDocument();
  });

  it('Handling user tracking and identification', () => {
    useSelector.mockReturnValue({
      user: {
        _id: 'user123',
        loggedUsersCount: 5,
        plan: 'BASIC'
      }
    });

    render(
      <Provider store={store}>
        <Leaderboard />
      </Provider>
    );

    expect(identify).toHaveBeenCalledWith('user123', {
      'Unique Logged In Users': 5
    })

    expect(track).toHaveBeenCalledWith('Visit Dashboard', {
      distinct_id: 'user123',
      Page: 'Leaderboard',
      Date: expect.any(Date),
      'Unique Logged In Users': 5
    });
  });

  it('renders EmptyLeaderboardState and LeaderboardLayout when conditions are met', () => {
    const props = {
      overview: {
        gamesPlayed: 10,
        highestScore: 500
      },
      neverUsedTrivia: true,
      isPublic: false,
      userDetails: {
        plan: 'BASIC',
        user: {
          workspace: 'team123'
        }
      }
    };

    render(
      <Provider store={store}>
        <Leaderboard {...props} />
      </Provider>
    );

    expect(screen.getByTestId('empty-leaderboard-state')).toBeInTheDocument();
    expect(screen.getByTestId('leaderboard-layout')).toBeInTheDocument();
  });
});

当我试图检查测试文件的覆盖率时,我得到了以下错误。
Error Image我只能对测试文件进行更改,不能在其他地方进行更改。我也不能创建一个新文件。请帮助我解决这个错误。

pkmbmrz7

pkmbmrz71#

您正在导入:import { Provider, useSelector, connect } from 'react-redux';
但你只是在嘲笑我的用处:

jest.mock('react-redux', () => ({
  useSelector: jest.fn(),
}));

错误提示:connect不是函数。因为你已经为react-redux创建了一个mock,它只有一个useObject方法。你要做的是这样的事情:

jest.mock('react-redux', () => {
  return {
    ...jest.requireActual('react-redux'),
    useSelector: jest.fn(),
    //useDispatch: () => jest.fn(), if you also want to mock dispatch
  };
});

这样,您仍然拥有从react-redux到requireActual的所有原始方法。这应该解决了错误。
另外,您正在导入configureStore,但您没有使用它。创建一个mockStore如下:

const mockStore = {
    user: {
      _id: 'user123',
      loggedUsersCount: 5,
      plan: 'BASIC'
    }
  };

在描述中,但在任何测试之外。我不知道你想做什么,但你也不用那个。
相反,您似乎正在使用您正在导入的实际商店:import store from 'app/store';。这是一种不好的做法,因为您不会用干净的存储区开始每个测试,这可能会导致问题。你应该在每个单元测试之前创建一个新的存储区。我想这就是你导入configureStore的原因。

相关问题