Как имитировать промежуточное ПО redux-promise-listener и окончательную форму

Я устанавливаю react-redux-promise-listener (repo) для react-final-form через инструкции автора. Теперь у меня проблемы с издевательством над ним для тестирования.

Я получаю сообщение об ошибке: The redux-promise-listener middleware is not installed

Я попытался применить промежуточное программное обеспечение в тестовом провайдере:

// app/frontend/__mocks__/TestReduxProvider.js
import React from 'react';
import { createStore, applyMiddleware } from 'redux';
import { Provider as ReduxProvider } from 'react-redux';
import { compose, setDisplayName, defaultProps } from 'recompose';
import createReduxPromiseListener from 'redux-promise-listener';

import rootReducer from '../store/rootReducer';

const displayName = 'TestReduxProvider';

const enhance = compose(
  setDisplayName(displayName),
  defaultProps({ state: {} }),
);

const reduxPromiseListener = createReduxPromiseListener();

function TestReduxProvider(props) {
  const { state, children } = props;
  const store = createStore(
    rootReducer,
    state,
    applyMiddleware(reduxPromiseListener.middleware),
  );

  return <ReduxProvider store={store}>{children}</ReduxProvider>;
}

export const promiseListener = reduxPromiseListener;
export default enhance(TestReduxProvider);

// sample test 

import React from 'react';
import TestReduxProvider from '~/__mocks__/TestReduxProvider';

import { render } from 'enzyme';
import Form from '../Form';

it('should not break if no params', () => {
  const wrapper = render(
    <TestReduxProvider>
      <Form />
    </TestReduxProvider>
  );
  expect(wrapper).toMatchSnapshot();
});
// form component relevant

import { connect } from 'react-redux';
import { Form as FormHandler } from 'react-final-form';

import MakeAsyncFunction from 'react-redux-promise-listener';
import { promiseListener } from '~/store/createStore';
import {
  STATUS_SUCCESS,
  STATUS_FAILURE,
} from '~/store/modules/async/constants';


const Form = props => {
  const targetFormErrors = formErrors[targetAction] || '';

  return (
    <StyledForm >
      <MakeAsyncFunction
        listener={promiseListener}
        start={targetAction}
        resolve={`${targetAction}/${STATUS_SUCCESS}`}
        reject={`${targetAction}/${STATUS_FAILURE}`}
        setPayload={setPayloadHandler}
      >
        {asyncFunc => (
          <FormHandler
            onSubmit={asyncFunc}
            validate={isValid}
            initialValues={formattedInitialValues}
            render={({ handleSubmit, pristine, errors, form }) => {
              if (navigationState !== 'form') {
                form.reset();
              }

              return (
                <form
                  onSubmit={event => {
                    setSubmitAttempted(true);
                    handleSubmit(event)
                      .then(() => submitSuccessHandler(form))
                      .catch(() => {
                      });
                  }}
                >
                  {inputsArray.map(formObject => {
                    return (
                      <div key={formObject.property}>
                        <label>
                          {formObject.label}
                          {formObject.isRequired !== false && !isDisabled && (
                            <span className="required"> *</span>
                          )}
                          <InputContainer>
                            <Input
                              formObject={formObject}
                              isDisabled={isDisabled}
                            />
                          </InputContainer>
                        </label>
                      </div>
                    );
                  })}
                </form>
              );
            }}
          />
        )}
      </MakeAsyncFunction>
    </StyledForm>
  );
};

export default enhance(Form);



Я ожидал, что снимок будет отображаться. Однако вместо этого я получил ошибку:


