Selaa lähdekoodia

Use Backbone.NativeView instead of Backbone.View

JC Brand 7 vuotta sitten
vanhempi
commit
671691353a

+ 4 - 1
css/converse.css

@@ -1199,7 +1199,8 @@
     animation-timing-function: ease; }
   #converse-embedded-chat .hidden,
   #conversejs .hidden {
-    opacity: 0; }
+    opacity: 0;
+    display: none; }
   #converse-embedded-chat .collapsed,
   #conversejs .collapsed {
     height: 0 !important;
@@ -2297,6 +2298,8 @@
   #conversejs .toggle-controlbox span {
     color: white; }
 
+#conversejs #controlbox #converse-register .button-cancel {
+  font-size: 90%; }
 #conversejs #controlbox .controlbox-pane {
   border-bottom-left-radius: 4px;
   border-bottom-right-radius: 4px;

+ 2 - 1
css/inverse.css

@@ -1199,7 +1199,8 @@
     animation-timing-function: ease; }
   #converse-embedded-chat .hidden,
   #conversejs .hidden {
-    opacity: 0; }
+    opacity: 0;
+    display: none; }
   #converse-embedded-chat .collapsed,
   #conversejs .collapsed {
     height: 0 !important;

+ 6 - 0
package-lock.json

@@ -1002,6 +1002,12 @@
         "underscore": "1.8.3"
       }
     },
+    "backbone.nativeview": {
+      "version": "0.3.3",
+      "resolved": "https://registry.npmjs.org/backbone.nativeview/-/backbone.nativeview-0.3.3.tgz",
+      "integrity": "sha1-dDNXM028kQKw2bsT3pFOCjXnvcQ=",
+      "dev": true
+    },
     "backbone.overview": {
       "version": "git+https://github.com/jcbrand/Backbone.Overview.git#2c37461bfa8d9e8bcf8284033d3242c57eafb52d",
       "dev": true,

+ 1 - 0
package.json

@@ -36,6 +36,7 @@
     "awesomplete-avoid-xss": "^1.1.2",
     "backbone": "1.3.3",
     "backbone.browserStorage": "0.0.3",
+    "backbone.nativeview": "^0.3.3",
     "backbone.overview": "git+https://github.com/jcbrand/Backbone.Overview.git",
     "backbone.vdomview": "git+https://github.com/jcbrand/backbone.vdomview.git",
     "bootstrap": "^3.3.7",

+ 6 - 0
sass/converse/_controlbox.scss

@@ -1,5 +1,11 @@
 #conversejs {
     #controlbox {
+        #converse-register {
+            .button-cancel {
+                font-size: 90%;
+            }
+        }
+
         .controlbox-pane {
             border-bottom-left-radius: $chatbox-border-radius;
             border-bottom-right-radius: $chatbox-border-radius;

+ 11 - 13
spec/bookmarks.js

@@ -34,15 +34,15 @@
             spyOn(view, 'renderBookmarkForm').and.callThrough();
             spyOn(view, 'closeForm').and.callThrough();
 
-            var $bookmark = view.$el.find('.icon-pushpin');
-            $bookmark.click();
+            var $bookmark = $(view.el).find('.icon-pushpin');
+            $bookmark[0].click();
             expect(view.renderBookmarkForm).toHaveBeenCalled();
 
-            view.$el.find('.button-cancel').click();
+            view.el.querySelector('.button-cancel').click();
             expect(view.closeForm).toHaveBeenCalled();
             expect($bookmark.hasClass('on-button'), false);
 
-            $bookmark.click();
+            $bookmark[0].click();
             expect(view.renderBookmarkForm).toHaveBeenCalled();
 
             /* Client uploads data:
@@ -77,11 +77,11 @@
              *  </iq>
              */
             expect(view.model.get('bookmarked')).toBeFalsy();
-            var $form = view.$el.find('.chatroom-form');
+            var $form = $(view.el).find('.chatroom-form');
             $form.find('input[name="name"]').val('Play&apos;s the Thing');
             $form.find('input[name="autojoin"]').prop('checked', true);
             $form.find('input[name="nick"]').val('JC');
-            view.$el.find('.button-primary').click();
+            view.el.querySelector('.button-primary').click();
 
             expect(view.model.get('bookmarked')).toBeTruthy();
             expect($bookmark.hasClass('on-button'), true);
@@ -160,7 +160,7 @@
 
                 test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy');
                 var view = _converse.chatboxviews.get('lounge@localhost');
-                var $bookmark_icon = view.$('.icon-pushpin');
+                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();
@@ -188,7 +188,7 @@
                 });
                 expect(_converse.bookmarks.length).toBe(1);
                 expect(view.model.get('bookmarked')).toBeTruthy();
-                var $bookmark_icon = view.$('.icon-pushpin');
+                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) {
@@ -196,7 +196,7 @@
                     IQ_id = sendIQ.bind(this)(iq, callback, errback);
                 });
                 spyOn(_converse.connection, 'getUniqueId').and.callThrough();
-                $bookmark_icon.click();
+                $bookmark_icon[0].click();
                 expect(view.toggleBookmark).toHaveBeenCalled();
                 expect($bookmark_icon.hasClass('button-on')).toBeFalsy();
                 expect(_converse.bookmarks.length).toBe(0);
@@ -409,7 +409,6 @@
                     }
                 }).length).toBe(1);
 
-                _converse.chatboxviews.get('controlbox').$('#chatrooms dl.bookmarks').html('');
                 var stanza = $iq({'to': _converse.connection.jid, 'type':'result', 'id':IQ_id})
                     .c('pubsub', {'xmlns': Strophe.NS.PUBSUB})
                         .c('items', {'node': 'storage:bookmarks'})
@@ -463,7 +462,6 @@
                         return true;
                     }
                 }).length).toBe(1);
-                _converse.chatboxviews.get('controlbox').$('#chatrooms dl.bookmarks').html('');
                 var stanza = $iq({'to': _converse.connection.jid, 'type':'result', 'id':IQ_id})
                     .c('pubsub', {'xmlns': Strophe.NS.PUBSUB})
                         .c('items', {'node': 'storage:bookmarks'})
@@ -485,10 +483,10 @@
                     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').click();
+                    $('#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').click();
+                    $('#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);

+ 124 - 124
spec/chatbox.js

@@ -15,6 +15,7 @@
     var Strophe = converse.env.Strophe;
     var Promise = converse.env.Promise;
     var moment = converse.env.moment;
+    var u = converse.env.utils;
 
     return describe("Chatboxes", function() {
         describe("A Chatbox", function () {
@@ -46,13 +47,13 @@
 
                     _converse.chatboxes.onMessage(msg);
                     var view = _converse.chatboxviews.get(sender_jid);
-                    expect(_.includes(view.$el.find('.chat-msg-author').text(), '**Max Frankfurter')).toBeTruthy();
-                    expect(view.$el.find('.chat-msg-content').text()).toBe(' is tired');
+                    expect(_.includes($(view.el).find('.chat-msg-author').text(), '**Max Frankfurter')).toBeTruthy();
+                    expect($(view.el).find('.chat-msg-content').text()).toBe(' is tired');
 
                     message = '/me is as well';
                     test_utils.sendMessage(view, message);
-                    expect(_.includes(view.$el.find('.chat-msg-author:last').text(), '**Max Mustermann')).toBeTruthy();
-                    expect(view.$el.find('.chat-msg-content:last').text()).toBe(' is as well');
+                    expect(_.includes($(view.el).find('.chat-msg-author:last').text(), '**Max Mustermann')).toBeTruthy();
+                    expect($(view.el).find('.chat-msg-content:last').text()).toBe(' is as well');
                     done();
                 });
             }));
@@ -74,14 +75,14 @@
                 expect($("#conversejs .chatbox").length).toBe(1); // Controlbox is open
 
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('.roster-group li').length;
+                    return $(_converse.rosterview.el).find('.roster-group li').length;
                 }, 700).then(function () {
-                    var online_contacts = _converse.rosterview.$el.find('.roster-group .current-xmpp-contact a.open-chat');
+                    var online_contacts = $(_converse.rosterview.el).find('.roster-group .current-xmpp-contact a.open-chat');
                     expect(online_contacts.length).toBe(15);
                     for (i=0; i<online_contacts.length; i++) {
                         $el = $(online_contacts[i]);
                         jid = $el.text().trim().replace(/ /g,'.').toLowerCase() + '@localhost';
-                        $el.click();
+                        $el[0].click();
                         chatboxview = _converse.chatboxviews.get(jid);
                         expect(_converse.chatboxes.length).toEqual(i+2);
                         expect(_converse.chatboxviews.trimChats).toHaveBeenCalled();
@@ -115,15 +116,15 @@
 
                 _converse.rosterview.update(); // XXX: Hack to make sure $roster element is attached.
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('.roster-group li').length;
+                    return $(_converse.rosterview.el).find('.roster-group li').length;
                 }, 700).then(function () {
                     // Test that they can be maximized again
-                    var online_contacts = _converse.rosterview.$el.find('.roster-group .current-xmpp-contact a.open-chat');
+                    var online_contacts = $(_converse.rosterview.el).find('.roster-group .current-xmpp-contact a.open-chat');
                     expect(online_contacts.length).toBe(15);
                     for (i=0; i<online_contacts.length; i++) {
                         $el = $(online_contacts[i]);
                         jid = _.trim($el.text().trim()).replace(/ /g,'.').toLowerCase() + '@localhost';
-                        $el.click();
+                        $el[0].click();
                         expect(_converse.chatboxviews.trimChats).toHaveBeenCalled();
 
                         chatboxview = _converse.chatboxviews.get(jid);
@@ -142,7 +143,7 @@
                     spyOn(chatbox, 'maximize').and.callThrough();
                     spyOn(trimmedview, 'restore').and.callThrough();
                     trimmedview.delegateEvents();
-                    trimmedview.$("a.restore-chat").click();
+                    trimmedview.el.querySelector("a.restore-chat").click();
 
                     expect(trimmedview.restore).toHaveBeenCalled();
                     expect(chatbox.maximize).toHaveBeenCalled();
@@ -165,11 +166,11 @@
                 });
 
                 var chatBoxView = _converse.chatboxviews.get(sender_jid);
-                expect(chatBoxView.$el.is(':visible')).toBeFalsy();
+                expect(u.isVisible(chatBoxView.el)).toBeFalsy();
 
                 var minimized_chat = _converse.minimized_chats.get(sender_jid);
                 expect(minimized_chat).toBeTruthy();
-                expect(minimized_chat.$el.is(':visible')).toBeTruthy();
+                expect($(minimized_chat.el).is(':visible')).toBeTruthy();
                 done();
             }));
 
@@ -193,9 +194,9 @@
                 spyOn(_converse.ChatBoxView.prototype, 'focus');
                 chatbox = test_utils.openChatBoxFor(_converse, contact_jid);
 
-                $el = _converse.rosterview.$el.find('a.open-chat:contains("'+chatbox.get('fullname')+'")');
+                $el = $(_converse.rosterview.el).find('a.open-chat:contains("'+chatbox.get('fullname')+'")');
                 jid = $el.text().replace(/ /g,'.').toLowerCase() + '@localhost';
-                $el.click();
+                $el[0].click();
                 expect(_converse.chatboxes.length).toEqual(2);
                 var chatboxview = _converse.chatboxviews.get(contact_jid);
                 expect(chatboxview.focus).toHaveBeenCalled();
@@ -248,7 +249,7 @@
                 test_utils.openControlBox();
                 test_utils.openContactsPanel(_converse);
                 test_utils.waitUntil(function () {
-                        return _converse.rosterview.$el.find('.roster-group').length;
+                        return $(_converse.rosterview.el).find('.roster-group').length;
                     }, 300)
                 .then(function () {
                     var chatbox = test_utils.openChatBoxes(_converse, 1)[0],
@@ -262,12 +263,12 @@
                     controlview.delegateEvents();
                     chatview.delegateEvents();
 
-                    controlview.$el.find('.close-chatbox-button').click();
+                    controlview.el.querySelector('.close-chatbox-button').click();
 
                     expect(controlview.close).toHaveBeenCalled();
                     expect(_converse.emit).toHaveBeenCalledWith('chatBoxClosed', jasmine.any(Object));
                     expect(_converse.emit.calls.count(), 1);
-                    chatview.$el.find('.close-chatbox-button').click();
+                    chatview.el.querySelector('.close-chatbox-button').click();
 
                     expect(chatview.close).toHaveBeenCalled();
                     expect(_converse.emit).toHaveBeenCalledWith('chatBoxClosed', jasmine.any(Object));
@@ -286,7 +287,7 @@
                 test_utils.openControlBox();
                 test_utils.openContactsPanel(_converse);
                 test_utils.waitUntil(function () {
-                        return _converse.rosterview.$el.find('.roster-group').length;
+                        return $(_converse.rosterview.el).find('.roster-group').length;
                     }, 300)
                 .then(function () {
                     var chatbox = test_utils.openChatBoxes(_converse, 1)[0],
@@ -298,27 +299,27 @@
                     // We need to rebind all events otherwise our spy won't be called
                     chatview.delegateEvents();
 
-                    chatview.$el.find('.toggle-chatbox-button').click();
+                    chatview.el.querySelector('.toggle-chatbox-button').click();
 
                     expect(chatview.minimize).toHaveBeenCalled();
                     expect(_converse.emit).toHaveBeenCalledWith('chatBoxMinimized', jasmine.any(Object));
                     expect(_converse.emit.calls.count(), 2);
-                    expect(chatview.$el.is(':visible')).toBeFalsy();
+                    expect(u.isVisible(chatview.el)).toBeFalsy();
                     expect(chatview.model.get('minimized')).toBeTruthy();
-                    chatview.$el.find('.toggle-chatbox-button').click();
+                    chatview.el.querySelector('.toggle-chatbox-button').click();
                     trimmedview = trimmed_chatboxes.get(chatview.model.get('id'));
                     spyOn(trimmedview, 'restore').and.callThrough();
                     trimmedview.delegateEvents();
-                    trimmedview.$("a.restore-chat").click();
+                    trimmedview.el.querySelector("a.restore-chat").click();
 
                     expect(trimmedview.restore).toHaveBeenCalled();
                     expect(_converse.emit).toHaveBeenCalledWith('chatBoxMaximized', jasmine.any(Object));
                     return test_utils.waitUntil(function () {
-                        return chatview.$el.find('.chat-body').is(':visible');
+                        return $(chatview.el).find('.chat-body').is(':visible');
                     }, 500);
                 }).then(function () {
-                    expect(chatview.$el.find('.toggle-chatbox-button').hasClass('icon-minus')).toBeTruthy();
-                    expect(chatview.$el.find('.toggle-chatbox-button').hasClass('icon-plus')).toBeFalsy();
+                    expect($(chatview.el).find('.toggle-chatbox-button').hasClass('icon-minus')).toBeTruthy();
+                    expect($(chatview.el).find('.toggle-chatbox-button').hasClass('icon-plus')).toBeFalsy();
                     expect(chatview.model.get('minimized')).toBeFalsy();
                     done();
                 });
@@ -333,7 +334,7 @@
                 test_utils.openControlBox();
                 test_utils.openContactsPanel(_converse);
                 test_utils.waitUntil(function () {
-                        return _converse.rosterview.$el.find('.roster-group').length;
+                        return $(_converse.rosterview.el).find('.roster-group').length;
                     }, 300)
                 .then(function () {
                     spyOn(_converse, 'emit');
@@ -384,7 +385,7 @@
                     var view = _converse.chatboxviews.get(contact_jid);
                     expect(chatbox).toBeDefined();
                     expect(view).toBeDefined();
-                    var $toolbar = view.$el.find('ul.chat-toolbar');
+                    var $toolbar = $(view.el).find('ul.chat-toolbar');
                     expect($toolbar.length).toBe(1);
                     expect($toolbar.children('li').length).toBe(3);
                     done();
@@ -421,13 +422,13 @@
                         toolbar.querySelector('li.toggle-smiley').click(); // Close the panel again
                         return test_utils.waitUntil(function () {
                             return !view.el.querySelector('.toggle-smiley .toolbar-menu').offsetHeight;
-                        }, 300);
+                        }, 900);
                     }).then(function () {
                         toolbar.querySelector('li.toggle-smiley').click();
                         expect(view.toggleEmojiMenu).toHaveBeenCalled();
                         return test_utils.waitUntil(function () {
-                            var $picker = view.$el.find('.toggle-smiley .emoji-picker-container');
-                            return $picker.is(':visible');
+                            var $picker = $(view.el).find('.toggle-smiley .emoji-picker-container');
+                            return u.isVisible($picker[0]);
                         }, 300);
                     }).then(function () {
                         var nodes = view.el.querySelectorAll('.toggle-smiley ul li');
@@ -448,20 +449,20 @@
                     test_utils.openContactsPanel(_converse);
 
                     test_utils.waitUntil(function () {
-                            return _converse.rosterview.$el.find('.roster-group').length;
+                            return $(_converse.rosterview.el).find('.roster-group').length;
                         }, 300)
                     .then(function () {
                         // TODO: More tests can be added here...
                         var contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost';
                         test_utils.openChatBoxFor(_converse, contact_jid);
                         var view = _converse.chatboxviews.get(contact_jid);
-                        var $toolbar = view.$el.find('ul.chat-toolbar');
+                        var $toolbar = $(view.el).find('ul.chat-toolbar');
                         expect($toolbar.children('li.toggle-otr').length).toBe(1);
                         // Register spies
                         spyOn(view, 'toggleOTRMenu').and.callThrough();
                         view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
 
-                        $toolbar.children('li.toggle-otr').click();
+                        $toolbar[0].querySelector('li.toggle-otr').click();
                         expect(view.toggleOTRMenu).toHaveBeenCalled();
                         done();
                     });
@@ -476,7 +477,7 @@
                     test_utils.openControlBox();
                     test_utils.openContactsPanel(_converse);
 
-                    var view, callButton, $toolbar;
+                    var view;
                     var contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost';
                     spyOn(_converse, 'emit');
                     // First check that the button doesn't show if it's not enabled
@@ -484,19 +485,18 @@
                     _converse.visible_toolbar_buttons.call = false;
                     test_utils.openChatBoxFor(_converse, contact_jid);
                     view = _converse.chatboxviews.get(contact_jid);
-                    $toolbar = view.$el.find('ul.chat-toolbar');
-                    callButton = $toolbar.find('.toggle-call');
-                    expect(callButton.length).toBe(0);
+                    var toolbar = view.el.querySelector('ul.chat-toolbar');
+                    var call_button = toolbar.querySelector('.toggle-call');
+                    expect(_.isNull(call_button)).toBeTruthy();
                     view.close();
                     // Now check that it's shown if enabled and that it emits
                     // callButtonClicked
                     _converse.visible_toolbar_buttons.call = true; // enable the button
                     test_utils.openChatBoxFor(_converse, contact_jid);
                     view = _converse.chatboxviews.get(contact_jid);
-                    $toolbar = view.$el.find('ul.chat-toolbar');
-                    callButton = $toolbar.find('.toggle-call');
-                    expect(callButton.length).toBe(1);
-                    callButton.click();
+                    var toolbar = view.el.querySelector('ul.chat-toolbar');
+                    call_button = toolbar.querySelector('.toggle-call');
+                    call_button.click();
                     expect(_converse.emit).toHaveBeenCalledWith('callButtonClicked', jasmine.any(Object));
                     done();
                 }));
@@ -518,7 +518,7 @@
                     test_utils.openChatBoxFor(_converse, contact_jid);
                     view = _converse.chatboxviews.get(contact_jid);
                     view = _converse.chatboxviews.get(contact_jid);
