First unit test
This commit is contained in:
parent
15e446b540
commit
33b891f170
4827
package-lock.json
generated
4827
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -36,6 +36,7 @@
|
|||||||
"react-transition-group": "^1.1.3",
|
"react-transition-group": "^1.1.3",
|
||||||
"redux": "^3.6.0",
|
"redux": "^3.6.0",
|
||||||
"redux-logger": "^3.0.6",
|
"redux-logger": "^3.0.6",
|
||||||
|
"redux-promise-middleware": "^4.3.0",
|
||||||
"redux-thunk": "^2.2.0",
|
"redux-thunk": "^2.2.0",
|
||||||
"seamless-immutable": "^7.1.2",
|
"seamless-immutable": "^7.1.2",
|
||||||
"simple-peer": "^8.1.0",
|
"simple-peer": "^8.1.0",
|
||||||
@ -66,11 +67,14 @@
|
|||||||
"node-sass": "^4.5.3",
|
"node-sass": "^4.5.3",
|
||||||
"nodemon": "^1.11.0",
|
"nodemon": "^1.11.0",
|
||||||
"react-addons-test-utils": "^15.5.1",
|
"react-addons-test-utils": "^15.5.1",
|
||||||
|
"redux-mock-store": "^1.2.3",
|
||||||
"uglify-js": "^2.6.2",
|
"uglify-js": "^2.6.2",
|
||||||
"watchify": "^3.9.0"
|
"watchify": "^3.9.0"
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
"scriptPreprocessor": "<rootDir>/node_modules/babel-jest",
|
"transform": {
|
||||||
|
".*": "<rootDir>/node_modules/babel-jest"
|
||||||
|
},
|
||||||
"modulePathIgnorePatterns": [
|
"modulePathIgnorePatterns": [
|
||||||
"<rootDir>/node_modules/"
|
"<rootDir>/node_modules/"
|
||||||
]
|
]
|
||||||
|
|||||||
1
src/client/__mocks__/callId.js
Normal file
1
src/client/__mocks__/callId.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export default 'call1234'
|
||||||
46
src/client/__tests__/App-test.js
Normal file
46
src/client/__tests__/App-test.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
jest.mock('../actions/CallActions.js')
|
||||||
|
jest.mock('../callId.js')
|
||||||
|
jest.mock('../iceServers.js')
|
||||||
|
|
||||||
|
import App from '../containers/App.js'
|
||||||
|
import React from 'react'
|
||||||
|
import ReactDOM from 'react-dom'
|
||||||
|
import TestUtils from 'react-dom/test-utils'
|
||||||
|
import configureStore from 'redux-mock-store'
|
||||||
|
import reducers from '../reducers'
|
||||||
|
import { Provider } from 'react-redux'
|
||||||
|
import { init } from '../actions/CallActions.js'
|
||||||
|
import { middlewares } from '../store.js'
|
||||||
|
|
||||||
|
// jest.useFakeTimers()
|
||||||
|
|
||||||
|
describe('App', () => {
|
||||||
|
|
||||||
|
let state
|
||||||
|
beforeEach(() => {
|
||||||
|
init.mockReturnValue({ type: 'INIT' })
|
||||||
|
state = reducers()
|
||||||
|
})
|
||||||
|
|
||||||
|
let component, node, store
|
||||||
|
function render() {
|
||||||
|
store = configureStore(middlewares)(state)
|
||||||
|
console.log(store.getState())
|
||||||
|
component = TestUtils.renderIntoDocument(
|
||||||
|
<Provider store={store}>
|
||||||
|
<App />
|
||||||
|
</Provider>
|
||||||
|
)
|
||||||
|
node = ReactDOM.findDOMNode(component)
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('render', () => {
|
||||||
|
it('renders without issues', () => {
|
||||||
|
render()
|
||||||
|
// jest.runAllTimers()
|
||||||
|
expect(node).toBeTruthy()
|
||||||
|
expect(init.mock.calls.length).toBe(1)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
@ -6,15 +6,16 @@ import getUserMedia from '../window/getUserMedia.js'
|
|||||||
import handshake from '../peer/handshake.js'
|
import handshake from '../peer/handshake.js'
|
||||||
import socket from '../socket.js'
|
import socket from '../socket.js'
|
||||||
|
|
||||||
export const init = () => dispatch => {
|
export const init = () => dispatch => ({
|
||||||
return Promise.all([
|
type: constants.INIT,
|
||||||
|
payload: Promise.all([
|
||||||
connect()(dispatch),
|
connect()(dispatch),
|
||||||
getCameraStream()(dispatch)
|
getCameraStream()(dispatch)
|
||||||
])
|
])
|
||||||
.spread((socket, stream) => {
|
.spread((socket, stream) => {
|
||||||
handshake.init({ socket, callId, stream })
|
handshake.init({ socket, callId, stream })
|
||||||
})
|
})
|
||||||
}
|
})
|
||||||
|
|
||||||
export const connect = () => dispatch => {
|
export const connect = () => dispatch => {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
|
|||||||
@ -1,33 +1,44 @@
|
|||||||
|
import * as constants from '../constants.js'
|
||||||
|
|
||||||
|
const TIMEOUT = 5000
|
||||||
|
|
||||||
function format (string, args) {
|
function format (string, args) {
|
||||||
string = args
|
string = args
|
||||||
.reduce((string, arg, i) => string.replace('{' + i + '}', arg), string)
|
.reduce((string, arg, i) => string.replace('{' + i + '}', arg), string)
|
||||||
return string
|
return string
|
||||||
}
|
}
|
||||||
|
|
||||||
function _notify (type, args) {
|
const _notify = (type, args) => dispatch => {
|
||||||
let string = args[0] || ''
|
let string = args[0] || ''
|
||||||
let message = format(string, Array.prototype.slice.call(args, 1))
|
let message = format(string, Array.prototype.slice.call(args, 1))
|
||||||
return {
|
const payload = { type, message }
|
||||||
type: 'notify',
|
dispatch({
|
||||||
payload: { type, message }
|
type: constants.NOTIFY,
|
||||||
}
|
payload
|
||||||
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
dispatch({
|
||||||
|
type: constants.NOTIFY_DISMISS,
|
||||||
|
payload
|
||||||
|
})
|
||||||
|
}, TIMEOUT)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function info () {
|
export const info = () => dispatch => {
|
||||||
return _notify('info', arguments)
|
_notify('info', arguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function warn () {
|
export const warn = () => dispatch => {
|
||||||
return _notify('warning', arguments)
|
_notify('warning', arguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function error () {
|
export const error = () => dispatch => {
|
||||||
return _notify('error', arguments)
|
_notify('error', arguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function alert (message, dismissable) {
|
export function alert (message, dismissable) {
|
||||||
return {
|
return {
|
||||||
type: 'alert',
|
type: constants.ALERT,
|
||||||
payload: {
|
payload: {
|
||||||
action: dismissable ? 'Dismiss' : '',
|
action: dismissable ? 'Dismiss' : '',
|
||||||
dismissable: !!dismissable,
|
dismissable: !!dismissable,
|
||||||
@ -36,3 +47,10 @@ export function alert (message, dismissable) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const dismiss = alert => {
|
||||||
|
return {
|
||||||
|
type: constants.ALERT_DISMISS,
|
||||||
|
payload: alert
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ export const AlertPropType = PropTypes.shape({
|
|||||||
message: PropTypes.string.isRequired
|
message: PropTypes.string.isRequired
|
||||||
})
|
})
|
||||||
|
|
||||||
export class Alert extends React.PureComponent {
|
export class Alert extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
alert: AlertPropType,
|
alert: AlertPropType,
|
||||||
dismiss: PropTypes.func.isRequired
|
dismiss: PropTypes.func.isRequired
|
||||||
@ -31,7 +31,7 @@ export class Alert extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Alerts extends React.PureComponent {
|
export default class Alerts extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
alerts: PropTypes.arrayOf(AlertPropType).isRequired,
|
alerts: PropTypes.arrayOf(AlertPropType).isRequired,
|
||||||
dismiss: PropTypes.func.isRequired
|
dismiss: PropTypes.func.isRequired
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import Alert from './Alerts.js'
|
import Alerts, { AlertPropType } from './Alerts.js'
|
||||||
import Input from './Input.js'
|
import Input from './Input.js'
|
||||||
import Notifications from './Notifications.js'
|
import Notifications from './Notifications.js'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
@ -6,24 +6,28 @@ import React from 'react'
|
|||||||
import Video, { StreamPropType } from './Video.js'
|
import Video, { StreamPropType } from './Video.js'
|
||||||
import _ from 'underscore'
|
import _ from 'underscore'
|
||||||
|
|
||||||
export default class App extends React.PureComponent {
|
export default class App extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
streams: PropTypes.arrayOf(StreamPropType).isRequired,
|
streams: PropTypes.objectOf(StreamPropType).isRequired,
|
||||||
|
alerts: PropTypes.arrayOf(AlertPropType).isRequired,
|
||||||
activate: PropTypes.func.isRequired,
|
activate: PropTypes.func.isRequired,
|
||||||
active: PropTypes.string.isRequired,
|
active: PropTypes.string,
|
||||||
init: PropTypes.func.isRequired
|
init: PropTypes.func.isRequired,
|
||||||
|
notify: PropTypes.func.isRequired
|
||||||
}
|
}
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
const { init } = this.props
|
const { init } = this.props
|
||||||
init()
|
init()
|
||||||
}
|
}
|
||||||
render () {
|
render () {
|
||||||
const { active, activate, streams } = this.props
|
const {
|
||||||
|
active, activate, alerts, dismiss, notify, notifications, streams
|
||||||
|
} = this.props
|
||||||
|
|
||||||
return (<div className="app">
|
return (<div className="app">
|
||||||
<Alert />
|
<Alerts alerts={alerts} dismiss={dismiss} />
|
||||||
<Notifications />
|
<Notifications notifications={notifications} />
|
||||||
<Input />
|
<Input notify={notify} />
|
||||||
<div className="videos">
|
<div className="videos">
|
||||||
{_.map(streams, (stream, userId) => (
|
{_.map(streams, (stream, userId) => (
|
||||||
<Video
|
<Video
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import PropTypes from 'prop-types'
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import peers from '../peer/peers.js'
|
import peers from '../peer/peers.js'
|
||||||
|
|
||||||
export default class Input extends React.PureComponent {
|
export default class Input extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
notify: PropTypes.func.isRequired
|
notify: PropTypes.func.isRequired
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import CSSTransitionGroup from 'react-transition-group'
|
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
|
import { CSSTransitionGroup } from 'react-transition-group'
|
||||||
|
|
||||||
export const NotificationPropTypes = PropTypes.shape({
|
export const NotificationPropTypes = PropTypes.shape({
|
||||||
id: PropTypes.string.isRequired,
|
id: PropTypes.string.isRequired,
|
||||||
@ -9,7 +9,7 @@ export const NotificationPropTypes = PropTypes.shape({
|
|||||||
message: PropTypes.string.isRequired
|
message: PropTypes.string.isRequired
|
||||||
})
|
})
|
||||||
|
|
||||||
export default class Notifications extends React.PureComponent {
|
export default class Notifications extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
notifications: PropTypes.arrayOf(NotificationPropTypes).isRequired,
|
notifications: PropTypes.arrayOf(NotificationPropTypes).isRequired,
|
||||||
max: PropTypes.number.isRequired
|
max: PropTypes.number.isRequired
|
||||||
|
|||||||
@ -9,7 +9,7 @@ export const StreamPropType = PropTypes.shape({
|
|||||||
url: PropTypes.string.isRequired
|
url: PropTypes.string.isRequired
|
||||||
})
|
})
|
||||||
|
|
||||||
export default class Video extends React.PureComponent {
|
export default class Video extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
activate: PropTypes.func.isRequired,
|
activate: PropTypes.func.isRequired,
|
||||||
active: PropTypes.string.required,
|
active: PropTypes.string.required,
|
||||||
|
|||||||
@ -1,71 +0,0 @@
|
|||||||
jest.unmock('../alert.js')
|
|
||||||
|
|
||||||
const React = require('react')
|
|
||||||
const ReactDOM = require('react-dom')
|
|
||||||
const TestUtils = require('react-addons-test-utils')
|
|
||||||
|
|
||||||
const Alert = require('../alert.js')
|
|
||||||
const dispatcher = require('../../dispatcher/dispatcher.js')
|
|
||||||
const alertStore = require('../../store/alertStore.js')
|
|
||||||
|
|
||||||
describe('alert', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
alertStore.getAlert.mockClear()
|
|
||||||
})
|
|
||||||
|
|
||||||
function render () {
|
|
||||||
let component = TestUtils.renderIntoDocument(<div><Alert /></div>)
|
|
||||||
return ReactDOM.findDOMNode(component)
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('render', () => {
|
|
||||||
it('should do nothing when no alert', () => {
|
|
||||||
let node = render()
|
|
||||||
expect(node.querySelector('.alert.hidden')).toBeTruthy()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should render alert', () => {
|
|
||||||
alertStore.getAlert.mockReturnValue({
|
|
||||||
message: 'example',
|
|
||||||
type: 'warning'
|
|
||||||
})
|
|
||||||
|
|
||||||
let node = render()
|
|
||||||
|
|
||||||
expect(node.querySelector('.alert.warning')).toBeTruthy()
|
|
||||||
expect(node.querySelector('.alert span').textContent).toMatch(/example/)
|
|
||||||
expect(node.querySelector('.alert button')).toBeNull()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should render dismissable alert', () => {
|
|
||||||
alertStore.getAlert.mockReturnValue({
|
|
||||||
message: 'example',
|
|
||||||
type: 'warning',
|
|
||||||
dismissable: true
|
|
||||||
})
|
|
||||||
|
|
||||||
let node = render()
|
|
||||||
|
|
||||||
expect(node.querySelector('.alert.warning')).toBeTruthy()
|
|
||||||
expect(node.querySelector('.alert span').textContent).toMatch(/example/)
|
|
||||||
expect(node.querySelector('.alert button')).toBeTruthy()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should dispatch dismiss alert on dismiss clicked', () => {
|
|
||||||
let alert = {
|
|
||||||
message: 'example',
|
|
||||||
type: 'warning',
|
|
||||||
dismissable: true
|
|
||||||
}
|
|
||||||
alertStore.getAlert.mockReturnValue(alert)
|
|
||||||
|
|
||||||
let node = render()
|
|
||||||
TestUtils.Simulate.click(node.querySelector('.alert button'))
|
|
||||||
|
|
||||||
expect(dispatcher.dispatch.mock.calls).toEqual([[{
|
|
||||||
type: 'alert-dismiss',
|
|
||||||
alert
|
|
||||||
}]])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
jest.unmock('../app.js')
|
|
||||||
jest.unmock('underscore')
|
|
||||||
|
|
||||||
const React = require('react')
|
|
||||||
const ReactDOM = require('react-dom')
|
|
||||||
const TestUtils = require('react-addons-test-utils')
|
|
||||||
|
|
||||||
require('../alert.js').mockImplementation(() => <div />)
|
|
||||||
require('../notifications.js').mockImplementation(() => <div />)
|
|
||||||
const App = require('../app.js')
|
|
||||||
const activeStore = require('../../store/activeStore.js')
|
|
||||||
const dispatcher = require('../../dispatcher/dispatcher.js')
|
|
||||||
const streamStore = require('../../store/streamStore.js')
|
|
||||||
|
|
||||||
describe('app', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
dispatcher.dispatch.mockClear()
|
|
||||||
})
|
|
||||||
|
|
||||||
function render (active) {
|
|
||||||
streamStore.getStreams.mockReturnValue({
|
|
||||||
user1: { stream: 1 },
|
|
||||||
user2: { stream: 2 }
|
|
||||||
})
|
|
||||||
let component = TestUtils.renderIntoDocument(<div><App /></div>)
|
|
||||||
return ReactDOM.findDOMNode(component).children[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
it('should render div.app', () => {
|
|
||||||
let node = render()
|
|
||||||
expect(node.tagName).toBe('DIV')
|
|
||||||
expect(node.className).toBe('app')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should have rendered two videos', () => {
|
|
||||||
let node = render()
|
|
||||||
|
|
||||||
expect(node.querySelectorAll('video').length).toBe(2)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should mark .active video', () => {
|
|
||||||
activeStore.getActive.mockReturnValue('user1')
|
|
||||||
activeStore.isActive.mockImplementation(test => test === 'user1')
|
|
||||||
|
|
||||||
let node = render()
|
|
||||||
expect(node.querySelectorAll('.video-container').length).toBe(2)
|
|
||||||
expect(node.querySelectorAll('.video-container.active').length).toBe(1)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should dispatch mark-active on video click', () => {
|
|
||||||
let node = render()
|
|
||||||
|
|
||||||
TestUtils.Simulate.click(node.querySelectorAll('video')[1])
|
|
||||||
|
|
||||||
expect(dispatcher.dispatch.mock.calls).toEqual([[{
|
|
||||||
type: 'mark-active',
|
|
||||||
userId: 'user2'
|
|
||||||
}]])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
jest.unmock('../notifications.js')
|
|
||||||
|
|
||||||
const React = require('react')
|
|
||||||
const ReactDOM = require('react-dom')
|
|
||||||
const TestUtils = require('react-addons-test-utils')
|
|
||||||
|
|
||||||
const Notifications = require('../notifications.js')
|
|
||||||
const notificationsStore = require('../../store/notificationsStore.js')
|
|
||||||
|
|
||||||
describe('alert', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
notificationsStore.getNotifications.mockClear()
|
|
||||||
notificationsStore.getNotifications.mockReturnValue([])
|
|
||||||
})
|
|
||||||
|
|
||||||
function render (component) {
|
|
||||||
let rendered = TestUtils.renderIntoDocument(<div>{component}</div>)
|
|
||||||
return ReactDOM.findDOMNode(rendered)
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('render', () => {
|
|
||||||
it('should render notifications placeholder', () => {
|
|
||||||
let node = render(<Notifications />)
|
|
||||||
expect(node.querySelector('.notifications')).toBeTruthy()
|
|
||||||
expect(node.querySelector('.notifications .notification')).toBeFalsy()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should render notifications', () => {
|
|
||||||
notificationsStore.getNotifications.mockReturnValue([{
|
|
||||||
_id: 1,
|
|
||||||
message: 'message 1',
|
|
||||||
type: 'warning'
|
|
||||||
}, {
|
|
||||||
_id: 2,
|
|
||||||
message: 'message 2',
|
|
||||||
type: 'error'
|
|
||||||
}])
|
|
||||||
|
|
||||||
let node = render(<Notifications />)
|
|
||||||
expect(notificationsStore.getNotifications.mock.calls).toEqual([[ 10 ]])
|
|
||||||
|
|
||||||
let c = node.querySelector('.notifications')
|
|
||||||
expect(c).toBeTruthy()
|
|
||||||
expect(c.querySelectorAll('.notification').length).toBe(2)
|
|
||||||
expect(c.querySelector('.notification.warning').textContent)
|
|
||||||
.toEqual('message 1')
|
|
||||||
expect(c.querySelector('.notification.error').textContent)
|
|
||||||
.toEqual('message 2')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should render max X notifications', () => {
|
|
||||||
render(<Notifications max={1} />)
|
|
||||||
expect(notificationsStore.getNotifications.mock.calls).toEqual([[ 1 ]])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@ -1,5 +1,11 @@
|
|||||||
|
import { PENDING, FULFILLED, REJECTED } from 'redux-promise-middleware'
|
||||||
export const ME = '_me_'
|
export const ME = '_me_'
|
||||||
|
|
||||||
|
export const INIT = 'INIT'
|
||||||
|
export const INIT_PENDING = `${INIT}${PENDING}`
|
||||||
|
export const INIT_FULFILLED = `${INIT}${FULFILLED}`
|
||||||
|
export const INIT_REJECTED = `${INIT}${REJECTED}`
|
||||||
|
|
||||||
export const ALERT = 'ALERT'
|
export const ALERT = 'ALERT'
|
||||||
export const ALERT_DISMISS = 'ALERT_DISMISS'
|
export const ALERT_DISMISS = 'ALERT_DISMISS'
|
||||||
export const ALERT_CLEAR = 'ALERT_CLEAR'
|
export const ALERT_CLEAR = 'ALERT_CLEAR'
|
||||||
|
|||||||
27
src/client/containers/App.js
Normal file
27
src/client/containers/App.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import * as NotifyActions from '../actions/NotifyActions.js'
|
||||||
|
import * as CallActions from '../actions/CallActions.js'
|
||||||
|
import App from '../components/App.js'
|
||||||
|
import React from 'react'
|
||||||
|
import { bindActionCreators } from 'redux'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
import peers from '../peer/peers.js'
|
||||||
|
|
||||||
|
function mapStateToProps(state) {
|
||||||
|
return {
|
||||||
|
streams: state.streams.all,
|
||||||
|
alerts: state.alerts,
|
||||||
|
notifications: state.notifications,
|
||||||
|
active: state.streams.active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapDispatchToProps(dispatch) {
|
||||||
|
return {
|
||||||
|
activate: bindActionCreators(CallActions.activateStream, dispatch),
|
||||||
|
dismiss: bindActionCreators(NotifyActions.dismiss, dispatch),
|
||||||
|
init: bindActionCreators(CallActions.init, dispatch),
|
||||||
|
notify: bindActionCreators(NotifyActions.info, dispatch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(App)
|
||||||
@ -3,7 +3,7 @@ import Immutable from 'seamless-immutable'
|
|||||||
|
|
||||||
const defaultState = Immutable([])
|
const defaultState = Immutable([])
|
||||||
|
|
||||||
export default function alert (state = defaultState, action) {
|
export default function alerts (state = defaultState, action) {
|
||||||
switch (action && action.type) {
|
switch (action && action.type) {
|
||||||
case constants.ALERT:
|
case constants.ALERT:
|
||||||
return Immutable(state.asMutable().push(action.payload))
|
return Immutable(state.asMutable().push(action.payload))
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
import alerts from './alerts.js'
|
import alerts from './alerts.js'
|
||||||
import notifications from './notifications.js'
|
import notifications from './notifications.js'
|
||||||
import streams from './streams.js'
|
import streams from './streams.js'
|
||||||
|
import { combineReducers } from 'redux'
|
||||||
|
|
||||||
export default {
|
export default combineReducers({
|
||||||
alerts,
|
alerts,
|
||||||
notifications,
|
notifications,
|
||||||
streams
|
streams
|
||||||
}
|
})
|
||||||
|
|||||||
@ -1,24 +1,18 @@
|
|||||||
import * as constants from '../constants.js'
|
import * as constants from '../constants.js'
|
||||||
import Immutable from 'seamless-immutable'
|
import Immutable from 'seamless-immutable'
|
||||||
|
|
||||||
const defaultState = Immutable({
|
const defaultState = Immutable([])
|
||||||
notifications: []
|
|
||||||
})
|
|
||||||
|
|
||||||
export default function notify (state = defaultState, action) {
|
export default function notifications (state = defaultState, action) {
|
||||||
switch (action && action.type) {
|
switch (action && action.type) {
|
||||||
case constants.NOTIFY:
|
case constants.NOTIFY:
|
||||||
const notifications = state.notifications.asMutable()
|
const notifications = state.asMutable()
|
||||||
notifications.push(action.payload)
|
notifications.push(action.payload)
|
||||||
return state.merge({
|
return Immutable(notifications)
|
||||||
notifications
|
|
||||||
})
|
|
||||||
case constants.NOTIFY_DISMISS:
|
case constants.NOTIFY_DISMISS:
|
||||||
return state.merge({
|
return state.filter(n => n !== action.payload)
|
||||||
notifications: state.notifications.filter(n => n !== action.payload)
|
|
||||||
})
|
|
||||||
case constants.NOTIFY_CLEAR:
|
case constants.NOTIFY_CLEAR:
|
||||||
return state.merge({ notifications: [] })
|
return defaultState
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,12 +4,12 @@ import Immutable from 'seamless-immutable'
|
|||||||
|
|
||||||
const defaultState = Immutable({
|
const defaultState = Immutable({
|
||||||
active: null,
|
active: null,
|
||||||
streams: {}
|
all: {}
|
||||||
})
|
})
|
||||||
|
|
||||||
function addStream (state, action) {
|
function addStream (state, action) {
|
||||||
const { userId, stream } = action.payload
|
const { userId, stream } = action.payload
|
||||||
const streams = state.streams.merge({
|
const streams = state.all.merge({
|
||||||
[userId]: {
|
[userId]: {
|
||||||
userId,
|
userId,
|
||||||
stream,
|
stream,
|
||||||
@ -20,11 +20,11 @@ function addStream (state, action) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function removeStream (state, action) {
|
function removeStream (state, action) {
|
||||||
const streams = state.streams.without(action.payload.userId)
|
const streams = state.all.without(action.payload.userId)
|
||||||
return state.merge({ streams })
|
return state.merge({ streams })
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function stream (state = defaultState, action) {
|
export default function streams (state = defaultState, action) {
|
||||||
switch (action && action.type) {
|
switch (action && action.type) {
|
||||||
case constants.STREAM_ADD:
|
case constants.STREAM_ADD:
|
||||||
return addStream(state, action)
|
return addStream(state, action)
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
import logger from 'redux-logger'
|
import logger from 'redux-logger'
|
||||||
import reducer from './reducers'
|
import promiseMiddleware from 'redux-promise-middleware'
|
||||||
|
import reducers from './reducers'
|
||||||
import thunk from 'redux-thunk'
|
import thunk from 'redux-thunk'
|
||||||
import { applyMiddleware, createStore } from 'redux'
|
import { applyMiddleware, createStore } from 'redux'
|
||||||
|
|
||||||
|
export const middlewares = [thunk, promiseMiddleware(), logger]
|
||||||
|
|
||||||
export default createStore(
|
export default createStore(
|
||||||
reducer,
|
reducers,
|
||||||
applyMiddleware(thunk, logger)
|
applyMiddleware.apply(null, middlewares)
|
||||||
)
|
)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user