Commit ca9229a9 authored by JC Brand's avatar JC Brand

`createMessage` now returns a promise.

Also, fix all broken tests, mostly related to this.
parent b4110dc1
...@@ -63132,7 +63132,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ ...@@ -63132,7 +63132,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
} else { } else {
resolve(this.messages.create(attrs)); resolve(this.messages.create(attrs));
} }
}); }).catch(e => reject(e));
}); });
}, },
...@@ -63323,7 +63323,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ ...@@ -63323,7 +63323,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
if (!message) { if (!message) {
// Only create the message when we're sure it's not a duplicate // Only create the message when we're sure it's not a duplicate
chatbox.incrementUnreadMsgCounter(chatbox.createMessage(stanza, original_stanza)); chatbox.createMessage(stanza, original_stanza).then(msg => chatbox.incrementUnreadMsgCounter(msg)).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
} }
} }
...@@ -73120,7 +73120,7 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } ...@@ -73120,7 +73120,7 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
return; return;
} }
this.incrementUnreadMsgCounter(this.createMessage(stanza, original_stanza)); this.createMessage(stanza, original_stanza).then(msg => this.incrementUnreadMsgCounter(msg)).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
} }
if (sender !== this.get('nick')) { if (sender !== this.get('nick')) {
...@@ -27,10 +27,11 @@ ...@@ -27,10 +27,11 @@
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
test_utils.openControlBox(); test_utils.openControlBox();
let view;
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
test_utils.waitUntil(() => _converse.chatboxes.length == 2).then(() => { .then(() => {
var view = _converse.chatboxviews.get(contact_jid); view = _converse.chatboxviews.get(contact_jid);
test_utils.sendMessage(view, '/help'); test_utils.sendMessage(view, '/help');
const info_messages = Array.prototype.slice.call(view.el.querySelectorAll('.chat-info:not(.chat-date)'), 0); const info_messages = Array.prototype.slice.call(view.el.querySelectorAll('.chat-info:not(.chat-date)'), 0);
...@@ -39,13 +40,15 @@ ...@@ -39,13 +40,15 @@
expect(info_messages.pop().textContent).toBe('/me: Write in the third person'); expect(info_messages.pop().textContent).toBe('/me: Write in the third person');
expect(info_messages.pop().textContent).toBe('/clear: Remove messages'); expect(info_messages.pop().textContent).toBe('/clear: Remove messages');
var msg = $msg({ const msg = $msg({
from: contact_jid, from: contact_jid,
to: _converse.connection.jid, to: _converse.connection.jid,
type: 'chat', type: 'chat',
id: (new Date()).getTime() id: (new Date()).getTime()
}).c('body').t('hello world').tree(); }).c('body').t('hello world').tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => view.content.querySelectorAll('.chat-msg').length);
}).then(() => {
expect(view.content.lastElementChild.textContent.trim().indexOf('hello world')).not.toBe(-1); expect(view.content.lastElementChild.textContent.trim().indexOf('hello world')).not.toBe(-1);
done(); done();
}); });
...@@ -741,7 +744,7 @@ ...@@ -741,7 +744,7 @@
spyOn(_converse, 'log'); spyOn(_converse, 'log');
recipient_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost'; recipient_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost';
return test_utils.openChatBoxFor(_converse, recipient_jid); return test_utils.openChatBoxFor(_converse, recipient_jid);
}).then(() => { }).then((view) => {
var msg = $msg({ var msg = $msg({
'from': _converse.bare_jid, 'from': _converse.bare_jid,
'id': (new Date()).getTime(), 'id': (new Date()).getTime(),
...@@ -757,7 +760,8 @@ ...@@ -757,7 +760,8 @@
'type': 'chat' 'type': 'chat'
}).c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
// Check that the chatbox and its view now exist // Check that the chatbox and its view now exist
var chatbox = _converse.chatboxes.get(recipient_jid); var chatbox = _converse.chatboxes.get(recipient_jid);
var chatboxview = _converse.chatboxviews.get(recipient_jid); var chatboxview = _converse.chatboxviews.get(recipient_jid);
...@@ -886,7 +890,7 @@ ...@@ -886,7 +890,7 @@
spyOn(_converse, 'log'); spyOn(_converse, 'log');
recipient_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost'; recipient_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost';
return test_utils.openChatBoxFor(_converse, recipient_jid); return test_utils.openChatBoxFor(_converse, recipient_jid);
}).then(() => { }).then((view) => {
var msg = $msg({ var msg = $msg({
'from': _converse.bare_jid, 'from': _converse.bare_jid,
'id': (new Date()).getTime(), 'id': (new Date()).getTime(),
...@@ -902,7 +906,8 @@ ...@@ -902,7 +906,8 @@
'type': 'chat' 'type': 'chat'
}).c('paused', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('paused', {'xmlns': Strophe.NS.CHATSTATES}).tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
// Check that the chatbox and its view now exist // Check that the chatbox and its view now exist
var chatbox = _converse.chatboxes.get(recipient_jid); var chatbox = _converse.chatboxes.get(recipient_jid);
var chatboxview = _converse.chatboxviews.get(recipient_jid); var chatboxview = _converse.chatboxviews.get(recipient_jid);
...@@ -1041,17 +1046,18 @@ ...@@ -1041,17 +1046,18 @@
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
test_utils.openControlBox(); test_utils.openControlBox();
const sender_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost'; const sender_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost';
let view;
// See XEP-0085 http://xmpp.org/extensions/xep-0085.html#definitions // See XEP-0085 http://xmpp.org/extensions/xep-0085.html#definitions
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
test_utils.openChatBoxFor(_converse, sender_jid) test_utils.openChatBoxFor(_converse, sender_jid)
.then(() => { .then(() => {
var view = _converse.chatboxviews.get(sender_jid); view = _converse.chatboxviews.get(sender_jid);
expect(view.el.querySelectorAll('.chat-event').length).toBe(0); expect(view.el.querySelectorAll('.chat-event').length).toBe(0);
// Insert <composing> message, to also check that // Insert <composing> message, to also check that
// text messages are inserted correctly with // text messages are inserted correctly with
// temporary chat events in the chat contents. // temporary chat events in the chat contents.
var msg = $msg({ const msg = $msg({
'to': _converse.bare_jid, 'to': _converse.bare_jid,
'xmlns': 'jabber:client', 'xmlns': 'jabber:client',
'from': sender_jid, 'from': sender_jid,
...@@ -1059,14 +1065,18 @@ ...@@ -1059,14 +1065,18 @@
.c('composing', {'xmlns': Strophe.NS.CHATSTATES}).up() .c('composing', {'xmlns': Strophe.NS.CHATSTATES}).up()
.tree(); .tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
expect(view.el.querySelectorAll('.chat-state-notification').length).toBe(1); expect(view.el.querySelectorAll('.chat-state-notification').length).toBe(1);
msg = $msg({ const msg = $msg({
from: sender_jid, from: sender_jid,
to: _converse.connection.jid, to: _converse.connection.jid,
type: 'chat', type: 'chat',
id: (new Date()).getTime() id: (new Date()).getTime()
}).c('body').c('inactive', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('body').c('inactive', {'xmlns': Strophe.NS.CHATSTATES}).tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => (view.model.messages.length > 1));
}).then(() => {
expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object)); expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
expect($(view.el).find('.chat-state-notification').length).toBe(0); expect($(view.el).find('.chat-state-notification').length).toBe(0);
done(); done();
...@@ -1178,12 +1188,15 @@ ...@@ -1178,12 +1188,15 @@
.c('active', {'xmlns': Strophe.NS.CHATSTATES}).tree(); .c('active', {'xmlns': Strophe.NS.CHATSTATES}).tree();
_converse.windowState = 'hidden'; _converse.windowState = 'hidden';
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
expect(_converse.incrementMsgCounter).toHaveBeenCalled(); return test_utils.waitUntil(() => _converse.api.chats.get().length)
expect(_converse.clearMsgCounter).not.toHaveBeenCalled(); .then(() => {
expect(_converse.msg_counter).toBe(1); expect(_converse.incrementMsgCounter).toHaveBeenCalled();
expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object)); expect(_converse.clearMsgCounter).not.toHaveBeenCalled();
_converse.windowSate = previous_state; expect(_converse.msg_counter).toBe(1);
done(); expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
_converse.windowSate = previous_state;
done();
});
})); }));
it("is cleared when the window is focused", it("is cleared when the window is focused",
...@@ -1237,7 +1250,8 @@ ...@@ -1237,7 +1250,8 @@
// initial state // initial state
expect(_converse.msg_counter).toBe(0); expect(_converse.msg_counter).toBe(0);
var message = 'This message will always increment the message counter from zero', let view;
const message = 'This message will always increment the message counter from zero',
sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost', sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost',
msgFactory = function () { msgFactory = function () {
return $msg({ return $msg({
...@@ -1254,24 +1268,29 @@ ...@@ -1254,24 +1268,29 @@
// leave converse-chat page // leave converse-chat page
_converse.windowState = 'hidden'; _converse.windowState = 'hidden';
_converse.chatboxes.onMessage(msgFactory()); _converse.chatboxes.onMessage(msgFactory());
expect(_converse.msg_counter).toBe(1); return test_utils.waitUntil(() => _converse.api.chats.get().length)
.then(() => {
expect(_converse.msg_counter).toBe(1);
// come back to converse-chat page // come back to converse-chat page
_converse.saveWindowState(null, 'focus'); _converse.saveWindowState(null, 'focus');
var view = _converse.chatboxviews.get(sender_jid); view = _converse.chatboxviews.get(sender_jid);
expect(u.isVisible(view.el)).toBeTruthy(); expect(u.isVisible(view.el)).toBeTruthy();
expect(_converse.msg_counter).toBe(0); expect(_converse.msg_counter).toBe(0);
// close chatbox and leave converse-chat page again // close chatbox and leave converse-chat page again
view.close(); view.close();
_converse.windowState = 'hidden'; _converse.windowState = 'hidden';
// check that msg_counter is incremented from zero again // check that msg_counter is incremented from zero again
_converse.chatboxes.onMessage(msgFactory()); _converse.chatboxes.onMessage(msgFactory());
view = _converse.chatboxviews.get(sender_jid); return test_utils.waitUntil(() => _converse.api.chats.get().length)
expect(u.isVisible(view.el)).toBeTruthy(); }).then(() => {
expect(_converse.msg_counter).toBe(1); view = _converse.chatboxviews.get(sender_jid);
done(); expect(u.isVisible(view.el)).toBeTruthy();
expect(_converse.msg_counter).toBe(1);
done();
});
})); }));
}); });
...@@ -1288,13 +1307,17 @@ ...@@ -1288,13 +1307,17 @@
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost', const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost',
msg = test_utils.createChatMessage(_converse, sender_jid, 'This message will be unread'); msg = test_utils.createChatMessage(_converse, sender_jid, 'This message will be unread');
let view;
test_utils.openChatBoxFor(_converse, sender_jid) test_utils.openChatBoxFor(_converse, sender_jid)
.then((view) => { .then((v) => {
view = v;
view.model.save('scrolled', true); view.model.save('scrolled', true);
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
expect(view.model.get('num_unread')).toBe(1); expect(view.model.get('num_unread')).toBe(1);
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
it("is not incremented when the message is received and ChatBoxView is scrolled down", it("is not incremented when the message is received and ChatBoxView is scrolled down",
...@@ -1323,15 +1346,18 @@ ...@@ -1323,15 +1346,18 @@
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; let chatbox;
var msgFactory = function () { const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
const msgFactory = function () {
return test_utils.createChatMessage(_converse, sender_jid, 'This message will be unread'); return test_utils.createChatMessage(_converse, sender_jid, 'This message will be unread');
}; };
test_utils.openChatBoxFor(_converse, sender_jid) test_utils.openChatBoxFor(_converse, sender_jid)
.then(() => { .then(() => {
var chatbox = _converse.chatboxes.get(sender_jid); chatbox = _converse.chatboxes.get(sender_jid);
_converse.windowState = 'hidden'; _converse.windowState = 'hidden';
_converse.chatboxes.onMessage(msgFactory()); _converse.chatboxes.onMessage(msgFactory());
return test_utils.waitUntil(() => chatbox.messages.length);
}).then(() => {
expect(chatbox.get('num_unread')).toBe(1); expect(chatbox.get('num_unread')).toBe(1);
done(); done();
}); });
...@@ -1344,17 +1370,19 @@ ...@@ -1344,17 +1370,19 @@
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
let chatbox;
var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
var msgFactory = function () { const msgFactory = function () {
return test_utils.createChatMessage(_converse, sender_jid, 'This message will be unread'); return test_utils.createChatMessage(_converse, sender_jid, 'This message will be unread');
}; };
test_utils.openChatBoxFor(_converse, sender_jid) test_utils.openChatBoxFor(_converse, sender_jid)
.then(() => { .then(() => {
var chatbox = _converse.chatboxes.get(sender_jid); chatbox = _converse.chatboxes.get(sender_jid);
chatbox.save('scrolled', true); chatbox.save('scrolled', true);
_converse.windowState = 'hidden'; _converse.windowState = 'hidden';
_converse.chatboxes.onMessage(msgFactory()); _converse.chatboxes.onMessage(msgFactory());
return test_utils.waitUntil(() => chatbox.messages.length);
}).then(() => {
expect(chatbox.get('num_unread')).toBe(1); expect(chatbox.get('num_unread')).toBe(1);
done(); done();
}); });
...@@ -1368,20 +1396,23 @@ ...@@ -1368,20 +1396,23 @@
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
let chatbox;
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
var msgFactory = function () { const msgFactory = function () {
return test_utils.createChatMessage(_converse, sender_jid, 'This message will be unread'); return test_utils.createChatMessage(_converse, sender_jid, 'This message will be unread');
}; };
test_utils.openChatBoxFor(_converse, sender_jid) test_utils.openChatBoxFor(_converse, sender_jid)
.then(() => { .then(() => {
const chatbox = _converse.chatboxes.get(sender_jid); chatbox = _converse.chatboxes.get(sender_jid);
_converse.windowState = 'hidden'; _converse.windowState = 'hidden';
_converse.chatboxes.onMessage(msgFactory()); _converse.chatboxes.onMessage(msgFactory());
return test_utils.waitUntil(() => chatbox.messages.length);
}).then(() => {
expect(chatbox.get('num_unread')).toBe(1); expect(chatbox.get('num_unread')).toBe(1);
_converse.saveWindowState(null, 'focus'); _converse.saveWindowState(null, 'focus');
expect(chatbox.get('num_unread')).toBe(0); expect(chatbox.get('num_unread')).toBe(0);
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
it("is not cleared when ChatBoxView was scrolled up and the windows become focused", it("is not cleared when ChatBoxView was scrolled up and the windows become focused",
...@@ -1391,21 +1422,24 @@ ...@@ -1391,21 +1422,24 @@
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; let chatbox;
var msgFactory = function () { const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
const msgFactory = function () {
return test_utils.createChatMessage(_converse, sender_jid, 'This message will be unread'); return test_utils.createChatMessage(_converse, sender_jid, 'This message will be unread');
}; };
test_utils.openChatBoxFor(_converse, sender_jid) test_utils.openChatBoxFor(_converse, sender_jid)
.then(() => { .then(() => {
var chatbox = _converse.chatboxes.get(sender_jid); chatbox = _converse.chatboxes.get(sender_jid);
chatbox.save('scrolled', true); chatbox.save('scrolled', true);
_converse.windowState = 'hidden'; _converse.windowState = 'hidden';
_converse.chatboxes.onMessage(msgFactory()); _converse.chatboxes.onMessage(msgFactory());
return test_utils.waitUntil(() => chatbox.messages.length);
}).then(() => {
expect(chatbox.get('num_unread')).toBe(1); expect(chatbox.get('num_unread')).toBe(1);
_converse.saveWindowState(null, 'focus'); _converse.saveWindowState(null, 'focus');
expect(chatbox.get('num_unread')).toBe(1); expect(chatbox.get('num_unread')).toBe(1);
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
}); });
...@@ -1419,28 +1453,29 @@ ...@@ -1419,28 +1453,29 @@
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
let msg, chatbox, indicator_el, selector;
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length, 500) test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length, 500)
.then(() => test_utils.openChatBoxFor(_converse, sender_jid)) .then(() => test_utils.openChatBoxFor(_converse, sender_jid))
.then(() => { .then(() => {
var chatbox = _converse.chatboxes.get(sender_jid); chatbox = _converse.chatboxes.get(sender_jid);
chatbox.save('scrolled', true); chatbox.save('scrolled', true);
msg = test_utils.createChatMessage(_converse, sender_jid, 'This message will be unread');
var msg = test_utils.createChatMessage(_converse, sender_jid, 'This message will be unread');
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => chatbox.messages.length);
var selector = 'a.open-chat:contains("' + chatbox.get('fullname') + '") .msgs-indicator', }).then(() => {
indicator_el = sizzle(selector, _converse.rosterview.el).pop(); selector = 'a.open-chat:contains("' + chatbox.get('fullname') + '") .msgs-indicator';
indicator_el = sizzle(selector, _converse.rosterview.el).pop();
expect(indicator_el.textContent).toBe('1'); expect(indicator_el.textContent).toBe('1');
msg = test_utils.createChatMessage(_converse, sender_jid, 'This message will be unread too'); msg = test_utils.createChatMessage(_converse, sender_jid, 'This message will be unread too');
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => chatbox.messages.length);
}).then(() => {
indicator_el = sizzle(selector, _converse.rosterview.el).pop(); indicator_el = sizzle(selector, _converse.rosterview.el).pop();
expect(indicator_el.textContent).toBe('2'); expect(indicator_el.textContent).toBe('2');
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
it("is updated when message is received and chatbox is minimized", it("is updated when message is received and chatbox is minimized",
...@@ -1452,28 +1487,30 @@ ...@@ -1452,28 +1487,30 @@
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
let chatbox, indicator_el, msg, selector;
test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length, 500) test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length, 500)
.then(() => test_utils.openChatBoxFor(_converse, sender_jid)) .then(() => test_utils.openChatBoxFor(_converse, sender_jid))
.then(() => { .then(() => {
var chatbox = _converse.chatboxes.get(sender_jid); chatbox = _converse.chatboxes.get(sender_jid);
var chatboxview = _converse.chatboxviews.get(sender_jid); var chatboxview = _converse.chatboxviews.get(sender_jid);
chatboxview.minimize(); chatboxview.minimize();
var msg = test_utils.createChatMessage(_converse, sender_jid, 'This message will be unread'); msg = test_utils.createChatMessage(_converse, sender_jid, 'This message will be unread');
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => chatbox.messages.length);
var selector = 'a.open-chat:contains("' + chatbox.get('fullname') + '") .msgs-indicator', }).then(() => {
indicator_el = sizzle(selector, _converse.rosterview.el).pop(); selector = 'a.open-chat:contains("' + chatbox.get('fullname') + '") .msgs-indicator';
indicator_el = sizzle(selector, _converse.rosterview.el).pop();
expect(indicator_el.textContent).toBe('1'); expect(indicator_el.textContent).toBe('1');
msg = test_utils.createChatMessage(_converse, sender_jid, 'This message will be unread too'); msg = test_utils.createChatMessage(_converse, sender_jid, 'This message will be unread too');
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => chatbox.messages.length);
}).then(() => {
indicator_el = sizzle(selector, _converse.rosterview.el).pop(); indicator_el = sizzle(selector, _converse.rosterview.el).pop();
expect(indicator_el.textContent).toBe('2'); expect(indicator_el.textContent).toBe('2');
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
it("is cleared when chatbox is maximzied after receiving messages in minimized mode", it("is cleared when chatbox is maximzied after receiving messages in minimized mode",
...@@ -1484,27 +1521,28 @@ ...@@ -1484,27 +1521,28 @@
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
let chatbox, view, select_msgs_indicator;
const msgFactory = function () {
return test_utils.createChatMessage(_converse, sender_jid, 'This message will be received as unread, but eventually will be read');
};
test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length, 500) test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length, 500)
.then(() => test_utils.openChatBoxFor(_converse, sender_jid)) .then(() => test_utils.openChatBoxFor(_converse, sender_jid))
.then(() => { .then(() => {
var chatbox = _converse.chatboxes.get(sender_jid); chatbox = _converse.chatboxes.get(sender_jid);
var chatboxview = _converse.chatboxviews.get(sender_jid); view = _converse.chatboxviews.get(sender_jid);
var msgsIndicatorSelector = 'a.open-chat:contains("' + chatbox.get('fullname') + '") .msgs-indicator'; var msgsIndicatorSelector = 'a.open-chat:contains("' + chatbox.get('fullname') + '") .msgs-indicator';
var selectMsgsIndicator = () => $(_converse.rosterview.el).find(msgsIndicatorSelector); select_msgs_indicator = () => $(_converse.rosterview.el).find(msgsIndicatorSelector);
var msgFactory = function () { view.minimize();
return test_utils.createChatMessage(_converse, sender_jid, 'This message will be received as unread, but eventually will be read');
};
chatboxview.minimize();
_converse.chatboxes.onMessage(msgFactory()); _converse.chatboxes.onMessage(msgFactory());
expect(selectMsgsIndicator().text()).toBe('1'); return test_utils.waitUntil(() => chatbox.messages.length);
}).then(() => {
expect(select_msgs_indicator().text()).toBe('1');
_converse.chatboxes.onMessage(msgFactory()); _converse.chatboxes.onMessage(msgFactory());
expect(selectMsgsIndicator().text()).toBe('2'); return test_utils.waitUntil(() => chatbox.messages.length);
}).then(() => {
chatboxview.maximize(); expect(select_msgs_indicator().text()).toBe('2');
expect(selectMsgsIndicator().length).toBe(0); view.maximize();
expect(select_msgs_indicator().length).toBe(0);
done(); done();
}); });
})); }));
...@@ -1518,27 +1556,27 @@ ...@@ -1518,27 +1556,27 @@
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
let view, chatbox, select_msgs_indicator;
test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length, 500) test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length, 500)
.then(() => test_utils.openChatBoxFor(_converse, sender_jid)) .then(() => test_utils.openChatBoxFor(_converse, sender_jid))
.then(() => { .then(() => {
var chatbox = _converse.chatboxes.get(sender_jid); chatbox = _converse.chatboxes.get(sender_jid);
var chatboxview = _converse.chatboxviews.get(sender_jid); view = _converse.chatboxviews.get(sender_jid);
var msgFactory = function () { var msgFactory = function () {
return test_utils.createChatMessage(_converse, sender_jid, 'This message will be received as unread, but eventually will be read'); return test_utils.createChatMessage(_converse, sender_jid, 'This message will be received as unread, but eventually will be read');
}; };
var msgsIndicatorSelector = 'a.open-chat:contains("' + chatbox.get('fullname') + '") .msgs-indicator', var msgsIndicatorSelector = 'a.open-chat:contains("' + chatbox.get('fullname') + '") .msgs-indicator';
selectMsgsIndicator = () => $(_converse.rosterview.el).find(msgsIndicatorSelector); select_msgs_indicator = () => $(_converse.rosterview.el).find(msgsIndicatorSelector);
chatbox.save('scrolled', true); chatbox.save('scrolled', true);
_converse.chatboxes.onMessage(msgFactory()); _converse.chatboxes.onMessage(msgFactory());
expect(selectMsgsIndicator().text()).toBe('1'); return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
chatboxview.viewUnreadMessages(); expect(select_msgs_indicator().text()).toBe('1');
view.viewUnreadMessages();
_converse.rosterview.render(); _converse.rosterview.render();
expect(selectMsgsIndicator().length).toBe(0); expect(select_msgs_indicator().length).toBe(0);
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
it("is not cleared after user clicks on roster view when chatbox is already opened and scrolled up", it("is not cleared after user clicks on roster view when chatbox is already opened and scrolled up",
...@@ -1550,24 +1588,25 @@ ...@@ -1550,24 +1588,25 @@
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
let select_msgs_indicator, view;
test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length, 500) test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length, 500)
.then(() => test_utils.openChatBoxFor(_converse, sender_jid)) .then(() => test_utils.openChatBoxFor(_converse, sender_jid))
.then(() => { .then(() => {
var chatbox = _converse.chatboxes.get(sender_jid); const chatbox = _converse.chatboxes.get(sender_jid);
var chatboxview = _converse.chatboxviews.get(sender_jid); view = _converse.chatboxviews.get(sender_jid);
var msgFactory = function () { var msgFactory = function () {
return test_utils.createChatMessage(_converse, sender_jid, 'This message will be received as unread, but eventually will be read'); return test_utils.createChatMessage(_converse, sender_jid, 'This message will be received as unread, but eventually will be read');
}; };
var msgsIndicatorSelector = 'a.open-chat:contains("' + chatbox.get('fullname') + '") .msgs-indicator', var msgsIndicatorSelector = 'a.open-chat:contains("' + chatbox.get('fullname') + '") .msgs-indicator';
selectMsgsIndicator = () => $(_converse.rosterview.el).find(msgsIndicatorSelector); select_msgs_indicator = () => $(_converse.rosterview.el).find(msgsIndicatorSelector);
chatbox.save('scrolled', true); chatbox.save('scrolled', true);
_converse.chatboxes.onMessage(msgFactory()); _converse.chatboxes.onMessage(msgFactory());
expect(selectMsgsIndicator().text()).toBe('1'); return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
test_utils.openChatBoxFor(_converse, sender_jid); expect(select_msgs_indicator().text()).toBe('1');
expect(selectMsgsIndicator().text()).toBe('1'); return test_utils.openChatBoxFor(_converse, sender_jid);
}).then(() => {
expect(select_msgs_indicator().text()).toBe('1');
done(); done();
}); });
})); }));
...@@ -1584,20 +1623,21 @@ ...@@ -1584,20 +1623,21 @@
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
let selectUnreadMsgCount;
test_utils.openChatBoxFor(_converse, sender_jid) test_utils.openChatBoxFor(_converse, sender_jid)
.then(() => { .then(() => {
const msgFactory = function () { const msgFactory = function () {
return test_utils.createChatMessage(_converse, sender_jid, 'This message will be received as unread, but eventually will be read'); return test_utils.createChatMessage(_converse, sender_jid, 'This message will be received as unread, but eventually will be read');
}; };
const selectUnreadMsgCount = function () { selectUnreadMsgCount = function () {
const minimizedChatBoxView = _converse.minimized_chats.get(sender_jid); const minimizedChatBoxView = _converse.minimized_chats.get(sender_jid);
return minimizedChatBoxView.el.querySelector('.message-count'); return minimizedChatBoxView.el.querySelector('.message-count');
}; };
const chatbox = _converse.chatboxes.get(sender_jid); const chatbox = _converse.chatboxes.get(sender_jid);
chatbox.save('scrolled', true); chatbox.save('scrolled', true);
_converse.chatboxes.onMessage(msgFactory()); _converse.chatboxes.onMessage(msgFactory());
return test_utils.waitUntil(() => chatbox.messages.length);
}).then(() => {
const chatboxview = _converse.chatboxviews.get(sender_jid); const chatboxview = _converse.chatboxviews.get(sender_jid);
chatboxview.minimize(); chatboxview.minimize();
...@@ -1605,7 +1645,7 @@ ...@@ -1605,7 +1645,7 @@
expect(u.isVisible(unread_count)).toBeTruthy(); expect(u.isVisible(unread_count)).toBeTruthy();
expect(unread_count.innerHTML).toBe('1'); expect(unread_count.innerHTML).toBe('1');
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
it("is incremented when message is received and windows is not focused", it("is incremented when message is received and windows is not focused",
...@@ -1617,27 +1657,27 @@ ...@@ -1617,27 +1657,27 @@
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
let selectUnreadMsgCount;
test_utils.openChatBoxFor(_converse, sender_jid) test_utils.openChatBoxFor(_converse, sender_jid)
.then(() => { .then(() => {
const msgFactory = function () { const msgFactory = function () {
return test_utils.createChatMessage(_converse, sender_jid, return test_utils.createChatMessage(_converse, sender_jid,
'This message will be received as unread, but eventually will be read'); 'This message will be received as unread, but eventually will be read');
}; };
const selectUnreadMsgCount = function () { selectUnreadMsgCount = function () {
const minimizedChatBoxView = _converse.minimized_chats.get(sender_jid); const minimizedChatBoxView = _converse.minimized_chats.get(sender_jid);
return minimizedChatBoxView.el.querySelector('.message-count'); return minimizedChatBoxView.el.querySelector('.message-count');
}; };
const view = _converse.chatboxviews.get(sender_jid);
const chatboxview = _converse.chatboxviews.get(sender_jid); view.minimize();
chatboxview.minimize();
_converse.chatboxes.onMessage(msgFactory()); _converse.chatboxes.onMessage(msgFactory());
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
const unread_count = selectUnreadMsgCount(); const unread_count = selectUnreadMsgCount();
expect(u.isVisible(unread_count)).toBeTruthy(); expect(u.isVisible(unread_count)).toBeTruthy();
expect(unread_count.innerHTML).toBe('1'); expect(unread_count.innerHTML).toBe('1');
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
it("will render Openstreetmap-URL from geo-URI", it("will render Openstreetmap-URL from geo-URI",
......
...@@ -612,10 +612,14 @@ ...@@ -612,10 +612,14 @@
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.openAndEnterChatRoom(_converse, 'coven', 'chat.shakespeare.lit', 'dummy').then(function () { let view, chat_content, $chat_content;
var view = _converse.chatboxviews.get('coven@chat.shakespeare.lit'); const ONE_DAY_LATER = 86400000;
var chat_content = view.el.querySelector('.chat-content'); const baseTime = new Date();
var $chat_content = $(chat_content); test_utils.openAndEnterChatRoom(_converse, 'coven', 'chat.shakespeare.lit', 'dummy')
.then(() => {
view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
chat_content = view.el.querySelector('.chat-content');
$chat_content = $(chat_content);
var indicator = chat_content.querySelector('.date-separator'); var indicator = chat_content.querySelector('.date-separator');
expect(indicator).not.toBe(null); expect(indicator).not.toBe(null);
expect(indicator.getAttribute('class')).toEqual('message date-separator'); expect(indicator.getAttribute('class')).toEqual('message date-separator');
...@@ -625,11 +629,8 @@ ...@@ -625,11 +629,8 @@
expect(chat_content.querySelector('div.chat-info').textContent).toBe( expect(chat_content.querySelector('div.chat-info').textContent).toBe(
"dummy has entered the groupchat" "dummy has entered the groupchat"
); );
var baseTime = new Date();
jasmine.clock().install(); jasmine.clock().install();
jasmine.clock().mockDate(baseTime); jasmine.clock().mockDate(baseTime);
var ONE_DAY_LATER = 86400000;
jasmine.clock().tick(ONE_DAY_LATER); jasmine.clock().tick(ONE_DAY_LATER);
/* <presence to="dummy@localhost/_converse.js-29092160" /* <presence to="dummy@localhost/_converse.js-29092160"
...@@ -694,7 +695,7 @@ ...@@ -694,7 +695,7 @@
jasmine.clock().tick(ONE_DAY_LATER); jasmine.clock().tick(ONE_DAY_LATER);
var stanza = Strophe.xmlHtmlNode( const stanza = Strophe.xmlHtmlNode(
'<message xmlns="jabber:client"' + '<message xmlns="jabber:client"' +
' to="dummy@localhost/_converse.js-290929789"' + ' to="dummy@localhost/_converse.js-290929789"' +
' type="groupchat"' + ' type="groupchat"' +
...@@ -703,8 +704,15 @@ ...@@ -703,8 +704,15 @@
' <delay xmlns="urn:xmpp:delay" stamp="'+moment().format()+'" from="some1@localhost"/>'+ ' <delay xmlns="urn:xmpp:delay" stamp="'+moment().format()+'" from="some1@localhost"/>'+
'</message>').firstChild; '</message>').firstChild;
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
jasmine.clock().uninstall();
presence = $pres({ return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
jasmine.clock().install();
jasmine.clock().mockDate(baseTime);
jasmine.clock().tick(ONE_DAY_LATER);
jasmine.clock().tick(ONE_DAY_LATER);
jasmine.clock().tick(ONE_DAY_LATER);
const presence = $pres({
to: 'dummy@localhost/_converse.js-29092160', to: 'dummy@localhost/_converse.js-29092160',
from: 'coven@chat.shakespeare.lit/newguy' from: 'coven@chat.shakespeare.lit/newguy'
}).c('x', {xmlns: Strophe.NS.MUC_USER}) }).c('x', {xmlns: Strophe.NS.MUC_USER})
...@@ -715,7 +723,7 @@ ...@@ -715,7 +723,7 @@
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
let time = chat_content.querySelectorAll('time.separator-text'); const time = chat_content.querySelectorAll('time.separator-text');
expect(time.length).toEqual(4); expect(time.length).toEqual(4);
var $indicator = $chat_content.find('.date-separator:eq(3)'); var $indicator = $chat_content.find('.date-separator:eq(3)');
...@@ -727,7 +735,7 @@ ...@@ -727,7 +735,7 @@
jasmine.clock().tick(ONE_DAY_LATER); jasmine.clock().tick(ONE_DAY_LATER);
stanza = Strophe.xmlHtmlNode( const stanza = Strophe.xmlHtmlNode(
'<message xmlns="jabber:client"' + '<message xmlns="jabber:client"' +
' to="dummy@localhost/_converse.js-290929789"' + ' to="dummy@localhost/_converse.js-290929789"' +
' type="groupchat"' + ' type="groupchat"' +
...@@ -736,11 +744,18 @@ ...@@ -736,11 +744,18 @@
' <delay xmlns="urn:xmpp:delay" stamp="'+moment().format()+'" from="some1@localhost"/>'+ ' <delay xmlns="urn:xmpp:delay" stamp="'+moment().format()+'" from="some1@localhost"/>'+
'</message>').firstChild; '</message>').firstChild;
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
jasmine.clock().uninstall();
return test_utils.waitUntil(() => view.model.messages.length > 1);
}).then(() => {
jasmine.clock().install();
jasmine.clock().mockDate(baseTime);
jasmine.clock().tick(ONE_DAY_LATER);
jasmine.clock().tick(ONE_DAY_LATER);
jasmine.clock().tick(ONE_DAY_LATER);
jasmine.clock().tick(ONE_DAY_LATER);
jasmine.clock().tick(ONE_DAY_LATER); jasmine.clock().tick(ONE_DAY_LATER);
// Test a user leaving a groupchat // Test a user leaving a groupchat
presence = $pres({ const presence = $pres({
to: 'dummy@localhost/_converse.js-29092160', to: 'dummy@localhost/_converse.js-29092160',
type: 'unavailable', type: 'unavailable',
from: 'coven@chat.shakespeare.lit/newguy' from: 'coven@chat.shakespeare.lit/newguy'
...@@ -754,10 +769,10 @@ ...@@ -754,10 +769,10 @@
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
time = chat_content.querySelectorAll('time.separator-text'); const time = chat_content.querySelectorAll('time.separator-text');
expect(time.length).toEqual(6); expect(time.length).toEqual(6);
$indicator = $chat_content.find('.date-separator:eq(5)'); const $indicator = $chat_content.find('.date-separator:eq(5)');
expect($indicator.attr('class')).toEqual('message date-separator'); expect($indicator.attr('class')).toEqual('message date-separator');
expect($indicator.data('isodate')).toEqual(moment().startOf('day').format()); expect($indicator.data('isodate')).toEqual(moment().startOf('day').format());
...@@ -766,11 +781,9 @@ ...@@ -766,11 +781,9 @@
expect($chat_content.find('div.chat-info:last').html()).toBe( expect($chat_content.find('div.chat-info:last').html()).toBe(
'newguy has left the groupchat. '+ 'newguy has left the groupchat. '+
'"Disconnected: Replaced by new connection"'); '"Disconnected: Replaced by new connection"');
jasmine.clock().uninstall(); jasmine.clock().uninstall();
done(); done();
return; }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
});
})); }));
it("shows its description in the chat heading", it("shows its description in the chat heading",
...@@ -827,16 +840,16 @@ ...@@ -827,16 +840,16 @@
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched'], {},
function (done, _converse) { function (done, _converse) {
let view;
test_utils.waitUntilDiscoConfirmed(_converse, 'localhost', [], ['vcard-temp']) test_utils.waitUntilDiscoConfirmed(_converse, 'localhost', [], ['vcard-temp'])
.then(function () { .then(() => test_utils.waitUntil(() => _converse.xmppstatus.vcard.get('fullname')))
return test_utils.waitUntil(() => _converse.xmppstatus.vcard.get('fullname')) .then(() => {
}).then(function () {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
return test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy'); return test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy');
}).then(function () { }).then(() => {
var view = _converse.chatboxviews.get('lounge@localhost'); view = _converse.chatboxviews.get('lounge@localhost');
if (!$(view.el).find('.chat-area').length) { view.renderChatArea(); } if (!$(view.el).find('.chat-area').length) { view.renderChatArea(); }
var message = '/me is tired'; const message = '/me is tired';
var nick = mock.chatroom_names[0], var nick = mock.chatroom_names[0],
msg = $msg({ msg = $msg({
'from': 'lounge@localhost/'+nick, 'from': 'lounge@localhost/'+nick,
...@@ -845,17 +858,21 @@ ...@@ -845,17 +858,21 @@
'type': 'groupchat' 'type': 'groupchat'
}).c('body').t(message).tree(); }).c('body').t(message).tree();
view.model.onMessage(msg); view.model.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
expect(_.includes($(view.el).find('.chat-msg__author').text(), '**Dyon van de Wege')).toBeTruthy(); expect(_.includes($(view.el).find('.chat-msg__author').text(), '**Dyon van de Wege')).toBeTruthy();
expect($(view.el).find('.chat-msg__text').text()).toBe(' is tired'); expect($(view.el).find('.chat-msg__text').text()).toBe(' is tired');
message = '/me is as well'; const message = '/me is as well';
msg = $msg({ const msg = $msg({
from: 'lounge@localhost/Max Mustermann', from: 'lounge@localhost/Max Mustermann',
id: (new Date()).getTime(), id: (new Date()).getTime(),
to: 'dummy@localhost', to: 'dummy@localhost',
type: 'groupchat' type: 'groupchat'
}).c('body').t(message).tree(); }).c('body').t(message).tree();
view.model.onMessage(msg); view.model.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length > 1);
}).then(() => {
expect(_.includes($(view.el).find('.chat-msg__author:last').text(), '**Max Mustermann')).toBeTruthy(); expect(_.includes($(view.el).find('.chat-msg__author:last').text(), '**Max Mustermann')).toBeTruthy();
expect($(view.el).find('.chat-msg__text:last').text()).toBe(' is as well'); expect($(view.el).find('.chat-msg__text:last').text()).toBe(' is as well');
done(); done();
...@@ -1495,20 +1512,18 @@ ...@@ -1495,20 +1512,18 @@
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched'], {},
function (done, _converse) { function (done, _converse) {
let view;
const text = 'This is a received message';
test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () { test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () {
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
var view = _converse.chatboxviews.get('lounge@localhost'); view = _converse.chatboxviews.get('lounge@localhost');
if (!$(view.el).find('.chat-area').length) { view.renderChatArea(); } if (!$(view.el).find('.chat-area').length) { view.renderChatArea(); }
var nick = mock.chatroom_names[0]; var nick = mock.chatroom_names[0];
view.model.occupants.create({ view.model.occupants.create({
'nick': nick, 'nick': nick,
'muc_jid': `${view.model.get('jid')}/${nick}` 'muc_jid': `${view.model.get('jid')}/${nick}`
}); });
var text = 'This is a received message';
var message = $msg({ var message = $msg({
from: 'lounge@localhost/'+nick, from: 'lounge@localhost/'+nick,
id: '1', id: '1',
...@@ -1516,6 +1531,8 @@ ...@@ -1516,6 +1531,8 @@
type: 'groupchat' type: 'groupchat'
}).c('body').t(text); }).c('body').t(text);
view.model.onMessage(message.nodeTree); view.model.onMessage(message.nodeTree);
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
var $chat_content = $(view.el).find('.chat-content'); var $chat_content = $(view.el).find('.chat-content');
expect($chat_content.find('.chat-msg').length).toBe(1); expect($chat_content.find('.chat-msg').length).toBe(1);
expect($chat_content.find('.chat-msg__text').text()).toBe(text); expect($chat_content.find('.chat-msg__text').text()).toBe(text);
...@@ -1568,9 +1585,10 @@ ...@@ -1568,9 +1585,10 @@
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched'], {},
function (done, _converse) { function (done, _converse) {
let view;
var message = 'This message is received while the chat area is scrolled up'; var message = 'This message is received while the chat area is scrolled up';
test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () { test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () {
var view = _converse.chatboxviews.get('lounge@localhost'); view = _converse.chatboxviews.get('lounge@localhost');
spyOn(view, 'scrollDown').and.callThrough(); spyOn(view, 'scrollDown').and.callThrough();
/* Create enough messages so that there's a /* Create enough messages so that there's a
* scrollbar. * scrollbar.
...@@ -1584,8 +1602,10 @@ ...@@ -1584,8 +1602,10 @@
id: (new Date()).getTime(), id: (new Date()).getTime(),
}).c('body').t('Message: '+i).tree()); }).c('body').t('Message: '+i).tree());
} }
return test_utils.waitUntil(() => view.model.messages.length === 20);
}).then(() => {
// Give enough time for `markScrolled` to have been called // Give enough time for `markScrolled` to have been called
setTimeout(function () { setTimeout(() => {
view.content.scrollTop = 0; view.content.scrollTop = 0;
view.model.onMessage( view.model.onMessage(
$msg({ $msg({
...@@ -1595,12 +1615,15 @@ ...@@ -1595,12 +1615,15 @@
id: (new Date()).getTime(), id: (new Date()).getTime(),
}).c('body').t(message).tree()); }).c('body').t(message).tree());
// Now check that the message appears inside the chatbox in the DOM test_utils.waitUntil(() => view.model.messages.length === 21)
var $chat_content = $(view.el).find('.chat-content'); .then(() => {
var msg_txt = $chat_content.find('.chat-msg:last').find('.chat-msg__text').text(); // Now check that the message appears inside the chatbox in the DOM
expect(msg_txt).toEqual(message); var $chat_content = $(view.el).find('.chat-content');
expect(view.content.scrollTop).toBe(0); var msg_txt = $chat_content.find('.chat-msg:last').find('.chat-msg__text').text();
done(); expect(msg_txt).toEqual(message);
expect(view.content.scrollTop).toBe(0);
done();
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
}, 500); }, 500);
}); });
})); }));
...@@ -3435,19 +3458,19 @@ ...@@ -3435,19 +3458,19 @@
var roomspanel = _converse.chatboxviews.get('controlbox').roomspanel; var roomspanel = _converse.chatboxviews.get('controlbox').roomspanel;
expect(roomspanel.el.querySelectorAll('.available-room').length).toBe(0); expect(roomspanel.el.querySelectorAll('.available-room').length).toBe(0);
var room_jid = 'kitchen@conference.shakespeare.lit'; let view, nick;
test_utils.openAndEnterChatRoom( const room_jid = 'kitchen@conference.shakespeare.lit';
_converse, 'kitchen', 'conference.shakespeare.lit', 'fires').then(function () { const message = 'fires: Your attention is required';
test_utils.openAndEnterChatRoom(_converse, 'kitchen', 'conference.shakespeare.lit', 'fires')
.then(() => {
expect(roomspanel.el.querySelectorAll('.available-room').length).toBe(1); expect(roomspanel.el.querySelectorAll('.available-room').length).toBe(1);
expect(roomspanel.el.querySelectorAll('.msgs-indicator').length).toBe(0); expect(roomspanel.el.querySelectorAll('.msgs-indicator').length).toBe(0);
var view = _converse.chatboxviews.get(room_jid); view = _converse.chatboxviews.get(room_jid);
view.model.set({'minimized': true}); view.model.set({'minimized': true});
var contact_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost'; var contact_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost';
var message = 'fires: Your attention is required'; nick = mock.chatroom_names[0];
var nick = mock.chatroom_names[0];
view.model.onMessage($msg({ view.model.onMessage($msg({
from: room_jid+'/'+nick, from: room_jid+'/'+nick,
...@@ -3455,7 +3478,8 @@ ...@@ -3455,7 +3478,8 @@
to: 'dummy@localhost', to: 'dummy@localhost',
type: 'groupchat' type: 'groupchat'
}).c('body').t(message).tree()); }).c('body').t(message).tree());
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
expect(roomspanel.el.querySelectorAll('.available-room').length).toBe(1); expect(roomspanel.el.querySelectorAll('.available-room').length).toBe(1);
expect(roomspanel.el.querySelectorAll('.msgs-indicator').length).toBe(1); expect(roomspanel.el.querySelectorAll('.msgs-indicator').length).toBe(1);
expect(roomspanel.el.querySelector('.msgs-indicator').textContent).toBe('1'); expect(roomspanel.el.querySelector('.msgs-indicator').textContent).toBe('1');
...@@ -3466,17 +3490,16 @@ ...@@ -3466,17 +3490,16 @@
'to': 'dummy@localhost', 'to': 'dummy@localhost',
'type': 'groupchat' 'type': 'groupchat'
}).c('body').t(message).tree()); }).c('body').t(message).tree());
return test_utils.waitUntil(() => view.model.messages.length > 1);
}).then(() => {
expect(roomspanel.el.querySelectorAll('.available-room').length).toBe(1); expect(roomspanel.el.querySelectorAll('.available-room').length).toBe(1);
expect(roomspanel.el.querySelectorAll('.msgs-indicator').length).toBe(1); expect(roomspanel.el.querySelectorAll('.msgs-indicator').length).toBe(1);
expect(roomspanel.el.querySelector('.msgs-indicator').textContent).toBe('2'); expect(roomspanel.el.querySelector('.msgs-indicator').textContent).toBe('2');
view.model.set({'minimized': false}); view.model.set({'minimized': false});
expect(roomspanel.el.querySelectorAll('.available-room').length).toBe(1); expect(roomspanel.el.querySelectorAll('.available-room').length).toBe(1);
expect(roomspanel.el.querySelectorAll('.msgs-indicator').length).toBe(0); expect(roomspanel.el.querySelectorAll('.msgs-indicator').length).toBe(0);
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
describe("A Chat Status Notification", function () { describe("A Chat Status Notification", function () {
...@@ -3488,11 +3511,11 @@ ...@@ -3488,11 +3511,11 @@
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.openAndEnterChatRoom( let view;
_converse, 'coven', 'chat.shakespeare.lit', 'some1').then(function () { const room_jid = 'coven@chat.shakespeare.lit';
test_utils.openAndEnterChatRoom(_converse, 'coven', 'chat.shakespeare.lit', 'some1')
var room_jid = 'coven@chat.shakespeare.lit'; .then(() => {
var view = _converse.chatboxviews.get('coven@chat.shakespeare.lit'); view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
var $chat_content = $(view.el).find('.chat-content'); var $chat_content = $(view.el).find('.chat-content');
expect($chat_content.find('div.chat-info:first').html()).toBe("some1 has entered the groupchat"); expect($chat_content.find('div.chat-info:first').html()).toBe("some1 has entered the groupchat");
...@@ -3534,9 +3557,9 @@ ...@@ -3534,9 +3557,9 @@
to: 'dummy@localhost', to: 'dummy@localhost',
type: 'groupchat' type: 'groupchat'
}).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
view.model.onMessage(msg); view.model.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
// Check that the notification appears inside the chatbox in the DOM // Check that the notification appears inside the chatbox in the DOM
var events = view.el.querySelectorAll('.chat-event'); var events = view.el.querySelectorAll('.chat-event');
expect(events.length).toBe(3); expect(events.length).toBe(3);
...@@ -3548,91 +3571,63 @@ ...@@ -3548,91 +3571,63 @@
expect(notifications.length).toBe(1); expect(notifications.length).toBe(1);
expect(notifications[0].textContent).toEqual('newguy is typing'); expect(notifications[0].textContent).toEqual('newguy is typing');
const timeout_functions = [];
spyOn(window, 'setTimeout').and.callFake(function (func, delay) {
timeout_functions.push(func);
});
// Check that it doesn't appear twice // Check that it doesn't appear twice
msg = $msg({ const msg = $msg({
from: room_jid+'/newguy', from: room_jid+'/newguy',
id: (new Date()).getTime(), id: (new Date()).getTime(),
to: 'dummy@localhost', to: 'dummy@localhost',
type: 'groupchat' type: 'groupchat'
}).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
view.model.onMessage(msg); view.model.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length > 1);
events = view.el.querySelectorAll('.chat-event'); }).then(() => {
const events = view.el.querySelectorAll('.chat-event');
expect(events.length).toBe(3); expect(events.length).toBe(3);
expect(events[0].textContent).toEqual('some1 has entered the groupchat'); expect(events[0].textContent).toEqual('some1 has entered the groupchat');
expect(events[1].textContent).toEqual('newguy has entered the groupchat'); expect(events[1].textContent).toEqual('newguy has entered the groupchat');
expect(events[2].textContent).toEqual('nomorenicks has entered the groupchat'); expect(events[2].textContent).toEqual('nomorenicks has entered the groupchat');
notifications = view.el.querySelectorAll('.chat-state-notification'); const notifications = view.el.querySelectorAll('.chat-state-notification');
expect(notifications.length).toBe(1); expect(notifications.length).toBe(1);
expect(notifications[0].textContent).toEqual('newguy is typing'); expect(notifications[0].textContent).toEqual('newguy is typing');
expect(timeout_functions.length).toBe(1);
// <composing> state for a different occupant // <composing> state for a different occupant
msg = $msg({ const msg = $msg({
from: room_jid+'/nomorenicks', from: room_jid+'/nomorenicks',
id: (new Date()).getTime(), id: (new Date()).getTime(),
to: 'dummy@localhost', to: 'dummy@localhost',
type: 'groupchat' type: 'groupchat'
}).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
view.model.onMessage(msg); view.model.onMessage(msg);
events = view.el.querySelectorAll('.chat-event'); return test_utils.waitUntil(() => view.model.messages.length > 2);
}).then(() => {
const events = view.el.querySelectorAll('.chat-event');
expect(events.length).toBe(3); expect(events.length).toBe(3);
expect(events[0].textContent).toEqual('some1 has entered the groupchat'); expect(events[0].textContent).toEqual('some1 has entered the groupchat');
expect(events[1].textContent).toEqual('newguy has entered the groupchat'); expect(events[1].textContent).toEqual('newguy has entered the groupchat');
expect(events[2].textContent).toEqual('nomorenicks has entered the groupchat'); expect(events[2].textContent).toEqual('nomorenicks has entered the groupchat');
notifications = view.el.querySelectorAll('.chat-state-notification'); const notifications = view.el.querySelectorAll('.chat-state-notification');
expect(notifications.length).toBe(2); expect(notifications.length).toBe(2);
expect(notifications[0].textContent).toEqual('newguy is typing'); expect(notifications[0].textContent).toEqual('newguy is typing');
expect(notifications[1].textContent).toEqual('nomorenicks is typing'); expect(notifications[1].textContent).toEqual('nomorenicks is typing');
expect(timeout_functions.length).toBe(2);
// Check that new messages appear under the chat state // Check that new messages appear under the chat state
// notifications // notifications
msg = $msg({ const msg = $msg({
from: 'lounge@localhost/some1', from: 'lounge@localhost/some1',
id: (new Date()).getTime(), id: (new Date()).getTime(),
to: 'dummy@localhost', to: 'dummy@localhost',
type: 'groupchat' type: 'groupchat'
}).c('body').t('hello world').tree(); }).c('body').t('hello world').tree();
view.model.onMessage(msg); view.model.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length);
var messages = view.el.querySelectorAll('.message'); }).then(() => {
const messages = view.el.querySelectorAll('.message');
expect(messages.length).toBe(7); expect(messages.length).toBe(7);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1); expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(view.el.querySelector('.chat-msg .chat-msg__text').textContent).toBe('hello world'); expect(view.el.querySelector('.chat-msg .chat-msg__text').textContent).toBe('hello world');
// Test that the composing notifications get removed
// via timeout.
timeout_functions[0]();
events = view.el.querySelectorAll('.chat-event');
expect(events.length).toBe(3);
expect(events[0].textContent).toEqual('some1 has entered the groupchat');
expect(events[1].textContent).toEqual('newguy has entered the groupchat');
expect(events[2].textContent).toEqual('nomorenicks has entered the groupchat');
notifications = view.el.querySelectorAll('.chat-state-notification');
expect(notifications.length).toBe(1);
expect(notifications[0].textContent).toEqual('nomorenicks is typing');
timeout_functions[1]();
events = view.el.querySelectorAll('.chat-event');
expect(events.length).toBe(3);
expect(events[0].textContent).toEqual('some1 has entered the groupchat');
expect(events[1].textContent).toEqual('newguy has entered the groupchat');
expect(events[2].textContent).toEqual('nomorenicks has entered the groupchat');
notifications = view.el.querySelectorAll('.chat-state-notification');
expect(notifications.length).toBe(0);
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
}); });
...@@ -3642,10 +3637,11 @@ ...@@ -3642,10 +3637,11 @@
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
let view, msg
const room_jid = 'coven@chat.shakespeare.lit';
test_utils.openChatRoom(_converse, "coven", 'chat.shakespeare.lit', 'some1') test_utils.openChatRoom(_converse, "coven", 'chat.shakespeare.lit', 'some1')
.then(() => { .then(() => {
var room_jid = 'coven@chat.shakespeare.lit'; view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
var view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
var $chat_content = $(view.el).find('.chat-content'); var $chat_content = $(view.el).find('.chat-content');
/* <presence to="dummy@localhost/_converse.js-29092160" /* <presence to="dummy@localhost/_converse.js-29092160"
...@@ -3700,13 +3696,15 @@ ...@@ -3700,13 +3696,15 @@
// See XEP-0085 http://xmpp.org/extensions/xep-0085.html#definitions // See XEP-0085 http://xmpp.org/extensions/xep-0085.html#definitions
// <composing> state // <composing> state
var msg = $msg({ const msg = $msg({
from: room_jid+'/newguy', from: room_jid+'/newguy',
id: (new Date()).getTime(), id: (new Date()).getTime(),
to: 'dummy@localhost', to: 'dummy@localhost',
type: 'groupchat' type: 'groupchat'
}).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
view.model.onMessage(msg); view.model.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
// Check that the notification appears inside the chatbox in the DOM // Check that the notification appears inside the chatbox in the DOM
var events = view.el.querySelectorAll('.chat-event'); var events = view.el.querySelectorAll('.chat-event');
...@@ -3720,63 +3718,69 @@ ...@@ -3720,63 +3718,69 @@
expect(notifications[0].textContent).toEqual('newguy is typing'); expect(notifications[0].textContent).toEqual('newguy is typing');
// Check that it doesn't appear twice // Check that it doesn't appear twice
msg = $msg({ const msg = $msg({
from: room_jid+'/newguy', from: room_jid+'/newguy',
id: (new Date()).getTime(), id: (new Date()).getTime(),
to: 'dummy@localhost', to: 'dummy@localhost',
type: 'groupchat' type: 'groupchat'
}).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
view.model.onMessage(msg); view.model.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length > 1);
}).then(() => {
events = view.el.querySelectorAll('.chat-event'); const events = view.el.querySelectorAll('.chat-event');
expect(events.length).toBe(3); expect(events.length).toBe(3);
expect(events[0].textContent).toEqual('some1 has entered the groupchat'); expect(events[0].textContent).toEqual('some1 has entered the groupchat');
expect(events[1].textContent).toEqual('newguy has entered the groupchat'); expect(events[1].textContent).toEqual('newguy has entered the groupchat');
expect(events[2].textContent).toEqual('nomorenicks has entered the groupchat'); expect(events[2].textContent).toEqual('nomorenicks has entered the groupchat');
notifications = view.el.querySelectorAll('.chat-state-notification'); const notifications = view.el.querySelectorAll('.chat-state-notification');
expect(notifications.length).toBe(1); expect(notifications.length).toBe(1);
expect(notifications[0].textContent).toEqual('newguy is typing'); expect(notifications[0].textContent).toEqual('newguy is typing');
// <composing> state for a different occupant // <composing> state for a different occupant
msg = $msg({ const msg = $msg({
from: room_jid+'/nomorenicks', from: room_jid+'/nomorenicks',
id: (new Date()).getTime(), id: (new Date()).getTime(),
to: 'dummy@localhost', to: 'dummy@localhost',
type: 'groupchat' type: 'groupchat'
}).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
view.model.onMessage(msg); view.model.onMessage(msg);
events = view.el.querySelectorAll('.chat-event'); return test_utils.waitUntil(() => view.model.messages.length > 2);
}).then(() => {
const events = view.el.querySelectorAll('.chat-event');
expect(events.length).toBe(3); expect(events.length).toBe(3);
expect(events[0].textContent).toEqual('some1 has entered the groupchat'); expect(events[0].textContent).toEqual('some1 has entered the groupchat');
expect(events[1].textContent).toEqual('newguy has entered the groupchat'); expect(events[1].textContent).toEqual('newguy has entered the groupchat');
expect(events[2].textContent).toEqual('nomorenicks has entered the groupchat'); expect(events[2].textContent).toEqual('nomorenicks has entered the groupchat');
notifications = view.el.querySelectorAll('.chat-state-notification'); const notifications = view.el.querySelectorAll('.chat-state-notification');
expect(notifications.length).toBe(2); expect(notifications.length).toBe(2);
expect(notifications[0].textContent).toEqual('newguy is typing'); expect(notifications[0].textContent).toEqual('newguy is typing');
expect(notifications[1].textContent).toEqual('nomorenicks is typing'); expect(notifications[1].textContent).toEqual('nomorenicks is typing');
// <paused> state from occupant who typed first // <paused> state from occupant who typed first
msg = $msg({ const msg = $msg({
from: room_jid+'/newguy', from: room_jid+'/newguy',
id: (new Date()).getTime(), id: (new Date()).getTime(),
to: 'dummy@localhost', to: 'dummy@localhost',
type: 'groupchat' type: 'groupchat'
}).c('body').c('paused', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('body').c('paused', {'xmlns': Strophe.NS.CHATSTATES}).tree();
view.model.onMessage(msg); view.model.onMessage(msg);
events = view.el.querySelectorAll('.chat-event'); return test_utils.waitUntil(() => view.model.messages.length > 3);
}).then(() => {
const events = view.el.querySelectorAll('.chat-event');
expect(events.length).toBe(3); expect(events.length).toBe(3);
expect(events[0].textContent).toEqual('some1 has entered the groupchat'); expect(events[0].textContent).toEqual('some1 has entered the groupchat');
expect(events[1].textContent).toEqual('newguy has entered the groupchat'); expect(events[1].textContent).toEqual('newguy has entered the groupchat');
expect(events[2].textContent).toEqual('nomorenicks has entered the groupchat'); expect(events[2].textContent).toEqual('nomorenicks has entered the groupchat');
notifications = view.el.querySelectorAll('.chat-state-notification'); const notifications = view.el.querySelectorAll('.chat-state-notification');
expect(notifications.length).toBe(2); expect(notifications.length).toBe(2);
expect(notifications[0].textContent).toEqual('nomorenicks is typing'); expect(notifications[0].textContent).toEqual('nomorenicks is typing');
expect(notifications[1].textContent).toEqual('newguy has stopped typing'); expect(notifications[1].textContent).toEqual('newguy has stopped typing');
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
}); });
}); });
......
(function (root, factory) { (function (root, factory) {
define(["jquery", "jasmine", "mock", "test-utils"], factory); define(["jquery", "jasmine", "mock", "test-utils"], factory);
} (this, function ($, jasmine, mock, test_utils) { } (this, function ($, jasmine, mock, test_utils) {
var _ = converse.env._; const _ = converse.env._,
var $pres = converse.env.$pres; $pres = converse.env.$pres,
var $msg = converse.env.$msg; $msg = converse.env.$msg,
var $iq = converse.env.$iq; $iq = converse.env.$iq,
var u = converse.env.utils; u = converse.env.utils,
Strophe = converse.env.Strophe;
describe("The Controlbox", function () { describe("The Controlbox", function () {
...@@ -72,18 +73,18 @@ ...@@ -72,18 +73,18 @@
test_utils.createContacts(_converse, 'all').openControlBox(); test_utils.createContacts(_converse, 'all').openControlBox();
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
let chatview;
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, sender_jid); test_utils.openChatBoxFor(_converse, sender_jid);
return test_utils.waitUntil(() => _converse.chatboxes.length).then(() => { return test_utils.waitUntil(() => _converse.chatboxes.length).then(() => {
chatview = _converse.chatboxviews.get(sender_jid);
const chatview = _converse.chatboxviews.get(sender_jid);
chatview.model.set({'minimized': true}); chatview.model.set({'minimized': true});
expect(_.isNull(_converse.chatboxviews.el.querySelector('.restore-chat .message-count'))).toBeTruthy(); expect(_.isNull(_converse.chatboxviews.el.querySelector('.restore-chat .message-count'))).toBeTruthy();
expect(_.isNull(_converse.rosterview.el.querySelector('.msgs-indicator'))).toBeTruthy(); expect(_.isNull(_converse.rosterview.el.querySelector('.msgs-indicator'))).toBeTruthy();
var msg = $msg({ const msg = $msg({
from: sender_jid, from: sender_jid,
to: _converse.connection.jid, to: _converse.connection.jid,
type: 'chat', type: 'chat',
...@@ -91,10 +92,13 @@ ...@@ -91,10 +92,13 @@
}).c('body').t('hello').up() }).c('body').t('hello').up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll(".msgs-indicator"));
}).then(() => {
spyOn(chatview.model, 'incrementUnreadMsgCounter').and.callThrough();
expect(_converse.chatboxviews.el.querySelector('.restore-chat .message-count').textContent).toBe('1'); expect(_converse.chatboxviews.el.querySelector('.restore-chat .message-count').textContent).toBe('1');
expect(_converse.rosterview.el.querySelector('.msgs-indicator').textContent).toBe('1'); expect(_converse.rosterview.el.querySelector('.msgs-indicator').textContent).toBe('1');
msg = $msg({ const msg = $msg({
from: sender_jid, from: sender_jid,
to: _converse.connection.jid, to: _converse.connection.jid,
type: 'chat', type: 'chat',
...@@ -102,14 +106,15 @@ ...@@ -102,14 +106,15 @@
}).c('body').t('hello again').up() }).c('body').t('hello again').up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => chatview.model.incrementUnreadMsgCounter.calls.count());
}).then(() => {
expect(_converse.chatboxviews.el.querySelector('.restore-chat .message-count').textContent).toBe('2'); expect(_converse.chatboxviews.el.querySelector('.restore-chat .message-count').textContent).toBe('2');
expect(_converse.rosterview.el.querySelector('.msgs-indicator').textContent).toBe('2'); expect(_converse.rosterview.el.querySelector('.msgs-indicator').textContent).toBe('2');
chatview.model.set({'minimized': false}); chatview.model.set({'minimized': false});
expect(_.isNull(_converse.chatboxviews.el.querySelector('.restore-chat .message-count'))).toBeTruthy(); expect(_.isNull(_converse.chatboxviews.el.querySelector('.restore-chat .message-count'))).toBeTruthy();
expect(_.isNull(_converse.rosterview.el.querySelector('.msgs-indicator'))).toBeTruthy(); expect(_.isNull(_converse.rosterview.el.querySelector('.msgs-indicator'))).toBeTruthy();
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
})); }));
}); });
......
...@@ -20,15 +20,27 @@ ...@@ -20,15 +20,27 @@
null, ['discoInitialized'], {}, null, ['discoInitialized'], {},
function (done, _converse) { function (done, _converse) {
test_utils.openAndEnterChatRoom(_converse, 'trek-radio', 'conference.lightwitch.org', 'jcbrand').then(function () { let view, stanza;
var chatroomview = _converse.chatboxviews.get('trek-radio@conference.lightwitch.org');
var stanza = Strophe.xmlHtmlNode( test_utils.openAndEnterChatRoom(_converse, 'trek-radio', 'conference.lightwitch.org', 'jcbrand')
.then(() => {
view = _converse.chatboxviews.get('trek-radio@conference.lightwitch.org');
stanza = Strophe.xmlHtmlNode(
`<message xmlns="jabber:client" to="jcbrand@lightwitch.org/converse.js-73057452" type="groupchat" from="trek-radio@conference.lightwitch.org/comndrdukath#0805 (STO)"> `<message xmlns="jabber:client" to="jcbrand@lightwitch.org/converse.js-73057452" type="groupchat" from="trek-radio@conference.lightwitch.org/comndrdukath#0805 (STO)">
<body>negan</body> <body>negan</body>
<stanza-id xmlns="urn:xmpp:sid:0" id="45fbbf2a-1059-479d-9283-c8effaf05621" by="trek-radio@conference.lightwitch.org"/> <stanza-id xmlns="urn:xmpp:sid:0" id="45fbbf2a-1059-479d-9283-c8effaf05621" by="trek-radio@conference.lightwitch.org"/>
</message>`).firstElementChild; </message>`).firstElementChild;
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
return test_utils.waitUntil(() => view.content.querySelectorAll('.chat-msg').length)
}).then(() => {
// XXX: we wait here until the first message appears before
// sending the duplicate. If we don't do that, then the
// duplicate appears before the promise for `createMessage`
// has been resolved, which means that the `isDuplicate`
// check fails because the first message doesn't exist yet.
//
// Not sure whether such a race-condition might pose a problem
// in "real-world" situations.
stanza = Strophe.xmlHtmlNode( stanza = Strophe.xmlHtmlNode(
`<message xmlns="jabber:client" to="jcbrand@lightwitch.org/converse.js-73057452"> `<message xmlns="jabber:client" to="jcbrand@lightwitch.org/converse.js-73057452">
<result xmlns="urn:xmpp:mam:2" queryid="82d9db27-6cf8-4787-8c2c-5a560263d823" id="45fbbf2a-1059-479d-9283-c8effaf05621"> <result xmlns="urn:xmpp:mam:2" queryid="82d9db27-6cf8-4787-8c2c-5a560263d823" id="45fbbf2a-1059-479d-9283-c8effaf05621">
...@@ -39,10 +51,14 @@ ...@@ -39,10 +51,14 @@
</forwarded> </forwarded>
</result> </result>
</message>`).firstElementChild; </message>`).firstElementChild;
chatroomview.model.onMessage(stanza);
expect(chatroomview.content.querySelectorAll('.chat-msg').length).toBe(1); spyOn(view.model, 'isDuplicate').and.callThrough();
view.model.onMessage(stanza);
return test_utils.waitUntil(() => view.model.isDuplicate.calls.count());
}).then(() => {
expect(view.content.querySelectorAll('.chat-msg').length).toBe(1);
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
})) }))
}); });
......
...@@ -274,32 +274,29 @@ ...@@ -274,32 +274,29 @@
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.waitUntil(function () { let message, msg, view;
return $(_converse.rosterview.el).find('.roster-group').length; const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
}, 300) test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length)
.then(function () { .then(() => {
var message, msg;
spyOn(_converse, 'log'); spyOn(_converse, 'log');
spyOn(_converse.chatboxes, 'getChatBox').and.callThrough(); spyOn(_converse.chatboxes, 'getChatBox').and.callThrough();
_converse.filter_by_resource = true; _converse.filter_by_resource = true;
var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
/* <message id='aeb213' to='juliet@capulet.lit/chamber'> /* <message id='aeb213' to='juliet@capulet.lit/chamber'>
* <forwarded xmlns='urn:xmpp:forward:0'> * <forwarded xmlns='urn:xmpp:forward:0'>
* <delay xmlns='urn:xmpp:delay' stamp='2010-07-10T23:08:25Z'/> * <delay xmlns='urn:xmpp:delay' stamp='2010-07-10T23:08:25Z'/>
* <message xmlns='jabber:client' * <message xmlns='jabber:client'
* to='juliet@capulet.lit/balcony' * to='juliet@capulet.lit/balcony'
* from='romeo@montague.lit/orchard' * from='romeo@montague.lit/orchard'
* type='chat'> * type='chat'>
* <body>Call me but love, and I'll be new baptized; Henceforth I never will be Romeo.</body> * <body>Call me but love, and I'll be new baptized; Henceforth I never will be Romeo.</body>
* </message> * </message>
* </forwarded> * </forwarded>
* </message> * </message>
*/ */
msg = $msg({'id': 'aeb213', 'to': _converse.bare_jid}) msg = $msg({'id': 'aeb213', 'to': _converse.bare_jid})
.c('forwarded', {'xmlns': 'urn:xmpp:forward:0'}) .c('forwarded', {'xmlns': 'urn:xmpp:forward:0'})
.c('delay', {'xmlns': 'urn:xmpp:delay', 'stamp':'2018-01-02T13:08:25Z'}).up() .c('delay', {'xmlns': 'urn:xmpp:delay', 'stamp':'2018-01-02T13:08:25Z'}).up()
...@@ -311,7 +308,9 @@ ...@@ -311,7 +308,9 @@
.c('body').t("message") .c('body').t("message")
.tree(); .tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => _converse.api.chats.get().length);
}).then(() => {
view = _converse.chatboxviews.get(sender_jid);
msg = $msg({'id': 'aeb214', 'to': _converse.bare_jid}) msg = $msg({'id': 'aeb214', 'to': _converse.bare_jid})
.c('forwarded', {'xmlns': 'urn:xmpp:forward:0'}) .c('forwarded', {'xmlns': 'urn:xmpp:forward:0'})
.c('delay', {'xmlns': 'urn:xmpp:delay', 'stamp':'2017-12-31T22:08:25Z'}).up() .c('delay', {'xmlns': 'urn:xmpp:delay', 'stamp':'2017-12-31T22:08:25Z'}).up()
...@@ -323,6 +322,8 @@ ...@@ -323,6 +322,8 @@
.c('body').t("Older message") .c('body').t("Older message")
.tree(); .tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
msg = $msg({'id': 'aeb215', 'to': _converse.bare_jid}) msg = $msg({'id': 'aeb215', 'to': _converse.bare_jid})
.c('forwarded', {'xmlns': 'urn:xmpp:forward:0'}) .c('forwarded', {'xmlns': 'urn:xmpp:forward:0'})
...@@ -335,7 +336,8 @@ ...@@ -335,7 +336,8 @@
.c('body').t("Inbetween message").up() .c('body').t("Inbetween message").up()
.tree(); .tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
msg = $msg({'id': 'aeb216', 'to': _converse.bare_jid}) msg = $msg({'id': 'aeb216', 'to': _converse.bare_jid})
.c('forwarded', {'xmlns': 'urn:xmpp:forward:0'}) .c('forwarded', {'xmlns': 'urn:xmpp:forward:0'})
.c('delay', {'xmlns': 'urn:xmpp:delay', 'stamp':'2018-01-01T13:18:23Z'}).up() .c('delay', {'xmlns': 'urn:xmpp:delay', 'stamp':'2018-01-01T13:18:23Z'}).up()
...@@ -347,7 +349,8 @@ ...@@ -347,7 +349,8 @@
.c('body').t("another inbetween message") .c('body').t("another inbetween message")
.tree(); .tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
msg = $msg({'id': 'aeb217', 'to': _converse.bare_jid}) msg = $msg({'id': 'aeb217', 'to': _converse.bare_jid})
.c('forwarded', {'xmlns': 'urn:xmpp:forward:0'}) .c('forwarded', {'xmlns': 'urn:xmpp:forward:0'})
.c('delay', {'xmlns': 'urn:xmpp:delay', 'stamp':'2018-01-02T12:18:23Z'}).up() .c('delay', {'xmlns': 'urn:xmpp:delay', 'stamp':'2018-01-02T12:18:23Z'}).up()
...@@ -359,7 +362,8 @@ ...@@ -359,7 +362,8 @@
.c('body').t("An earlier message on the next day") .c('body').t("An earlier message on the next day")
.tree(); .tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
msg = $msg({'id': 'aeb218', 'to': _converse.bare_jid}) msg = $msg({'id': 'aeb218', 'to': _converse.bare_jid})
.c('forwarded', {'xmlns': 'urn:xmpp:forward:0'}) .c('forwarded', {'xmlns': 'urn:xmpp:forward:0'})
.c('delay', {'xmlns': 'urn:xmpp:delay', 'stamp':'2018-01-02T22:28:23Z'}).up() .c('delay', {'xmlns': 'urn:xmpp:delay', 'stamp':'2018-01-02T22:28:23Z'}).up()
...@@ -371,7 +375,8 @@ ...@@ -371,7 +375,8 @@
.c('body').t("newer message from the next day") .c('body').t("newer message from the next day")
.tree(); .tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
// Insert <composing> message, to also check that // Insert <composing> message, to also check that
// text messages are inserted correctly with // text messages are inserted correctly with
// temporary chat events in the chat contents. // temporary chat events in the chat contents.
...@@ -384,7 +389,8 @@ ...@@ -384,7 +389,8 @@
.c('composing', {'xmlns': Strophe.NS.CHATSTATES}).up() .c('composing', {'xmlns': Strophe.NS.CHATSTATES}).up()
.tree(); .tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
msg = $msg({ msg = $msg({
'id': 'aeb220', 'id': 'aeb220',
'to': _converse.bare_jid, 'to': _converse.bare_jid,
...@@ -395,10 +401,10 @@ ...@@ -395,10 +401,10 @@
.c('body').t("latest message") .c('body').t("latest message")
.tree(); .tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length);
var chatboxview = _converse.chatboxviews.get(sender_jid); }).then(() => {
var $chat_content = $(chatboxview.el).find('.chat-content'); var $chat_content = $(view.el.querySelector('.chat-content'));
chatboxview.clearSpinner(); //cleanup view.clearSpinner(); //cleanup
expect($chat_content[0].querySelectorAll('.date-separator').length).toEqual(4); expect($chat_content[0].querySelectorAll('.date-separator').length).toEqual(4);
...@@ -450,7 +456,7 @@ ...@@ -450,7 +456,7 @@
expect($day[0].nextElementSibling.querySelector('.chat-msg__text').textContent).toBe('latest message'); expect($day[0].nextElementSibling.querySelector('.chat-msg__text').textContent).toBe('latest message');
expect($el.hasClass('chat-msg--followup')).toBe(false); expect($el.hasClass('chat-msg--followup')).toBe(false);
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
it("is ignored if it's a malformed headline message", it("is ignored if it's a malformed headline message",
...@@ -499,9 +505,10 @@ ...@@ -499,9 +505,10 @@
// Send a message from a different resource // Send a message from a different resource
spyOn(_converse, 'log'); spyOn(_converse, 'log');
var msgtext = 'This is a carbon message'; let chat_content;
var sender_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost'; const msgtext = 'This is a carbon message';
var msg = $msg({ const sender_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost';
const msg = $msg({
'from': sender_jid, 'from': sender_jid,
'id': (new Date()).getTime(), 'id': (new Date()).getTime(),
'to': _converse.connection.jid, 'to': _converse.connection.jid,
...@@ -516,28 +523,29 @@ ...@@ -516,28 +523,29 @@
'type': 'chat' 'type': 'chat'
}).c('body').t(msgtext).tree(); }).c('body').t(msgtext).tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => _converse.api.chats.get().length)
// Check that the chatbox and its view now exist .then(() => {
var chatbox = _converse.chatboxes.get(sender_jid); // Check that the chatbox and its view now exist
var chatboxview = _converse.chatboxviews.get(sender_jid); var chatbox = _converse.chatboxes.get(sender_jid);
expect(chatbox).toBeDefined(); var chatboxview = _converse.chatboxviews.get(sender_jid);
expect(chatboxview).toBeDefined(); expect(chatbox).toBeDefined();
// Check that the message was received and check the message parameters expect(chatboxview).toBeDefined();
expect(chatbox.messages.length).toEqual(1); // Check that the message was received and check the message parameters
var msg_obj = chatbox.messages.models[0]; expect(chatbox.messages.length).toEqual(1);
expect(msg_obj.get('message')).toEqual(msgtext); var msg_obj = chatbox.messages.models[0];
expect(msg_obj.get('fullname')).toEqual(mock.cur_names[1]); expect(msg_obj.get('message')).toEqual(msgtext);
expect(msg_obj.get('sender')).toEqual('them'); expect(msg_obj.get('fullname')).toEqual(mock.cur_names[1]);
expect(msg_obj.get('is_delayed')).toEqual(false); expect(msg_obj.get('sender')).toEqual('them');
// Now check that the message appears inside the chatbox in the DOM expect(msg_obj.get('is_delayed')).toEqual(false);
const chat_content = chatboxview.el.querySelector('.chat-content'); // Now check that the message appears inside the chatbox in the DOM
expect(chat_content.querySelector('.chat-msg .chat-msg__text').textContent).toEqual(msgtext); chat_content = chatboxview.el.querySelector('.chat-content');
expect(chat_content.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy(); expect(chat_content.querySelector('.chat-msg .chat-msg__text').textContent).toEqual(msgtext);
return test_utils.waitUntil(() => chatbox.vcard.get('fullname') === 'Candice van der Knijff') expect(chat_content.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy();
.then(function () { return test_utils.waitUntil(() => chatbox.vcard.get('fullname') === 'Candice van der Knijff')
}).then(() => {
expect(chat_content.querySelector('span.chat-msg__author').textContent.trim()).toBe('Candice van der Knijff'); expect(chat_content.querySelector('span.chat-msg__author').textContent.trim()).toBe('Candice van der Knijff');
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
it("can be a carbon message that this user sent from a different client, as defined in XEP-0280", it("can be a carbon message that this user sent from a different client, as defined in XEP-0280",
...@@ -545,14 +553,15 @@ ...@@ -545,14 +553,15 @@
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched'], {},
function (done, _converse) { function (done, _converse) {
let recipient_jid, msgtext;
test_utils.waitUntilDiscoConfirmed(_converse, 'localhost', [], ['vcard-temp']).then(function () { test_utils.waitUntilDiscoConfirmed(_converse, 'localhost', [], ['vcard-temp']).then(function () {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
// Send a message from a different resource // Send a message from a different resource
spyOn(_converse, 'log'); spyOn(_converse, 'log');
const msgtext = 'This is a sent carbon message'; msgtext = 'This is a sent carbon message';
const recipient_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost'; recipient_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost';
const msg = $msg({ const msg = $msg({
'from': _converse.bare_jid, 'from': _converse.bare_jid,
'id': (new Date()).getTime(), 'id': (new Date()).getTime(),
...@@ -568,7 +577,8 @@ ...@@ -568,7 +577,8 @@
'type': 'chat' 'type': 'chat'
}).c('body').t(msgtext).tree(); }).c('body').t(msgtext).tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => _converse.api.chats.get().length);
}).then(() => {
// Check that the chatbox and its view now exist // Check that the chatbox and its view now exist
const chatbox = _converse.chatboxes.get(recipient_jid); const chatbox = _converse.chatboxes.get(recipient_jid);
const chatboxview = _converse.chatboxviews.get(recipient_jid); const chatboxview = _converse.chatboxviews.get(recipient_jid);
...@@ -647,13 +657,14 @@ ...@@ -647,13 +657,14 @@
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
const contact_name = mock.cur_names[0]; const contact_name = mock.cur_names[0];
const contact_jid = contact_name.replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = contact_name.replace(/ /g,'.').toLowerCase() + '@localhost';
let chatview, trimmedview, $count, trimmed_chatboxes;
test_utils.openControlBox(); test_utils.openControlBox();
spyOn(_converse, 'emit').and.callThrough(); spyOn(_converse, 'emit').and.callThrough();
test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length) test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length)
.then(() => test_utils.openChatBoxFor(_converse, contact_jid)) .then(() => test_utils.openChatBoxFor(_converse, contact_jid))
.then(() => { .then(() => {
var chatview = _converse.chatboxviews.get(contact_jid); chatview = _converse.chatboxviews.get(contact_jid);
expect(u.isVisible(chatview.el)).toBeTruthy(); expect(u.isVisible(chatview.el)).toBeTruthy();
expect(chatview.model.get('minimized')).toBeFalsy(); expect(chatview.model.get('minimized')).toBeFalsy();
chatview.el.querySelector('.toggle-chatbox-button').click(); chatview.el.querySelector('.toggle-chatbox-button').click();
...@@ -668,10 +679,12 @@ ...@@ -668,10 +679,12 @@
}).c('body').t(message).up() }).c('body').t(message).up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => chatview.model.messages.length);
}).then(() => {
expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object)); expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
var trimmed_chatboxes = _converse.minimized_chats; trimmed_chatboxes = _converse.minimized_chats;
var trimmedview = trimmed_chatboxes.get(contact_jid); trimmedview = trimmed_chatboxes.get(contact_jid);
var $count = $(trimmedview.el).find('.message-count'); $count = $(trimmedview.el).find('.message-count');
expect(u.isVisible(chatview.el)).toBeFalsy(); expect(u.isVisible(chatview.el)).toBeFalsy();
expect(trimmedview.model.get('minimized')).toBeTruthy(); expect(trimmedview.model.get('minimized')).toBeTruthy();
expect(u.isVisible($count[0])).toBeTruthy(); expect(u.isVisible($count[0])).toBeTruthy();
...@@ -685,6 +698,8 @@ ...@@ -685,6 +698,8 @@
}).c('body').t('This message is also sent to a minimized chatbox').up() }).c('body').t('This message is also sent to a minimized chatbox').up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree() .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()
); );
return test_utils.waitUntil(() => chatview.model.messages.length);
}).then(() => {
expect(u.isVisible(chatview.el)).toBeFalsy(); expect(u.isVisible(chatview.el)).toBeFalsy();
expect(trimmedview.model.get('minimized')).toBeTruthy(); expect(trimmedview.model.get('minimized')).toBeTruthy();
$count = $(trimmedview.el).find('.message-count'); $count = $(trimmedview.el).find('.message-count');
...@@ -693,7 +708,7 @@ ...@@ -693,7 +708,7 @@
trimmedview.el.querySelector('.restore-chat').click(); trimmedview.el.querySelector('.restore-chat').click();
expect(trimmed_chatboxes.keys().length).toBe(0); expect(trimmed_chatboxes.keys().length).toBe(0);
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
it("will indicate when it has a time difference of more than a day between it and its predecessor", it("will indicate when it has a time difference of more than a day between it and its predecessor",
...@@ -707,20 +722,19 @@ ...@@ -707,20 +722,19 @@
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
const contact_name = mock.cur_names[1]; const contact_name = mock.cur_names[1];
const contact_jid = contact_name.replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = contact_name.replace(/ /g,'.').toLowerCase() + '@localhost';
let view, chatbox, msg_obj, msg_txt, sender_txt, one_day_ago, message, chat_content, $chat_content, $time;
test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length) test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length)
.then(() => test_utils.openChatBoxFor(_converse, contact_jid)) .then(() => test_utils.openChatBoxFor(_converse, contact_jid))
.then(() => { .then(() => {
test_utils.clearChatBoxMessages(_converse, contact_jid); test_utils.clearChatBoxMessages(_converse, contact_jid);
var one_day_ago = moment(); one_day_ago = moment();
one_day_ago.subtract('days', 1); one_day_ago.subtract('days', 1);
var message = 'This is a day old message'; chatbox = _converse.chatboxes.get(contact_jid);
var chatbox = _converse.chatboxes.get(contact_jid); view = _converse.chatboxviews.get(contact_jid);
var chatboxview = _converse.chatboxviews.get(contact_jid);
var msg_obj;
var msg_txt;
var sender_txt;
var msg = $msg({ message = 'This is a day old message';
const msg = $msg({
from: contact_jid, from: contact_jid,
to: _converse.connection.jid, to: _converse.connection.jid,
type: 'chat', type: 'chat',
...@@ -729,6 +743,8 @@ ...@@ -729,6 +743,8 @@
.c('delay', { xmlns:'urn:xmpp:delay', from: 'localhost', stamp: one_day_ago.format() }) .c('delay', { xmlns:'urn:xmpp:delay', from: 'localhost', stamp: one_day_ago.format() })
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length)
}).then(() => {
expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object)); expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
expect(chatbox.messages.length).toEqual(1); expect(chatbox.messages.length).toEqual(1);
msg_obj = chatbox.messages.models[0]; msg_obj = chatbox.messages.models[0];
...@@ -736,62 +752,62 @@ ...@@ -736,62 +752,62 @@
expect(msg_obj.get('fullname')).toEqual(contact_name); expect(msg_obj.get('fullname')).toEqual(contact_name);
expect(msg_obj.get('sender')).toEqual('them'); expect(msg_obj.get('sender')).toEqual('them');
expect(msg_obj.get('is_delayed')).toEqual(true); expect(msg_obj.get('is_delayed')).toEqual(true);
return test_utils.waitUntil(() => chatbox.vcard.get('fullname') === 'Candice van der Knijff') return test_utils.waitUntil(() => chatbox.vcard.get('fullname') === 'Candice van der Knijff')
.then(function () { }).then(() => {
const chat_content = chatboxview.el.querySelector('.chat-content'); chat_content = view.el.querySelector('.chat-content');
expect(chat_content.querySelector('.chat-msg .chat-msg__text').textContent).toEqual(message); expect(chat_content.querySelector('.chat-msg .chat-msg__text').textContent).toEqual(message);
expect(chat_content.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy(); expect(chat_content.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy();
expect(chat_content.querySelector('span.chat-msg__author').textContent.trim()).toBe('Candice van der Knijff'); expect(chat_content.querySelector('span.chat-msg__author').textContent.trim()).toBe('Candice van der Knijff');
expect(chat_content.querySelectorAll('.date-separator').length).toEqual(1); expect(chat_content.querySelectorAll('.date-separator').length).toEqual(1);
const day = chat_content.querySelector('.date-separator'); const day = chat_content.querySelector('.date-separator');
expect(day.getAttribute('class')).toEqual('message date-separator'); expect(day.getAttribute('class')).toEqual('message date-separator');
expect(day.getAttribute('data-isodate')).toEqual(moment(one_day_ago.startOf('day')).format()); expect(day.getAttribute('data-isodate')).toEqual(moment(one_day_ago.startOf('day')).format());
const $chat_content = $(chat_content); $chat_content = $(chat_content);
var $time = $chat_content.find('time.separator-text'); $time = $chat_content.find('time.separator-text');
expect($time.text()).toEqual(moment(one_day_ago.startOf('day')).format("dddd MMM Do YYYY")); expect($time.text()).toEqual(moment(one_day_ago.startOf('day')).format("dddd MMM Do YYYY"));
message = 'This is a current message'; message = 'This is a current message';
msg = $msg({ const msg = $msg({
from: contact_jid, from: contact_jid,
to: _converse.connection.jid, to: _converse.connection.jid,
type: 'chat', type: 'chat',
id: new Date().getTime() id: new Date().getTime()
}).c('body').t(message).up() }).c('body').t(message).up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object)); return test_utils.waitUntil(() => view.model.messages.length > 1);
// Check that there is a <time> element, with the required }).then(() => {
// props. expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
expect($chat_content[0].querySelectorAll('time.separator-text').length).toEqual(2); // There are now two time elements // Check that there is a <time> element, with the required
// props.
var message_date = new Date(); expect($chat_content[0].querySelectorAll('time.separator-text').length).toEqual(2); // There are now two time elements
const $day = $chat_content.find('.date-separator:last');
expect($day.length).toEqual(1); var message_date = new Date();
expect($day.attr('class')).toEqual('message date-separator'); const $day = $chat_content.find('.date-separator:last');
expect($day.data('isodate')).toEqual(moment(message_date).startOf('day').format()); expect($day.length).toEqual(1);
expect($day.attr('class')).toEqual('message date-separator');
$time = $chat_content.find('time.separator-text:last'); expect($day.data('isodate')).toEqual(moment(message_date).startOf('day').format());
expect($time.text()).toEqual(moment(message_date).startOf('day').format("dddd MMM Do YYYY"));
$time = $chat_content.find('time.separator-text:last');
// Normal checks for the 2nd message expect($time.text()).toEqual(moment(message_date).startOf('day').format("dddd MMM Do YYYY"));
expect(chatbox.messages.length).toEqual(2);
msg_obj = chatbox.messages.models[1]; // Normal checks for the 2nd message
expect(msg_obj.get('message')).toEqual(message); expect(chatbox.messages.length).toEqual(2);
expect(msg_obj.get('fullname')).toEqual(contact_name); msg_obj = chatbox.messages.models[1];
expect(msg_obj.get('sender')).toEqual('them'); expect(msg_obj.get('message')).toEqual(message);
expect(msg_obj.get('is_delayed')).toEqual(false); expect(msg_obj.get('fullname')).toEqual(contact_name);
msg_txt = $chat_content.find('.chat-msg').last().find('.chat-msg__text').text(); expect(msg_obj.get('sender')).toEqual('them');
expect(msg_txt).toEqual(message); expect(msg_obj.get('is_delayed')).toEqual(false);
msg_txt = $chat_content.find('.chat-msg').last().find('.chat-msg__text').text();
expect(msg_txt).toEqual(message);
expect(chat_content.querySelector('.chat-msg:last-child .chat-msg__text').textContent).toEqual(message); expect(chat_content.querySelector('.chat-msg:last-child .chat-msg__text').textContent).toEqual(message);
expect(chat_content.querySelector('.chat-msg:last-child .chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy(); expect(chat_content.querySelector('.chat-msg:last-child .chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy();
expect(chat_content.querySelector('.chat-msg:last-child .chat-msg__author').textContent.trim()).toBe('Candice van der Knijff'); expect(chat_content.querySelector('.chat-msg:last-child .chat-msg__author').textContent.trim()).toBe('Candice van der Knijff');
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
});
})); }));
it("can be sent from a chatbox, and will appear inside it", it("can be sent from a chatbox, and will appear inside it",
...@@ -922,38 +938,45 @@ ...@@ -922,38 +938,45 @@
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); let view, stanza, chat_content;
test_utils.openChatBoxFor(_converse, contact_jid)
let stanza = Strophe.xmlHtmlNode( .then((v) => {
"<message from='"+contact_jid+"'"+ view = v;
" type='chat'"+ stanza = Strophe.xmlHtmlNode(
" to='dummy@localhost/resource'>"+ "<message from='"+contact_jid+"'"+
" <body>Hey\nHave you heard the news?</body>"+ " type='chat'"+
"</message>").firstChild; " to='dummy@localhost/resource'>"+
_converse.connection._dataRecv(test_utils.createRequest(stanza)); " <body>Hey\nHave you heard the news?</body>"+
"</message>").firstChild;
const view = _converse.chatboxviews.get(contact_jid); _converse.connection._dataRecv(test_utils.createRequest(stanza));
const chat_content = view.el.querySelector('.chat-content'); return test_utils.waitUntil(() => view.model.messages.length);
expect(chat_content.querySelector('.chat-msg__text').innerHTML).toBe('Hey<br>Have you heard the news?'); }).then(() => {
const view = _converse.chatboxviews.get(contact_jid);
stanza = Strophe.xmlHtmlNode( chat_content = view.el.querySelector('.chat-content');
"<message from='"+contact_jid+"'"+ expect(chat_content.querySelector('.chat-msg__text').innerHTML).toBe('Hey<br>Have you heard the news?');
" type='chat'"+
" to='dummy@localhost/resource'>"+ stanza = Strophe.xmlHtmlNode(
" <body>Hey\n\n\nHave you heard the news?</body>"+ "<message from='"+contact_jid+"'"+
"</message>").firstChild; " type='chat'"+
_converse.connection._dataRecv(test_utils.createRequest(stanza)); " to='dummy@localhost/resource'>"+
expect(chat_content.querySelector('.message:last-child .chat-msg__text').innerHTML).toBe('Hey<br><br>Have you heard the news?'); " <body>Hey\n\n\nHave you heard the news?</body>"+
"</message>").firstChild;
stanza = Strophe.xmlHtmlNode( _converse.connection._dataRecv(test_utils.createRequest(stanza));
"<message from='"+contact_jid+"'"+ return test_utils.waitUntil(() => view.model.messages.length);
" type='chat'"+ }).then(() => {
" to='dummy@localhost/resource'>"+ expect(chat_content.querySelector('.message:last-child .chat-msg__text').innerHTML).toBe('Hey<br><br>Have you heard the news?');
" <body>Hey\nHave you heard\nthe news?</body>"+ stanza = Strophe.xmlHtmlNode(
"</message>").firstChild; "<message from='"+contact_jid+"'"+
_converse.connection._dataRecv(test_utils.createRequest(stanza)); " type='chat'"+
expect(chat_content.querySelector('.message:last-child .chat-msg__text').innerHTML).toBe('Hey<br>Have you heard<br>the news?'); " to='dummy@localhost/resource'>"+
done(); " <body>Hey\nHave you heard\nthe news?</body>"+
"</message>").firstChild;
_converse.connection._dataRecv(test_utils.createRequest(stanza));
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
expect(chat_content.querySelector('.message:last-child .chat-msg__text').innerHTML).toBe('Hey<br>Have you heard<br>the news?');
done();
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
it("will render images from their URLs", it("will render images from their URLs",
...@@ -1042,19 +1065,19 @@ ...@@ -1042,19 +1065,19 @@
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length, 300) let message, msg, view, sender_jid, chat_content;
.then(function () { const base_time = new Date();
const base_time = new Date(); const ONE_MINUTE_LATER = 60000;
const ONE_MINUTE_LATER = 60000;
test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length, 300)
.then(() => {
jasmine.clock().install(); jasmine.clock().install();
jasmine.clock().mockDate(base_time); jasmine.clock().mockDate(base_time);
var message, msg;
spyOn(_converse, 'log'); spyOn(_converse, 'log');
spyOn(_converse.chatboxes, 'getChatBox').and.callThrough(); spyOn(_converse.chatboxes, 'getChatBox').and.callThrough();
_converse.filter_by_resource = true; _converse.filter_by_resource = true;
var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
_converse.chatboxes.onMessage($msg({ _converse.chatboxes.onMessage($msg({
'from': sender_jid, 'from': sender_jid,
...@@ -1063,9 +1086,10 @@ ...@@ -1063,9 +1086,10 @@
'id': (new Date()).getTime() 'id': (new Date()).getTime()
}).c('body').t('A message').up() }).c('body').t('A message').up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
return test_utils.waitUntil(() => _converse.api.chats.get().length);
}).then(() => {
jasmine.clock().tick(3*ONE_MINUTE_LATER); jasmine.clock().tick(3*ONE_MINUTE_LATER);
view = _converse.chatboxviews.get(sender_jid);
_converse.chatboxes.onMessage($msg({ _converse.chatboxes.onMessage($msg({
'from': sender_jid, 'from': sender_jid,
'to': _converse.connection.jid, 'to': _converse.connection.jid,
...@@ -1073,9 +1097,9 @@ ...@@ -1073,9 +1097,9 @@
'id': (new Date()).getTime() 'id': (new Date()).getTime()
}).c('body').t("Another message 3 minutes later").up() }).c('body').t("Another message 3 minutes later").up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
jasmine.clock().tick(11*ONE_MINUTE_LATER); jasmine.clock().tick(11*ONE_MINUTE_LATER);
_converse.chatboxes.onMessage($msg({ _converse.chatboxes.onMessage($msg({
'from': sender_jid, 'from': sender_jid,
'to': _converse.connection.jid, 'to': _converse.connection.jid,
...@@ -1083,9 +1107,9 @@ ...@@ -1083,9 +1107,9 @@
'id': (new Date()).getTime() 'id': (new Date()).getTime()
}).c('body').t("Another message 14 minutes since we started").up() }).c('body').t("Another message 14 minutes since we started").up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
jasmine.clock().tick(1000); jasmine.clock().tick(1000);
// Insert <composing> message, to also check that // Insert <composing> message, to also check that
// text messages are inserted correctly with // text messages are inserted correctly with
// temporary chat events in the chat contents. // temporary chat events in the chat contents.
...@@ -1097,9 +1121,9 @@ ...@@ -1097,9 +1121,9 @@
'type': 'chat'}) 'type': 'chat'})
.c('composing', {'xmlns': Strophe.NS.CHATSTATES}).up() .c('composing', {'xmlns': Strophe.NS.CHATSTATES}).up()
.tree()); .tree());
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
jasmine.clock().tick(1*ONE_MINUTE_LATER); jasmine.clock().tick(1*ONE_MINUTE_LATER);
_converse.chatboxes.onMessage($msg({ _converse.chatboxes.onMessage($msg({
'from': sender_jid, 'from': sender_jid,
'to': _converse.connection.jid, 'to': _converse.connection.jid,
...@@ -1107,13 +1131,12 @@ ...@@ -1107,13 +1131,12 @@
'id': (new Date()).getTime() 'id': (new Date()).getTime()
}).c('body').t("Another message 1 minute and 1 second since the previous one").up() }).c('body').t("Another message 1 minute and 1 second since the previous one").up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
jasmine.clock().tick(1*ONE_MINUTE_LATER); jasmine.clock().tick(1*ONE_MINUTE_LATER);
var view = _converse.chatboxviews.get(sender_jid);
test_utils.sendMessage(view, "Another message within 10 minutes, but from a different person"); test_utils.sendMessage(view, "Another message within 10 minutes, but from a different person");
var chat_content = view.el.querySelector('.chat-content'); chat_content = view.el.querySelector('.chat-content');
expect(chat_content.querySelectorAll('.message').length).toBe(6); expect(chat_content.querySelectorAll('.message').length).toBe(6);
expect(chat_content.querySelectorAll('.chat-msg').length).toBe(5); expect(chat_content.querySelectorAll('.chat-msg').length).toBe(5);
expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(2)'))).toBe(false); expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(2)'))).toBe(false);
...@@ -1144,7 +1167,8 @@ ...@@ -1144,7 +1167,8 @@
'type': 'chat'}) 'type': 'chat'})
.c('body').t("A delayed message, sent 5 minutes since we started") .c('body').t("A delayed message, sent 5 minutes since we started")
.tree()); .tree());
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
expect(chat_content.querySelectorAll('.message').length).toBe(7); expect(chat_content.querySelectorAll('.message').length).toBe(7);
expect(chat_content.querySelectorAll('.chat-msg').length).toBe(6); expect(chat_content.querySelectorAll('.chat-msg').length).toBe(6);
expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(2)'))).toBe(false); expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(2)'))).toBe(false);
...@@ -1172,7 +1196,9 @@ ...@@ -1172,7 +1196,9 @@
'from': _converse.bare_jid+"/some-other-resource", 'from': _converse.bare_jid+"/some-other-resource",
'type': 'chat'}) 'type': 'chat'})
.c('body').t("A carbon message 4 minutes later") .c('body').t("A carbon message 4 minutes later")
.tree()); .tree());
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
expect(chat_content.querySelectorAll('.message').length).toBe(8); expect(chat_content.querySelectorAll('.message').length).toBe(8);
expect(chat_content.querySelectorAll('.chat-msg').length).toBe(7); expect(chat_content.querySelectorAll('.chat-msg').length).toBe(7);
expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(2)'))).toBe(false); expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(2)'))).toBe(false);
...@@ -1198,7 +1224,7 @@ ...@@ -1198,7 +1224,7 @@
jasmine.clock().uninstall(); jasmine.clock().uninstall();
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
...@@ -1209,17 +1235,16 @@ ...@@ -1209,17 +1235,16 @@
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched'], {},
function (done, _converse) { function (done, _converse) {
let sender_jid, message, chat_content;
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length, 300) test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length, 300)
.then(function () { .then(() => {
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
const message = 'This is a received message'; message = 'This is a received message';
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
// We don't already have an open chatbox for this user // We don't already have an open chatbox for this user
expect(_converse.chatboxes.get(sender_jid)).not.toBeDefined(); expect(_converse.chatboxes.get(sender_jid)).not.toBeDefined();
_converse.chatboxes.onMessage( _converse.chatboxes.onMessage(
$msg({ $msg({
'from': sender_jid, 'from': sender_jid,
...@@ -1229,9 +1254,9 @@ ...@@ -1229,9 +1254,9 @@
}).c('body').t(message).up() }).c('body').t(message).up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree() .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()
); );
return test_utils.waitUntil(() => _converse.api.chats.get().length);
}).then(() => {
expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object)); expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
// Check that the chatbox and its view now exist // Check that the chatbox and its view now exist
const chatbox = _converse.chatboxes.get(sender_jid); const chatbox = _converse.chatboxes.get(sender_jid);
const chatboxview = _converse.chatboxviews.get(sender_jid); const chatboxview = _converse.chatboxviews.get(sender_jid);
...@@ -1245,15 +1270,14 @@ ...@@ -1245,15 +1270,14 @@
expect(msg_obj.get('sender')).toEqual('them'); expect(msg_obj.get('sender')).toEqual('them');
expect(msg_obj.get('is_delayed')).toEqual(false); expect(msg_obj.get('is_delayed')).toEqual(false);
// Now check that the message appears inside the chatbox in the DOM // Now check that the message appears inside the chatbox in the DOM
const chat_content = chatboxview.el.querySelector('.chat-content'); chat_content = chatboxview.el.querySelector('.chat-content');
expect(chat_content.querySelector('.chat-msg .chat-msg__text').textContent).toEqual(message); expect(chat_content.querySelector('.chat-msg .chat-msg__text').textContent).toEqual(message);
expect(chat_content.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy(); expect(chat_content.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy();
return test_utils.waitUntil(() => chatbox.vcard.get('fullname') === mock.cur_names[0]) return test_utils.waitUntil(() => chatbox.vcard.get('fullname') === mock.cur_names[0]);
.then(function () { }).then(() => {
expect(chat_content.querySelector('span.chat-msg__author').textContent.trim()).toBe('Max Frankfurter'); expect(chat_content.querySelector('span.chat-msg__author').textContent.trim()).toBe('Max Frankfurter');
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
});
})); }));
it("can be replaced with a correction", it("can be replaced with a correction",
...@@ -1266,16 +1290,17 @@ ...@@ -1266,16 +1290,17 @@
test_utils.openControlBox(); test_utils.openControlBox();
const message = 'This is a received message'; const message = 'This is a received message';
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
const msg_id = u.getUniqueId();
test_utils.openChatBoxFor(_converse, sender_jid) test_utils.openChatBoxFor(_converse, sender_jid)
.then(() => { .then((view) => {
const msg_id = u.getUniqueId();
_converse.chatboxes.onMessage($msg({ _converse.chatboxes.onMessage($msg({
'from': sender_jid, 'from': sender_jid,
'to': _converse.connection.jid, 'to': _converse.connection.jid,
'type': 'chat', 'type': 'chat',
'id': msg_id, 'id': msg_id,
}).c('body').t('But soft, what light through yonder airlock breaks?').tree()); }).c('body').t('But soft, what light through yonder airlock breaks?').tree());
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
var chatboxview = _converse.chatboxviews.get(sender_jid); var chatboxview = _converse.chatboxviews.get(sender_jid);
expect(chatboxview.el.querySelectorAll('.chat-msg').length).toBe(1); expect(chatboxview.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(chatboxview.el.querySelector('.chat-msg__text').textContent) expect(chatboxview.el.querySelector('.chat-msg__text').textContent)
...@@ -1318,7 +1343,7 @@ ...@@ -1318,7 +1343,7 @@
expect(older_msgs[0].textContent).toBe('But soft, what light through yonder airlock breaks?'); expect(older_msgs[0].textContent).toBe('But soft, what light through yonder airlock breaks?');
expect(older_msgs[1].textContent).toBe('But soft, what light through yonder chimney breaks?'); expect(older_msgs[1].textContent).toBe('But soft, what light through yonder chimney breaks?');
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
}); });
})); }));
...@@ -1343,6 +1368,7 @@ ...@@ -1343,6 +1368,7 @@
'jid': sender_jid 'jid': sender_jid
}); });
}); });
let chatbox, chatboxview;
var message = 'This is a received message from someone not on the roster'; var message = 'This is a received message from someone not on the roster';
var msg = $msg({ var msg = $msg({
from: sender_jid, from: sender_jid,
...@@ -1356,27 +1382,28 @@ ...@@ -1356,27 +1382,28 @@
expect(_converse.chatboxes.get(sender_jid)).not.toBeDefined(); expect(_converse.chatboxes.get(sender_jid)).not.toBeDefined();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object)); return test_utils.waitUntil(() => _converse.api.chats.get().length)
.then(() => {
// Check that the chatbox and its view now exist expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
var chatbox = _converse.chatboxes.get(sender_jid);
var chatboxview = _converse.chatboxviews.get(sender_jid);
expect(chatbox).toBeDefined();
expect(chatboxview).toBeDefined();
var author_el = chatboxview.el.querySelector('.chat-msg__author'); // Check that the chatbox and its view now exist
expect(chatbox.get('fullname') === sender_jid); chatbox = _converse.chatboxes.get(sender_jid);
expect( _.includes(author_el.textContent.trim(), 'max.frankfurter@localhost')).toBeTruthy(); chatboxview = _converse.chatboxviews.get(sender_jid);
expect(chatbox).toBeDefined();
expect(chatboxview).toBeDefined();
test_utils.waitUntil(function () { return vcard_fetched; }, 100) const author_el = chatboxview.el.querySelector('.chat-msg__author');
.then(function () { expect(chatbox.get('fullname') === sender_jid);
expect( _.includes(author_el.textContent.trim(), 'Max Frankfurter')).toBeTruthy();
return test_utils.waitUntil(function () { return vcard_fetched; }, 100);
}).then(() => {
expect(_converse.api.vcard.get).toHaveBeenCalled(); expect(_converse.api.vcard.get).toHaveBeenCalled();
return test_utils.waitUntil(() => chatbox.vcard.get('fullname') === mock.cur_names[0]) return test_utils.waitUntil(() => chatbox.vcard.get('fullname') === mock.cur_names[0])
}).then(function () { }).then(() => {
var author_el = chatboxview.el.querySelector('.chat-msg__author'); var author_el = chatboxview.el.querySelector('.chat-msg__author');
expect( _.includes(author_el.textContent.trim(), 'Max Frankfurter')).toBeTruthy(); expect( _.includes(author_el.textContent.trim(), 'Max Frankfurter')).toBeTruthy();
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
}); });
...@@ -1391,6 +1418,7 @@ ...@@ -1391,6 +1418,7 @@
_converse.allow_non_roster_messaging = false; _converse.allow_non_roster_messaging = false;
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
let chatboxview;
var message = 'This is a received message from someone not on the roster'; var message = 'This is a received message from someone not on the roster';
var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
var msg = $msg({ var msg = $msg({
...@@ -1406,34 +1434,36 @@ ...@@ -1406,34 +1434,36 @@
var chatbox = _converse.chatboxes.get(sender_jid); var chatbox = _converse.chatboxes.get(sender_jid);
expect(chatbox).not.toBeDefined(); expect(chatbox).not.toBeDefined();
// onMessage is a handler for received XMPP messages
_converse.chatboxes.onMessage(msg);
expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
// onMessage is a handler for received XMPP messages // onMessage is a handler for received XMPP messages
_converse.allow_non_roster_messaging =true;
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object)); test_utils.waitUntil(() => _converse.api.chats.get().length)
.then(() => {
// Check that the chatbox and its view now exist chatboxview = _converse.chatboxviews.get(sender_jid);
chatbox = _converse.chatboxes.get(sender_jid); expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
var chatboxview = _converse.chatboxviews.get(sender_jid); // onMessage is a handler for received XMPP messages
expect(chatbox).toBeDefined(); _converse.allow_non_roster_messaging =true;
expect(chatboxview).toBeDefined(); _converse.chatboxes.onMessage(msg);
// Check that the message was received and check the message parameters return test_utils.waitUntil(() => chatboxview.model.messages.length);
expect(chatbox.messages.length).toEqual(1); }).then(() => {
var msg_obj = chatbox.messages.models[0]; expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
expect(msg_obj.get('message')).toEqual(message); // Check that the chatbox and its view now exist
expect(msg_obj.get('fullname')).toEqual(undefined); chatbox = _converse.chatboxes.get(sender_jid);
expect(msg_obj.get('sender')).toEqual('them'); expect(chatbox).toBeDefined();
expect(msg_obj.get('is_delayed')).toEqual(false); expect(chatboxview).toBeDefined();
// Now check that the message appears inside the chatbox in the DOM // Check that the message was received and check the message parameters
var chat_content = chatboxview.el.querySelector('.chat-content'); expect(chatbox.messages.length).toEqual(1);
expect(chat_content.querySelector('.chat-msg .chat-msg__text').textContent).toEqual(message); var msg_obj = chatbox.messages.models[0];
expect(chat_content.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy(); expect(msg_obj.get('message')).toEqual(message);
expect(chat_content.querySelector('span.chat-msg__author').textContent.trim()).toBe('max.frankfurter@localhost'); expect(msg_obj.get('fullname')).toEqual(undefined);
done(); expect(msg_obj.get('sender')).toEqual('them');
expect(msg_obj.get('is_delayed')).toEqual(false);
// Now check that the message appears inside the chatbox in the DOM
var chat_content = chatboxview.el.querySelector('.chat-content');
expect(chat_content.querySelector('.chat-msg .chat-msg__text').textContent).toEqual(message);
expect(chat_content.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy();
expect(chat_content.querySelector('span.chat-msg__author').textContent.trim()).toBe('Max Frankfurter');
done();
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
}); });
...@@ -1464,13 +1494,15 @@ ...@@ -1464,13 +1494,15 @@
* <active xmlns="http://jabber.org/protocol/chatstates"/> * <active xmlns="http://jabber.org/protocol/chatstates"/>
* </message> * </message>
*/ */
let $chat_content, view;
const error_txt = 'Server-to-server connection failed: Connecting failed: connection timeout';
var sender_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost'; var sender_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost';
var fullname = _converse.xmppstatus.get('fullname'); var fullname = _converse.xmppstatus.get('fullname');
fullname = _.isEmpty(fullname)? _converse.bare_jid: fullname; fullname = _.isEmpty(fullname)? _converse.bare_jid: fullname;
_converse.api.chats.open(sender_jid) _converse.api.chats.open(sender_jid)
.then(() => { .then(() => {
var msg_text = 'This message will not be sent, due to an error'; var msg_text = 'This message will not be sent, due to an error';
var view = _converse.chatboxviews.get(sender_jid); view = _converse.chatboxviews.get(sender_jid);
var message = view.model.messages.create({ var message = view.model.messages.create({
'msgid': '82bc02ce-9651-4336-baf0-fa04762ed8d2', 'msgid': '82bc02ce-9651-4336-baf0-fa04762ed8d2',
'fullname': fullname, 'fullname': fullname,
...@@ -1479,7 +1511,7 @@ ...@@ -1479,7 +1511,7 @@
'message': msg_text 'message': msg_text
}); });
view.model.sendMessage(message); view.model.sendMessage(message);
var $chat_content = $(view.el).find('.chat-content'); $chat_content = $(view.el).find('.chat-content');
var msg_txt = $chat_content.find('.chat-msg:last').find('.chat-msg__text').text(); var msg_txt = $chat_content.find('.chat-msg:last').find('.chat-msg__text').text();
expect(msg_txt).toEqual(msg_text); expect(msg_txt).toEqual(msg_text);
...@@ -1509,8 +1541,7 @@ ...@@ -1509,8 +1541,7 @@
* </error> * </error>
* </message> * </message>
*/ */
var error_txt = 'Server-to-server connection failed: Connecting failed: connection timeout'; const stanza = $msg({
var stanza = $msg({
'to': _converse.connection.jid, 'to': _converse.connection.jid,
'type':'error', 'type':'error',
'id':'82bc02ce-9651-4336-baf0-fa04762ed8d2', 'id':'82bc02ce-9651-4336-baf0-fa04762ed8d2',
...@@ -1521,9 +1552,10 @@ ...@@ -1521,9 +1552,10 @@
.c('text', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" }) .c('text', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" })
.t('Server-to-server connection failed: Connecting failed: connection timeout'); .t('Server-to-server connection failed: Connecting failed: connection timeout');
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
expect($chat_content.find('.chat-error').text()).toEqual(error_txt); expect($chat_content.find('.chat-error').text()).toEqual(error_txt);
const stanza = $msg({
stanza = $msg({
'to': _converse.connection.jid, 'to': _converse.connection.jid,
'type':'error', 'type':'error',
'id':'some-other-unused-id', 'id':'some-other-unused-id',
...@@ -1534,11 +1566,13 @@ ...@@ -1534,11 +1566,13 @@
.c('text', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" }) .c('text', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" })
.t('Server-to-server connection failed: Connecting failed: connection timeout'); .t('Server-to-server connection failed: Connecting failed: connection timeout');
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
return test_utils.waitUntil(() => view.model.messages.length > 1);
}).then(() => {
expect($chat_content.find('.chat-error').length).toEqual(2); expect($chat_content.find('.chat-error').length).toEqual(2);
// If the last message is already an error message, // If the last message is already an error message,
// then we don't render it another time. // then we don't render it another time.
stanza = $msg({ const stanza = $msg({
'to': _converse.connection.jid, 'to': _converse.connection.jid,
'type':'error', 'type':'error',
'id':'another-unused-id', 'id':'another-unused-id',
...@@ -1549,10 +1583,11 @@ ...@@ -1549,10 +1583,11 @@
.c('text', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" }) .c('text', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" })
.t('Server-to-server connection failed: Connecting failed: connection timeout'); .t('Server-to-server connection failed: Connecting failed: connection timeout');
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
return test_utils.waitUntil(() => view.model.messages.length > 2);
}).then(() => {
expect($chat_content.find('.chat-error').length).toEqual(2); expect($chat_content.find('.chat-error').length).toEqual(2);
// A different error message will however render // A different error message will however render
stanza = $msg({ const stanza = $msg({
'to': _converse.connection.jid, 'to': _converse.connection.jid,
'type':'error', 'type':'error',
'id':'another-id', 'id':'another-id',
...@@ -1563,6 +1598,8 @@ ...@@ -1563,6 +1598,8 @@
.c('text', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" }) .c('text', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" })
.t('Something else went wrong as well'); .t('Something else went wrong as well');
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
return test_utils.waitUntil(() => view.model.messages.length > 3);
}).then(() => {
expect($chat_content.find('.chat-error').length).toEqual(3); expect($chat_content.find('.chat-error').length).toEqual(3);
done(); done();
}); });
...@@ -1610,7 +1647,8 @@ ...@@ -1610,7 +1647,8 @@
id: (new Date()).getTime() id: (new Date()).getTime()
}).c('body').t(message).up() }).c('body').t(message).up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
return test_utils.waitUntil(() => chatboxview.model.messages.length > 20);
}).then(() => {
// Now check that the message appears inside the chatbox in the DOM // Now check that the message appears inside the chatbox in the DOM
const $chat_content = $(chatboxview.el).find('.chat-content'); const $chat_content = $(chatboxview.el).find('.chat-content');
const msg_txt = $chat_content.find('.chat-msg:last').find('.chat-msg__text').text(); const msg_txt = $chat_content.find('.chat-msg:last').find('.chat-msg__text').text();
...@@ -1623,7 +1661,8 @@ ...@@ -1623,7 +1661,8 @@
// Scroll down again // Scroll down again
chatboxview.content.scrollTop = chatboxview.content.scrollHeight; chatboxview.content.scrollTop = chatboxview.content.scrollHeight;
return test_utils.waitUntil(() => !u.isVisible(chatboxview.el.querySelector('.new-msgs-indicator')), 900); return test_utils.waitUntil(() => !u.isVisible(chatboxview.el.querySelector('.new-msgs-indicator')), 900);
}).then(done); }).then(done)
.catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
it("is ignored if it's intended for a different resource and filter_by_resource is set to true", it("is ignored if it's intended for a different resource and filter_by_resource is set to true",
...@@ -1634,12 +1673,10 @@ ...@@ -1634,12 +1673,10 @@
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.waitUntil(function () { let message, sender_jid, msg, view;
return $(_converse.rosterview.el).find('.roster-group').length; test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length)
}, 300) .then(() => {
.then(function () {
// Send a message from a different resource // Send a message from a different resource
var message, sender_jid, msg;
spyOn(_converse, 'log'); spyOn(_converse, 'log');
spyOn(_converse.chatboxes, 'getChatBox').and.callThrough(); spyOn(_converse.chatboxes, 'getChatBox').and.callThrough();
_converse.filter_by_resource = true; _converse.filter_by_resource = true;
...@@ -1652,7 +1689,8 @@ ...@@ -1652,7 +1689,8 @@
}).c('body').t("This message will not be shown").up() }).c('body').t("This message will not be shown").up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
return test_utils.waitUntil(() => _converse.api.chats.get().length);
}).then(() => {
expect(_converse.log).toHaveBeenCalledWith( expect(_converse.log).toHaveBeenCalledWith(
"onMessage: Ignoring incoming message intended for a different resource: dummy@localhost/some-other-resource", "onMessage: Ignoring incoming message intended for a different resource: dummy@localhost/some-other-resource",
Strophe.LogLevel.INFO); Strophe.LogLevel.INFO);
...@@ -1668,14 +1706,16 @@ ...@@ -1668,14 +1706,16 @@
}).c('body').t(message).up() }).c('body').t(message).up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
view = _converse.chatboxviews.get(sender_jid);
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
expect(_converse.chatboxes.getChatBox).toHaveBeenCalled(); expect(_converse.chatboxes.getChatBox).toHaveBeenCalled();
var chatboxview = _converse.chatboxviews.get(sender_jid); var chat_content = $(view.el).find('.chat-content:last')[0];
var $chat_content = $(chatboxview.el).find('.chat-content:last'); var msg_txt = chat_content.querySelector('.chat-msg .chat-msg__text').textContent;
var msg_txt = $chat_content.find('.chat-msg').find('.chat-msg__text').text();
expect(msg_txt).toEqual(message); expect(msg_txt).toEqual(message);
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
}); });
...@@ -1690,7 +1730,7 @@ ...@@ -1690,7 +1730,7 @@
test_utils.createContacts(_converse, 'current', 1); test_utils.createContacts(_converse, 'current', 1);
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
let view; let view, msg, media;
test_utils.openChatBoxFor(_converse, contact_jid) test_utils.openChatBoxFor(_converse, contact_jid)
.then(() => { .then(() => {
view = _converse.chatboxviews.get(contact_jid); view = _converse.chatboxviews.get(contact_jid);
...@@ -1707,9 +1747,9 @@ ...@@ -1707,9 +1747,9 @@
return test_utils.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-msg audio').length, 1000); return test_utils.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-msg audio').length, 1000);
}).then(() => { }).then(() => {
let msg = view.el.querySelector('.chat-msg .chat-msg__text'); msg = view.el.querySelector('.chat-msg .chat-msg__text');
expect(msg.outerHTML).toEqual('<div class="chat-msg__text">Have you heard this funny audio?</div>'); expect(msg.outerHTML).toEqual('<div class="chat-msg__text">Have you heard this funny audio?</div>');
let media = view.el.querySelector('.chat-msg .chat-msg__media'); media = view.el.querySelector('.chat-msg .chat-msg__media');
expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual( expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual(
'<!-- src/templates/audio.html -->'+ '<!-- src/templates/audio.html -->'+
'<audio controls=""><source src="http://localhost/audio.mp3" type="audio/mpeg"></audio>'+ '<audio controls=""><source src="http://localhost/audio.mp3" type="audio/mpeg"></audio>'+
...@@ -1724,7 +1764,8 @@ ...@@ -1724,7 +1764,8 @@
" <x xmlns='jabber:x:oob'><url>http://localhost/audio.mp3</url></x>"+ " <x xmlns='jabber:x:oob'><url>http://localhost/audio.mp3</url></x>"+
"</message>").firstChild; "</message>").firstChild;
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
msg = view.el.querySelector('.chat-msg:last-child .chat-msg__text'); msg = view.el.querySelector('.chat-msg:last-child .chat-msg__text');
expect(msg.innerHTML).toEqual('<!-- message gets added here via renderMessage -->'); // Emtpy expect(msg.innerHTML).toEqual('<!-- message gets added here via renderMessage -->'); // Emtpy
media = view.el.querySelector('.chat-msg:last-child .chat-msg__media'); media = view.el.querySelector('.chat-msg:last-child .chat-msg__media');
...@@ -1733,7 +1774,7 @@ ...@@ -1733,7 +1774,7 @@
'<audio controls=""><source src="http://localhost/audio.mp3" type="audio/mpeg"></audio>'+ '<audio controls=""><source src="http://localhost/audio.mp3" type="audio/mpeg"></audio>'+
'<a target="_blank" rel="noopener" href="http://localhost/audio.mp3">Download audio file</a>'); '<a target="_blank" rel="noopener" href="http://localhost/audio.mp3">Download audio file</a>');
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
it("will render video from oob mp4 URLs", it("will render video from oob mp4 URLs",
...@@ -1744,9 +1785,10 @@ ...@@ -1744,9 +1785,10 @@
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
let view, msg, media;
test_utils.openChatBoxFor(_converse, contact_jid) test_utils.openChatBoxFor(_converse, contact_jid)
.then(() => { .then(() => {
const view = _converse.chatboxviews.get(contact_jid); view = _converse.chatboxviews.get(contact_jid);
spyOn(view.model, 'sendMessage').and.callThrough(); spyOn(view.model, 'sendMessage').and.callThrough();
const stanza = Strophe.xmlHtmlNode( const stanza = Strophe.xmlHtmlNode(
...@@ -1758,35 +1800,36 @@ ...@@ -1758,35 +1800,36 @@
"</message>").firstChild; "</message>").firstChild;
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
test_utils.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-msg video').length, 2000).then(function () { return test_utils.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-msg video').length, 2000)
let msg = view.el.querySelector('.chat-msg .chat-msg__text'); }).then(() => {
expect(msg.outerHTML).toEqual('<div class="chat-msg__text">Have you seen this funny video?</div>'); msg = view.el.querySelector('.chat-msg .chat-msg__text');
let media = view.el.querySelector('.chat-msg .chat-msg__media'); expect(msg.outerHTML).toEqual('<div class="chat-msg__text">Have you seen this funny video?</div>');
expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual( media = view.el.querySelector('.chat-msg .chat-msg__media');
'<!-- src/templates/video.html -->'+ expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual(
'<video controls=""><source src="http://localhost/video.mp4" type="video/mp4"></video>'+ '<!-- src/templates/video.html -->'+
'<a target="_blank" rel="noopener" href="http://localhost/video.mp4">Download video file</a>'); '<video controls=""><source src="http://localhost/video.mp4" type="video/mp4"></video>'+
'<a target="_blank" rel="noopener" href="http://localhost/video.mp4">Download video file</a>');
// If the <url> and <body> contents is the same, don't duplicate.
const stanza = Strophe.xmlHtmlNode(
"<message from='"+contact_jid+"'"+
" type='chat'"+
" to='dummy@localhost/resource'>"+
" <body>http://localhost/video.mp4</body>"+
" <x xmlns='jabber:x:oob'><url>http://localhost/video.mp4</url></x>"+
"</message>").firstChild;
_converse.connection._dataRecv(test_utils.createRequest(stanza));
msg = view.el.querySelector('.chat-msg:last-child .chat-msg__text'); // If the <url> and <body> contents is the same, don't duplicate.
expect(msg.innerHTML).toEqual('<!-- message gets added here via renderMessage -->'); // Emtpy const stanza = Strophe.xmlHtmlNode(
media = view.el.querySelector('.chat-msg:last-child .chat-msg__media'); "<message from='"+contact_jid+"'"+
expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual( " type='chat'"+
'<!-- src/templates/video.html -->'+ " to='dummy@localhost/resource'>"+
'<video controls=""><source src="http://localhost/video.mp4" type="video/mp4"></video>'+ " <body>http://localhost/video.mp4</body>"+
'<a target="_blank" rel="noopener" href="http://localhost/video.mp4">Download video file</a>'); " <x xmlns='jabber:x:oob'><url>http://localhost/video.mp4</url></x>"+
done(); "</message>").firstChild;
}); _converse.connection._dataRecv(test_utils.createRequest(stanza));
}); return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
msg = view.el.querySelector('.chat-msg:last-child .chat-msg__text');
expect(msg.innerHTML).toEqual('<!-- message gets added here via renderMessage -->'); // Emtpy
media = view.el.querySelector('.chat-msg:last-child .chat-msg__media');
expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual(
'<!-- src/templates/video.html -->'+
'<video controls=""><source src="http://localhost/video.mp4" type="video/mp4"></video>'+
'<a target="_blank" rel="noopener" href="http://localhost/video.mp4">Download video file</a>');
done();
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
it("will render download links for files from oob URLs", it("will render download links for files from oob URLs",
...@@ -1872,10 +1915,12 @@ ...@@ -1872,10 +1915,12 @@
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
let view;
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () { test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy')
const view = _converse.chatboxviews.get('lounge@localhost'); .then(() => {
if (!$(view.el).find('.chat-area').length) { view.renderChatArea(); } view = _converse.chatboxviews.get('lounge@localhost');
if (!view.el.querySelectorAll('.chat-area').length) { view.renderChatArea(); }
const message = 'dummy: Your attention is required'; const message = 'dummy: Your attention is required';
const nick = mock.chatroom_names[0], const nick = mock.chatroom_names[0],
msg = $msg({ msg = $msg({
...@@ -1885,6 +1930,8 @@ ...@@ -1885,6 +1930,8 @@
type: 'groupchat' type: 'groupchat'
}).c('body').t(message).tree(); }).c('body').t(message).tree();
view.model.onMessage(msg); view.model.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
expect($(view.el).find('.chat-msg').hasClass('mentioned')).toBeTruthy(); expect($(view.el).find('.chat-msg').hasClass('mentioned')).toBeTruthy();
done(); done();
}).catch(_.partial(console.error, _)); }).catch(_.partial(console.error, _));
...@@ -1896,9 +1943,10 @@ ...@@ -1896,9 +1943,10 @@
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched'], {},
function (done, _converse) { function (done, _converse) {
let view;
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () { test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () {
const view = _converse.chatboxviews.get('lounge@localhost'); view = _converse.chatboxviews.get('lounge@localhost');
const msg = $msg({ const msg = $msg({
from: 'lounge@localhost/dummy', from: 'lounge@localhost/dummy',
id: (new Date()).getTime(), id: (new Date()).getTime(),
...@@ -1906,9 +1954,11 @@ ...@@ -1906,9 +1954,11 @@
type: 'groupchat' type: 'groupchat'
}).c('body').t('I wrote this message!').tree(); }).c('body').t('I wrote this message!').tree();
view.model.onMessage(msg); view.model.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
expect(view.model.messages.last().get('sender')).toBe('me'); expect(view.model.messages.last().get('sender')).toBe('me');
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
it("can be replaced with a correction", it("can be replaced with a correction",
...@@ -1942,7 +1992,8 @@ ...@@ -1942,7 +1992,8 @@
'type': 'groupchat', 'type': 'groupchat',
'id': msg_id, 'id': msg_id,
}).c('body').t('But soft, what light through yonder airlock breaks?').tree()); }).c('body').t('But soft, what light through yonder airlock breaks?').tree());
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1); expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(view.el.querySelector('.chat-msg__text').textContent) expect(view.el.querySelector('.chat-msg__text').textContent)
.toBe('But soft, what light through yonder airlock breaks?'); .toBe('But soft, what light through yonder airlock breaks?');
...@@ -1954,7 +2005,6 @@ ...@@ -1954,7 +2005,6 @@
'id': u.getUniqueId(), 'id': u.getUniqueId(),
}).c('body').t('But soft, what light through yonder chimney breaks?').up() }).c('body').t('But soft, what light through yonder chimney breaks?').up()
.c('replace', {'id': msg_id, 'xmlns': 'urn:xmpp:message-correct:0'}).tree()); .c('replace', {'id': msg_id, 'xmlns': 'urn:xmpp:message-correct:0'}).tree());
return test_utils.waitUntil(() => view.el.querySelector('.chat-msg__text').textContent === return test_utils.waitUntil(() => view.el.querySelector('.chat-msg__text').textContent ===
'But soft, what light through yonder chimney breaks?'); 'But soft, what light through yonder chimney breaks?');
}).then(() => { }).then(() => {
...@@ -1992,14 +2042,14 @@ ...@@ -1992,14 +2042,14 @@
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched'], {},
function (done, _converse) { function (done, _converse) {
let msg_id, view; let msg_id, view, textarea;
test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy') test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy')
.then(() => { .then(() => {
const room_jid = 'lounge@localhost'; const room_jid = 'lounge@localhost';
const room = _converse.api.rooms.get(room_jid); const room = _converse.api.rooms.get(room_jid);
view = _converse.chatboxviews.get(room_jid); view = _converse.chatboxviews.get(room_jid);
const textarea = view.el.querySelector('textarea.chat-textarea'); textarea = view.el.querySelector('textarea.chat-textarea');
expect(textarea.value).toBe(''); expect(textarea.value).toBe('');
view.keyPressed({ view.keyPressed({
target: textarea, target: textarea,
...@@ -2064,6 +2114,8 @@ ...@@ -2064,6 +2114,8 @@
'to': 'dummy@localhost', 'to': 'dummy@localhost',
'type': 'groupchat' 'type': 'groupchat'
}).c('body').t('Hello world').tree()); }).c('body').t('Hello world').tree());
return test_utils.waitUntil(() => view.model.messages.length > 1);
}).then(() => {
expect(view.el.querySelectorAll('.chat-msg').length).toBe(2); expect(view.el.querySelectorAll('.chat-msg').length).toBe(2);
// Test that pressing the down arrow cancels message correction // Test that pressing the down arrow cancels message correction
...@@ -2096,9 +2148,10 @@ ...@@ -2096,9 +2148,10 @@
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched'], {},
function (done, _converse) { function (done, _converse) {
let view;
test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'tom') test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'tom')
.then(() => { .then(() => {
const view = _converse.chatboxviews.get('lounge@localhost'); view = _converse.chatboxviews.get('lounge@localhost');
['z3r0', 'mr.robot', 'gibson', 'sw0rdf1sh'].forEach((nick) => { ['z3r0', 'mr.robot', 'gibson', 'sw0rdf1sh'].forEach((nick) => {
_converse.connection._dataRecv(test_utils.createRequest( _converse.connection._dataRecv(test_utils.createRequest(
$pres({ $pres({
...@@ -2113,7 +2166,6 @@ ...@@ -2113,7 +2166,6 @@
})) }))
); );
}); });
const msg = $msg({ const msg = $msg({
from: 'lounge@localhost/gibson', from: 'lounge@localhost/gibson',
id: (new Date()).getTime(), id: (new Date()).getTime(),
...@@ -2124,7 +2176,8 @@ ...@@ -2124,7 +2176,8 @@
.c('reference', {'xmlns':'urn:xmpp:reference:0', 'begin':'11', 'end':'14', 'type':'mention', 'uri':'xmpp:dummy@localhost'}).up() .c('reference', {'xmlns':'urn:xmpp:reference:0', 'begin':'11', 'end':'14', 'type':'mention', 'uri':'xmpp:dummy@localhost'}).up()
.c('reference', {'xmlns':'urn:xmpp:reference:0', 'begin':'15', 'end':'23', 'type':'mention', 'uri':'xmpp:mr.robot@localhost'}).nodeTree; .c('reference', {'xmlns':'urn:xmpp:reference:0', 'begin':'15', 'end':'23', 'type':'mention', 'uri':'xmpp:mr.robot@localhost'}).nodeTree;
view.model.onMessage(msg); view.model.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length);
}).then(() => {
expect(view.el.querySelectorAll('.chat-msg__text').length).toBe(1); expect(view.el.querySelectorAll('.chat-msg__text').length).toBe(1);
expect(view.el.querySelector('.chat-msg__text').outerHTML).toBe( expect(view.el.querySelector('.chat-msg__text').outerHTML).toBe(
'<div class="chat-msg__text">hello <span class="mention">z3r0</span> '+ '<div class="chat-msg__text">hello <span class="mention">z3r0</span> '+
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
const _ = converse.env._; const _ = converse.env._;
const $msg = converse.env.$msg; const $msg = converse.env.$msg;
const u = converse.env.utils; const u = converse.env.utils;
const Strophe = converse.env.Strophe;
describe("The Minimized Chats Widget", function () { describe("The Minimized Chats Widget", function () {
...@@ -43,7 +44,7 @@ ...@@ -43,7 +44,7 @@
expect(_converse.minimized_chats.keys().length).toBe(2); expect(_converse.minimized_chats.keys().length).toBe(2);
expect(_.includes(_converse.minimized_chats.keys(), contact_jid)).toBeTruthy(); expect(_.includes(_converse.minimized_chats.keys(), contact_jid)).toBeTruthy();
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
it("can be toggled to hide or show minimized chats", it("can be toggled to hide or show minimized chats",
...@@ -74,7 +75,7 @@ ...@@ -74,7 +75,7 @@
}).then(() => { }).then(() => {
expect(_converse.minimized_chats.toggleview.model.get('collapsed')).toBeTruthy(); expect(_converse.minimized_chats.toggleview.model.get('collapsed')).toBeTruthy();
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
it("shows the number messages received to minimized chats", it("shows the number messages received to minimized chats",
...@@ -99,7 +100,7 @@ ...@@ -99,7 +100,7 @@
contact_jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost'; contact_jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid);
} }
return test_utils.waitUntil(() => _converse.chatboxes.length == 4).then(() => { test_utils.waitUntil(() => _converse.chatboxes.length == 4).then(() => {
for (i=0; i<3; i++) { for (i=0; i<3; i++) {
chatview = _converse.chatboxviews.get(contact_jid); chatview = _converse.chatboxviews.get(contact_jid);
chatview.model.set({'minimized': true}); chatview.model.set({'minimized': true});
...@@ -111,9 +112,11 @@ ...@@ -111,9 +112,11 @@
}).c('body').t('This message is sent to a minimized chatbox').up() }).c('body').t('This message is sent to a minimized chatbox').up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
expect($(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count')).is(':visible')).toBeTruthy();
expect($(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count')).text()).toBe((i+1).toString());
} }
return test_utils.waitUntil(() => chatview.model.messages.length);
}).then(() => {
expect(u.isVisible(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count'))).toBeTruthy();
expect(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count').textContent).toBe((3).toString());
// Chat state notifications don't increment the unread messages counter // Chat state notifications don't increment the unread messages counter
// <composing> state // <composing> state
_converse.chatboxes.onMessage($msg({ _converse.chatboxes.onMessage($msg({
...@@ -122,7 +125,7 @@ ...@@ -122,7 +125,7 @@
type: 'chat', type: 'chat',
id: (new Date()).getTime() id: (new Date()).getTime()
}).c('composing', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()); }).c('composing', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
expect($(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count')).text()).toBe((i).toString()); expect(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count').textContent).toBe((i).toString());
// <paused> state // <paused> state
_converse.chatboxes.onMessage($msg({ _converse.chatboxes.onMessage($msg({
...@@ -131,7 +134,7 @@ ...@@ -131,7 +134,7 @@
type: 'chat', type: 'chat',
id: (new Date()).getTime() id: (new Date()).getTime()
}).c('paused', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()); }).c('paused', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
expect($(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count')).text()).toBe((i).toString()); expect(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count').textContent).toBe((i).toString());
// <gone> state // <gone> state
_converse.chatboxes.onMessage($msg({ _converse.chatboxes.onMessage($msg({
...@@ -140,7 +143,7 @@ ...@@ -140,7 +143,7 @@
type: 'chat', type: 'chat',
id: (new Date()).getTime() id: (new Date()).getTime()
}).c('gone', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()); }).c('gone', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
expect($(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count')).text()).toBe((i).toString()); expect(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count').textContent).toBe((i).toString());
// <inactive> state // <inactive> state
_converse.chatboxes.onMessage($msg({ _converse.chatboxes.onMessage($msg({
...@@ -149,9 +152,9 @@ ...@@ -149,9 +152,9 @@
type: 'chat', type: 'chat',
id: (new Date()).getTime() id: (new Date()).getTime()
}).c('inactive', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()); }).c('inactive', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
expect($(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count')).text()).toBe((i).toString()); expect(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count').textContent).toBe((i).toString());
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
it("shows the number messages received to minimized groupchats", it("shows the number messages received to minimized groupchats",
...@@ -159,7 +162,7 @@ ...@@ -159,7 +162,7 @@
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched'], {},
function (done, _converse) { function (done, _converse) {
var room_jid = 'kitchen@conference.shakespeare.lit'; const room_jid = 'kitchen@conference.shakespeare.lit';
test_utils.openAndEnterChatRoom( test_utils.openAndEnterChatRoom(
_converse, 'kitchen', 'conference.shakespeare.lit', 'fires').then(function () { _converse, 'kitchen', 'conference.shakespeare.lit', 'fires').then(function () {
var view = _converse.chatboxviews.get(room_jid); var view = _converse.chatboxviews.get(room_jid);
...@@ -175,11 +178,12 @@ ...@@ -175,11 +178,12 @@
type: 'groupchat' type: 'groupchat'
}).c('body').t(message).tree(); }).c('body').t(message).tree();
view.model.onMessage(msg); view.model.onMessage(msg);
return test_utils.waitUntil(() => view.model.messages.length);
expect($(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count')).is(':visible')).toBeTruthy(); }).then(() => {
expect($(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count')).text()).toBe('1'); expect(u.isVisible(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count'))).toBeTruthy();
expect(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count').textContent).toBe('1');
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
})); }));
}); });
})); }));
...@@ -229,14 +229,16 @@ ...@@ -229,14 +229,16 @@
// have to mock stanza traffic. // have to mock stanza traffic.
}, function (done, _converse) { }, function (done, _converse) {
let view, nick;
const room_jid = 'kitchen@conference.shakespeare.lit';
test_utils.waitUntil(() => !_.isUndefined(_converse.rooms_list_view), 500) test_utils.waitUntil(() => !_.isUndefined(_converse.rooms_list_view), 500)
.then(() => test_utils.openAndEnterChatRoom(_converse, 'kitchen', 'conference.shakespeare.lit', 'romeo')) .then(() => test_utils.openAndEnterChatRoom(_converse, 'kitchen', 'conference.shakespeare.lit', 'romeo'))
.then(() => { .then(() => {
const room_jid = 'kitchen@conference.shakespeare.lit'; view = _converse.chatboxviews.get(room_jid);
const view = _converse.chatboxviews.get(room_jid);
view.model.set({'minimized': true}); view.model.set({'minimized': true});
const contact_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost';
const nick = mock.chatroom_names[0]; nick = mock.chatroom_names[0];
view.model.onMessage( view.model.onMessage(
$msg({ $msg({
from: room_jid+'/'+nick, from: room_jid+'/'+nick,
...@@ -260,9 +262,11 @@ ...@@ -260,9 +262,11 @@
type: 'groupchat' type: 'groupchat'
}).c('body').t('romeo: Your attention is required').tree() }).c('body').t('romeo: Your attention is required').tree()
); );
var indicator_el = _converse.rooms_list_view.el.querySelector(".msgs-indicator"); return test_utils.waitUntil(() => _converse.rooms_list_view.el.querySelectorAll(".msgs-indicator"));
}).then(() => {
spyOn(view.model, 'incrementUnreadMsgCounter').and.callThrough();
const indicator_el = _converse.rooms_list_view.el.querySelector(".msgs-indicator");
expect(indicator_el.textContent).toBe('1'); expect(indicator_el.textContent).toBe('1');
view.model.onMessage( view.model.onMessage(
$msg({ $msg({
from: room_jid+'/'+nick, from: room_jid+'/'+nick,
...@@ -271,14 +275,16 @@ ...@@ -271,14 +275,16 @@
type: 'groupchat' type: 'groupchat'
}).c('body').t('romeo: and another thing...').tree() }).c('body').t('romeo: and another thing...').tree()
); );
indicator_el = _converse.rooms_list_view.el.querySelector(".msgs-indicator"); return test_utils.waitUntil(() => view.model.incrementUnreadMsgCounter.calls.count());
}).then(() => {
let indicator_el = _converse.rooms_list_view.el.querySelector(".msgs-indicator");
expect(indicator_el.textContent).toBe('2'); expect(indicator_el.textContent).toBe('2');
// When the chat gets maximized again, the unread indicators are removed // When the chat gets maximized again, the unread indicators are removed
view.model.set({'minimized': false}); view.model.set({'minimized': false});
indicator_el = _converse.rooms_list_view.el.querySelector(".msgs-indicator"); indicator_el = _converse.rooms_list_view.el.querySelector(".msgs-indicator");
expect(_.isNull(indicator_el)); expect(_.isNull(indicator_el));
room_el = _converse.rooms_list_view.el.querySelector(".available-chatroom"); const room_el = _converse.rooms_list_view.el.querySelector(".available-chatroom");
expect(_.includes(room_el.classList, 'unread-msgs')).toBeFalsy(); expect(_.includes(room_el.classList, 'unread-msgs')).toBeFalsy();
done(); done();
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
......
...@@ -497,8 +497,6 @@ ...@@ -497,8 +497,6 @@
stanza.getElementsByTagName(_converse.ACTIVE).length && _converse.ACTIVE || stanza.getElementsByTagName(_converse.ACTIVE).length && _converse.ACTIVE ||
stanza.getElementsByTagName(_converse.GONE).length && _converse.GONE; stanza.getElementsByTagName(_converse.GONE).length && _converse.GONE;
const attrs = { const attrs = {
'chat_state': chat_state, 'chat_state': chat_state,
'is_archived': !_.isNil(archive), 'is_archived': !_.isNil(archive),
...@@ -552,7 +550,7 @@ ...@@ -552,7 +550,7 @@
} else { } else {
resolve(this.messages.create(attrs)); resolve(this.messages.create(attrs));
} }
}); }).catch(e => reject(e))
}); });
}, },
...@@ -729,8 +727,11 @@ ...@@ -729,8 +727,11 @@
if (chatbox && !chatbox.handleMessageCorrection(stanza)) { if (chatbox && !chatbox.handleMessageCorrection(stanza)) {
const msgid = stanza.getAttribute('id'), const msgid = stanza.getAttribute('id'),
message = msgid && chatbox.messages.findWhere({msgid}); message = msgid && chatbox.messages.findWhere({msgid});
if (!message) { // Only create the message when we're sure it's not a duplicate if (!message) {
chatbox.incrementUnreadMsgCounter(chatbox.createMessage(stanza, original_stanza)); // Only create the message when we're sure it's not a duplicate
chatbox.createMessage(stanza, original_stanza)
.then(msg => chatbox.incrementUnreadMsgCounter(msg))
.catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
} }
} }
_converse.emit('message', {'stanza': original_stanza, 'chatbox': chatbox}); _converse.emit('message', {'stanza': original_stanza, 'chatbox': chatbox});
......
...@@ -128,6 +128,7 @@ ...@@ -128,6 +128,7 @@
// //
// New functions which don't exist yet can also be added. // New functions which don't exist yet can also be added.
ChatBox: { ChatBox: {
getMessageAttributesFromStanza (message, original_stanza) { getMessageAttributesFromStanza (message, original_stanza) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.__super__.getMessageAttributesFromStanza.apply(this, arguments) this.__super__.getMessageAttributesFromStanza.apply(this, arguments)
......
...@@ -926,7 +926,9 @@ ...@@ -926,7 +926,9 @@
if (sender === '') { if (sender === '') {
return; return;
} }
this.incrementUnreadMsgCounter(this.createMessage(stanza, original_stanza)); this.createMessage(stanza, original_stanza)
.then(msg => this.incrementUnreadMsgCounter(msg))
.catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
} }
if (sender !== this.get('nick')) { if (sender !== this.get('nick')) {
// We only emit an event if it's not our own message // We only emit an event if it's not our own message
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment