test react mock mapdispatchtoprops form javascript reactjs redux react-redux jestjs

javascript - mock - Violación Invariant de ReactJs/Redux: No se pudo encontrar "store" en el contexto o en los accesorios de "Connect(LoginContainer)"



mock redux jest (3)

Necesita pasar la tienda como un accesorio o contexto en su prueba. el método mount acepta el contexto como otro parámetro.

y ¿cómo se consigue la tienda aquí? Usted crea la tienda de la misma manera que creó en app.js

No estoy seguro de por qué estoy recibiendo este error, sucedió cuando agregué connect from redux a mi componente de inicio de sesión, para poder conectar mi store .

FAIL src / components / auth / Login.test.js

● El paquete de prueba no se ejecutó

Violación invariante: no se pudo encontrar "almacenar" ni en el contexto ni en los accesorios de "Connect (LoginContainer)". Envuelva el componente raíz en un <Provider> , o explícitamente pase "almacenar" como apoyo a "Conectar (LoginContainer)".

Index.js

import React from ''react'' import ReactDOM from ''react-dom'' import { Provider } from "react-redux" import { createCommonStore } from "./store"; import App from ''./App'' import css from ''./manage2.scss'' const store = createCommonStore(); const element = document.getElementById(''manage2''); console.log("Index.js Default store", store.getState()); ReactDOM.render( <Provider store={store}> // <-- store added here <App /> </Provider>, element);

store.js

import React from "react" import { applyMiddleware, combineReducers, compose, createStore} from "redux" import thunk from "redux-thunk" import { userReducer } from "./reducers/UserReducer" import { authReducer } from "./reducers/AuthReducer" export const createCommonStore = (trackStore=false) => { const reducers = combineReducers({ user: userReducer, user: authReducer }); //noinspection JSUnresolvedVariable const store = createStore(reducers, compose( applyMiddleware(thunk), window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() ) ); if (trackStore) { store.subscribe((() => { console.log(" store changed", store.getState()); })); } return store; };

App.js

import React from ''react'' import { BrowserRouter as Router } from ''react-router-dom'' import Routes from ''./components/Routes'' const supportsHistory = "pushState" in window.history export default class App extends React.Component { render() { return ( <Router forceRefresh={!supportsHistory}> <Routes /> </Router> ); } }

Routes.js

import React from ''react'' import { Route, Switch } from ''react-router-dom'' import LoginContainer from ''./auth/Login'' import Dashboard from ''./Dashboard'' import NoMatch from ''./NoMatch'' const Routes = () => { return ( <Switch> <Route exact={ true } path="/" component={ LoginContainer }/> <Route path="/dashboard" component={ Dashboard }/> <Route component={ NoMatch } /> </Switch> ); } export default Routes

Finalmente Login.js (código eliminado por brevedad

import React from ''react'' import { connect } from "react-redux" import { bindActionCreators } from ''redux''; import { setCurrentUser } from ''../../actions/authActions'' import * as api from ''../../services/api'' const mapDispatchToProps = (dispatch) => { console.log(''mapDispatchToProps'', dispatch); return { setUser: (user) => { bindActionCreators(setCurrentUser(user), dispatch) } } } class LoginContainer extends React.Component { constructor(props) { super(props) this.state = {}; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(e) { } handleSubmit(e) { } render() { return ( <div className="app-bg"> ... </div> ) } } export default connect(null, mapDispatchToProps)(LoginContainer);

Login.test

import React from ''react'' import ReactTestUtils from ''react-dom/test-utils'' import { mount, shallow } from ''enzyme'' import toJson from ''enzyme-to-json'' import { missingLogin } from ''../../consts/errors'' import Login from ''./Login'' import Notification from ''../common/Notification'' const loginComponent = shallow(<Login />); const fakeEvent = { preventDefault: () => '''' }; describe(''<Login /> component'', () => { it(''should render'', () => { const tree = toJson(loginComponent); expect(tree).toMatchSnapshot(); }); it(''should render the Notification component if state.error is true'', () => { loginComponent.setState({ error: true }); expect(loginComponent.find(Notification).length).toBe(1); }); }); describe(''User Login'', () => { it(''should fail if no credentials are provided'', () => { expect(loginComponent.find(''.form-login'').length).toBe(1); loginComponent.find(''.form-login'').simulate(''submit'', fakeEvent); expect(loginComponent.find(Notification).length).toBe(1); const notificationComponent = shallow(<Notification message={ missingLogin }/>); expect(notificationComponent.text()).toEqual(''Please fill out both username and password.''); }); it(''input fields should be filled correctly'', () => { const credentials = { username: ''leongaban'', password: ''testpass'' }; expect(loginComponent.find(''#input-auth-username'').length).toBe(1); const usernameInput = loginComponent.find(''#input-auth-username''); usernameInput.value = credentials.username; expect(usernameInput.value).toBe(''leongaban''); const passwordInput = loginComponent.find(''#input-auth-password''); passwordInput.value = credentials.password; expect(passwordInput.value).toBe(''testpass''); }); });

¿Qué ves mal aquí?


Puede usar el contextType de React o pasar propType. Debería declararlo ya sea como prop o contextType.

Provider.contextTypes = { Store: React.PropTypes.object.isRequired }; Provider.propTypes= { Store: React.PropTypes.object.isRequired };


Redux recomienda exportar el componente desconectado para pruebas unitarias. Ver sus documentos .

En login.js:

// Named export for tests export class LoginContainer extends React.Component { } // Default export export default connect(null, mapDispatchToProps)(LoginContainer);

Y en tu prueba:

// Import the named export, which has not gone through the connect function import { LoginContainer as Login } from ''./Login'';

A continuación, puede especificar cualquier accesorio que habría venido de la tienda directamente en el componente.