Explorar el Código

Fix broken tests and update changelog

JC Brand hace 8 años
padre
commit
397927b189
Se han modificado 7 ficheros con 789 adiciones y 763 borrados
  1. 3 1
      CHANGES.md
  2. 463 431
      spec/chatroom.js
  3. 18 17
      spec/minchats.js
  4. 68 66
      spec/notification.js
  5. 51 50
      spec/roomslist.js
  6. 138 156
      src/converse-muc.js
  7. 48 42
      tests/utils.js

+ 3 - 1
CHANGES.md

@@ -2,7 +2,9 @@
 
 ## 3.2.0 (Unreleased)
 
-- #866 Add babel in order to support ES2015 syntax
+- All promises are now native (or polyfilled) ES2015 Promises
+  instead of jQuery's Deferred. [jcbrand]
+- #866 Add babel in order to support ES2015 syntax [jcbrand]
 
 ## 3.1.0 (2017-07-05)
 

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 463 - 431
spec/chatroom.js


+ 18 - 17
spec/minchats.js

@@ -144,24 +144,25 @@
 
             var room_jid = 'kitchen@conference.shakespeare.lit';
             test_utils.openAndEnterChatRoom(
-                _converse, 'kitchen', 'conference.shakespeare.lit', 'fires');
-            var view = _converse.chatboxviews.get(room_jid);
-            view.model.set({'minimized': true});
+                _converse, 'kitchen', 'conference.shakespeare.lit', 'fires').then(function () {
+                var view = _converse.chatboxviews.get(room_jid);
+                view.model.set({'minimized': true});
+
+                var contact_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost';
+                var message = 'fires: Your attention is required';
+                var nick = mock.chatroom_names[0],
+                    msg = $msg({
+                        from: room_jid+'/'+nick,
+                        id: (new Date()).getTime(),
+                        to: 'dummy@localhost',
+                        type: 'groupchat'
+                    }).c('body').t(message).tree();
+                view.handleMUCMessage(msg);
 
-            var contact_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost';
-            var message = 'fires: Your attention is required';
-            var nick = mock.chatroom_names[0],
-                msg = $msg({
-                    from: room_jid+'/'+nick,
-                    id: (new Date()).getTime(),
-                    to: 'dummy@localhost',
-                    type: 'groupchat'
-                }).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');
-            done();
+                expect(_converse.minimized_chats.toggleview.$('.unread-message-count').is(':visible')).toBeTruthy();
+                expect(_converse.minimized_chats.toggleview.$('.unread-message-count').text()).toBe('1');
+                done();
+            });
         }));
     });
 }));

+ 68 - 66
spec/notification.js