-                    $toolbar = view.$el.find('ul.chat-toolbar');
+                    $toolbar = $(view.el).find('ul.chat-toolbar');
                     clearButton = $toolbar.find('.toggle-clear');
                     expect(clearButton.length).toBe(0);
                     view.close();
@@ -527,12 +527,12 @@
                     _converse.visible_toolbar_buttons.clear = true; // enable the button
                     test_utils.openChatBoxFor(_converse, contact_jid);
                     view = _converse.chatboxviews.get(contact_jid);
-                    $toolbar = view.$el.find('ul.chat-toolbar');
+                    $toolbar = $(view.el).find('ul.chat-toolbar');
                     clearButton = $toolbar.find('.toggle-clear');
                     expect(clearButton.length).toBe(1);
                     spyOn(view, 'clearMessages');
                     view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
-                    clearButton.click();
+                    clearButton[0].click();
                     expect(view.clearMessages).toHaveBeenCalled();
                     done();
                 }));
@@ -551,7 +551,7 @@
                         test_utils.openControlBox();
                         test_utils.openContactsPanel(_converse);
                         test_utils.waitUntil(function () {
-                                return _converse.rosterview.$el.find('.roster-group').length;
+                                return $(_converse.rosterview.el).find('.roster-group').length;
                             }, 300)
                         .then(function () {
                             spyOn(_converse, 'emit');
@@ -585,7 +585,7 @@
                             expect(msg_obj.get('sender')).toEqual('them');
                             expect(msg_obj.get('delayed')).toEqual(false);
                             // Now check that the message appears inside the chatbox in the DOM
-                            var $chat_content = chatboxview.$el.find('.chat-content');
+                            var $chat_content = $(chatboxview.el).find('.chat-content');
                             var msg_txt = $chat_content.find('.chat-message').find('.chat-msg-content').text();
                             expect(msg_txt).toEqual(message);
                             var sender_txt = $chat_content.find('span.chat-msg-them').text();
@@ -699,7 +699,7 @@
                             expect(msg_obj.get('sender')).toEqual('them');
                             expect(msg_obj.get('delayed')).toEqual(false);
                             // Now check that the message appears inside the chatbox in the DOM
-                            var $chat_content = chatboxview.$el.find('.chat-content');
+                            var $chat_content = $(chatboxview.el).find('.chat-content');
                             var msg_txt = $chat_content.find('.chat-message').find('.chat-msg-content').text();
                             expect(msg_txt).toEqual(message);
                             var sender_txt = $chat_content.find('span.chat-msg-them').text();
@@ -748,7 +748,7 @@
                                 'message': msg_text
                             });
                             view.sendMessage(message);
-                            var $chat_content = view.$el.find('.chat-content');
+                            var $chat_content = $(view.el).find('.chat-content');
                             var msg_txt = $chat_content.find('.chat-message:last').find('.chat-msg-content').text();
                             expect(msg_txt).toEqual(msg_text);
 
@@ -861,20 +861,20 @@
                                 .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
 
                             // Now check that the message appears inside the chatbox in the DOM
-                            var $chat_content = chatboxview.$el.find('.chat-content');
+                            var $chat_content = $(chatboxview.el).find('.chat-content');
                             var msg_txt = $chat_content.find('.chat-message:last').find('.chat-msg-content').text();
                             expect(msg_txt).toEqual(message);
                             return test_utils.waitUntil(function () {
-                                return chatboxview.$('.new-msgs-indicator').is(':visible');
+                                return u.isVisible(chatboxview.el.querySelector('.new-msgs-indicator'));
                             }, 500);
                         }).then(function () {
                             expect(chatboxview.model.get('scrolled')).toBe(true);
                             expect(chatboxview.content.scrollTop).toBe(0);
-                            expect(chatboxview.$('.new-msgs-indicator').is(':visible')).toBeTruthy();
+                            expect(u.isVisible(chatboxview.el.querySelector('.new-msgs-indicator'))).toBeTruthy();
                             // Scroll down again
                             chatboxview.content.scrollTop = chatboxview.content.scrollHeight;
                             return test_utils.waitUntil(function () {
-                                return !chatboxview.$('.new-msgs-indicator').is(':visible');
+                                return !u.isVisible(chatboxview.el.querySelector('.new-msgs-indicator'));
                             }, 700);
                         }).then(done);
                     }));
@@ -889,7 +889,7 @@
                         test_utils.openContactsPanel(_converse);
 
                         test_utils.waitUntil(function () {
-                                return _converse.rosterview.$el.find('.roster-group').length;
+                                return $(_converse.rosterview.el).find('.roster-group').length;
                             }, 300)
                         .then(function () {
                             // Send a message from a different resource
@@ -925,7 +925,7 @@
 
                             expect(_converse.chatboxes.getChatBox).toHaveBeenCalled();
                             var chatboxview = _converse.chatboxviews.get(sender_jid);
-                            var $chat_content = chatboxview.$el.find('.chat-content:last');
+                            var $chat_content = $(chatboxview.el).find('.chat-content:last');
                             var msg_txt = $chat_content.find('.chat-message').find('.chat-msg-content').text();
                             expect(msg_txt).toEqual(message);
                             done();
@@ -943,7 +943,7 @@
                     test_utils.openContactsPanel(_converse);
 
                     test_utils.waitUntil(function () {
-                            return _converse.rosterview.$el.find('.roster-group').length;
+                            return $(_converse.rosterview.el).find('.roster-group').length;
                         }, 300)
                     .then(function () {
                         var message, msg;
@@ -1037,7 +1037,7 @@
                         _converse.chatboxes.onMessage(msg);
 
                         var chatboxview = _converse.chatboxviews.get(sender_jid);
-                        var $chat_content = chatboxview.$el.find('.chat-content');
+                        var $chat_content = $(chatboxview.el).find('.chat-content');
                         chatboxview.clearSpinner(); //cleanup
 
                         var $time = $chat_content.find('time');
@@ -1150,7 +1150,7 @@
                     expect(msg_obj.get('sender')).toEqual('them');
                     expect(msg_obj.get('delayed')).toEqual(false);
                     // Now check that the message appears inside the chatbox in the DOM
-                    var $chat_content = chatboxview.$el.find('.chat-content');
+                    var $chat_content = $(chatboxview.el).find('.chat-content');
                     var msg_txt = $chat_content.find('.chat-message').find('.chat-msg-content').text();
                     expect(msg_txt).toEqual(msgtext);
                     var sender_txt = $chat_content.find('span.chat-msg-them').text();
@@ -1207,7 +1207,7 @@
                         expect(msg_obj.get('sender')).toEqual('me');
                         expect(msg_obj.get('delayed')).toEqual(false);
                         // Now check that the message appears inside the chatbox in the DOM
-                        var $chat_content = chatboxview.$el.find('.chat-content');
+                        var $chat_content = $(chatboxview.el).find('.chat-content');
                         var msg_txt = $chat_content.find('.chat-message').find('.chat-msg-content').text();
                         expect(msg_txt).toEqual(msgtext);
                         done();
@@ -1272,7 +1272,7 @@
                     test_utils.openControlBox();
                     test_utils.openContactsPanel(_converse);
                     test_utils.waitUntil(function () {
-                            return _converse.rosterview.$el.find('.roster-group').length;
+                            return $(_converse.rosterview.el).find('.roster-group').length;
                         }, 300)
                     .then(function () {
                         var contact_name = mock.cur_names[0];
@@ -1281,9 +1281,9 @@
                         spyOn(_converse, 'emit').and.callThrough();
                         test_utils.openChatBoxFor(_converse, contact_jid);
                         var chatview = _converse.chatboxviews.get(contact_jid);
-                        expect(chatview.$el.is(':visible')).toBeTruthy();
+                        expect(u.isVisible(chatview.el)).toBeTruthy();
                         expect(chatview.model.get('minimized')).toBeFalsy();
-                        chatview.$el.find('.toggle-chatbox-button').click();
+                        chatview.el.querySelector('.toggle-chatbox-button').click();
                         expect(chatview.model.get('minimized')).toBeTruthy();
                         var message = 'This message is sent to a minimized chatbox';
                         var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
@@ -1298,10 +1298,10 @@
                         expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
                         var trimmed_chatboxes = _converse.minimized_chats;
                         var trimmedview = trimmed_chatboxes.get(contact_jid);
-                        var $count = trimmedview.$el.find('.chat-head-message-count');
-                        expect(chatview.$el.is(':visible')).toBeFalsy();
+                        var $count = $(trimmedview.el).find('.chat-head-message-count');
+                        expect(u.isVisible(chatview.el)).toBeFalsy();
                         expect(trimmedview.model.get('minimized')).toBeTruthy();
-                        expect($count.is(':visible')).toBeTruthy();
+                        expect(u.isVisible($count[0])).toBeTruthy();
                         expect($count.html()).toBe('1');
                         _converse.chatboxes.onMessage(
                             $msg({
@@ -1312,12 +1312,12 @@
                             }).c('body').t('This message is also sent to a minimized chatbox').up()
                             .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()
                         );
-                        expect(chatview.$el.is(':visible')).toBeFalsy();
+                        expect(u.isVisible(chatview.el)).toBeFalsy();
                         expect(trimmedview.model.get('minimized')).toBeTruthy();
-                        $count = trimmedview.$el.find('.chat-head-message-count');
-                        expect($count.is(':visible')).toBeTruthy();
+                        $count = $(trimmedview.el).find('.chat-head-message-count');
+                        expect(u.isVisible($count[0])).toBeTruthy();
                         expect($count.html()).toBe('2');
-                        trimmedview.$el.find('.restore-chat').click();
+                        trimmedview.el.querySelector('.restore-chat').click();
                         expect(trimmed_chatboxes.keys().length).toBe(0);
                         done();
                     });
@@ -1332,7 +1332,7 @@
                     test_utils.openControlBox();
                     test_utils.openContactsPanel(_converse);
                     test_utils.waitUntil(function () {
-                            return _converse.rosterview.$el.find('.roster-group').length;
+                            return $(_converse.rosterview.el).find('.roster-group').length;
                         }, 300)
                     .then(function () {
                         spyOn(_converse, 'emit');
@@ -1345,7 +1345,7 @@
                         var message = 'This is a day old message';
                         var chatbox = _converse.chatboxes.get(contact_jid);
                         var chatboxview = _converse.chatboxviews.get(contact_jid);
-                        var $chat_content = chatboxview.$el.find('.chat-content');
+                        var $chat_content = $(chatboxview.el).find('.chat-content');
                         var msg_obj;
                         var msg_txt;
                         var sender_txt;
@@ -1432,7 +1432,7 @@
                     expect(view.sendMessage).toHaveBeenCalled();
                     expect(view.model.messages.length, 2);
                     expect(_converse.emit.calls.mostRecent().args, ['messageSend', message]);
-                    expect(view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content').text()).toEqual(message);
+                    expect($(view.el).find('.chat-content').find('.chat-message').last().find('.chat-msg-content').text()).toEqual(message);
                     done();
                 }));
 
@@ -1452,7 +1452,7 @@
                     spyOn(view, 'sendMessage').and.callThrough();
                     test_utils.sendMessage(view, message);
                     expect(view.sendMessage).toHaveBeenCalled();
-                    var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
+                    var msg = $(view.el).find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
                     expect(msg.text()).toEqual(message);
                     expect(msg.html()).toEqual('&lt;p&gt;This message contains &lt;em&gt;some&lt;/em&gt; &lt;b&gt;markup&lt;/b&gt;&lt;/p&gt;');
                     done();
@@ -1474,7 +1474,7 @@
                     spyOn(view, 'sendMessage').and.callThrough();
                     test_utils.sendMessage(view, message);
                     expect(view.sendMessage).toHaveBeenCalled();
-                    var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
+                    var msg = $(view.el).find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
                     expect(msg.text()).toEqual(message);
                     expect(msg.html()).toEqual('This message contains a hyperlink: <a target="_blank" rel="noopener" href="http://www.opkode.com">www.opkode.com</a>');
                     done();
@@ -1497,7 +1497,7 @@
                     message = "http://www.opkode.com/'onmouseover='alert(1)'whatever";
                     test_utils.sendMessage(view, message);
                     expect(view.sendMessage).toHaveBeenCalled();
-                    msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
+                    msg = $(view.el).find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
                     expect(msg.text()).toEqual(message);
                     expect(msg.html()).toEqual('<a target="_blank" rel="noopener" href="http://www.opkode.com/%27onmouseover=%27alert%281%29%27whatever">http://www.opkode.com/\'onmouseover=\'alert(1)\'whatever</a>');
 
@@ -1505,7 +1505,7 @@
                     test_utils.sendMessage(view, message);
 
                     expect(view.sendMessage).toHaveBeenCalled();
-                    msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
+                    msg = $(view.el).find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
                     expect(msg.text()).toEqual(message);
                     expect(msg.html()).toEqual('<a target="_blank" rel="noopener" href="http://www.opkode.com/%22onmouseover=%22alert%281%29%22whatever">http://www.opkode.com/"onmouseover="alert(1)"whatever</a>');
 
@@ -1513,7 +1513,7 @@
                     test_utils.sendMessage(view, message);
 
                     expect(view.sendMessage).toHaveBeenCalled();
-                    msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
+                    msg = $(view.el).find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
                     expect(msg.text()).toEqual(message);
                     expect(msg.html()).toEqual('<a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Ender%27s_Game">https://en.wikipedia.org/wiki/Ender\'s_Game</a>');
 
@@ -1521,7 +1521,7 @@
                     test_utils.sendMessage(view, message);
 
                     expect(view.sendMessage).toHaveBeenCalled();
-                    msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
+                    msg = $(view.el).find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
                     expect(msg.text()).toEqual(message);
                     expect(msg.html()).toEqual('<a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Ender%27s_Game">https://en.wikipedia.org/wiki/Ender%27s_Game</a>');
                     done();
@@ -1543,21 +1543,21 @@
                     test_utils.sendMessage(view, message);
 
                     test_utils.waitUntil(function () {
-                        return view.$el.find('.chat-content').find('.chat-message img').length;
+                        return $(view.el).find('.chat-content').find('.chat-message img').length;
                     }, 500).then(function () {
                         expect(view.sendMessage).toHaveBeenCalled();
-                        var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
+                        var msg = $(view.el).find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
                         expect(msg.html()).toEqual(
                             '<a target="_blank" rel="noopener" href="'+base_url+'/logo/conversejs.svg"><img src="' +
                                 message + '" class="chat-image"></a>');
                         message += "?param1=val1&param2=val2";
                         test_utils.sendMessage(view, message);
                         return test_utils.waitUntil(function () {
-                            return view.$el.find('.chat-content').find('.chat-message img').length === 2;
+                            return $(view.el).find('.chat-content').find('.chat-message img').length === 2;
                         }, 500);
                     }).then(function () {
                         expect(view.sendMessage).toHaveBeenCalled();
-                        var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
+                        var msg = $(view.el).find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
                         expect(msg.html()).toEqual(
                             '<a target="_blank" rel="noopener" href="'+base_url+'/logo/conversejs.svg?param1=val1&amp;param2=val2"><img src="'+
                                 message.replace(/&/g, '&amp;') +
@@ -1567,11 +1567,11 @@
                         message += ' hello world '+base_url+"/logo/conversejs.svg";
                         test_utils.sendMessage(view, message);
                         return test_utils.waitUntil(function () {
-                            return view.$el.find('.chat-content').find('.chat-message img').length === 4;
+                            return $(view.el).find('.chat-content').find('.chat-message img').length === 4;
                         }, 500);
                     }).then(function () {
                         expect(view.sendMessage).toHaveBeenCalled();
-                        var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
+                        var msg = $(view.el).find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
                         expect(msg.html()).toEqual(
                             '<a target="_blank" rel="noopener" href="'+base_url+'/logo/conversejs.svg?param1=val1&amp;param2=val2">'+
                             '<img src="'+base_url+'/logo/conversejs.svg?param1=val1&amp;param2=val2" class="chat-image"></a> hello world '+
@@ -1599,7 +1599,7 @@
                     var chatbox = _converse.chatboxes.get(contact_jid);
                     expect(chatbox.messages.models.length, 1);
                     var msg_object = chatbox.messages.models[0];
-                    var msg_time_author = view.$el.find('.chat-content').find('.chat-message')
+                    var msg_time_author = $(view.el).find('.chat-content').find('.chat-message')
                                             .last().find('.chat-msg-author.chat-msg-me').text();
                     var msg_time_rendered = msg_time_author.split(" ",1);
                     var msg_time = moment(msg_object.get('time')).format(_converse.time_format);
@@ -1644,7 +1644,7 @@
                         test_utils.openControlBox();
                         test_utils.openContactsPanel(_converse);
                         test_utils.waitUntil(function () {
-                            return _converse.rosterview.$el.find('.roster-group').length;
+                            return $(_converse.rosterview.el).find('.roster-group').length;
                         }, 300).then(function () {
                             spyOn(_converse.connection, 'send');
                             var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
@@ -1672,7 +1672,7 @@
                         var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
 
                         test_utils.waitUntil(function () {
-                            return _converse.rosterview.$el.find('.roster-group').length;
+                            return $(_converse.rosterview.el).find('.roster-group').length;
                         }, 500).then(function () {
                             test_utils.openChatBoxFor(_converse, contact_jid);
                             var view = _converse.chatboxviews.get(contact_jid);
@@ -1711,7 +1711,7 @@
                         test_utils.openControlBox();
                         test_utils.openContactsPanel(_converse);
                         test_utils.waitUntil(function () {
-                            return _converse.rosterview.$el.find('.roster-group').length;
+                            return $(_converse.rosterview.el).find('.roster-group').length;
                         }, 300).then(function () {
                             var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
                             test_utils.openChatBoxFor(_converse, contact_jid);
@@ -1720,7 +1720,7 @@
                             spyOn(_converse.connection, 'send');
                             spyOn(_converse, 'emit');
                             view.keyPressed({
-                                target: view.$el.find('textarea.chat-textarea'),
+                                target: $(view.el).find('textarea.chat-textarea'),
                                 keyCode: 1
                             });
                             expect(view.model.get('chat_state')).toBe('composing');
@@ -1733,7 +1733,7 @@
 
                             // The notification is not sent again
                             view.keyPressed({
-                                target: view.$el.find('textarea.chat-textarea'),
+                                target: $(view.el).find('textarea.chat-textarea'),
                                 keyCode: 1
                             });
                             expect(view.model.get('chat_state')).toBe('composing');
@@ -1768,7 +1768,7 @@
                         var chatboxview = _converse.chatboxviews.get(sender_jid);
                         expect(chatboxview).toBeDefined();
                         // Check that the notification appears inside the chatbox in the DOM
-                        var $events = chatboxview.$el.find('.chat-event');
+                        var $events = $(chatboxview.el).find('.chat-event');
                         expect($events.text()).toEqual(mock.cur_names[1] + ' is typing');
                         done();
                     }));
@@ -1815,7 +1815,7 @@
                             expect(msg_obj.get('fullname')).toEqual(_converse.xmppstatus.get('fullname'));
                             expect(msg_obj.get('sender')).toEqual('me');
                             expect(msg_obj.get('delayed')).toEqual(false);
-                            var $chat_content = chatboxview.$el.find('.chat-content');
+                            var $chat_content = $(chatboxview.el).find('.chat-content');
                             var status_text = $chat_content.find('.chat-info.chat-event').text();
                             expect(status_text).toBe('Typing from another device');
                             done();
@@ -1835,7 +1835,7 @@
                         test_utils.openControlBox();
                         test_utils.openContactsPanel(_converse);
                         test_utils.waitUntil(function () {
-                                return _converse.rosterview.$el.find('.roster-group li').length;
+                                return $(_converse.rosterview.el).find('.roster-group li').length;
                         }, 700).then(function () {
                             _converse.TIMEOUTS.PAUSED = 200; // Make the timeout shorter so that we can test
 
@@ -1846,7 +1846,7 @@
                             spyOn(view, 'setChatState').and.callThrough();
                             expect(view.model.get('chat_state')).toBe('active');
                             view.keyPressed({
-                                target: view.$el.find('textarea.chat-textarea'),
+                                target: $(view.el).find('textarea.chat-textarea'),
                                 keyCode: 1
                             });
                             expect(view.model.get('chat_state')).toBe('composing');
@@ -1873,14 +1873,14 @@
                             // out if the user simply types longer than the
                             // timeout.
                             view.keyPressed({
-                                target: view.$el.find('textarea.chat-textarea'),
+                                target: $(view.el).find('textarea.chat-textarea'),
                                 keyCode: 1
                             });
                             expect(view.setChatState).toHaveBeenCalled();
                             expect(view.model.get('chat_state')).toBe('composing');
 
                             view.keyPressed({
-                                target: view.$el.find('textarea.chat-textarea'),
+                                target: $(view.el).find('textarea.chat-textarea'),
                                 keyCode: 1
                             });
                             expect(view.model.get('chat_state')).toBe('composing');
@@ -1897,7 +1897,7 @@
                         test_utils.openControlBox();
                         test_utils.openContactsPanel(_converse);
                         test_utils.waitUntil(function () {
-                                return _converse.rosterview.$el.find('.roster-group').length;
+                                return $(_converse.rosterview.el).find('.roster-group').length;
                             }, 300)
                         .then(function () {
                             // TODO: only show paused state if the previous state was composing
@@ -1914,7 +1914,7 @@
                             _converse.chatboxes.onMessage(msg);
                             expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
                             var chatboxview = _converse.chatboxviews.get(sender_jid);
-                            var $events = chatboxview.$el.find('.chat-event');
+                            var $events = $(chatboxview.el).find('.chat-event');
                             expect($events.text()).toEqual(mock.cur_names[1] + ' has stopped typing');
                             done();
                         });
@@ -1962,7 +1962,7 @@
                             expect(msg_obj.get('fullname')).toEqual(_converse.xmppstatus.get('fullname'));
                             expect(msg_obj.get('sender')).toEqual('me');
                             expect(msg_obj.get('delayed')).toEqual(false);
-                            var $chat_content = chatboxview.$el.find('.chat-content');
+                            var $chat_content = $(chatboxview.el).find('.chat-content');
                             var status_text = $chat_content.find('.chat-info.chat-event').text();
                             expect(status_text).toBe('Stopped typing on the other device');
                             done();
@@ -1982,7 +1982,7 @@
                         test_utils.openControlBox();
                         test_utils.openContactsPanel(_converse);
                         test_utils.waitUntil(function () {
-                            return _converse.rosterview.$el.find('.roster-group').length;
+                            return $(_converse.rosterview.el).find('.roster-group').length;
                         }, 500).then(function () {
                             // Make the timeouts shorter so that we can test
                             _converse.TIMEOUTS.PAUSED = 200;
@@ -1998,7 +1998,7 @@
                             view = _converse.chatboxviews.get(contact_jid);
                             expect(view.model.get('chat_state')).toBe('active');
                             view.keyPressed({
-                                target: view.$el.find('textarea.chat-textarea'),
+                                target: $(view.el).find('textarea.chat-textarea'),
                                 keyCode: 1
                             });
                             return test_utils.waitUntil(function () {
@@ -2072,7 +2072,7 @@
                         test_utils.openControlBox();
                         test_utils.openContactsPanel(_converse);
                         test_utils.waitUntil(function () {
-                            return _converse.rosterview.$el.find('.roster-group').length;
+                            return $(_converse.rosterview.el).find('.roster-group').length;
                         }, 300).then(function () {
                             var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
                             test_utils.openChatBoxFor(_converse, contact_jid);
@@ -2106,9 +2106,9 @@
                         var sender_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost';
                         test_utils.openChatBoxFor(_converse, sender_jid);
                         var view = _converse.chatboxviews.get(sender_jid);
-                        expect(view.$el.find('.chat-event').length).toBe(0);
+                        expect($(view.el).find('.chat-event').length).toBe(0);
                         view.showStatusNotification(sender_jid+' is typing');
-                        expect(view.$el.find('.chat-event').length).toBe(1);
+                        expect($(view.el).find('.chat-event').length).toBe(1);
                         var msg = $msg({
                                 from: sender_jid,
                                 to: _converse.connection.jid,
@@ -2117,7 +2117,7 @@
                             }).c('body').c('inactive', {'xmlns': Strophe.NS.CHATSTATES}).tree();
                         _converse.chatboxes.onMessage(msg);
                         expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
-                        expect(view.$el.find('.chat-event').length).toBe(0);
+                        expect($(view.el).find('.chat-event').length).toBe(0);
                         done();
                     }));
                 });
@@ -2145,7 +2145,7 @@
                         _converse.chatboxes.onMessage(msg);
                         expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
                         var chatboxview = _converse.chatboxviews.get(sender_jid);
-                        var $events = chatboxview.$el.find('.chat-event');
+                        var $events = $(chatboxview.el).find('.chat-event');
                         expect($events.text()).toEqual(mock.cur_names[1] + ' has gone away');
                         done();
                     }));
@@ -2305,7 +2305,7 @@
                 // come back to converse-chat page
                 _converse.saveWindowState(null, 'focus');
                 var view = _converse.chatboxviews.get(sender_jid);
-                expect(view.$el.is(':visible')).toBeTruthy();
+                expect(u.isVisible(view.el)).toBeTruthy();
                 expect(_converse.msg_counter).toBe(0);
 
                 // close chatbox and leave converse-chat page again
@@ -2315,7 +2315,7 @@
                 // check that msg_counter is incremented from zero again
                 _converse.chatboxes.onMessage(msgFactory());
                 view = _converse.chatboxviews.get(sender_jid);
-                expect(view.$el.is(':visible')).toBeTruthy();
+                expect(u.isVisible(view.el)).toBeTruthy();
                 expect(_converse.msg_counter).toBe(1);
                 done();
             }));
@@ -2467,7 +2467,7 @@
                 test_utils.createContacts(_converse, 'current');
                 test_utils.openContactsPanel(_converse);
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('.roster-group').length;
+                    return $(_converse.rosterview.el).find('.roster-group').length;
                 }, 500)
                 .then(function () {
                     var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
@@ -2479,14 +2479,14 @@
                     _converse.chatboxes.onMessage(msg);
 
                     var msgIndicatorSelector = 'a.open-chat:contains("' + chatbox.get('fullname') + '") .msgs-indicator',
-                        $msgIndicator = $(_converse.rosterview.$el.find(msgIndicatorSelector));
+                        $msgIndicator = $($(_converse.rosterview.el).find(msgIndicatorSelector));
 
                     expect($msgIndicator.text()).toBe('1');
 
                     msg = test_utils.createChatMessage(_converse, sender_jid, 'This message will be unread too');
                     _converse.chatboxes.onMessage(msg);
 
-                    $msgIndicator = $(_converse.rosterview.$el.find(msgIndicatorSelector));
+                    $msgIndicator = $($(_converse.rosterview.el).find(msgIndicatorSelector));
                     expect($msgIndicator.text()).toBe('2');
                     done();
                 });
@@ -2500,7 +2500,7 @@
                 test_utils.createContacts(_converse, 'current');
                 test_utils.openContactsPanel(_converse);
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('.roster-group').length;
+                    return $(_converse.rosterview.el).find('.roster-group').length;
                 }, 500)
                 .then(function () {
                     var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
@@ -2513,14 +2513,14 @@
                     _converse.chatboxes.onMessage(msg);
 
                     var msgIndicatorSelector = 'a.open-chat:contains("' + chatbox.get('fullname') + '") .msgs-indicator',
-                        $msgIndicator = $(_converse.rosterview.$el.find(msgIndicatorSelector));
+                        $msgIndicator = $($(_converse.rosterview.el).find(msgIndicatorSelector));
 
                     expect($msgIndicator.text()).toBe('1');
 
                     msg = test_utils.createChatMessage(_converse, sender_jid, 'This message will be unread too');
                     _converse.chatboxes.onMessage(msg);
 
-                    $msgIndicator = $(_converse.rosterview.$el.find(msgIndicatorSelector));
+                    $msgIndicator = $($(_converse.rosterview.el).find(msgIndicatorSelector));
                     expect($msgIndicator.text()).toBe('2');
                     done();
                 });
@@ -2534,7 +2534,7 @@
                 test_utils.createContacts(_converse, 'current');
                 test_utils.openContactsPanel(_converse);
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('.roster-group').length;
+                    return $(_converse.rosterview.el).find('.roster-group').length;
                 }, 500)
                 .then(function () {
                     var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
@@ -2542,7 +2542,7 @@
                     var chatbox = _converse.chatboxes.get(sender_jid);
                     var chatboxview = _converse.chatboxviews.get(sender_jid);
                     var msgsIndicatorSelector = 'a.open-chat:contains("' + chatbox.get('fullname') + '") .msgs-indicator';
-                    var selectMsgsIndicator = function () { return $(_converse.rosterview.$el.find(msgsIndicatorSelector)); };
+                    var selectMsgsIndicator = function () { return $($(_converse.rosterview.el).find(msgsIndicatorSelector)); };
                     var msgFactory = function () {
                         return test_utils.createChatMessage(_converse, sender_jid, 'This message will be received as unread, but eventually will be read');
                     };
@@ -2569,7 +2569,7 @@
                 test_utils.createContacts(_converse, 'current');
                 test_utils.openContactsPanel(_converse);
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('.roster-group').length;
+                    return $(_converse.rosterview.el).find('.roster-group').length;
                 }, 500)
                 .then(function () {
                     var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
@@ -2580,7 +2580,7 @@
                         return test_utils.createChatMessage(_converse, sender_jid, 'This message will be received as unread, but eventually will be read');
                     };
                     var msgsIndicatorSelector = 'a.open-chat:contains("' + chatbox.get('fullname') + '") .msgs-indicator',
-                        selectMsgsIndicator = function () { return $(_converse.rosterview.$el.find(msgsIndicatorSelector)); };
+                        selectMsgsIndicator = function () { return $($(_converse.rosterview.el).find(msgsIndicatorSelector)); };
 
                     chatbox.save('scrolled', true);
 
@@ -2602,7 +2602,7 @@
                 test_utils.createContacts(_converse, 'current');
                 test_utils.openContactsPanel(_converse);
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('.roster-group').length;
+                    return $(_converse.rosterview.el).find('.roster-group').length;
                 }, 500)
                 .then(function () {
                     var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
@@ -2613,7 +2613,7 @@
                         return test_utils.createChatMessage(_converse, sender_jid, 'This message will be received as unread, but eventually will be read');
                     };
                     var msgsIndicatorSelector = 'a.open-chat:contains("' + chatbox.get('fullname') + '") .msgs-indicator',
-                        selectMsgsIndicator = function () { return $(_converse.rosterview.$el.find(msgsIndicatorSelector)); };
+                        selectMsgsIndicator = function () { return $($(_converse.rosterview.el).find(msgsIndicatorSelector)); };
 
                     chatbox.save('scrolled', true);
 
@@ -2644,7 +2644,7 @@
                 };
                 var selectUnreadMsgCount = function () {
                     var minimizedChatBoxView = _converse.minimized_chats.get(sender_jid);
-                    return minimizedChatBoxView.$el.find('.chat-head-message-count');
+                    return $(minimizedChatBoxView.el).find('.chat-head-message-count');
                 };
 
                 var chatbox = _converse.chatboxes.get(sender_jid);
@@ -2655,7 +2655,7 @@
                 chatboxview.minimize();
 
                 var $unreadMsgCount = selectUnreadMsgCount();
-                expect($unreadMsgCount.is(':visible')).toBeTruthy();
+                expect(u.isVisible($unreadMsgCount[0])).toBeTruthy();
                 expect($unreadMsgCount.html()).toBe('1');
                 done();
             }));
