Ошибка типа: ref.collection не является функцией, использующей React-Redux-Firebase / React-Testing-Library - PullRequest
0 голосов
/ 19 февраля 2020

У меня были тонны проблем, когда я пытался воспроизвести компонент, связанный с реагирующим-редукс-пожарной базой, используя библиотеку реагирующего тестирования. Я получаю сообщение об ошибке [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. Я пытался везде искать какой-то ответ, но не повезло. Буду признателен за любую помощь!

1 Ответ

0 голосов
/ 21 февраля 2020

Так что я наконец-то понял! Компонент ожидал реквизиты, которые я не заполнил должным образом при настройке теста.

В моем компоненте были следующие строки:

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

Где auth - часть состояния моего приложения. Начальным состоянием для этого была пустая карта, поэтому, когда я попытался вытащить clientId оттуда и использовать ее для получения своих коллекций, она выдавала ошибку.

Решением было просто использование моего ложного магазина для отправки соответствующее действие для заполнения карты auth. Работал как шарм.

...