@@ -43,36 +43,37 @@
                             function (done, _converse) {
 
                         test_utils.createContacts(_converse, 'current');
-                        test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy');
-                        var view = _converse.chatboxviews.get('lounge@localhost');
-                        if (!view.$el.find('.chat-area').length) { view.renderChatArea(); }
-                        var no_notification = false;
-                        if (typeof window.Notification === 'undefined') {
-                            no_notification = true;
-                            window.Notification = function () {
-                                return {
-                                    'close': function () {}
+                        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(); }
+                            var no_notification = false;
+                            if (typeof window.Notification === 'undefined') {
+                                no_notification = true;
+                                window.Notification = function () {
+                                    return {
+                                        'close': function () {}
+                                    };
                                 };
-                            };
-                        }
-                        spyOn(_converse, 'showMessageNotification').and.callThrough();
-                        spyOn(_converse, 'areDesktopNotificationsEnabled').and.returnValue(true);
-                        
-                        var message = 'dummy: This message will show a desktop notification';
-                        var nick = mock.chatroom_names[0],
-                            msg = $msg({
-                                from: 'lounge@localhost/'+nick,
-                                id: (new Date()).getTime(),
-                                to: 'dummy@localhost',
-                                type: 'groupchat'
-                            }).c('body').t(message).tree();
-                        _converse.chatboxes.onMessage(msg); // This will emit 'message'
-                        expect(_converse.areDesktopNotificationsEnabled).toHaveBeenCalled();
-                        expect(_converse.showMessageNotification).toHaveBeenCalled();
-                        if (no_notification) {
-                            delete window.Notification;
-                        }
-                        done();
+                            }
+                            spyOn(_converse, 'showMessageNotification').and.callThrough();
+                            spyOn(_converse, 'areDesktopNotificationsEnabled').and.returnValue(true);
+                            
+                            var message = 'dummy: This message will show a desktop notification';
+                            var nick = mock.chatroom_names[0],
+                                msg = $msg({
+                                    from: 'lounge@localhost/'+nick,
+                                    id: (new Date()).getTime(),
+                                    to: 'dummy@localhost',
+                                    type: 'groupchat'
+                                }).c('body').t(message).tree();
+                            _converse.chatboxes.onMessage(msg); // This will emit 'message'
+                            expect(_converse.areDesktopNotificationsEnabled).toHaveBeenCalled();
+                            expect(_converse.showMessageNotification).toHaveBeenCalled();
+                            if (no_notification) {
+                                delete window.Notification;
+                            }
+                            done();
+                        });
                     }));
 
                     it("is shown for headline messages",
@@ -158,43 +159,44 @@
                         function (done, _converse) {
 
                     test_utils.createContacts(_converse, 'current');
-                    test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy');
-                    _converse.play_sounds = true;
-                    spyOn(_converse, 'playSoundNotification');
-                    var view = _converse.chatboxviews.get('lounge@localhost');
-                    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',
-                        id: '1',
-                        to: 'dummy@localhost',
-                        type: 'groupchat'
-                    }).c('body').t(text);
-                    view.onChatRoomMessage(message.nodeTree);
-                    expect(_converse.playSoundNotification).toHaveBeenCalled();
-
-                    text = "This message won't play a sound";
-                    message = $msg({
-                        from: 'lounge@localhost/otheruser',
-                        id: '2',
-                        to: 'dummy@localhost',
-                        type: 'groupchat'
-                    }).c('body').t(text);
-                    view.onChatRoomMessage(message.nodeTree);
-                    expect(_converse.playSoundNotification, 1);
-                    _converse.play_sounds = false;
-
-                    text = "This message won't play a sound because it is sent by dummy";
-                    message = $msg({
-                        from: 'lounge@localhost/dummy',
-                        id: '3',
-                        to: 'dummy@localhost',
-                        type: 'groupchat'
-                    }).c('body').t(text);
-                    view.onChatRoomMessage(message.nodeTree);
-                    expect(_converse.playSoundNotification, 1);
-                    _converse.play_sounds = false;
-                    done();
+                    test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () {
+                        _converse.play_sounds = true;
+                        spyOn(_converse, 'playSoundNotification');
+                        var view = _converse.chatboxviews.get('lounge@localhost');
+                        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',
+                            id: '1',
+                            to: 'dummy@localhost',
+                            type: 'groupchat'
+                        }).c('body').t(text);
+                        view.onChatRoomMessage(message.nodeTree);
+                        expect(_converse.playSoundNotification).toHaveBeenCalled();
+
+                        text = "This message won't play a sound";
+                        message = $msg({
+                            from: 'lounge@localhost/otheruser',
+                            id: '2',
+                            to: 'dummy@localhost',
+                            type: 'groupchat'
+                        }).c('body').t(text);
+                        view.onChatRoomMessage(message.nodeTree);
+                        expect(_converse.playSoundNotification, 1);
+                        _converse.play_sounds = false;
+
+                        text = "This message won't play a sound because it is sent by dummy";
+                        message = $msg({
+                            from: 'lounge@localhost/dummy',
+                            id: '3',
+                            to: 'dummy@localhost',
+                            type: 'groupchat'
+                        }).c('body').t(text);
+                        view.onChatRoomMessage(message.nodeTree);
+                        expect(_converse.playSoundNotification, 1);
+                        _converse.play_sounds = false;
+                        done();
+                    });
                 }));
             });
         });

+ 51 - 50
spec/roomslist.js

