0.0.18 • Published 8 years ago

redux-easy-connect v0.0.18

Weekly downloads
1
License
ISC
Repository
bitbucket
Last release
8 years ago

#redux-easy-connect npm Codeship Status for kenanberbic/redux-easy-connect Known Vulnerabilities

Redux easy connect contains:

  • ReduxComponent - Base class that provide redux CONNECT action on easy way (ONLY REACT)
  • reduxExtend - Same like base class, but it's implemented using class prototype. (REACT AND REACT NATIVE)
  • TestHelper - Provide functions that allowing access to component directly. This include redux actions, state, reducers and public functions
  • setType - Init rule for all action types

How to use

import {reduxExtend,
        ReduxComponent,
        TestHelper,
        setType} from 'redux-easy-connect';

// Export component (ReactJS, ReactNative)
export default reduxExtend(Component);

// Export component (ReactJS)
class Example extend ReduxComponent
export default Example.CONNECT

// Include component
<Example
    actions={ExampleActions}
    reducers={{userStore:["user"]}}
    services={{AuthService}}
    />

// set action type
export const EXAMPLE_GET_USER = setType("example/GET_USER");

// use action type with dispatch
dispatch(EXAMPLE_GET_USER({/* props that will be provided to reducers */}))

// use action type in reducers
switch(type)
    case EXAMPLE_GET_USER.type :
         /* props that will be provided to component */
         break;

// Call actions
this.Actions.getUser(1);

// Call services
this.Services.AuthService.getUser(1)

// Reducers
this.props.user

// Use test helper
const component = TestHelper.getComponent(rendered, Example);
// rendered created by react-test-renderer

component.setState(/**/);
component.Actions.getUser(1);
await component.waitForAllState();
await component.waitForAllDispatch();

expect(component.props.user).toBeInstanceOf(Object);

// Use test helper for load external javascript library''s
const window = await TestHelper.loadScript(
                                            jsdom.JSDOM,
                                            'path to script',
                                            {jsdom options} ||
                                            DEFAULT_JSDOM_OPTIONS /* isn''t required */);

// Use mock''s with global fetch
it('should expose global fetch object', TestHelper.isFetchGlobal);
const output = await TestHelper.mock([{
                                        url:'http://localhost:3000/test',
                                        body:{output:"example"},
                                        status: 200}]);

// DEFAULT_JSDOM_OPTIONS
{
    resources: 'usable',
    runScripts: "dangerously",
    url: "http://localhost:8080",
    referrer: "http://localhost:8080",
    contentType: "text/html",
    userAgent: "Mellblomenator/9000"
}

Example

npm install
npm test
npm start
http://localhost:3000

reduxExtend / ReduxComponent

PropsTypeIncludeExampleDescription
actionspropactions={UserActions}this.Actions.getUser()Include list of actions that can be accessible in component
servicespropservices={{UserService}}this.UserService.getUser()Include list of services that can be accessible in component
reducerspropreducers={{userStore:"user", authStore:true}}this.props.user, this.props. "all props from auth store"Include list of reducers and props that can be accessible in component
waitForAllDispatchfunccomponent. waitForAllDispatch()Continue to execute code after all actions finished with executing. ONLY FOR TESTS
waitForAllStatefunccomponent. waitForAllState()Continue to execute code after all state actions finished with executing. ONLY FOR TESTS
onDispatchEndeventonDispatchEnd(args){ }*
onStateEndeventonStateEnd(args){ }*

TestHelper

FuncArgumentsExampleDescription
getComponentRenderedComponent, Class component nameTestHelper. getComponent(rendered, Example): return Example;Find and return react component
loadScriptJSDOM, javascript path, optionsTestHelper.loadScript(JSDOM, 'script path') : return windowLoading external javascript libs like a google maps
isFetchGlobalit('should expose global fetch object', TestHelper.isFetchGlobal);Test you api calls with global fetch
mock{url, body, status}TestHelper. mock({ url: "http://localhost/test", body: {example:"test"}, status: 200}) : return PromiseMock http requests made using fetch

Full example

Action types

import {setType} from 'redux-easy-connect';

export const EXAMPLE_GET_USER = setType('example/GET_USER');
export const EXAMPLE_SAVE_USER = setType("example/SAVE_USER");
export const EXAMPLE_DELETE_USER = setType("example/DELETE_USER");

Redux store - Include services directly in actions

