0

我在尝试使用 react-testing-library 渲染 react-redux-firebase 连接组件时遇到了很多麻烦。我总是遇到一个[TypeError: ref.collection is not a function]错误,一旦我尝试运行它就会导致我的测试崩溃。

组件:

@firestoreConnect((props, {getState}) => {
  const {auth} = getState();
  const {clientId} = auth.data;

  return [
    {
      collection: 'clients',
      doc: clientId,
      subcollections: [{collection: 'users'}]
    },
    {
      collection: 'clients',
      doc: clientId,
      subcollections: [{collection: 'scripts'}]
    },
    {
      collection: 'clients',
      doc: clientId,
      subcollections: [{collection: 'teams'}]
    },
    {
      collection: 'clients',
      doc: clientId,
      subcollections: [{collection: 'lists'}],
      where: [
        ['status', '==', 'complete'],
        ['archived', '==', false]
      ]
    }
  ];
})
@connect(({auth, profile, ggFirestore}, {params}) => {
  const {clientRef, displayName, legacyClientId, permissions} = auth.data;
  return {
    users: ggFirestore.getIn(['users']),
    lists: ggFirestore.getIn(['lists']),
    scripts: ggFirestore.getIn(['scripts']),
    teams: ggFirestore.getIn(['teams']),
    profile,
    clientRef,
    displayName,
    legacyClientId,
    permissions,
    params
  };
})
export default class CampaignForm extends Component {
  constructor(props) {
    super(props);
    const campaignTypes = {
      '1to1sms': [
        VisibilityStep,
        TemplatesStep,
        ListsStep,
        OwnerStep,
        NameStep,
        SummaryStep
      ],
      '1to1email': [
        NameStep,
        TemplatesStep,
        ListsStep,
        SendEmailsStep,
        SuccessStep
      ]
    };

    this.state = {
      step: 0,
      contactTypeSteps: campaignTypes[props.params.contactType],
      campaignId: '',
      draftCampaignId: '',
      type: 'organizing',
      isProcessing: false,
      confirmSummary: false,
      contactType: props.params.contactType
    };
  }

...

  render() {
    const {
      step,
      success,
      error,
      contactTypeSteps,
      campaignId,
      draftCampaignId,
      isProcessing,
      confirmSummary,
      contactType
    } = this.state;

    const {params, lists, users, teams, scripts, profile} = this.props;
    const isLastStep =
      contactTypeSteps.length === step + 1 ||
      (contactType === '1to1email' && step === 3);
    const StepComponent = contactTypeSteps[step];
    if (profile && profile.role === 'volunteer') {
      return <PermissionDenied />;
    }
    if (users && lists && scripts && teams) {
      return (
        <div className="top-spacer" date-testid="_campaign-form">
          <SuccessMessage
            message={success}
            handleDismiss={() => {
              this.setState({success: null});
            }}
          />
          <ErrorMessage
            error={error}
            handleDismiss={() => {
              this.setState({error: null});
            }}
          />
          {confirmSummary ? (
            <SuccessStep
              campaignId={campaignId ? campaignId : draftCampaignId}
              campaignType={params.contactType}
              {...this.state}
              {...this.props}
              isOrganizer={profile && profile.role === 'organizer'}
            />
          ) : (
            <StepComponent
              handleNext={
                isLastStep ? ::this.handleFinalSubmit : ::this.handleNextClick
              }
              handlePrev={::this.handleBackClick}
              handleChange={::this.handleChange}
              contactType={params.contactType}
              isLastStep={isLastStep}
              isProcessing={isProcessing}
              {...this.props}
              {...this.state}
              isOrganizer={profile && profile.role === 'organizer'}
            />
          )}
        </div>
      );
    }
    return <Loading />;
  }
}

我的测试包装器:

import '@testing-library/jest-dom/extend-expect';
import 'firebase/firestore';

import { render } from '@testing-library/react';
import firebase from 'firebase';
import { createMemoryHistory } from 'history';
import React from 'react';
import { Provider } from 'react-redux';
import { reactReduxFirebase } from 'react-redux-firebase';
import { MemoryRouter } from 'react-router-dom';
import { compose, createStore } from 'redux';
import { reduxFirestore } from 'redux-firestore';

import rootReducer from '../ducks';

jest.mock('../store/fbTestConfig', () => ({
  firebase: {
    firestore: jest.fn(() => ({})),
    initializeApp: jest.fn(() => {})
  }
}));

const mockStore = compose(
  reactReduxFirebase(firebase, {}),
  reduxFirestore(firebase)
)(createStore);

export function renderWithRedux(
  Component,
  {
    initialState,
    store = mockStore(rootReducer, initialState),
    route = '/',
    history = createMemoryHistory({initialEntries: [route]})
  } = {}
) {
  return {
    ...render(
      <Provider store={store}>
        <MemoryRouter initialEntries={[route]}>{Component}</MemoryRouter>
      </Provider>,
      {}
    ),
    store,
    history
  };
}

我的测试:

import '@testing-library/jest-dom/extend-expect';

import { cleanup } from '@testing-library/react';
import React from 'react';

import CampaignForm from '../../components/Campaigns/CampaignForm';
import { renderWithRedux } from '../renderWithRedux';

beforeEach(cleanup);

test('CampaignForm renders', () => {
  const {debug} = renderWithRedux(<CampaignForm />, {
    route: 'organize/1to1sms'
  });
  debug();
});

我尝试控制台记录组件,它看起来像由 firestoreConnect 正确包装,但ref密钥始终设置为 null。我试过到处寻找某种答案,但没有运气。任何帮助将不胜感激!

4

1 回答 1

0

所以我终于想通了!该组件期待我在设置测试时没有正确播种的道具。

在我的组件中,我有以下几行:

const {auth} = getState();
const {clientId} = auth.data;

其中 auth 是我的应用程序状态的一部分。它的初始状态是一个空地图,所以当我试图clientId从那里拉出来并用它来获取我的收藏时,它抛出了一个错误。

解决方案只是使用我的模拟商店来调度适当的操作来填充auth地图。像魅力一样工作。

于 2020-02-21T20:46:03.410 回答