The redux-promise-listener middleware is not installed

      103 |     },
      104 |   ];
    > 105 |   const wrapper = render(
          |                   ^
      106 |     <TestReduxProvider>
      107 |       <Form inputsArray={INPUTS_ARRAY} />
      108 |     </TestReduxProvider>

      at Object.createAsyncFunction (node_modules/redux-promise-listener/dist/redux-promise-listener.cjs.js:60:13)
      at new MakeAsyncFunction (node_modules/react-redux-promise-listener/dist/react-redux-promise-listener.cjs.js:82:31)
      at processChild (node_modules/react-dom/cjs/react-dom-server.node.development.js:2846:14)
      at resolve (node_modules/react-dom/cjs/react-dom-server.node.development.js:2812:5)
      at ReactDOMServerRenderer.render (node_modules/react-dom/cjs/react-dom-server.node.development.js:3202:22)
      at ReactDOMServerRenderer.read (node_modules/react-dom/cjs/react-dom-server.node.development.js:3161:29)
      at Object.renderToStaticMarkup (node_modules/react-dom/cjs/react-dom-server.node.development.js:3661:27)
      at Object.renderToStaticMarkup [as render] (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:742:31)
      at render (node_modules/enzyme/src/render.js:21:25)
      at Object.<anonymous> (app/frontend/components/views/dashboard/views/accounts/components/__tests__/Form.test.js:105:19)

person jackhowa    schedule 27.08.2019    source источник
comment
Все, что делает react-redux-promise-listener, — это предоставляет функцию, которая возвращает обещание, а это именно то, что React Final Form хочет использовать. Вы переходите с Redux Form, и раньше это работало с Redux Form?   -  person Erik R.    schedule 28.08.2019
comment
Это работало в живой среде. Затем я использовал тестовую среду, и она не работала. Я понял, что проблема заключалась в импорте promiseListener из живого магазина, а не из тестового хранилища. Решил это, сохранив этот promiseListener в контексте, чтобы я мог динамически импортировать его.   -  person jackhowa    schedule 29.08.2019
comment
Спасибо за ответ и за создание фантастической библиотеки!   -  person jackhowa    schedule 29.08.2019
comment
По какой-то причине я просто не думаю, что вы должны тестировать это как пакет. Либо проверьте один middleware, либо логику вашей формы. Но не форма с редукционной интеграцией. На мой взгляд, так много всего может пойти не так, а это означает, что вообще не стоит его тестировать.   -  person windmaomao    schedule 29.08.2019


Ответы (1)


Проблема, с которой я столкнулся при воспроизведении живой среды в тестовой среде, заключалась в ошибке promiseListener. Я столкнулся с этой проблемой, импортировав непосредственно из файла хранилища в компоненте:

import { promiseListener } from '~/store/createStore';

решение:

// index.js
import createStore, { promiseListener } from './store/createStore';
import { Main } from './components';
import PromiseListenerContext from '~/store/PromiseListenerContext';

const app = (
  <ReduxProvider store={appStore}>
    <PromiseListenerContext.Provider value={promiseListener}>
      <Main />
    </PromiseListenerContext.Provider>
  </ReduxProvider>
// createStore.js

import { compose, applyMiddleware, createStore } from 'redux';
import createReduxPromiseListener from 'redux-promise-listener';

const reduxPromiseListener = createReduxPromiseListener();

function createStoreWrapper(history, testMiddleware) {
  const middleware = [
    reduxPromiseListener.middleware,
  ];
  if (testMiddleware) middleware.push(testMiddleware);

  const enhancers = [responsiveStoreEnhancer, applyMiddleware(...middleware)];

  const initialState = getInitialState();
  const enhancer = compose(...enhancers);

  const store = createStore(rootReducer, initialState, enhancer);

  addHandlers(store);

  return store;
}

export const promiseListener = reduxPromiseListener;

export default createStoreWrapper;
// test store 
import React from 'react';
import { createStore, applyMiddleware } from 'redux';
import { Provider as ReduxProvider } from 'react-redux';
import { compose, setDisplayName, defaultProps } from 'recompose';
import createReduxPromiseListener from 'redux-promise-listener';

import rootReducer from '../store/rootReducer';
import PromiseListenerContext from '~/store/PromiseListenerContext';

const displayName = 'TestReduxProvider';

const enhance = compose(
  setDisplayName(displayName),
  defaultProps({ state: {} })
);

function TestReduxProvider(props) {
  const { state, children } = props;

  const reduxPromiseListener = createReduxPromiseListener();

  const store = createStore(
    rootReducer,
    state,
    applyMiddleware(reduxPromiseListener.middleware)
  );

  return (
    <ReduxProvider store={store}>
      <PromiseListenerContext.Provider value={reduxPromiseListener}>
        {children}
      </PromiseListenerContext.Provider>
    </ReduxProvider>
  );
}
// test file 
import React from 'react';
import { render } from 'enzyme';
import Main from '../Main';
import TestReduxProvider from '~/__mocks__/TestReduxProvider';

it('should not break with basic params', () => {
  const wrapper = render(
    <TestReduxProvider>
      <Main pageObject={{}} />
    </TestReduxProvider>
  );
  expect(wrapper).toMatchSnapshot();
});

person jackhowa    schedule 29.08.2019