function configureStore(initialState) {
    return createStore(rootReducer, initialState, compose(
        applyMiddleware(
            thunk.withExtraArgument(Services) // Include services like last params,
            routerMiddleware(history),
            reduxImmutableStateInvariant(),
        ),
        window.devToolsExtension ? window.devToolsExtension() : f => f));
}

const store = configureStore({});

export default store;

Action example

import {EXAMPLE_GET_USER, EXAMPLE_DELETE_USER, EXAMPLE_SAVE_USER} from '../actionTypes';

export default class ExampleActions {
    static getUser(id) {
        return async (dispatch, getState, {UserService}) => {
            const user = UserService.getUser(id);
            dispatch(EXAMPLE_GET_USER({user}));
        }
    }

    static saveUser(user) {
        return async (dispatch, getState, {UserService}) => {
            const output = UserService.saveUser(user);
            dispatch(EXAMPLE_SAVE_USER({user:output}));
        }
    }

    static deleteUser(user) {
        return async (dispatch, getState, {UserService}) => {
            const user = UserService.deleteUser(user);
            dispatch(EXAMPLE_DELETE_USER({user}));
        }
    }
}

Reducer example

import {EXAMPLE_GET_USER, EXAMPLE_DELETE_USER, EXAMPLE_SAVE_USER} from '../actionTypes';

const initialState = {
    user: null
};

export default function userReducer(state = initialState, action) {
    switch (action.type) {
        case EXAMPLE_GET_USER.type:
            return Object.assign({}, {user:action.user});
        case EXAMPLE_SAVE_USER.type:
            return Object.assign({}, {user:action.user});
        case EXAMPLE_DELETE_USER.type:
            return Object.assign({}, {user:action.user});
        default:
            return state;
    }
}

Component example

import React from 'react';
import {reduxExtend, ReduxComponent} from 'redux-easy-connect';

// export class Example extends ReduxComponent
export class Example extends React.Component{
    constructor(props){
        super(props);

        this.handleAddUser = this.handleAddUser.bind(this);
        this.handleGetUser = this.handleGetUser.bind(this);
        this.handleDeleteUser = this.handleDeleteUser.bind(this);
    }

    handleAddUser(){
        const user = {id:1,name:"Example",email:"example@example.com"};
        this.Actions.saveUser(user);
    }

    handleGetUser(){
        this.Actions.getUser(1);
    }

    handleDeleteUser(){
        this.Actions.deleteUser(1);
    }

    handleExampleService(){
        this.Services.AuthService.login(/* props */);
    }

    render(){
        return (
            <div>
                <button onClick={this.handleAddUser}>Add user</button>
                <button onClick={this.handleGetUser}>Get user</button>
                <button onClick={this.handleDeleteUser}>Delete user</button>
                <div>{this.props.user && JSON.stringify(this.props.user)}</div>
            </div>
        );
    }
}

export default reduxExtend(Example);
// export default Example.CONNECT;

Test example

import React from 'react';
import renderer from 'react-test-renderer';
import {TestHelper} from 'redux-easy-connect';
import store from '../store'

import ExampleActions from '../example/actions';
import CONNECT, {Example} from '../example';

it('renders example with action button add user', async () => {
    const rendered = renderer.create(
        <CONNECT
            store={store}
            actions={ExampleActions}
            reducers={{userStore:["user"]}}
        />
    );

    const component = TestHelper.getComponent(rendered.getInstance(), Example);
    component.handleAddUser();
    await component.waitForAllDispatch();

    const json = rendered.toJSON();
    const messageContainer = json.children[json.children.length - 1];
    expect(messageContainer).toBeInstanceOf(Object);
    expect(messageContainer.children).not.toBeNull();
    expect(messageContainer.children.length).toEqual(1);
    expect(messageContainer.children[0]).toEqual('{\"id\":1,\"name\":\"Example\",\"email\":\"example@example.com\",\"action\":\"SAVE\"}');
    expect(json).toBeTruthy();
});
0.0.18

8 years ago

0.0.17

8 years ago

0.0.16

8 years ago

0.0.15

8 years ago

0.0.14

8 years ago

0.0.13

8 years ago

0.0.12

8 years ago

0.0.11

8 years ago

0.0.10

8 years ago

0.0.9

8 years ago

0.0.8

8 years ago

0.0.7

8 years ago

0.0.6

8 years ago

0.0.5

8 years ago

0.0.4

8 years ago

0.0.3

8 years ago

0.0.2

8 years ago

0.0.1

8 years ago