如何模拟redux-promise-listener中间件和最终形式

问题描述:

我通过react-final-formreact-final-form设置了react-redux-promise-listener (repo) 作者说明.现在,我在模拟它进行测试时遇到了麻烦.

I setup react-redux-promise-listener (repo) for react-final-form via author instructions. Now, I'm having trouble mocking it for testing.

我遇到错误:The redux-promise-listener middleware is not installed

我尝试在测试提供程序中应用中间件:

I've tried applying middleware within the test provider:

// 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);



我期望快照能够渲染.但是,我得到了一个错误:

I was expecting the snapshot to render. However, I got an error instead:


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)

我在测试环境中重现实时环境时遇到的问题是promiseListener.我通过直接从组件中的存储文件导入而遇到了这个问题:

The issue I had with reproducing the live environment in the test environment was the promiseListener. I ran into this issue by importing directly from store file in the component:

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();
});