@@ -2675,7 +2675,7 @@
                 };
                 var selectUnreadMsgCount = function () {
                     var minimizedChatBoxView = _converse.minimized_chats.get(sender_jid);
-                    return minimizedChatBoxView.$el.find('.chat-head-message-count');
+                    return $(minimizedChatBoxView.el).find('.chat-head-message-count');
                 };
 
                 var chatboxview = _converse.chatboxviews.get(sender_jid);
@@ -2684,7 +2684,7 @@
                 _converse.chatboxes.onMessage(msgFactory());
 
                 var $unreadMsgCount = selectUnreadMsgCount();
-                expect($unreadMsgCount.is(':visible')).toBeTruthy();
+                expect(u.isVisible($unreadMsgCount[0])).toBeTruthy();
                 expect($unreadMsgCount.html()).toBe('1');
                 done();
             }));

+ 178 - 117
spec/chatroom.js

@@ -8,6 +8,7 @@
     var Strophe = converse.env.Strophe;
     var Promise = converse.env.Promise;
     var moment = converse.env.moment;
+    var u = converse.env.utils;
 
     return describe("ChatRooms", function () {
         describe("The \"rooms\" API", function () {
@@ -32,9 +33,9 @@
                 }).then(function () {
                     return test_utils.openAndEnterChatRoom(_converse, 'news', 'localhost', 'dummy');
                 }).then(function () {
-                    expect(_converse.chatboxviews.get('lounge@localhost').$el.is(':visible')).toBeTruthy();
-                    expect(_converse.chatboxviews.get('leisure@localhost').$el.is(':visible')).toBeTruthy();
-                    expect(_converse.chatboxviews.get('news@localhost').$el.is(':visible')).toBeTruthy();
+                    expect(u.isVisible(_converse.chatboxviews.get('lounge@localhost').el)).toBeTruthy();
+                    expect(u.isVisible(_converse.chatboxviews.get('leisure@localhost').el)).toBeTruthy();
+                    expect(u.isVisible(_converse.chatboxviews.get('news@localhost').el)).toBeTruthy();
 
                     // XXX: bit of a cheat here. We want `cleanup()` to be
                     // called on the room. Either it's this or faking
@@ -43,8 +44,8 @@
 
                     _converse.api.rooms.close('lounge@localhost');
                     expect(_converse.chatboxviews.get('lounge@localhost')).toBeUndefined();
-                    expect(_converse.chatboxviews.get('leisure@localhost').$el.is(':visible')).toBeTruthy();
-                    expect(_converse.chatboxviews.get('news@localhost').$el.is(':visible')).toBeTruthy();
+                    expect(u.isVisible(_converse.chatboxviews.get('leisure@localhost').el)).toBeTruthy();
+                    expect(u.isVisible(_converse.chatboxviews.get('news@localhost').el)).toBeTruthy();
 
                     _converse.api.rooms.close(['leisure@localhost', 'news@localhost']);
                     expect(_converse.chatboxviews.get('lounge@localhost')).toBeUndefined();
@@ -54,8 +55,8 @@
                 }).then(function () {
                     return test_utils.openAndEnterChatRoom(_converse, 'leisure', 'localhost', 'dummy')
                 }).then(function () {
-                    expect(_converse.chatboxviews.get('lounge@localhost').$el.is(':visible')).toBeTruthy();
-                    expect(_converse.chatboxviews.get('leisure@localhost').$el.is(':visible')).toBeTruthy();
+                    expect(u.isVisible(_converse.chatboxviews.get('lounge@localhost').el)).toBeTruthy();
+                    expect(u.isVisible(_converse.chatboxviews.get('leisure@localhost').el)).toBeTruthy();
                     _converse.api.rooms.close();
                     expect(_converse.chatboxviews.get('lounge@localhost')).toBeUndefined();
                     expect(_converse.chatboxviews.get('leisure@localhost')).toBeUndefined();
@@ -73,7 +74,7 @@
 
                 test_utils.createContacts(_converse, 'current');
                 test_utils.waitUntil(function () {
-                        return _converse.rosterview.$el.find('.roster-group .group-toggle').length;
+                        return $(_converse.rosterview.el).find('.roster-group .group-toggle').length;
                     }, 300)
                 .then(function () {
                     test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () {
@@ -82,7 +83,7 @@
                         expect(room instanceof Object).toBeTruthy();
                         expect(room.is_chatroom).toBeTruthy();
                         var chatroomview = _converse.chatboxviews.get(jid);
-                        expect(chatroomview.$el.is(':visible')).toBeTruthy();
+                        expect(u.isVisible(chatroomview.el)).toBeTruthy();
                         chatroomview.close();
 
                         // Test with mixed case
@@ -91,19 +92,19 @@
                             room = _converse.api.rooms.get(jid);
                             expect(room instanceof Object).toBeTruthy();
                             chatroomview = _converse.chatboxviews.get(jid.toLowerCase());
-                            expect(chatroomview.$el.is(':visible')).toBeTruthy();
+                            expect(u.isVisible(chatroomview.el)).toBeTruthy();
 
                             jid = 'leisure@localhost';
                             room = _converse.api.rooms.get(jid);
                             expect(room instanceof Object).toBeTruthy();
                             chatroomview = _converse.chatboxviews.get(jid.toLowerCase());
-                            expect(chatroomview.$el.is(':visible')).toBeTruthy();
+                            expect(u.isVisible(chatroomview.el)).toBeTruthy();
 
                             jid = 'leiSure@localhost';
                             room = _converse.api.rooms.get(jid);
                             expect(room instanceof Object).toBeTruthy();
                             chatroomview = _converse.chatboxviews.get(jid.toLowerCase());
-                            expect(chatroomview.$el.is(':visible')).toBeTruthy();
+                            expect(u.isVisible(chatroomview.el)).toBeTruthy();
                             chatroomview.close();
 
                             // Non-existing room
@@ -133,7 +134,7 @@
                 test_utils.openControlBox();
                 test_utils.createContacts(_converse, 'current');
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('.roster-group .group-toggle').length;
+                    return $(_converse.rosterview.el).find('.roster-group .group-toggle').length;
                 }, 300).then(function () {
                     var jid = 'lounge@localhost';
                     var room = _converse.api.rooms.open(jid);
@@ -141,33 +142,33 @@
                     expect(room instanceof Object).toBeTruthy();
                     expect(room.is_chatroom).toBeTruthy();
                     var chatroomview = _converse.chatboxviews.get(jid);
-                    expect(chatroomview.$el.is(':visible')).toBeTruthy();
+                    expect(u.isVisible(chatroomview.el)).toBeTruthy();
 
                     // Test again, now that the room exists.
                     room = _converse.api.rooms.open(jid);
                     expect(room instanceof Object).toBeTruthy();
                     expect(room.is_chatroom).toBeTruthy();
                     chatroomview = _converse.chatboxviews.get(jid);
-                    expect(chatroomview.$el.is(':visible')).toBeTruthy();
+                    expect(u.isVisible(chatroomview.el)).toBeTruthy();
 
                     // Test with mixed case in JID
                     jid = 'Leisure@localhost';
                     room = _converse.api.rooms.open(jid);
                     expect(room instanceof Object).toBeTruthy();
                     chatroomview = _converse.chatboxviews.get(jid.toLowerCase());
-                    expect(chatroomview.$el.is(':visible')).toBeTruthy();
+                    expect(u.isVisible(chatroomview.el)).toBeTruthy();
 
                     jid = 'leisure@localhost';
                     room = _converse.api.rooms.open(jid);
                     expect(room instanceof Object).toBeTruthy();
                     chatroomview = _converse.chatboxviews.get(jid.toLowerCase());
-                    expect(chatroomview.$el.is(':visible')).toBeTruthy();
+                    expect(u.isVisible(chatroomview.el)).toBeTruthy();
 
                     jid = 'leiSure@localhost';
                     room = _converse.api.rooms.open(jid);
                     expect(room instanceof Object).toBeTruthy();
                     chatroomview = _converse.chatboxviews.get(jid.toLowerCase());
-                    expect(chatroomview.$el.is(':visible')).toBeTruthy();
+                    expect(u.isVisible(chatroomview.el)).toBeTruthy();
                     chatroomview.close();
 
                     _converse.muc_instant_rooms = false;
@@ -375,7 +376,7 @@
                     .c('status').attrs({code:'201'}).nodeTree;
 
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
-                    var info_text = view.$el.find('.chat-content .chat-info').text();
+                    var info_text = $(view.el).find('.chat-content .chat-info').text();
                     expect(info_text).toBe('A new room has been created');
 
                     // An instant room is created by saving the default configuratoin.
@@ -402,7 +403,7 @@
 
                 test_utils.openChatRoom(_converse, "coven", 'chat.shakespeare.lit', 'some1');
                 var view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
-                var $chat_content = view.$el.find('.chat-content');
+                var $chat_content = $(view.el).find('.chat-content');
 
                 /* We don't show join/leave messages for existing occupants. We
                  * know about them because we receive their presences before we
@@ -599,7 +600,7 @@
 
                 test_utils.openChatRoom(_converse, "coven", 'chat.shakespeare.lit', 'some1');
                 var view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
-                var $chat_content = view.$el.find('.chat-content');
+                var $chat_content = $(view.el).find('.chat-content');
 
                 /* <presence to="dummy@localhost/_converse.js-29092160"
                  *           from="coven@chat.shakespeare.lit/some1">
@@ -777,7 +778,7 @@
                 _converse.connection._dataRecv(test_utils.createRequest(features_stanza));
 
                 expect(view.generateHeadingHTML).toHaveBeenCalled();
-                expect(view.$('.chatroom-description').text()).toBe('This is the description');
+                expect($(view.el.querySelector('.chatroom-description')).text()).toBe('This is the description');
                 done();
             }));
 
@@ -789,7 +790,7 @@
                 test_utils.createContacts(_converse, 'current');
                 test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () {
                     var view = _converse.chatboxviews.get('lounge@localhost');
-                    if (!view.$el.find('.chat-area').length) { view.renderChatArea(); }
+                    if (!$(view.el).find('.chat-area').length) { view.renderChatArea(); }
                     var message = 'dummy: Your attention is required';
                     var nick = mock.chatroom_names[0],
                         msg = $msg({
@@ -799,7 +800,7 @@
                             type: 'groupchat'
                         }).c('body').t(message).tree();
                     view.handleMUCMessage(msg);
-                    expect(view.$el.find('.chat-message').hasClass('mentioned')).toBeTruthy();
+                    expect($(view.el).find('.chat-message').hasClass('mentioned')).toBeTruthy();
                     done();
                 });
             }));
@@ -820,7 +821,7 @@
                     return test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy');
                 }).then(function () {
                     var view = _converse.chatboxviews.get('lounge@localhost');
-                    if (!view.$el.find('.chat-area').length) { view.renderChatArea(); }
+                    if (!$(view.el).find('.chat-area').length) { view.renderChatArea(); }
                     var message = '/me is tired';
                     var nick = mock.chatroom_names[0],
                         msg = $msg({
@@ -830,8 +831,8 @@
                             type: 'groupchat'
                         }).c('body').t(message).tree();
                     view.handleMUCMessage(msg);
-                    expect(_.includes(view.$el.find('.chat-msg-author').text(), '**Dyon van de Wege')).toBeTruthy();
-                    expect(view.$el.find('.chat-msg-content').text()).toBe(' is tired');
+                    expect(_.includes($(view.el).find('.chat-msg-author').text(), '**Dyon van de Wege')).toBeTruthy();
+                    expect($(view.el).find('.chat-msg-content').text()).toBe(' is tired');
 
                     message = '/me is as well';
                     msg = $msg({
@@ -841,8 +842,8 @@
                         type: 'groupchat'
                     }).c('body').t(message).tree();
                     view.handleMUCMessage(msg);
-                    expect(_.includes(view.$el.find('.chat-msg-author:last').text(), '**Max Mustermann')).toBeTruthy();
-                    expect(view.$el.find('.chat-msg-content:last').text()).toBe(' is as well');
+                    expect(_.includes($(view.el).find('.chat-msg-author:last').text(), '**Max Mustermann')).toBeTruthy();
+                    expect($(view.el).find('.chat-msg-content:last').text()).toBe(' is as well');
                     done();
                 });
             }));
@@ -906,10 +907,10 @@
                     .c('status', {code: '110'});
                 _converse.connection._dataRecv(test_utils.createRequest(presence));
                 expect(view.saveAffiliationAndRole).toHaveBeenCalled();
-                expect(view.$('.configure-chatroom-button').is(':visible')).toBeTruthy();
-                expect(view.$('.toggle-chatbox-button').is(':visible')).toBeTruthy();
-                expect(view.$('.toggle-bookmark').is(':visible')).toBeTruthy();
-                view.$('.configure-chatroom-button').click();
+                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();
 
                 /* Check that an IQ is sent out, asking for the
                  * configuration form.
@@ -1045,33 +1046,33 @@
                 _converse.connection._dataRecv(test_utils.createRequest(config_stanza));
 
                 test_utils.waitUntil(function () {
-                    return view.$('form.chatroom-form').length;
+                    return $(view.el.querySelector('form.chatroom-form')).length;
                 }, 300).then(function () {
-                    expect(view.$('form.chatroom-form').length).toBe(1);
-                    expect(view.$('form.chatroom-form fieldset').length).toBe(2);
-                    var $membersonly = view.$('input[name="muc#roomconfig_membersonly"]');
+                    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 $moderated = view.$('input[name="muc#roomconfig_moderatedroom"]');
+                    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 $password = view.$('input[name="muc#roomconfig_roomsecret"]');
+                    var $password = $(view.el.querySelector('input[name="muc#roomconfig_roomsecret"]'));
                     expect($password.length).toBe(1);
                     expect($password.attr('type')).toBe('password');
 
-                    var $allowpm = view.$('select[name="muc#roomconfig_allowpm"]');
+                    var $allowpm = $(view.el.querySelector('select[name="muc#roomconfig_allowpm"]'));
                     expect($allowpm.length).toBe(1);
                     $allowpm.val('moderators');
 
-                    var $presencebroadcast = view.$('select[name="muc#roomconfig_presencebroadcast"]');
+                    var $presencebroadcast = $(view.el.querySelector('select[name="muc#roomconfig_presencebroadcast"]'));
                     expect($presencebroadcast.length).toBe(1);
                     $presencebroadcast.val(['moderator']);
 
-                    view.$('input[type="submit"]').click();
+                    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');
@@ -1304,7 +1305,7 @@
                     .c('status').attrs({code:'210'}).nodeTree;
 
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
-                    var info_text = view.$el.find('.chat-content .chat-info').text();
+                    var info_text = $(view.el).find('.chat-content .chat-info').text();
                     expect(info_text).toBe('Your nickname has been automatically set to thirdwitch');
                     done();
                 });
@@ -1333,12 +1334,12 @@
 
                 spyOn(view, 'directInvite').and.callThrough();
                 var $input;
-                view.$el.find('.chat-area').remove();
+                $(view.el).find('.chat-area').remove();
 
                 test_utils.waitUntil(function () {
-                        return view.$el.find('input.invited-contact').length;
+                        return $(view.el).find('input.invited-contact').length;
                 }, 300).then(function () {
-                    var $input = view.$el.find('input.invited-contact');
+                    var $input = $(view.el).find('input.invited-contact');
                     expect($input.attr('placeholder')).toBe('Invite');
                     $input.val("Felix");
                     var evt;
@@ -1425,7 +1426,7 @@
                 test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy');
                 spyOn(_converse, 'emit');
                 var view = _converse.chatboxviews.get('lounge@localhost');
-                if (!view.$el.find('.chat-area').length) { view.renderChatArea(); }
+                if (!$(view.el).find('.chat-area').length) { view.renderChatArea(); }
                 var nick = mock.chatroom_names[0];
                 var text = 'This is a received message';
                 var message = $msg({
@@ -1435,7 +1436,7 @@
                     type: 'groupchat'
                 }).c('body').t(text);
                 view.onChatRoomMessage(message.nodeTree);
-                var $chat_content = view.$el.find('.chat-content');
+                var $chat_content = $(view.el).find('.chat-content');
                 expect($chat_content.find('.chat-message').length).toBe(1);
                 expect($chat_content.find('.chat-msg-content').text()).toBe(text);
                 expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
@@ -1450,12 +1451,18 @@
                 test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () {
                     spyOn(_converse, 'emit');
                     var view = _converse.chatboxviews.get('lounge@localhost');
-                    if (!view.$el.find('.chat-area').length) { view.renderChatArea(); }
+                    if (!$(view.el).find('.chat-area').length) { view.renderChatArea(); }
                     var text = 'This is a sent message';
-                    view.$el.find('.chat-textarea').text(text);
-                    view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13}));
+                    var textarea = view.el.querySelector('.chat-textarea');
+                    textarea.value = text;
+                    view.keyPressed({
+                        target: textarea,
+                        preventDefault: _.noop,
+                        keyCode: 13
+                    });
+
                     expect(_converse.emit).toHaveBeenCalledWith('messageSend', text);
-                    var $chat_content = view.$el.find('.chat-content');
+                    var $chat_content = $(view.el).find('.chat-content');
                     expect($chat_content.find('.chat-message').length).toBe(1);
 
                     // Let's check that if we receive the same message again, it's
@@ -1508,7 +1515,7 @@
                             }).c('body').t(message).tree());
 
                         // Now check that the message appears inside the chatbox in the DOM
-                        var $chat_content = view.$el.find('.chat-content');
+                        var $chat_content = $(view.el).find('.chat-content');
                         var msg_txt = $chat_content.find('.chat-message:last').find('.chat-msg-content').text();
                         expect(msg_txt).toEqual(message);
                         expect(view.content.scrollTop).toBe(0);
@@ -1532,7 +1539,7 @@
                         '</message>').firstChild;
                     _converse.connection._dataRecv(test_utils.createRequest(stanza));
                     var view = _converse.chatboxviews.get('jdev@conference.jabber.org');
-                    var $chat_content = view.$el.find('.chat-content');
+                    var $chat_content = $(view.el).find('.chat-content');
                     expect($chat_content.find('.chat-info:last').text()).toBe('Topic set by ralphm to: '+text);
                     done();
                 });
@@ -1548,7 +1555,7 @@
                     var subject = '<img src="x" onerror="alert(\'XSS\');"/>';
                     var view = _converse.chatboxviews.get('jdev@conference.jabber.org');
                     view.setChatRoomSubject('ralphm', subject);
-                    var $chat_content = view.$el.find('.chat-content');
+                    var $chat_content = $(view.el).find('.chat-content');
                     expect($chat_content.find('.chat-info:last').text()).toBe('Topic set by ralphm to: '+subject);
                     done();
                 });
@@ -1597,7 +1604,7 @@
                 var __ = _converse.__;
                 test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'oldnick').then(function () {
                     var view = _converse.chatboxviews.get('lounge@localhost');
-                    var $chat_content = view.$el.find('.chat-content');
+                    var $chat_content = $(view.el).find('.chat-content');
 
                     // The user has just entered the room and receives their own
                     // presence from the server.
@@ -1617,7 +1624,7 @@
                     .c('status').attrs({code:'210'}).nodeTree;
 
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
-                    var $occupants = view.$('.occupant-list');
+                    var $occupants = $(view.el.querySelector('.occupant-list'));
                     expect($occupants.children().length).toBe(1);
                     expect($occupants.children().first(0).text()).toBe("oldnick");
 
@@ -1649,7 +1656,7 @@
                         __(_converse.muc.new_nickname_messages["303"], "newnick")
                     );
 
-                    $occupants = view.$('.occupant-list');
+                    $occupants = $(view.el.querySelector('.occupant-list'));
                     expect($occupants.children().length).toBe(0);
 
                     presence = $pres().attrs({
@@ -1672,7 +1679,7 @@
                     );
                     expect($chat_content.find('div.chat-info').last().html()).toBe(
                         "newnick has entered the room.");
-                    $occupants = view.$('.occupant-list');
+                    $occupants = $(view.el.querySelector('.occupant-list'));
                     expect($occupants.children().length).toBe(1);
                     expect($occupants.children().first(0).text()).toBe("newnick");
                     done();
@@ -1849,7 +1856,7 @@
                         .c('status', {code: '104'}).up()
                         .c('status', {code: '172'});
                     _converse.connection._dataRecv(test_utils.createRequest(message));
-                    var $chat_body = view.$('.chatroom-body');
+                    var $chat_body = $(view.el.querySelector('.chatroom-body'));
                     expect($chat_body.find('.message:last').text()).toBe('This room is now no longer anonymous');
                     done();
                 });
@@ -1894,9 +1901,9 @@
 
                     var view = _converse.chatboxviews.get('lounge@localhost');
                     view.onChatRoomPresence(presence);
-                    expect(view.$('.chat-area').is(':visible')).toBeFalsy();
-                    expect(view.$('.occupants').is(':visible')).toBeFalsy();
-                    var $chat_body = view.$('.chatroom-body');
+                    expect($(view.el.querySelector('.chat-area')).is(':visible')).toBeFalsy();
+                    expect($(view.el.querySelector('.occupants')).is(':visible')).toBeFalsy();
+                    var $chat_body = $(view.el.querySelector('.chatroom-body'));
                     expect($chat_body.find('.disconnect-msg').text()).toBe(
                         'You have been kicked from this room'+
                         'This action was done by Fluellen.'+
@@ -1951,15 +1958,15 @@
                 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.find('.toggle-chatbox-button').click();
+                view.el.querySelector('.toggle-chatbox-button').click();
 
                 expect(view.minimize).toHaveBeenCalled();
                 expect(_converse.emit).toHaveBeenCalledWith('chatBoxMinimized', jasmine.any(Object));
-                expect(view.$el.is(':visible')).toBeFalsy();
+                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.$("a.restore-chat").click();
+                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();
@@ -1978,7 +1985,7 @@
                 spyOn(_converse, 'emit');
                 spyOn(view, 'leave');
                 view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
-                view.$el.find('.close-chatbox-button').click();
+                view.el.querySelector('.close-chatbox-button').click();
                 expect(view.close).toHaveBeenCalled();
                 expect(view.leave).toHaveBeenCalled();
                 // XXX: After refactoring, the chat box only gets closed
@@ -2002,8 +2009,13 @@
                     var view = _converse.chatboxviews.get('lounge@localhost');
                     spyOn(view, 'onMessageSubmitted').and.callThrough();
                     var textarea = view.el.querySelector('.chat-textarea');
-                    textarea.textContent = '/help This is the room subject';
-                    $(textarea).trigger($.Event('keypress', {keyCode: 13}));
+                    textarea.value = '/help This is the room subject';
+                    view.keyPressed({
+                        target: textarea,
+                        preventDefault: _.noop,
+                        keyCode: 13
+                    });
+
                     expect(view.onMessageSubmitted).toHaveBeenCalled();
                     const info_messages = Array.prototype.slice.call(view.el.querySelectorAll('.chat-info:not(.chat-date)'), 0);
                     expect(info_messages.length).toBe(17);
@@ -2041,16 +2053,25 @@
                         sent_stanza = stanza;
                     });
                     // Check the alias /topic
-                    var $textarea = view.$el.find('.chat-textarea');
-                    $textarea.text('/topic This is the room subject');
-                    $textarea.trigger($.Event('keypress', {keyCode: 13}));
+                    var textarea = view.el.querySelector('.chat-textarea');
+                    textarea.value = '/topic This is the room subject';
+                    view.keyPressed({
+                        target: textarea,
+                        preventDefault: _.noop,
+                        keyCode: 13
+                    });
                     expect(view.onMessageSubmitted).toHaveBeenCalled();
                     expect(_converse.connection.send).toHaveBeenCalled();
                     expect(sent_stanza.textContent).toBe('This is the room subject');
 
                     // Check /subject
-                    $textarea.val('/subject This is a new subject');
-                    $textarea.trigger($.Event('keypress', {keyCode: 13}));
+                    textarea.value = '/subject This is a new subject';
+                    view.keyPressed({
+                        target: textarea,
+                        preventDefault: _.noop,
+                        keyCode: 13
+                    });
+
                     expect(sent_stanza.textContent).toBe('This is a new subject');
                     expect(sent_stanza.outerHTML).toBe(
                         '<message to="lounge@localhost" from="dummy@localhost/resource" type="groupchat" xmlns="jabber:client">'+
@@ -2058,8 +2079,12 @@
                         '</message>');
 
                     // Check case insensitivity
-                    $textarea.val('/Subject This is yet another subject');
-                    $textarea.trigger($.Event('keypress', {keyCode: 13}));
+                    textarea.value = '/Subject This is yet another subject';
+                    view.keyPressed({
+                        target: textarea,
+                        preventDefault: _.noop,
+                        keyCode: 13
+                    });
                     expect(sent_stanza.textContent).toBe('This is yet another subject');
                     expect(sent_stanza.outerHTML).toBe(
                         '<message to="lounge@localhost" from="dummy@localhost/resource" type="groupchat" xmlns="jabber:client">'+
@@ -2078,8 +2103,14 @@
                     var view = _converse.chatboxviews.get('lounge@localhost');
                     spyOn(view, 'onMessageSubmitted').and.callThrough();
                     spyOn(view, 'clearChatRoomMessages');
-                    view.$el.find('.chat-textarea').text('/clear');
-                    view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13}));
+                    var textarea = view.el.querySelector('.chat-textarea')
+                    textarea.value = '/clear';
+                    view.keyPressed({
+                        target: textarea,
+                        preventDefault: _.noop,
+                        keyCode: 13
+                    });
+
                     expect(view.onMessageSubmitted).toHaveBeenCalled();
                     expect(view.clearChatRoomMessages).toHaveBeenCalled();
                     done();
@@ -2103,8 +2134,13 @@
                     spyOn(view, 'setAffiliation').and.callThrough();
                     spyOn(view, 'showStatusNotification').and.callThrough();
                     spyOn(view, 'validateRoleChangeCommand').and.callThrough();
-                    view.$el.find('.chat-textarea').text('/owner');
-                    view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13}));
+                    var textarea = view.el.querySelector('.chat-textarea')
+                    textarea.value = '/owner';
+                    view.keyPressed({
+                        target: textarea,
+                        preventDefault: _.noop,
+                        keyCode: 13
+                    });
                     expect(view.onMessageSubmitted).toHaveBeenCalled();
                     expect(view.validateRoleChangeCommand).toHaveBeenCalled();
                     expect(view.showStatusNotification).toHaveBeenCalledWith(
@@ -2151,8 +2187,13 @@
                     spyOn(view, 'setAffiliation').and.callThrough();
                     spyOn(view, 'showStatusNotification').and.callThrough();
                     spyOn(view, 'validateRoleChangeCommand').and.callThrough();
-                    view.$el.find('.chat-textarea').text('/ban');
-                    view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13}));
+                    var textarea = view.el.querySelector('.chat-textarea')
+                    textarea.value = '/ban';
+                    view.keyPressed({
+                        target: textarea,
+                        preventDefault: _.noop,
+                        keyCode: 13
+                    });
                     expect(view.onMessageSubmitted).toHaveBeenCalled();
                     expect(view.validateRoleChangeCommand).toHaveBeenCalled();
                     expect(view.showStatusNotification).toHaveBeenCalledWith(
@@ -2198,8 +2239,14 @@
                     spyOn(view, 'modifyRole').and.callThrough();
                     spyOn(view, 'showStatusNotification').and.callThrough();
                     spyOn(view, 'validateRoleChangeCommand').and.callThrough();
-                    view.$el.find('.chat-textarea').text('/kick');
-                    view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13}));
+
+                    var textarea = view.el.querySelector('.chat-textarea')
+                    textarea.value = '/kick';
+                    view.keyPressed({
+                        target: textarea,
+                        preventDefault: _.noop,
+                        keyCode: 13
+                    });
                     expect(view.onMessageSubmitted).toHaveBeenCalled();
                     expect(view.validateRoleChangeCommand).toHaveBeenCalled();
                     expect(view.showStatusNotification).toHaveBeenCalledWith(
@@ -2297,8 +2344,14 @@
                     var info_msgs = Array.prototype.slice.call(view.el.querySelectorAll('.chat-info'), 0);
                     expect(info_msgs.pop().textContent).toBe("trustworthyguy has entered the room.");
 
-                    view.$el.find('.chat-textarea').text('/op');
-                    view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13}));
+                    var textarea = view.el.querySelector('.chat-textarea')
+                    textarea.value = '/op';
+                    view.keyPressed({
+                        target: textarea,
+                        preventDefault: _.noop,
+                        keyCode: 13
+                    });
+
                     expect(view.onMessageSubmitted).toHaveBeenCalled();
                     expect(view.validateRoleChangeCommand).toHaveBeenCalled();
                     expect(view.showStatusNotification).toHaveBeenCalledWith(
@@ -2430,8 +2483,14 @@
                     var info_msgs = Array.prototype.slice.call(view.el.querySelectorAll('.chat-info'), 0);
                     expect(info_msgs.pop().textContent).toBe("annoyingGuy has entered the room.");
 
-                    view.$el.find('.chat-textarea').text('/mute');
-                    view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13}));
+                    var textarea = view.el.querySelector('.chat-textarea')
+                    textarea.value = '/mute';
+                    view.keyPressed({
+                        target: textarea,
+                        preventDefault: _.noop,
+                        keyCode: 13
+                    });
+
                     expect(view.onMessageSubmitted).toHaveBeenCalled();
                     expect(view.validateRoleChangeCommand).toHaveBeenCalled();
                     expect(view.showStatusNotification).toHaveBeenCalledWith(
@@ -2525,13 +2584,15 @@
 
             var submitRoomForm = function (_converse) {
                 var roomspanel = _converse.chatboxviews.get('controlbox').roomspanel;
-                var $input = roomspanel.$el.find('input.new-chatroom-name');
-                var $nick = roomspanel.$el.find('input.new-chatroom-nick');
-                var $server = roomspanel.$el.find('input.new-chatroom-server');
-                $input.val('problematic');
-                $nick.val('dummy');
-                $server.val('muc.localhost');
-                roomspanel.$el.find('form').submit();
+                var input = roomspanel.el.querySelector('input.new-chatroom-name');
+                var nick = roomspanel.el.querySelector('input.new-chatroom-nick');
+                var server = roomspanel.el.querySelector('input.new-chatroom-server');
+                input.value = 'problematic';
+                if (nick) {
+                    nick.value = 'dummy';
+                }
+                server.value = 'muc.localhost';
+                roomspanel.el.querySelector('form [type="submit"]').click();
             };
 
             it("will show an error message if the room requires a password",
@@ -2553,7 +2614,7 @@
                 spyOn(view, 'renderPasswordForm').and.callThrough();
                 view.onChatRoomPresence(presence);
 
-                var $chat_body = view.$el.find('.chatroom-body');
+                var $chat_body = $(view.el).find('.chatroom-body');
                 expect(view.renderPasswordForm).toHaveBeenCalled();
                 expect($chat_body.find('form.chatroom-form').length).toBe(1);
                 expect($chat_body.find('legend').text()).toBe('This chatroom requires a password');
@@ -2584,7 +2645,7 @@
                 var view = _converse.chatboxviews.get('problematic@muc.localhost');
                 spyOn(view, 'showErrorMessage').and.callThrough();
                 view.onChatRoomPresence(presence);
-                expect(view.$el.find('.chatroom-body p:last').text()).toBe('You are not on the member list of this room.');
+                expect($(view.el).find('.chatroom-body p:last').text()).toBe('You are not on the member list of this room.');
                 done();
             }));
 
@@ -2605,7 +2666,7 @@
                 var view = _converse.chatboxviews.get('problematic@muc.localhost');
                 spyOn(view, 'showErrorMessage').and.callThrough();
                 view.onChatRoomPresence(presence);
-                expect(view.$el.find('.chatroom-body p:last').text()).toBe('You have been banned from this room.');
+                expect($(view.el).find('.chatroom-body p:last').text()).toBe('You have been banned from this room.');
                 done();
             }));
 
@@ -2626,9 +2687,9 @@
                 var view = _converse.chatboxviews.get('problematic@muc.localhost');
                 spyOn(view, 'showErrorMessage').and.callThrough();
                 view.onChatRoomPresence(presence);
-                expect(view.$el.find('.chatroom-body form.chatroom-form label:first').text()).toBe('Please choose your nickname');
+                expect($(view.el).find('.chatroom-body form.chatroom-form label:first').text()).toBe('Please choose your nickname');
 
-                var $input = view.$el.find('.chatroom-body form.chatroom-form input:first');
+                var $input = $(view.el).find('.chatroom-body form.chatroom-form input:first');
                 $input.val('nicky');
                 view.el.querySelector('input[type=submit]').click();
                 done();
@@ -2709,7 +2770,7 @@
                 var view = _converse.chatboxviews.get('problematic@muc.localhost');
                 spyOn(view, 'showErrorMessage').and.callThrough();
                 view.onChatRoomPresence(presence);
-                expect(view.$el.find('.chatroom-body p:last').text()).toBe('You are not allowed to create new rooms.');
+                expect($(view.el).find('.chatroom-body p:last').text()).toBe('You are not allowed to create new rooms.');
                 done();
             }));
 
@@ -2730,7 +2791,7 @@
                 var view = _converse.chatboxviews.get('problematic@muc.localhost');
                 spyOn(view, 'showErrorMessage').and.callThrough();
                 view.onChatRoomPresence(presence);
-                expect(view.$el.find('.chatroom-body p:last').text()).toBe("Your nickname doesn't conform to this room's policies.");
+                expect($(view.el).find('.chatroom-body p:last').text()).toBe("Your nickname doesn't conform to this room's policies.");
                 done();
             }));
 
@@ -2751,7 +2812,7 @@
                 var view = _converse.chatboxviews.get('problematic@muc.localhost');
                 spyOn(view, 'showErrorMessage').and.callThrough();
                 view.onChatRoomPresence(presence);
-                expect(view.$el.find('.chatroom-body p:last').text()).toBe("This room does not (yet) exist.");
+                expect($(view.el).find('.chatroom-body p:last').text()).toBe("This room does not (yet) exist.");
                 done();
             }));
 
@@ -2772,7 +2833,7 @@
                 var view = _converse.chatboxviews.get('problematic@muc.localhost');
                 spyOn(view, 'showErrorMessage').and.callThrough();
                 view.onChatRoomPresence(presence);
-                expect(view.$el.find('.chatroom-body p:last').text()).toBe("This room has reached its maximum number of occupants.");
+                expect($(view.el).find('.chatroom-body p:last').text()).toBe("This room has reached its maximum number of occupants.");
                 done();
             }));
         });
@@ -3008,15 +3069,15 @@
 
                 test_utils.openControlBox();
                 var cbview = _converse.chatboxviews.get('controlbox');
-                var $tabs = cbview.$el.find('#controlbox-tabs');
-                var $panels = cbview.$el.find('.controlbox-panes');
+                var $tabs = $(cbview.el).find('#controlbox-tabs');
+                var $panels = $(cbview.el).find('.controlbox-panes');
                 var $contacts = $panels.children().first();
                 var $chatrooms = $panels.children().last();
                 spyOn(cbview, 'switchTab').and.callThrough();
                 cbview.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
-                $tabs.find('li').last().find('a').click(); // Clicks the chatrooms tab
-                expect($contacts.is(':visible')).toBe(false);
-                expect($chatrooms.is(':visible')).toBe(true);
+                $tabs.find('li').last().find('a')[0].click(); // Clicks the chatrooms tab
+                expect(u.isVisible($contacts[0])).toBe(false);
+                expect(u.isVisible($chatrooms[0])).toBe(true);
                 expect(cbview.switchTab).toHaveBeenCalled();
                 done();
             }));
@@ -3028,9 +3089,9 @@
 
                 test_utils.openControlBox();
                 var roomspanel = _converse.chatboxviews.get('controlbox').roomspanel;
-                var $input = roomspanel.$el.find('input.new-chatroom-name');
-                var $nick = roomspanel.$el.find('input.new-chatroom-nick');
-                var $server = roomspanel.$el.find('input.new-chatroom-server');
+                var $input = $(roomspanel.el).find('input.new-chatroom-name');
+                var $nick = $(roomspanel.el).find('input.new-chatroom-nick');
+                var $server = $(roomspanel.el).find('input.new-chatroom-server');
                 expect($input.length).toBe(1);
                 expect($server.length).toBe(1);
                 expect($('.chatroom:visible').length).toBe(0); // There shouldn't be any chatrooms open currently
@@ -3045,7 +3106,7 @@
                 $input.val('Lounge');
                 $nick.val('dummy');
                 $server.val('muc.localhost');
-                roomspanel.$el.find('form').submit();
+                roomspanel.el.querySelector('form [type="submit"]').click();
                 expect(roomspanel.openChatRoom).toHaveBeenCalled();
                 expect($('.chatroom:visible').length).toBe(1); // There should now be an open chatroom
                 done();
@@ -3058,7 +3119,7 @@
 
                 test_utils.openControlBox();
                 var panel = _converse.chatboxviews.get('controlbox').roomspanel;
-                $(panel.tabs).find('li').last().find('a').click(); // Click the chatrooms tab
+                $(panel.tabs).find('li').last().find('a')[0].click(); // Click the chatrooms tab
                 panel.model.set({'muc_domain': 'muc.localhost'}); // Make sure the domain is set
                 // See: http://xmpp.org/extensions/xep-0045.html#disco-rooms
                 expect($('#available-chatrooms').children('dt').length).toBe(0);
@@ -3075,9 +3136,9 @@
                   .c('item', { jid:'inverness@chat.shakespeare.lit', name:'Macbeth&apos;s Castle'}).nodeTree;
 
                 panel.onRoomsFound(iq);
-                expect(panel.$('#available-chatrooms').children('dt').length).toBe(1);
-                expect(panel.$('#available-chatrooms').children('dt').first().text()).toBe("Rooms on muc.localhost");
-                expect(panel.$('#available-chatrooms').children('dd').length).toBe(4);
+                expect($(panel.el.querySelector('#available-chatrooms')).children('dt').length).toBe(1);
+                expect($(panel.el.querySelector('#available-chatrooms')).children('dt').first().text()).toBe("Rooms on muc.localhost");
+                expect($(panel.el.querySelector('#available-chatrooms')).children('dd').length).toBe(4);
                 done();
             }));
         });

+ 21 - 21
spec/controlbox.js

@@ -23,7 +23,7 @@
             spyOn(_converse, 'emit');
             // Redelegate so that the spies are now registered as the event handlers (specifically for 'onClick')
             _converse.controlboxtoggle.delegateEvents();
-            $('.toggle-controlbox').click();
+            document.querySelector('.toggle-controlbox').click();
             expect(_converse.controlboxtoggle.onClick).toHaveBeenCalled();
             expect(_converse.controlboxtoggle.showControlBox).toHaveBeenCalled();
             expect(_converse.emit).toHaveBeenCalledWith('controlBoxOpened', jasmine.any(Object));
@@ -40,8 +40,8 @@
 
                 test_utils.openControlBox();
                 var view = _converse.xmppstatusview;
-                expect(view.$el.find('a.choose-xmpp-status').hasClass('online')).toBe(true);
-                expect(view.$el.find('a.choose-xmpp-status').attr('data-value')).toBe('I am online');
+                expect($(view.el).find('a.choose-xmpp-status').hasClass('online')).toBe(true);
+                expect($(view.el).find('a.choose-xmpp-status').attr('data-value')).toBe('I am online');
                 done();
             }));
 
@@ -56,17 +56,17 @@
                 spyOn(view, 'setStatus').and.callThrough();
                 spyOn(_converse, 'emit');
                 view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
-                view.$el.find('a.choose-xmpp-status').click();
+                view.el.querySelector('a.choose-xmpp-status').click();
                 expect(view.toggleOptions).toHaveBeenCalled();
                 spyOn(view, 'updateStatusUI').and.callThrough();
                 view.initialize(); // Rebind events for spy
-                $(view.$el.find('.dropdown dd ul li a')[1]).click(); // Change status to "dnd"
+                $(view.el).find('.dropdown dd ul li a')[1].click(); // Change status to "dnd"
                 expect(view.setStatus).toHaveBeenCalled();
                 expect(_converse.emit).toHaveBeenCalledWith('statusChanged', 'dnd');
                 expect(view.updateStatusUI).toHaveBeenCalled();
-                expect(view.$el.find('a.choose-xmpp-status').hasClass('online')).toBe(false);
-                expect(view.$el.find('a.choose-xmpp-status').hasClass('dnd')).toBe(true);
-                expect(view.$el.find('a.choose-xmpp-status').attr('data-value')).toBe('I am busy');
+                expect($(view.el).find('a.choose-xmpp-status').hasClass('online')).toBe(false);
+                expect($(view.el).find('a.choose-xmpp-status').hasClass('dnd')).toBe(true);
+                expect($(view.el).find('a.choose-xmpp-status').attr('data-value')).toBe('I am busy');
                 done();
             }));
 
@@ -82,15 +82,15 @@
                 spyOn(view, 'renderStatusChangeForm').and.callThrough();
                 spyOn(_converse, 'emit');
                 view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
-                view.$el.find('a.change-xmpp-status-message').click();
+                view.el.querySelector('a.change-xmpp-status-message').click();
                 expect(view.renderStatusChangeForm).toHaveBeenCalled();
                 var msg = 'I am happy';
-                view.$el.find('input.custom-xmpp-status').val(msg);
-                view.$el.submit();
+                view.el.querySelector('input.custom-xmpp-status').value = msg;
+                view.el.querySelector('[type="submit"]').click();
                 expect(view.setStatusMessage).toHaveBeenCalled();
                 expect(_converse.emit).toHaveBeenCalledWith('statusMessageChanged', msg);
-                expect(view.$el.find('a.choose-xmpp-status').hasClass('online')).toBe(true);
-                expect(view.$el.find('a.choose-xmpp-status').attr('data-value')).toBe(msg);
+                expect($(view.el).find('a.choose-xmpp-status').hasClass('online')).toBe(true);
+                expect($(view.el).find('a.choose-xmpp-status').attr('data-value')).toBe(msg);
                 done();
             }));
         });
@@ -106,10 +106,10 @@
             var panel = _converse.chatboxviews.get('controlbox').contactspanel;
             spyOn(panel, 'toggleContactForm').and.callThrough();
             panel.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
-            panel.$el.find('a.toggle-xmpp-contact-form').click();
+            panel.el.querySelector('a.toggle-xmpp-contact-form').click();
             expect(panel.toggleContactForm).toHaveBeenCalled();
             // XXX: Awaiting more tests, close it again for now...
-            panel.$el.find('a.toggle-xmpp-contact-form').click();
+            panel.el.querySelector('a.toggle-xmpp-contact-form').click();
             done();
         }));
 
@@ -135,10 +135,10 @@
                 fullname: mock.pend_names[0]
             });
             test_utils.waitUntil(function () {
-                return _converse.rosterview.$el.find('.roster-group li:visible').length;
+                return $(_converse.rosterview.el).find('.roster-group li:visible').length;
             }, 700).then(function () {
                 // Checking that only one entry is created because both JID is same (Case sensitive check)
-                expect(_converse.rosterview.$el.find('li:visible').length).toBe(1);
+                expect($(_converse.rosterview.el).find('li:visible').length).toBe(1);
                 expect(_converse.rosterview.update).toHaveBeenCalled();
                 done();
             });
@@ -154,7 +154,7 @@
 
             test_utils.openControlBox();
             var cbview = _converse.chatboxviews.get('controlbox');
-            var $panels = cbview.$el.find('.controlbox-panes');
+            var $panels = $(cbview.el).find('.controlbox-panes');
             expect($panels.children().length).toBe(2);
             expect($panels.children().first().attr('id')).toBe('users');
             expect($panels.children().first().is(':visible')).toBe(true);
@@ -170,11 +170,11 @@
 
             test_utils.openControlBox();
             var cbview = _converse.chatboxviews.get('controlbox');
-            var $tabs = cbview.$el.find('#controlbox-tabs');
+            var $tabs = $(cbview.el).find('#controlbox-tabs');
             expect(cbview.model.get('active-panel')).toBe('users');
-            $tabs.find('li').last().find('a').click();
+            $tabs.find('li').last().find('a')[0].click();
             expect(cbview.model.get('active-panel')).toBe('chatrooms');
-            $tabs.find('li').first().find('a').click();
+            $tabs.find('li').first().find('a')[0].click();
             expect(cbview.model.get('active-panel')).toBe('users');
             done();
         }));

+ 4 - 3
spec/converse.js

@@ -1,10 +1,11 @@
 (function (root, factory) {
     define([
+        "jquery.noconflict",
         "jasmine",
         "converse-core",
         "mock",
         "test-utils"], factory);
-} (this, function (jasmine, converse, mock, test_utils) {
+} (this, function ($, jasmine, converse, mock, test_utils) {
     var b64_sha1 = converse.env.b64_sha1;
     var _ = converse.env._;
 
@@ -292,7 +293,7 @@
                     expect(box instanceof Object).toBeTruthy();
                     expect(box.model.get('box_id')).toBe(b64_sha1(jid));
                     chatboxview = _converse.chatboxviews.get(jid);
-                    expect(chatboxview.$el.is(':visible')).toBeTruthy();
+                    expect($(chatboxview.el).is(':visible')).toBeTruthy();
                     // Test for multiple JIDs
                     var jid2 = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost';
                     test_utils.openChatBoxFor(_converse, jid2);
@@ -320,7 +321,7 @@
                     ['close', 'endOTR', 'focus', 'get', 'initiateOTR', 'is_chatroom', 'maximize', 'minimize', 'open', 'set']
                 );
                 chatboxview = _converse.chatboxviews.get(jid);
-                expect(chatboxview.$el.is(':visible')).toBeTruthy();
+                expect($(chatboxview.el).is(':visible')).toBeTruthy();
                 // Test for multiple JIDs
                 var jid2 = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost';
                 var list = _converse.api.chats.open([jid, jid2]);

+ 21 - 21
spec/minchats.js

@@ -1,6 +1,6 @@
 (function (root, factory) {
-    define(["jasmine", "mock", "converse-core", "test-utils"], factory);
-} (this, function (jasmine, mock, converse, test_utils) {
+    define(["jquery.noconflict", "jasmine", "mock", "converse-core", "test-utils"], factory);
+} (this, function ($, jasmine, mock, converse, test_utils) {
     var _ = converse.env._;
     var $msg = converse.env.$msg;
 
@@ -22,10 +22,10 @@
             test_utils.openChatBoxFor(_converse, contact_jid);
             chatview = _converse.chatboxviews.get(contact_jid);
             expect(chatview.model.get('minimized')).toBeFalsy();
-            expect(_converse.minimized_chats.$el.is(':visible')).toBeFalsy();
-            chatview.$el.find('.toggle-chatbox-button').click();
+            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.el).is(':visible')).toBeTruthy();
             expect(_converse.minimized_chats.keys().length).toBe(1);
             expect(_converse.minimized_chats.keys()[0]).toBe(contact_jid);
 
@@ -33,9 +33,9 @@
             test_utils.openChatBoxFor(_converse, contact_jid);
             chatview = _converse.chatboxviews.get(contact_jid);
             expect(chatview.model.get('minimized')).toBeFalsy();
-            chatview.$el.find('.toggle-chatbox-button').click();
+            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.el).is(':visible')).toBeTruthy();
             expect(_converse.minimized_chats.keys().length).toBe(2);
             expect(_.includes(_converse.minimized_chats.keys(), contact_jid)).toBeTruthy();
             done();
@@ -55,17 +55,17 @@
             var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
             test_utils.openChatBoxFor(_converse, contact_jid);
             var chatview = _converse.chatboxviews.get(contact_jid);
-            expect(_converse.minimized_chats.$el.is(':visible')).toBeFalsy();
+            expect($(_converse.minimized_chats.el).is(':visible')).toBeFalsy();
             chatview.model.set({'minimized': true});
-            expect(_converse.minimized_chats.$el.is(':visible')).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);
-            expect(_converse.minimized_chats.$('.minimized-chats-flyout').is(':visible')).toBeTruthy();
+            expect($(_converse.minimized_chats.el.querySelector('.minimized-chats-flyout')).is(':visible')).toBeTruthy();
             expect(_converse.minimized_chats.toggleview.model.get('collapsed')).toBeFalsy();
-            _converse.minimized_chats.$('#toggle-minimized-chats').click();
+            _converse.minimized_chats.el.querySelector('#toggle-minimized-chats').click();
 
             return test_utils.waitUntil(function () {
-                return _converse.minimized_chats.$('.minimized-chats-flyout').is(':visible');
+                return $(_converse.minimized_chats.el.querySelector('.minimized-chats-flyout')).is(':visible');
             }, 500).then(function () {
                 expect(_converse.minimized_chats.toggleview.model.get('collapsed')).toBeTruthy();
                 done();
@@ -85,7 +85,7 @@
 
             var i, contact_jid, chatview, msg;
             _converse.minimized_chats.toggleview.model.set({'collapsed': true});
-            expect(_converse.minimized_chats.toggleview.$('.unread-message-count').is(':visible')).toBeFalsy();
+            expect($(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count')).is(':visible')).toBeFalsy();
             for (i=0; i<3; i++) {
                 contact_jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
                 test_utils.openChatBoxFor(_converse, contact_jid);
@@ -99,8 +99,8 @@
                 }).c('body').t('This message is sent to a minimized chatbox').up()
                 .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
                 _converse.chatboxes.onMessage(msg);
-                expect(_converse.minimized_chats.toggleview.$('.unread-message-count').is(':visible')).toBeTruthy();
-                expect(_converse.minimized_chats.toggleview.$('.unread-message-count').text()).toBe((i+1).toString());
+                expect($(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count')).is(':visible')).toBeTruthy();
+                expect($(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count')).text()).toBe((i+1).toString());
             }
             // Chat state notifications don't increment the unread messages counter
             // <composing> state
@@ -110,7 +110,7 @@
                 type: 'chat',
                 id: (new Date()).getTime()
             }).c('composing', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
-            expect(_converse.minimized_chats.toggleview.$('.unread-message-count').text()).toBe((i).toString());
+            expect($(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count')).text()).toBe((i).toString());
 
             // <paused> state
             _converse.chatboxes.onMessage($msg({
@@ -119,7 +119,7 @@
                 type: 'chat',
                 id: (new Date()).getTime()
             }).c('paused', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
-            expect(_converse.minimized_chats.toggleview.$('.unread-message-count').text()).toBe((i).toString());
+            expect($(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count')).text()).toBe((i).toString());
 
             // <gone> state
             _converse.chatboxes.onMessage($msg({
@@ -128,7 +128,7 @@
                 type: 'chat',
                 id: (new Date()).getTime()
             }).c('gone', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
-            expect(_converse.minimized_chats.toggleview.$('.unread-message-count').text()).toBe((i).toString());
+            expect($(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count')).text()).toBe((i).toString());
 
             // <inactive> state
             _converse.chatboxes.onMessage($msg({
@@ -137,7 +137,7 @@
                 type: 'chat',
                 id: (new Date()).getTime()
             }).c('inactive', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
-            expect(_converse.minimized_chats.toggleview.$('.unread-message-count').text()).toBe((i).toString());
+            expect($(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count')).text()).toBe((i).toString());
             done();
         }));
 
@@ -163,8 +163,8 @@
                     }).c('body').t(message).tree();
                 view.handleMUCMessage(msg);
 
-                expect(_converse.minimized_chats.toggleview.$('.unread-message-count').is(':visible')).toBeTruthy();
-                expect(_converse.minimized_chats.toggleview.$('.unread-message-count').text()).toBe('1');
+                expect($(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count')).is(':visible')).toBeTruthy();
+                expect($(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count')).text()).toBe('1');
                 done();
             });
         }));

+ 4 - 4
spec/notification.js

@@ -1,6 +1,6 @@
 (function (root, factory) {
-    define(["jasmine", "mock", "converse-core", "test-utils", "utils"], factory);
-} (this, function (jasmine, mock, converse, test_utils, utils) {
+    define(["jquery.noconflict", "jasmine", "mock", "converse-core", "test-utils", "utils"], factory);
+} (this, function ($, jasmine, mock, converse, test_utils, utils) {
     "use strict";
     var _ = converse.env._;
     var $msg = converse.env.$msg;
@@ -46,7 +46,7 @@
                         test_utils.createContacts(_converse, 'current');
                         test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () {
                             var view = _converse.chatboxviews.get('lounge@localhost');
-                            if (!view.$el.find('.chat-area').length) { view.renderChatArea(); }
+                            if (!$(view.el).find('.chat-area').length) { view.renderChatArea(); }
                             var no_notification = false;
                             if (typeof window.Notification === 'undefined') {
                                 no_notification = true;
@@ -165,7 +165,7 @@
                         _converse.play_sounds = true;
                         spyOn(_converse, 'playSoundNotification');
                         var view = _converse.chatboxviews.get('lounge@localhost');
-                        if (!view.$el.find('.chat-area').length) { view.renderChatArea(); }
+                        if (!$(view.el).find('.chat-area').length) { view.renderChatArea(); }
                         var text = 'This message will play a sound because it mentions dummy';
                         var message = $msg({
                             from: 'lounge@localhost/otheruser',

+ 4 - 4
spec/protocol.js

@@ -84,7 +84,7 @@
                     expect(_.isNull(form)).toBeTruthy();
 
                     // Click the "Add a contact" link.
-                    panel.$('.toggle-xmpp-contact-form').click();
+                    panel.el.querySelector('.toggle-xmpp-contact-form').click();
 
                     // Check that the form appears
                     form = panel.el.querySelector('form.add-xmpp-contact');
@@ -92,8 +92,8 @@
                     expect(_.includes(form.parentElement.classList, 'collapsed')).toBeFalsy();
 
                     // Fill in the form and submit
-                    $(form).find('input').val('contact@example.org');
-                    $(form).submit();
+                    form.querySelector('input').value = 'contact@example.org';
+                    form.querySelector('[type="submit"]').click();
 
                     /* In preparation for being able to render the contact in the
                     * user's client interface and for the server to keep track of the
@@ -496,7 +496,7 @@
 
                     var $header = $('a:contains("My contacts")');
                     // remove the first user
-                    $($header.parent().find('li .remove-xmpp-contact').get(0)).click();
+                    $header.parent().find('li .remove-xmpp-contact').get(0).click();
                     expect(window.confirm).toHaveBeenCalled();
 
                     /* Section 8.6 Removing a Roster Item and Cancelling All

+ 149 - 149
spec/register.js

@@ -21,7 +21,7 @@
 
             test_utils.openControlBox();
             var cbview = _converse.chatboxviews.get('controlbox');
-            expect(cbview.$('a.register-account').length).toBe(0);
+            expect($(cbview.el.querySelector('a.register-account')).length).toBe(0);
             done();
             });
         }));
@@ -39,7 +39,7 @@
             .then(function () {
             var cbview = _converse.chatboxviews.get('controlbox');
             test_utils.openControlBox();
-            var $panels = cbview.$('.controlbox-panes');
+            var $panels = $(cbview.el.querySelector('.controlbox-panes'));
             var $login = $panels.children().first();
             var $registration = $panels.children().last();
 
@@ -78,17 +78,17 @@
             cbview.el.querySelector('.toggle-register-login').click();
 
             // Check the form layout
-            var $form = cbview.$('#converse-register');
+            var $form = $(cbview.el.querySelector('#converse-register'));
             expect($form.find('input').length).toEqual(2);
             expect($form.find('input').first().attr('name')).toEqual('domain');
             expect($form.find('input').last().attr('type')).toEqual('submit');
             // Check that the input[type=domain] input is required
-            $form.find('input[type=submit]').click();
+            $form.find('input[type=submit]')[0].click();
             expect(registerview.onProviderChosen).not.toHaveBeenCalled();
 
             // Check that the form is accepted if input[type=domain] has a value
             $form.find('input[name=domain]').val('conversejs.org');
-            $form.find('input[type=submit]').click();
+            $form.find('input[type=submit]')[0].click();
             expect(registerview.onProviderChosen).toHaveBeenCalled();
             expect(_converse.connection.connect).toHaveBeenCalled();
             done();
@@ -104,53 +104,53 @@
 
             test_utils.waitUntil(function () {
                     return _.get(_converse.chatboxviews.get('controlbox'), 'registerpanel');
-                }, 300)
-            .then(function () {
-
-            var cbview = _converse.chatboxviews.get('controlbox');
-            cbview.$('#controlbox-tabs').find('li').last().find('a').click(); // Click the Register tab
-            var registerview = _converse.chatboxviews.get('controlbox').registerpanel;
-            spyOn(registerview, 'onProviderChosen').and.callThrough();
-            spyOn(registerview, 'getRegistrationFields').and.callThrough();
-            spyOn(registerview, 'onRegistrationFields').and.callThrough();
-            spyOn(registerview, 'renderRegistrationForm').and.callThrough();
-            registerview.delegateEvents();  // We need to rebind all events otherwise our spy won't be called
-            spyOn(_converse.connection, 'connect').and.callThrough();
-
-            expect(registerview._registering).toBeFalsy();
-            expect(_converse.connection.connected).toBeFalsy();
-            registerview.$('input[name=domain]').val('conversejs.org');
-            registerview.$('input[type=submit]').click();
-            expect(registerview.onProviderChosen).toHaveBeenCalled();
-            expect(registerview._registering).toBeTruthy();
-            expect(_converse.connection.connect).toHaveBeenCalled();
-
-            var stanza = new Strophe.Builder("stream:features", {
-                        'xmlns:stream': "http://etherx.jabber.org/streams",
-                        'xmlns': "jabber:client"
-                    })
-                .c('register',  {xmlns: "http://jabber.org/features/iq-register"}).up()
-                .c('mechanisms', {xmlns: "urn:ietf:params:xml:ns:xmpp-sasl"});
-            _converse.connection._connect_cb(test_utils.createRequest(stanza));
-
-            expect(registerview.getRegistrationFields).toHaveBeenCalled();
-
-            stanza = $iq({
-                    'type': 'result',
-                    'id': 'reg1'
-                }).c('query', {'xmlns': 'jabber:iq:register'})
-                    .c('instructions')
-                        .t('Please choose a username, password and provide your email address').up()
-                    .c('username').up()
-                    .c('password').up()
-                    .c('email');
-            _converse.connection._dataRecv(test_utils.createRequest(stanza));
-            expect(registerview.onRegistrationFields).toHaveBeenCalled();
-            expect(registerview.renderRegistrationForm).toHaveBeenCalled();
-            expect(registerview.$('input').length).toBe(5);
-            expect(registerview.$('input[type=submit]').length).toBe(1);
-            expect(registerview.$('input[type=button]').length).toBe(1);
-            done();
+            }, 300).then(function () {
+                test_utils.openControlBox();
+                var cbview = _converse.chatboxviews.get('controlbox');
+                cbview.el.querySelector('.toggle-register-login').click();
+
+                var registerview = _converse.chatboxviews.get('controlbox').registerpanel;
+                spyOn(registerview, 'onProviderChosen').and.callThrough();
+                spyOn(registerview, 'getRegistrationFields').and.callThrough();
+                spyOn(registerview, 'onRegistrationFields').and.callThrough();
+                spyOn(registerview, 'renderRegistrationForm').and.callThrough();
+                registerview.delegateEvents();  // We need to rebind all events otherwise our spy won't be called
+                spyOn(_converse.connection, 'connect').and.callThrough();
+
+                expect(registerview._registering).toBeFalsy();
+                expect(_converse.connection.connected).toBeFalsy();
+                registerview.el.querySelector('input[name=domain]').value  = 'conversejs.org';
+                registerview.el.querySelector('input[type=submit]').click();
+                expect(registerview.onProviderChosen).toHaveBeenCalled();
+                expect(registerview._registering).toBeTruthy();
+                expect(_converse.connection.connect).toHaveBeenCalled();
+
+                var stanza = new Strophe.Builder("stream:features", {
+                            'xmlns:stream': "http://etherx.jabber.org/streams",
+                            'xmlns': "jabber:client"
+                        })
+                    .c('register',  {xmlns: "http://jabber.org/features/iq-register"}).up()
+                    .c('mechanisms', {xmlns: "urn:ietf:params:xml:ns:xmpp-sasl"});
+                _converse.connection._connect_cb(test_utils.createRequest(stanza));
+
+                expect(registerview.getRegistrationFields).toHaveBeenCalled();
+
+                stanza = $iq({
+                        'type': 'result',
+                        'id': 'reg1'
+                    }).c('query', {'xmlns': 'jabber:iq:register'})
+                        .c('instructions')
+                            .t('Please choose a username, password and provide your email address').up()
+                        .c('username').up()
+                        .c('password').up()
+                        .c('email');
+                _converse.connection._dataRecv(test_utils.createRequest(stanza));
+                expect(registerview.onRegistrationFields).toHaveBeenCalled();
+                expect(registerview.renderRegistrationForm).toHaveBeenCalled();
+                expect(registerview.el.querySelectorAll('input').length).toBe(5);
+                expect(registerview.el.querySelectorAll('input[type=submit]').length).toBe(1);
+                expect(registerview.el.querySelectorAll('input[type=button]').length).toBe(1);
+                done();
             });
         }));
 
@@ -165,52 +165,53 @@
                     return _.get(_converse.chatboxviews.get('controlbox'), 'registerpanel');
                 }, 300)
             .then(function () {
-
-            var cbview = _converse.chatboxviews.get('controlbox');
-            cbview.$('#controlbox-tabs').find('li').last().find('a').click(); // Click the Register tab
-            var registerview = cbview.registerpanel;
-            spyOn(registerview, 'onProviderChosen').and.callThrough();
-            spyOn(registerview, 'getRegistrationFields').and.callThrough();
-            spyOn(registerview, 'onRegistrationFields').and.callThrough();
-            spyOn(registerview, 'renderRegistrationForm').and.callThrough();
-            registerview.delegateEvents();  // We need to rebind all events otherwise our spy won't be called
-            spyOn(_converse.connection, 'connect').and.callThrough();
-
-            registerview.$('input[name=domain]').val('conversejs.org');
-            registerview.$('input[type=submit]').click();
-
-            var stanza = new Strophe.Builder("stream:features", {
-                        'xmlns:stream': "http://etherx.jabber.org/streams",
-                        'xmlns': "jabber:client"
-                    })
-                .c('register',  {xmlns: "http://jabber.org/features/iq-register"}).up()
-                .c('mechanisms', {xmlns: "urn:ietf:params:xml:ns:xmpp-sasl"});
-            _converse.connection._connect_cb(test_utils.createRequest(stanza));
-            stanza = $iq({
-                    'type': 'result',
-                    'id': 'reg1'
-                }).c('query', {'xmlns': 'jabber:iq:register'})
-                    .c('instructions')
-                        .t('Please choose a username, password and provide your email address').up()
-                    .c('username').up()
-                    .c('password').up()
-                    .c('email');
-            _converse.connection._dataRecv(test_utils.createRequest(stanza));
-            expect(registerview.form_type).toBe('legacy');
-
-            registerview.$('input[name=username]').val('testusername');
-            registerview.$('input[name=password]').val('testpassword');
-            registerview.$('input[name=email]').val('test@email.local');
-
-            spyOn(_converse.connection, 'send');
-
-            registerview.$('input[type=submit]').click();
-
-            expect(_converse.connection.send).toHaveBeenCalled();
-            var $stanza = $(_converse.connection.send.calls.argsFor(0)[0].tree());
-            expect($stanza.children('query').children().length).toBe(3);
-            expect($stanza.children('query').children()[0].tagName).toBe('username');
-            done();
+                test_utils.openControlBox();
+                var cbview = _converse.chatboxviews.get('controlbox');
+                cbview.el.querySelector('.toggle-register-login').click();
+
+                var registerview = cbview.registerpanel;
+                spyOn(registerview, 'onProviderChosen').and.callThrough();
+                spyOn(registerview, 'getRegistrationFields').and.callThrough();
+                spyOn(registerview, 'onRegistrationFields').and.callThrough();
+                spyOn(registerview, 'renderRegistrationForm').and.callThrough();
+                registerview.delegateEvents();  // We need to rebind all events otherwise our spy won't be called
+                spyOn(_converse.connection, 'connect').and.callThrough();
+
+                registerview.el.querySelector('input[name=domain]').value = 'conversejs.org';
+                registerview.el.querySelector('input[type=submit]').click();
+
+                var stanza = new Strophe.Builder("stream:features", {
+                            'xmlns:stream': "http://etherx.jabber.org/streams",
+                            'xmlns': "jabber:client"
+                        })
+                    .c('register',  {xmlns: "http://jabber.org/features/iq-register"}).up()
+                    .c('mechanisms', {xmlns: "urn:ietf:params:xml:ns:xmpp-sasl"});
+                _converse.connection._connect_cb(test_utils.createRequest(stanza));
+                stanza = $iq({
+                        'type': 'result',
+                        'id': 'reg1'
+                    }).c('query', {'xmlns': 'jabber:iq:register'})
+                        .c('instructions')
+                            .t('Please choose a username, password and provide your email address').up()
+                        .c('username').up()
+                        .c('password').up()
+                        .c('email');
+                _converse.connection._dataRecv(test_utils.createRequest(stanza));
+                expect(registerview.form_type).toBe('legacy');
+
+                $(registerview.el.querySelector('input[name=username]')).val('testusername');
+                $(registerview.el.querySelector('input[name=password]')).val('testpassword');
+                $(registerview.el.querySelector('input[name=email]')).val('test@email.local');
+
+                spyOn(_converse.connection, 'send');
+
+                registerview.el.querySelector('input[type=submit]').click();
+
+                expect(_converse.connection.send).toHaveBeenCalled();
+                var $stanza = $(_converse.connection.send.calls.argsFor(0)[0].tree());
+                expect($stanza.children('query').children().length).toBe(3);
+                expect($stanza.children('query').children()[0].tagName).toBe('username');
+                done();
             });
         }));
 
@@ -223,57 +224,56 @@
 
             test_utils.waitUntil(function () {
                     return _.get(_converse.chatboxviews.get('controlbox'), 'registerpanel');
-                }, 300)
-            .then(function () {
-
-            var cbview = _converse.chatboxviews.get('controlbox');
-            cbview.$('#controlbox-tabs').find('li').last().find('a').click(); // Click the Register tab
-            var registerview = _converse.chatboxviews.get('controlbox').registerpanel;
-            spyOn(registerview, 'onProviderChosen').and.callThrough();
-            spyOn(registerview, 'getRegistrationFields').and.callThrough();
-            spyOn(registerview, 'onRegistrationFields').and.callThrough();
-            spyOn(registerview, 'renderRegistrationForm').and.callThrough();
-            registerview.delegateEvents();  // We need to rebind all events otherwise our spy won't be called
-            spyOn(_converse.connection, 'connect').and.callThrough();
-
-            registerview.$('input[name=domain]').val('conversejs.org');
-            registerview.$('input[type=submit]').click();
-
-            var stanza = new Strophe.Builder("stream:features", {
-                        'xmlns:stream': "http://etherx.jabber.org/streams",
-                        'xmlns': "jabber:client"
-                    })
-                .c('register',  {xmlns: "http://jabber.org/features/iq-register"}).up()
-                .c('mechanisms', {xmlns: "urn:ietf:params:xml:ns:xmpp-sasl"});
-            _converse.connection._connect_cb(test_utils.createRequest(stanza));
-            stanza = $iq({
-                    'type': 'result',
-                    'id': 'reg1'
-                }).c('query', {'xmlns': 'jabber:iq:register'})
-                    .c('instructions')
-                        .t('Using xform data').up()
-                    .c('x', { 'xmlns': 'jabber:x:data', 'type': 'form' })
-                        .c('instructions').t('xform instructions').up()
-                        .c('field', {'type': 'text-single', 'var': 'username'}).c('required').up().up()
-                        .c('field', {'type': 'text-private', 'var': 'password'}).c('required').up().up()
-                        .c('field', {'type': 'text-single', 'var': 'email'}).c('required').up().up();
-            _converse.connection._dataRecv(test_utils.createRequest(stanza));
-            expect(registerview.form_type).toBe('xform');
-
-            registerview.$('input[name=username]').val('testusername');
-            registerview.$('input[name=password]').val('testpassword');
-            registerview.$('input[name=email]').val('test@email.local');
-
-            spyOn(_converse.connection, 'send');
-
-            registerview.$('input[type=submit]').click();
-
-            expect(_converse.connection.send).toHaveBeenCalled();
-            var $stanza = $(_converse.connection.send.calls.argsFor(0)[0].tree());
-            expect($stanza.children('query').children().length).toBe(1);
-            expect($stanza.children('query').children().children().length).toBe(3);
-            expect($stanza.children('query').children().children()[0].tagName).toBe('field');
-            done();
+            }, 300).then(function () {
+                test_utils.openControlBox();
+                var cbview = _converse.chatboxviews.get('controlbox');
+                cbview.el.querySelector('.toggle-register-login').click();
+                var registerview = _converse.chatboxviews.get('controlbox').registerpanel;
+                spyOn(registerview, 'onProviderChosen').and.callThrough();
+                spyOn(registerview, 'getRegistrationFields').and.callThrough();
+                spyOn(registerview, 'onRegistrationFields').and.callThrough();
+                spyOn(registerview, 'renderRegistrationForm').and.callThrough();
+                registerview.delegateEvents();  // We need to rebind all events otherwise our spy won't be called
+                spyOn(_converse.connection, 'connect').and.callThrough();
+
+                registerview.el.querySelector('input[name=domain]').value = 'conversejs.org';
+                registerview.el.querySelector('input[type=submit]').click();
+
+                var stanza = new Strophe.Builder("stream:features", {
+                            'xmlns:stream': "http://etherx.jabber.org/streams",
+                            'xmlns': "jabber:client"
+                        })
+                    .c('register',  {xmlns: "http://jabber.org/features/iq-register"}).up()
+                    .c('mechanisms', {xmlns: "urn:ietf:params:xml:ns:xmpp-sasl"});
+                _converse.connection._connect_cb(test_utils.createRequest(stanza));
+                stanza = $iq({
+                        'type': 'result',
+                        'id': 'reg1'
+                    }).c('query', {'xmlns': 'jabber:iq:register'})
+                        .c('instructions')
+                            .t('Using xform data').up()
+                        .c('x', { 'xmlns': 'jabber:x:data', 'type': 'form' })
+                            .c('instructions').t('xform instructions').up()
+                            .c('field', {'type': 'text-single', 'var': 'username'}).c('required').up().up()
+                            .c('field', {'type': 'text-private', 'var': 'password'}).c('required').up().up()
+                            .c('field', {'type': 'text-single', 'var': 'email'}).c('required').up().up();
+                _converse.connection._dataRecv(test_utils.createRequest(stanza));
+                expect(registerview.form_type).toBe('xform');
+
+                $(registerview.el.querySelector('input[name=username]')).val('testusername');
+                $(registerview.el.querySelector('input[name=password]')).val('testpassword');
+                $(registerview.el.querySelector('input[name=email]')).val('test@email.local');
+
+                spyOn(_converse.connection, 'send');
+
+                registerview.el.querySelector('input[type=submit]').click();
+
+                expect(_converse.connection.send).toHaveBeenCalled();
+                var $stanza = $(_converse.connection.send.calls.argsFor(0)[0].tree());
+                expect($stanza.children('query').children().length).toBe(1);
+                expect($stanza.children('query').children().children().length).toBe(3);
+                expect($stanza.children('query').children().children()[0].tagName).toBe('field');
+                done();
             });
         }));
     });

+ 72 - 72
spec/roster.js

@@ -13,14 +13,14 @@
         expect($group.find('ul.collapsed').length).toBe(0);
         expect($toggle.hasClass('icon-closed')).toBeFalsy();
         expect($toggle.hasClass('icon-opened')).toBeTruthy();
-        $toggle.click();
+        $toggle[0].click();
 
         return test_utils.waitUntil(function () {
             return $group.find('ul.collapsed').length === 1;
         }, 500).then(function () {
             expect($toggle.hasClass('icon-closed')).toBeTruthy();
             expect($toggle.hasClass('icon-opened')).toBeFalsy();
-            $toggle.click();
+            $toggle[0].click();
             return test_utils.waitUntil(function () {
                 return $group.find('li').length === $group.find('li:visible').length
             }, 500);
@@ -268,7 +268,7 @@
                     return _converse.rosterview.$('.roster-filter').hasClass("x");
                 }, 900).then(function () {
                     var $filter = _converse.rosterview.$('.roster-filter');
-                    $filter.addClass("onX").click();
+                    $filter.addClass("onX")[0].click();
                     return test_utils.waitUntil(function () {
                         return !_converse.rosterview.$('.roster-filter').hasClass("x");
                     }, 900)
@@ -333,10 +333,10 @@
                 // Check that the groups appear alphabetically and that
                 // requesting and pending contacts are last.
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('.roster-group:visible a.group-toggle').length;
+                    return $(_converse.rosterview.el).find('.roster-group:visible a.group-toggle').length;
                 }, 500).then(function () {
                     var group_titles = $.map(
-                        _converse.rosterview.$el.find('.roster-group:visible a.group-toggle'),
+                        $(_converse.rosterview.el).find('.roster-group:visible a.group-toggle'),
                         function (o) { return $(o).text().trim(); }
                     );
                     expect(group_titles).toEqual([
@@ -381,10 +381,10 @@
                 // Check that the groups appear alphabetically and that
                 // requesting and pending contacts are last.
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('.roster-group:visible a.group-toggle').length;
+                    return $(_converse.rosterview.el).find('.roster-group:visible a.group-toggle').length;
                 }, 500).then(function () {
                     var group_titles = $.map(
-                        _converse.rosterview.$el.find('.roster-group:visible a.group-toggle'),
+                        $(_converse.rosterview.el).find('.roster-group:visible a.group-toggle'),
                         function (o) { return $(o).text().trim(); }
                     );
                     expect(group_titles).toEqual(['firstgroup']);
@@ -392,11 +392,11 @@
                     var contact = _converse.roster.get('groupchanger@localhost');
                     contact.set({'groups': ['secondgroup']});
                     return test_utils.waitUntil(function () {
-                        return _converse.rosterview.$el.find('.roster-group[data-group="secondgroup"]:visible a.group-toggle').length;
+                        return $(_converse.rosterview.el).find('.roster-group[data-group="secondgroup"]:visible a.group-toggle').length;
                     }, 500);
                 }).then(function () {
                     var group_titles = $.map(
-                        _converse.rosterview.$el.find('.roster-group:visible a.group-toggle'),
+                        $(_converse.rosterview.el).find('.roster-group:visible a.group-toggle'),
                         function (o) { return $(o).text().trim(); }
                     );
                     expect(group_titles).toEqual(['secondgroup']);
@@ -425,7 +425,7 @@
                     });
                 }
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('li:visible').length === 30;
+                    return $(_converse.rosterview.el).find('li:visible').length === 30;
                 }, 600).then(function () {
                     // Check that usernames appear alphabetically per group
                     _.each(groups, function (name) {
@@ -465,13 +465,13 @@
                     }
                 });
                 var view = _converse.rosterview.get('colleagues');
-                var $toggle = view.$el.find('a.group-toggle');
+                var $toggle = $(view.el).find('a.group-toggle');
                 expect(view.model.get('state')).toBe('opened');
-                $toggle.click();
+                $toggle[0].click();
                 return test_utils.waitUntil(function () {
                     return view.model.get('state') === 'closed';
                 }, 500).then(function () {
-                    $toggle.click();
+                    $toggle[0].click();
                     return test_utils.waitUntil(function () {
                         return view.model.get('state') === 'opened';
                     }, 500)
@@ -497,7 +497,7 @@
 
                 _addContacts(_converse);
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('.roster-group:visible li').length;
+                    return $(_converse.rosterview.el).find('.roster-group:visible li').length;
                 }, 500).then(function () {
                     checkHeaderToggling.apply(
                         _converse,
@@ -534,12 +534,12 @@
                 spyOn(_converse.rosterview, 'update').and.callThrough();
                 _addContacts(_converse);
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('li:visible').length;
+                    return $(_converse.rosterview.el).find('li:visible').length;
                 }, 700).then(function () {
-                    expect(_converse.rosterview.$el.is(':visible')).toEqual(true);
+                    expect($(_converse.rosterview.el).is(':visible')).toEqual(true);
                     expect(_converse.rosterview.update).toHaveBeenCalled();
-                    expect(_converse.rosterview.$el.find('li:visible').length).toBe(3);
-                    expect(_converse.rosterview.$el.find('ul.roster-group-contacts:visible').length).toBe(1);
+                    expect($(_converse.rosterview.el).find('li:visible').length).toBe(3);
+                    expect($(_converse.rosterview.el).find('ul.roster-group-contacts:visible').length).toBe(1);
                     done();
                 });
             }));
@@ -553,13 +553,13 @@
                 spyOn(_converse.rosterview, 'update').and.callThrough();
                 _addContacts(_converse);
                 test_utils.waitUntil(function () {
-                        return _converse.rosterview.$el.find('li:visible').length;
+                        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);
+                    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();
                 });
             }));
@@ -581,12 +581,12 @@
                     if (typeof callback === "function") { return callback(); }
                 });
                 test_utils.waitUntil(function () {
-                        return _converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')").length;
+                        return $(_converse.rosterview.el).find(".pending-contact-name:contains('"+name+"')").length;
                 }, 700).then(function () {
-                    _converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')")
-                        .parent().siblings('.remove-xmpp-contact').click();
+                    $(_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
+                        return $(_converse.rosterview.el).find(".pending-contact-name:contains('"+name+"')").length === 0
                     }, 700)
                 }).then(function () {
                     expect(window.confirm).toHaveBeenCalled();
@@ -618,8 +618,8 @@
                         var $pending_contacts = _converse.rosterview.get('Pending contacts').$el;
                         return $pending_contacts.is(':visible') && $pending_contacts.find('li:visible').length;
                 }, 700).then(function () {
-                    _converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')")
-                        .parent().siblings('.remove-xmpp-contact').click();
+                    $(_converse.rosterview.el).find(".pending-contact-name:contains('"+name+"')")
+                        .parent().siblings('.remove-xmpp-contact')[0].click();
                     expect(window.confirm).toHaveBeenCalled();
                     expect(_converse.connection.sendIQ).toHaveBeenCalled();
                     expect(_converse.rosterview.get('Pending contacts').$el.is(':visible')).toEqual(false);
@@ -637,10 +637,10 @@
                 spyOn(window, 'confirm').and.returnValue(true);
                 for (var i=0; i<mock.pend_names.length; i++) {
                     name = mock.pend_names[i];
-                    _converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')")
-                        .parent().siblings('.remove-xmpp-contact').click();
+                    $(_converse.rosterview.el).find(".pending-contact-name:contains('"+name+"')")
+                        .parent().siblings('.remove-xmpp-contact')[0].click();
                 }
-                expect(_converse.rosterview.$el.find('#pending-xmpp-contacts').is(':visible')).toBeFalsy();
+                expect($(_converse.rosterview.el).find('#pending-xmpp-contacts').is(':visible')).toBeFalsy();
                 done();
             }));
 
@@ -690,11 +690,11 @@
 
                 _addContacts(_converse);
                 test_utils.waitUntil(function () {
-                        return _converse.rosterview.$el.find('li:visible').length;
+                        return $(_converse.rosterview.el).find('li:visible').length;
                 }, 500).then(function () {
                     checkHeaderToggling.apply(
                         _converse,
-                        [_converse.rosterview.$el.find('.roster-group')]
+                        [$(_converse.rosterview.el).find('.roster-group')]
                     ).then(done);
                 });
             }));
@@ -707,10 +707,10 @@
                 _converse.roster_groups = false;
                 _addContacts(_converse);
                 test_utils.waitUntil(function () {
-                        return _converse.rosterview.$el.find('li:visible').length;
+                        return $(_converse.rosterview.el).find('li:visible').length;
                     }, 500)
                 .then(function () {
-                    _converse.rosterview.$el.find('.roster-group a.group-toggle').click();
+                    _converse.rosterview.el.querySelector('.roster-group a.group-toggle').click();
                     var name = "Max Mustermann";
                     var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
                     _converse.roster.create({
@@ -721,7 +721,7 @@
                         subscription: 'both'
                     });
                     var view = _converse.rosterview.get('My contacts').get(jid);
-                    expect(view.$el.is(':visible')).toBe(false);
+                    expect($(view.el).is(':visible')).toBe(false);
                     done();
                 });
             }));
@@ -743,7 +743,7 @@
                     expect(_converse.rosterview.update).toHaveBeenCalled();
                 }
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('li').length;
+                    return $(_converse.rosterview.el).find('li').length;
                 }, 600).then(function () {
                     // Check that they are sorted alphabetically
                     var t = _.reduce(_converse.rosterview.$('.roster-group')
@@ -763,7 +763,7 @@
 
                 _addContacts(_converse);
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('li').length;
+                    return $(_converse.rosterview.el).find('li').length;
                 }, 500).then(function () {
                     var name = mock.cur_names[0];
                     var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
@@ -773,13 +773,13 @@
                     spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback) {
                         if (typeof callback === "function") { return callback(); }
                     });
-                    _converse.rosterview.$el.find(".open-chat:contains('"+name+"')")
-                        .parent().find('.remove-xmpp-contact').click();
+                    $(_converse.rosterview.el).find(".open-chat:contains('"+name+"')")
+                        .parent().find('.remove-xmpp-contact')[0].click();
 
                     expect(window.confirm).toHaveBeenCalled();
                     expect(_converse.connection.sendIQ).toHaveBeenCalled();
                     expect(contact.removeFromRoster).toHaveBeenCalled();
-                    expect(_converse.rosterview.$el.find(".open-chat:contains('"+name+"')").length).toEqual(0);
+                    expect($(_converse.rosterview.el).find(".open-chat:contains('"+name+"')").length).toEqual(0);
                     done();
                 });
             }));
@@ -799,7 +799,7 @@
                     fullname: name
                 });
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('.roster-group:visible li').length;
+                    return $(_converse.rosterview.el).find('.roster-group:visible li').length;
                 }, 700).then(function () {
                     spyOn(window, 'confirm').and.returnValue(true);
                     spyOn(contact, 'removeFromRoster');
@@ -807,13 +807,13 @@
                         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').click();
+                    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(window.confirm).toHaveBeenCalled();
                     expect(_converse.connection.sendIQ).toHaveBeenCalled();
                     expect(contact.removeFromRoster).toHaveBeenCalled();
-                    expect(_converse.rosterview.$el.find('.roster-group').length).toEqual(0);
+                    expect($(_converse.rosterview.el).find('.roster-group').length).toEqual(0);
                     done();
                 });
             }));
@@ -825,12 +825,12 @@
 
                 _addContacts(_converse);
                 test_utils.waitUntil(function () {
-                        return _converse.rosterview.$el.find('.roster-group li').length;
+                        return $(_converse.rosterview.el).find('.roster-group li').length;
                 }, 700).then(function () {
                     var jid, t;
                     spyOn(_converse, 'emit');
                     spyOn(_converse.rosterview, 'update').and.callThrough();
-                    var $roster = _converse.rosterview.$el;
+                    var $roster = $(_converse.rosterview.el);
                     for (var i=0; i<mock.cur_names.length; i++) {
                         jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
                         _converse.roster.get(jid).set('chat_status', 'online');
@@ -852,12 +852,12 @@
 
                 _addContacts(_converse);
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('.roster-group li').length;
+                    return $(_converse.rosterview.el).find('.roster-group li').length;
                 }, 700).then(function () {
                     var jid, t;
                     spyOn(_converse, 'emit');
                     spyOn(_converse.rosterview, 'update').and.callThrough();
-                    var $roster = _converse.rosterview.$el;
+                    var $roster = $(_converse.rosterview.el);
                     for (var i=0; i<mock.cur_names.length; i++) {
                         jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
                         _converse.roster.get(jid).set('chat_status', 'dnd');
@@ -880,12 +880,12 @@
 
                 _addContacts(_converse);
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('.roster-group li').length;
+                    return $(_converse.rosterview.el).find('.roster-group li').length;
                 }, 700).then(function () {
                     var jid, t;
                     spyOn(_converse, 'emit');
                     spyOn(_converse.rosterview, 'update').and.callThrough();
-                    var $roster = _converse.rosterview.$el;
+                    var $roster = $(_converse.rosterview.el);
                     for (var i=0; i<mock.cur_names.length; i++) {
                         jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
                         _converse.roster.get(jid).set('chat_status', 'away');
@@ -908,12 +908,12 @@
 
                 _addContacts(_converse);
                 test_utils.waitUntil(function () {
-                        return _converse.rosterview.$el.find('.roster-group li').length;
+                        return $(_converse.rosterview.el).find('.roster-group li').length;
                 }, 700).then(function () {
                     var jid, t;
                     spyOn(_converse, 'emit');
                     spyOn(_converse.rosterview, 'update').and.callThrough();
-                    var $roster = _converse.rosterview.$el;
+                    var $roster = $(_converse.rosterview.el);
                     for (var i=0; i<mock.cur_names.length; i++) {
                         jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
                         _converse.roster.get(jid).set('chat_status', 'xa');
@@ -936,13 +936,13 @@
 
                 _addContacts(_converse);
                 test_utils.waitUntil(function () {
-                        return _converse.rosterview.$el.find('.roster-group li').length;
+                        return $(_converse.rosterview.el).find('.roster-group li').length;
                     }, 500)
                 .then(function () {
                     var jid, t;
                     spyOn(_converse, 'emit');
                     spyOn(_converse.rosterview, 'update').and.callThrough();
-                    var $roster = _converse.rosterview.$el;
+                    var $roster = $(_converse.rosterview.el);
                     for (var i=0; i<mock.cur_names.length; i++) {
                         jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
                         _converse.roster.get(jid).set('chat_status', 'unavailable');
@@ -965,7 +965,7 @@
 
                 _addContacts(_converse);
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('.roster-group li').length;
+                    return $(_converse.rosterview.el).find('.roster-group li').length;
                 }, 700).then(function () {
                     var i, jid;
                     for (i=0; i<3; i++) {
@@ -989,15 +989,15 @@
                         _converse.roster.get(jid).set('chat_status', 'unavailable');
                     }
                     return test_utils.waitUntil(function () {
-                        return _converse.rosterview.$el.find('li.online').length
+                        return $(_converse.rosterview.el).find('li.online').length
                     })
                 }).then(function () {
                     return test_utils.waitUntil(function () {
-                        return _converse.rosterview.$el.find('li:first').text().trim() === 'Candice van der Knijff'
+                        return $(_converse.rosterview.el).find('li:first').text().trim() === 'Candice van der Knijff'
                     }, 900);
                 }).then(function () {
                     var i;
-                    var contacts = _converse.rosterview.$el.find('.current-xmpp-contact');
+                    var contacts = $(_converse.rosterview.el).find('.current-xmpp-contact');
                     for (i=0; i<3; i++) {
                         expect($(contacts[i]).hasClass('online')).toBeTruthy();
                         expect($(contacts[i]).hasClass('both')).toBeTruthy();
@@ -1113,12 +1113,12 @@
                     fullname: name
                 });
                 test_utils.waitUntil(function () {
-                        return _converse.rosterview.$el.find('.roster-group:visible li').length;
+                        return $(_converse.rosterview.el).find('.roster-group:visible li').length;
                 }, 700).then(function () {
                     expect(_converse.rosterview.get('Contact requests').$el.is(':visible')).toEqual(true);
-                    _converse.rosterview.$el.find(".req-contact-name:contains('"+name+"')")
+                    $(_converse.rosterview.el).find(".req-contact-name:contains('"+name+"')")
                         .parent().siblings('.request-actions')
-                        .find('.decline-xmpp-request').click();
+                        .find('.decline-xmpp-request')[0].click();
                     expect(window.confirm).toHaveBeenCalled();
                     expect(_converse.rosterview.get('Contact requests').$el.is(':visible')).toEqual(false);
                     done();
@@ -1132,7 +1132,7 @@
 
                 test_utils.createContacts(_converse, 'requesting').openControlBox();
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('.roster-group:visible li').length;
+                    return $(_converse.rosterview.el).find('.roster-group:visible li').length;
                 }, 700).then(function () {
                     checkHeaderToggling.apply(
                         _converse,
@@ -1148,7 +1148,7 @@
 
                 test_utils.createContacts(_converse, 'requesting').openControlBox();
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('.roster-group li').length;
+                    return $(_converse.rosterview.el).find('.roster-group li').length;
                 }, 700).then(function () {
                     // TODO: Testing can be more thorough here, the user is
                     // actually not accepted/authorized because of
@@ -1160,9 +1160,9 @@
                         callback();
                     });
                     spyOn(contact, 'authorize').and.callFake(function () { return contact; });
-                    _converse.rosterview.$el.find(".req-contact-name:contains('"+name+"')")
+                    $(_converse.rosterview.el).find(".req-contact-name:contains('"+name+"')")
                         .parent().siblings('.request-actions')
-                        .find('.accept-xmpp-request').click();
+                        .find('.accept-xmpp-request')[0].click();
                     expect(_converse.roster.sendContactAddIQ).toHaveBeenCalled();
                     expect(contact.authorize).toHaveBeenCalled();
                     done();
@@ -1176,7 +1176,7 @@
 
                 test_utils.createContacts(_converse, 'requesting').openControlBox();
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('.roster-group li').length;
+                    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];
@@ -1184,9 +1184,9 @@
                     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+"')")
+                    $(_converse.rosterview.el).find(".req-contact-name:contains('"+name+"')")
                         .parent().siblings('.request-actions')
-                        .find('.decline-xmpp-request').click();
+                        .find('.decline-xmpp-request')[0].click();
                     expect(window.confirm).toHaveBeenCalled();
                     expect(contact.unauthorize).toHaveBeenCalled();
                     // There should now be one less contact
@@ -1279,13 +1279,13 @@
                 test_utils.createContacts(_converse, 'all').openControlBox();
                 test_utils.openContactsPanel(_converse);
                 test_utils.waitUntil(function () {
-                    return _converse.rosterview.$el.find('.roster-group li').length;
+                    return $(_converse.rosterview.el).find('.roster-group li').length;
                 }, 700).then(function () {
                     var jid, name, i;
                     for (i=0; i<mock.cur_names.length; i++) {
                         name = mock.cur_names[i];
                         jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
-                        var $dd = _converse.rosterview.$el.find("li:contains('"+name+"')").children().first();
+                        var $dd = $(_converse.rosterview.el).find("li:contains('"+name+"')").children().first();
                         var dd_text = $dd.text();
                         var dd_title = $dd.attr('title');
                         expect(_.trim(dd_text)).toBe(name);

+ 2 - 1
src/config.js

@@ -20,9 +20,10 @@ require.config({
         "babel":                    "node_modules/requirejs-babel/babel-5.8.34.min",
         "backbone":                 "node_modules/backbone/backbone",
         "backbone.browserStorage":  "node_modules/backbone.browserStorage/backbone.browserStorage",
+        "backbone.nativeview":      "node_modules/backbone.nativeview/backbone.nativeview",
         "backbone.noconflict":      "src/backbone.noconflict",
-        "backbone.overview":        "node_modules/backbone.overview/dist/backbone.overview",
         "backbone.orderedlistview": "node_modules/backbone.overview/dist/backbone.orderedlistview",
+        "backbone.overview":        "node_modules/backbone.overview/dist/backbone.overview",
         "backbone.vdomview":        "node_modules/backbone.vdomview/dist/backbone.vdomview",
         "emojione":                 "node_modules/emojione/lib/js/emojione",
         "es6-promise":              "node_modules/es6-promise/dist/es6-promise.auto",

+ 2 - 2
src/converse-bookmarks.js

@@ -385,7 +385,7 @@
                 }
             });
 
-            _converse.BookmarksView = Backbone.View.extend({
+            _converse.BookmarksView = Backbone.NativeView.extend({
                 tagName: 'div',
                 className: 'bookmarks-list rooms-list-container hidden',
                 events: {
@@ -491,7 +491,7 @@
 
                 toggleBookmarksList (ev) {
                     if (ev && ev.preventDefault) { ev.preventDefault(); }
-                    if (u.hasClass(ev.target, 'icon-opened')) {
+                    if (u.hasClass('icon-opened', ev.target)) {
                         u.slideIn(this.el.querySelector('.bookmarks'));
                         this.list_model.save({'toggle-state': _converse.CLOSED});
                         ev.target.classList.remove("icon-opened");

+ 12 - 9
src/converse-chatview.js

@@ -142,7 +142,7 @@
                 }
             });
 
-            _converse.EmojiPickerView = Backbone.View.extend({
+            _converse.EmojiPickerView = Backbone.NativeView.extend({
                 className: 'emoji-picker-container toolbar-menu collapsed',
                 events: {
                     'click .emoji-category-picker li.emoji-category': 'chooseCategory',
@@ -231,7 +231,7 @@
                 }
             });
 
-            _converse.ChatBoxHeading = Backbone.View.extend({
+            _converse.ChatBoxHeading = Backbone.NativeView.extend({
 
                 initialize () {
                     this.model.on('change:image', this.render, this);
@@ -259,7 +259,7 @@
                 }
             });
 
-            _converse.ChatBoxView = Backbone.View.extend({
+            _converse.ChatBoxView = Backbone.NativeView.extend({
                 length: 200,
                 className: 'chatbox hidden',
                 is_chatroom: false,  // Leaky abstraction from MUC
@@ -425,8 +425,8 @@
                 getPreviousMessageElement (el) {
                     let prev_msg_el = el.previousSibling;
                     while (!_.isNull(prev_msg_el) &&
-                            !u.hasClass(prev_msg_el, 'message') &&
-                            !u.hasClass(prev_msg_el, 'chat-info')) {
+                            !u.hasClass('message', prev_msg_el) &&
+                            !u.hasClass('chat-info', prev_msg_el)) {
                         prev_msg_el = prev_msg_el.previousSibling
                     }
                     return prev_msg_el;
@@ -435,8 +435,8 @@
                 getLastMessageElement () {
                     let last_msg_el = this.content.lastElementChild;
                     while (!_.isNull(last_msg_el) &&
-                            !u.hasClass(last_msg_el, 'message') &&
-                            !u.hasClass(last_msg_el, 'chat-info')) {
+                            !u.hasClass('message', last_msg_el) &&
+                            !u.hasClass('chat-info', last_msg_el)) {
                         last_msg_el = last_msg_el.previousSibling
                     }
                     return last_msg_el;
@@ -445,8 +445,8 @@
                 getFirstMessageElement () {
                     let first_msg_el = this.content.firstElementChild;
                     while (!_.isNull(first_msg_el) &&
-                            !u.hasClass(first_msg_el, 'message') &&
-                            !u.hasClass(first_msg_el, 'chat-info')) {
+                            !u.hasClass('message', first_msg_el) &&
+                            !u.hasClass('chat-info', first_msg_el)) {
                         first_msg_el = first_msg_el.nextSibling
                     }
                     return first_msg_el;
@@ -860,6 +860,9 @@
                 },
 
                 toggleEmojiMenu (ev) {
+                    if (u.hasClass('insert-emoji', ev.target)) {
+                        return;
+                    }
                     if (!_.isUndefined(ev)) {
                         ev.stopPropagation();
                         if (ev.target.classList.contains('emoji-category-picker') ||

+ 2 - 2
src/converse-controlbox.js

@@ -539,7 +539,7 @@
             });
 
 
-            _converse.ContactsPanel = Backbone.View.extend({
+            _converse.ContactsPanel = Backbone.NativeView.extend({
                 tagName: 'div',
                 className: 'controlbox-pane',
                 id: 'users',
@@ -699,7 +699,7 @@
             });
 
 
-            _converse.ControlBoxToggle = Backbone.View.extend({
+            _converse.ControlBoxToggle = Backbone.NativeView.extend({
                 tagName: 'a',
                 className: 'toggle-controlbox hidden',
                 id: 'toggle-controlbox',

+ 1 - 0
src/converse-core.js

@@ -16,6 +16,7 @@
             "strophe",
             "pluggable",
             "backbone.noconflict",
+            "backbone.nativeview",
             "backbone.browserStorage"
     ], factory);
 }(this, function (sizzle, Promise, _, polyfill, i18n, utils, moment, Strophe, pluggable, Backbone) {

+ 1 - 1
src/converse-headline.js

@@ -96,7 +96,7 @@
                 },
 
                 render () {
-                    this.$el.attr('id', this.model.get('box_id'))
+                    this.el.setAttribute('id', this.model.get('box_id'))
                     this.el.innerHTML = tpl_chatbox(
                         _.extend(this.model.toJSON(), {
                                 info_close: '',

+ 2 - 2
src/converse-minimize.js

@@ -330,7 +330,7 @@
 
             _converse.api.promises.add('minimizedChatsInitialized');
 
-            _converse.MinimizedChatBoxView = Backbone.View.extend({
+            _converse.MinimizedChatBoxView = Backbone.NativeView.extend({
                 tagName: 'div',
                 className: 'chat-head',
                 events: {
@@ -497,7 +497,7 @@
             });
 
 
-            _converse.MinimizedChatsToggleView = Backbone.View.extend({
+            _converse.MinimizedChatsToggleView = Backbone.NativeView.extend({
                 el: '#toggle-minimized-chats',
 
                 initialize () {

+ 4 - 4
src/converse-muc.js

@@ -415,7 +415,7 @@
             });
 
             _converse.ChatRoomView = _converse.ChatBoxView.extend({
-                /* Backbone View which renders a chat room, based upon the view
+                /* Backbone.NativeView which renders a chat room, based upon the view
                  * for normal one-on-one chat boxes.
                  */
                 length: 300,
@@ -506,7 +506,7 @@
                 },
 
                 createOccupantsView () {
-                    /* Create the ChatRoomOccupantsView Backbone.View
+                    /* Create the ChatRoomOccupantsView Backbone.NativeView
                      */
                     const model = new _converse.ChatRoomOccupants();
                     model.chatroomview = this;
@@ -2549,8 +2549,8 @@
                 },
             });
 
-            _converse.RoomsPanel = Backbone.View.extend({
-                /* Backbone View which renders the "Rooms" tab and accompanying
+            _converse.RoomsPanel = Backbone.NativeView.extend({
+                /* Backbone.NativeView which renders the "Rooms" tab and accompanying
                  * panel in the control box.
                  *
                  * In this panel, chat rooms can be listed, joined and new rooms

+ 2 - 2
src/converse-profile.js

@@ -35,7 +35,7 @@
             const { _converse } = this,
                 { __ } = _converse;
 
-            _converse.XMPPStatusView = Backbone.View.extend({
+            _converse.XMPPStatusView = Backbone.NativeView.extend({
                 el: "form#set-xmpp-status",
                 events: {
                     "click a.choose-xmpp-status": "toggleOptions",
@@ -108,7 +108,7 @@
 
                 setStatus (ev) {
                     ev.preventDefault();
-                    const value = ev.currentTarget.getAttribute('data-value');
+                    const value = ev.target.getAttribute('data-value');
                     if (value === 'logout') {
                         _converse.logOut();
                     } else {

+ 1 - 1
src/converse-register.js

@@ -167,7 +167,7 @@
                 }
             });
 
-            _converse.RegisterPanel = Backbone.View.extend({
+            _converse.RegisterPanel = Backbone.NativeView.extend({
                 tagName: 'div',
                 id: "converse-register-panel",
                 className: 'controlbox-pane fade-in',

+ 1 - 1
src/converse-roomslist.js

@@ -48,7 +48,7 @@
                 }
             });
 
-            _converse.RoomsListView = Backbone.View.extend({
+            _converse.RoomsListView = Backbone.NativeView.extend({
                 tagName: 'div',
                 className: 'open-rooms-list rooms-list-container',
                 events: {

+ 1 - 1
src/converse-rosterview.js

@@ -272,7 +272,7 @@
                 }
             });
 
-            _converse.RosterContactView = Backbone.View.extend({
+            _converse.RosterContactView = Backbone.NativeView.extend({
                 tagName: 'li',
                 className: 'hidden',
 

+ 3 - 3
src/utils.js

@@ -161,7 +161,7 @@
         return obj;
     };
 
-    u.slideInAllElements = function (elements, duration=600) {
+    u.slideInAllElements = function (elements, duration=300) {
         return Promise.all(
             _.map(
                 elements,
@@ -178,7 +178,7 @@
         }
     };
 
-    u.hasClass = function (el, className) {
+    u.hasClass = function (className, el) {
         return _.includes(el.classList, className);
     };
 
@@ -208,7 +208,7 @@
                 resolve();
                 return;
             }
-            if (!u.hasClass(el, 'collapsed') && !u.hasClass(el, 'hidden')) {
+            if (!u.hasClass('collapsed', el) && !u.hasClass('hidden', el)) {
                 resolve();
                 return;
             }

+ 23 - 19
tests/utils.js

@@ -6,6 +6,7 @@
     var $pres = converse_api.env.$pres;
     var $iq = converse_api.env.$iq;
     var Strophe = converse_api.env.Strophe;
+    var u = converse_api.env.utils;
     var utils = {};
 
     if (typeof window.Promise === 'undefined') {
@@ -54,21 +55,20 @@
     };
 
     utils.openControlBox = function () {
-        var $toggle = $(".toggle-controlbox");
-        if (!$("#controlbox").is(':visible')) {
-            if (!$toggle.is(':visible')) {
-                $toggle[0].classList.remove('hidden');
-                $toggle.click();
-            } else {
-                $toggle.click();
+        var toggle = document.querySelector(".toggle-controlbox");
+        if (!u.isVisible(document.querySelector("#controlbox"))) {
+            if (!u.isVisible(toggle)) {
+                u.removeClass('hidden', toggle);
             }
+            toggle.click();
         }
         return this;
     };
 
     utils.closeControlBox = function () {
-        if ($("#controlbox").is(':visible')) {
-            $("#controlbox").find(".close-chatbox-button").click();
+        var controlbox = document.querySelector("#controlbox");
+        if (u.isVisible(controlbox)) {
+            controlbox.querySelector(".close-chatbox-button").click();
         }
         return this;
     };
@@ -76,15 +76,15 @@
     utils.openContactsPanel = function (converse) {
         this.openControlBox(converse);
         var cbview = converse.chatboxviews.get('controlbox');
-        var $tabs = cbview.$el.find('#controlbox-tabs');
-        $tabs.find('li').first().find('a').click();
+        var $tabs = $(cbview.el).find('#controlbox-tabs');
+        $tabs.find('li').first().find('a')[0].click();
     };
 
     utils.openRoomsPanel = function (converse) {
         utils.openControlBox();
         var cbview = converse.chatboxviews.get('controlbox');
-        var $tabs = cbview.$el.find('#controlbox-tabs');
-        $tabs.find('li').last().find('a').click();
+        var $tabs = $(cbview.el).find('#controlbox-tabs');
+        $tabs.find('li').last().find('a')[0].click();
     };
 
     utils.openChatBoxes = function (converse, amount) {
@@ -105,9 +105,9 @@
         this.openControlBox(_converse);
         this.openRoomsPanel(_converse);
         var roomspanel = _converse.chatboxviews.get('controlbox').roomspanel;
-        roomspanel.$el.find('input.new-chatroom-name').val(room);
-        roomspanel.$el.find('input.new-chatroom-server').val(server);
-        roomspanel.$el.find('form').submit();
+        roomspanel.el.querySelector('input.new-chatroom-name').value = room;
+        roomspanel.el.querySelector('input.new-chatroom-server').value = server;
+        roomspanel.el.querySelector('form input[type="submit"]').click();
         this.closeControlBox(_converse);
     };
 
@@ -170,7 +170,7 @@
 
     utils.clearChatBoxMessages = function (converse, jid) {
         var view = converse.chatboxviews.get(jid);
-        view.$el.find('.chat-content').empty();
+        $(view.el).find('.chat-content').empty();
         view.model.messages.reset();
         view.model.messages.browserStorage._clear();
     };
@@ -254,8 +254,12 @@
     }
 
     utils.sendMessage = function (chatboxview, message) {
-        chatboxview.$el.find('.chat-textarea').val(message);
-        chatboxview.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13}));
+        chatboxview.el.querySelector('.chat-textarea').value = message;
+        chatboxview.keyPressed({
+            target: chatboxview.el.querySelector('textarea.chat-textarea'),
+            preventDefault: _.noop,
+            keyCode: 13
+        });
     };
     return utils;
 }));