@@ -94,56 +94,57 @@
             .then(function () {
                 var room_jid = 'kitchen@conference.shakespeare.lit';
                 test_utils.openAndEnterChatRoom(
-                    _converse, 'kitchen', 'conference.shakespeare.lit', 'romeo');
-                var view = _converse.chatboxviews.get(room_jid);
-                view.model.set({'minimized': true});
-
-                var contact_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost';
-                var nick = mock.chatroom_names[0];
-                view.handleMUCMessage(
-                    $msg({
-                        from: room_jid+'/'+nick,
-                        id: (new Date()).getTime(),
-                        to: 'dummy@localhost',
-                        type: 'groupchat'
-                    }).c('body').t('foo').tree());
-
-                // If the user isn't mentioned, the counter doesn't get incremented, but the text of the room is bold
-                var room_el = _converse.rooms_list_view.el.querySelector(
-                    ".available-chatroom"
-                );
-                expect(_.includes(room_el.classList, 'unread-msgs'));
-
-                // If the user is mentioned, the counter also gets updated
-                view.handleMUCMessage(
-                    $msg({
-                        from: room_jid+'/'+nick,
-                        id: (new Date()).getTime(),
-                        to: 'dummy@localhost',
-                        type: 'groupchat'
-                    }).c('body').t('romeo: Your attention is required').tree()
-                );
-                var indicator_el = _converse.rooms_list_view.el.querySelector(".msgs-indicator");
-                expect(indicator_el.textContent).toBe('1');
-
-                view.handleMUCMessage(
-                    $msg({
-                        from: room_jid+'/'+nick,
-                        id: (new Date()).getTime(),
-                        to: 'dummy@localhost',
-                        type: 'groupchat'
-                    }).c('body').t('romeo: and another thing...').tree()
-                );
-                indicator_el = _converse.rooms_list_view.el.querySelector(".msgs-indicator");
-                expect(indicator_el.textContent).toBe('2');
-
-                // When the chat gets maximized again, the unread indicators are removed
-                view.model.set({'minimized': false});
-                indicator_el = _converse.rooms_list_view.el.querySelector(".msgs-indicator");
-                expect(_.isNull(indicator_el));
-                room_el = _converse.rooms_list_view.el.querySelector(".available-chatroom");
-                expect(_.includes(room_el.classList, 'unread-msgs')).toBeFalsy();
-                done();
+                    _converse, 'kitchen', 'conference.shakespeare.lit', 'romeo').then(function () {
+
+                    var view = _converse.chatboxviews.get(room_jid);
+                    view.model.set({'minimized': true});
+                    var contact_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost';
+                    var nick = mock.chatroom_names[0];
+                    view.handleMUCMessage(
+                        $msg({
+                            from: room_jid+'/'+nick,
+                            id: (new Date()).getTime(),
+                            to: 'dummy@localhost',
+                            type: 'groupchat'
+                        }).c('body').t('foo').tree());
+
+                    // If the user isn't mentioned, the counter doesn't get incremented, but the text of the room is bold
+                    var room_el = _converse.rooms_list_view.el.querySelector(
+                        ".available-chatroom"
+                    );
+                    expect(_.includes(room_el.classList, 'unread-msgs'));
+
+                    // If the user is mentioned, the counter also gets updated
+                    view.handleMUCMessage(
+                        $msg({
+                            from: room_jid+'/'+nick,
+                            id: (new Date()).getTime(),
+                            to: 'dummy@localhost',
+                            type: 'groupchat'
+                        }).c('body').t('romeo: Your attention is required').tree()
+                    );
+                    var indicator_el = _converse.rooms_list_view.el.querySelector(".msgs-indicator");
+                    expect(indicator_el.textContent).toBe('1');
+
+                    view.handleMUCMessage(
+                        $msg({
+                            from: room_jid+'/'+nick,
+                            id: (new Date()).getTime(),
+                            to: 'dummy@localhost',
+                            type: 'groupchat'
+                        }).c('body').t('romeo: and another thing...').tree()
+                    );
+                    indicator_el = _converse.rooms_list_view.el.querySelector(".msgs-indicator");
+                    expect(indicator_el.textContent).toBe('2');
+
+                    // When the chat gets maximized again, the unread indicators are removed
+                    view.model.set({'minimized': false});
+                    indicator_el = _converse.rooms_list_view.el.querySelector(".msgs-indicator");
+                    expect(_.isNull(indicator_el));
+                    room_el = _converse.rooms_list_view.el.querySelector(".available-chatroom");
+                    expect(_.includes(room_el.classList, 'unread-msgs')).toBeFalsy();
+                    done();
+                });
             });
         }));
     });

