Wait for promises before opening chats in API methods

This commit is contained in:
JC Brand 2018-07-30 18:16:32 +02:00
parent cb118b9cd0
commit 506aa33131
14 changed files with 2464 additions and 2374 deletions

View File

@ -39,6 +39,9 @@
- New API method `_converse.api.vcard.update`. - New API method `_converse.api.vcard.update`.
- The `contactStatusChanged` event has been renamed to `contactPresenceChanged` - The `contactStatusChanged` event has been renamed to `contactPresenceChanged`
and a event `presenceChanged` is now also triggered on the contact. and a event `presenceChanged` is now also triggered on the contact.
- `_converse.api.chats.open` and `_converse.api.rooms.open` now returns a
`Presence` which resolves with the `Backbone.Model` representing the chat
object.
## UI changes ## UI changes

41
dist/converse.js vendored
View File

@ -76149,17 +76149,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
this.model.on('show', this.show, this); this.model.on('show', this.show, this);
this.model.occupants.on('add', this.showJoinNotification, this); this.model.occupants.on('add', this.showJoinNotification, this);
this.model.occupants.on('remove', this.showLeaveNotification, this); this.model.occupants.on('remove', this.showLeaveNotification, this);
this.model.occupants.on('change:show', occupant => { this.model.occupants.on('change:show', this.showJoinOrLeaveNotification, this);
if (!occupant.isMember() || _.includes(occupant.get('states'), '303')) {
return;
}
if (occupant.get('show') === 'offline') {
this.showLeaveNotification(occupant);
} else if (occupant.get('show') === 'online') {
this.showJoinNotification(occupant);
}
});
this.createEmojiPicker(); this.createEmojiPicker();
this.createOccupantsView(); this.createOccupantsView();
this.render().insertIntoDOM(); this.render().insertIntoDOM();
@ -76169,8 +76159,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
const handler = () => { const handler = () => {
if (!u.isPersistableModel(this.model)) { if (!u.isPersistableModel(this.model)) {
// Happens during tests, nothing to do if this // Happens during tests, nothing to do if this
// is a hanging chatbox (i.e. not in the // is a hanging chatbox (i.e. not in the collection anymore).
// collection anymore).
return; return;
} }
@ -77047,6 +77036,18 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
} }
}, },
showJoinOrLeaveNotification(occupant) {
if (!occupant.isMember() || _.includes(occupant.get('states'), '303')) {
return;
}
if (occupant.get('show') === 'offline') {
this.showLeaveNotification(occupant);
} else if (occupant.get('show') === 'online') {
this.showJoinNotification(occupant);
}
},
showJoinNotification(occupant) { showJoinNotification(occupant) {
if (this.model.get('connection_status') !== converse.ROOMSTATUS.ENTERED) { if (this.model.get('connection_status') !== converse.ROOMSTATUS.ENTERED) {
return; return;
@ -77094,10 +77095,9 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
showLeaveNotification(occupant) { showLeaveNotification(occupant) {
const nick = occupant.get('nick'), const nick = occupant.get('nick'),
stat = occupant.get('status'), stat = occupant.get('status'),
last_el = this.content.lastElementChild, last_el = this.content.lastElementChild;
last_msg_date = last_el.getAttribute('data-isodate');
if (_.includes(_.get(last_el, 'classList', []), 'chat-info') && moment(last_msg_date).isSame(new Date(), "day") && _.get(last_el, 'dataset', {}).join === `"${nick}"`) { if (last_el && _.includes(_.get(last_el, 'classList', []), 'chat-info') && moment(last_el.getAttribute('data-isodate')).isSame(new Date(), "day") && _.get(last_el, 'dataset', {}).join === `"${nick}"`) {
let message; let message;
if (_.isNil(stat)) { if (_.isNil(stat)) {
@ -77128,7 +77128,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
'data': `data-leave="${nick}"` 'data': `data-leave="${nick}"`
}; };
if (_.includes(_.get(last_el, 'classList', []), 'chat-info') && _.get(last_el, 'dataset', {}).leavejoin === `"${nick}"`) { if (last_el && _.includes(_.get(last_el, 'classList', []), 'chat-info') && _.get(last_el, 'dataset', {}).leavejoin === `"${nick}"`) {
last_el.outerHTML = tpl_info(data); last_el.outerHTML = tpl_info(data);
} else { } else {
const el = u.stringToElement(tpl_info(data)); const el = u.stringToElement(tpl_info(data));
@ -83843,8 +83843,13 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
xhr.onload = function () { xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 400) { if (xhr.status >= 200 && xhr.status < 400) {
jed_instance = new Jed(window.JSON.parse(xhr.responseText)); try {
const data = window.JSON.parse(xhr.responseText);
jed_instance = new Jed(data);
resolve(); resolve();
} catch (e) {
xhr.onerror(e);
}
} else { } else {
xhr.onerror(); xhr.onerror();
} }

View File

@ -34,24 +34,24 @@
}); });
spyOn(_converse.connection, 'getUniqueId').and.callThrough(); spyOn(_converse.connection, 'getUniqueId').and.callThrough();
test_utils.openChatRoom(_converse, 'theplay', 'conference.shakespeare.lit', 'JC'); let view;
test_utils.openChatRoom(_converse, 'theplay', 'conference.shakespeare.lit', 'JC')
.then(() => {
var jid = 'theplay@conference.shakespeare.lit'; var jid = 'theplay@conference.shakespeare.lit';
var view = _converse.chatboxviews.get(jid); view = _converse.chatboxviews.get(jid);
spyOn(view, 'renderBookmarkForm').and.callThrough(); spyOn(view, 'renderBookmarkForm').and.callThrough();
spyOn(view, 'closeForm').and.callThrough(); spyOn(view, 'closeForm').and.callThrough();
return test_utils.waitUntil(() => !_.isNull(view.el.querySelector('.toggle-bookmark')));
test_utils.waitUntil(function () { }).then(() => {
return !_.isNull(view.el.querySelector('.toggle-bookmark')); var bookmark = view.el.querySelector('.toggle-bookmark');
}, 300).then(function () { bookmark.click();
var $bookmark = $(view.el).find('.toggle-bookmark');
$bookmark[0].click();
expect(view.renderBookmarkForm).toHaveBeenCalled(); expect(view.renderBookmarkForm).toHaveBeenCalled();
view.el.querySelector('.button-cancel').click(); view.el.querySelector('.button-cancel').click();
expect(view.closeForm).toHaveBeenCalled(); expect(view.closeForm).toHaveBeenCalled();
expect($bookmark.hasClass('on-button'), false); expect(u.hasClass('on-button', bookmark), false);
$bookmark[0].click(); bookmark.click();
expect(view.renderBookmarkForm).toHaveBeenCalled(); expect(view.renderBookmarkForm).toHaveBeenCalled();
/* Client uploads data: /* Client uploads data:
@ -93,7 +93,7 @@
view.el.querySelector('.btn-primary').click(); view.el.querySelector('.btn-primary').click();
expect(view.model.get('bookmarked')).toBeTruthy(); expect(view.model.get('bookmarked')).toBeTruthy();
expect($bookmark.hasClass('on-button'), true); expect(u.hasClass('on-button', bookmark), true);
expect(sent_stanza.toLocaleString()).toBe( expect(sent_stanza.toLocaleString()).toBe(
"<iq type='set' from='dummy@localhost/resource' xmlns='jabber:client' id='"+IQ_id+"'>"+ "<iq type='set' from='dummy@localhost/resource' xmlns='jabber:client' id='"+IQ_id+"'>"+
@ -175,17 +175,16 @@
it("displays that it's bookmarked through its bookmark icon", mock.initConverseWithPromises( it("displays that it's bookmarked through its bookmark icon", mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, function (done, _converse) { null, ['rosterGroupsFetched'], {}, function (done, _converse) {
let view;
test_utils.waitUntilDiscoConfirmed( test_utils.waitUntilDiscoConfirmed(
_converse, _converse.bare_jid, _converse, _converse.bare_jid,
[{'category': 'pubsub', 'type': 'pep'}], [{'category': 'pubsub', 'type': 'pep'}],
['http://jabber.org/protocol/pubsub#publish-options'] ['http://jabber.org/protocol/pubsub#publish-options']
).then(function () { ).then(() => test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy'))
test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy'); .then(() => {
var view = _converse.chatboxviews.get('lounge@localhost'); view = _converse.chatboxviews.get('lounge@localhost');
return test_utils.waitUntil(() => !_.isNull(view.el.querySelector('.toggle-bookmark')))
test_utils.waitUntil(function () { }).then(function () {
return !_.isNull(view.el.querySelector('.toggle-bookmark'));
}, 300).then(function () {
var bookmark_icon = view.el.querySelector('.toggle-bookmark'); var bookmark_icon = view.el.querySelector('.toggle-bookmark');
expect(_.includes(bookmark_icon.classList, 'button-on')).toBeFalsy(); expect(_.includes(bookmark_icon.classList, 'button-on')).toBeFalsy();
view.model.set('bookmarked', true); view.model.set('bookmarked', true);
@ -194,27 +193,25 @@
expect(_.includes(bookmark_icon.classList, 'button-on')).toBeFalsy(); expect(_.includes(bookmark_icon.classList, 'button-on')).toBeFalsy();
done(); done();
}); });
});
})); }));
it("can be unbookmarked", mock.initConverseWithPromises( it("can be unbookmarked", mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, function (done, _converse) { null, ['rosterGroupsFetched'], {}, function (done, _converse) {
let sent_stanza, IQ_id, view, sendIQ;
test_utils.waitUntilDiscoConfirmed( test_utils.waitUntilDiscoConfirmed(
_converse, _converse.bare_jid, _converse, _converse.bare_jid,
[{'category': 'pubsub', 'type': 'pep'}], [{'category': 'pubsub', 'type': 'pep'}],
['http://jabber.org/protocol/pubsub#publish-options'] ['http://jabber.org/protocol/pubsub#publish-options']
).then(function () { ).then(() => {
var sent_stanza, IQ_id; sendIQ = _converse.connection.sendIQ;
var sendIQ = _converse.connection.sendIQ; return test_utils.openChatRoom(_converse, 'theplay', 'conference.shakespeare.lit', 'JC');
}).then(() => {
test_utils.openChatRoom(_converse, 'theplay', 'conference.shakespeare.lit', 'JC');
var jid = 'theplay@conference.shakespeare.lit'; var jid = 'theplay@conference.shakespeare.lit';
var view = _converse.chatboxviews.get(jid); view = _converse.chatboxviews.get(jid);
return test_utils.waitUntil(() => !_.isNull(view.el.querySelector('.toggle-bookmark')));
test_utils.waitUntil(function () { }).then(function () {
return !_.isNull(view.el.querySelector('.toggle-bookmark'));
}, 300).then(function () {
spyOn(view, 'toggleBookmark').and.callThrough(); spyOn(view, 'toggleBookmark').and.callThrough();
spyOn(_converse.bookmarks, 'sendBookmarkStanza').and.callThrough(); spyOn(_converse.bookmarks, 'sendBookmarkStanza').and.callThrough();
view.delegateEvents(); view.delegateEvents();
@ -227,17 +224,17 @@
}); });
expect(_converse.bookmarks.length).toBe(1); expect(_converse.bookmarks.length).toBe(1);
expect(view.model.get('bookmarked')).toBeTruthy(); expect(view.model.get('bookmarked')).toBeTruthy();
var $bookmark_icon = $(view.el.querySelector('.toggle-bookmark')); var bookmark_icon = view.el.querySelector('.toggle-bookmark');
expect($bookmark_icon.hasClass('button-on')).toBeTruthy(); expect(u.hasClass('button-on', bookmark_icon)).toBeTruthy();
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_stanza = iq; sent_stanza = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
spyOn(_converse.connection, 'getUniqueId').and.callThrough(); spyOn(_converse.connection, 'getUniqueId').and.callThrough();
$bookmark_icon[0].click(); bookmark_icon.click();
expect(view.toggleBookmark).toHaveBeenCalled(); expect(view.toggleBookmark).toHaveBeenCalled();
expect($bookmark_icon.hasClass('button-on')).toBeFalsy(); expect(u.hasClass('button-on', bookmark_icon)).toBeFalsy();
expect(_converse.bookmarks.length).toBe(0); expect(_converse.bookmarks.length).toBe(0);
// Check that an IQ stanza is sent out, containing no // Check that an IQ stanza is sent out, containing no
@ -269,7 +266,6 @@
); );
done(); done();
}); });
});
})); }));
}); });
@ -585,9 +581,8 @@
'name': 'The Play', 'name': 'The Play',
'nick': '' 'nick': ''
}); });
test_utils.waitUntil(function () { test_utils.waitUntil(() => $('#chatrooms .bookmarks.rooms-list .room-item:visible').length
return $('#chatrooms .bookmarks.rooms-list .room-item:visible').length; ).then(function () {
}, 300).then(function () {
expect($('#chatrooms .bookmarks.rooms-list').hasClass('collapsed')).toBeFalsy(); expect($('#chatrooms .bookmarks.rooms-list').hasClass('collapsed')).toBeFalsy();
expect($('#chatrooms .bookmarks.rooms-list .room-item:visible').length).toBe(1); expect($('#chatrooms .bookmarks.rooms-list .room-item:visible').length).toBe(1);
expect(_converse.bookmarksview.list_model.get('toggle-state')).toBe(_converse.OPENED); expect(_converse.bookmarksview.list_model.get('toggle-state')).toBe(_converse.OPENED);
@ -612,6 +607,7 @@
{ hide_open_bookmarks: true }, { hide_open_bookmarks: true },
function (done, _converse) { function (done, _converse) {
const jid = 'room@conference.example.org';
test_utils.waitUntilDiscoConfirmed( test_utils.waitUntilDiscoConfirmed(
_converse, _converse.bare_jid, _converse, _converse.bare_jid,
[{'category': 'pubsub', 'type': 'pep'}], [{'category': 'pubsub', 'type': 'pep'}],
@ -625,14 +621,12 @@
_converse.emit('bookmarksInitialized'); _converse.emit('bookmarksInitialized');
// Check that it's there // Check that it's there
var jid = 'room@conference.example.org';
_converse.bookmarks.create({ _converse.bookmarks.create({
'jid': jid, 'jid': jid,
'autojoin': false, 'autojoin': false,
'name': 'The Play', 'name': 'The Play',
'nick': ' Othello' 'nick': ' Othello'
}); });
expect(_converse.bookmarks.length).toBe(1); expect(_converse.bookmarks.length).toBe(1);
var room_els = _converse.bookmarksview.el.querySelectorAll(".open-room"); var room_els = _converse.bookmarksview.el.querySelectorAll(".open-room");
expect(room_els.length).toBe(1); expect(room_els.length).toBe(1);
@ -640,9 +634,11 @@
// Check that it disappears once the room is opened // Check that it disappears once the room is opened
var bookmark = _converse.bookmarksview.el.querySelector(".open-room"); var bookmark = _converse.bookmarksview.el.querySelector(".open-room");
bookmark.click(); bookmark.click();
return test_utils.waitUntil(() => _converse.chatboxviews.get(jid));
}).then(() => {
expect(u.hasClass('hidden', _converse.bookmarksview.el.querySelector(".available-chatroom"))).toBeTruthy(); expect(u.hasClass('hidden', _converse.bookmarksview.el.querySelector(".available-chatroom"))).toBeTruthy();
// Check that it reappears once the room is closed // Check that it reappears once the room is closed
var view = _converse.chatboxviews.get(jid); const view = _converse.chatboxviews.get(jid);
view.close(); view.close();
expect(u.hasClass('hidden', _converse.bookmarksview.el.querySelector(".available-chatroom"))).toBeFalsy(); expect(u.hasClass('hidden', _converse.bookmarksview.el.querySelector(".available-chatroom"))).toBeFalsy();
done(); done();

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,16 @@
(function (root, factory) { (function (root, factory) {
define(["jquery", "jasmine", "mock", "test-utils" ], factory); define(["jquery", "jasmine", "mock", "test-utils" ], factory);
} (this, function ($, jasmine, mock, test_utils) { } (this, function ($, jasmine, mock, test_utils) {
var _ = converse.env._; const _ = converse.env._,
var $pres = converse.env.$pres; $pres = converse.env.$pres,
var $iq = converse.env.$iq; $iq = converse.env.$iq,
var $msg = converse.env.$msg; $msg = converse.env.$msg,
var Strophe = converse.env.Strophe; Strophe = converse.env.Strophe,
var Promise = converse.env.Promise; Promise = converse.env.Promise,
var moment = converse.env.moment; moment = converse.env.moment,
var sizzle = converse.env.sizzle; sizzle = converse.env.sizzle,
var u = converse.env.utils; Backbone = converse.env.Backbone,
u = converse.env.utils;
return describe("ChatRooms", function () { return describe("ChatRooms", function () {
describe("The \"rooms\" API", function () { describe("The \"rooms\" API", function () {
@ -107,7 +108,7 @@
it("has a method 'open' which opens (optionally configures) and returns a wrapped chat box", it("has a method 'open' which opens (optionally configures) and returns a wrapped chat box",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
// Mock 'getRoomFeatures', otherwise the room won't be // Mock 'getRoomFeatures', otherwise the room won't be
@ -119,22 +120,24 @@
return deferred.promise(); return deferred.promise();
}); });
const sent_IQ_els = [];
let jid = 'lounge@localhost';
let chatroomview, sent_IQ, IQ_id;
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.waitUntil(function () { test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group .group-toggle').length)
return $(_converse.rosterview.el).find('.roster-group .group-toggle').length; .then(() => _converse.api.rooms.open(jid))
}, 300).then(function () { .then((room) => {
var jid = 'lounge@localhost';
var room = _converse.api.rooms.open(jid);
// Test on groupchat that's not yet open // Test on groupchat that's not yet open
expect(room instanceof Object).toBeTruthy(); expect(room instanceof Backbone.Model).toBeTruthy();
var chatroomview = _converse.chatboxviews.get(jid); chatroomview = _converse.chatboxviews.get(jid);
expect(chatroomview.is_chatroom).toBeTruthy(); expect(chatroomview.is_chatroom).toBeTruthy();
expect(u.isVisible(chatroomview.el)).toBeTruthy(); expect(u.isVisible(chatroomview.el)).toBeTruthy();
// Test again, now that the room exists. // Test again, now that the room exists.
room = _converse.api.rooms.open(jid); return _converse.api.rooms.open(jid);
expect(room instanceof Object).toBeTruthy(); }).then((room) => {
expect(room instanceof Backbone.Model).toBeTruthy();
chatroomview = _converse.chatboxviews.get(jid); chatroomview = _converse.chatboxviews.get(jid);
expect(chatroomview.is_chatroom).toBeTruthy(); expect(chatroomview.is_chatroom).toBeTruthy();
expect(u.isVisible(chatroomview.el)).toBeTruthy(); expect(u.isVisible(chatroomview.el)).toBeTruthy();
@ -142,26 +145,28 @@
// Test with mixed case in JID // Test with mixed case in JID
jid = 'Leisure@localhost'; jid = 'Leisure@localhost';
room = _converse.api.rooms.open(jid); return _converse.api.rooms.open(jid);
expect(room instanceof Object).toBeTruthy(); }).then((room) => {
expect(room instanceof Backbone.Model).toBeTruthy();
chatroomview = _converse.chatboxviews.get(jid.toLowerCase()); chatroomview = _converse.chatboxviews.get(jid.toLowerCase());
expect(u.isVisible(chatroomview.el)).toBeTruthy(); expect(u.isVisible(chatroomview.el)).toBeTruthy();
jid = 'leisure@localhost'; jid = 'leisure@localhost';
room = _converse.api.rooms.open(jid); return _converse.api.rooms.open(jid);
expect(room instanceof Object).toBeTruthy(); }).then((room) => {
expect(room instanceof Backbone.Model).toBeTruthy();
chatroomview = _converse.chatboxviews.get(jid.toLowerCase()); chatroomview = _converse.chatboxviews.get(jid.toLowerCase());
expect(u.isVisible(chatroomview.el)).toBeTruthy(); expect(u.isVisible(chatroomview.el)).toBeTruthy();
jid = 'leiSure@localhost'; jid = 'leiSure@localhost';
room = _converse.api.rooms.open(jid); return _converse.api.rooms.open(jid);
expect(room instanceof Object).toBeTruthy(); }).then((room) => {
expect(room instanceof Backbone.Model).toBeTruthy();
chatroomview = _converse.chatboxviews.get(jid.toLowerCase()); chatroomview = _converse.chatboxviews.get(jid.toLowerCase());
expect(u.isVisible(chatroomview.el)).toBeTruthy(); expect(u.isVisible(chatroomview.el)).toBeTruthy();
chatroomview.close(); chatroomview.close();
_converse.muc_instant_rooms = false; _converse.muc_instant_rooms = false;
var sent_IQ, IQ_id, sent_IQ_els = [];
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_IQ = iq; sent_IQ = iq;
@ -169,7 +174,7 @@
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
// Test with configuration // Test with configuration
_converse.api.rooms.open('room@conference.example.org', { return _converse.api.rooms.open('room@conference.example.org', {
'nick': 'some1', 'nick': 'some1',
'auto_configure': true, 'auto_configure': true,
'roomconfig': { 'roomconfig': {
@ -181,6 +186,7 @@
'whois': 'anyone' 'whois': 'anyone'
} }
}); });
}).then((room) => {
chatroomview = _converse.chatboxviews.get('room@conference.example.org'); chatroomview = _converse.chatboxviews.get('room@conference.example.org');
// We pretend this is a new room, so no disco info is returned. // We pretend this is a new room, so no disco info is returned.
@ -252,11 +258,8 @@
spyOn(chatroomview.model, 'sendConfiguration').and.callThrough(); spyOn(chatroomview.model, 'sendConfiguration').and.callThrough();
_converse.connection._dataRecv(test_utils.createRequest(node.firstElementChild)); _converse.connection._dataRecv(test_utils.createRequest(node.firstElementChild));
return test_utils.waitUntil(() => chatroomview.model.sendConfiguration.calls.count() === 1);
}).then(() => {
return test_utils.waitUntil(function () {
return chatroomview.model.sendConfiguration.calls.count() === 1;
}, 300).then(function () {
var sent_stanza = sent_IQ_els.pop(); var sent_stanza = sent_IQ_els.pop();
while (sent_stanza.getAttribute('type') !== 'set') { while (sent_stanza.getAttribute('type') !== 'set') {
sent_stanza = sent_IQ_els.pop(); sent_stanza = sent_IQ_els.pop();
@ -271,7 +274,6 @@
expect(sizzle('field[var="muc#roomconfig_historylength"] value', sent_stanza).pop().textContent).toBe('20'); expect(sizzle('field[var="muc#roomconfig_historylength"] value', sent_stanza).pop().textContent).toBe('20');
done(); done();
}); });
});
})); }));
}); });
@ -279,12 +281,12 @@
it("will be created when muc_instant_rooms is set to true", it("will be created when muc_instant_rooms is set to true",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
var IQ_stanzas = _converse.connection.IQ_stanzas; const IQ_stanzas = _converse.connection.IQ_stanzas;
var sent_IQ, IQ_id; const sendIQ = _converse.connection.sendIQ;
var sendIQ = _converse.connection.sendIQ; let sent_IQ, IQ_id, view;
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
if (iq.nodeTree.getAttribute('to') === 'lounge@localhost') { if (iq.nodeTree.getAttribute('to') === 'lounge@localhost') {
sent_IQ = iq; sent_IQ = iq;
@ -293,8 +295,8 @@
sendIQ.bind(this)(iq, callback, errback); sendIQ.bind(this)(iq, callback, errback);
} }
}); });
test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy'); test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy')
.then(() => {
// We pretend this is a new room, so no disco info is returned. // We pretend this is a new room, so no disco info is returned.
// //
/* <iq from="jordie.langen@chat.example.org/converse.js-11659299" to="myroom@conference.chat.example.org" type="get"> /* <iq from="jordie.langen@chat.example.org/converse.js-11659299" to="myroom@conference.chat.example.org" type="get">
@ -315,7 +317,7 @@
.c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"}); .c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"});
_converse.connection._dataRecv(test_utils.createRequest(features_stanza)); _converse.connection._dataRecv(test_utils.createRequest(features_stanza));
var view = _converse.chatboxviews.get('lounge@localhost'); view = _converse.chatboxviews.get('lounge@localhost');
spyOn(view, 'join').and.callThrough(); spyOn(view, 'join').and.callThrough();
spyOn(view, 'submitNickname').and.callThrough(); spyOn(view, 'submitNickname').and.callThrough();
@ -326,11 +328,8 @@
* node="x-roomuser-item"/> * node="x-roomuser-item"/>
* </iq> * </iq>
*/ */
test_utils.waitUntil(function () { return test_utils.waitUntil(() => _.filter(IQ_stanzas, (iq) => iq.nodeTree.querySelector('query[node="x-roomuser-item"]')).length);
return _.filter(IQ_stanzas, function (iq) { }).then(() => {
return iq.nodeTree.querySelector('query[node="x-roomuser-item"]');
}).length > 0;
}, 300).then(function () {
const iq = _.filter(IQ_stanzas, function (iq) { const iq = _.filter(IQ_stanzas, function (iq) {
return iq.nodeTree.querySelector(`query[node="x-roomuser-item"]`); return iq.nodeTree.querySelector(`query[node="x-roomuser-item"]`);
}).pop(); }).pop();
@ -411,10 +410,11 @@
it("shows join/leave messages when users enter or exit a groupchat", it("shows join/leave messages when users enter or exit a groupchat",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.openChatRoom(_converse, "coven", 'chat.shakespeare.lit', 'some1'); test_utils.openChatRoom(_converse, "coven", 'chat.shakespeare.lit', 'some1')
.then(() => {
var view = _converse.chatboxviews.get('coven@chat.shakespeare.lit'); var view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
var $chat_content = $(view.el).find('.chat-content'); var $chat_content = $(view.el).find('.chat-content');
@ -604,6 +604,7 @@
expect($chat_content[0].querySelectorAll('div.chat-info').length).toBe(5); expect($chat_content[0].querySelectorAll('div.chat-info').length).toBe(5);
expect($chat_content.find('div.chat-info:last').html()).toBe("nomorenicks has entered the groupchat"); expect($chat_content.find('div.chat-info:last').html()).toBe("nomorenicks has entered the groupchat");
done(); done();
});
})); }));
it("shows a new day indicator if a join/leave message is received on a new day", it("shows a new day indicator if a join/leave message is received on a new day",
@ -774,19 +775,19 @@
it("shows its description in the chat heading", it("shows its description in the chat heading",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
var sent_IQ, IQ_id; let sent_IQ, IQ_id, view;
var sendIQ = _converse.connection.sendIQ; const sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_IQ = iq; sent_IQ = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
_converse.api.rooms.open('coven@chat.shakespeare.lit', {'nick': 'some1'}); _converse.api.rooms.open('coven@chat.shakespeare.lit', {'nick': 'some1'})
var view = _converse.chatboxviews.get('coven@chat.shakespeare.lit'); .then(() => {
view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
var features_stanza = $iq({ const features_stanza = $iq({
from: 'coven@chat.shakespeare.lit', from: 'coven@chat.shakespeare.lit',
'id': IQ_id, 'id': IQ_id,
'to': 'dummy@localhost/desktop', 'to': 'dummy@localhost/desktop',
@ -814,9 +815,9 @@
.c('field', {'type':'text-single', 'var':'muc#roominfo_occupants', 'label':'Number of participants'}) .c('field', {'type':'text-single', 'var':'muc#roominfo_occupants', 'label':'Number of participants'})
.c('value').t(0); .c('value').t(0);
_converse.connection._dataRecv(test_utils.createRequest(features_stanza)); _converse.connection._dataRecv(test_utils.createRequest(features_stanza));
test_utils.waitUntil(() => _.get(view.el.querySelector('.chatroom-description'), 'textContent')) return test_utils.waitUntil(() => _.get(view.el.querySelector('.chatroom-description'), 'textContent'))
.then(function () { }).then(function () {
expect($(view.el.querySelector('.chatroom-description')).text()).toBe('This is the description'); expect(view.el.querySelector('.chatroom-description').textContent).toBe('This is the description');
done(); done();
}); });
})); }));
@ -886,7 +887,7 @@
it("can be configured if you're its owner", it("can be configured if you're its owner",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
var view; var view;
@ -897,7 +898,8 @@
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
_converse.api.rooms.open('coven@chat.shakespeare.lit', {'nick': 'some1'}); _converse.api.rooms.open('coven@chat.shakespeare.lit', {'nick': 'some1'})
.then(() => {
view = _converse.chatboxviews.get('coven@chat.shakespeare.lit'); view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
spyOn(view.model, 'saveAffiliationAndRole').and.callThrough(); spyOn(view.model, 'saveAffiliationAndRole').and.callThrough();
@ -933,12 +935,9 @@
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(view.model.saveAffiliationAndRole).toHaveBeenCalled(); expect(view.model.saveAffiliationAndRole).toHaveBeenCalled();
expect($(view.el.querySelector('.toggle-chatbox-button')).is(':visible')).toBeTruthy(); expect($(view.el.querySelector('.toggle-chatbox-button')).is(':visible')).toBeTruthy();
return test_utils.waitUntil(() => !_.isNull(view.el.querySelector('.configure-chatroom-button')))
test_utils.waitUntil(function () { }).then(() => {
return !_.isNull(view.el.querySelector('.configure-chatroom-button'));
}, 300).then(function () {
expect($(view.el.querySelector('.configure-chatroom-button')).is(':visible')).toBeTruthy(); expect($(view.el.querySelector('.configure-chatroom-button')).is(':visible')).toBeTruthy();
view.el.querySelector('.configure-chatroom-button').click(); view.el.querySelector('.configure-chatroom-button').click();
/* Check that an IQ is sent out, asking for the /* Check that an IQ is sent out, asking for the
@ -1074,9 +1073,8 @@
.c('value').t('cauldronburn'); .c('value').t('cauldronburn');
_converse.connection._dataRecv(test_utils.createRequest(config_stanza)); _converse.connection._dataRecv(test_utils.createRequest(config_stanza));
test_utils.waitUntil(function () { return test_utils.waitUntil(() => view.el.querySelectorAll('form.chatroom-form').length)
return $(view.el.querySelector('form.chatroom-form')).length; }).then(() => {
}, 300).then(function () {
expect($(view.el.querySelector('form.chatroom-form')).length).toBe(1); expect($(view.el.querySelector('form.chatroom-form')).length).toBe(1);
expect(view.el.querySelectorAll('form.chatroom-form fieldset').length).toBe(2); expect(view.el.querySelectorAll('form.chatroom-form fieldset').length).toBe(2);
var $membersonly = $(view.el.querySelector('input[name="muc#roomconfig_membersonly"]')); var $membersonly = $(view.el.querySelector('input[name="muc#roomconfig_membersonly"]'));
@ -1109,7 +1107,6 @@
expect($sent_stanza.find('field[var="muc#roomconfig_allowpm"] value').text()).toBe('moderators'); expect($sent_stanza.find('field[var="muc#roomconfig_allowpm"] value').text()).toBe('moderators');
expect($sent_stanza.find('field[var="muc#roomconfig_presencebroadcast"] value').text()).toBe('moderator'); expect($sent_stanza.find('field[var="muc#roomconfig_presencebroadcast"] value').text()).toBe('moderator');
done(); done();
});
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
})); }));
@ -1318,12 +1315,12 @@
it("will use the user's reserved nickname, if it exists", it("will use the user's reserved nickname, if it exists",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
var IQ_stanzas = _converse.connection.IQ_stanzas; let sent_IQ, IQ_id, view;
var sent_IQ, IQ_id; const IQ_stanzas = _converse.connection.IQ_stanzas;
var sendIQ = _converse.connection.sendIQ; const sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
if (iq.nodeTree.getAttribute('to') === 'lounge@localhost') { if (iq.nodeTree.getAttribute('to') === 'lounge@localhost') {
sent_IQ = iq; sent_IQ = iq;
@ -1333,8 +1330,8 @@
} }
}); });
test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy'); test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy')
.then(() => {
// We pretend this is a new room, so no disco info is returned. // We pretend this is a new room, so no disco info is returned.
var features_stanza = $iq({ var features_stanza = $iq({
from: 'lounge@localhost', from: 'lounge@localhost',
@ -1345,7 +1342,7 @@
.c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"}); .c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"});
_converse.connection._dataRecv(test_utils.createRequest(features_stanza)); _converse.connection._dataRecv(test_utils.createRequest(features_stanza));
var view = _converse.chatboxviews.get('lounge@localhost'); view = _converse.chatboxviews.get('lounge@localhost');
spyOn(view, 'join').and.callThrough(); spyOn(view, 'join').and.callThrough();
/* <iq from='hag66@shakespeare.lit/pda' /* <iq from='hag66@shakespeare.lit/pda'
@ -1356,12 +1353,8 @@
* node='x-roomuser-item'/> * node='x-roomuser-item'/>
* </iq> * </iq>
*/ */
return test_utils.waitUntil(() => _.filter(IQ_stanzas, (iq) => iq.nodeTree.querySelector('query[node="x-roomuser-item"]')).length)
test_utils.waitUntil(function () { }).then(() => {
return _.filter(IQ_stanzas, function (iq) {
return iq.nodeTree.querySelector('query[node="x-roomuser-item"]');
}).length > 0;
}, 300).then(function () {
const iq = _.filter(IQ_stanzas, function (iq) { const iq = _.filter(IQ_stanzas, function (iq) {
return iq.nodeTree.querySelector(`query[node="x-roomuser-item"]`); return iq.nodeTree.querySelector(`query[node="x-roomuser-item"]`);
}).pop(); }).pop();
@ -1421,20 +1414,23 @@
it("allows the user to invite their roster contacts to enter the groupchat", it("allows the user to invite their roster contacts to enter the groupchat",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy');
test_utils.createContacts(_converse, 'current'); // We need roster contacts, so that we have someone to invite test_utils.createContacts(_converse, 'current'); // We need roster contacts, so that we have someone to invite
// Since we don't actually fetch roster contacts, we need to // Since we don't actually fetch roster contacts, we need to
// cheat here and emit the event. // cheat here and emit the event.
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
let view;
test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy')
.then(() => {
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
spyOn(window, 'prompt').and.callFake(function () { spyOn(window, 'prompt').and.callFake(function () {
return "Please join!"; return "Please join!";
}); });
var view = _converse.chatboxviews.get('lounge@localhost'); view = _converse.chatboxviews.get('lounge@localhost');
// XXX: cheating a lttle bit, normally this'll be set after // XXX: cheating a lttle bit, normally this'll be set after
// receiving the features for the groupchat. // receiving the features for the groupchat.
@ -1444,9 +1440,8 @@
var $input; var $input;
$(view.el).find('.chat-area').remove(); $(view.el).find('.chat-area').remove();
test_utils.waitUntil(function () { return test_utils.waitUntil(() => view.el.querySelectorAll('input.invited-contact').length)
return $(view.el).find('input.invited-contact').length; }).then(function () {
}, 300).then(function () {
var $input = $(view.el).find('input.invited-contact'); var $input = $(view.el).find('input.invited-contact');
expect($input.attr('placeholder')).toBe('Invite'); expect($input.attr('placeholder')).toBe('Invite');
$input.val("Felix"); $input.val("Felix");
@ -1782,7 +1777,7 @@
it("queries for the groupchat information before attempting to join the user", it("queries for the groupchat information before attempting to join the user",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
var sent_IQ, IQ_id; var sent_IQ, IQ_id;
@ -1792,15 +1787,16 @@
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
_converse.api.rooms.open('coven@chat.shakespeare.lit', {'nick': 'some1'}); let view;
_converse.api.rooms.open('coven@chat.shakespeare.lit', {'nick': 'some1'})
.then(() => {
// Check that the groupchat queried for the feautures. // Check that the groupchat queried for the feautures.
expect(sent_IQ.toLocaleString()).toBe( expect(sent_IQ.toLocaleString()).toBe(
"<iq from='dummy@localhost/resource' to='coven@chat.shakespeare.lit' type='get' xmlns='jabber:client' id='"+IQ_id+"'>"+ "<iq from='dummy@localhost/resource' to='coven@chat.shakespeare.lit' type='get' xmlns='jabber:client' id='"+IQ_id+"'>"+
"<query xmlns='http://jabber.org/protocol/disco#info'/>"+ "<query xmlns='http://jabber.org/protocol/disco#info'/>"+
"</iq>"); "</iq>");
var view = _converse.chatboxviews.get('coven@chat.shakespeare.lit'); view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
spyOn(view.model, 'parseRoomFeatures').and.callThrough(); spyOn(view.model, 'parseRoomFeatures').and.callThrough();
/* <iq from='coven@chat.shakespeare.lit' /* <iq from='coven@chat.shakespeare.lit'
* id='ik3vs715' * id='ik3vs715'
@ -1821,7 +1817,7 @@
* </query> * </query>
* </iq> * </iq>
*/ */
var features_stanza = $iq({ const features_stanza = $iq({
from: 'coven@chat.shakespeare.lit', from: 'coven@chat.shakespeare.lit',
'id': IQ_id, 'id': IQ_id,
'to': 'dummy@localhost/desktop', 'to': 'dummy@localhost/desktop',
@ -1841,8 +1837,8 @@
.c('feature', {'var': 'muc_unmoderated'}).up() .c('feature', {'var': 'muc_unmoderated'}).up()
.c('feature', {'var': 'muc_nonanonymous'}); .c('feature', {'var': 'muc_nonanonymous'});
_converse.connection._dataRecv(test_utils.createRequest(features_stanza)); _converse.connection._dataRecv(test_utils.createRequest(features_stanza));
test_utils.waitUntil(() => view.model.parseRoomFeatures.calls.count(), 300) return test_utils.waitUntil(() => view.model.parseRoomFeatures.calls.count(), 300)
.then(() => { }).then(() => {
expect(view.model.get('features_fetched')).toBeTruthy(); expect(view.model.get('features_fetched')).toBeTruthy();
expect(view.model.get('passwordprotected')).toBe(true); expect(view.model.get('passwordprotected')).toBe(true);
expect(view.model.get('hidden')).toBe(true); expect(view.model.get('hidden')).toBe(true);
@ -2014,10 +2010,11 @@
it("can be saved to, and retrieved from, browserStorage", it("can be saved to, and retrieved from, browserStorage",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy'); test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy')
.then(() => {
// We instantiate a new ChatBoxes collection, which by default // We instantiate a new ChatBoxes collection, which by default
// will be empty. // will be empty.
test_utils.openControlBox(); test_utils.openControlBox();
@ -2042,15 +2039,17 @@
} }
_converse.rosterview.render(); _converse.rosterview.render();
done(); done();
});
})); }));
it("can be minimized by clicking a DOM element with class 'toggle-chatbox-button'", it("can be minimized by clicking a DOM element with class 'toggle-chatbox-button'",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy'); test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy')
var view = _converse.chatboxviews.get('lounge@localhost'), .then(() => {
const view = _converse.chatboxviews.get('lounge@localhost'),
trimmed_chatboxes = _converse.minimized_chats; trimmed_chatboxes = _converse.minimized_chats;
spyOn(view, 'minimize').and.callThrough(); spyOn(view, 'minimize').and.callThrough();
@ -2071,15 +2070,18 @@
expect(view.model.get('minimized')).toBeFalsy(); expect(view.model.get('minimized')).toBeFalsy();
expect(_converse.emit.calls.count(), 3); expect(_converse.emit.calls.count(), 3);
done(); done();
});
})); }));
it("can be closed again by clicking a DOM element with class 'close-chatbox-button'", it("can be closed again by clicking a DOM element with class 'close-chatbox-button'",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy'); test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy')
var view = _converse.chatboxviews.get('lounge@localhost'); .then(() => {
const view = _converse.chatboxviews.get('lounge@localhost');
spyOn(view, 'close').and.callThrough(); spyOn(view, 'close').and.callThrough();
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
spyOn(view.model, 'leave'); spyOn(view.model, 'leave');
@ -2089,6 +2091,7 @@
expect(view.model.leave).toHaveBeenCalled(); expect(view.model.leave).toHaveBeenCalled();
expect(_converse.emit).toHaveBeenCalledWith('chatBoxClosed', jasmine.any(Object)); expect(_converse.emit).toHaveBeenCalledWith('chatBoxClosed', jasmine.any(Object));
done(); done();
});
})); }));
}); });
@ -2953,20 +2956,20 @@
it("will first be added to the member list if the groupchat is members only", it("will first be added to the member list if the groupchat is members only",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
var sent_IQs = [], IQ_ids = []; var sent_IQs = [], IQ_ids = [];
var invitee_jid, sent_stanza, sent_id; let invitee_jid, sent_stanza, sent_id, view;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_IQs.push(iq); sent_IQs.push(iq);
IQ_ids.push(sendIQ.bind(this)(iq, callback, errback)); IQ_ids.push(sendIQ.bind(this)(iq, callback, errback));
}); });
_converse.api.rooms.open('coven@chat.shakespeare.lit', {'nick': 'dummy'}); _converse.api.rooms.open('coven@chat.shakespeare.lit', {'nick': 'dummy'})
.then(() => {
var view = _converse.chatboxviews.get('coven@chat.shakespeare.lit'); view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
spyOn(view.model, 'parseRoomFeatures').and.callThrough(); spyOn(view.model, 'parseRoomFeatures').and.callThrough();
// State that the chat is members-only via the features IQ // State that the chat is members-only via the features IQ
@ -2988,8 +2991,8 @@
.c('feature', {'var': 'muc_membersonly'}).up(); .c('feature', {'var': 'muc_membersonly'}).up();
_converse.connection._dataRecv(test_utils.createRequest(features_stanza)); _converse.connection._dataRecv(test_utils.createRequest(features_stanza));
test_utils.waitUntil(() => view.model.parseRoomFeatures.calls.count(), 300) return test_utils.waitUntil(() => view.model.parseRoomFeatures.calls.count(), 300);
.then(() => { }).then(() => {
expect(view.model.get('membersonly')).toBeTruthy(); expect(view.model.get('membersonly')).toBeTruthy();
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
@ -3174,10 +3177,12 @@
it("contains a link to a modal through which a new chatroom can be created", it("contains a link to a modal through which a new chatroom can be created",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.openControlBox(); test_utils.openControlBox();
_converse.emit('rosterContactsFetched');
var roomspanel = _converse.chatboxviews.get('controlbox').roomspanel; var roomspanel = _converse.chatboxviews.get('controlbox').roomspanel;
roomspanel.el.querySelector('.show-add-muc-modal').click(); roomspanel.el.querySelector('.show-add-muc-modal').click();
test_utils.closeControlBox(_converse); test_utils.closeControlBox(_converse);
@ -3193,6 +3198,8 @@
modal.el.querySelector('input[name="chatroom"]').value = 'lounce@muc.localhost'; modal.el.querySelector('input[name="chatroom"]').value = 'lounce@muc.localhost';
modal.el.querySelector('form input[type="submit"]').click(); modal.el.querySelector('form input[type="submit"]').click();
return test_utils.waitUntil(() => _converse.chatboxes.length);
}).then(() => {
expect($('.chatroom:visible').length).toBe(1); // There should now be an open chatroom expect($('.chatroom:visible').length).toBe(1); // There should now be an open chatroom
done(); done();
}).catch(_.partial(console.error, _)); }).catch(_.partial(console.error, _));
@ -3200,10 +3207,9 @@
it("contains a link to a modal which can list groupchats publically available on the server", it("contains a link to a modal which can list groupchats publically available on the server",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
var sent_stanza, IQ_id; var sent_stanza, IQ_id;
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
@ -3216,9 +3222,8 @@
roomspanel.el.querySelector('.show-list-muc-modal').click(); roomspanel.el.querySelector('.show-list-muc-modal').click();
test_utils.closeControlBox(_converse); test_utils.closeControlBox(_converse);
const modal = roomspanel.list_rooms_modal; const modal = roomspanel.list_rooms_modal;
test_utils.waitUntil(function () { test_utils.waitUntil(() => u.isVisible(modal.el), 1000)
return u.isVisible(modal.el); .then(() => {
}, 1000).then(function () {
spyOn(_converse.ChatRoom.prototype, 'getRoomFeatures').and.callFake(function () { spyOn(_converse.ChatRoom.prototype, 'getRoomFeatures').and.callFake(function () {
var deferred = new $.Deferred(); var deferred = new $.Deferred();
deferred.resolve(); deferred.resolve();
@ -3231,7 +3236,8 @@
const input = modal.el.querySelector('input[name="server"]').value = 'chat.shakespear.lit'; const input = modal.el.querySelector('input[name="server"]').value = 'chat.shakespear.lit';
modal.el.querySelector('input[type="submit"]').click(); modal.el.querySelector('input[type="submit"]').click();
return test_utils.waitUntil(() => _converse.chatboxes.length);
}).then(() => {
expect(sent_stanza.toLocaleString()).toBe( expect(sent_stanza.toLocaleString()).toBe(
"<iq to='chat.shakespear.lit' from='dummy@localhost/resource' type='get' xmlns='jabber:client' id='"+IQ_id+"'>"+ "<iq to='chat.shakespear.lit' from='dummy@localhost/resource' type='get' xmlns='jabber:client' id='"+IQ_id+"'>"+
"<query xmlns='http://jabber.org/protocol/disco#items'/>"+ "<query xmlns='http://jabber.org/protocol/disco#items'/>"+
@ -3260,6 +3266,8 @@
expect(rooms[4].textContent.trim()).toBe("Macbeth's Castle"); expect(rooms[4].textContent.trim()).toBe("Macbeth's Castle");
rooms[4].querySelector('.open-room').click(); rooms[4].querySelector('.open-room').click();
return test_utils.waitUntil(() => _converse.chatboxes.length > 1);
}).then(() => {
expect($('.chatroom:visible').length).toBe(1); // There should now be an open chatroom expect($('.chatroom:visible').length).toBe(1); // There should now be an open chatroom
var view = _converse.chatboxviews.get('inverness@chat.shakespeare.lit'); var view = _converse.chatboxviews.get('inverness@chat.shakespeare.lit');
expect(view.el.querySelector('.chat-head-chatroom').textContent.trim()).toBe("Macbeth's Castle"); expect(view.el.querySelector('.chat-head-chatroom').textContent.trim()).toBe("Macbeth's Castle");
@ -3509,10 +3517,11 @@
describe("A paused notification", function () { describe("A paused notification", function () {
it("will be shown if received", it("will be shown if received",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.openChatRoom(_converse, "coven", 'chat.shakespeare.lit', 'some1'); test_utils.openChatRoom(_converse, "coven", 'chat.shakespeare.lit', 'some1')
.then(() => {
var room_jid = 'coven@chat.shakespeare.lit'; var room_jid = 'coven@chat.shakespeare.lit';
var view = _converse.chatboxviews.get('coven@chat.shakespeare.lit'); var view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
var $chat_content = $(view.el).find('.chat-content'); var $chat_content = $(view.el).find('.chat-content');
@ -3645,6 +3654,7 @@
expect(notifications[0].textContent).toEqual('nomorenicks is typing'); expect(notifications[0].textContent).toEqual('nomorenicks is typing');
expect(notifications[1].textContent).toEqual('newguy has stopped typing'); expect(notifications[1].textContent).toEqual('newguy has stopped typing');
done(); done();
});
})); }));
}); });
}); });

View File

@ -225,25 +225,28 @@
[{'category': 'server', 'type':'IM'}], [{'category': 'server', 'type':'IM'}],
['http://jabber.org/protocol/disco#items'], [], 'info').then(function () { ['http://jabber.org/protocol/disco#items'], [], 'info').then(function () {
test_utils.waitUntilDiscoConfirmed(_converse, _converse.domain, [], [], ['upload.localhost'], 'items').then(function () { let contact_jid, view;
test_utils.waitUntilDiscoConfirmed(_converse, 'upload.localhost', [], [Strophe.NS.HTTPUPLOAD], []).then(function () {
test_utils.createContacts(_converse, 'current'); test_utils.waitUntilDiscoConfirmed(_converse, _converse.domain, [], [], ['upload.localhost'], 'items')
var contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost'; .then(() => test_utils.waitUntilDiscoConfirmed(_converse, 'upload.localhost', [], [Strophe.NS.HTTPUPLOAD], []))
test_utils.openChatBoxFor(_converse, contact_jid); .then(() => {
var view = _converse.chatboxviews.get(contact_jid); test_utils.createContacts(_converse, 'current', 3);
test_utils.waitUntil(function () { _converse.emit('rosterContactsFetched');
return view.el.querySelector('.upload-file');
}, 150).then(function () { contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost';
return test_utils.openChatBoxFor(_converse, contact_jid);
}).then(() => {
view = _converse.chatboxviews.get(contact_jid);
test_utils.waitUntil(() => view.el.querySelector('.upload-file'));
}).then(() => {
expect(view.el.querySelector('.chat-toolbar .upload-file')).not.toBe(null); expect(view.el.querySelector('.chat-toolbar .upload-file')).not.toBe(null);
done(); done();
}); });
}); });
});
});
})); }));
it("appears in MUC chats", mock.initConverseWithPromises( it("appears in MUC chats", mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.waitUntilDiscoConfirmed( test_utils.waitUntilDiscoConfirmed(
@ -251,19 +254,15 @@
[{'category': 'server', 'type':'IM'}], [{'category': 'server', 'type':'IM'}],
['http://jabber.org/protocol/disco#items'], [], 'info').then(function () { ['http://jabber.org/protocol/disco#items'], [], 'info').then(function () {
test_utils.waitUntilDiscoConfirmed(_converse, _converse.domain, [], [], ['upload.localhost'], 'items').then(function () { test_utils.waitUntilDiscoConfirmed(_converse, _converse.domain, [], [], ['upload.localhost'], 'items')
test_utils.waitUntilDiscoConfirmed(_converse, 'upload.localhost', [], [Strophe.NS.HTTPUPLOAD], []).then(function () { .then(() => test_utils.waitUntilDiscoConfirmed(_converse, 'upload.localhost', [], [Strophe.NS.HTTPUPLOAD], []))
test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () { .then(() => test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy'))
var view = _converse.chatboxviews.get('lounge@localhost'); .then(() => test_utils.waitUntil(() => _converse.chatboxviews.get('lounge@localhost').el.querySelector('.upload-file')))
test_utils.waitUntil(function () { .then(() => {
return view.el.querySelector('.upload-file'); const view = _converse.chatboxviews.get('lounge@localhost');
}).then(function () {
expect(view.el.querySelector('.chat-toolbar .upload-file')).not.toBe(null); expect(view.el.querySelector('.chat-toolbar .upload-file')).not.toBe(null);
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
});
});
});
}); });
})); }));
@ -277,12 +276,16 @@
var send_backup = XMLHttpRequest.prototype.send; var send_backup = XMLHttpRequest.prototype.send;
var IQ_stanzas = _converse.connection.IQ_stanzas; var IQ_stanzas = _converse.connection.IQ_stanzas;
let contact_jid;
test_utils.waitUntilDiscoConfirmed(_converse, _converse.domain, [], [], ['upload.montague.tld'], 'items').then(function () { test_utils.waitUntilDiscoConfirmed(_converse, _converse.domain, [], [], ['upload.montague.tld'], 'items')
test_utils.waitUntilDiscoConfirmed(_converse, 'upload.montague.tld', [], [Strophe.NS.HTTPUPLOAD], []).then(function () { .then(() => test_utils.waitUntilDiscoConfirmed(_converse, 'upload.montague.tld', [], [Strophe.NS.HTTPUPLOAD], []))
.then(() => {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
var contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost'; _converse.emit('rosterContactsFetched');
test_utils.openChatBoxFor(_converse, contact_jid); contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost';
return test_utils.openChatBoxFor(_converse, contact_jid);
}).then(() => {
var view = _converse.chatboxviews.get(contact_jid); var view = _converse.chatboxviews.get(contact_jid);
var file = { var file = {
'type': 'image/jpeg', 'type': 'image/jpeg',
@ -375,7 +378,6 @@
}); });
}); });
}); });
});
})); }));
it("is uploaded and sent out from a groupchat", mock.initConverseWithAsync(function (done, _converse) { it("is uploaded and sent out from a groupchat", mock.initConverseWithAsync(function (done, _converse) {
@ -487,18 +489,16 @@
}); });
})); }));
it("shows and error message if the file is too large", mock.initConverseWithAsync(function (done, _converse) { it("shows an error message if the file is too large", mock.initConverseWithAsync(function (done, _converse) {
var IQ_stanzas = _converse.connection.IQ_stanzas; const IQ_stanzas = _converse.connection.IQ_stanzas;
var IQ_ids = _converse.connection.IQ_ids; const IQ_ids = _converse.connection.IQ_ids;
var send_backup = XMLHttpRequest.prototype.send; const send_backup = XMLHttpRequest.prototype.send;
let view, contact_jid;
test_utils.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, [], []).then(function () { test_utils.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, [], [])
test_utils.waitUntil(function () { .then(() => test_utils.waitUntil(() => _.filter(
return _.filter(IQ_stanzas, function (iq) { IQ_stanzas, (iq) => iq.nodeTree.querySelector('iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]')).length
return iq.nodeTree.querySelector( )).then(() => {
'iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]');
}).length > 0;
}, 300).then(function () {
var stanza = _.find(IQ_stanzas, function (iq) { var stanza = _.find(IQ_stanzas, function (iq) {
return iq.nodeTree.querySelector( return iq.nodeTree.querySelector(
'iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]'); 'iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]');
@ -519,8 +519,8 @@
.c('feature', { .c('feature', {
'var': 'http://jabber.org/protocol/disco#items'}); 'var': 'http://jabber.org/protocol/disco#items'});
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
return _converse.api.disco.entities.get();
_converse.api.disco.entities.get().then(function(entities) { }).then(function (entities) {
expect(entities.length).toBe(2); expect(entities.length).toBe(2);
expect(_.includes(entities.pluck('jid'), 'localhost')).toBe(true); expect(_.includes(entities.pluck('jid'), 'localhost')).toBe(true);
expect(_.includes(entities.pluck('jid'), 'dummy@localhost')).toBe(true); expect(_.includes(entities.pluck('jid'), 'dummy@localhost')).toBe(true);
@ -535,7 +535,6 @@
return iq.nodeTree.querySelector('iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#items"]'); return iq.nodeTree.querySelector('iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#items"]');
}).length > 0; }).length > 0;
}, 300); }, 300);
});
}).then(function () { }).then(function () {
var stanza = _.find(IQ_stanzas, function (iq) { var stanza = _.find(IQ_stanzas, function (iq) {
return iq.nodeTree.querySelector('iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#items"]'); return iq.nodeTree.querySelector('iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#items"]');
@ -550,6 +549,7 @@
.c('item', { .c('item', {
'jid': 'upload.localhost', 'jid': 'upload.localhost',
'name': 'HTTP File Upload'}); 'name': 'HTTP File Upload'});
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
_converse.api.disco.entities.get().then(function (entities) { _converse.api.disco.entities.get().then(function (entities) {
@ -584,15 +584,18 @@
.c('field', {'var':'max-file-size'}) .c('field', {'var':'max-file-size'})
.c('value').t('5242880'); .c('value').t('5242880');
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
return _converse.api.disco.entities.get();
_converse.api.disco.entities.get().then(function (entities) { }).then(function (entities) {
expect(entities.get('localhost').items.get('upload.localhost').identities.where({'category': 'store'}).length).toBe(1); expect(entities.get('localhost').items.get('upload.localhost').identities.where({'category': 'store'}).length).toBe(1);
_converse.api.disco.supports(Strophe.NS.HTTPUPLOAD, _converse.domain).then( return _converse.api.disco.supports(Strophe.NS.HTTPUPLOAD, _converse.domain);
function (result) { }).then(function (result) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
var contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost'; _converse.emit('rosterContactsFetched');
test_utils.openChatBoxFor(_converse, contact_jid);
var view = _converse.chatboxviews.get(contact_jid); contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost';
return test_utils.openChatBoxFor(_converse, contact_jid);
}).then(() => {
view = _converse.chatboxviews.get(contact_jid);
var file = { var file = {
'type': 'image/jpeg', 'type': 'image/jpeg',
'size': '5242881', 'size': '5242881',
@ -600,27 +603,23 @@
'name': "my-juliet.jpg" 'name': "my-juliet.jpg"
}; };
view.model.sendFiles([file]); view.model.sendFiles([file]);
return test_utils.waitUntil(function () { return test_utils.waitUntil(() => view.el.querySelectorAll('.message').length)
return view.el.querySelectorAll('.message').length;
}).then(function () { }).then(function () {
const messages = view.el.querySelectorAll('.message.chat-error'); const messages = view.el.querySelectorAll('.message.chat-error');
expect(messages.length).toBe(1); expect(messages.length).toBe(1);
expect(messages[0].textContent).toBe( expect(messages[0].textContent).toBe(
'The size of your file, my-juliet.jpg, exceeds the maximum allowed by your server, which is 5 MB.'); 'The size of your file, my-juliet.jpg, exceeds the maximum allowed by your server, which is 5 MB.');
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
}
);
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
})
});
})); }));
}); });
}); });
describe("While a file is being uploaded", function () { describe("While a file is being uploaded", function () {
it("shows a progress bar", mock.initConverseWithAsync(function (done, _converse) { it("shows a progress bar", mock.initConverseWithPromises(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, function (done, _converse) {
test_utils.waitUntilDiscoConfirmed( test_utils.waitUntilDiscoConfirmed(
_converse, _converse.domain, _converse, _converse.domain,
[{'category': 'server', 'type':'IM'}], [{'category': 'server', 'type':'IM'}],
@ -628,26 +627,28 @@
var send_backup = XMLHttpRequest.prototype.send; var send_backup = XMLHttpRequest.prototype.send;
var IQ_stanzas = _converse.connection.IQ_stanzas; var IQ_stanzas = _converse.connection.IQ_stanzas;
let view, contact_jid;
test_utils.waitUntilDiscoConfirmed(_converse, _converse.domain, [], [], ['upload.montague.tld'], 'items').then(function () { test_utils.waitUntilDiscoConfirmed(_converse, _converse.domain, [], [], ['upload.montague.tld'], 'items')
test_utils.waitUntilDiscoConfirmed(_converse, 'upload.montague.tld', [], [Strophe.NS.HTTPUPLOAD], []).then(function () { .then(() => test_utils.waitUntilDiscoConfirmed(_converse, 'upload.montague.tld', [], [Strophe.NS.HTTPUPLOAD], []))
.then(() => {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
var contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost'; _converse.emit('rosterContactsFetched');
test_utils.openChatBoxFor(_converse, contact_jid);
var view = _converse.chatboxviews.get(contact_jid); contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost';
var file = { return test_utils.openChatBoxFor(_converse, contact_jid);
}).then(() => {
view = _converse.chatboxviews.get(contact_jid);
const file = {
'type': 'image/jpeg', 'type': 'image/jpeg',
'size': '23456' , 'size': '23456' ,
'lastModifiedDate': "", 'lastModifiedDate': "",
'name': "my-juliet.jpg" 'name': "my-juliet.jpg"
}; };
view.model.sendFiles([file]); view.model.sendFiles([file]);
return test_utils.waitUntil(function () { return test_utils.waitUntil(() => _.filter(IQ_stanzas, (iq) => iq.nodeTree.querySelector('iq[to="upload.montague.tld"] request')).length)
return _.filter(IQ_stanzas, function (iq) {
return iq.nodeTree.querySelector('iq[to="upload.montague.tld"] request');
}).length > 0;
}).then(function () { }).then(function () {
var iq = IQ_stanzas.pop(); const iq = IQ_stanzas.pop();
expect(iq.toLocaleString()).toBe( expect(iq.toLocaleString()).toBe(
"<iq from='dummy@localhost/resource' "+ "<iq from='dummy@localhost/resource' "+
"to='upload.montague.tld' "+ "to='upload.montague.tld' "+
@ -660,10 +661,9 @@
"content-type='image/jpeg'/>"+ "content-type='image/jpeg'/>"+
"</iq>"); "</iq>");
var base_url = document.URL.split(window.location.pathname)[0]; const base_url = document.URL.split(window.location.pathname)[0];
var message = base_url+"/logo/conversejs-filled.svg"; const message = base_url+"/logo/conversejs-filled.svg";
const stanza = Strophe.xmlHtmlNode(
var stanza = Strophe.xmlHtmlNode(
"<iq from='upload.montague.tld'"+ "<iq from='upload.montague.tld'"+
" id='"+iq.nodeTree.getAttribute('id')+"'"+ " id='"+iq.nodeTree.getAttribute('id')+"'"+
" to='dummy@localhost/resource'"+ " to='dummy@localhost/resource'"+
@ -676,7 +676,6 @@
" <get url='"+message+"' />"+ " <get url='"+message+"' />"+
"</slot>"+ "</slot>"+
"</iq>").firstElementChild; "</iq>").firstElementChild;
spyOn(XMLHttpRequest.prototype, 'send').and.callFake(function () { spyOn(XMLHttpRequest.prototype, 'send').and.callFake(function () {
const message = view.model.messages.at(0); const message = view.model.messages.at(0);
expect(view.el.querySelector('.chat-content progress').getAttribute('value')).toBe('0'); expect(view.el.querySelector('.chat-content progress').getAttribute('value')).toBe('0');
@ -694,11 +693,8 @@
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
}); });
}); });
});
});
})); }));
}); });
}); });
}); });
})); }));

