Merge branch 'develop'
This commit is contained in:
commit
adb9959b03
|
@ -12,7 +12,7 @@
|
||||||
margin-bottom: 40px;
|
margin-bottom: 40px;
|
||||||
line-height: calc(100vh - 200px);
|
line-height: calc(100vh - 200px);
|
||||||
font-size: 80vh;
|
font-size: 80vh;
|
||||||
color: blue;
|
color: red;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,6 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bleno": "^0.4.2",
|
"bleno": "^0.4.2",
|
||||||
"redux": "^3.7.1",
|
"redux": "^3.7.1",
|
||||||
"redux-thunk": "^2.2.0",
|
|
||||||
"text-encoding": "^0.6.4"
|
"text-encoding": "^0.6.4"
|
||||||
},
|
},
|
||||||
"bundlesize": [
|
"bundlesize": [
|
||||||
|
|
|
@ -4,18 +4,27 @@ export default function Actions(central, TYPES) {
|
||||||
payload: state,
|
payload: state,
|
||||||
});
|
});
|
||||||
|
|
||||||
const syncStore = () => dispatch => central.read().then(state => dispatch(syncState(state)));
|
const syncStore = () => ({
|
||||||
|
type: TYPES.BLUETOOTH_SYNC_REQUEST,
|
||||||
|
request: dispatch => central.read().then(state => dispatch(syncState(state))),
|
||||||
|
});
|
||||||
|
|
||||||
const connectStore = name => (dispatch) => {
|
const connectStore = name => ({
|
||||||
|
type: TYPES.BLUETOOTH_CONNECT_REQUEST,
|
||||||
|
request: (dispatch) => {
|
||||||
dispatch({ type: TYPES.BLUETOOTH_CONNECTING });
|
dispatch({ type: TYPES.BLUETOOTH_CONNECTING });
|
||||||
return central
|
return central
|
||||||
.connect(name)
|
.connect(name)
|
||||||
.then(() => central.handler(state => dispatch(syncState(state))))
|
.then(() => central.handler(state => dispatch(syncState(state))))
|
||||||
.then(() => dispatch({ type: TYPES.BLUETOOTH_CONNECTED }))
|
.then(() => dispatch({ type: TYPES.BLUETOOTH_CONNECTED }))
|
||||||
.then(() => dispatch(syncStore()));
|
.then(() => dispatch(syncStore()));
|
||||||
};
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const sendAction = action => () => central.write(action);
|
const sendAction = action => ({
|
||||||
|
type: TYPES.BLUETOOTH_SEND_REQUEST,
|
||||||
|
request: () => central.write(action),
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
connectStore,
|
connectStore,
|
||||||
|
|
|
@ -32,9 +32,12 @@ test('syncState', () => {
|
||||||
|
|
||||||
test('connectStore', () => {
|
test('connectStore', () => {
|
||||||
const { connectStore } = Actions(central, TYPES);
|
const { connectStore } = Actions(central, TYPES);
|
||||||
expect.assertions(8);
|
const action = connectStore('mockName');
|
||||||
|
expect.assertions(10);
|
||||||
|
|
||||||
const promise = connectStore('mockName')(dispatch).then(() => {
|
expect(action.type).toEqual(TYPES.BLUETOOTH_CONNECT_REQUEST);
|
||||||
|
|
||||||
|
const promise = action.request(dispatch).then(() => {
|
||||||
expect(central.connect).toBeCalled();
|
expect(central.connect).toBeCalled();
|
||||||
expect(central.handler).toBeCalled();
|
expect(central.handler).toBeCalled();
|
||||||
|
|
||||||
|
@ -42,7 +45,9 @@ test('connectStore', () => {
|
||||||
expect(dispatch.mock.calls[0][0]).toEqual({ type: TYPES.BLUETOOTH_CONNECTING });
|
expect(dispatch.mock.calls[0][0]).toEqual({ type: TYPES.BLUETOOTH_CONNECTING });
|
||||||
expect(dispatch.mock.calls[1][0]).toEqual({ type: TYPES.BLUETOOTH_CONNECTED });
|
expect(dispatch.mock.calls[1][0]).toEqual({ type: TYPES.BLUETOOTH_CONNECTED });
|
||||||
|
|
||||||
return dispatch.mock.calls[2][0](dispatch); // syncStore
|
const syncStore = dispatch.mock.calls[2][0];
|
||||||
|
expect(syncStore.type).toEqual(TYPES.BLUETOOTH_SYNC_REQUEST);
|
||||||
|
return syncStore.request(dispatch);
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
expect(central.read).toBeCalled();
|
expect(central.read).toBeCalled();
|
||||||
expect(dispatch.mock.calls[3][0]).toEqual({ type: TYPES.BLUETOOTH_SYNC, payload: 'mockState' });
|
expect(dispatch.mock.calls[3][0]).toEqual({ type: TYPES.BLUETOOTH_SYNC, payload: 'mockState' });
|
||||||
|
@ -55,9 +60,12 @@ test('connectStore', () => {
|
||||||
|
|
||||||
test('syncStore', () => {
|
test('syncStore', () => {
|
||||||
const { syncStore } = Actions(central, TYPES);
|
const { syncStore } = Actions(central, TYPES);
|
||||||
expect.assertions(3);
|
const action = syncStore();
|
||||||
|
expect.assertions(4);
|
||||||
|
|
||||||
const promise = syncStore()(dispatch).then(() => {
|
expect(action.type).toEqual(TYPES.BLUETOOTH_SYNC_REQUEST);
|
||||||
|
|
||||||
|
const promise = action.request(dispatch).then(() => {
|
||||||
expect(central.read).toBeCalled();
|
expect(central.read).toBeCalled();
|
||||||
expect(dispatch).toBeCalledWith({ type: TYPES.BLUETOOTH_SYNC, payload: 'mockState' });
|
expect(dispatch).toBeCalledWith({ type: TYPES.BLUETOOTH_SYNC, payload: 'mockState' });
|
||||||
|
|
||||||
|
@ -69,9 +77,12 @@ test('syncStore', () => {
|
||||||
|
|
||||||
test('sendAction', () => {
|
test('sendAction', () => {
|
||||||
const { sendAction } = Actions(central, TYPES);
|
const { sendAction } = Actions(central, TYPES);
|
||||||
expect.assertions(2);
|
const action = sendAction('mockAction');
|
||||||
|
expect.assertions(3);
|
||||||
|
|
||||||
const promise = sendAction('mockAction')(dispatch).then(() => {
|
expect(action.type).toEqual(TYPES.BLUETOOTH_SEND_REQUEST);
|
||||||
|
|
||||||
|
const promise = action.request(dispatch).then(() => {
|
||||||
expect(central.write).toBeCalledWith('mockAction');
|
expect(central.write).toBeCalledWith('mockAction');
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -4,3 +4,7 @@ export const BLUETOOTH_ERROR = '@@bluetooth/ERROR';
|
||||||
export const BLUETOOTH_READ = '@@bluetooth/READ';
|
export const BLUETOOTH_READ = '@@bluetooth/READ';
|
||||||
export const BLUETOOTH_SYNC = '@@bluetooth/SYNC';
|
export const BLUETOOTH_SYNC = '@@bluetooth/SYNC';
|
||||||
export const BLUETOOTH_SEND = '@@bluetooth/SEND';
|
export const BLUETOOTH_SEND = '@@bluetooth/SEND';
|
||||||
|
|
||||||
|
export const BLUETOOTH_CONNECT_REQUEST = '@@bluetooth/CONNECT_REQUEST';
|
||||||
|
export const BLUETOOTH_SEND_REQUEST = '@@bluetooth/SEND_REQUEST';
|
||||||
|
export const BLUETOOTH_SYNC_REQUEST = '@@bluetooth/SYNC_REQUEST';
|
||||||
|
|
|
@ -1,9 +1,26 @@
|
||||||
import ACTIONS from '../actions';
|
import ACTIONS from '../actions';
|
||||||
|
import * as TYPES from '../actions/types';
|
||||||
|
|
||||||
const { sendAction } = ACTIONS;
|
const { sendAction } = ACTIONS;
|
||||||
|
|
||||||
|
const {
|
||||||
|
BLUETOOTH_CONNECT_REQUEST,
|
||||||
|
BLUETOOTH_SEND_REQUEST,
|
||||||
|
BLUETOOTH_SYNC_REQUEST,
|
||||||
|
} = TYPES;
|
||||||
|
|
||||||
|
const REQUESTS = [
|
||||||
|
BLUETOOTH_CONNECT_REQUEST,
|
||||||
|
BLUETOOTH_SEND_REQUEST,
|
||||||
|
BLUETOOTH_SYNC_REQUEST,
|
||||||
|
];
|
||||||
|
|
||||||
export default (actions = []) => store => next => (action) => {
|
export default (actions = []) => store => next => (action) => {
|
||||||
|
if (typeof action !== 'object') {
|
||||||
|
return next(action);
|
||||||
|
}
|
||||||
const { type } = action;
|
const { type } = action;
|
||||||
|
if (REQUESTS.includes(type)) action.request(store.dispatch);
|
||||||
if (actions.includes(type)) store.dispatch(sendAction(action));
|
if (actions.includes(type)) store.dispatch(sendAction(action));
|
||||||
return next(action);
|
return next(action);
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,3 +35,17 @@ test('actions included', () => {
|
||||||
expect(store.dispatch).toBeCalledWith('mockAction');
|
expect(store.dispatch).toBeCalledWith('mockAction');
|
||||||
expect(next).toBeCalledWith({ type: 'ACTION' });
|
expect(next).toBeCalledWith({ type: 'ACTION' });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('actions request', () => {
|
||||||
|
const request = jest.fn();
|
||||||
|
const action = { type: '@@bluetooth/CONNECT_REQUEST', request };
|
||||||
|
middleware(['ACTION'])(store)(next)(action);
|
||||||
|
expect(request).toBeCalledWith(store.dispatch);
|
||||||
|
expect(next).toBeCalledWith(action);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('actions not an object', () => {
|
||||||
|
const funcAction = jest.fn();
|
||||||
|
middleware(['ACTION'])(store)(next)(funcAction);
|
||||||
|
expect(next).toBeCalledWith(funcAction);
|
||||||
|
});
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
/* global window */
|
/* global window */
|
||||||
import { createStore, applyMiddleware, compose } from 'redux';
|
import { createStore, applyMiddleware, compose } from 'redux';
|
||||||
import thunk from 'redux-thunk';
|
|
||||||
|
|
||||||
import middleware from '../middleware';
|
import middleware from '../middleware';
|
||||||
import reducers from '../reducers';
|
import reducers from '../reducers';
|
||||||
|
|
||||||
export default (actions) => {
|
export default (actions) => {
|
||||||
const middlewares = [middleware(actions), thunk];
|
const middlewares = [middleware(actions)];
|
||||||
const enhancers = [applyMiddleware(...middlewares)];
|
const enhancers = [applyMiddleware(...middlewares)];
|
||||||
|
|
||||||
/* eslint-disable no-underscore-dangle */
|
/* eslint-disable no-underscore-dangle */
|
||||||
|
|
Loading…
Reference in New Issue