+ 138 - 156
src/converse-muc.js

@@ -62,7 +62,7 @@
     const ROOMS_PANEL_ID = 'chatrooms';
     const CHATROOMS_TYPE = 'chatroom';
 
-    const { Strophe, Backbone, $iq, $build, $msg, $pres, b64_sha1, sizzle, utils, _, fp, moment } = converse.env;
+    const { Strophe, Backbone, Promise, $iq, $build, $msg, $pres, b64_sha1, sizzle, utils, _, fp, moment } = converse.env;
 
     // Add Strophe Namespaces
     Strophe.addNamespace('MUC_ADMIN', Strophe.NS.MUC + "#admin");
@@ -448,11 +448,12 @@
                     this.registerHandlers();
 
                     if (this.model.get('connection_status') !==  ROOMSTATUS.ENTERED) {
-                        this.getRoomFeatures().always(() => {
+                        const handler = () => {
                             this.join();
                             this.fetchMessages();
                             _converse.emit('chatRoomOpened', this);
-                        });
+                        }
+                        this.getRoomFeatures().then(handler, handler);
                     } else {
                         this.fetchMessages();
                         _converse.emit('chatRoomOpened', this);
@@ -636,13 +637,13 @@
                      *  A promise which resolves once the list has been
                      *  retrieved.
                      */
-                    const deferred = new $.Deferred();
-                    affiliation = affiliation || 'member';
-                    const iq = $iq({to: chatroom_jid, type: "get"})
-                        .c("query", {xmlns: Strophe.NS.MUC_ADMIN})
-                            .c("item", {'affiliation': affiliation});
-                    _converse.connection.sendIQ(iq, deferred.resolve, deferred.reject);
-                    return deferred.promise();
+                    return new Promise((resolve, reject) => {
+                        affiliation = affiliation || 'member';
+                        const iq = $iq({to: chatroom_jid, type: "get"})
+                            .c("query", {xmlns: Strophe.NS.MUC_ADMIN})
+                                .c("item", {'affiliation': affiliation});
+                        _converse.connection.sendIQ(iq, resolve, reject);
+                    });
                 },
 
                 parseMemberListIQ (iq) {
@@ -725,18 +726,18 @@
                      *  (Object) member: Map containing the member's jid and
                      *      optionally a reason and affiliation.
                      */
-                    const deferred = new $.Deferred();
-                    const iq = $iq({to: chatroom_jid, type: "set"})
-                        .c("query", {xmlns: Strophe.NS.MUC_ADMIN})
-                        .c("item", {
-                            'affiliation': member.affiliation || affiliation,
-                            'jid': member.jid
-                        });
-                    if (!_.isUndefined(member.reason)) {
-                        iq.c("reason", member.reason);
-                    }
-                    _converse.connection.sendIQ(iq, deferred.resolve, deferred.reject);
-                    return deferred;
+                    return new Promise((resolve, reject) => {
+                        const iq = $iq({to: chatroom_jid, type: "set"})
+                            .c("query", {xmlns: Strophe.NS.MUC_ADMIN})
+                            .c("item", {
+                                'affiliation': member.affiliation || affiliation,
+                                'jid': member.jid
+                            });
+                        if (!_.isUndefined(member.reason)) {
+                            iq.c("reason", member.reason);
+                        }
+                        _converse.connection.sendIQ(iq, resolve, reject);
+                    });
                 },
 
                 setAffiliation (affiliation, members) {
@@ -772,10 +773,10 @@
                         members,
                         _.partial(this.sendAffiliationIQ, this.model.get('jid'), affiliation)
                     );
-                    return $.when.apply($, promises);
+                    return Promise.all(promises);
                 },
 
