Fix broken tests

This commit is contained in:
Jerko Steiner 2019-11-11 23:10:10 -03:00
parent 7e5c7db3f9
commit 6d3201d1fe
17 changed files with 124 additions and 129 deletions

View File

@ -39,6 +39,14 @@ describe('reducers/alerts', () => {
message: 'Connected to server socket',
type: 'warning'
}
}, {
type: constants.MESSAGE_ADD,
payload: {
image: null,
message: 'Connected to server socket',
timestamp: jasmine.any(String),
userId: '[PeerCalls]'
}
}])
await promise
expect(SocketActions.handshake.mock.calls).toEqual([[{
@ -62,6 +70,14 @@ describe('reducers/alerts', () => {
message: 'Connected to server socket',
type: 'warning'
}
}, {
type: constants.MESSAGE_ADD,
payload: {
image: null,
message: 'Connected to server socket',
timestamp: jasmine.any(String),
userId: '[PeerCalls]'
}
}, {
type: constants.NOTIFY,
payload: {
@ -69,6 +85,14 @@ describe('reducers/alerts', () => {
message: 'Server socket disconnected',
type: 'error'
}
}, {
type: constants.MESSAGE_ADD,
payload: {
image: null,
message: 'Server socket disconnected',
timestamp: jasmine.any(String),
userId: '[PeerCalls]'
}
}])
await promise
})

View File

@ -9,8 +9,3 @@ export const addMessage = ({ userId, message, timestamp, image }) => ({
image
}
})
export const loadHistory = messages => ({
type: constants.MESSAGES_HISTORY,
messages
})

View File

@ -49,7 +49,7 @@ class PeerHandler {
const { dispatch, user } = this
const message = JSON.parse(new window.TextDecoder('utf-8').decode(object))
debug('peer: %s, message: %o', user.id, object)
switch (object.type) {
switch (message.type) {
case 'file':
dispatch(ChatActions.addMessage({
userId: user.id,
@ -143,18 +143,26 @@ export const destroyPeers = () => ({
export const sendMessage = message => (dispatch, getState) => {
const { peers } = getState()
dispatch(NotifyActions.info('Sending message type: {0} to {1} peers.',
message.type, Object.keys(peers).length))
_.each(peers, peer => {
debug('Sending message type: %s to %s peers.',
message.type, Object.keys(peers).length)
_.each(peers, (peer, userId) => {
switch (message.type) {
case 'file':
dispatch(ChatActions.addMessage({
userId: 'You',
message: 'Send file: "' +
message.payload.name + '" to peer: ' + peer._id,
message.payload.name + '" to peer: ' + userId,
timestamp: new Date().toLocaleString(),
image: message.payload.data
}))
break
default:
dispatch(ChatActions.addMessage({
userId: 'You',
message: message.payload,
timestamp: new Date().toLocaleString(),
image: null
}))
}
peer.send(JSON.stringify(message))
})

View File

@ -96,16 +96,15 @@ describe('PeerActions', () => {
})
it('decodes a message', () => {
const message = 'test'
const object = JSON.stringify({ message })
const payload = 'test'
const object = JSON.stringify({ payload })
peer.emit('data', Buffer.from(object, 'utf-8'))
const { notifications } = store.getState()
const keys = Object.keys(notifications)
const n = notifications[keys[keys.length - 1]]
expect(n).toEqual({
id: jasmine.any(String),
type: 'info',
message: `${user.id}: ${message}`
const { messages } = store.getState()
expect(messages[messages.length - 1]).toEqual({
userId: 'user2',
timestamp: jasmine.any(String),
image: null,
message: 'test'
})
})
})
@ -158,12 +157,12 @@ describe('PeerActions', () => {
})
it('sends a message to all peers', () => {
store.dispatch(PeerActions.sendMessage('test'))
store.dispatch(PeerActions.sendMessage({ payload: 'test', type: 'text' }))
const { peers } = store.getState()
expect(peers['user2'].send.mock.calls)
.toEqual([[ '{"message":"test"}' ]])
.toEqual([[ '{"payload":"test","type":"text"}' ]])
expect(peers['user3'].send.mock.calls)
.toEqual([[ '{"message":"test"}' ]])
.toEqual([[ '{"payload":"test","type":"text"}' ]])
})
})

View File

@ -1,4 +1,3 @@
import * as ChatActions from '../actions/ChatActions.js'
import * as NotifyActions from '../actions/NotifyActions.js'
import * as PeerActions from '../actions/PeerActions.js'
import * as constants from '../constants.js'
@ -42,16 +41,6 @@ class SocketHandler {
.filter(id => !newUsersMap[id])
.forEach(id => peers[id].destroy())
}
handleMessages = (messages) => {
const { dispatch } = this
debug('socket messages: %o', messages)
dispatch(ChatActions.loadHistory(messages))
}
handleNewMessage = (payload) => {
const { dispatch } = this
debug('socket message: %o', payload)
dispatch(ChatActions.addMessage(payload))
}
}
export function handshake ({ socket, roomName, stream }) {
@ -66,8 +55,6 @@ export function handshake ({ socket, roomName, stream }) {
socket.on(constants.SOCKET_EVENT_SIGNAL, handler.handleSignal)
socket.on(constants.SOCKET_EVENT_USERS, handler.handleUsers)
socket.on(constants.SOCKET_EVENT_MESSAGES, handler.handleMessages)
socket.on(constants.SOCKET_EVENT_NEW_MESSAGE, handler.handleNewMessage)
debug('socket.id: %s', socket.id)
debug('emit ready for room: %s', roomName)

View File

@ -15,7 +15,6 @@ export default class App extends React.PureComponent {
dismissAlert: PropTypes.func.isRequired,
init: PropTypes.func.isRequired,
notifications: PropTypes.objectOf(NotificationPropTypes).isRequired,
notify: PropTypes.func.isRequired,
messages: PropTypes.arrayOf(MessagePropTypes).isRequired,
peers: PropTypes.object.isRequired,
sendMessage: PropTypes.func.isRequired,
@ -55,7 +54,6 @@ export default class App extends React.PureComponent {
alerts,
dismissAlert,
notifications,
notify,
messages,
onSendFile,
peers,
@ -79,7 +77,6 @@ export default class App extends React.PureComponent {
<Notifications notifications={notifications} />
<Chat
messages={messages}
notify={notify}
onClose={this.handleHideChat}
sendMessage={sendMessage}
videos={videos}

View File

@ -2,7 +2,6 @@ import Input from './Input.js'
import PropTypes from 'prop-types'
import React from 'react'
import classnames from 'classnames'
import socket from '../socket.js'
export const MessagePropTypes = PropTypes.shape({
userId: PropTypes.string.isRequired,
@ -11,11 +10,26 @@ export const MessagePropTypes = PropTypes.shape({
image: PropTypes.string
})
function Message (props) {
const { message } = props
return (
<p className="message-text">
{message.image && (
<img src={message.image} width="100%" />
)}
{message.message}
</p>
)
}
Message.propTypes = {
message: MessagePropTypes
}
export default class Chat extends React.PureComponent {
static propTypes = {
visible: PropTypes.bool.isRequired,
messages: PropTypes.arrayOf(MessagePropTypes).isRequired,
notify: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
sendMessage: PropTypes.func.isRequired,
videos: PropTypes.object.isRequired
@ -35,7 +49,7 @@ export default class Chat extends React.PureComponent {
this.scrollToBottom()
}
render () {
const { messages, videos, notify, sendMessage } = this.props
const { messages, videos, sendMessage } = this.props
return (
<div className={classnames('chat-container', {
show: this.props.visible
@ -53,7 +67,7 @@ export default class Chat extends React.PureComponent {
{messages.length ? (
messages.map((message, i) => (
<div key={i}>
{message.userId === socket.id ? (
{message.userId === 'You' ? (
<div className="chat-item chat-item-me">
<div className="message">
<span className="message-user-name">
@ -61,7 +75,7 @@ export default class Chat extends React.PureComponent {
</span>
<span className="icon icon-schedule" />
<time className="message-time">{message.timestamp}</time>
<p className="message-text">{message.message}</p>
<Message message={message} />
</div>
{message.image ? (
<img className="chat-item-img" src={message.image} />
@ -82,12 +96,7 @@ export default class Chat extends React.PureComponent {
</span>
<span className="icon icon-schedule" />
<time className="message-time">{message.timestamp}</time>
<p className="message-text">
{message.image && (
<img src={message.image} width="100%" />
)}
{message.message}
</p>
<Message message={message} />
</div>
</div>
)}
@ -104,7 +113,6 @@ export default class Chat extends React.PureComponent {
<Input
videos={videos}
notify={notify}
sendMessage={sendMessage}
/>
</div>

View File

@ -1,11 +1,8 @@
import PropTypes from 'prop-types'
import React from 'react'
import socket from '../socket.js'
export default class Input extends React.PureComponent {
static propTypes = {
videos: PropTypes.object.isRequired,
notify: PropTypes.func.isRequired,
sendMessage: PropTypes.func.isRequired
}
constructor () {
@ -35,35 +32,27 @@ export default class Input extends React.PureComponent {
})
}
submit = () => {
const { videos, notify, sendMessage } = this.props
const { sendMessage } = this.props
const { message } = this.state
if (message) {
notify('You: ' + message)
sendMessage(message)
const userId = socket.id
const timestamp = new Date().toLocaleString('en-US', {
hour: 'numeric',
minute: 'numeric',
hour12: false
sendMessage({
payload: message,
type: 'text'
})
let image = null
// let image = null
// take snapshoot
try {
const video = videos[userId]
if (video) {
const canvas = document.createElement('canvas')
canvas.height = video.videoHeight
canvas.width = video.videoWidth
const avatar = canvas.getContext('2d')
avatar.drawImage(video, 0, 0, canvas.width, canvas.height)
image = canvas.toDataURL()
}
} catch (e) {}
const payload = { userId, message, timestamp, image }
socket.emit('new_message', payload)
// // take snapshoot
// try {
// const video = videos[userId]
// if (video) {
// const canvas = document.createElement('canvas')
// canvas.height = video.videoHeight
// canvas.width = video.videoWidth
// const avatar = canvas.getContext('2d')
// avatar.drawImage(video, 0, 0, canvas.width, canvas.height)
// image = canvas.toDataURL()
// }
// } catch (e) {}
}
this.setState({ message: '' })
}

View File

@ -39,8 +39,8 @@ describe('components/Input', () => {
it('sends a message', () => {
TestUtils.Simulate.submit(node)
expect(input.value).toBe('')
expect(sendMessage.mock.calls).toEqual([[ message ]])
expect(notify.mock.calls).toEqual([[ `You: ${message}` ]])
expect(sendMessage.mock.calls)
.toEqual([[ { payload: message, type: 'text' } ]])
})
})
@ -50,8 +50,8 @@ describe('components/Input', () => {
key: 'Enter'
})
expect(input.value).toBe('')
expect(sendMessage.mock.calls).toEqual([[ message ]])
expect(notify.mock.calls).toEqual([[ `You: ${message}` ]])
expect(sendMessage.mock.calls)
.toEqual([[ { payload: message, type: 'text' } ]])
})
it('does nothing when other key pressed', () => {
@ -59,7 +59,6 @@ describe('components/Input', () => {
key: 'test'
})
expect(sendMessage.mock.calls.length).toBe(0)
expect(notify.mock.calls.length).toBe(0)
})
})

View File

@ -47,9 +47,9 @@ export default class Toolbar extends React.PureComponent {
handleSendFile = () => {
this.file.current.click()
}
handleSelectFiles = () => {
handleSelectFiles = (event) => {
Array
.from(this.file.current.files)
.from(event.target.files)
.forEach(file => this.props.onSendFile(file))
}
render () {

View File

@ -17,20 +17,23 @@ describe('components/Toolbar', () => {
return <Toolbar
chatVisible={this.props.chatVisible}
onToggleChat={this.props.onToggleChat}
onSendFile={this.props.onSendFile}
messages={this.props.messages}
stream={this.state.stream || this.props.stream}
/>
}
}
let component, node, mediaStream, url, onToggleChat
let component, node, mediaStream, url, onToggleChat, onSendFile
function render () {
mediaStream = new MediaStream()
onToggleChat = jest.fn()
onSendFile = jest.fn()
component = TestUtils.renderIntoDocument(
<ToolbarWrapper
chatVisible
onToggleChat={onToggleChat}
onSendFile={onSendFile}
messages={[]}
stream={{ mediaStream, url }}
/>
@ -38,10 +41,8 @@ describe('components/Toolbar', () => {
node = ReactDOM.findDOMNode(component)
}
describe('render', () => {
it('should not fail', () => {
render()
})
beforeEach(() => {
render()
})
describe('handleChatClick', () => {
@ -85,4 +86,28 @@ describe('components/Toolbar', () => {
})
})
describe('handleSendFile', () => {
it('triggers input dialog', () => {
const sendFileButton = node.querySelector('.send-file')
const click = jest.fn()
const file = node.querySelector('input[type=file]')
file.click = click
TestUtils.Simulate.click(sendFileButton)
expect(click.mock.calls.length).toBe(1)
})
})
describe('handleSelectFiles', () => {
it('iterates through files and calls onSendFile for each', () => {
const file = node.querySelector('input[type=file]')
const files = [{ name: 'first' }]
TestUtils.Simulate.change(file, {
target: {
files
}
})
expect(onSendFile.mock.calls).toEqual([[ files[0] ]])
})
})
})

View File

@ -18,7 +18,6 @@ export const NOTIFY_DISMISS = 'NOTIFY_DISMISS'
export const NOTIFY_CLEAR = 'NOTIFY_CLEAR'
export const MESSAGE_ADD = 'MESSAGE_ADD'
export const MESSAGES_HISTORY = 'MESSAGES_HISTORY'
export const PEER_ADD = 'PEER_ADD'
export const PEER_REMOVE = 'PEER_REMOVE'
@ -33,8 +32,6 @@ export const PEER_EVENT_DATA = 'data'
export const SOCKET_EVENT_SIGNAL = 'signal'
export const SOCKET_EVENT_USERS = 'users'
export const SOCKET_EVENT_MESSAGES = 'messages'
export const SOCKET_EVENT_NEW_MESSAGE = 'new_message'
export const STREAM_ADD = 'PEER_STREAM_ADD'
export const STREAM_REMOVE = 'PEER_STREAM_REMOVE'

View File

@ -23,7 +23,6 @@ function mapDispatchToProps (dispatch) {
sendMessage: bindActionCreators(PeerActions.sendMessage, dispatch),
dismissAlert: bindActionCreators(NotifyActions.dismissAlert, dispatch),
init: bindActionCreators(CallActions.init, dispatch),
notify: bindActionCreators(NotifyActions.info, dispatch),
onSendFile: bindActionCreators(PeerActions.sendFile, dispatch)
}
}

View File

@ -9,8 +9,6 @@ export default function messages (state = defaultState, action) {
const messages = state.asMutable()
messages.push(action.payload)
return Immutable(messages)
case constants.MESSAGES_HISTORY:
return Immutable(action.messages)
default:
return state
}

View File

@ -17,12 +17,4 @@ describe('reducers/messages', () => {
})
})
describe('messageHistory', () => {
it('get chat message hisotry', () => {
let state = messages()
state = messages(state, ChatActions.loadHistory([]))
expect(state).toEqual([])
})
})
})

View File

@ -2,8 +2,6 @@
const debug = require('debug')('peer-calls:socket')
const _ = require('underscore')
const messages = {}
module.exports = function (socket, io) {
socket.on('signal', payload => {
// debug('signal: %s, payload: %o', socket.id, payload)
@ -13,11 +11,6 @@ module.exports = function (socket, io) {
})
})
socket.on('new_message', payload => {
addMesssage(socket.room, payload)
io.to(socket.room).emit('new_message', payload)
})
socket.on('ready', roomName => {
debug('ready: %s, room: %s', socket.id, roomName)
if (socket.room) socket.leave(socket.room)
@ -26,17 +19,13 @@ module.exports = function (socket, io) {
socket.room = roomName
let users = getUsers(roomName)
let messages = getMesssages(roomName)
debug('ready: %s, room: %s, users: %o, messages: %o',
socket.id, roomName, users, messages)
debug('ready: %s, room: %s, users: %o', socket.id, roomName, users)
io.to(roomName).emit('users', {
initiator: socket.id,
users
})
io.to(roomName).emit('messages', messages)
})
function getUsers (roomName) {
@ -45,14 +34,4 @@ module.exports = function (socket, io) {
})
}
function getMesssages (roomName) {
if (_.isUndefined(messages[roomName])) {
messages[roomName] = []
}
return messages[roomName]
}
function addMesssage (roomName, payload) {
getMesssages(roomName).push(payload)
}
}

View File

@ -83,7 +83,7 @@ describe('server/socket', () => {
it('should emit users', () => {
socket.emit('ready', 'room3')
expect(io.to.mock.calls).toEqual([[ 'room3' ], [ 'room3' ]])
expect(io.to.mock.calls).toEqual([[ 'room3' ]])
expect(io.to('room3').emit.mock.calls).toEqual([
[
'users', {
@ -96,8 +96,7 @@ describe('server/socket', () => {
id: 'socket2'
}]
}
],
['messages', []]
]
])
})
})