View File

@ -21,14 +21,15 @@
it("can be sent as a correction by clicking the pencil icon", it("can be sent as a correction by clicking the pencil icon",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current', 1); test_utils.createContacts(_converse, 'current', 1);
_converse.emit('rosterContactsFetched');
test_utils.openControlBox(); test_utils.openControlBox();
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
.then(() => {
const view = _converse.chatboxviews.get(contact_jid); const view = _converse.chatboxviews.get(contact_jid);
const textarea = view.el.querySelector('textarea.chat-textarea'); const textarea = view.el.querySelector('textarea.chat-textarea');
@ -115,19 +116,21 @@
); );
expect(view.el.querySelectorAll('.chat-msg .chat-msg__action').length).toBe(1); expect(view.el.querySelectorAll('.chat-msg .chat-msg__action').length).toBe(1);
done(); done();
});
})); }));
it("can be sent as a correction by using the up arrow", it("can be sent as a correction by using the up arrow",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current', 1); test_utils.createContacts(_converse, 'current', 1);
_converse.emit('rosterContactsFetched');
test_utils.openControlBox(); test_utils.openControlBox();
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
.then(() => {
const view = _converse.chatboxviews.get(contact_jid); const view = _converse.chatboxviews.get(contact_jid);
const textarea = view.el.querySelector('textarea.chat-textarea'); const textarea = view.el.querySelector('textarea.chat-textarea');
expect(textarea.value).toBe(''); expect(textarea.value).toBe('');
@ -262,6 +265,7 @@
expect(view.model.messages.at(1).get('correcting')).toBeFalsy(); expect(view.model.messages.at(1).get('correcting')).toBeFalsy();
expect(view.model.messages.at(2).get('correcting')).toBeFalsy(); expect(view.model.messages.at(2).get('correcting')).toBeFalsy();
done(); done();
});
})); }));
@ -321,15 +325,16 @@
it("can be replaced with a correction", it("can be replaced with a correction",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current', 1); test_utils.createContacts(_converse, 'current', 1);
_converse.emit('rosterContactsFetched');
test_utils.openControlBox(); test_utils.openControlBox();
const message = 'This is a received message'; const message = 'This is a received message';
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, sender_jid); test_utils.openChatBoxFor(_converse, sender_jid)
.then(() => {
const msg_id = u.getUniqueId(); const msg_id = u.getUniqueId();
_converse.chatboxes.onMessage($msg({ _converse.chatboxes.onMessage($msg({
'from': sender_jid, 'from': sender_jid,
@ -381,6 +386,7 @@
expect(older_msgs[1].textContent).toBe('But soft, what light through yonder chimney breaks?'); expect(older_msgs[1].textContent).toBe('But soft, what light through yonder chimney breaks?');
done(); done();
}); });
});
})); }));
describe("when a chatbox is opened for someone who is not in the roster", function () { describe("when a chatbox is opened for someone who is not in the roster", function () {
@ -500,10 +506,11 @@
it("will have the error message displayed after itself", it("will have the error message displayed after itself",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched');
test_utils.openControlBox(); test_utils.openControlBox();
// TODO: what could still be done for error // TODO: what could still be done for error
@ -524,7 +531,8 @@
var sender_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost'; var sender_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost';
var fullname = _converse.xmppstatus.get('fullname'); var fullname = _converse.xmppstatus.get('fullname');
fullname = _.isEmpty(fullname)? _converse.bare_jid: fullname; fullname = _.isEmpty(fullname)? _converse.bare_jid: fullname;
_converse.api.chats.open(sender_jid); _converse.api.chats.open(sender_jid)
.then(() => {
var msg_text = 'This message will not be sent, due to an error'; var msg_text = 'This message will not be sent, due to an error';
var view = _converse.chatboxviews.get(sender_jid); var view = _converse.chatboxviews.get(sender_jid);
var message = view.model.messages.create({ var message = view.model.messages.create({
@ -621,25 +629,28 @@
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
expect($chat_content.find('.chat-error').length).toEqual(3); expect($chat_content.find('.chat-error').length).toEqual(3);
done(); done();
});
})); }));
}); });
it("will cause the chat area to be scrolled down only if it was at the bottom originally", it("will cause the chat area to be scrolled down only if it was at the bottom originally",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched');
test_utils.openControlBox(); test_utils.openControlBox();
var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; let chatboxview;
test_utils.openChatBoxFor(_converse, sender_jid); const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
const message = 'This message is received while the chat area is scrolled up';
var chatboxview = _converse.chatboxviews.get(sender_jid); test_utils.openChatBoxFor(_converse, sender_jid)
.then(() => {
chatboxview = _converse.chatboxviews.get(sender_jid);
spyOn(chatboxview, 'onScrolledDown').and.callThrough(); spyOn(chatboxview, 'onScrolledDown').and.callThrough();
// Create enough messages so that there's a scrollbar. // Create enough messages so that there's a scrollbar.
var message = 'This message is received while the chat area is scrolled up';
for (var i=0; i<20; i++) { for (var i=0; i<20; i++) {
_converse.chatboxes.onMessage($msg({ _converse.chatboxes.onMessage($msg({
from: sender_jid, from: sender_jid,
@ -649,18 +660,12 @@
}).c('body').t('Message: '+i).up() }).c('body').t('Message: '+i).up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
} }
return test_utils.waitUntil(function () { return test_utils.waitUntil(() => chatboxview.content.scrollTop, 1000)
return chatboxview.content.scrollTop; .then(() => test_utils.waitUntil(() => !chatboxview.model.get('auto_scrolled'), 500))
}, 1000).then(function () { }).then(() => {
return test_utils.waitUntil(function () {
return !chatboxview.model.get('auto_scrolled');
}, 500);
}).then(function () {
chatboxview.content.scrollTop = 0; chatboxview.content.scrollTop = 0;
return test_utils.waitUntil(function () { return test_utils.waitUntil(() => chatboxview.model.get('scrolled'), 900);
return chatboxview.model.get('scrolled'); }).then(() => {
}, 900);
}).then(function () {
_converse.chatboxes.onMessage($msg({ _converse.chatboxes.onMessage($msg({
from: sender_jid, from: sender_jid,
to: _converse.connection.jid, to: _converse.connection.jid,
@ -1109,23 +1114,22 @@
it("received for a minimized chat box will increment a counter on its header", it("received for a minimized chat box will increment a counter on its header",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
if (_converse.view_mode === 'fullscreen') { if (_converse.view_mode === 'fullscreen') {
return done(); return done();
} }
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched');
const contact_name = mock.cur_names[0];
const contact_jid = contact_name.replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.waitUntil(function () {
return $(_converse.rosterview.el).find('.roster-group').length;
}, 300)
.then(function () {
var contact_name = mock.cur_names[0];
var contact_jid = contact_name.replace(/ /g,'.').toLowerCase() + '@localhost';
spyOn(_converse, 'emit').and.callThrough(); spyOn(_converse, 'emit').and.callThrough();
test_utils.openChatBoxFor(_converse, contact_jid);
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); var chatview = _converse.chatboxviews.get(contact_jid);
expect(u.isVisible(chatview.el)).toBeTruthy(); expect(u.isVisible(chatview.el)).toBeTruthy();
expect(chatview.model.get('minimized')).toBeFalsy(); expect(chatview.model.get('minimized')).toBeFalsy();
@ -1171,19 +1175,18 @@
it("will indicate when it has a time difference of more than a day between it and its predecessor", it("will indicate when it has a time difference of more than a day between it and its predecessor",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.waitUntil(function () {
return $(_converse.rosterview.el).find('.roster-group').length;
}, 300)
.then(function () {
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
var contact_name = mock.cur_names[1]; const contact_name = mock.cur_names[1];
var contact_jid = contact_name.replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = contact_name.replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length)
.then(() => test_utils.openChatBoxFor(_converse, contact_jid))
.then(() => {
test_utils.clearChatBoxMessages(_converse, contact_jid); test_utils.clearChatBoxMessages(_converse, contact_jid);
var one_day_ago = moment(); var one_day_ago = moment();
one_day_ago.subtract('days', 1); one_day_ago.subtract('days', 1);
@ -1270,18 +1273,20 @@
it("can be sent from a chatbox, and will appear inside it", it("can be sent from a chatbox, and will appear inside it",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched');
test_utils.openControlBox(); test_utils.openControlBox();
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
.then(() => {
expect(_converse.emit).toHaveBeenCalledWith('chatBoxFocused', jasmine.any(Object)); expect(_converse.emit).toHaveBeenCalledWith('chatBoxFocused', jasmine.any(Object));
var view = _converse.chatboxviews.get(contact_jid); const view = _converse.chatboxviews.get(contact_jid);
var message = 'This message is sent from this chatbox'; const message = 'This message is sent from this chatbox';
spyOn(view.model, 'sendMessage').and.callThrough(); spyOn(view.model, 'sendMessage').and.callThrough();
test_utils.sendMessage(view, message); test_utils.sendMessage(view, message);
expect(view.model.sendMessage).toHaveBeenCalled(); expect(view.model.sendMessage).toHaveBeenCalled();
@ -1289,61 +1294,70 @@
expect(_converse.emit.calls.mostRecent().args, ['messageSend', message]); expect(_converse.emit.calls.mostRecent().args, ['messageSend', message]);
expect($(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg__text').text()).toEqual(message); expect($(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg__text').text()).toEqual(message);
done(); done();
});
})); }));
it("is sanitized to prevent Javascript injection attacks", it("is sanitized to prevent Javascript injection attacks",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched');
test_utils.openControlBox(); test_utils.openControlBox();
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
var view = _converse.chatboxviews.get(contact_jid); .then(() => {
var message = '<p>This message contains <em>some</em> <b>markup</b></p>'; const view = _converse.chatboxviews.get(contact_jid);
const message = '<p>This message contains <em>some</em> <b>markup</b></p>';
spyOn(view.model, 'sendMessage').and.callThrough(); spyOn(view.model, 'sendMessage').and.callThrough();
test_utils.sendMessage(view, message); test_utils.sendMessage(view, message);
expect(view.model.sendMessage).toHaveBeenCalled(); expect(view.model.sendMessage).toHaveBeenCalled();
var msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg__text'); const msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg__text');
expect(msg.text()).toEqual(message); expect(msg.text()).toEqual(message);
expect(msg.html()).toEqual('&lt;p&gt;This message contains &lt;em&gt;some&lt;/em&gt; &lt;b&gt;markup&lt;/b&gt;&lt;/p&gt;'); expect(msg.html()).toEqual('&lt;p&gt;This message contains &lt;em&gt;some&lt;/em&gt; &lt;b&gt;markup&lt;/b&gt;&lt;/p&gt;');
done(); done();
});
})); }));
it("can contain hyperlinks, which will be clickable", it("can contain hyperlinks, which will be clickable",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched');
test_utils.openControlBox(); test_utils.openControlBox();
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
var view = _converse.chatboxviews.get(contact_jid); .then(() => {
var message = 'This message contains a hyperlink: www.opkode.com'; const view = _converse.chatboxviews.get(contact_jid);
const message = 'This message contains a hyperlink: www.opkode.com';
spyOn(view.model, 'sendMessage').and.callThrough(); spyOn(view.model, 'sendMessage').and.callThrough();
test_utils.sendMessage(view, message); test_utils.sendMessage(view, message);
expect(view.model.sendMessage).toHaveBeenCalled(); expect(view.model.sendMessage).toHaveBeenCalled();
var msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg__text'); const msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg__text');
expect(msg.text()).toEqual(message); expect(msg.text()).toEqual(message);
expect(msg.html()).toEqual('This message contains a hyperlink: <a target="_blank" rel="noopener" href="http://www.opkode.com">www.opkode.com</a>'); expect(msg.html()).toEqual('This message contains a hyperlink: <a target="_blank" rel="noopener" href="http://www.opkode.com">www.opkode.com</a>');
done(); done();
});
})); }));
it("will have properly escaped URLs", it("will have properly escaped URLs",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched');
test_utils.openControlBox(); test_utils.openControlBox();
var message, msg; let message, msg;
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
.then(() => {
var view = _converse.chatboxviews.get(contact_jid); var view = _converse.chatboxviews.get(contact_jid);
spyOn(view.model, 'sendMessage').and.callThrough(); spyOn(view.model, 'sendMessage').and.callThrough();
message = "http://www.opkode.com/'onmouseover='alert(1)'whatever"; message = "http://www.opkode.com/'onmouseover='alert(1)'whatever";
@ -1376,10 +1390,14 @@
expect(msg.text()).toEqual(message); expect(msg.text()).toEqual(message);
expect(msg.html()).toEqual('<a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Ender%27s_Game">'+message+'</a>'); expect(msg.html()).toEqual('<a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Ender%27s_Game">'+message+'</a>');
done(); done();
});
})); }));
it("will render newlines", mock.initConverseWithPromises(null, ['rosterGroupsFetched'], {}, function (done, _converse) { it("will render newlines",
mock.initConverseWithPromises(null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched');
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid);
@ -1417,19 +1435,22 @@
it("will render images from their URLs", it("will render images from their URLs",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current', 1); test_utils.createContacts(_converse, 'current', 1);
_converse.emit('rosterContactsFetched');
const base_url = document.URL.split(window.location.pathname)[0]; const base_url = document.URL.split(window.location.pathname)[0];
let message = base_url+"/logo/conversejs-filled.svg"; let message = base_url+"/logo/conversejs-filled.svg";
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); let view;
const view = _converse.chatboxviews.get(contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
.then(() => {
view = _converse.chatboxviews.get(contact_jid);
spyOn(view.model, 'sendMessage').and.callThrough(); spyOn(view.model, 'sendMessage').and.callThrough();
test_utils.sendMessage(view, message); test_utils.sendMessage(view, message);
return test_utils.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-image').length, 1000)
test_utils.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-image').length, 1000).then(() => { }).then(() => {
expect(view.model.sendMessage).toHaveBeenCalled(); expect(view.model.sendMessage).toHaveBeenCalled();
const msg = $(view.el).find('.chat-content .chat-msg').last().find('.chat-msg__text'); const msg = $(view.el).find('.chat-content .chat-msg').last().find('.chat-msg__text');
expect(msg.html().trim()).toEqual( expect(msg.html().trim()).toEqual(
@ -1462,29 +1483,32 @@
it("will render the message time as configured", it("will render the message time as configured",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'],
function (done, _converse) { {}, function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched');
_converse.time_format = 'hh:mm'; _converse.time_format = 'hh:mm';
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
var view = _converse.chatboxviews.get(contact_jid); .then(() => {
var message = 'This message is sent from this chatbox'; const view = _converse.chatboxviews.get(contact_jid);
const message = 'This message is sent from this chatbox';
test_utils.sendMessage(view, message); test_utils.sendMessage(view, message);
var chatbox = _converse.chatboxes.get(contact_jid); const chatbox = _converse.chatboxes.get(contact_jid);
expect(chatbox.messages.models.length, 1); expect(chatbox.messages.models.length, 1);
var msg_object = chatbox.messages.models[0]; const msg_object = chatbox.messages.models[0];
var msg_author = view.el.querySelector('.chat-content .chat-msg:last-child .chat-msg__author'); const msg_author = view.el.querySelector('.chat-content .chat-msg:last-child .chat-msg__author');
expect(msg_author.textContent.trim()).toBe('Max Mustermann'); expect(msg_author.textContent.trim()).toBe('Max Mustermann');
var msg_time = view.el.querySelector('.chat-content .chat-msg:last-child .chat-msg__time'); const msg_time = view.el.querySelector('.chat-content .chat-msg:last-child .chat-msg__time');
var time = moment(msg_object.get('time')).format(_converse.time_format); const time = moment(msg_object.get('time')).format(_converse.time_format);
expect(msg_time.textContent).toBe(time); expect(msg_time.textContent).toBe(time);
done(); done();
});
})); }));
it("will be correctly identified and rendered as a followup message", it("will be correctly identified and rendered as a followup message",
@ -1655,17 +1679,20 @@
})); }));
describe("which contains a OOB URL", function () { describe("which contains an OOB URL", function () {
it("will render audio from oob mp3 URLs", it("will render audio from oob mp3 URLs",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current', 1); test_utils.createContacts(_converse, 'current', 1);
_converse.emit('rosterContactsFetched');
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); let view;
const view = _converse.chatboxviews.get(contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
.then(() => {
view = _converse.chatboxviews.get(contact_jid);
spyOn(view.model, 'sendMessage').and.callThrough(); spyOn(view.model, 'sendMessage').and.callThrough();
const stanza = Strophe.xmlHtmlNode( const stanza = Strophe.xmlHtmlNode(
@ -1674,10 +1701,11 @@
" to='dummy@localhost/resource'>"+ " to='dummy@localhost/resource'>"+
" <body>Have you heard this funny audio?</body>"+ " <body>Have you heard this funny audio?</body>"+
" <x xmlns='jabber:x:oob'><url>http://localhost/audio.mp3</url></x>"+ " <x xmlns='jabber:x:oob'><url>http://localhost/audio.mp3</url></x>"+
"</message>").firstChild; "</message>").firstChild
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
test_utils.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-msg audio').length, 1000).then(function () { 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'); let msg = view.el.querySelector('.chat-msg .chat-msg__text');
expect(msg.outerHTML).toEqual('<div class="chat-msg__text">Have you heard this funny audio?</div>'); expect(msg.outerHTML).toEqual('<div class="chat-msg__text">Have you heard this funny audio?</div>');
let media = view.el.querySelector('.chat-msg .chat-msg__media'); let media = view.el.querySelector('.chat-msg .chat-msg__media');
@ -1709,12 +1737,14 @@
it("will render video from oob mp4 URLs", it("will render video from oob mp4 URLs",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched');
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
.then(() => {
const view = _converse.chatboxviews.get(contact_jid); const view = _converse.chatboxviews.get(contact_jid);
spyOn(view.model, 'sendMessage').and.callThrough(); spyOn(view.model, 'sendMessage').and.callThrough();
@ -1755,17 +1785,21 @@
'<a target="_blank" rel="noopener" href="http://localhost/video.mp4">Download video file</a>'); '<a target="_blank" rel="noopener" href="http://localhost/video.mp4">Download video file</a>');
done(); done();
}); });
});
})); }));
it("will render download links for files from oob URLs", it("will render download links for files from oob URLs",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current', 1); test_utils.createContacts(_converse, 'current', 1);
_converse.emit('rosterContactsFetched');
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); let view;
const view = _converse.chatboxviews.get(contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
.then(() => {
view = _converse.chatboxviews.get(contact_jid);
spyOn(view.model, 'sendMessage').and.callThrough(); spyOn(view.model, 'sendMessage').and.callThrough();
const stanza = Strophe.xmlHtmlNode( const stanza = Strophe.xmlHtmlNode(
@ -1777,7 +1811,8 @@
"</message>").firstChild; "</message>").firstChild;
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
test_utils.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-msg a').length, 1000).then(function () { test_utils.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-msg a').length, 1000);
}).then(function () {
const msg = view.el.querySelector('.chat-msg .chat-msg__text'); const msg = view.el.querySelector('.chat-msg .chat-msg__text');
expect(msg.outerHTML).toEqual('<div class="chat-msg__text">Have you downloaded this funny file?</div>'); expect(msg.outerHTML).toEqual('<div class="chat-msg__text">Have you downloaded this funny file?</div>');
const media = view.el.querySelector('.chat-msg .chat-msg__media'); const media = view.el.querySelector('.chat-msg .chat-msg__media');
@ -1790,13 +1825,16 @@
it("will render images from oob URLs", it("will render images from oob URLs",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched');
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); let view;
const view = _converse.chatboxviews.get(contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
.then(() => {
view = _converse.chatboxviews.get(contact_jid);
spyOn(view.model, 'sendMessage').and.callThrough(); spyOn(view.model, 'sendMessage').and.callThrough();
const base_url = document.URL.split(window.location.pathname)[0]; const base_url = document.URL.split(window.location.pathname)[0];
const url = base_url+"/logo/conversejs-filled.svg"; const url = base_url+"/logo/conversejs-filled.svg";
@ -1809,8 +1847,8 @@
" <x xmlns='jabber:x:oob'><url>"+url+"</url></x>"+ " <x xmlns='jabber:x:oob'><url>"+url+"</url></x>"+
"</message>").firstChild; "</message>").firstChild;
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
return test_utils.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-msg img').length, 2000);
test_utils.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-msg img').length, 2000).then(function () { }).then(function () {
const msg = view.el.querySelector('.chat-msg .chat-msg__text'); const msg = view.el.querySelector('.chat-msg .chat-msg__text');
expect(msg.outerHTML).toEqual('<div class="chat-msg__text">Have you seen this funny image?</div>'); expect(msg.outerHTML).toEqual('<div class="chat-msg__text">Have you seen this funny image?</div>');
const media = view.el.querySelector('.chat-msg .chat-msg__media'); const media = view.el.querySelector('.chat-msg .chat-msg__media');

View File

@ -13,13 +13,16 @@
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched');
test_utils.openControlBox(); test_utils.openControlBox();
_converse.minimized_chats.toggleview.model.browserStorage._clear(); _converse.minimized_chats.toggleview.model.browserStorage._clear();
_converse.minimized_chats.initToggle(); _converse.minimized_chats.initToggle();
var contact_jid, chatview; let contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; let chatview;
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
.then(() => {
chatview = _converse.chatboxviews.get(contact_jid); chatview = _converse.chatboxviews.get(contact_jid);
expect(chatview.model.get('minimized')).toBeFalsy(); expect(chatview.model.get('minimized')).toBeFalsy();
expect($(_converse.minimized_chats.el).is(':visible')).toBeFalsy(); expect($(_converse.minimized_chats.el).is(':visible')).toBeFalsy();
@ -30,7 +33,8 @@
expect(_converse.minimized_chats.keys()[0]).toBe(contact_jid); expect(_converse.minimized_chats.keys()[0]).toBe(contact_jid);
contact_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost'; contact_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); return test_utils.openChatBoxFor(_converse, contact_jid);
}).then(() => {
chatview = _converse.chatboxviews.get(contact_jid); chatview = _converse.chatboxviews.get(contact_jid);
expect(chatview.model.get('minimized')).toBeFalsy(); expect(chatview.model.get('minimized')).toBeFalsy();
chatview.el.querySelector('.toggle-chatbox-button').click(); chatview.el.querySelector('.toggle-chatbox-button').click();
@ -39,6 +43,7 @@
expect(_converse.minimized_chats.keys().length).toBe(2); expect(_converse.minimized_chats.keys().length).toBe(2);
expect(_.includes(_converse.minimized_chats.keys(), contact_jid)).toBeTruthy(); expect(_.includes(_converse.minimized_chats.keys(), contact_jid)).toBeTruthy();
done(); done();
});
})); }));
it("can be toggled to hide or show minimized chats", it("can be toggled to hide or show minimized chats",
@ -47,24 +52,26 @@
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched');
test_utils.openControlBox(); test_utils.openControlBox();
_converse.minimized_chats.toggleview.model.browserStorage._clear(); _converse.minimized_chats.toggleview.model.browserStorage._clear();
_converse.minimized_chats.initToggle(); _converse.minimized_chats.initToggle();
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
var chatview = _converse.chatboxviews.get(contact_jid); .then(() => {
expect($(_converse.minimized_chats.el).is(':visible')).toBeFalsy(); const chatview = _converse.chatboxviews.get(contact_jid);
expect(u.isVisible(_converse.minimized_chats.el)).toBeFalsy();
chatview.model.set({'minimized': true}); chatview.model.set({'minimized': true});
expect($(_converse.minimized_chats.el).is(':visible')).toBeTruthy(); expect(u.isVisible(_converse.minimized_chats.el)).toBeTruthy();
expect(_converse.minimized_chats.keys().length).toBe(1); expect(_converse.minimized_chats.keys().length).toBe(1);
expect(_converse.minimized_chats.keys()[0]).toBe(contact_jid); expect(_converse.minimized_chats.keys()[0]).toBe(contact_jid);
expect($(_converse.minimized_chats.el.querySelector('.minimized-chats-flyout')).is(':visible')).toBeTruthy(); expect(u.isVisible(_converse.minimized_chats.el.querySelector('.minimized-chats-flyout'))).toBeTruthy();
expect(_converse.minimized_chats.toggleview.model.get('collapsed')).toBeFalsy(); expect(_converse.minimized_chats.toggleview.model.get('collapsed')).toBeFalsy();
_converse.minimized_chats.el.querySelector('#toggle-minimized-chats').click(); _converse.minimized_chats.el.querySelector('#toggle-minimized-chats').click();
return test_utils.waitUntil(() => u.isVisible(_converse.minimized_chats.el.querySelector('.minimized-chats-flyout')));
return test_utils.waitUntil(() => u.isVisible(u.isVisible(_converse.minimized_chats.el.querySelector('.minimized-chats-flyout')))) }).then(() => {
.then(function () {
expect(_converse.minimized_chats.toggleview.model.get('collapsed')).toBeTruthy(); expect(_converse.minimized_chats.toggleview.model.get('collapsed')).toBeTruthy();
done(); done();
}); });

View File

@ -12,25 +12,26 @@
describe("A list of open rooms", function () { describe("A list of open rooms", function () {
it("is shown in the \"Rooms\" panel", mock.initConverseWithPromises( it("is shown in the \"Rooms\" panel", mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], null, ['rosterGroupsFetched', 'chatBoxesFetched'],
{ allow_bookmarks: false // Makes testing easier, otherwise we { allow_bookmarks: false // Makes testing easier, otherwise we
// have to mock stanza traffic. // have to mock stanza traffic.
}, },
function (done, _converse) { function (done, _converse) {
test_utils.openControlBox(); test_utils.openControlBox();
var controlbox = _converse.chatboxviews.get('controlbox'); const controlbox = _converse.chatboxviews.get('controlbox');
let list = controlbox.el.querySelector('div.rooms-list-container');
var list = controlbox.el.querySelector('div.rooms-list-container');
expect(_.includes(list.classList, 'hidden')).toBeTruthy(); expect(_.includes(list.classList, 'hidden')).toBeTruthy();
test_utils.openChatRoom(_converse, 'room', 'conference.shakespeare.lit', 'JC'); let room_els;
test_utils.openChatRoom(_converse, 'room', 'conference.shakespeare.lit', 'JC')
.then(() => {
expect(_.isUndefined(_converse.rooms_list_view)).toBeFalsy(); expect(_.isUndefined(_converse.rooms_list_view)).toBeFalsy();
var room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room"); room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room");
expect(room_els.length).toBe(1); expect(room_els.length).toBe(1);
expect(room_els[0].innerText).toBe('room@conference.shakespeare.lit'); expect(room_els[0].innerText).toBe('room@conference.shakespeare.lit');
return test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy');
test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy'); }).then(() => {
room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room"); room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room");
expect(room_els.length).toBe(2); expect(room_els.length).toBe(2);
@ -50,6 +51,7 @@
list = controlbox.el.querySelector('div.rooms-list-container'); list = controlbox.el.querySelector('div.rooms-list-container');
expect(_.includes(list.classList, 'hidden')).toBeTruthy(); expect(_.includes(list.classList, 'hidden')).toBeTruthy();
done(); done();
});
} }
)); ));
}); });
@ -57,26 +59,26 @@
describe("A groupchat shown in the groupchats list", function () { describe("A groupchat shown in the groupchats list", function () {
it("is highlighted if its currently open", mock.initConverseWithPromises( it("is highlighted if its currently open", mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], null, ['rosterGroupsFetched', 'chatBoxesFetched'],
{ whitelisted_plugins: ['converse-roomslist'], { whitelisted_plugins: ['converse-roomslist'],
allow_bookmarks: false // Makes testing easier, otherwise we allow_bookmarks: false // Makes testing easier, otherwise we
// have to mock stanza traffic. // have to mock stanza traffic.
}, function (done, _converse) { }, function (done, _converse) {
spyOn(_converse, 'isSingleton').and.callFake(function () { spyOn(_converse, 'isSingleton').and.callFake(() => true);
return true;
});
let room_els, item;
test_utils.openControlBox(); test_utils.openControlBox();
_converse.api.rooms.open('coven@chat.shakespeare.lit', {'nick': 'some1'}); _converse.api.rooms.open('coven@chat.shakespeare.lit', {'nick': 'some1'})
let room_els = _converse.rooms_list_view.el.querySelectorAll(".available-chatroom"); .then(() => {
room_els = _converse.rooms_list_view.el.querySelectorAll(".available-chatroom");
expect(room_els.length).toBe(1); expect(room_els.length).toBe(1);
let item = room_els[0]; item = room_els[0];
expect(u.hasClass('open', item)).toBe(true); expect(u.hasClass('open', item)).toBe(true);
expect(item.textContent.trim()).toBe('coven@chat.shakespeare.lit'); expect(item.textContent.trim()).toBe('coven@chat.shakespeare.lit');
return _converse.api.rooms.open('balcony@chat.shakespeare.lit', {'nick': 'some1'});
_converse.api.rooms.open('balcony@chat.shakespeare.lit', {'nick': 'some1'}); }).then(() => {
room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room"); room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room");
expect(room_els.length).toBe(2); expect(room_els.length).toBe(2);
@ -85,18 +87,21 @@
item = room_els[0]; item = room_els[0];
expect(item.textContent.trim()).toBe('balcony@chat.shakespeare.lit'); expect(item.textContent.trim()).toBe('balcony@chat.shakespeare.lit');
done(); done();
});
})); }));
it("has an info icon which opens a details modal when clicked", mock.initConverseWithPromises( it("has an info icon which opens a details modal when clicked", mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], null, ['rosterGroupsFetched', 'chatBoxesFetched'],
{ whitelisted_plugins: ['converse-roomslist'], { whitelisted_plugins: ['converse-roomslist'],
allow_bookmarks: false // Makes testing easier, otherwise we allow_bookmarks: false // Makes testing easier, otherwise we
// have to mock stanza traffic. // have to mock stanza traffic.
}, function (done, _converse) { }, function (done, _converse) {
let view;
test_utils.openControlBox(); test_utils.openControlBox();
_converse.api.rooms.open('coven@chat.shakespeare.lit', {'nick': 'some1'}); _converse.api.rooms.open('coven@chat.shakespeare.lit', {'nick': 'some1'})
const view = _converse.chatboxviews.get('coven@chat.shakespeare.lit'); .then(() => {
view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
const last_stanza = _.last(_converse.connection.IQ_stanzas).nodeTree; const last_stanza = _.last(_converse.connection.IQ_stanzas).nodeTree;
const IQ_id = last_stanza.getAttribute('id'); const IQ_id = last_stanza.getAttribute('id');
const features_stanza = $iq({ const features_stanza = $iq({
@ -127,9 +132,8 @@
.c('field', {'type':'text-single', 'var':'muc#roominfo_occupants', 'label':'Number of occupants'}) .c('field', {'type':'text-single', 'var':'muc#roominfo_occupants', 'label':'Number of occupants'})
.c('value').t(0); .c('value').t(0);
_converse.connection._dataRecv(test_utils.createRequest(features_stanza)); _converse.connection._dataRecv(test_utils.createRequest(features_stanza));
return test_utils.waitUntil(() => view.model.get('connection_status') === converse.ROOMSTATUS.CONNECTING)
test_utils.waitUntil(() => view.model.get('connection_status') === converse.ROOMSTATUS.CONNECTING) }).then(function () {
.then(function () {
var presence = $pres({ var presence = $pres({
to: _converse.connection.jid, to: _converse.connection.jid,
from: 'coven@chat.shakespeare.lit/some1', from: 'coven@chat.shakespeare.lit/some1',
@ -201,12 +205,10 @@
}, },
function (done, _converse) { function (done, _converse) {
spyOn(window, 'confirm').and.callFake(function () { spyOn(window, 'confirm').and.callFake(() => true);
return true;
});
expect(_converse.chatboxes.length).toBe(1); expect(_converse.chatboxes.length).toBe(1);
test_utils.openChatRoom( test_utils.openChatRoom(_converse, 'lounge', 'conference.shakespeare.lit', 'JC')
_converse, 'lounge', 'conference.shakespeare.lit', 'JC'); .then(() => {
expect(_converse.chatboxes.length).toBe(2); expect(_converse.chatboxes.length).toBe(2);
var room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room"); var room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room");
expect(room_els.length).toBe(1); expect(room_els.length).toBe(1);
@ -218,6 +220,7 @@
expect(room_els.length).toBe(0); expect(room_els.length).toBe(0);
expect(_converse.chatboxes.length).toBe(1); expect(_converse.chatboxes.length).toBe(1);
done(); done();
});
})); }));
it("shows unread messages directed at the user", mock.initConverseWithAsync( it("shows unread messages directed at the user", mock.initConverseWithAsync(

View File

@ -92,12 +92,14 @@
it("can be sent without a hint", it("can be sent without a hint",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current', 1);
_converse.emit('rosterContactsFetched');
test_utils.openControlBox(); test_utils.openControlBox();
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
// XXX: We need to send a presence from the contact, so that we // XXX: We need to send a presence from the contact, so that we
// have a resource, that resource is then queried to see // have a resource, that resource is then queried to see
@ -108,9 +110,9 @@
'to': 'dummy@localhost' 'to': 'dummy@localhost'
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
.then(() => test_utils.waitUntilDiscoConfirmed(_converse, contact_jid+'/phone', [], [Strophe.NS.SPOILER]))
test_utils.waitUntilDiscoConfirmed(_converse, contact_jid+'/phone', [], [Strophe.NS.SPOILER]).then(function () { .then(() => {
var view = _converse.chatboxviews.get(contact_jid); var view = _converse.chatboxviews.get(contact_jid);
spyOn(view, 'onMessageSubmitted').and.callThrough(); spyOn(view, 'onMessageSubmitted').and.callThrough();
spyOn(_converse.connection, 'send'); spyOn(_converse.connection, 'send');
@ -167,10 +169,12 @@
it("can be sent with a hint", it("can be sent with a hint",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current', 1);
_converse.emit('rosterContactsFetched');
test_utils.openControlBox(); test_utils.openControlBox();
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
@ -183,9 +187,9 @@
'to': 'dummy@localhost' 'to': 'dummy@localhost'
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
.then(() => test_utils.waitUntilDiscoConfirmed(_converse, contact_jid+'/phone', [], [Strophe.NS.SPOILER]))
test_utils.waitUntilDiscoConfirmed(_converse, contact_jid+'/phone', [], [Strophe.NS.SPOILER]).then(function () { .then(() => {
var view = _converse.chatboxviews.get(contact_jid); var view = _converse.chatboxviews.get(contact_jid);
var spoiler_toggle = view.el.querySelector('.toggle-compose-spoiler'); var spoiler_toggle = view.el.querySelector('.toggle-compose-spoiler');
spoiler_toggle.click(); spoiler_toggle.click();

View File

@ -58,16 +58,17 @@
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
let view, modal;
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
.then(() => {
const view = _converse.chatboxviews.get(contact_jid); view = _converse.chatboxviews.get(contact_jid);
const show_modal_button = view.el.querySelector('.show-user-details-modal'); const show_modal_button = view.el.querySelector('.show-user-details-modal');
expect(u.isVisible(show_modal_button)).toBeTruthy(); expect(u.isVisible(show_modal_button)).toBeTruthy();
show_modal_button.click(); show_modal_button.click();
const modal = view.user_details_modal; modal = view.user_details_modal;
test_utils.waitUntil(() => u.isVisible(modal.el), 2000) return test_utils.waitUntil(() => u.isVisible(modal.el), 2000);
.then(function () { }).then(function () {
spyOn(window, 'confirm').and.returnValue(true); spyOn(window, 'confirm').and.returnValue(true);
spyOn(view.model.contact, 'removeFromRoster').and.callFake(function (callback, errback) { spyOn(view.model.contact, 'removeFromRoster').and.callFake(function (callback, errback) {
errback(); errback();

View File

@ -561,8 +561,7 @@
const handler = () => { const handler = () => {
if (!u.isPersistableModel(this.model)) { if (!u.isPersistableModel(this.model)) {
// Happens during tests, nothing to do if this // Happens during tests, nothing to do if this
// is a hanging chatbox (i.e. not in the // is a hanging chatbox (i.e. not in the collection anymore).
// collection anymore).
return; return;
} }
this.populateAndJoin(); this.populateAndJoin();

View File

@ -148,8 +148,13 @@
); );
xhr.onload = function () { xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 400) { if (xhr.status >= 200 && xhr.status < 400) {
jed_instance = new Jed(window.JSON.parse(xhr.responseText)); try {
const data = window.JSON.parse(xhr.responseText);
jed_instance = new Jed(data);
resolve(); resolve();
} catch (e) {
xhr.onerror(e);
}
} else { } else {
xhr.onerror(); xhr.onerror();
} }

View File

@ -98,8 +98,9 @@
return views; return views;
}; };
utils.openChatBoxFor = function (converse, jid) { utils.openChatBoxFor = function (_converse, jid) {
return converse.roster.get(jid).trigger("open"); _converse.roster.get(jid).trigger("open");
return utils.waitUntil(() => _converse.chatboxviews.get(jid));
}; };
utils.openChatRoomViaModal = function (_converse, jid, nick) { utils.openChatRoomViaModal = function (_converse, jid, nick) {
@ -121,14 +122,14 @@
}; };
utils.openChatRoom = function (_converse, room, server, nick) { utils.openChatRoom = function (_converse, room, server, nick) {
_converse.api.rooms.open(`${room}@${server}`); return _converse.api.rooms.open(`${room}@${server}`);
}; };
utils.openAndEnterChatRoom = function (_converse, room, server, nick) { utils.openAndEnterChatRoom = function (_converse, room, server, nick) {
let last_stanza; let last_stanza;
return new Promise(function (resolve, reject) { return new Promise((resolve, reject) => {
_converse.api.rooms.open(`${room}@${server}`); return _converse.api.rooms.open(`${room}@${server}`).then(() => {
const view = _converse.chatboxviews.get((room+'@'+server).toLowerCase()); const view = _converse.chatboxviews.get((room+'@'+server).toLowerCase());
// We pretend this is a new room, so no disco info is returned. // We pretend this is a new room, so no disco info is returned.
let last_stanza = _.last(_converse.connection.IQ_stanzas).nodeTree; let last_stanza = _.last(_converse.connection.IQ_stanzas).nodeTree;
@ -178,7 +179,7 @@
.c('status').attrs({code:'110'}); .c('status').attrs({code:'110'});
_converse.connection._dataRecv(utils.createRequest(presence)); _converse.connection._dataRecv(utils.createRequest(presence));
resolve(); resolve();
}).catch(_.partial(console.error, _));
}).catch(_.partial(console.error, _)); }).catch(_.partial(console.error, _));
}).catch(_.partial(console.error, _)); }).catch(_.partial(console.error, _));
}; };