Fix old unit tests

This commit is contained in:
Jerko Steiner 2017-06-15 23:00:17 -04:00
parent 33b891f170
commit 46ec853280
13 changed files with 263 additions and 115 deletions

View File

@ -3,7 +3,8 @@
"extends": ["standard", "standard-react"], "extends": ["standard", "standard-react"],
"rules": { "rules": {
"max-len": [2, 80, 4], "max-len": [2, 80, 4],
"jsx-quotes": ["error", "prefer-double"] "jsx-quotes": ["error", "prefer-double"],
"padded-blocks": 0
}, },
"globals": { "globals": {
"expect": true, "expect": true,

10
__mocks__/simple-peer.js Normal file
View File

@ -0,0 +1,10 @@
import EventEmitter from 'events'
const Peer = jest.genMockFunction().mockImplementation(() => {
let peer = new EventEmitter()
peer.destroy = jest.genMockFunction()
peer.signal = jest.genMockFunction()
Peer.instances.push(peer)
return peer
})
Peer.instances = []
export default Peer

View File

@ -0,0 +1,3 @@
import configureStore from 'redux-mock-store'
import { middlewares } from '../middlewares.js'
export default configureStore(middlewares)({})

View File

@ -12,8 +12,6 @@ import { Provider } from 'react-redux'
import { init } from '../actions/CallActions.js' import { init } from '../actions/CallActions.js'
import { middlewares } from '../store.js' import { middlewares } from '../store.js'
// jest.useFakeTimers()
describe('App', () => { describe('App', () => {
let state let state
@ -25,7 +23,6 @@ describe('App', () => {
let component, node, store let component, node, store
function render() { function render() {
store = configureStore(middlewares)(state) store = configureStore(middlewares)(state)
console.log(store.getState())
component = TestUtils.renderIntoDocument( component = TestUtils.renderIntoDocument(
<Provider store={store}> <Provider store={store}>
<App /> <App />
@ -37,7 +34,6 @@ describe('App', () => {
describe('render', () => { describe('render', () => {
it('renders without issues', () => { it('renders without issues', () => {
render() render()
// jest.runAllTimers()
expect(node).toBeTruthy() expect(node).toBeTruthy()
expect(init.mock.calls.length).toBe(1) expect(init.mock.calls.length).toBe(1)
}) })

View File

@ -24,16 +24,16 @@ const _notify = (type, args) => dispatch => {
}, TIMEOUT) }, TIMEOUT)
} }
export const info = () => dispatch => { export const info = function() {
_notify('info', arguments) return dispatch => _notify('info', arguments)(dispatch)
} }
export const warn = () => dispatch => { export const warn = function() {
_notify('warning', arguments) return dispatch => _notify('warning', arguments)(dispatch)
} }
export const error = () => dispatch => { export const error = function() {
_notify('error', arguments) return dispatch => _notify('error', arguments)(dispatch)
} }
export function alert (message, dismissable) { export function alert (message, dismissable) {

10
src/client/middlewares.js Normal file
View File

@ -0,0 +1,10 @@
import logger from 'redux-logger'
import promiseMiddleware from 'redux-promise-middleware'
import thunk from 'redux-thunk'
export const middlewares = [thunk, promiseMiddleware()]
export const create = log => {
const m = middlewares.slice()
log && m.push(logger)
return m
}

View File

@ -1,8 +0,0 @@
'use strict'
const Peer = require('simple-peer')
function init (opts) {
return Peer(opts)
}
module.exports = { init }

View File

@ -1,30 +1,23 @@
jest.unmock('../handshake.js') jest.mock('simple-peer')
jest.unmock('../peers.js') jest.mock('../../store.js')
jest.unmock('events') jest.mock('../../callId.js')
jest.unmock('underscore') jest.mock('../../iceServers.js')
const EventEmitter = require('events').EventEmitter import * as constants from '../../constants.js'
const Peer = require('../Peer.js') import * as handshake from '../handshake.js'
const dispatcher = require('../../dispatcher/dispatcher.js') import Peer from 'simple-peer'
const handshake = require('../handshake.js') import peers from '../peers.js'
const peers = require('../peers.js') import store from '../../store.js'
import { EventEmitter } from 'events'
describe('handshake', () => { describe('handshake', () => {
let socket, peerInstances let socket
beforeEach(() => { beforeEach(() => {
socket = new EventEmitter() socket = new EventEmitter()
socket.id = 'a' socket.id = 'a'
peerInstances = []
Peer.init = jest.genMockFunction().mockImplementation(() => { Peer.instances = []
let peer = new EventEmitter() store.clearActions()
peer.destroy = jest.genMockFunction()
peer.signal = jest.genMockFunction()
peerInstances.push(peer)
return peer
})
dispatcher.dispatch.mockClear()
}) })
afterEach(() => peers.clear()) afterEach(() => peers.clear())
@ -40,7 +33,7 @@ describe('handshake', () => {
initiator: 'a' initiator: 'a'
} }
socket.emit('users', payload) socket.emit('users', payload)
expect(peerInstances.length).toBe(1) expect(Peer.instances.length).toBe(1)
// when // when
payload = { payload = {
@ -50,9 +43,9 @@ describe('handshake', () => {
socket.emit('users', payload) socket.emit('users', payload)
// then // then
expect(peerInstances.length).toBe(2) expect(Peer.instances.length).toBe(2)
expect(peerInstances[0].destroy.mock.calls.length).toBe(1) expect(Peer.instances[0].destroy.mock.calls.length).toBe(1)
expect(peerInstances[1].destroy.mock.calls.length).toBe(0) expect(Peer.instances[1].destroy.mock.calls.length).toBe(0)
}) })
}) })
@ -73,8 +66,8 @@ describe('handshake', () => {
data data
}) })
expect(peerInstances.length).toBe(1) expect(Peer.instances.length).toBe(1)
expect(peerInstances[0].signal.mock.calls.length).toBe(1) expect(Peer.instances[0].signal.mock.calls.length).toBe(1)
}) })
it('does nothing if no peer', () => { it('does nothing if no peer', () => {
@ -83,8 +76,8 @@ describe('handshake', () => {
data data
}) })
expect(peerInstances.length).toBe(1) expect(Peer.instances.length).toBe(1)
expect(peerInstances[0].signal.mock.calls.length).toBe(0) expect(Peer.instances[0].signal.mock.calls.length).toBe(0)
}) })
}) })
}) })
@ -101,8 +94,8 @@ describe('handshake', () => {
initiator: 'a', initiator: 'a',
users: [{ id: 'a' }, { id: 'b'}] users: [{ id: 'a' }, { id: 'b'}]
}) })
expect(peerInstances.length).toBe(1) expect(Peer.instances.length).toBe(1)
peer = peerInstances[0] peer = Peer.instances[0]
expect(ready).toBeDefined() expect(ready).toBeDefined()
}) })
@ -130,29 +123,37 @@ describe('handshake', () => {
describe('stream', () => { describe('stream', () => {
it('adds a stream to streamStore', () => { it('adds a stream to streamStore', () => {
expect(dispatcher.dispatch.mock.calls.length).toBe(0) store.clearActions()
let stream = {} let stream = {}
peer.emit('stream', stream) peer.emit('stream', stream)
expect(dispatcher.dispatch.mock.calls.length).toBe(1) expect(store.getActions()).toEqual([{
expect(dispatcher.dispatch.mock.calls).toEqual([[{ type: constants.STREAM_ADD,
type: 'add-stream', payload: {
userId: 'b', stream,
stream userId: 'b'
}]]) }
}])
}) })
}) })
describe('close', () => { describe('close', () => {
it('removes stream from streamStore', () => { it('removes stream from streamStore', () => {
store.clearActions()
peer.emit('close') peer.emit('close')
expect(dispatcher.dispatch.mock.calls.length).toBe(1) expect(store.getActions()).toEqual([{
expect(dispatcher.dispatch.mock.calls).toEqual([[{ type: constants.NOTIFY,
type: 'remove-stream', payload: {
message: 'Peer connection closed',
type: 'error'
}
}, {
type: constants.STREAM_REMOVE,
payload: {
userId: 'b' userId: 'b'
}]]) }
}])
}) })
}) })
}) })

