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