System chat messages (#7771)

* fix: removed duplicate checkContent call in addMessage

addMessage is called in one place (sendMessage), and the checks
are already contained there. addMessage is the lower level call
and so should be called only from within core itself.

* feat: #7330 chat system messages for join, leave, rename

* fix: add back content checking in .addMessage();

* fix: tests, and added .addSystemMessage() method

Tests were relying on message indices that changed due to the
new system messages.

* feat: add tests for system chat messages

* refactor: rewrite half of src/messaging/rooms.js, fix tests

* feat: #7743 messaging/room.js

* fix: tests for messaging/room.js, #7743

* fix: trying to fix tests

* fix: omg :rage2:
This commit is contained in:
Julian Lam
2019-07-19 12:20:11 -04:00
committed by GitHub
parent 28151f86da
commit 4fb271c684
7 changed files with 264 additions and 295 deletions

View File

@@ -35,6 +35,10 @@
"chat.show-ip": "Show IP", "chat.show-ip": "Show IP",
"chat.owner": "Room Owner", "chat.owner": "Room Owner",
"chat.system.user-join": "%1 has joined the room",
"chat.system.user-leave": "%1 has left the room",
"chat.system.room-rename": "%2 has renamed this room: %1",
"composer.compose": "Compose", "composer.compose": "Compose",
"composer.show_preview": "Show Preview", "composer.show_preview": "Show Preview",
"composer.hide_preview": "Hide Preview", "composer.hide_preview": "Hide Preview",

View File

@@ -94,11 +94,19 @@ define('forum/chats/messages', ['components', 'sounds', 'translator', 'benchpres
messages.parseMessage = function (data, callback) { messages.parseMessage = function (data, callback) {
function done(html) {
translator.translate(html, callback);
}
if (Array.isArray(data)) {
Benchpress.parse('partials/chats/message' + (Array.isArray(data) ? 's' : ''), { Benchpress.parse('partials/chats/message' + (Array.isArray(data) ? 's' : ''), {
messages: data, messages: data,
}, function (html) { }, done);
translator.translate(html, callback); } else {
}); Benchpress.parse('partials/chats/' + (data.system ? 'system-message' : 'message'), {
messages: data,
}, done);
}
}; };

View File

@@ -53,6 +53,7 @@ module.exports = function (Messaging) {
var mid; var mid;
var message; var message;
var isNewSet; var isNewSet;
const timestamp = data.timestamp || new Date().getTime();
async.waterfall([ async.waterfall([
function (next) { function (next) {
@@ -65,10 +66,11 @@ module.exports = function (Messaging) {
mid = _mid; mid = _mid;
message = { message = {
content: String(data.content), content: String(data.content),
timestamp: data.timestamp, timestamp: timestamp,
fromuid: data.uid, fromuid: data.uid,
roomId: data.roomId, roomId: data.roomId,
deleted: 0, deleted: 0,
system: data.system || 0,
}; };
if (data.ip) { if (data.ip) {
message.ip = data.ip; message.ip = data.ip;
@@ -80,7 +82,7 @@ module.exports = function (Messaging) {
db.setObject('message:' + mid, message, next); db.setObject('message:' + mid, message, next);
}, },
function (next) { function (next) {
Messaging.isNewSet(data.uid, data.roomId, data.timestamp, next); Messaging.isNewSet(data.uid, data.roomId, timestamp, next);
}, },
function (_isNewSet, next) { function (_isNewSet, next) {
isNewSet = _isNewSet; isNewSet = _isNewSet;
@@ -91,8 +93,8 @@ module.exports = function (Messaging) {
}, },
function (uids, next) { function (uids, next) {
async.parallel([ async.parallel([
async.apply(Messaging.addRoomToUsers, data.roomId, uids, data.timestamp), async.apply(Messaging.addRoomToUsers, data.roomId, uids, timestamp),
async.apply(Messaging.addMessageToUsers, data.roomId, uids, mid, data.timestamp), async.apply(Messaging.addMessageToUsers, data.roomId, uids, mid, timestamp),
async.apply(Messaging.markUnread, uids, data.roomId), async.apply(Messaging.markUnread, uids, data.roomId),
], next); ], next);
}, },
@@ -115,6 +117,16 @@ module.exports = function (Messaging) {
], callback); ], callback);
}; };
Messaging.addSystemMessage = async (content, uid, roomId) => {
const message = await Messaging.addMessage({
content: content,
uid: uid,
roomId: roomId,
system: 1,
});
Messaging.notifyUsersInRoom(uid, roomId, message);
};
Messaging.addRoomToUsers = function (roomId, uids, timestamp, callback) { Messaging.addRoomToUsers = function (roomId, uids, timestamp, callback) {
if (!uids.length) { if (!uids.length) {
return callback(); return callback();

View File

@@ -7,7 +7,7 @@ var user = require('../user');
var utils = require('../utils'); var utils = require('../utils');
var plugins = require('../plugins'); var plugins = require('../plugins');
const intFields = ['timestamp', 'edited', 'fromuid', 'roomId', 'deleted']; const intFields = ['timestamp', 'edited', 'fromuid', 'roomId', 'deleted', 'system'];
module.exports = function (Messaging) { module.exports = function (Messaging) {
Messaging.newMessageCutoff = 1000 * 60 * 3; Messaging.newMessageCutoff = 1000 * 60 * 3;
@@ -86,9 +86,14 @@ module.exports = function (Messaging) {
message.newSet = false; message.newSet = false;
message.roomId = String(message.roomId || roomId); message.roomId = String(message.roomId || roomId);
message.deleted = !!message.deleted; message.deleted = !!message.deleted;
message.system = !!message.system;
}); });
async.map(messages, function (message, next) { async.map(messages, function (message, next) {
if (message.system) {
return setImmediate(next, null, message);
}
Messaging.parse(message.content, message.fromuid, uid, roomId, isNew, function (err, result) { Messaging.parse(message.content, message.fromuid, uid, roomId, isNew, function (err, result) {
if (err) { if (err) {
return next(err); return next(err);

View File

@@ -259,11 +259,11 @@ Messaging.getLatestUndeletedMessage = function (uid, roomId, callback) {
done = true; done = true;
return next(); return next();
} }
Messaging.getMessageField(mids[0], 'deleted', _next); Messaging.getMessageFields(mids[0], ['deleted', 'system'], _next);
}, },
function (deleted, _next) { function (states, _next) {
done = !deleted; done = !states.deleted && !states.system;
if (!deleted) { if (done) {
latestMid = mids[0]; latestMid = mids[0];
} }
index += 1; index += 1;

View File

@@ -1,6 +1,5 @@
'use strict'; 'use strict';
var async = require('async');
var validator = require('validator'); var validator = require('validator');
var db = require('../database'); var db = require('../database');
@@ -10,34 +9,23 @@ var privileges = require('../privileges');
var meta = require('../meta'); var meta = require('../meta');
module.exports = function (Messaging) { module.exports = function (Messaging) {
Messaging.getRoomData = function (roomId, callback) { Messaging.getRoomData = async (roomId) => {
async.waterfall([ const data = await db.getObject('chat:room:' + roomId);
function (next) {
db.getObject('chat:room:' + roomId, next);
},
function (data, next) {
if (!data) { if (!data) {
return callback(new Error('[[error:no-chat-room]]')); throw new Error('[[error:no-chat-room]]');
} }
modifyRoomData([data]); modifyRoomData([data]);
next(null, data); return data;
},
], callback);
}; };
Messaging.getRoomsData = function (roomIds, callback) { Messaging.getRoomsData = async (roomIds) => {
var keys = roomIds.map(function (roomId) { const roomData = await db.getObjects(roomIds.map(function (roomId) {
return 'chat:room:' + roomId; return 'chat:room:' + roomId;
}); }));
async.waterfall([
function (next) {
db.getObjects(keys, next);
},
function (roomData, next) {
modifyRoomData(roomData); modifyRoomData(roomData);
next(null, roomData); return roomData;
},
], callback);
}; };
function modifyRoomData(rooms) { function modifyRoomData(rooms) {
@@ -52,284 +40,204 @@ module.exports = function (Messaging) {
}); });
} }
Messaging.newRoom = function (uid, toUids, callback) { Messaging.newRoom = async (uid, toUids) => {
var roomId; const now = Date.now();
var now = Date.now(); const roomId = await db.incrObjectField('global', 'nextChatRoomId');
async.waterfall([ const room = {
function (next) {
db.incrObjectField('global', 'nextChatRoomId', next);
},
function (_roomId, next) {
roomId = _roomId;
var room = {
owner: uid, owner: uid,
roomId: roomId, roomId: roomId,
}; };
db.setObject('chat:room:' + roomId, room, next);
}, await Promise.all([
function (next) { db.setObject('chat:room:' + roomId, room),
db.sortedSetAdd('chat:room:' + roomId + ':uids', now, uid, next); db.sortedSetAdd('chat:room:' + roomId + ':uids', now, uid),
}, ]);
function (next) { await Promise.all([
Messaging.addUsersToRoom(uid, toUids, roomId, next); Messaging.addUsersToRoom(uid, toUids, roomId),
}, Messaging.addRoomToUsers(roomId, [uid].concat(toUids), now),
function (next) { ]);
Messaging.addRoomToUsers(roomId, [uid].concat(toUids), now, next);
}, return roomId;
function (next) {
next(null, roomId);
},
], callback);
}; };
Messaging.isUserInRoom = function (uid, roomId, callback) { Messaging.isUserInRoom = async (uid, roomId) => {
async.waterfall([ const inRoom = db.isSortedSetMember('chat:room:' + roomId + ':uids', uid);
function (next) { const data = await plugins.fireHook('filter:messaging.isUserInRoom', { uid: uid, roomId: roomId, inRoom: inRoom });
db.isSortedSetMember('chat:room:' + roomId + ':uids', uid, next); return data.inRoom;
},
function (inRoom, next) {
plugins.fireHook('filter:messaging.isUserInRoom', { uid: uid, roomId: roomId, inRoom: inRoom }, next);
},
function (data, next) {
next(null, data.inRoom);
},
], callback);
}; };
Messaging.roomExists = function (roomId, callback) { Messaging.roomExists = async roomId => db.exists('chat:room:' + roomId + ':uids');
db.exists('chat:room:' + roomId + ':uids', callback);
Messaging.getUserCountInRoom = async roomId => db.sortedSetCard('chat:room:' + roomId + ':uids');
Messaging.isRoomOwner = async (uid, roomId) => {
const owner = await db.getObjectField('chat:room:' + roomId, 'owner');
return parseInt(uid, 10) === parseInt(owner, 10);
}; };
Messaging.getUserCountInRoom = function (roomId, callback) { Messaging.addUsersToRoom = async function (uid, uids, roomId) {
db.sortedSetCard('chat:room:' + roomId + ':uids', callback);
};
Messaging.isRoomOwner = function (uid, roomId, callback) {
async.waterfall([
function (next) {
db.getObjectField('chat:room:' + roomId, 'owner', next);
},
function (owner, next) {
next(null, parseInt(uid, 10) === parseInt(owner, 10));
},
], callback);
};
Messaging.addUsersToRoom = function (uid, uids, roomId, callback) {
async.waterfall([
function (next) {
Messaging.isUserInRoom(uid, roomId, next);
},
function (inRoom, next) {
if (!inRoom) {
return next(new Error('[[error:cant-add-users-to-chat-room]]'));
}
const now = Date.now(); const now = Date.now();
const timestamps = uids.map(() => now); const timestamps = uids.map(() => now);
db.sortedSetAdd('chat:room:' + roomId + ':uids', timestamps, uids, next); const inRoom = await Messaging.isUserInRoom(uid, roomId);
}, if (!inRoom) {
function (next) { throw new Error('[[error:cant-add-users-to-chat-room]]');
async.parallel({
userCount: async.apply(db.sortedSetCard, 'chat:room:' + roomId + ':uids'),
roomData: async.apply(db.getObject, 'chat:room:' + roomId),
}, next);
},
function (results, next) {
if (!results.roomData.hasOwnProperty('groupChat') && results.userCount > 2) {
return db.setObjectField('chat:room:' + roomId, 'groupChat', 1, next);
} }
next();
}, await db.sortedSetAdd('chat:room:' + roomId + ':uids', timestamps, uids);
], callback); const [userCount, roomData] = await Promise.all([
db.sortedSetCard('chat:room:' + roomId + ':uids'),
db.getObject('chat:room:' + roomId),
]);
if (!roomData.hasOwnProperty('groupChat') && userCount > 2) {
await db.setObjectField('chat:room:' + roomId, 'groupChat', 1);
}
await Promise.all(uids.map(uid => Messaging.addSystemMessage('user-join', uid, roomId)));
}; };
Messaging.removeUsersFromRoom = function (uid, uids, roomId, callback) { Messaging.removeUsersFromRoom = async (uid, uids, roomId) => {
async.waterfall([ const [isOwner, userCount] = await Promise.all([
function (next) { Messaging.isRoomOwner(uid, roomId),
async.parallel({ Messaging.getUserCountInRoom(roomId),
isOwner: async.apply(Messaging.isRoomOwner, uid, roomId), ]);
userCount: async.apply(Messaging.getUserCountInRoom, roomId),
}, next); if (!isOwner) {
}, throw new Error('[[error:cant-remove-users-from-chat-room]]');
function (results, next) {
if (!results.isOwner) {
return next(new Error('[[error:cant-remove-users-from-chat-room]]'));
} }
if (results.userCount === 2) { if (userCount === 2) {
return next(new Error('[[error:cant-remove-last-user]]')); throw new Error('[[error:cant-remove-last-user]]');
} }
Messaging.leaveRoom(uids, roomId, next);
}, await Messaging.leaveRoom(uids, roomId);
], callback);
}; };
Messaging.leaveRoom = function (uids, roomId, callback) { Messaging.leaveRoom = async (uids, roomId) => {
async.waterfall([ const keys = uids
function (next) { .map(function (uid) {
db.sortedSetRemove('chat:room:' + roomId + ':uids', uids, next);
},
function (next) {
var keys = uids.map(function (uid) {
return 'uid:' + uid + ':chat:rooms'; return 'uid:' + uid + ':chat:rooms';
}); })
keys = keys.concat(uids.map(function (uid) { .concat(uids.map(function (uid) {
return 'uid:' + uid + ':chat:rooms:unread'; return 'uid:' + uid + ':chat:rooms:unread';
})); }));
db.sortedSetsRemove(keys, roomId, next);
}, await Promise.all([
function (next) { db.sortedSetRemove('chat:room:' + roomId + ':uids', uids),
updateOwner(roomId, next); db.sortedSetsRemove(keys, roomId),
}, ]);
], callback);
await Promise.all(uids.map(uid => Messaging.addSystemMessage('user-leave', uid, roomId)));
await updateOwner(roomId);
}; };
Messaging.leaveRooms = function (uid, roomIds, callback) { Messaging.leaveRooms = async (uid, roomIds) => {
async.waterfall([
function (next) {
const roomKeys = roomIds.map(roomId => 'chat:room:' + roomId + ':uids'); const roomKeys = roomIds.map(roomId => 'chat:room:' + roomId + ':uids');
db.sortedSetsRemove(roomKeys, uid, next); await Promise.all([
}, db.sortedSetsRemove(roomKeys, uid),
function (next) {
db.sortedSetRemove([ db.sortedSetRemove([
'uid:' + uid + ':chat:rooms', 'uid:' + uid + ':chat:rooms',
'uid:' + uid + ':chat:rooms:unread', 'uid:' + uid + ':chat:rooms:unread',
], roomIds, next); ], roomIds),
}, ]);
function (next) {
async.eachSeries(roomIds, updateOwner, next); await Promise.all(
}, roomIds.map(roomId => updateOwner(roomId))
], callback); .concat(roomIds.map(roomId => Messaging.addSystemMessage('user-leave', uid, roomId)))
);
}; };
function updateOwner(roomId, callback) { async function updateOwner(roomId) {
async.waterfall([ const uids = await db.getSortedSetRange('chat:room:' + roomId + ':uids', 0, 0);
function (next) { const newOwner = uids[0] || 0;
db.getSortedSetRange('chat:room:' + roomId + ':uids', 0, 0, next); await db.setObjectField('chat:room:' + roomId, 'owner', newOwner);
},
function (uids, next) {
var newOwner = uids[0] || 0;
db.setObjectField('chat:room:' + roomId, 'owner', newOwner, next);
},
], callback);
} }
Messaging.getUidsInRoom = function (roomId, start, stop, callback) { Messaging.getUidsInRoom = async (roomId, start, stop) => db.getSortedSetRevRange('chat:room:' + roomId + ':uids', start, stop);
db.getSortedSetRevRange('chat:room:' + roomId + ':uids', start, stop, callback);
};
Messaging.getUsersInRoom = function (roomId, start, stop, callback) { Messaging.getUsersInRoom = async (roomId, start, stop) => {
async.waterfall([ const uids = await Messaging.getUidsInRoom(roomId, start, stop);
function (next) { const [users, ownerId] = await Promise.all([
Messaging.getUidsInRoom(roomId, start, stop, next); user.getUsersFields(uids, ['uid', 'username', 'picture', 'status']),
}, db.getObjectField('chat:room:' + roomId, 'owner'),
function (uids, next) { ]);
user.getUsersFields(uids, ['uid', 'username', 'picture', 'status'], next);
}, return users.map(function (user) {
function (users, next) {
db.getObjectField('chat:room:' + roomId, 'owner', function (err, ownerId) {
next(err, users.map(function (user) {
user.isOwner = parseInt(user.uid, 10) === parseInt(ownerId, 10); user.isOwner = parseInt(user.uid, 10) === parseInt(ownerId, 10);
return user; return user;
}));
}); });
},
], callback);
}; };
Messaging.renameRoom = function (uid, roomId, newName, callback) { Messaging.renameRoom = async function (uid, roomId, newName) {
if (!newName) { if (!newName) {
return callback(new Error('[[error:invalid-name]]')); throw new Error('[[error:invalid-name]]');
} }
newName = newName.trim(); newName = newName.trim();
if (newName.length > 75) { if (newName.length > 75) {
return callback(new Error('[[error:chat-room-name-too-long]]')); throw new Error('[[error:chat-room-name-too-long]]');
} }
async.waterfall([
function (next) { const payload = await plugins.fireHook('filter:chat.renameRoom', {
plugins.fireHook('filter:chat.renameRoom', {
uid: uid, uid: uid,
roomId: roomId, roomId: roomId,
newName: newName, newName: newName,
}, next); });
}, const isOwner = await Messaging.isRoomOwner(payload.uid, payload.roomId);
function (result, next) {
Messaging.isRoomOwner(uid, roomId, next);
},
function (isOwner, next) {
if (!isOwner) { if (!isOwner) {
return next(new Error('[[error:no-privileges]]')); throw new Error('[[error:no-privileges]]');
} }
db.setObjectField('chat:room:' + roomId, 'roomName', newName, next);
}, await db.setObjectField('chat:room:' + payload.roomId, 'roomName', payload.newName);
async.apply(plugins.fireHook, 'action:chat.renameRoom', { await Messaging.addSystemMessage('room-rename, ' + payload.newName.replace(',', '%2C'), payload.uid, payload.roomId);
roomId: roomId,
newName: newName, plugins.fireHook('action:chat.renameRoom', {
}), roomId: payload.roomId,
], callback); newName: payload.newName,
});
}; };
Messaging.canReply = function (roomId, uid, callback) { Messaging.canReply = async (roomId, uid) => {
async.waterfall([ const inRoom = db.isSortedSetMember('chat:room:' + roomId + ':uids', uid);
function (next) { const data = await plugins.fireHook('filter:messaging.canReply', { uid: uid, roomId: roomId, inRoom: inRoom, canReply: inRoom });
db.isSortedSetMember('chat:room:' + roomId + ':uids', uid, next); return data.canReply;
},
function (inRoom, next) {
plugins.fireHook('filter:messaging.canReply', { uid: uid, roomId: roomId, inRoom: inRoom, canReply: inRoom }, next);
},
function (data, next) {
next(null, data.canReply);
},
], callback);
}; };
Messaging.loadRoom = function (uid, data, callback) { Messaging.loadRoom = async (uid, data) => {
async.waterfall([ const canChat = await privileges.global.can('chat', uid);
function (next) {
privileges.global.can('chat', uid, next);
},
function (canChat, next) {
if (!canChat) { if (!canChat) {
return next(new Error('[[error:no-privileges]]')); throw new Error('[[error:no-privileges]]');
} }
const inRoom = await Messaging.isUserInRoom(uid, data.roomId);
Messaging.isUserInRoom(uid, data.roomId, next);
},
function (inRoom, next) {
if (!inRoom) { if (!inRoom) {
return callback(null, null); return null;
} }
async.parallel({ const [roomData, canReply, users, messages, isAdminOrGlobalMod] = await Promise.all([
roomData: async.apply(Messaging.getRoomData, data.roomId), Messaging.getRoomData(data.roomId),
canReply: async.apply(Messaging.canReply, data.roomId, uid), Messaging.canReply(data.roomId, uid),
users: async.apply(Messaging.getUsersInRoom, data.roomId, 0, -1), Messaging.getUsersInRoom(data.roomId, 0, -1),
messages: async.apply(Messaging.getMessages, { Messaging.getMessages({
callerUid: uid, callerUid: uid,
uid: data.uid || uid, uid: data.uid || uid,
roomId: data.roomId, roomId: data.roomId,
isNew: false, isNew: false,
}), }),
isAdminOrGlobalMod: function (next) { user.isAdminOrGlobalMod(uid),
user.isAdminOrGlobalMod(uid, next); ]);
},
}, next); var room = roomData;
}, room.messages = messages;
function (results, next) {
var room = results.roomData;
room.messages = results.messages;
room.isOwner = parseInt(room.owner, 10) === parseInt(uid, 10); room.isOwner = parseInt(room.owner, 10) === parseInt(uid, 10);
room.users = results.users.filter(function (user) { room.users = users.filter(function (user) {
return user && parseInt(user.uid, 10) && parseInt(user.uid, 10) !== uid; return user && parseInt(user.uid, 10) && parseInt(user.uid, 10) !== uid;
}); });
room.canReply = results.canReply; room.canReply = canReply;
room.groupChat = room.hasOwnProperty('groupChat') ? room.groupChat : results.users.length > 2; room.groupChat = room.hasOwnProperty('groupChat') ? room.groupChat : users.length > 2;
room.usernames = Messaging.generateUsernames(results.users, uid); room.usernames = Messaging.generateUsernames(users, uid);
room.maximumUsersInChatRoom = meta.config.maximumUsersInChatRoom; room.maximumUsersInChatRoom = meta.config.maximumUsersInChatRoom;
room.maximumChatMessageLength = meta.config.maximumChatMessageLength; room.maximumChatMessageLength = meta.config.maximumChatMessageLength;
room.showUserInput = !room.maximumUsersInChatRoom || room.maximumUsersInChatRoom > 2; room.showUserInput = !room.maximumUsersInChatRoom || room.maximumUsersInChatRoom > 2;
room.isAdminOrGlobalMod = results.isAdminOrGlobalMod; room.isAdminOrGlobalMod = isAdminOrGlobalMod;
next(null, room);
}, return room;
], callback);
}; };
}; };

View File

@@ -113,6 +113,16 @@ describe('Messaging Library', function () {
}); });
}); });
it('should send a user-join system message when a chat room is created', (done) => {
socketModules.chats.getMessages({ uid: fooUid }, { uid: fooUid, roomId: roomId, start: 0 }, function (err, messages) {
assert.ifError(err);
assert.equal(messages.length, 1);
assert.strictEqual(messages[0].system, true);
assert.strictEqual(messages[0].content, 'user-join');
done();
});
});
it('should fail to add user to room with invalid data', function (done) { it('should fail to add user to room with invalid data', function (done) {
socketModules.chats.addUserToRoom({ uid: fooUid }, null, function (err) { socketModules.chats.addUserToRoom({ uid: fooUid }, null, function (err) {
assert.equal(err.message, '[[error:invalid-data]]'); assert.equal(err.message, '[[error:invalid-data]]');
@@ -185,6 +195,17 @@ describe('Messaging Library', function () {
}); });
}); });
it('should send a user-leave system message when a user leaves the chat room', (done) => {
socketModules.chats.getMessages({ uid: fooUid }, { uid: fooUid, roomId: roomId, start: 0 }, function (err, messages) {
assert.ifError(err);
assert.equal(messages.length, 3);
const message = messages.pop();
assert.strictEqual(message.system, true);
assert.strictEqual(message.content, 'user-leave');
done();
});
});
it('should change owner when owner leaves room', function (done) { it('should change owner when owner leaves room', function (done) {
socketModules.chats.newRoom({ uid: herpUid }, { touid: fooUid }, function (err, roomId) { socketModules.chats.newRoom({ uid: herpUid }, { touid: fooUid }, function (err, roomId) {
assert.ifError(err); assert.ifError(err);
@@ -330,7 +351,8 @@ describe('Messaging Library', function () {
myRoomId = _roomId; myRoomId = _roomId;
assert.ifError(err); assert.ifError(err);
assert(myRoomId); assert(myRoomId);
socketModules.chats.getRaw({ uid: bazUid }, { mid: 1 }, function (err) { socketModules.chats.getRaw({ uid: bazUid }, { mid: 2 }, function (err) {
assert(err);
assert.equal(err.message, '[[error:not-allowed]]'); assert.equal(err.message, '[[error:not-allowed]]');
socketModules.chats.send({ uid: bazUid }, { roomId: myRoomId, message: 'admin will see this' }, function (err, message) { socketModules.chats.send({ uid: bazUid }, { roomId: myRoomId, message: 'admin will see this' }, function (err, message) {
assert.ifError(err); assert.ifError(err);
@@ -392,8 +414,8 @@ describe('Messaging Library', function () {
}, function (err, messages) { }, function (err, messages) {
assert.ifError(err); assert.ifError(err);
assert(Array.isArray(messages)); assert(Array.isArray(messages));
assert.equal(messages[0].roomId, roomId); assert.equal(messages[4].roomId, roomId);
assert.equal(messages[0].fromuid, fooUid); assert.equal(messages[4].fromuid, fooUid);
done(); done();
}); });
}); });
@@ -449,6 +471,16 @@ describe('Messaging Library', function () {
}); });
}); });
it('should send a room-rename system message when a room is renamed', (done) => {
socketModules.chats.getMessages({ uid: fooUid }, { uid: fooUid, roomId: roomId, start: 0 }, function (err, messages) {
assert.ifError(err);
const message = messages.pop();
assert.strictEqual(message.system, true);
assert.strictEqual(message.content, 'room-rename, new room name');
done();
});
});
it('should fail to load room with invalid-data', function (done) { it('should fail to load room with invalid-data', function (done) {
socketModules.chats.loadRoom({ uid: fooUid }, null, function (err) { socketModules.chats.loadRoom({ uid: fooUid }, null, function (err) {
assert.equal(err.message, '[[error:invalid-data]]'); assert.equal(err.message, '[[error:invalid-data]]');