View File

@ -1,36 +1,68 @@
jest.unmock('../peers.js') jest.mock('../../window/video.js')
jest.mock('../../callId.js')
jest.mock('../../iceServers.js')
jest.mock('../../store.js')
// const configureStore = require('redux-mock-store').default
// const { middlewares } = require('../../middlewares.js')
// return configureStore(middlewares)({})
// })
jest.mock('simple-peer')
// const EventEmitter = require('events').EventEmitter
// const Peer = jest.genMockFunction().mockImplementation(() => {
// let peer = new EventEmitter()
// peer.destroy = jest.genMockFunction()
// peer.signal = jest.genMockFunction()
// Peer.instances.push(peer)
// return peer
// })
// Peer.instances = []
// return Peer
// })
const EventEmitter = require('events').EventEmitter import * as constants from '../../constants.js'
const Peer = require('../Peer.js') import Peer from 'simple-peer'
const dispatcher = require('../../dispatcher/dispatcher.js') import peers from '../peers.js'
const notify = require('../../action/notify.js') import store from '../../store.js'
const peers = require('../peers.js') import { EventEmitter } from 'events'
import { play } from '../../window/video.js'
const { dispatch } = store
describe('peers', () => { describe('peers', () => {
function createSocket () { function createSocket () {
let socket = new EventEmitter() const socket = new EventEmitter()
socket.id = 'user1' socket.id = 'user1'
return socket return socket
} }
let socket, stream, peerInstances, user let socket, stream, user
beforeEach(() => { beforeEach(() => {
dispatcher.dispatch.mockClear() store.clearActions()
notify.warn.mockClear()
user = { id: 'user2' } user = { id: 'user2' }
socket = createSocket() socket = createSocket()
peerInstances = [] Peer.instances = []
Peer.mockClear()
play.mockClear()
stream = { stream: true } stream = { stream: true }
})
Peer.init = jest.genMockFunction().mockImplementation(() => { const actions = {
let peer = new EventEmitter() connecting: {
peer.destroy = jest.genMockFunction() type: constants.NOTIFY,
peer.signal = jest.genMockFunction() payload: {
peerInstances.push(peer) message: 'Connecting to peer...',
return peer type: 'warning'
}) }
}) },
established: {
type: constants.NOTIFY,
payload: {
message: 'Peer connection established',
type: 'warning'
}
}
}
afterEach(() => peers.clear()) afterEach(() => peers.clear())
@ -38,31 +70,32 @@ describe('peers', () => {
it('creates a new peer', () => { it('creates a new peer', () => {
peers.create({ socket, user, initiator: 'user2', stream }) peers.create({ socket, user, initiator: 'user2', stream })
expect(notify.warn.mock.calls).toEqual([[ 'Connecting to peer...' ]]) expect(store.getActions()).toEqual([actions.connecting])
// expect(notify.warn.mock.calls).toEqual([[ 'Connecting to peer...' ]])
expect(peerInstances.length).toBe(1) expect(Peer.instances.length).toBe(1)
expect(Peer.init.mock.calls.length).toBe(1) expect(Peer.mock.calls.length).toBe(1)
expect(Peer.init.mock.calls[0][0].initiator).toBe(false) expect(Peer.mock.calls[0][0].initiator).toBe(false)
expect(Peer.init.mock.calls[0][0].stream).toBe(stream) expect(Peer.mock.calls[0][0].stream).toBe(stream)
}) })
it('sets initiator correctly', () => { it('sets initiator correctly', () => {
peers.create({ socket, user, initiator: 'user1', stream }) peers.create({ socket, user, initiator: 'user1', stream })
expect(peerInstances.length).toBe(1) expect(Peer.instances.length).toBe(1)
expect(Peer.init.mock.calls.length).toBe(1) expect(Peer.mock.calls.length).toBe(1)
expect(Peer.init.mock.calls[0][0].initiator).toBe(true) expect(Peer.mock.calls[0][0].initiator).toBe(true)
expect(Peer.init.mock.calls[0][0].stream).toBe(stream) expect(Peer.mock.calls[0][0].stream).toBe(stream)
}) })
it('destroys old peer before creating new one', () => { it('destroys old peer before creating new one', () => {
peers.create({ socket, user, initiator: 'user2', stream }) peers.create({ socket, user, initiator: 'user2', stream })
peers.create({ socket, user, initiator: 'user2', stream }) peers.create({ socket, user, initiator: 'user2', stream })
expect(peerInstances.length).toBe(2) expect(Peer.instances.length).toBe(2)
expect(Peer.init.mock.calls.length).toBe(2) expect(Peer.mock.calls.length).toBe(2)
expect(peerInstances[0].destroy.mock.calls.length).toBe(1) expect(Peer.instances[0].destroy.mock.calls.length).toBe(1)
expect(peerInstances[1].destroy.mock.calls.length).toBe(0) expect(Peer.instances[1].destroy.mock.calls.length).toBe(0)
}) })
}) })
@ -71,21 +104,21 @@ describe('peers', () => {
beforeEach(() => { beforeEach(() => {
peers.create({ socket, user, initiator: 'user1', stream }) peers.create({ socket, user, initiator: 'user1', stream })
notify.warn.mockClear() peer = Peer.instances[0]
peer = peerInstances[0]
}) })
describe('connect', () => { describe('connect', () => {
beforeEach(() => peer.emit('connect')) beforeEach(() => peer.emit('connect'))
it('sends a notification', () => { it('sends a notification', () => {
expect(notify.warn.mock.calls).toEqual([[ expect(store.getActions()).toEqual([
'Peer connection established' actions.connecting,
]]) actions.established
])
}) })
it('dispatches "play" action', () => { it('dispatches "play" action', () => {
expect(dispatcher.dispatch.mock.calls).toEqual([[{ type: 'play' }]]) expect(play.mock.calls.length).toBe(1)
}) })
}) })
}) })
@ -98,7 +131,7 @@ describe('peers', () => {
it('returns Peer instance when found', () => { it('returns Peer instance when found', () => {
peers.create({ socket, user, initiator: 'user2', stream }) peers.create({ socket, user, initiator: 'user2', stream })
expect(peers.get(user.id)).toBe(peerInstances[0]) expect(peers.get(user.id)).toBe(Peer.instances[0])
}) })
}) })
@ -121,7 +154,7 @@ describe('peers', () => {
peers.destroy(user.id) peers.destroy(user.id)
expect(peerInstances[0].destroy.mock.calls.length).toEqual(1) expect(Peer.instances[0].destroy.mock.calls.length).toEqual(1)
}) })
it('throws no error when peer missing', () => { it('throws no error when peer missing', () => {
@ -140,8 +173,8 @@ describe('peers', () => {
peers.clear() peers.clear()
expect(peerInstances[0].destroy.mock.calls.length).toEqual(1) expect(Peer.instances[0].destroy.mock.calls.length).toEqual(1)
expect(peerInstances[1].destroy.mock.calls.length).toEqual(1) expect(Peer.instances[1].destroy.mock.calls.length).toEqual(1)
expect(peers.getIds()).toEqual([]) expect(peers.getIds()).toEqual([])
}) })

View File

@ -1,10 +1,11 @@
import NotifyActions from '../actions/NotifyActions.js' import * as NotifyActions from '../actions/NotifyActions.js'
import _ from 'underscore' import _ from 'underscore'
import _debug from 'debug' import _debug from 'debug'
import peers from './peers.js' import peers from './peers.js'
import { dispatch } from '../store.js' import store from '../store.js'
const debug = _debug('peercalls') const debug = _debug('peercalls')
const { dispatch } = store
export function init (socket, roomName, stream) { export function init (socket, roomName, stream) {
function createPeer (user, initiator) { function createPeer (user, initiator) {

View File

@ -1,13 +1,14 @@
import CallActions from '../actions/CallActions.js' import * as CallActions from '../actions/CallActions.js'
import NotifyActions from '../actions/NotifyActions.js' import * as NotifyActions from '../actions/NotifyActions.js'
import Peer from './Peer.js' import Peer from 'simple-peer'
import _ from 'underscore' import _ from 'underscore'
import _debug from 'debug' import _debug from 'debug'
import iceServers from '../iceServers.js' import iceServers from '../iceServers.js'
import { dispatch } from '../store.js' import store from '../store.js'
import { play } from '../window/video.js' import { play } from '../window/video.js'
const debug = _debug('peercalls') const debug = _debug('peercalls')
const { dispatch } = store
let peers = {} let peers = {}
@ -31,7 +32,7 @@ function create ({ socket, user, initiator, stream }) {
destroy(user.id) destroy(user.id)
} }
const peer = peers[user.id] = Peer.init({ const peer = peers[user.id] = new Peer({
initiator: socket.id === initiator, initiator: socket.id === initiator,
stream, stream,
config: { iceServers } config: { iceServers }

View File

@ -1,10 +1,10 @@
import logger from 'redux-logger' import { create } from './middlewares.js'
import promiseMiddleware from 'redux-promise-middleware'
import reducers from './reducers' import reducers from './reducers'
import thunk from 'redux-thunk'
import { applyMiddleware, createStore } from 'redux' import { applyMiddleware, createStore } from 'redux'
export const middlewares = [thunk, promiseMiddleware(), logger] export const middlewares = create(
window.localStorage && window.localStorage.debug
)
export default createStore( export default createStore(
reducers, reducers,

View File

@ -0,0 +1,100 @@
import Promise from 'bluebird'
import createObjectURL from '../createObjectURL.js'
import getUserMedia from '../getUserMedia.js'
import navigator from '../navigator.js'
import { play } from '../video.js'
describe('window', () => {
describe('getUserMedia', () => {
class MediaStream {}
const stream = new MediaStream()
const constraints = { video: true }
afterEach(() => {
delete navigator.mediaDevices
delete navigator.getUserMedia
delete navigator.webkitGetUserMedia
})
it('calls navigator.mediaDevices.getUserMedia', () => {
const promise = Promise.resolve(stream)
navigator.mediaDevices = {
getUserMedia: jest.fn().mockReturnValue(promise)
}
expect(getUserMedia(constraints)).toBe(promise)
})
;['getUserMedia', 'webkitGetUserMedia'].forEach((method) => {
it(`it calls navigator.${method} as a fallback`, () => {
navigator[method] = jest.fn()
.mockImplementation(
(constraints, onSuccess, onError) => onSuccess(stream)
)
return getUserMedia(constraints)
.then(s => expect(s).toBe(stream))
})
})
it('throws error when no supported method', done => {
getUserMedia(constraints)
.asCallback(err => {
expect(err).toBeTruthy()
expect(err.message).toBe('Browser unsupported')
done()
})
})
})
describe('play', () => {
let v1, v2
beforeEach(() => {
v1 = window.document.createElement('video')
v2 = window.document.createElement('video')
window.document.body.appendChild(v1)
window.document.body.appendChild(v2)
v1.play = jest.fn()
v2.play = jest.fn()
})
afterEach(() => {
window.document.body.removeChild(v1)
window.document.body.removeChild(v2)
})
it('gets all videos and plays them', () => {
play()
expect(v1.play.mock.calls.length).toBe(1)
expect(v2.play.mock.calls.length).toBe(1)
})
it('does not fail on error', () => {
v1.play.mockImplementation(() => { throw new Error('test') })
play()
expect(v1.play.mock.calls.length).toBe(1)
expect(v2.play.mock.calls.length).toBe(1)
})
})
describe('navigator', () => {
it('exposes window.navigator', () => {
expect(navigator).toBe(window.navigator)
})
})
describe('createObjectURL', () => {
it('calls window.URL.createObjectURL', () => {
window.URL.createObjectURL = jest.fn().mockReturnValue('test')
expect(createObjectURL()).toBe('test')
})
})
})