-                setAffiliations (members, onSuccess, onError) {
+                setAffiliations (members) {
                     /* Send IQ stanzas to the server to modify the
                      * affiliations in this room.
                      *
@@ -786,14 +787,8 @@
                      *  (Function) onSuccess: callback for a succesful response
                      *  (Function) onError: callback for an error response
                      */
-                    if (_.isEmpty(members)) {
-                        // Succesfully updated with zero affilations :)
-                        onSuccess(null);
-                        return;
-                    }
                     const affiliations = _.uniq(_.map(members, 'affiliation'));
-                    const promises = _.map(affiliations, _.partial(this.setAffiliation.bind(this), _, members));
-                    $.when.apply($, promises).done(onSuccess).fail(onError);
+                    _.each(affiliations, _.partial(this.setAffiliation.bind(this), _, members));
                 },
 
                 marshallAffiliationIQs () {
@@ -814,12 +809,13 @@
                     if (_.isString(affiliations)) {
                         affiliations = [affiliations];
                     }
-                    const deferred = new $.Deferred();
-                    const promises = _.map(affiliations, _.partial(this.requestMemberList, this.model.get('jid')));
-                    $.when.apply($, promises).always(
-                        _.flow(this.marshallAffiliationIQs.bind(this), deferred.resolve)
-                    );
-                    return deferred.promise();
+                    return new Promise((resolve, reject) => {
+                        const promises = _.map(affiliations, _.partial(this.requestMemberList, this.model.get('jid')));
+                        Promise.all(promises).then(
+                            _.flow(this.marshallAffiliationIQs.bind(this), resolve),
+                            _.flow(this.marshallAffiliationIQs.bind(this), resolve)
+                        );
+                    });
                 },
 
                 updateMemberLists (members, affiliations, deltaFunc) {
@@ -840,15 +836,9 @@
                      *  updated or once it's been established there's no need
                      *  to update the list.
                      */
-                    const deferred = new $.Deferred();
                     this.getJidsWithAffiliations(affiliations).then((old_members) => {
-                        this.setAffiliations(
-                            deltaFunc(members, old_members),
-                            deferred.resolve,
-                            deferred.reject
-                        );
+                        this.setAffiliations(deltaFunc(members, old_members));
                     });
-                    return deferred.promise();
                 },
 
                 directInvite (recipient, reason) {
@@ -1010,14 +1000,14 @@
                             this.setAffiliation('admin',
                                     [{ 'jid': args[0],
                                        'reason': args[1]
-                                    }]).fail(this.onCommandError.bind(this));
+                                    }]).then(null, this.onCommandError.bind(this));
                             break;
                         case 'ban':
                             if (!this.validateRoleChangeCommand(command, args)) { break; }
                             this.setAffiliation('outcast',
                                     [{ 'jid': args[0],
                                        'reason': args[1]
-                                    }]).fail(this.onCommandError.bind(this));
+                                    }]).then(null, this.onCommandError.bind(this));
                             break;
                         case 'clear':
                             this.clearChatRoomMessages();
@@ -1065,7 +1055,7 @@
                             this.setAffiliation('member',
                                     [{ 'jid': args[0],
                                        'reason': args[1]
-                                    }]).fail(this.onCommandError.bind(this));
+                                    }]).then(null, this.onCommandError.bind(this));
                             break;
                         case 'nick':
                             _converse.connection.send($pres({
@@ -1079,7 +1069,7 @@
                             this.setAffiliation('owner',
                                     [{ 'jid': args[0],
                                        'reason': args[1]
-                                    }]).fail(this.onCommandError.bind(this));
+                                    }]).then(null, this.onCommandError.bind(this));
                             break;
                         case 'op':
                             if (!this.validateRoleChangeCommand(command, args)) { break; }
@@ -1092,7 +1082,7 @@
                             this.setAffiliation('none',
                                     [{ 'jid': args[0],
                                        'reason': args[1]
-                                    }]).fail(this.onCommandError.bind(this));
+                                    }]).then(null, this.onCommandError.bind(this));
                             break;
                         case 'topic':
                         case 'subject':
@@ -1330,22 +1320,18 @@
                      * Parameters:
                      *  (HTMLElement) form: The configuration form DOM element.
                      */
