diff --git a/dist/converse.js b/dist/converse.js index bdb183569..d61c3e34a 100644 --- a/dist/converse.js +++ b/dist/converse.js @@ -47993,8 +47993,14 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins 'info_toggle_bookmark': this.model.get('bookmarked') ? __('Unbookmark this groupchat') : __('Bookmark this groupchat'), 'bookmarked': this.model.get('bookmarked') })); - const close_button = this.el.querySelector('.close-chatbox-button'); - close_button.insertAdjacentHTML('afterend', bookmark_button); + const buttons_row = this.el.querySelector('.chatbox-buttons'); + const close_button = buttons_row.querySelector('.close-chatbox-button'); + + if (close_button) { + close_button.insertAdjacentHTML('afterend', bookmark_button); + } else { + buttons_row.insertAdjacentHTML('beforeEnd', bookmark_button); + } }, async renderHeading() { @@ -52743,10 +52749,18 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_1__["default"].plugins const div = document.createElement('div'); div.innerHTML = html; - const button = div.querySelector('.close-chatbox-button'); - button.insertAdjacentHTML('afterend', templates_chatbox_minimize_html__WEBPACK_IMPORTED_MODULE_2___default()({ + const buttons_row = div.querySelector('.chatbox-buttons'); + const button = buttons_row.querySelector('.close-chatbox-button'); + const minimize_el = templates_chatbox_minimize_html__WEBPACK_IMPORTED_MODULE_2___default()({ 'info_minimize': __('Minimize this chat box') - })); + }); + + if (button) { + button.insertAdjacentHTML('afterend', minimize_el); + } else { + buttons_row.insertAdjacentHTML('beforeEnd', minimize_el); + } + return div.innerHTML; } @@ -53601,7 +53615,7 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_5__["default"].plugins 'submit form': 'showRooms', 'click a.room-info': 'toggleRoomInfo', 'change input[name=nick]': 'setNick', - 'change input[name=server]': 'setDomain', + 'change input[name=server]': 'setDomainFromEvent', 'click .open-room': 'openRoom' }, @@ -53726,12 +53740,12 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_5__["default"].plugins showRooms(ev) { ev.preventDefault(); const data = new FormData(ev.target); - this.model.save('muc_domain', Strophe.getDomainFromJid(data.get('server'))); + this.model.setDomain(data.get('server')); this.updateRoomsList(); }, - setDomain(ev) { - this.model.save('muc_domain', Strophe.getDomainFromJid(ev.target.value)); + setDomainFromEvent(ev) { + this.model.setDomain(ev.target.value); }, setNick(ev) { @@ -53778,7 +53792,6 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_5__["default"].plugins parseRoomDataFromEvent(form) { const data = new FormData(form); const jid = data.get('chatroom'); - this.model.save('muc_domain', Strophe.getDomainFromJid(jid)); let nick; if (_converse.locked_muc_nickname) { @@ -53812,6 +53825,7 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_5__["default"].plugins jid = `${Strophe.escapeNode(data.jid)}@${_converse.muc_domain}`; } else { jid = data.jid; + this.model.setDomain(jid); } _converse.api.rooms.open(jid, _.extend(data, { @@ -55504,7 +55518,6 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_5__["default"].plugins }); function setMUCDomain(domain, controlboxview) { - _converse.muc_domain = domain; controlboxview.roomspanel.model.save('muc_domain', Strophe.getDomainFromJid(domain)); } @@ -60557,7 +60570,7 @@ __webpack_require__.r(__webpack_exports__); /* END: Removable components */ -const WHITELISTED_PLUGINS = ['converse-autocomplete', 'converse-bookmarks', 'converse-caps', 'converse-chatboxviews', 'converse-chatview', 'converse-controlbox', 'converse-dragresize', 'converse-embedded', 'converse-fullscreen', 'converse-headline', 'converse-mam-views', 'converse-message-view', 'converse-minimize', 'converse-modal', 'converse-muc-views', 'converse-notification', 'converse-oauth', 'converse-omemo', 'converse-profile', 'converse-push', 'converse-register', 'converse-roomslist', 'converse-rosterview', 'converse-singleton']; +const WHITELISTED_PLUGINS = ['converse-autocomplete', 'converse-bookmarks', 'converse-caps', 'converse-chatboxviews', 'converse-chatview', 'converse-controlbox', 'converse-dragresize', 'converse-embedded', 'converse-fullscreen', 'converse-headline', 'converse-mam-views', 'converse-message-view', 'converse-minimize', 'converse-modal', 'converse-muc-views', 'converse-notification', 'converse-omemo', 'converse-profile', 'converse-push', 'converse-register', 'converse-roomslist', 'converse-rosterview', 'converse-singleton']; const initialize = _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_22__["default"].initialize; _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_22__["default"].initialize = function (settings, callback) { @@ -67921,10 +67934,17 @@ _converse_core__WEBPACK_IMPORTED_MODULE_3__["default"].plugins.add('converse-muc _converse.RoomsPanelModel = Backbone.Model.extend({ defaults: function defaults() { return { - 'muc_domain': '', + 'muc_domain': _converse.muc_domain, 'nick': _converse.getDefaultMUCNickname() }; + }, + + setDomain(jid) { + if (!_converse.locked_muc_domain) { + this.save('muc_domain', Strophe.getDomainFromJid(jid)); + } } + }); /** * A direct MUC invitation to join a groupchat has been received diff --git a/package-lock.json b/package-lock.json index f3314f3bb..31b9e261b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8091,12 +8091,6 @@ "integrity": "sha1-elSbvZ/+FYWwzQoZHiAwVb7ldLQ=", "dev": true }, - "jquery": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.2.1.tgz", - "integrity": "sha1-XE2d5lKvbNCncBVKYxu6ErAVx4c=", - "dev": true - }, "js-base64": { "version": "2.4.9", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.9.tgz", diff --git a/package.json b/package.json index 0dd6e510d..bcaca3c02 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,6 @@ "install": "^0.9.5", "jasmine-core": "2.99.1", "jed": "1.1.1", - "jquery": "3.2.1", "jsdoc": "^3.5.5", "lerna": "^3.13.1", "lodash-template-loader": "^2.0.0", diff --git a/spec/bookmarks.js b/spec/bookmarks.js index 7132800cc..2f418d306 100644 --- a/spec/bookmarks.js +++ b/spec/bookmarks.js @@ -3,11 +3,10 @@ (function (root, factory) { define([ "jasmine", - "jquery", "mock", "test-utils" ], factory); -} (this, function (jasmine, $, mock, test_utils) { +} (this, function (jasmine, mock, test_utils) { "use strict"; const $iq = converse.env.$iq, $msg = converse.env.$msg, @@ -604,16 +603,18 @@ 'name': 'The Play', 'nick': '' }); - await test_utils.waitUntil(() => $('#chatrooms .bookmarks.rooms-list .room-item:visible').length); - expect($('#chatrooms .bookmarks.rooms-list').hasClass('collapsed')).toBeFalsy(); - expect($('#chatrooms .bookmarks.rooms-list .room-item:visible').length).toBe(1); + const el = _converse.chatboxviews.el + const selector = '#chatrooms .bookmarks.rooms-list .room-item'; + await test_utils.waitUntil(() => sizzle(selector, el).filter(u.isVisible).length); + expect(u.hasClass('collapsed', sizzle('#chatrooms .bookmarks.rooms-list', el).pop())).toBeFalsy(); + expect(sizzle(selector, el).filter(u.isVisible).length).toBe(1); expect(_converse.bookmarksview.list_model.get('toggle-state')).toBe(_converse.OPENED); - $('#chatrooms .bookmarks-toggle')[0].click(); - expect($('#chatrooms .bookmarks.rooms-list').hasClass('collapsed')).toBeTruthy(); + sizzle('#chatrooms .bookmarks-toggle', el).pop().click(); + expect(u.hasClass('collapsed', sizzle('#chatrooms .bookmarks.rooms-list', el).pop())).toBeTruthy(); expect(_converse.bookmarksview.list_model.get('toggle-state')).toBe(_converse.CLOSED); - $('#chatrooms .bookmarks-toggle')[0].click(); - expect($('#chatrooms .bookmarks.rooms-list').hasClass('collapsed')).toBeFalsy(); - expect($('#chatrooms .bookmarks.rooms-list .room-item:visible').length).toBe(1); + sizzle('#chatrooms .bookmarks-toggle', el).pop().click(); + expect(u.hasClass('collapsed', sizzle('#chatrooms .bookmarks.rooms-list', el).pop())).toBeFalsy(); + expect(sizzle(selector, el).filter(u.isVisible).length).toBe(1); expect(_converse.bookmarksview.list_model.get('toggle-state')).toBe(_converse.OPENED); done(); })); diff --git a/spec/disco.js b/spec/disco.js index 4d387719a..70f6a0f00 100644 --- a/spec/disco.js +++ b/spec/disco.js @@ -1,14 +1,13 @@ (function (root, factory) { define([ "jasmine", - "jquery", "mock", "test-utils"], factory); -} (this, function (jasmine, $, mock, test_utils) { +} (this, function (jasmine, mock, test_utils) { "use strict"; - var Strophe = converse.env.Strophe; - var $iq = converse.env.$iq; - var _ = converse.env._; + const Strophe = converse.env.Strophe; + const $iq = converse.env.$iq; + const _ = converse.env._; describe("Service Discovery", function () { @@ -19,8 +18,8 @@ null, ['discoInitialized'], {}, function (done, _converse) { - var IQ_stanzas = _converse.connection.IQ_stanzas; - var IQ_ids = _converse.connection.IQ_ids; + const IQ_stanzas = _converse.connection.IQ_stanzas; + const IQ_ids = _converse.connection.IQ_ids; test_utils.waitUntil(function () { return _.filter(IQ_stanzas, function (iq) { return iq.nodeTree.querySelector('iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]'); diff --git a/spec/headline.js b/spec/headline.js index db6d16657..de38d50a6 100644 --- a/spec/headline.js +++ b/spec/headline.js @@ -1,11 +1,10 @@ (function (root, factory) { define([ "jasmine", - "jquery", "mock", "test-utils" ], factory); -} (this, function (jasmine, $, mock, test_utils) { +} (this, function (jasmine, mock, test_utils) { "use strict"; var $msg = converse.env.$msg, _ = converse.env._, diff --git a/spec/minchats.js b/spec/minchats.js index ff16083d3..de8a2d297 100644 --- a/spec/minchats.js +++ b/spec/minchats.js @@ -11,7 +11,7 @@ it("shows chats that have been minimized", mock.initConverse( null, ['rosterGroupsFetched'], {}, - function (done, _converse) { + async function (done, _converse) { test_utils.createContacts(_converse, 'current'); _converse.api.trigger('rosterContactsFetched'); @@ -21,36 +21,32 @@ _converse.minimized_chats.initToggle(); let contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; - let chatview; - test_utils.openChatBoxFor(_converse, contact_jid) - .then(() => { - chatview = _converse.chatboxviews.get(contact_jid); - expect(chatview.model.get('minimized')).toBeFalsy(); - expect($(_converse.minimized_chats.el).is(':visible')).toBeFalsy(); - chatview.el.querySelector('.toggle-chatbox-button').click(); - expect(chatview.model.get('minimized')).toBeTruthy(); - expect($(_converse.minimized_chats.el).is(':visible')).toBeTruthy(); - expect(_converse.minimized_chats.keys().length).toBe(1); - expect(_converse.minimized_chats.keys()[0]).toBe(contact_jid); + await test_utils.openChatBoxFor(_converse, contact_jid) + let chatview = _converse.chatboxviews.get(contact_jid); + expect(chatview.model.get('minimized')).toBeFalsy(); + expect(u.isVisible(_converse.minimized_chats.el)).toBe(false); + chatview.el.querySelector('.toggle-chatbox-button').click(); + expect(chatview.model.get('minimized')).toBeTruthy(); + expect(u.isVisible(_converse.minimized_chats.el)).toBe(true); + expect(_converse.minimized_chats.keys().length).toBe(1); + expect(_converse.minimized_chats.keys()[0]).toBe(contact_jid); - contact_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost'; - return test_utils.openChatBoxFor(_converse, contact_jid); - }).then(() => { - chatview = _converse.chatboxviews.get(contact_jid); - expect(chatview.model.get('minimized')).toBeFalsy(); - chatview.el.querySelector('.toggle-chatbox-button').click(); - expect(chatview.model.get('minimized')).toBeTruthy(); - expect($(_converse.minimized_chats.el).is(':visible')).toBeTruthy(); - expect(_converse.minimized_chats.keys().length).toBe(2); - expect(_.includes(_converse.minimized_chats.keys(), contact_jid)).toBeTruthy(); - done(); - }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)) + contact_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost'; + await test_utils.openChatBoxFor(_converse, contact_jid); + chatview = _converse.chatboxviews.get(contact_jid); + expect(chatview.model.get('minimized')).toBeFalsy(); + chatview.el.querySelector('.toggle-chatbox-button').click(); + expect(chatview.model.get('minimized')).toBeTruthy(); + expect(u.isVisible(_converse.minimized_chats.el)).toBe(true); + expect(_converse.minimized_chats.keys().length).toBe(2); + expect(_.includes(_converse.minimized_chats.keys(), contact_jid)).toBeTruthy(); + done(); })); it("can be toggled to hide or show minimized chats", mock.initConverse( null, ['rosterGroupsFetched'], {}, - function (done, _converse) { + async function (done, _converse) { test_utils.createContacts(_converse, 'current'); _converse.api.trigger('rosterContactsFetched'); @@ -60,22 +56,19 @@ _converse.minimized_chats.initToggle(); const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; - test_utils.openChatBoxFor(_converse, contact_jid) - .then(() => { - const chatview = _converse.chatboxviews.get(contact_jid); - expect(u.isVisible(_converse.minimized_chats.el)).toBeFalsy(); - chatview.model.set({'minimized': true}); - expect(u.isVisible(_converse.minimized_chats.el)).toBeTruthy(); - expect(_converse.minimized_chats.keys().length).toBe(1); - expect(_converse.minimized_chats.keys()[0]).toBe(contact_jid); - expect(u.isVisible(_converse.minimized_chats.el.querySelector('.minimized-chats-flyout'))).toBeTruthy(); - expect(_converse.minimized_chats.toggleview.model.get('collapsed')).toBeFalsy(); - _converse.minimized_chats.el.querySelector('#toggle-minimized-chats').click(); - return test_utils.waitUntil(() => u.isVisible(_converse.minimized_chats.el.querySelector('.minimized-chats-flyout'))); - }).then(() => { - expect(_converse.minimized_chats.toggleview.model.get('collapsed')).toBeTruthy(); - done(); - }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)) + await test_utils.openChatBoxFor(_converse, contact_jid); + const chatview = _converse.chatboxviews.get(contact_jid); + expect(u.isVisible(_converse.minimized_chats.el)).toBeFalsy(); + chatview.model.set({'minimized': true}); + expect(u.isVisible(_converse.minimized_chats.el)).toBeTruthy(); + expect(_converse.minimized_chats.keys().length).toBe(1); + expect(_converse.minimized_chats.keys()[0]).toBe(contact_jid); + expect(u.isVisible(_converse.minimized_chats.el.querySelector('.minimized-chats-flyout'))).toBeTruthy(); + expect(_converse.minimized_chats.toggleview.model.get('collapsed')).toBeFalsy(); + _converse.minimized_chats.el.querySelector('#toggle-minimized-chats').click(); + await test_utils.waitUntil(() => u.isVisible(_converse.minimized_chats.el.querySelector('.minimized-chats-flyout'))); + expect(_converse.minimized_chats.toggleview.model.get('collapsed')).toBeTruthy(); + done(); })); it("shows the number messages received to minimized chats", diff --git a/spec/muc.js b/spec/muc.js index 15e6bbf99..12ad2f5b5 100644 --- a/spec/muc.js +++ b/spec/muc.js @@ -1231,7 +1231,7 @@ /* Server responds with the configuration form. * See: // https://xmpp.org/extensions/xep-0045.html#example-165 */ - var config_stanza = $iq({from: 'coven@chat.shakespeare.lit', + const config_stanza = $iq({from: 'coven@chat.shakespeare.lit', 'id': IQ_id, 'to': 'dummy@localhost/desktop', 'type': 'result'}) @@ -1712,7 +1712,7 @@ it("allows the user to invite their roster contacts to enter the groupchat", mock.initConverse( - null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, + null, ['rosterGroupsFetched', 'chatBoxesFetched'], {'view_mode': 'fullscreen'}, async function (done, _converse) { test_utils.createContacts(_converse, 'current'); // We need roster contacts, so that we have someone to invite diff --git a/spec/notification.js b/spec/notification.js index 96d555955..0dc131c86 100644 --- a/spec/notification.js +++ b/spec/notification.js @@ -1,6 +1,6 @@ (function (root, factory) { - define(["jquery", "jasmine", "mock", "test-utils"], factory); -} (this, function ($, jasmine, mock, test_utils) { + define(["jasmine", "mock", "test-utils"], factory); +} (this, function (jasmine, mock, test_utils) { "use strict"; const Strophe = converse.env.Strophe, _ = converse.env._, diff --git a/spec/protocol.js b/spec/protocol.js index 3d0573f72..307e38779 100644 --- a/spec/protocol.js +++ b/spec/protocol.js @@ -1,10 +1,9 @@ (function (root, factory) { define([ "jasmine", - "jquery", "mock", "test-utils"], factory); -} (this, function (jasmine, $, mock, test_utils) { +} (this, function (jasmine, mock, test_utils) { "use strict"; const Strophe = converse.env.Strophe; const $iq = converse.env.$iq; @@ -212,16 +211,16 @@ expect(_converse.roster.updateContact).toHaveBeenCalled(); // Check that the user is now properly shown as a pending // contact in the roster. - await test_utils.waitUntil(function () { - var $header = $('a:contains("Pending contacts")'); - var $contacts = $header.parent().find('li:visible'); - return $contacts.length; + await test_utils.waitUntil(() => { + const header = sizzle('a:contains("Pending contacts")', _converse.rosterview.el).pop(); + const contacts = _.filter(header.parentElement.querySelectorAll('li'), u.isVisible); + return contacts.length; }, 600); - var $header = $('a:contains("Pending contacts")'); - var $contacts = $header.parent().find('li'); - expect($contacts.length).toBe(1); - expect($contacts.is(':visible')).toBeTruthy(); + let header = sizzle('a:contains("Pending contacts")', _converse.rosterview.el).pop(); + let contacts = header.parentElement.querySelectorAll('li'); + expect(contacts.length).toBe(1); + expect(u.isVisible(contacts[0])).toBe(true); spyOn(contact, "ackSubscribe").and.callThrough(); /* Here we assume the "happy path" that the contact @@ -285,10 +284,10 @@ const header = sizzle('a:contains("My contacts")', _converse.rosterview.el); return sizzle('li', header[0].parentNode).filter(l => u.isVisible(l)).length; }, 600); - const header = sizzle('a:contains("My contacts")', _converse.rosterview.el); + header = sizzle('a:contains("My contacts")', _converse.rosterview.el); expect(header.length).toBe(1); expect(u.isVisible(header[0])).toBeTruthy(); - const contacts = header[0].parentNode.querySelectorAll('li'); + contacts = header[0].parentNode.querySelectorAll('li'); expect(contacts.length).toBe(1); // Check that it has the right classes and text expect(u.hasClass('to', contacts[0])).toBeTruthy(); @@ -360,8 +359,8 @@ expect(_converse.roster.updateContact).toHaveBeenCalled(); // The class on the contact will now have switched. - expect($contacts.hasClass('to')).toBeFalsy(); - expect($contacts.hasClass('both')).toBeTruthy(); + expect(u.hasClass('to', contacts[0])).toBe(false); + expect(u.hasClass('both', contacts[0])).toBe(true); done(); })); @@ -471,11 +470,11 @@ sent_IQ = iq; IQ_id = sendIQ.bind(this)(iq, callback, errback); }); - const $header = $('a:contains("My contacts")'); - await test_utils.waitUntil(() => $header.parent().find('li').length); + const header = sizzle('a:contains("My contacts")', _converse.rosterview.el).pop(); + await test_utils.waitUntil(() => header.parentElement.querySelectorAll('li').length); // remove the first user - $header.parent().find('li .remove-xmpp-contact').get(0).click(); + header.parentElement.querySelector('li .remove-xmpp-contact').click(); expect(window.confirm).toHaveBeenCalled(); /* Section 8.6 Removing a Roster Item and Cancelling All @@ -515,17 +514,18 @@ it("Receiving a subscription request", mock.initConverse( null, ['rosterGroupsFetched'], {}, - function (done, _converse) { + async function (done, _converse) { spyOn(_converse.api, "trigger"); test_utils.openControlBox(_converse); - test_utils.createContacts(_converse, 'current'); // Create some contacts so that we can test positioning + // Create some contacts so that we can test positioning + test_utils.createContacts(_converse, 'current'); /* */ - var stanza = $pres({ + const stanza = $pres({ 'to': _converse.bare_jid, 'from': 'contact@example.org', 'type': 'subscribe' @@ -533,19 +533,17 @@ 'xmlns': Strophe.NS.NICK, }).t('Clint Contact'); _converse.connection._dataRecv(test_utils.createRequest(stanza)); - return test_utils.waitUntil(function () { - var $header = $('a:contains("Contact requests")'); - var $contacts = $header.parent().find('li:visible'); - return $contacts.length; - }, 600).then(function () { - expect(_converse.api.trigger).toHaveBeenCalledWith('contactRequest', jasmine.any(Object)); - var $header = $('a:contains("Contact requests")'); - expect($header.length).toBe(1); - expect($header.is(":visible")).toBeTruthy(); - var $contacts = $header.parent().find('li'); - expect($contacts.length).toBe(1); - done(); - }); + await test_utils.waitUntil(() => { + const header = sizzle('a:contains("Contact requests")', _converse.rosterview.el).pop(); + const contacts = _.filter(header.parentElement.querySelectorAll('li'), u.isVisible); + return contacts.length; + }, 300); + expect(_converse.api.trigger).toHaveBeenCalledWith('contactRequest', jasmine.any(Object)); + const header = sizzle('a:contains("Contact requests")', _converse.rosterview.el).pop(); + expect(u.isVisible(header)).toBe(true); + const contacts = header.parentElement.querySelectorAll('li'); + expect(contacts.length).toBe(1); + done(); })); }); }); diff --git a/spec/register.js b/spec/register.js index 26d9a80eb..9314bc03e 100644 --- a/spec/register.js +++ b/spec/register.js @@ -319,7 +319,7 @@ max-age="0">iVBORw0KGgoAAAANSUhEUgAAALQAAAA8BAMAAAA9AI20AAAAMFBMVEX///8AAADf39+fn59fX19/f3+/v78fHx8/Pz9PT08bGxsvLy9jY2NTU1MXFxcnJyc84bkWAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAERUlEQVRYhe1WTXMaRxDdDxY4JWpYvDinpVyxdATLin0MiRLlCHEi+7hYUcVHTSI7urhK6yr5//gn5N/4Z7inX89+CQkTcFUO6gOwS8/r7tdvesbzvoT5ROR5JJ9bB97xAK22XWAY1WznlnUr7QaAzSOsWufXQ6wH/FmO60b4D936LJr8TWRwW4SNgOsodZr8m4vZUoRt2xZ3xHXgna1FCE5+f5aWwPU//bXgg8eHjyqPp4aXJeOlwLUIt0O39zOvPWW3WfHmCCkli816FxlK0rnFGKZ484dN+eIXsw1R+G+JfjwgOpMnm+r5SxA63gS2Q8MchO1RLN8jSn4W4F5OPed2evhTthKLG3bsfjLL874XGBpWHLrU0953i/ev7JsfViHbhsWSQTunJDOppeAe0hVGokJUHBOphmjrbBlgabviJKXbIP0B//gKSBHZh2rvJnQp3wsapMFz+VsTPNhPr0Hn9N57YOjywaxFSU6S79fUF39KBDgnt6yjZOeSffk+4IXDZovbQl9E96m34EzQKMepQcbzijAGiBmDsO+LaqzqG3m3kEf+DQ2mY+vdk5c2n2Iaj5QGi6n59FHDmcuP4t8MGlRaF39P6ENyIaB2EXdpjLnQq9IgdVxfax3ilBc10u4gowX9K6BaKiZNmCC7CF/WpkJvWxN00OjuoqGYLqAnpILLE68Ymrt9M0S9hcznUJ8RykdlLalUfFaDjvA8pT2kxmsl5fuMaM6mSWUpUhDoudSucdhiZFDwphEHwsMwhEpH0jsm+/UBK2wCzFIiitalN7YjWkyIBgTNPgpDXX4rjk4UH+yPPgfK4HNZQCP/KZ0fGnrnKl8+pXl3X7FwZuwNUdwDGO+BjPUn6XaKtbkm+MJ6vtaXSnIz6wBT/m+VvZNIhz7ayabQLSeRQDmYkjt0KlmHDa555v9DzFxx+CCvCG4K3dbx6mTYtfPs1Dgdh0i3W+cl4lnnhblMKKBBA23X1Ezc3E5ZoPS5KHjPiU1rKTviYe1fTsa6e3UwXGWI4ykB8uiGqkmA6Cbf3K4JTH3LOBlbX+yPWll57LKVeH8CTEvyVPV2TXL8kPnPqtA51CaFYxOH2rJoZunSnvsSj48WiaDccl6KEgiMSarITsa+rWWBnqFloYlT1qWW2GKw9nPSbEvoVHFst967XgNQjxdA66Q6VFEUh488xfaSo7cHB52XYzA4eRlVteeT8ostWfuPea0oF6MwzlwgZE9gQI+uUV0gzK+WlpUrNI8juhhX/OyNwZnRrsDfxOqS1aDR+gC6NUPvJpvQeVZ9eiNr9aDUuddY3bLnA4tH4r/49UboznH1ia8PV/uP3WUB3dxtzj1uxfDZgbEbZx17Itwrf0Jyc8N4en+5dhivtKeYjGJ8yXgUzKvSU/uWJZmsuAYtseDku+K3zMHi4lC1h0suPmtZaEp2tm3hEV2lXwb6zu7szv6f9glF5rPGT5xR7AAAAABJRU5ErkJggg== You need a client that supports x:data and CAPTCHA to register - `); _converse.connection._dataRecv(test_utils.createRequest(stanza)); expect(registerview.form_type).toBe('xform'); expect(registerview.el.querySelectorAll('#converse-register input[required="required"]').length).toBe(3); diff --git a/spec/roster.js b/spec/roster.js index b992ecbf0..0a73ed063 100644 --- a/spec/roster.js +++ b/spec/roster.js @@ -1,6 +1,6 @@ (function (root, factory) { - define(["jquery", "jasmine", "mock", "test-utils"], factory); -} (this, function ($, jasmine, mock, test_utils) { + define(["jasmine", "mock", "test-utils"], factory); +} (this, function (jasmine, mock, test_utils) { const $iq = converse.env.$iq; const $msg = converse.env.$msg; const $pres = converse.env.$pres; @@ -11,7 +11,7 @@ const checkHeaderToggling = async function (group) { - var toggle = group.querySelector('a.group-toggle'); + const toggle = group.querySelector('a.group-toggle'); expect(u.isVisible(group)).toBeTruthy(); expect(group.querySelectorAll('ul.collapsed').length).toBe(0); expect(u.hasClass('fa-caret-right', toggle.firstElementChild)).toBeFalsy(); @@ -22,7 +22,7 @@ expect(u.hasClass('fa-caret-right', toggle.firstElementChild)).toBeTruthy(); expect(u.hasClass('fa-caret-down', toggle.firstElementChild)).toBeFalsy(); toggle.click(); - await test_utils.waitUntil(() => group.querySelectorAll('li').length === $(group).find('li:visible').length); + await test_utils.waitUntil(() => group.querySelectorAll('li').length === _.filter(group.querySelectorAll('li'), u.isVisible).length); expect(u.hasClass('fa-caret-right', toggle.firstElementChild)).toBeFalsy(); expect(u.hasClass('fa-caret-down', toggle.firstElementChild)).toBeTruthy(); }; @@ -120,219 +120,180 @@ it("will only appear when roster contacts flow over the visible area", mock.initConverse( null, ['rosterGroupsFetched'], {}, - function (done, _converse) { + async function (done, _converse) { - var $filter = $(_converse.rosterview.el.querySelector('.roster-filter')); + var filter = _converse.rosterview.el.querySelector('.roster-filter'); var names = mock.cur_names; test_utils.openControlBox(); _converse.rosterview.update(); // XXX: Will normally called as event handler - expect($filter.length).toBe(1); - test_utils.waitUntil(function () { - return !$filter.is(':visible'); - }).then(function () { - for (var i=0; i !u.isVisible(filter)); + for (var i=0; i $roster.find('li:visible').length === 15, 600) - .then(function (contacts) { - expect($roster.find('ul.roster-group-contacts:visible').length).toBe(5); - $filter[0].value = "candice"; - u.triggerEvent($filter[0], "keydown", "KeyboardEvent"); - return test_utils.waitUntil(() => $roster.find('li:visible').length === 1, 600); - }).then(function (contacts) { - // Only one roster contact is now visible - expect($roster.find('li:visible').length).toBe(1); - expect($roster.find('li:visible').eq(0).text().trim()).toBe('Candice van der Knijff'); - // Only one foster group is still visible - expect($roster.find('.roster-group:visible').length).toBe(1); - expect(_.trim($roster.find('.roster-group:visible a.group-toggle').eq(0).text())).toBe('colleagues'); + const contacts = await test_utils.waitUntil(() => (sizzle('li', roster).filter(u.isVisible).length === 15), 600); + expect(sizzle('ul.roster-group-contacts', roster).filter(u.isVisible).length).toBe(5); + filter.value = "candice"; + u.triggerEvent(filter, "keydown", "KeyboardEvent"); + await test_utils.waitUntil(() => (sizzle('li', roster).filter(u.isVisible).length === 1), 600); + // Only one roster contact is now visible + let visible_contacts = sizzle('li', roster).filter(u.isVisible); + expect(visible_contacts.length).toBe(1); + expect(visible_contacts.pop().textContent.trim()).toBe('Candice van der Knijff'); + // Only one foster group is still visible + expect(sizzle('.roster-group', roster).filter(u.isVisible).length).toBe(1); + const visible_group = sizzle('.roster-group', roster).filter(u.isVisible).pop(); + expect(visible_group.querySelector('a.group-toggle').textContent.trim()).toBe('colleagues'); - $filter = $(_converse.rosterview.el).find('.roster-filter'); - $filter.val("an"); - u.triggerEvent($filter[0], "keydown", "KeyboardEvent"); - - return test_utils.waitUntil(function () { - return $roster.find('li:visible').length === 5; - }, 600) - }).then(function (contacts) { - // Five roster contact is now visible - expect($roster.find('li:visible').length).toBe(5); - // Four groups are still visible - var $groups = $roster.find('.roster-group:visible a.group-toggle'); - expect($groups.length).toBe(4); - expect(_.trim($groups.eq(0).text())).toBe('colleagues'); - expect(_.trim($groups.eq(1).text())).toBe('Family'); - expect(_.trim($groups.eq(2).text())).toBe('friends & acquaintences'); - expect(_.trim($groups.eq(3).text())).toBe('ænemies'); + filter = _converse.rosterview.el.querySelector('.roster-filter'); + filter.value = "an"; + u.triggerEvent(filter, "keydown", "KeyboardEvent"); + await test_utils.waitUntil(() => (sizzle('li', roster).filter(u.isVisible).length === 5), 600); - $filter = $(_converse.rosterview.el).find('.roster-filter'); - $filter.val("xxx"); - u.triggerEvent($filter[0], "keydown", "KeyboardEvent"); + visible_contacts = sizzle('li', roster).filter(u.isVisible); + expect(visible_contacts.length).toBe(5); - return test_utils.waitUntil(function () { - return $roster.find('li:visible').length === 0; - }, 600) - }).then(function () { - expect($roster.find('ul.roster-group-contacts:visible a.group-toggle').length).toBe(0); - $filter = $(_converse.rosterview.el).find('.roster-filter'); - $filter.val(""); // Check that contacts are shown again, when the filter string is cleared. - u.triggerEvent($filter[0], "keydown", "KeyboardEvent"); - return test_utils.waitUntil(function () { - return $roster.find('li:visible').length === 15; - }, 600) - }).then(function () { - expect($roster.find('ul.roster-group-contacts:visible').length).toBe(5); - _converse.roster_groups = false; - done(); - }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); + let visible_groups = sizzle('.roster-group', roster).filter(u.isVisible).map(el => el.querySelector('a.group-toggle')); + expect(visible_groups.length).toBe(4); + expect(visible_groups[0].textContent.trim()).toBe('colleagues'); + expect(visible_groups[1].textContent.trim()).toBe('Family'); + expect(visible_groups[2].textContent.trim()).toBe('friends & acquaintences'); + expect(visible_groups[3].textContent.trim()).toBe('ænemies'); + + filter = _converse.rosterview.el.querySelector('.roster-filter'); + filter.value = "xxx"; + u.triggerEvent(filter, "keydown", "KeyboardEvent"); + await test_utils.waitUntil(() => (sizzle('li', roster).filter(u.isVisible).length === 0), 600); + visible_groups = sizzle('.roster-group', roster).filter(u.isVisible).map(el => el.querySelector('a.group-toggle')); + expect(visible_groups.length).toBe(0); + + filter = _converse.rosterview.el.querySelector('.roster-filter'); + filter.value = ""; + u.triggerEvent(filter, "keydown", "KeyboardEvent"); + await test_utils.waitUntil(() => (sizzle('li', roster).filter(u.isVisible).length === 15), 600); + expect(sizzle('ul.roster-group-contacts', roster).filter(u.isVisible).length).toBe(5); + done(); })); it("will also filter out contacts added afterwards", mock.initConverse( null, ['rosterGroupsFetched'], {}, - function (done, _converse) { + async function (done, _converse) { test_utils.openControlBox(); test_utils.createGroupedContacts(_converse); - var $filter = $(_converse.rosterview.el).find('.roster-filter'); - var $roster = $(_converse.rosterview.roster_el); + const filter = _converse.rosterview.el.querySelector('.roster-filter'); + const roster = _converse.rosterview.roster_el; _converse.rosterview.filter_view.delegateEvents(); - test_utils.waitUntil(function () { - return $roster.find('li:visible').length === 15; - }, 300).then(function (contacts) { - $filter.val("an"); - u.triggerEvent($filter[0], "keydown", "KeyboardEvent"); + await test_utils.waitUntil(() => (sizzle('li', roster).filter(u.isVisible).length === 15), 600); + filter.value = "an"; + u.triggerEvent(filter, "keydown", "KeyboardEvent"); + await test_utils.waitUntil(() => (sizzle('li', roster).filter(u.isVisible).length === 5), 600); - return test_utils.waitUntil(function () { - return $roster.find('li:visible').length === 5; - }, 500) - }).then(function (contacts) { - // Five roster contact is now visible - expect($roster.find('li:visible').length).toBe(5); - // Four groups are still visible - var $groups = $roster.find('.roster-group:visible a.group-toggle'); - expect($groups.length).toBe(4); - expect(_.trim($groups.eq(0).text())).toBe('colleagues'); - expect(_.trim($groups.eq(1).text())).toBe('Family'); - expect(_.trim($groups.eq(2).text())).toBe('friends & acquaintences'); - expect(_.trim($groups.eq(3).text())).toBe('ænemies'); + // Five roster contact is now visible + const visible_contacts = sizzle('li', roster).filter(u.isVisible); + expect(visible_contacts.length).toBe(5); + let visible_groups = sizzle('.roster-group', roster).filter(u.isVisible).map(el => el.querySelector('a.group-toggle')); + expect(visible_groups.length).toBe(4); + expect(visible_groups[0].textContent.trim()).toBe('colleagues'); + expect(visible_groups[1].textContent.trim()).toBe('Family'); + expect(visible_groups[2].textContent.trim()).toBe('friends & acquaintences'); + expect(visible_groups[3].textContent.trim()).toBe('ænemies'); - _converse.roster.create({ - jid: 'latecomer@localhost', - subscription: 'both', - ask: null, - groups: ['newgroup'], - fullname: 'Marty McLatecomer' - }); - return test_utils.waitUntil(function () { - return $roster.find('.roster-group[data-group="newgroup"] li').length; - }, 300); - }).then(function (contacts) { - // The "newgroup" group doesn't appear - expect($roster.find('.roster-group:visible').length).toBe(4); - expect($roster.find('.roster-group').length).toBe(6); - done(); + _converse.roster.create({ + jid: 'latecomer@localhost', + subscription: 'both', + ask: null, + groups: ['newgroup'], + fullname: 'Marty McLatecomer' }); + await test_utils.waitUntil(() => sizzle('.roster-group[data-group="newgroup"] li', roster).length, 300); + visible_groups = sizzle('.roster-group', roster).filter(u.isVisible).map(el => el.querySelector('a.group-toggle')); + // The "newgroup" group doesn't appear + expect(visible_groups.length).toBe(4); + expect(visible_groups[0].textContent.trim()).toBe('colleagues'); + expect(visible_groups[1].textContent.trim()).toBe('Family'); + expect(visible_groups[2].textContent.trim()).toBe('friends & acquaintences'); + expect(visible_groups[3].textContent.trim()).toBe('ænemies'); + expect(roster.querySelectorAll('.roster-group').length).toBe(6); + done(); })); it("can be used to filter the groups shown", mock.initConverse( - null, ['rosterGroupsFetched'], {}, - function (done, _converse) { + null, ['rosterGroupsFetched'], {'roster_groups': true}, + async function (done, _converse) { - _converse.roster_groups = true; test_utils.openControlBox(); test_utils.createGroupedContacts(_converse); _converse.rosterview.filter_view.delegateEvents(); - var $roster = $(_converse.rosterview.roster_el); + var roster = _converse.rosterview.roster_el; var button = _converse.rosterview.el.querySelector('span[data-type="groups"]'); button.click(); - test_utils.waitUntil(function () { - return $roster.find('li:visible').length === 15; - }, 600).then(function () { - expect($roster.find('div.roster-group:visible a.group-toggle').length).toBe(5); + const contacts = await test_utils.waitUntil(() => (sizzle('li', roster).filter(u.isVisible).length === 15), 600); + expect(sizzle('.roster-group', roster).filter(u.isVisible).length).toBe(5); - var filter = _converse.rosterview.el.querySelector('.roster-filter'); - filter.value = "colleagues"; - u.triggerEvent(filter, "keydown", "KeyboardEvent"); + var filter = _converse.rosterview.el.querySelector('.roster-filter'); + filter.value = "colleagues"; + u.triggerEvent(filter, "keydown", "KeyboardEvent"); - return test_utils.waitUntil(function () { - return $roster.find('div.roster-group:not(.collapsed) a.group-toggle').length === 1; - }, 600); - }).then(function () { - expect(_.trim($roster.find('div.roster-group:not(.collapsed) a').eq(0).text())).toBe('colleagues'); - expect($roster.find('div.roster-group:not(.collapsed) li:visible').length).toBe(3); + await test_utils.waitUntil(() => (sizzle('div.roster-group:not(.collapsed)', roster).length === 1), 600); + expect(sizzle('div.roster-group:not(.collapsed)', roster).pop().firstElementChild.textContent.trim()).toBe('colleagues'); + expect(sizzle('div.roster-group:not(.collapsed) li', roster).filter(u.isVisible).length).toBe(3); + // Check that all contacts under the group are shown + expect(sizzle('div.roster-group:not(.collapsed) li', roster).filter(l => !u.isVisible(l)).length).toBe(0); - // Check that all contacts under the group are shown - expect($roster.find('div.roster-group:not(.collapsed) li:hidden').length).toBe(0); + filter = _converse.rosterview.el.querySelector('.roster-filter'); + filter.value = "xxx"; + u.triggerEvent(filter, "keydown", "KeyboardEvent"); - var filter = _converse.rosterview.el.querySelector('.roster-filter'); - filter.value = "xxx"; - u.triggerEvent(filter, "keydown", "KeyboardEvent"); + await test_utils.waitUntil(() => (roster.querySelectorAll('div.roster-group.collapsed').length === 5), 700); + expect(roster.querySelectorAll('div.roster-group:not(.collapsed) a').length).toBe(0); - return test_utils.waitUntil(function () { - return $roster.find('div.roster-group.collapsed a.group-toggle').length === 5; - }, 700); - }).then(function () { - expect($roster.find('div.roster-group:not(.collapsed) a').length).toBe(0); - - var filter = _converse.rosterview.el.querySelector('.roster-filter'); - filter.value = ""; // Check that groups are shown again, when the filter string is cleared. - u.triggerEvent(filter, "keydown", "KeyboardEvent"); - return test_utils.waitUntil(function () { - return $roster.find('div.roster-group.collapsed a.group-toggle').length === 0; - }, 600); - }).then(function () { - expect($roster.find('div.roster-group:not(collapsed)').length).toBe(5); - expect($roster.find('div.roster-group:not(collapsed) li').length).toBe(15); - done(); - }); + filter = _converse.rosterview.el.querySelector('.roster-filter'); + filter.value = ""; // Check that groups are shown again, when the filter string is cleared. + u.triggerEvent(filter, "keydown", "KeyboardEvent"); + await test_utils.waitUntil(() => (roster.querySelectorAll('div.roster-group.collapsed').length === 0), 700); + expect(sizzle('div.roster-group:not(collapsed)', roster).length).toBe(5); + expect(sizzle('div.roster-group:not(collapsed) li', roster).length).toBe(15); + done(); })); it("has a button with which its contents can be cleared", @@ -375,25 +336,25 @@ var button = _converse.rosterview.el.querySelector('span[data-type="state"]'); button.click(); - var $roster = $(_converse.rosterview.roster_el); - test_utils.waitUntil(() => $roster.find('li:visible').length === 15, 500).then(function () { + var roster = _converse.rosterview.roster_el; + test_utils.waitUntil(() => sizzle('li', roster).filter(u.isVisible).length === 15, 500).then(function () { var filter = _converse.rosterview.el.querySelector('.state-type'); - expect($roster.find('ul.roster-group-contacts:visible').length).toBe(5); + expect(sizzle('ul.roster-group-contacts', roster).filter(u.isVisible).length).toBe(5); filter.value = "online"; u.triggerEvent(filter, 'change'); - return test_utils.waitUntil(() => $roster.find('li:visible').length === 1, 500); + return test_utils.waitUntil(() => sizzle('li', roster).filter(u.isVisible).length === 1, 500); }).then(function () { - expect($roster.find('li:visible').eq(0).text().trim()).toBe('Rinse Sommer'); - expect($roster.find('ul.roster-group-contacts:visible').length).toBe(1); + expect(sizzle('li', roster).filter(u.isVisible).pop().textContent.trim()).toBe('Rinse Sommer'); + expect(sizzle('ul.roster-group-contacts', roster).filter(u.isVisible).length).toBe(1); var filter = _converse.rosterview.el.querySelector('.state-type'); filter.value = "dnd"; u.triggerEvent(filter, 'change'); return test_utils.waitUntil(function () { - return $roster.find('li:visible').eq(0).text().trim() === 'Annegreet Gomez'; + return sizzle('li', roster).filter(u.isVisible).pop().textContent.trim() === 'Annegreet Gomez'; }, 900) }).then(function () { - expect($roster.find('ul.roster-group-contacts:visible').length).toBe(1); + expect(sizzle('ul.roster-group-contacts', roster).filter(u.isVisible).length).toBe(1); done(); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); })); @@ -486,11 +447,10 @@ it("can share contacts with other roster groups", mock.initConverse( - null, ['rosterGroupsFetched'], {}, - function (done, _converse) { + null, ['rosterGroupsFetched'], {'roster_groups': true}, + async function (done, _converse) { - _converse.roster_groups = true; - var groups = ['colleagues', 'friends']; + const groups = ['colleagues', 'friends']; spyOn(_converse.rosterview, 'update').and.callThrough(); test_utils.openControlBox(); _converse.rosterview.render(); @@ -503,18 +463,15 @@ fullname: mock.cur_names[i] }); } - test_utils.waitUntil(function () { - return $(_converse.rosterview.el).find('li:visible').length === 30; - }, 600).then(function () { - // Check that usernames appear alphabetically per group - _.each(groups, function (name) { - var $contacts = $(_converse.rosterview.el).find('.roster-group[data-group="'+name+'"] ul li'); - var names = $.map($contacts, function (o) { return $(o).text().trim(); }); - expect(names).toEqual(_.clone(names).sort()); - expect(names.length).toEqual(mock.cur_names.length); - }); - done(); + await test_utils.waitUntil(() => (sizzle('li', _converse.rosterview.el).filter(u.isVisible).length === 30), 600); + // Check that usernames appear alphabetically per group + _.each(groups, function (name) { + const contacts = sizzle('.roster-group[data-group="'+name+'"] ul li', _converse.rosterview.el); + const names = contacts.map(o => o.textContent.trim()); + expect(names).toEqual(_.clone(names).sort()); + expect(names.length).toEqual(mock.cur_names.length); }); + done(); })); it("remembers whether it is closed or opened", @@ -568,7 +525,7 @@ async function (done, _converse) { _addContacts(_converse); - await test_utils.waitUntil(() => $(_converse.rosterview.el).find('.roster-group:visible li').length, 1000); + await test_utils.waitUntil(() => sizzle('.roster-group', _converse.rosterview.el).filter(u.isVisible).map(e => e.querySelector('li')).length, 1000); await checkHeaderToggling.apply( _converse, [_converse.rosterview.get('Pending contacts').el] @@ -612,62 +569,49 @@ it("are shown in the roster when hide_offline_users", mock.initConverse( - null, ['rosterGroupsFetched'], {}, - function (done, _converse) { + null, ['rosterGroupsFetched'], {'hide_offline_users': true}, + async function (done, _converse) { - _converse.hide_offline_users = true; spyOn(_converse.rosterview, 'update').and.callThrough(); _addContacts(_converse); - test_utils.waitUntil(function () { - return $(_converse.rosterview.el).find('li:visible').length; - }, 500) - .then(function () { - expect(_converse.rosterview.update).toHaveBeenCalled(); - expect($(_converse.rosterview.el).is(':visible')).toBe(true); - expect($(_converse.rosterview.el).find('li:visible').length).toBe(3); - expect($(_converse.rosterview.el).find('ul.roster-group-contacts:visible').length).toBe(1); - done(); - }); + await test_utils.waitUntil(() => sizzle('li', _converse.rosterview.el).filter(u.isVisible).length, 500) + expect(_converse.rosterview.update).toHaveBeenCalled(); + expect(u.isVisible(_converse.rosterview.el)).toBe(true); + expect(sizzle('li', _converse.rosterview.el).filter(u.isVisible).length).toBe(3); + expect(sizzle('ul.roster-group-contacts', _converse.rosterview.el).filter(u.isVisible).length).toBe(1); + done(); })); it("can be removed by the user", mock.initConverse( null, ['rosterGroupsFetched'], {}, - function (done, _converse) { + async function (done, _converse) { _addContacts(_converse); - var name = mock.pend_names[0]; - var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost'; - var contact = _converse.roster.get(jid); + const name = mock.pend_names[0]; + const jid = name.replace(/ /g,'.').toLowerCase() + '@localhost'; + const contact = _converse.roster.get(jid); var sent_IQ; spyOn(window, 'confirm').and.returnValue(true); spyOn(contact, 'unauthorize').and.callFake(function () { return contact; }); spyOn(contact, 'removeFromRoster').and.callThrough(); - test_utils.waitUntil(function () { - return $(_converse.rosterview.el).find(".pending-contact-name:contains('"+name+"')").length; - }, 700).then(function () { - - var sendIQ = _converse.connection.sendIQ; - spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) { - sent_IQ = iq; - callback(); - }); - $(_converse.rosterview.el).find(".pending-contact-name:contains('"+name+"')") - .parent().siblings('.remove-xmpp-contact')[0].click(); - return test_utils.waitUntil(function () { - return $(_converse.rosterview.el).find(".pending-contact-name:contains('"+name+"')").length === 0 - }, 1000) - }).then(function () { - expect(window.confirm).toHaveBeenCalled(); - expect(contact.removeFromRoster).toHaveBeenCalled(); - expect(sent_IQ.toLocaleString()).toBe( - ``+ - ``+ - ``+ - ``+ - ``); - done(); + await test_utils.waitUntil(() => sizzle(".pending-contact-name:contains('"+name+"')", _converse.rosterview.el).length, 700); + var sendIQ = _converse.connection.sendIQ; + spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) { + sent_IQ = iq; + callback(); }); + sizzle(`.remove-xmpp-contact[title="Click to remove ${name} as a contact"]`, _converse.rosterview.el).pop().click(); + await test_utils.waitUntil(() => (sizzle(".pending-contact-name:contains('"+name+"')", _converse.rosterview.el).length === 0), 1000); + expect(window.confirm).toHaveBeenCalled(); + expect(contact.removeFromRoster).toHaveBeenCalled(); + expect(sent_IQ.toLocaleString()).toBe( + ``+ + ``+ + ``+ + ``+ + ``); + done(); })); it("do not have a header if there aren't any", @@ -692,8 +636,7 @@ return u.isVisible(el) && _.filter(el.querySelectorAll('li'), li => u.isVisible(li)).length; }, 700) - $(_converse.rosterview.el).find(".pending-contact-name:contains('"+name+"')") - .parent().siblings('.remove-xmpp-contact')[0].click(); + sizzle(`.remove-xmpp-contact[title="Click to remove ${name} as a contact"]`, _converse.rosterview.el).pop().click(); expect(window.confirm).toHaveBeenCalled(); expect(_converse.connection.sendIQ).toHaveBeenCalled(); @@ -704,21 +647,17 @@ it("is shown when a new private message is received", mock.initConverse( null, ['rosterGroupsFetched'], {}, - function (done, _converse) { + async function (done, _converse) { _addContacts(_converse); - return test_utils.waitUntil(() => _converse.roster.at(0).vcard.get('fullname')) - .then(function () { - var name; - spyOn(window, 'confirm').and.returnValue(true); - for (var i=0; i _converse.roster.at(0).vcard.get('fullname')) + spyOn(window, 'confirm').and.returnValue(true); + for (var i=0; i (result + value.textContent.trim()), ''); + expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join('')); done(); }); @@ -849,16 +787,14 @@ sent_IQ = iq; callback(); }); - $(_converse.rosterview.el).find(".open-chat:contains('"+name+"')") - .parent().find('.remove-xmpp-contact')[0].click(); - + sizzle(`.remove-xmpp-contact[title="Click to remove ${name} as a contact"]`, _converse.rosterview.el).pop().click(); expect(window.confirm).toHaveBeenCalled(); expect(sent_IQ.toLocaleString()).toBe( ``+ ``+ ``); expect(contact.removeFromRoster).toHaveBeenCalled(); - await test_utils.waitUntil(() => $(_converse.rosterview.el).find(".open-chat:contains('"+name+"')").length === 0); + await test_utils.waitUntil(() => sizzle(".open-chat:contains('"+name+"')", _converse.rosterview.el).length === 0); done(); })); @@ -876,15 +812,14 @@ ask: null, fullname: name }); - await test_utils.waitUntil(() => $(_converse.rosterview.el).find('.roster-group:visible li').length, 1000); + await test_utils.waitUntil(() => sizzle('.roster-group', _converse.rosterview.el).filter(u.isVisible).map(e => e.querySelector('li')).length, 1000); spyOn(window, 'confirm').and.returnValue(true); spyOn(contact, 'removeFromRoster').and.callThrough(); spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback) { if (typeof callback === "function") { return callback(); } }); - expect($(_converse.rosterview.el).find('.roster-group').css('display')).toEqual('block'); - $(_converse.rosterview.el).find(".open-chat:contains('"+name+"')") - .parent().find('.remove-xmpp-contact')[0].click(); + expect(u.isVisible(_converse.rosterview.el.querySelector('.roster-group'))).toBe(true); + sizzle(`.remove-xmpp-contact[title="Click to remove ${name} as a contact"]`, _converse.rosterview.el).pop().click(); expect(window.confirm).toHaveBeenCalled(); expect(_converse.connection.sendIQ).toHaveBeenCalled(); expect(contact.removeFromRoster).toHaveBeenCalled(); @@ -898,17 +833,17 @@ function (done, _converse) { _addContacts(_converse); - test_utils.waitUntil(() => $(_converse.rosterview.el).find('.roster-group li').length, 700) + test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group li').length, 700) .then(function () { var jid, t; spyOn(_converse.rosterview, 'update').and.callThrough(); - var $roster = $(_converse.rosterview.el); + const roster = _converse.rosterview.el; for (var i=0; i sizzle('.roster-group li', _converse.rosterview.el).length, 700); + var jid, t; + spyOn(_converse.rosterview, 'update').and.callThrough(); + const roster = _converse.rosterview.el; + for (var i=0; i sizzle('.roster-group li', _converse.rosterview.el).length, 500) + var jid, t; + spyOn(_converse.rosterview, 'update').and.callThrough(); + var roster = _converse.rosterview.el; + for (var i=0; i sizzle('.roster-group', _converse.rosterview.el).filter(u.isVisible).length, 900); + expect(u.isVisible(_converse.rosterview.get('Contact requests').el)).toEqual(true); + expect(sizzle('.roster-group', _converse.rosterview.el).filter(u.isVisible).map(e => e.querySelector('li')).length).toBe(1); + sizzle('.roster-group', _converse.rosterview.el).filter(u.isVisible).map(e => e.querySelector('li .decline-xmpp-request'))[0].click(); + expect(window.confirm).toHaveBeenCalled(); + expect(u.isVisible(_converse.rosterview.get('Contact requests').el)).toEqual(false); + done(); })); it("can be collapsed under their own header", mock.initConverse( null, ['rosterGroupsFetched'], {}, - function (done, _converse) { + async function (done, _converse) { test_utils.createContacts(_converse, 'requesting').openControlBox(); - test_utils.waitUntil(function () { - return $(_converse.rosterview.el).find('.roster-group:visible li').length; - }, 700).then(function () { - checkHeaderToggling.apply( - _converse, - [_converse.rosterview.get('Contact requests').el] - ).then(done); - }); + await test_utils.waitUntil(() => sizzle('.roster-group', _converse.rosterview.el).filter(u.isVisible).length, 700); + await checkHeaderToggling.apply( + _converse, + [_converse.rosterview.get('Contact requests').el] + ); + done(); })); it("can have their requests accepted by the user", @@ -1213,16 +1136,17 @@ test_utils.openControlBox(); test_utils.createContacts(_converse, 'requesting').openControlBox(); + const name = mock.req_names.sort()[0]; + const jid = name.replace(/ /g,'.').toLowerCase() + '@localhost'; + const contact = _converse.roster.get(jid); + spyOn(contact, 'authorize').and.callFake(() => contact); await test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group li').length) // TODO: Testing can be more thorough here, the user is // actually not accepted/authorized because of // mock_connection. - const jid = mock.req_names.sort()[0].replace(/ /g,'.').toLowerCase() + '@localhost'; - const contact = _converse.roster.get(jid); - spyOn(contact, 'authorize').and.callFake(() => contact); spyOn(_converse.roster, 'sendContactAddIQ').and.callFake(() => Promise.resolve()); - $(_converse.rosterview.el).find(".req-contact-name:contains('"+name+"')") - .parent().parent().find('.accept-xmpp-request')[0].click(); + const req_contact = sizzle(".req-contact-name:contains('"+name+"')", _converse.rosterview.el).pop(); + req_contact.parentElement.parentElement.querySelector('.accept-xmpp-request').click(); expect(_converse.roster.sendContactAddIQ).toHaveBeenCalled(); await test_utils.waitUntil(() => contact.authorize.calls.count()); expect(contact.authorize).toHaveBeenCalled(); @@ -1232,30 +1156,27 @@ it("can have their requests denied by the user", mock.initConverse( null, ['rosterGroupsFetched'], {}, - function (done, _converse) { + async function (done, _converse) { test_utils.createContacts(_converse, 'requesting').openControlBox(); - test_utils.waitUntil(function () { - return $(_converse.rosterview.el).find('.roster-group li').length; - }, 700).then(function () { - _converse.rosterview.update(); // XXX: Hack to make sure $roster element is attaced. - var name = mock.req_names.sort()[1]; - var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost'; - var contact = _converse.roster.get(jid); - spyOn(window, 'confirm').and.returnValue(true); - spyOn(contact, 'unauthorize').and.callFake(function () { return contact; }); - $(_converse.rosterview.el).find(".req-contact-name:contains('"+name+"')") - .parent().parent().find('.decline-xmpp-request')[0].click(); - expect(window.confirm).toHaveBeenCalled(); - expect(contact.unauthorize).toHaveBeenCalled(); - // There should now be one less contact - expect(_converse.roster.length).toEqual(mock.req_names.length-1); - done(); - }); + await test_utils.waitUntil(() => sizzle('.roster-group li', _converse.rosterview.el).length, 700); + _converse.rosterview.update(); // XXX: Hack to make sure $roster element is attaced. + const name = mock.req_names.sort()[1]; + const jid = name.replace(/ /g,'.').toLowerCase() + '@localhost'; + const contact = _converse.roster.get(jid); + spyOn(window, 'confirm').and.returnValue(true); + spyOn(contact, 'unauthorize').and.callFake(function () { return contact; }); + const req_contact = sizzle(".req-contact-name:contains('"+name+"')", _converse.rosterview.el).pop(); + req_contact.parentElement.parentElement.querySelector('.decline-xmpp-request').click(); + expect(window.confirm).toHaveBeenCalled(); + expect(contact.unauthorize).toHaveBeenCalled(); + // There should now be one less contact + expect(_converse.roster.length).toEqual(mock.req_names.length-1); + done(); })); it("are persisted even if other contacts' change their presence ", mock.initConverse( - null, ['rosterGroupsFetched'], {}, function (done, _converse) { + null, ['rosterGroupsFetched'], {}, async function (done, _converse) { /* This is a regression test. * https://github.com/jcbrand/_converse.js/issues/262 @@ -1264,38 +1185,35 @@ let stanza = $pres({from: 'data@enterprise/resource', type: 'subscribe'}); _converse.connection._dataRecv(test_utils.createRequest(stanza)); - test_utils.waitUntil(function () { - return $('a:contains("Contact requests")').length; - }, 700).then(function () { - expect(_converse.roster.pluck('jid').length).toBe(1); - expect(_.includes(_converse.roster.pluck('jid'), 'data@enterprise')).toBeTruthy(); - // Taken from the spec - // https://xmpp.org/rfcs/rfc3921.html#rfc.section.7.3 - stanza = $iq({ - to: _converse.connection.jid, - type: 'result', - id: 'roster_1' - }).c('query', { - xmlns: 'jabber:iq:roster', - }).c('item', { - jid: 'romeo@example.net', - name: 'Romeo', - subscription:'both' - }).c('group').t('Friends').up().up() - .c('item', { - jid: 'mercutio@example.org', - name: 'Mercutio', - subscription:'from' - }).c('group').t('Friends').up().up() - .c('item', { - jid: 'benvolio@example.org', - name: 'Benvolio', - subscription:'both' - }).c('group').t('Friends'); - _converse.roster.onReceivedFromServer(stanza.tree()); - expect(_.includes(_converse.roster.pluck('jid'), 'data@enterprise')).toBeTruthy(); - done(); - }); + await test_utils.waitUntil(() => sizzle('a:contains("Contact requests")', _converse.rosterview.el).length, 700); + expect(_converse.roster.pluck('jid').length).toBe(1); + expect(_.includes(_converse.roster.pluck('jid'), 'data@enterprise')).toBeTruthy(); + // Taken from the spec + // https://xmpp.org/rfcs/rfc3921.html#rfc.section.7.3 + stanza = $iq({ + to: _converse.connection.jid, + type: 'result', + id: 'roster_1' + }).c('query', { + xmlns: 'jabber:iq:roster', + }).c('item', { + jid: 'romeo@example.net', + name: 'Romeo', + subscription:'both' + }).c('group').t('Friends').up().up() + .c('item', { + jid: 'mercutio@example.org', + name: 'Mercutio', + subscription:'from' + }).c('group').t('Friends').up().up() + .c('item', { + jid: 'benvolio@example.org', + name: 'Benvolio', + subscription:'both' + }).c('group').t('Friends'); + _converse.roster.onReceivedFromServer(stanza.tree()); + expect(_.includes(_converse.roster.pluck('jid'), 'data@enterprise')).toBeTruthy(); + done(); })); }); @@ -1332,25 +1250,19 @@ it("will show fullname and jid properties on tooltip", mock.initConverse( null, ['rosterGroupsFetched'], {}, - function (done, _converse) { + async function (done, _converse) { test_utils.createContacts(_converse, 'all').openControlBox(); - test_utils.waitUntil(function () { - return $(_converse.rosterview.el).find('.roster-group li').length; - }, 700).then(function () { - var jid, name, i; - for (i=0; i sizzle('.roster-group li', _converse.rosterview.el).length, 700); + for (let i=0; i