diff --git a/spec/bookmarks.js b/spec/bookmarks.js index 68a7e693c..43bcd6965 100644 --- a/spec/bookmarks.js +++ b/spec/bookmarks.js @@ -12,6 +12,7 @@ } (this, function (jasmine, $, converse, utils, mock, test_utils) { "use strict"; var $iq = converse.env.$iq, + Backbone = converse.env.Backbone, Strophe = converse.env.Strophe, _ = converse.env._, u = converse.env.utils; @@ -20,7 +21,7 @@ it("can be bookmarked", mock.initConverseWithPromises( null, ['rosterGroupsFetched'], {}, function (done, _converse) { - + var sent_stanza, IQ_id; var sendIQ = _converse.connection.sendIQ; spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) { @@ -30,105 +31,110 @@ spyOn(_converse.connection, 'getUniqueId').and.callThrough(); test_utils.openChatRoom(_converse, 'theplay', 'conference.shakespeare.lit', 'JC'); + var jid = 'theplay@conference.shakespeare.lit'; var view = _converse.chatboxviews.get(jid); spyOn(view, 'renderBookmarkForm').and.callThrough(); spyOn(view, 'closeForm').and.callThrough(); - var $bookmark = $(view.el).find('.icon-pushpin'); - $bookmark[0].click(); - expect(view.renderBookmarkForm).toHaveBeenCalled(); + test_utils.waitUntil(function () { + return !_.isNull(view.el.querySelector('.toggle-bookmark')); + }, 300).then(function () { + var $bookmark = $(view.el).find('.icon-pushpin'); + $bookmark[0].click(); + expect(view.renderBookmarkForm).toHaveBeenCalled(); - view.el.querySelector('.button-cancel').click(); - expect(view.closeForm).toHaveBeenCalled(); - expect($bookmark.hasClass('on-button'), false); + view.el.querySelector('.button-cancel').click(); + expect(view.closeForm).toHaveBeenCalled(); + expect($bookmark.hasClass('on-button'), false); - $bookmark[0].click(); - expect(view.renderBookmarkForm).toHaveBeenCalled(); + $bookmark[0].click(); + expect(view.renderBookmarkForm).toHaveBeenCalled(); - /* Client uploads data: - * -------------------- - * - * - * - * - * - * - * JC - * - * - * - * - * - * - * - * http://jabber.org/protocol/pubsub#publish-options - * - * - * true - * - * - * whitelist - * - * - * - * - * - */ - expect(view.model.get('bookmarked')).toBeFalsy(); - var $form = $(view.el).find('.chatroom-form'); - $form.find('input[name="name"]').val('Play's the Thing'); - $form.find('input[name="autojoin"]').prop('checked', true); - $form.find('input[name="nick"]').val('JC'); - view.el.querySelector('.button-primary').click(); + /* Client uploads data: + * -------------------- + * + * + * + * + * + * + * JC + * + * + * + * + * + * + * + * http://jabber.org/protocol/pubsub#publish-options + * + * + * true + * + * + * whitelist + * + * + * + * + * + */ + expect(view.model.get('bookmarked')).toBeFalsy(); + var $form = $(view.el).find('.chatroom-form'); + $form.find('input[name="name"]').val('Play's the Thing'); + $form.find('input[name="autojoin"]').prop('checked', true); + $form.find('input[name="nick"]').val('JC'); + view.el.querySelector('.button-primary').click(); - expect(view.model.get('bookmarked')).toBeTruthy(); - expect($bookmark.hasClass('on-button'), true); + expect(view.model.get('bookmarked')).toBeTruthy(); + expect($bookmark.hasClass('on-button'), true); - expect(sent_stanza.toLocaleString()).toBe( - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - "JC"+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - "http://jabber.org/protocol/pubsub#publish-options"+ - ""+ - ""+ - "true"+ - ""+ - ""+ - "whitelist"+ - ""+ - ""+ - ""+ - ""+ - "" - ); + expect(sent_stanza.toLocaleString()).toBe( + ""+ + ""+ + ""+ + ""+ + ""+ + ""+ + "JC"+ + ""+ + ""+ + ""+ + ""+ + ""+ + ""+ + ""+ + "http://jabber.org/protocol/pubsub#publish-options"+ + ""+ + ""+ + "true"+ + ""+ + ""+ + "whitelist"+ + ""+ + ""+ + ""+ + ""+ + "" + ); - /* Server acknowledges successful storage - * - * - */ - var stanza = $iq({ - 'to':_converse.connection.jid, - 'type':'result', - 'id':IQ_id + /* Server acknowledges successful storage + * + * + */ + var stanza = $iq({ + 'to':_converse.connection.jid, + 'type':'result', + 'id':IQ_id + }); + _converse.connection._dataRecv(test_utils.createRequest(stanza)); + // We ignore this IQ stanza... (unless it's an error stanza), so + // nothing to test for here. + done(); }); - _converse.connection._dataRecv(test_utils.createRequest(stanza)); - // We ignore this IQ stanza... (unless it's an error stanza), so - // nothing to test for here. - done(); })); it("will be automatically opened if 'autojoin' is set on the bookmark", mock.initConverseWithPromises( @@ -161,13 +167,18 @@ test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy'); var view = _converse.chatboxviews.get('lounge@localhost'); - var $bookmark_icon = $(view.el.querySelector('.icon-pushpin')); - expect($bookmark_icon.hasClass('button-on')).toBeFalsy(); - view.model.set('bookmarked', true); - expect($bookmark_icon.hasClass('button-on')).toBeTruthy(); - view.model.set('bookmarked', false); - expect($bookmark_icon.hasClass('button-on')).toBeFalsy(); - done(); + + test_utils.waitUntil(function () { + return !_.isNull(view.el.querySelector('.toggle-bookmark')); + }, 300).then(function () { + var bookmark_icon = view.el.querySelector('.icon-pushpin'); + expect(_.includes(bookmark_icon.classList, 'button-on')).toBeFalsy(); + view.model.set('bookmarked', true); + expect(_.includes(bookmark_icon.classList, 'button-on')).toBeTruthy(); + view.model.set('bookmarked', false); + expect(_.includes(bookmark_icon.classList, 'button-on')).toBeFalsy(); + done(); + }); })); it("can be unbookmarked", mock.initConverseWithPromises( @@ -175,61 +186,68 @@ var sent_stanza, IQ_id; var sendIQ = _converse.connection.sendIQ; + test_utils.openChatRoom(_converse, 'theplay', 'conference.shakespeare.lit', 'JC'); var jid = 'theplay@conference.shakespeare.lit'; var view = _converse.chatboxviews.get(jid); - spyOn(view, 'toggleBookmark').and.callThrough(); - spyOn(_converse.bookmarks, 'sendBookmarkStanza').and.callThrough(); - view.delegateEvents(); - _converse.bookmarks.create({ - 'jid': view.model.get('jid'), - 'autojoin': false, - 'name': 'The Play', - 'nick': ' Othello' - }); - expect(_converse.bookmarks.length).toBe(1); - expect(view.model.get('bookmarked')).toBeTruthy(); - var $bookmark_icon = $(view.el.querySelector('.icon-pushpin')); - expect($bookmark_icon.hasClass('button-on')).toBeTruthy(); - spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) { - sent_stanza = iq; - IQ_id = sendIQ.bind(this)(iq, callback, errback); - }); - spyOn(_converse.connection, 'getUniqueId').and.callThrough(); - $bookmark_icon[0].click(); - expect(view.toggleBookmark).toHaveBeenCalled(); - expect($bookmark_icon.hasClass('button-on')).toBeFalsy(); - expect(_converse.bookmarks.length).toBe(0); + test_utils.waitUntil(function () { + return !_.isNull(view.el.querySelector('.toggle-bookmark')); + }, 300).then(function () { + spyOn(view, 'toggleBookmark').and.callThrough(); + spyOn(_converse.bookmarks, 'sendBookmarkStanza').and.callThrough(); + view.delegateEvents(); - // Check that an IQ stanza is sent out, containing no - // conferences to bookmark (since we removed the one and - // only bookmark). - expect(sent_stanza.toLocaleString()).toBe( - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - "http://jabber.org/protocol/pubsub#publish-options"+ - ""+ - ""+ - "true"+ - ""+ - ""+ - "whitelist"+ - ""+ - ""+ - ""+ - ""+ - "" - ); - done(); + _converse.bookmarks.create({ + 'jid': view.model.get('jid'), + 'autojoin': false, + 'name': 'The Play', + 'nick': ' Othello' + }); + expect(_converse.bookmarks.length).toBe(1); + expect(view.model.get('bookmarked')).toBeTruthy(); + var $bookmark_icon = $(view.el.querySelector('.icon-pushpin')); + expect($bookmark_icon.hasClass('button-on')).toBeTruthy(); + + spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) { + sent_stanza = iq; + IQ_id = sendIQ.bind(this)(iq, callback, errback); + }); + spyOn(_converse.connection, 'getUniqueId').and.callThrough(); + $bookmark_icon[0].click(); + expect(view.toggleBookmark).toHaveBeenCalled(); + expect($bookmark_icon.hasClass('button-on')).toBeFalsy(); + expect(_converse.bookmarks.length).toBe(0); + + // Check that an IQ stanza is sent out, containing no + // conferences to bookmark (since we removed the one and + // only bookmark). + expect(sent_stanza.toLocaleString()).toBe( + ""+ + ""+ + ""+ + ""+ + ""+ + ""+ + ""+ + ""+ + ""+ + ""+ + "http://jabber.org/protocol/pubsub#publish-options"+ + ""+ + ""+ + "true"+ + ""+ + ""+ + "whitelist"+ + ""+ + ""+ + ""+ + ""+ + "" + ); + done(); + }); })); }); @@ -308,88 +326,21 @@ })); it("can be retrieved from the XMPP server", mock.initConverseWithPromises( - ['send'], ['rosterGroupsFetched'], {}, function (done, _converse) { + ['send'], ['chatBoxesFetched', 'roomsPanelRendered', 'rosterGroupsFetched'], {}, + function (done, _converse) { - /* Client requests all items - * ------------------------- - * - * - * - * - * - * - */ - var IQ_id; - expect(_.filter(_converse.connection.send.calls.all(), function (call) { - var stanza = call.args[0]; - if (!(stanza instanceof Element) || stanza.nodeName !== 'iq') { - return; - } - // XXX: Wrapping in a div is a workaround for PhantomJS - var div = document.createElement('div'); - div.appendChild(stanza); - if (div.innerHTML === - ''+ - ''+ - ''+ - ''+ - '') { - IQ_id = stanza.getAttribute('id'); - return true; - } - }).length).toBe(1); - - /* - * Server returns all items - * ------------------------ - * - * - * - * - * - * - * JC - * - * - * - * - * - * - */ - expect(_converse.bookmarks.models.length).toBe(0); - var stanza = $iq({'to': _converse.connection.jid, 'type':'result', 'id':IQ_id}) - .c('pubsub', {'xmlns': Strophe.NS.PUBSUB}) - .c('items', {'node': 'storage:bookmarks'}) - .c('item', {'id': 'current'}) - .c('storage', {'xmlns': 'storage:bookmarks'}) - .c('conference', { - 'name': 'The Play's the Thing', - 'autojoin': 'true', - 'jid': 'theplay@conference.shakespeare.lit' - }).c('nick').t('JC').up().up() - .c('conference', { - 'name': 'Another room', - 'autojoin': 'false', - 'jid': 'another@conference.shakespeare.lit' - }).c('nick').t('JC').up().up(); - _converse.connection._dataRecv(test_utils.createRequest(stanza)); - expect(_converse.bookmarks.models.length).toBe(2); - expect(_converse.bookmarks.findWhere({'jid': 'theplay@conference.shakespeare.lit'}).get('autojoin')).toBe(true); - expect(_converse.bookmarks.findWhere({'jid': 'another@conference.shakespeare.lit'}).get('autojoin')).toBe(false); - done(); - })); - - describe("The rooms panel", function () { - - it("shows a list of bookmarks", mock.initConverseWithPromises( - ['send'], ['rosterGroupsFetched'], {}, function (done, _converse) { - - test_utils.openControlBox().openRoomsPanel(_converse); + test_utils.waitUntil(function () { + return _converse.bookmarks; + }, 300).then(function () { + /* Client requests all items + * ------------------------- + * + * + * + * + * + * + */ var IQ_id; expect(_.filter(_converse.connection.send.calls.all(), function (call) { var stanza = call.args[0]; @@ -411,6 +362,28 @@ } }).length).toBe(1); + /* + * Server returns all items + * ------------------------ + * + * + * + * + * + * + * JC + * + * + * + * + * + * + */ + expect(_converse.bookmarks.models.length).toBe(0); var stanza = $iq({'to': _converse.connection.jid, 'type':'result', 'id':IQ_id}) .c('pubsub', {'xmlns': Strophe.NS.PUBSUB}) .c('items', {'node': 'storage:bookmarks'}) @@ -418,97 +391,156 @@ .c('storage', {'xmlns': 'storage:bookmarks'}) .c('conference', { 'name': 'The Play's the Thing', - 'autojoin': 'false', + 'autojoin': 'true', 'jid': 'theplay@conference.shakespeare.lit' }).c('nick').t('JC').up().up() - .c('conference', { - 'name': '1st Bookmark', - 'autojoin': 'false', - 'jid': 'first@conference.shakespeare.lit' - }).c('nick').t('JC').up().up() - .c('conference', { - 'name': 'Bookmark with a very very long name that will be shortened', - 'autojoin': 'false', - 'jid': 'longname@conference.shakespeare.lit' - }).c('nick').t('JC').up().up() .c('conference', { 'name': 'Another room', 'autojoin': 'false', 'jid': 'another@conference.shakespeare.lit' }).c('nick').t('JC').up().up(); _converse.connection._dataRecv(test_utils.createRequest(stanza)); + expect(_converse.bookmarks.models.length).toBe(2); + expect(_converse.bookmarks.findWhere({'jid': 'theplay@conference.shakespeare.lit'}).get('autojoin')).toBe(true); + expect(_converse.bookmarks.findWhere({'jid': 'another@conference.shakespeare.lit'}).get('autojoin')).toBe(false); + done(); + }); + })); + + describe("The rooms panel", function () { + + it("shows a list of bookmarks", mock.initConverseWithPromises( + ['send'], ['rosterGroupsFetched'], {}, function (done, _converse) { test_utils.waitUntil(function () { - return $('#chatrooms dl.bookmarks dd').length; + return _converse.bookmarks; }, 300).then(function () { - expect($('#chatrooms dl.bookmarks dd').length).toBe(4); - expect($('#chatrooms dl.bookmarks dd a').text().trim()).toBe( - "1st Bookmark  Another room  Bookmark with a very very long name that will be shortened  The Play's the Thing") - spyOn(window, 'confirm').and.returnValue(true); - $('#chatrooms dl.bookmarks dd:nth-child(2) a:nth-child(2)')[0].click(); - expect(window.confirm).toHaveBeenCalled(); + test_utils.openControlBox().openRoomsPanel(_converse); + var IQ_id; + expect(_.filter(_converse.connection.send.calls.all(), function (call) { + var stanza = call.args[0]; + if (!(stanza instanceof Element) || stanza.nodeName !== 'iq') { + return; + } + // XXX: Wrapping in a div is a workaround for PhantomJS + var div = document.createElement('div'); + div.appendChild(stanza); + if (div.innerHTML === + ''+ + ''+ + ''+ + ''+ + '') { + IQ_id = stanza.getAttribute('id'); + return true; + } + }).length).toBe(1); - return test_utils.waitUntil(function () { - return $('#chatrooms dl.bookmarks dd a').text().trim() === - "1st Bookmark  Bookmark with a very very long name that will be shortened  The Play's the Thing"; - }, 300) - }).then(done); + var stanza = $iq({'to': _converse.connection.jid, 'type':'result', 'id':IQ_id}) + .c('pubsub', {'xmlns': Strophe.NS.PUBSUB}) + .c('items', {'node': 'storage:bookmarks'}) + .c('item', {'id': 'current'}) + .c('storage', {'xmlns': 'storage:bookmarks'}) + .c('conference', { + 'name': 'The Play's the Thing', + 'autojoin': 'false', + 'jid': 'theplay@conference.shakespeare.lit' + }).c('nick').t('JC').up().up() + .c('conference', { + 'name': '1st Bookmark', + 'autojoin': 'false', + 'jid': 'first@conference.shakespeare.lit' + }).c('nick').t('JC').up().up() + .c('conference', { + 'name': 'Bookmark with a very very long name that will be shortened', + 'autojoin': 'false', + 'jid': 'longname@conference.shakespeare.lit' + }).c('nick').t('JC').up().up() + .c('conference', { + 'name': 'Another room', + 'autojoin': 'false', + 'jid': 'another@conference.shakespeare.lit' + }).c('nick').t('JC').up().up(); + _converse.connection._dataRecv(test_utils.createRequest(stanza)); + + test_utils.waitUntil(function () { + return $('#chatrooms dl.bookmarks dd').length; + }, 300).then(function () { + expect($('#chatrooms dl.bookmarks dd').length).toBe(4); + expect($('#chatrooms dl.bookmarks dd a').text().trim()).toBe( + "1st Bookmark  Another room  Bookmark with a very very long name that will be shortened  The Play's the Thing") + + spyOn(window, 'confirm').and.returnValue(true); + $('#chatrooms dl.bookmarks dd:nth-child(2) a:nth-child(2)')[0].click(); + expect(window.confirm).toHaveBeenCalled(); + + return test_utils.waitUntil(function () { + return $('#chatrooms dl.bookmarks dd a').text().trim() === + "1st Bookmark  Bookmark with a very very long name that will be shortened  The Play's the Thing"; + }, 300) + }).then(done); + }); })); it("remembers the toggle state of the bookmarks list", mock.initConverseWithPromises( ['send'], ['rosterGroupsFetched'], {}, function (done, _converse) { - var IQ_id; - expect(_.filter(_converse.connection.send.calls.all(), function (call) { - var stanza = call.args[0]; - if (!(stanza instanceof Element) || stanza.nodeName !== 'iq') { - return; - } - // XXX: Wrapping in a div is a workaround for PhantomJS - var div = document.createElement('div'); - div.appendChild(stanza); - if (div.innerHTML === - ''+ - ''+ - ''+ - ''+ - '') { - IQ_id = stanza.getAttribute('id'); - return true; - } - }).length).toBe(1); - - var stanza = $iq({'to': _converse.connection.jid, 'type':'result', 'id':IQ_id}) - .c('pubsub', {'xmlns': Strophe.NS.PUBSUB}) - .c('items', {'node': 'storage:bookmarks'}) - .c('item', {'id': 'current'}) - .c('storage', {'xmlns': 'storage:bookmarks'}); - _converse.connection._dataRecv(test_utils.createRequest(stanza)); - - _converse.bookmarks.create({ - 'jid': 'theplay@conference.shakespeare.lit', - 'autojoin': false, - 'name': 'The Play', - 'nick': '' - }); - test_utils.openControlBox().openRoomsPanel(_converse); - test_utils.waitUntil(function () { - return $('#chatrooms dl.bookmarks dd:visible').length; + return _converse.bookmarks; }, 300).then(function () { - expect($('#chatrooms dl.bookmarks').hasClass('collapsed')).toBeFalsy(); - expect($('#chatrooms dl.bookmarks dd:visible').length).toBe(1); - expect(_converse.bookmarksview.list_model.get('toggle-state')).toBe(_converse.OPENED); - $('#chatrooms .bookmarks-toggle')[0].click(); - expect($('#chatrooms dl.bookmarks').hasClass('collapsed')).toBeTruthy(); - expect(_converse.bookmarksview.list_model.get('toggle-state')).toBe(_converse.CLOSED); - $('#chatrooms .bookmarks-toggle')[0].click(); - expect($('#chatrooms dl.bookmarks').hasClass('collapsed')).toBeFalsy(); - expect($('#chatrooms dl.bookmarks dd:visible').length).toBe(1); - expect(_converse.bookmarksview.list_model.get('toggle-state')).toBe(_converse.OPENED); - done(); + var IQ_id; + expect(_.filter(_converse.connection.send.calls.all(), function (call) { + var stanza = call.args[0]; + if (!(stanza instanceof Element) || stanza.nodeName !== 'iq') { + return; + } + // XXX: Wrapping in a div is a workaround for PhantomJS + var div = document.createElement('div'); + div.appendChild(stanza); + if (div.innerHTML === + ''+ + ''+ + ''+ + ''+ + '') { + IQ_id = stanza.getAttribute('id'); + return true; + } + }).length).toBe(1); + + var stanza = $iq({'to': _converse.connection.jid, 'type':'result', 'id':IQ_id}) + .c('pubsub', {'xmlns': Strophe.NS.PUBSUB}) + .c('items', {'node': 'storage:bookmarks'}) + .c('item', {'id': 'current'}) + .c('storage', {'xmlns': 'storage:bookmarks'}); + _converse.connection._dataRecv(test_utils.createRequest(stanza)); + + _converse.bookmarks.create({ + 'jid': 'theplay@conference.shakespeare.lit', + 'autojoin': false, + 'name': 'The Play', + 'nick': '' + }); + test_utils.openControlBox().openRoomsPanel(_converse); + + test_utils.waitUntil(function () { + return $('#chatrooms dl.bookmarks dd:visible').length; + }, 300).then(function () { + expect($('#chatrooms dl.bookmarks').hasClass('collapsed')).toBeFalsy(); + expect($('#chatrooms dl.bookmarks dd:visible').length).toBe(1); + expect(_converse.bookmarksview.list_model.get('toggle-state')).toBe(_converse.OPENED); + $('#chatrooms .bookmarks-toggle')[0].click(); + expect($('#chatrooms dl.bookmarks').hasClass('collapsed')).toBeTruthy(); + expect(_converse.bookmarksview.list_model.get('toggle-state')).toBe(_converse.CLOSED); + $('#chatrooms .bookmarks-toggle')[0].click(); + expect($('#chatrooms dl.bookmarks').hasClass('collapsed')).toBeFalsy(); + expect($('#chatrooms dl.bookmarks dd:visible').length).toBe(1); + expect(_converse.bookmarksview.list_model.get('toggle-state')).toBe(_converse.OPENED); + done(); + }); }); })); }); @@ -521,36 +553,40 @@ { hide_open_bookmarks: true }, function (done, _converse) { - test_utils.openControlBox().openRoomsPanel(_converse); - // XXX Create bookmarks view here, otherwise we need to mock stanza - // traffic for it to get created. - _converse.bookmarksview = new _converse.BookmarksView( - {'model': _converse.bookmarks} - ); - _converse.emit('bookmarksInitialized'); + test_utils.waitUntil(function () { + return _converse.bookmarks; + }, 300).then(function () { + test_utils.openControlBox().openRoomsPanel(_converse); + // XXX Create bookmarks view here, otherwise we need to mock stanza + // traffic for it to get created. + _converse.bookmarksview = new _converse.BookmarksView( + {'model': _converse.bookmarks} + ); + _converse.emit('bookmarksInitialized'); - // Check that it's there - var jid = 'room@conference.example.org'; - _converse.bookmarks.create({ - 'jid': jid, - 'autojoin': false, - 'name': 'The Play', - 'nick': ' Othello' + // Check that it's there + var jid = 'room@conference.example.org'; + _converse.bookmarks.create({ + 'jid': jid, + 'autojoin': false, + 'name': 'The Play', + 'nick': ' Othello' + }); + + expect(_converse.bookmarks.length).toBe(1); + var room_els = _converse.bookmarksview.el.querySelectorAll(".open-room"); + expect(room_els.length).toBe(1); + + // Check that it disappears once the room is opened + var bookmark = _converse.bookmarksview.el.querySelector(".open-room"); + bookmark.click(); + expect(u.hasClass('hidden', _converse.bookmarksview.el.querySelector(".available-chatroom"))).toBeTruthy(); + // Check that it reappears once the room is closed + var view = _converse.chatboxviews.get(jid); + view.close(); + expect(u.hasClass('hidden', _converse.bookmarksview.el.querySelector(".available-chatroom"))).toBeFalsy(); + done(); }); - - expect(_converse.bookmarks.length).toBe(1); - var room_els = _converse.bookmarksview.el.querySelectorAll(".open-room"); - expect(room_els.length).toBe(1); - - // Check that it disappears once the room is opened - var bookmark = _converse.bookmarksview.el.querySelector(".open-room"); - bookmark.click(); - expect(u.hasClass('hidden', _converse.bookmarksview.el.querySelector(".available-chatroom"))).toBeTruthy(); - // Check that it reappears once the room is closed - var view = _converse.chatboxviews.get(jid); - view.close(); - expect(u.hasClass('hidden', _converse.bookmarksview.el.querySelector(".available-chatroom"))).toBeFalsy(); - done(); })); }); })); diff --git a/spec/chatbox.js b/spec/chatbox.js index 02ad8783c..957436ef7 100644 --- a/spec/chatbox.js +++ b/spec/chatbox.js @@ -57,7 +57,7 @@ null, ['rosterGroupsFetched'], {}, function (done, _converse) { - test_utils.waitUntilFeatureSupportConfirmed(_converse, 'vcard-temp') + test_utils.waitUntilFeatureSupportConfirmed(_converse, 'localhost', 'vcard-temp') .then(function () { return test_utils.waitUntil(function () { return _converse.xmppstatus.get('fullname'); @@ -1228,7 +1228,7 @@ function (done, _converse) { var contact, sent_stanza, IQ_id, stanza; - test_utils.waitUntilFeatureSupportConfirmed(_converse, 'vcard-temp') + test_utils.waitUntilFeatureSupportConfirmed(_converse, 'localhost', 'vcard-temp') .then(function () { return test_utils.waitUntil(function () { return _converse.xmppstatus.get('fullname'); @@ -1842,7 +1842,7 @@ function (done, _converse) { var contact, sent_stanza, IQ_id, stanza; - test_utils.waitUntilFeatureSupportConfirmed(_converse, 'vcard-temp') + test_utils.waitUntilFeatureSupportConfirmed(_converse, 'localhost', 'vcard-temp') .then(function () { return test_utils.waitUntil(function () { return _converse.xmppstatus.get('fullname'); @@ -1989,7 +1989,7 @@ function (done, _converse) { var contact, sent_stanza, IQ_id, stanza; - test_utils.waitUntilFeatureSupportConfirmed(_converse, 'vcard-temp') + test_utils.waitUntilFeatureSupportConfirmed(_converse, 'localhost', 'vcard-temp') .then(function () { return test_utils.waitUntil(function () { return _converse.xmppstatus.get('fullname'); diff --git a/spec/chatroom.js b/spec/chatroom.js index ac8a0ac06..4840c24dc 100644 --- a/spec/chatroom.js +++ b/spec/chatroom.js @@ -762,7 +762,6 @@ }); var view = _converse.api.rooms.open('coven@chat.shakespeare.lit', {'nick': 'some1'}); - spyOn(view, 'generateHeadingHTML').and.callThrough(); var features_stanza = $iq({ from: 'coven@chat.shakespeare.lit', 'id': IQ_id, @@ -791,10 +790,12 @@ .c('field', {'type':'text-single', 'var':'muc#roominfo_occupants', 'label':'Number of occupants'}) .c('value').t(0); _converse.connection._dataRecv(test_utils.createRequest(features_stanza)); - - expect(view.generateHeadingHTML).toHaveBeenCalled(); - expect($(view.el.querySelector('.chatroom-description')).text()).toBe('This is the description'); - done(); + test_utils.waitUntil(function () { + return _.get(view.el.querySelector('.chatroom-description'), 'textContent'); + }).then(function () { + expect($(view.el.querySelector('.chatroom-description')).text()).toBe('This is the description'); + done(); + }); })); it("will specially mark messages in which you are mentioned", @@ -825,8 +826,7 @@ null, ['rosterGroupsFetched'], {}, function (done, _converse) { - - test_utils.waitUntilFeatureSupportConfirmed(_converse, 'vcard-temp') + test_utils.waitUntilFeatureSupportConfirmed(_converse, 'localhost', 'vcard-temp') .then(function () { return test_utils.waitUntil(function () { return _converse.xmppstatus.get('fullname'); @@ -890,19 +890,24 @@ _converse.api.rooms.open('coven@chat.shakespeare.lit', {'nick': 'some1'}); view = _converse.chatboxviews.get('coven@chat.shakespeare.lit'); - spyOn(view, 'saveAffiliationAndRole').and.callThrough(); - // We pretend this is a new room, so no disco info is returned. - var features_stanza = $iq({ - from: 'coven@chat.shakespeare.lit', - 'id': IQ_id, - 'to': 'dummy@localhost/desktop', - 'type': 'error' - }).c('error', {'type': 'cancel'}) - .c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"}); - _converse.connection._dataRecv(test_utils.createRequest(features_stanza)); + test_utils.waitUntil(function () { + return !_.isNull(view.el.querySelector('.toggle-bookmark')); + }, 300).then(function () { - /* * * @@ -910,191 +915,198 @@ * * */ - var presence = $pres({ - to: 'dummy@localhost/_converse.js-29092160', - from: 'coven@chat.shakespeare.lit/some1' - }).c('x', {xmlns: Strophe.NS.MUC_USER}) - .c('item', { - 'affiliation': 'owner', - 'jid': 'dummy@localhost/_converse.js-29092160', - 'role': 'moderator' - }).up() - .c('status', {code: '110'}); - _converse.connection._dataRecv(test_utils.createRequest(presence)); - expect(view.saveAffiliationAndRole).toHaveBeenCalled(); - expect($(view.el.querySelector('.configure-chatroom-button')).is(':visible')).toBeTruthy(); - expect($(view.el.querySelector('.toggle-chatbox-button')).is(':visible')).toBeTruthy(); - expect($(view.el.querySelector('.toggle-bookmark')).is(':visible')).toBeTruthy(); - view.el.querySelector('.configure-chatroom-button').click(); + var presence = $pres({ + to: 'dummy@localhost/_converse.js-29092160', + from: 'coven@chat.shakespeare.lit/some1' + }).c('x', {xmlns: Strophe.NS.MUC_USER}) + .c('item', { + 'affiliation': 'owner', + 'jid': 'dummy@localhost/_converse.js-29092160', + 'role': 'moderator' + }).up() + .c('status', {code: '110'}); + _converse.connection._dataRecv(test_utils.createRequest(presence)); + expect(view.saveAffiliationAndRole).toHaveBeenCalled(); + expect($(view.el.querySelector('.toggle-chatbox-button')).is(':visible')).toBeTruthy(); + expect($(view.el.querySelector('.toggle-bookmark')).is(':visible')).toBeTruthy(); - /* Check that an IQ is sent out, asking for the - * configuration form. - * See: // http://xmpp.org/extensions/xep-0045.html#example-163 - * - * - * - * - */ - expect(sent_IQ.toLocaleString()).toBe( - ""+ - ""+ - ""); + test_utils.waitUntil(function () { + return !_.isNull(view.el.querySelector('.configure-chatroom-button')); + }, 300).then(function () { + expect($(view.el.querySelector('.configure-chatroom-button')).is(':visible')).toBeTruthy(); - /* Server responds with the configuration form. - * See: // http://xmpp.org/extensions/xep-0045.html#example-165 - */ - var config_stanza = $iq({from: 'coven@chat.shakespeare.lit', - 'id': IQ_id, - 'to': 'dummy@localhost/desktop', - 'type': 'result'}) - .c('query', { 'xmlns': 'http://jabber.org/protocol/muc#owner'}) - .c('x', { 'xmlns': 'jabber:x:data', 'type': 'form'}) - .c('title').t('Configuration for "coven" Room').up() - .c('instructions').t('Complete this form to modify the configuration of your room.').up() - .c('field', {'type': 'hidden', 'var': 'FORM_TYPE'}) - .c('value').t('http://jabber.org/protocol/muc#roomconfig').up().up() - .c('field', { - 'label': 'Natural-Language Room Name', - 'type': 'text-single', - 'var': 'muc#roomconfig_roomname'}) - .c('value').t('A Dark Cave').up().up() - .c('field', { - 'label': 'Short Description of Room', - 'type': 'text-single', - 'var': 'muc#roomconfig_roomdesc'}) - .c('value').t('The place for all good witches!').up().up() - .c('field', { - 'label': 'Enable Public Logging?', - 'type': 'boolean', - 'var': 'muc#roomconfig_enablelogging'}) - .c('value').t(0).up().up() - .c('field', { - 'label': 'Allow Occupants to Change Subject?', - 'type': 'boolean', - 'var': 'muc#roomconfig_changesubject'}) - .c('value').t(0).up().up() - .c('field', { - 'label': 'Allow Occupants to Invite Others?', - 'type': 'boolean', - 'var': 'muc#roomconfig_allowinvites'}) - .c('value').t(0).up().up() - .c('field', { - 'label': 'Who Can Send Private Messages?', - 'type': 'list-single', - 'var': 'muc#roomconfig_allowpm'}) - .c('value').t('anyone').up() - .c('option', {'label': 'Anyone'}) - .c('value').t('anyone').up().up() - .c('option', {'label': 'Anyone with Voice'}) - .c('value').t('participants').up().up() - .c('option', {'label': 'Moderators Only'}) - .c('value').t('moderators').up().up() - .c('option', {'label': 'Nobody'}) - .c('value').t('none').up().up().up() - .c('field', { - 'label': 'Roles for which Presence is Broadcasted', - 'type': 'list-multi', - 'var': 'muc#roomconfig_presencebroadcast'}) - .c('value').t('moderator').up() - .c('value').t('participant').up() - .c('value').t('visitor').up() - .c('option', {'label': 'Moderator'}) - .c('value').t('moderator').up().up() - .c('option', {'label': 'Participant'}) - .c('value').t('participant').up().up() - .c('option', {'label': 'Visitor'}) - .c('value').t('visitor').up().up().up() - .c('field', { - 'label': 'Roles and Affiliations that May Retrieve Member List', - 'type': 'list-multi', - 'var': 'muc#roomconfig_getmemberlist'}) - .c('value').t('moderator').up() - .c('value').t('participant').up() - .c('value').t('visitor').up() - .c('option', {'label': 'Moderator'}) - .c('value').t('moderator').up().up() - .c('option', {'label': 'Participant'}) - .c('value').t('participant').up().up() - .c('option', {'label': 'Visitor'}) - .c('value').t('visitor').up().up().up() - .c('field', { - 'label': 'Make Room Publicly Searchable?', - 'type': 'boolean', - 'var': 'muc#roomconfig_publicroom'}) - .c('value').t(0).up().up() - .c('field', { - 'label': 'Make Room Publicly Searchable?', - 'type': 'boolean', - 'var': 'muc#roomconfig_publicroom'}) - .c('value').t(0).up().up() - .c('field', { - 'label': 'Make Room Persistent?', - 'type': 'boolean', - 'var': 'muc#roomconfig_persistentroom'}) - .c('value').t(0).up().up() - .c('field', { - 'label': 'Make Room Moderated?', - 'type': 'boolean', - 'var': 'muc#roomconfig_moderatedroom'}) - .c('value').t(0).up().up() - .c('field', { - 'label': 'Make Room Members Only?', - 'type': 'boolean', - 'var': 'muc#roomconfig_membersonly'}) - .c('value').t(0).up().up() - .c('field', { - 'label': 'Password Required for Entry?', - 'type': 'boolean', - 'var': 'muc#roomconfig_passwordprotectedroom'}) - .c('value').t(1).up().up() - .c('field', {'type': 'fixed'}) - .c('value').t('If a password is required to enter this room,'+ - 'you must specify the password below.').up().up() - .c('field', { - 'label': 'Password', - 'type': 'text-private', - 'var': 'muc#roomconfig_roomsecret'}) - .c('value').t('cauldronburn'); - _converse.connection._dataRecv(test_utils.createRequest(config_stanza)); + view.el.querySelector('.configure-chatroom-button').click(); - test_utils.waitUntil(function () { - return $(view.el.querySelector('form.chatroom-form')).length; - }, 300).then(function () { - expect($(view.el.querySelector('form.chatroom-form')).length).toBe(1); - expect(view.el.querySelectorAll('form.chatroom-form fieldset').length).toBe(2); - var $membersonly = $(view.el.querySelector('input[name="muc#roomconfig_membersonly"]')); - expect($membersonly.length).toBe(1); - expect($membersonly.attr('type')).toBe('checkbox'); - $membersonly.prop('checked', true); + /* Check that an IQ is sent out, asking for the + * configuration form. + * See: // http://xmpp.org/extensions/xep-0045.html#example-163 + * + * + * + * + */ + expect(sent_IQ.toLocaleString()).toBe( + ""+ + ""+ + ""); - var $moderated = $(view.el.querySelector('input[name="muc#roomconfig_moderatedroom"]')); - expect($moderated.length).toBe(1); - expect($moderated.attr('type')).toBe('checkbox'); - $moderated.prop('checked', true); + /* Server responds with the configuration form. + * See: // http://xmpp.org/extensions/xep-0045.html#example-165 + */ + var config_stanza = $iq({from: 'coven@chat.shakespeare.lit', + 'id': IQ_id, + 'to': 'dummy@localhost/desktop', + 'type': 'result'}) + .c('query', { 'xmlns': 'http://jabber.org/protocol/muc#owner'}) + .c('x', { 'xmlns': 'jabber:x:data', 'type': 'form'}) + .c('title').t('Configuration for "coven" Room').up() + .c('instructions').t('Complete this form to modify the configuration of your room.').up() + .c('field', {'type': 'hidden', 'var': 'FORM_TYPE'}) + .c('value').t('http://jabber.org/protocol/muc#roomconfig').up().up() + .c('field', { + 'label': 'Natural-Language Room Name', + 'type': 'text-single', + 'var': 'muc#roomconfig_roomname'}) + .c('value').t('A Dark Cave').up().up() + .c('field', { + 'label': 'Short Description of Room', + 'type': 'text-single', + 'var': 'muc#roomconfig_roomdesc'}) + .c('value').t('The place for all good witches!').up().up() + .c('field', { + 'label': 'Enable Public Logging?', + 'type': 'boolean', + 'var': 'muc#roomconfig_enablelogging'}) + .c('value').t(0).up().up() + .c('field', { + 'label': 'Allow Occupants to Change Subject?', + 'type': 'boolean', + 'var': 'muc#roomconfig_changesubject'}) + .c('value').t(0).up().up() + .c('field', { + 'label': 'Allow Occupants to Invite Others?', + 'type': 'boolean', + 'var': 'muc#roomconfig_allowinvites'}) + .c('value').t(0).up().up() + .c('field', { + 'label': 'Who Can Send Private Messages?', + 'type': 'list-single', + 'var': 'muc#roomconfig_allowpm'}) + .c('value').t('anyone').up() + .c('option', {'label': 'Anyone'}) + .c('value').t('anyone').up().up() + .c('option', {'label': 'Anyone with Voice'}) + .c('value').t('participants').up().up() + .c('option', {'label': 'Moderators Only'}) + .c('value').t('moderators').up().up() + .c('option', {'label': 'Nobody'}) + .c('value').t('none').up().up().up() + .c('field', { + 'label': 'Roles for which Presence is Broadcasted', + 'type': 'list-multi', + 'var': 'muc#roomconfig_presencebroadcast'}) + .c('value').t('moderator').up() + .c('value').t('participant').up() + .c('value').t('visitor').up() + .c('option', {'label': 'Moderator'}) + .c('value').t('moderator').up().up() + .c('option', {'label': 'Participant'}) + .c('value').t('participant').up().up() + .c('option', {'label': 'Visitor'}) + .c('value').t('visitor').up().up().up() + .c('field', { + 'label': 'Roles and Affiliations that May Retrieve Member List', + 'type': 'list-multi', + 'var': 'muc#roomconfig_getmemberlist'}) + .c('value').t('moderator').up() + .c('value').t('participant').up() + .c('value').t('visitor').up() + .c('option', {'label': 'Moderator'}) + .c('value').t('moderator').up().up() + .c('option', {'label': 'Participant'}) + .c('value').t('participant').up().up() + .c('option', {'label': 'Visitor'}) + .c('value').t('visitor').up().up().up() + .c('field', { + 'label': 'Make Room Publicly Searchable?', + 'type': 'boolean', + 'var': 'muc#roomconfig_publicroom'}) + .c('value').t(0).up().up() + .c('field', { + 'label': 'Make Room Publicly Searchable?', + 'type': 'boolean', + 'var': 'muc#roomconfig_publicroom'}) + .c('value').t(0).up().up() + .c('field', { + 'label': 'Make Room Persistent?', + 'type': 'boolean', + 'var': 'muc#roomconfig_persistentroom'}) + .c('value').t(0).up().up() + .c('field', { + 'label': 'Make Room Moderated?', + 'type': 'boolean', + 'var': 'muc#roomconfig_moderatedroom'}) + .c('value').t(0).up().up() + .c('field', { + 'label': 'Make Room Members Only?', + 'type': 'boolean', + 'var': 'muc#roomconfig_membersonly'}) + .c('value').t(0).up().up() + .c('field', { + 'label': 'Password Required for Entry?', + 'type': 'boolean', + 'var': 'muc#roomconfig_passwordprotectedroom'}) + .c('value').t(1).up().up() + .c('field', {'type': 'fixed'}) + .c('value').t('If a password is required to enter this room,'+ + 'you must specify the password below.').up().up() + .c('field', { + 'label': 'Password', + 'type': 'text-private', + 'var': 'muc#roomconfig_roomsecret'}) + .c('value').t('cauldronburn'); + _converse.connection._dataRecv(test_utils.createRequest(config_stanza)); - var $password = $(view.el.querySelector('input[name="muc#roomconfig_roomsecret"]')); - expect($password.length).toBe(1); - expect($password.attr('type')).toBe('password'); + test_utils.waitUntil(function () { + return $(view.el.querySelector('form.chatroom-form')).length; + }, 300).then(function () { + expect($(view.el.querySelector('form.chatroom-form')).length).toBe(1); + expect(view.el.querySelectorAll('form.chatroom-form fieldset').length).toBe(2); + var $membersonly = $(view.el.querySelector('input[name="muc#roomconfig_membersonly"]')); + expect($membersonly.length).toBe(1); + expect($membersonly.attr('type')).toBe('checkbox'); + $membersonly.prop('checked', true); - var $allowpm = $(view.el.querySelector('select[name="muc#roomconfig_allowpm"]')); - expect($allowpm.length).toBe(1); - $allowpm.val('moderators'); + var $moderated = $(view.el.querySelector('input[name="muc#roomconfig_moderatedroom"]')); + expect($moderated.length).toBe(1); + expect($moderated.attr('type')).toBe('checkbox'); + $moderated.prop('checked', true); - var $presencebroadcast = $(view.el.querySelector('select[name="muc#roomconfig_presencebroadcast"]')); - expect($presencebroadcast.length).toBe(1); - $presencebroadcast.val(['moderator']); + var $password = $(view.el.querySelector('input[name="muc#roomconfig_roomsecret"]')); + expect($password.length).toBe(1); + expect($password.attr('type')).toBe('password'); - view.el.querySelector('input[type="submit"]').click(); + var $allowpm = $(view.el.querySelector('select[name="muc#roomconfig_allowpm"]')); + expect($allowpm.length).toBe(1); + $allowpm.val('moderators'); - var $sent_stanza = $(sent_IQ.toLocaleString()); - expect($sent_stanza.find('field[var="muc#roomconfig_membersonly"] value').text()).toBe('1'); - expect($sent_stanza.find('field[var="muc#roomconfig_moderatedroom"] value').text()).toBe('1'); - 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'); - done(); + var $presencebroadcast = $(view.el.querySelector('select[name="muc#roomconfig_presencebroadcast"]')); + expect($presencebroadcast.length).toBe(1); + $presencebroadcast.val(['moderator']); + + view.el.querySelector('input[type="submit"]').click(); + + var $sent_stanza = $(sent_IQ.toLocaleString()); + expect($sent_stanza.find('field[var="muc#roomconfig_membersonly"] value').text()).toBe('1'); + expect($sent_stanza.find('field[var="muc#roomconfig_moderatedroom"] value').text()).toBe('1'); + 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'); + done(); + }); + }); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); })); @@ -1973,24 +1985,28 @@ var view = _converse.chatboxviews.get('lounge@localhost'), trimmed_chatboxes = _converse.minimized_chats; - spyOn(view, 'minimize').and.callThrough(); - spyOn(view, 'maximize').and.callThrough(); - spyOn(_converse, 'emit'); - view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called - view.el.querySelector('.toggle-chatbox-button').click(); + test_utils.waitUntil(function () { + return !_.isNull(view.el.querySelector('.toggle-bookmark')); + }, 300).then(function () { + spyOn(view, 'minimize').and.callThrough(); + spyOn(view, 'maximize').and.callThrough(); + spyOn(_converse, 'emit'); + view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called + view.el.querySelector('.toggle-chatbox-button').click(); - expect(view.minimize).toHaveBeenCalled(); - expect(_converse.emit).toHaveBeenCalledWith('chatBoxMinimized', jasmine.any(Object)); - expect(u.isVisible(view.el)).toBeFalsy(); - expect(view.model.get('minimized')).toBeTruthy(); - expect(view.minimize).toHaveBeenCalled(); - var trimmedview = trimmed_chatboxes.get(view.model.get('id')); - trimmedview.el.querySelector("a.restore-chat").click(); - expect(view.maximize).toHaveBeenCalled(); - expect(_converse.emit).toHaveBeenCalledWith('chatBoxMaximized', jasmine.any(Object)); - expect(view.model.get('minimized')).toBeFalsy(); - expect(_converse.emit.calls.count(), 3); - done(); + expect(view.minimize).toHaveBeenCalled(); + expect(_converse.emit).toHaveBeenCalledWith('chatBoxMinimized', jasmine.any(Object)); + expect(u.isVisible(view.el)).toBeFalsy(); + expect(view.model.get('minimized')).toBeTruthy(); + expect(view.minimize).toHaveBeenCalled(); + var trimmedview = trimmed_chatboxes.get(view.model.get('id')); + trimmedview.el.querySelector("a.restore-chat").click(); + expect(view.maximize).toHaveBeenCalled(); + expect(_converse.emit).toHaveBeenCalledWith('chatBoxMaximized', jasmine.any(Object)); + expect(view.model.get('minimized')).toBeFalsy(); + expect(_converse.emit.calls.count(), 3); + done(); + }); })); it("can be closed again by clicking a DOM element with class 'close-chatbox-button'", @@ -2000,19 +2016,23 @@ test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy'); var view = _converse.chatboxviews.get('lounge@localhost'); - spyOn(view, 'close').and.callThrough(); - spyOn(_converse, 'emit'); - spyOn(view, 'leave'); - view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called - view.el.querySelector('.close-chatbox-button').click(); - expect(view.close).toHaveBeenCalled(); - expect(view.leave).toHaveBeenCalled(); - // XXX: After refactoring, the chat box only gets closed - // once we have confirmation from the server. To test this, - // we would have to mock the returned presence stanza. - // See the "leave" method on the ChatRoomView. - // expect(_converse.emit).toHaveBeenCalledWith('chatBoxClosed', jasmine.any(Object)); - done(); + test_utils.waitUntil(function () { + return !_.isNull(view.el.querySelector('.toggle-bookmark')); + }, 300).then(function () { + spyOn(view, 'close').and.callThrough(); + spyOn(_converse, 'emit'); + spyOn(view, 'leave'); + view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called + view.el.querySelector('.close-chatbox-button').click(); + expect(view.close).toHaveBeenCalled(); + expect(view.leave).toHaveBeenCalled(); + // XXX: After refactoring, the chat box only gets closed + // once we have confirmation from the server. To test this, + // we would have to mock the returned presence stanza. + // See the "leave" method on the ChatRoomView. + // expect(_converse.emit).toHaveBeenCalledWith('chatBoxClosed', jasmine.any(Object)); + done(); + }); })); }); diff --git a/spec/disco.js b/spec/disco.js index 41dde28b4..17c1598e2 100644 --- a/spec/disco.js +++ b/spec/disco.js @@ -79,7 +79,7 @@ _converse.connection._dataRecv(test_utils.createRequest(stanza)); var entities = _converse.disco_entities; - expect(entities.length).toBe(1); + expect(entities.length).toBe(2); // We have an extra entity, which is the user's JID expect(entities.get(_converse.domain).features.length).toBe(5); expect(entities.get(_converse.domain).identities.length).toBe(3); expect(entities.get('localhost').features.where({'var': 'jabber:iq:version'}).length).toBe(1); @@ -159,7 +159,7 @@ _converse.connection._dataRecv(test_utils.createRequest(stanza)); entities = _converse.disco_entities; - expect(entities.length).toBe(4); + expect(entities.length).toBe(5); // We have an extra entity, which is the user's JID expect(entities.get(_converse.domain).identities.where({'category': 'conference'}).length).toBe(1); expect(entities.get(_converse.domain).identities.where({'category': 'directory'}).length).toBe(1); done(); diff --git a/spec/protocol.js b/spec/protocol.js index 9f85566bd..cc401f2f9 100644 --- a/spec/protocol.js +++ b/spec/protocol.js @@ -55,7 +55,7 @@ function (done, _converse) { var contact, sent_stanza, IQ_id, stanza; - test_utils.waitUntilFeatureSupportConfirmed(_converse, 'vcard-temp') + test_utils.waitUntilFeatureSupportConfirmed(_converse, 'localhost', 'vcard-temp') .then(function () { return test_utils.waitUntil(function () { return _converse.xmppstatus.get('fullname'); diff --git a/src/converse-bookmarks.js b/src/converse-bookmarks.js index 1a5ed8af8..c1560164a 100644 --- a/src/converse-bookmarks.js +++ b/src/converse-bookmarks.js @@ -71,26 +71,33 @@ this.setBookmarkState(); }, - generateHeadingHTML () { + renderHeading () { const { _converse } = this.__super__, - { __ } = _converse, - html = this.__super__.generateHeadingHTML.apply(this, arguments); + { __ } = _converse; + if (_converse.allow_bookmarks) { - const div = document.createElement('div'); - div.innerHTML = html; - const bookmark_button = tpl_chatroom_bookmark_toggle( - _.assignIn( - this.model.toJSON(), - { - info_toggle_bookmark: __('Bookmark this room'), - bookmarked: this.model.get('bookmarked') - } - )); - const close_button = div.querySelector('.close-chatbox-button'); - close_button.insertAdjacentHTML('afterend', bookmark_button); - return div.innerHTML; + _converse.api.disco.getIdentity('pubsub', 'pep', _converse.bare_jid).then((identity) => { + if (_.isNil(identity)) { + return; + } + const div = document.createElement('div'); + div.innerHTML = this.generateHeadingHTML(); + + const bookmark_button = tpl_chatroom_bookmark_toggle( + _.assignIn( + this.model.toJSON(), + { + info_toggle_bookmark: __('Bookmark this room'), + bookmarked: this.model.get('bookmarked') + } + )); + const close_button = div.querySelector('.close-chatbox-button'); + close_button.insertAdjacentHTML('afterend', bookmark_button); + this.el.querySelector('.chat-head-chatroom').innerHTML = div.innerHTML; + }); + } else { + return this.__super__.renderHeading.apply(this, arguments); } - return html; }, checkForReservedNick () { @@ -112,6 +119,9 @@ onBookmarked () { const icon = this.el.querySelector('.icon-pushpin'); + if (_.isNull(icon)) { + return; + } if (this.model.get('bookmarked')) { icon.classList.add('button-on'); } else { @@ -520,14 +530,23 @@ if (!_converse.allow_bookmarks) { return; } - _converse.bookmarks = new _converse.Bookmarks(); - _converse.bookmarks.fetchBookmarks().then(() => { - _converse.bookmarksview = new _converse.BookmarksView( - {'model': _converse.bookmarks} - ); - }) - .catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR)) - .then(() => { + // Only initialize bookmarks if the server supports PEP + _converse.api.disco.getIdentity('pubsub', 'pep', _converse.bare_jid).then((identity) => { + if (_.isNil(identity)) { + _converse.emit('bookmarksInitialized'); + return; + } + _converse.bookmarks = new _converse.Bookmarks(); + _converse.bookmarks.fetchBookmarks().then(() => { + _converse.bookmarksview = new _converse.BookmarksView( + {'model': _converse.bookmarks} + ); + }).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR)) + .then(() => { + _converse.emit('bookmarksInitialized'); + }); + }).catch((e) => { + _converse.log(e, Strophe.LogLevel.ERROR); _converse.emit('bookmarksInitialized'); }); }; diff --git a/src/converse-core.js b/src/converse-core.js index 16847fdaf..c340833a1 100644 --- a/src/converse-core.js +++ b/src/converse-core.js @@ -1473,6 +1473,7 @@ this.connfeedback = new this.ConnectionFeedback(); this.XMPPStatus = Backbone.Model.extend({ + initialize () { this.set({ 'status' : this.getStatus() diff --git a/src/converse-muc.js b/src/converse-muc.js index 5ddb5cd29..3c901e2ef 100644 --- a/src/converse-muc.js +++ b/src/converse-muc.js @@ -326,6 +326,9 @@ ); } const promises = [_converse.api.waitUntil('roomsAutoJoined')] + if (_converse.allow_bookmarks) { + promises.push( _converse.api.waitUntil('bookmarksInitialized')); + } Promise.all(promises).then(() => { _converse.api.rooms.open(jid); }); diff --git a/tests/mock.js b/tests/mock.js index 4b61b2042..889a276aa 100644 --- a/tests/mock.js +++ b/tests/mock.js @@ -118,6 +118,14 @@ 'debug': false }, settings || {})); _converse.ChatBoxViews.prototype.trimChat = function () {}; + + var entity = _converse.api.disco.entities.get(_converse.bare_jid, true); + entity.identities.create({ + 'category': 'pubsub', + 'type': 'pep' + }); + entity.waitUntilFeaturesDiscovered.resolve(); + window.converse_disable_effects = true; return _converse; } diff --git a/tests/utils.js b/tests/utils.js index 89bb9fb1c..d10e9ecd5 100644 --- a/tests/utils.js +++ b/tests/utils.js @@ -14,11 +14,12 @@ } utils.waitUntil = waitUntilPromise.default; - utils.waitUntilFeatureSupportConfirmed = function (_converse, feature_name) { + utils.waitUntilFeatureSupportConfirmed = function (_converse, entity_jid, feature_name) { var IQ_disco, stanza; return utils.waitUntil(function () { IQ_disco = _.filter(_converse.connection.IQ_stanzas, function (iq) { - return iq.nodeTree.querySelector('query[xmlns="http://jabber.org/protocol/disco#info"]'); + return iq.nodeTree.querySelector('query[xmlns="http://jabber.org/protocol/disco#info"]') && + iq.nodeTree.getAttribute('to') === entity_jid; }).pop(); return !_.isUndefined(IQ_disco); }, 300).then(function () {