-                    const deferred = new $.Deferred();
-                    const $inputs = $(form).find(':input:not([type=button]):not([type=submit])'),
-                        configArray = [];
-                    $inputs.each(function () {
-                        configArray.push(utils.webForm2xForm(this));
-                    });
-                    this.sendConfiguration(
-                        configArray,
-                        deferred.resolve,
-                        deferred.reject
-                    );
-                    this.$el.find('div.chatroom-form-container').hide((el) => {
-                        $(el).remove();
-                        this.renderAfterTransition();
+                    return new Promise((resolve, reject) => {
+                        const $inputs = $(form).find(':input:not([type=button]):not([type=submit])'),
+                            configArray = [];
+                        $inputs.each(function () {
+                            configArray.push(utils.webForm2xForm(this));
+                        });
+                        this.sendConfiguration(configArray, resolve, reject);
+                        this.$el.find('div.chatroom-form-container').hide((el) => {
+                            $(el).remove();
+                            this.renderAfterTransition();
+                        });
                     });
-                    return deferred.promise();
                 },
 
                 autoConfigureChatRoom () {
@@ -1360,44 +1346,38 @@
                      *       containing the configuration.
                      */
                     const that = this;
-                    const deferred = new $.Deferred();
-
-                    this.fetchRoomConfiguration().then(function (stanza) {
-                        const configArray = [],
-                            fields = stanza.querySelectorAll('field'),
-                            config = that.model.get('roomconfig');
-                        
-                        let count = fields.length;
-
-                        _.each(fields, function (field) {
-                            const fieldname = field.getAttribute('var').replace('muc#roomconfig_', ''),
-                                type = field.getAttribute('type');
-                            let value;
-                            if (fieldname in config) {
-                                switch (type) {
-                                    case 'boolean':
-                                        value = config[fieldname] ? 1 : 0;
-                                        break;
-                                    case 'list-multi':
-                                        // TODO: we don't yet handle "list-multi" types
-                                        value = field.innerHTML;
-                                        break;
-                                    default:
-                                        value = config[fieldname];
+                    return new Promise((resolve, reject) => {
+                        this.fetchRoomConfiguration().then(function (stanza) {
+                            const configArray = [],
+                                fields = stanza.querySelectorAll('field'),
+                                config = that.model.get('roomconfig');
+                            let count = fields.length;
+
+                            _.each(fields, function (field) {
+                                const fieldname = field.getAttribute('var').replace('muc#roomconfig_', ''),
+                                    type = field.getAttribute('type');
+                                let value;
+                                if (fieldname in config) {
+                                    switch (type) {
+                                        case 'boolean':
+                                            value = config[fieldname] ? 1 : 0;
+                                            break;
+                                        case 'list-multi':
+                                            // TODO: we don't yet handle "list-multi" types
+                                            value = field.innerHTML;
+                                            break;
+                                        default:
+                                            value = config[fieldname];
+                                    }
+                                    field.innerHTML = $build('value').t(value);
                                 }
-                                field.innerHTML = $build('value').t(value);
-                            }
-                            configArray.push(field);
-                            if (!--count) {
-                                that.sendConfiguration(
-                                    configArray,
-                                    deferred.resolve,
-                                    deferred.reject
-                                );
-                            }
+                                configArray.push(field);
+                                if (!--count) {
+                                    that.sendConfiguration(configArray, resolve, reject);
+                                }
+                            });
                         });
                     });
-                    return deferred;
                 },
 
                 cancelConfiguration () {
@@ -1419,70 +1399,72 @@
                      * Parameters:
                      *  (Function) handler: The handler for the response IQ
                      */
-                    const deferred = new $.Deferred();
-                    _converse.connection.sendIQ(
-                        $iq({
-                            'to': this.model.get('jid'),
-                            'type': "get"
-                        }).c("query", {xmlns: Strophe.NS.MUC_OWNER}),
-                        (iq) => {
-                            if (handler) {
-                                handler.apply(this, arguments);
+                    return new Promise((resolve, reject) => {
+                        _converse.connection.sendIQ(
+                            $iq({
+                                'to': this.model.get('jid'),
+                                'type': "get"
+                            }).c("query", {xmlns: Strophe.NS.MUC_OWNER}),
+                            (iq) => {
+                                if (handler) {
+                                    handler.apply(this, arguments);
+                                }
+                                resolve(iq);
+                            },
+                            reject // errback
+                        );
+                    });
+                },
+
+                parseRoomFeatures (iq) {
+                    /* See http://xmpp.org/extensions/xep-0045.html#disco-roominfo
+                     *
+                     *  <identity
+                     *      category='conference'
+                     *      name='A Dark Cave'
+                     *      type='text'/>
+                     *  <feature var='http://jabber.org/protocol/muc'/>
+                     *  <feature var='muc_passwordprotected'/>
+                     *  <feature var='muc_hidden'/>
+                     *  <feature var='muc_temporary'/>
+                     *  <feature var='muc_open'/>
+                     *  <feature var='muc_unmoderated'/>
+                     *  <feature var='muc_nonanonymous'/>
+                     *  <feature var='urn:xmpp:mam:0'/>
+                     */
+                    const features = {
+                        'features_fetched': true
+                    };
+                    _.each(iq.querySelectorAll('feature'), function (field) {
+                        const fieldname = field.getAttribute('var');
+                        if (!fieldname.startsWith('muc_')) {
+                            if (fieldname === Strophe.NS.MAM) {
+                                features.mam_enabled = true;
                             }
-                            deferred.resolve(iq);
-                        },
-                        deferred.reject // errback
-                    );
-                    return deferred.promise();
+                            return;
+                        }
+                        features[fieldname.replace('muc_', '')] = true;
+                    });
+                    const desc_field = iq.querySelector('field[var="muc#roominfo_description"] value');
+                    if (!_.isNull(desc_field)) {
+                        features.description = desc_field.textContent;
+                    }
+                    this.model.save(features);
                 },
 
                 getRoomFeatures () {
                     /* Fetch the room disco info, parse it and then
                      * save it on the Backbone.Model of this chat rooms.
                      */
-                    const deferred = new $.Deferred();
-                    const that = this;
-                    _converse.connection.disco.info(this.model.get('jid'), null,
-                        function (iq) {
-                            /* See http://xmpp.org/extensions/xep-0045.html#disco-roominfo
-                             *
-                             *  <identity
-                             *      category='conference'
-                             *      name='A Dark Cave'
-                             *      type='text'/>
-                             *  <feature var='http://jabber.org/protocol/muc'/>
-                             *  <feature var='muc_passwordprotected'/>
-                             *  <feature var='muc_hidden'/>
-                             *  <feature var='muc_temporary'/>
-                             *  <feature var='muc_open'/>
-                             *  <feature var='muc_unmoderated'/>
-                             *  <feature var='muc_nonanonymous'/>
-                             *  <feature var='urn:xmpp:mam:0'/>
-                             */
-                            const features = {
-                                'features_fetched': true
-                            };
-                            _.each(iq.querySelectorAll('feature'), function (field) {
-                                const fieldname = field.getAttribute('var');
-                                if (!fieldname.startsWith('muc_')) {
-                                    if (fieldname === Strophe.NS.MAM) {
-                                        features.mam_enabled = true;
-                                    }
-                                    return;
-                                }
-                                features[fieldname.replace('muc_', '')] = true;
-                            });
-                            const desc_field = iq.querySelector('field[var="muc#roominfo_description"] value');
-                            if (!_.isNull(desc_field)) {
-                                features.description = desc_field.textContent;
-                            }
-                            that.model.save(features);
-                            return deferred.resolve();
-                        },
-                        deferred.reject,
-                        5000
-                    );
-                    return deferred.promise();
+                    return new Promise((resolve, reject) => {
+                        _converse.connection.disco.info(
+                            this.model.get('jid'),
+                            null,
+                            _.flow(this.parseRoomFeatures.bind(this), resolve),
+                            () => { reject(new Error("Could not parse the room features")) },
+                            5000
+                        );
+                    });
                 },
 
                 getAndRenderConfigurationForm (ev) {

+ 48 - 42
tests/utils.js

@@ -86,54 +86,60 @@
         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-nick').val(nick);
         roomspanel.$el.find('input.new-chatroom-server').val(server);
         roomspanel.$el.find('form').submit();
         this.closeControlBox(_converse);
     };
 
     utils.openAndEnterChatRoom = function (converse, room, server, nick) {
-        sinon.spy(converse.connection, 'sendIQ');
-        utils.openChatRoom(converse, room, server);
-        var view = converse.chatboxviews.get((room+'@'+server).toLowerCase());
-
-        // We pretend this is a new room, so no disco info is returned.
-        var IQ_id = converse.connection.sendIQ.firstCall.returnValue;
-        var features_stanza = $iq({
-                from: 'lounge@localhost',
-                'id': IQ_id,
-                'to': 'dummy@localhost/desktop',
-                'type': 'error'
-            }).c('error', {'type': 'cancel'})
-                .c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"});
-        converse.connection._dataRecv(utils.createRequest(features_stanza));
-
-        // The XMPP server returns the reserved nick for this user.
-        IQ_id = converse.connection.sendIQ.secondCall.returnValue;
-        var stanza = $iq({
-            'type': 'result',
-            'id': IQ_id,
-            'from': view.model.get('jid'),
-            'to': converse.connection.jid 
-        }).c('query', {'xmlns': 'http://jabber.org/protocol/disco#info', 'node': 'x-roomuser-item'})
-            .c('identity', {'category': 'conference', 'name': nick, 'type': 'text'});
-        converse.connection._dataRecv(utils.createRequest(stanza));
-        // The user has just entered the room (because join was called)
-        // and receives their own presence from the server.
-        // See example 24: http://xmpp.org/extensions/xep-0045.html#enter-pres
-        var presence = $pres({
-                to: converse.connection.jid,
-                from: room+'@'+server+'/'+nick,
-                id: 'DC352437-C019-40EC-B590-AF29E879AF97'
-        }).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
-            .c('item').attrs({
-                affiliation: 'member',
-                jid: converse.bare_jid,
-                role: 'occupant'
-            }).up()
-            .c('status').attrs({code:'110'});
-        converse.connection._dataRecv(utils.createRequest(presence));
-        converse.connection.sendIQ.restore();
+        return new Promise(function (resolve, reject) {
+            sinon.spy(converse.connection, 'sendIQ');
+            utils.openChatRoom(converse, room, server);
+            var view = converse.chatboxviews.get((room+'@'+server).toLowerCase());
+
+            // We pretend this is a new room, so no disco info is returned.
+            var IQ_id = converse.connection.sendIQ.firstCall.returnValue;
+            var features_stanza = $iq({
+                    'from': 'lounge@localhost',
+                    'id': IQ_id,
+                    'to': 'dummy@localhost/desktop',
+                    'type': 'error'
+                }).c('error', {'type': 'cancel'})
+                    .c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"});
+            converse.connection._dataRecv(utils.createRequest(features_stanza));
+
+            utils.waitUntil(function () {
+                return converse.connection.sendIQ.secondCall;
+            }).then(function () {
+                // The XMPP server returns the reserved nick for this user.
+                IQ_id = converse.connection.sendIQ.secondCall.returnValue;
+                var stanza = $iq({
+                    'type': 'result',
+                    'id': IQ_id,
+                    'from': view.model.get('jid'),
+                    'to': converse.connection.jid 
+                }).c('query', {'xmlns': 'http://jabber.org/protocol/disco#info', 'node': 'x-roomuser-item'})
+                    .c('identity', {'category': 'conference', 'name': nick, 'type': 'text'});
+                converse.connection._dataRecv(utils.createRequest(stanza));
+                // The user has just entered the room (because join was called)
+                // and receives their own presence from the server.
+                // See example 24: http://xmpp.org/extensions/xep-0045.html#enter-pres
+                var presence = $pres({
+                        to: converse.connection.jid,
+                        from: room+'@'+server+'/'+nick,
+                        id: 'DC352437-C019-40EC-B590-AF29E879AF97'
+                }).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
+                    .c('item').attrs({
+                        affiliation: 'member',
+                        jid: converse.bare_jid,
+                        role: 'occupant'
+                    }).up()
+                    .c('status').attrs({code:'110'});
+                converse.connection._dataRecv(utils.createRequest(presence));
+                converse.connection.sendIQ.restore();
+                resolve();
+            });
+        });
     };
 
     utils.clearBrowserStorage = function () {

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio