Forráskód Böngészése

Test `/help`, `/kick` and `/mute` commands

JC Brand 7 éve
szülő
commit
2b6db9d50b
2 módosított fájl, 337 hozzáadás és 161 törlés
  1. 315 146
      spec/chatroom.js
  2. 22 15
      src/converse-muc.js

+ 315 - 146
spec/chatroom.js

@@ -10,16 +10,27 @@
 
 
     return describe("ChatRooms", function () {
     return describe("ChatRooms", function () {
         describe("The \"rooms\" API", function () {
         describe("The \"rooms\" API", function () {
+            var original_timeout;
+
+            beforeEach(function() {
+                original_timeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
+                jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
+            });
+
+            afterEach(function() {
+                jasmine.DEFAULT_TIMEOUT_INTERVAL = original_timeout;
+            });
 
 
             it("has a method 'close' which closes rooms by JID or all rooms when called with no arguments",
             it("has a method 'close' which closes rooms by JID or all rooms when called with no arguments",
                 mock.initConverseWithPromises(
                 mock.initConverseWithPromises(
                     null, ['rosterGroupsFetched'], {},
                     null, ['rosterGroupsFetched'], {},
                     function (done, _converse) {
                     function (done, _converse) {
 
 
-                test_utils.createContacts(_converse, 'current');
                 test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () {
                 test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () {
-                test_utils.openAndEnterChatRoom(_converse, 'leisure', 'localhost', 'dummy').then(function () {
-                test_utils.openAndEnterChatRoom(_converse, 'news', 'localhost', 'dummy').then(function () {
+                    return test_utils.openAndEnterChatRoom(_converse, 'leisure', 'localhost', 'dummy');
+                }).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('lounge@localhost').$el.is(':visible')).toBeTruthy();
                     expect(_converse.chatboxviews.get('leisure@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(_converse.chatboxviews.get('news@localhost').$el.is(':visible')).toBeTruthy();
@@ -38,20 +49,19 @@
                     expect(_converse.chatboxviews.get('lounge@localhost')).toBeUndefined();
                     expect(_converse.chatboxviews.get('lounge@localhost')).toBeUndefined();
                     expect(_converse.chatboxviews.get('leisure@localhost')).toBeUndefined();
                     expect(_converse.chatboxviews.get('leisure@localhost')).toBeUndefined();
                     expect(_converse.chatboxviews.get('news@localhost')).toBeUndefined();
                     expect(_converse.chatboxviews.get('news@localhost')).toBeUndefined();
-
-                    test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () {
-                    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();
-
-                        _converse.api.rooms.close();
-                        expect(_converse.chatboxviews.get('lounge@localhost')).toBeUndefined();
-                        expect(_converse.chatboxviews.get('leisure@localhost')).toBeUndefined();
-                        done();
-                    });
-                    });
-                });
-                });
+                    return test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy');
+                }).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();
+                    _converse.api.rooms.close();
+                    expect(_converse.chatboxviews.get('lounge@localhost')).toBeUndefined();
+                    expect(_converse.chatboxviews.get('leisure@localhost')).toBeUndefined();
+                    return done();
+                }).catch((err) => {
+                    _converse.log(err, Strophe.LogLevel.FATAL);
+                    done();
                 });
                 });
             }));
             }));
 
 
@@ -300,6 +310,7 @@
 
 
                 var view = _converse.chatboxviews.get('lounge@localhost');
                 var view = _converse.chatboxviews.get('lounge@localhost');
                 spyOn(view, 'join').and.callThrough();
                 spyOn(view, 'join').and.callThrough();
+                spyOn(view, 'submitNickname').and.callThrough();
 
 
                 /* <iq to="myroom@conference.chat.example.org"
                 /* <iq to="myroom@conference.chat.example.org"
                  *     from="jordie.langen@chat.example.org/converse.js-11659299"
                  *     from="jordie.langen@chat.example.org/converse.js-11659299"
@@ -329,10 +340,10 @@
                     .c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"});
                     .c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"});
                     _converse.connection._dataRecv(test_utils.createRequest(stanza));
                     _converse.connection._dataRecv(test_utils.createRequest(stanza));
 
 
-                    // TODO: enter nickname
-                    var $input = view.$el.find('input.new-chatroom-nick');
-                    $input.val('nicky').parents('form').submit();
-
+                    var input = view.el.querySelector('input.new-chatroom-nick');
+                    input.value = 'nicky';
+                    view.el.querySelector('input[type=submit]').click();
+                    expect(view.submitNickname).toHaveBeenCalled();
                     expect(view.join).toHaveBeenCalled();
                     expect(view.join).toHaveBeenCalled();
 
 
                     // The user has just entered the room (because join was called)
                     // The user has just entered the room (because join was called)
@@ -426,7 +437,7 @@
                     }).up()
                     }).up()
                     .c('status', {code: '110'});
                     .c('status', {code: '110'});
                 _converse.connection._dataRecv(test_utils.createRequest(presence));
                 _converse.connection._dataRecv(test_utils.createRequest(presence));
-                expect($chat_content.find('div.chat-info:first').html()).toBe("some1 has joined the room.");
+                expect($chat_content.find('div.chat-info:first').html()).toBe("some1 has entered the room.");
 
 
                 presence = $pres({
                 presence = $pres({
                         to: 'dummy@localhost/_converse.js-29092160',
                         to: 'dummy@localhost/_converse.js-29092160',
@@ -439,7 +450,7 @@
                     });
                     });
                 _converse.connection._dataRecv(test_utils.createRequest(presence));
                 _converse.connection._dataRecv(test_utils.createRequest(presence));
                 expect($chat_content.find('div.chat-info').length).toBe(2);
                 expect($chat_content.find('div.chat-info').length).toBe(2);
-                expect($chat_content.find('div.chat-info:last').html()).toBe("newguy has joined the room.");
+                expect($chat_content.find('div.chat-info:last').html()).toBe("newguy has entered the room.");
 
 
                 // Don't show duplicate join messages
                 // Don't show duplicate join messages
                 presence = $pres({
                 presence = $pres({
@@ -1335,7 +1346,7 @@
                     expect($occupants.children().first(0).text()).toBe("oldnick");
                     expect($occupants.children().first(0).text()).toBe("oldnick");
 
 
                     expect($chat_content.find('div.chat-info').length).toBe(2);
                     expect($chat_content.find('div.chat-info').length).toBe(2);
-                    expect($chat_content.find('div.chat-info:first').html()).toBe("oldnick has joined the room.");
+                    expect($chat_content.find('div.chat-info:first').html()).toBe("oldnick has entered the room.");
                     expect($chat_content.find('div.chat-info:last').html()).toBe(
                     expect($chat_content.find('div.chat-info:last').html()).toBe(
                         __(_converse.muc.new_nickname_messages["210"], "oldnick")
                         __(_converse.muc.new_nickname_messages["210"], "oldnick")
                     );
                     );
@@ -1384,7 +1395,7 @@
                         __(_converse.muc.new_nickname_messages["303"], "newnick")
                         __(_converse.muc.new_nickname_messages["303"], "newnick")
                     );
                     );
                     expect($chat_content.find('div.chat-info').last().html()).toBe(
                     expect($chat_content.find('div.chat-info').last().html()).toBe(
-                        "newnick has joined the room.");
+                        "newnick has entered the room.");
                     $occupants = view.$('.occupant-list');
                     $occupants = view.$('.occupant-list');
                     expect($occupants.children().length).toBe(1);
                     expect($occupants.children().length).toBe(1);
                     expect($occupants.children().first(0).text()).toBe("newnick");
                     expect($occupants.children().first(0).text()).toBe("newnick");
@@ -1706,152 +1717,310 @@
 
 
         describe("Each chat room can take special commands", function () {
         describe("Each chat room can take special commands", function () {
 
 
-            it("to set the room topic",
+            it("/help to show the available commands",
                 mock.initConverseWithPromises(
                 mock.initConverseWithPromises(
                     null, ['rosterGroupsFetched'], {},
                     null, ['rosterGroupsFetched'], {},
                     function (done, _converse) {
                     function (done, _converse) {
 
 
-                var sent_stanza;
-                test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy');
-                var view = _converse.chatboxviews.get('lounge@localhost');
-                spyOn(view, 'onMessageSubmitted').and.callThrough();
-                spyOn(view, 'clearChatRoomMessages');
-                spyOn(_converse.connection, 'send').and.callFake(function (stanza) {
-                    sent_stanza = stanza;
+                test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () {
+                    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}));
+                    expect(view.onMessageSubmitted).toHaveBeenCalled();
+                    const info_messages = Array.prototype.slice.call(view.el.querySelectorAll('.chat-info'), 0);
+                    expect(info_messages.length).toBe(17);
+                    expect(info_messages.pop().textContent).toBe('/voice: Allow muted user to post messages');
+                    expect(info_messages.pop().textContent).toBe('/topic: Set room subject (alias for /subject)');
+                    expect(info_messages.pop().textContent).toBe('/subject: Set room subject');
+                    expect(info_messages.pop().textContent).toBe('/revoke: Revoke user\'s membership');
+                    expect(info_messages.pop().textContent).toBe('/owner: Grant ownership of this room');
+                    expect(info_messages.pop().textContent).toBe('/op: Grant moderator role to user');
+                    expect(info_messages.pop().textContent).toBe('/nick: Change your nickname');
+                    expect(info_messages.pop().textContent).toBe('/mute: Remove user\'s ability to post messages');
+                    expect(info_messages.pop().textContent).toBe('/member: Grant membership to a user');
+                    expect(info_messages.pop().textContent).toBe('/me: Write in 3rd person');
+                    expect(info_messages.pop().textContent).toBe('/kick: Kick user from room');
+                    expect(info_messages.pop().textContent).toBe('/help: Show this menu');
+                    expect(info_messages.pop().textContent).toBe('/deop: Change user role to occupant');
+                    expect(info_messages.pop().textContent).toBe('/clear: Remove messages');
+                    expect(info_messages.pop().textContent).toBe('/ban: Ban user from room');
+                    expect(info_messages.pop().textContent).toBe('/admin: Change user\'s affiliation to admin');
+                    done();
                 });
                 });
-                // 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}));
-                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}));
-                expect(sent_stanza.textContent).toBe('This is a new subject');
-
-                // Check case insensitivity
-                //
-                // XXX: This works in the browser but fails on phantomjs
-                // expect(sent_stanza.outerHTML).toBe(
-                //     '<message to="lounge@localhost" from="dummy@localhost/resource" type="groupchat" xmlns="jabber:client">'+
-                //         '<subject xmlns="jabber:client">This is yet another subject</subject>'+
-                //     '</message>');
-                $textarea.val('/Subject This is yet another subject');
-                $textarea.trigger($.Event('keypress', {keyCode: 13}));
-                expect(sent_stanza.textContent).toBe('This is yet another subject');
-                done();
             }));
             }));
 
 
-            it("to clear messages",
+            it("/topic to set the room topic",
                 mock.initConverseWithPromises(
                 mock.initConverseWithPromises(
                     null, ['rosterGroupsFetched'], {},
                     null, ['rosterGroupsFetched'], {},
                     function (done, _converse) {
                     function (done, _converse) {
 
 
-                test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy');
-                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}));
-                expect(view.onMessageSubmitted).toHaveBeenCalled();
-                expect(view.clearChatRoomMessages).toHaveBeenCalled();
-                done();
+                test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () {
+                    var sent_stanza;
+                    var view = _converse.chatboxviews.get('lounge@localhost');
+                    spyOn(view, 'onMessageSubmitted').and.callThrough();
+                    spyOn(view, 'clearChatRoomMessages');
+                    spyOn(_converse.connection, 'send').and.callFake(function (stanza) {
+                        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}));
+                    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}));
+                    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">'+
+                            '<subject xmlns="jabber:client">This is a new subject</subject>'+
+                        '</message>');
+
+                    // Check case insensitivity
+                    $textarea.val('/Subject This is yet another subject');
+                    $textarea.trigger($.Event('keypress', {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">'+
+                            '<subject xmlns="jabber:client">This is yet another subject</subject>'+
+                        '</message>');
+                    done();
+                });
             }));
             }));
 
 
-            it("to make a user an owner",
+            it("/clear to clear messages",
                 mock.initConverseWithPromises(
                 mock.initConverseWithPromises(
                     null, ['rosterGroupsFetched'], {},
                     null, ['rosterGroupsFetched'], {},
                     function (done, _converse) {
                     function (done, _converse) {
 
 
-                var sent_IQ, IQ_id;
-                var sendIQ = _converse.connection.sendIQ;
-                spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
-                    sent_IQ = iq;
-                    IQ_id = sendIQ.bind(this)(iq, callback, errback);
+                test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () {
+                    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}));
+                    expect(view.onMessageSubmitted).toHaveBeenCalled();
+                    expect(view.clearChatRoomMessages).toHaveBeenCalled();
+                    done();
                 });
                 });
-                test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy');
-                var view = _converse.chatboxviews.get('lounge@localhost');
-                spyOn(view, 'onMessageSubmitted').and.callThrough();
-                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}));
-                expect(view.onMessageSubmitted).toHaveBeenCalled();
-                expect(view.validateRoleChangeCommand).toHaveBeenCalled();
-                expect(view.showStatusNotification).toHaveBeenCalledWith(
-                    "Error: the \"owner\" command takes two arguments, the user's nickname and optionally a reason.",
-                    true
-                );
-                expect(view.setAffiliation).not.toHaveBeenCalled();
-
-                // Call now with the correct amount of arguments.
-                // XXX: Calling onMessageSubmitted directly, trying
-                // again via triggering Event doesn't work for some weird
-                // reason.
-                view.onMessageSubmitted('/owner annoyingGuy@localhost You\'re annoying');
-                expect(view.validateRoleChangeCommand.calls.count()).toBe(2);
-                expect(view.showStatusNotification.calls.count()).toBe(1);
-                expect(view.setAffiliation).toHaveBeenCalled();
-                // Check that the member list now gets updated
-                expect(sent_IQ.toLocaleString()).toBe(
-                    "<iq to='lounge@localhost' type='set' xmlns='jabber:client' id='"+IQ_id+"'>"+
-                        "<query xmlns='http://jabber.org/protocol/muc#admin'>"+
-                            "<item affiliation='owner' jid='annoyingGuy@localhost'>"+
-                                "<reason>You&apos;re annoying</reason>"+
-                            "</item>"+
-                        "</query>"+
-                    "</iq>");
-                done();
             }));
             }));
 
 
-            it("to ban a user",
+            it("/owner to make a user an owner",
                 mock.initConverseWithPromises(
                 mock.initConverseWithPromises(
                     null, ['rosterGroupsFetched'], {},
                     null, ['rosterGroupsFetched'], {},
                     function (done, _converse) {
                     function (done, _converse) {
 
 
-                var sent_IQ, IQ_id;
-                var sendIQ = _converse.connection.sendIQ;
-                spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
-                    sent_IQ = iq;
-                    IQ_id = sendIQ.bind(this)(iq, callback, errback);
+                test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () {
+                    var sent_IQ, IQ_id;
+                    var sendIQ = _converse.connection.sendIQ;
+                    spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
+                        sent_IQ = iq;
+                        IQ_id = sendIQ.bind(this)(iq, callback, errback);
+                    });
+                    var view = _converse.chatboxviews.get('lounge@localhost');
+                    spyOn(view, 'onMessageSubmitted').and.callThrough();
+                    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}));
+                    expect(view.onMessageSubmitted).toHaveBeenCalled();
+                    expect(view.validateRoleChangeCommand).toHaveBeenCalled();
+                    expect(view.showStatusNotification).toHaveBeenCalledWith(
+                        "Error: the \"owner\" command takes two arguments, the user's nickname and optionally a reason.",
+                        true
+                    );
+                    expect(view.setAffiliation).not.toHaveBeenCalled();
+
+                    // Call now with the correct amount of arguments.
+                    // XXX: Calling onMessageSubmitted directly, trying
+                    // again via triggering Event doesn't work for some weird
+                    // reason.
+                    view.onMessageSubmitted('/owner annoyingGuy@localhost You\'re responsible');
+                    expect(view.validateRoleChangeCommand.calls.count()).toBe(2);
+                    expect(view.showStatusNotification.calls.count()).toBe(1);
+                    expect(view.setAffiliation).toHaveBeenCalled();
+                    // Check that the member list now gets updated
+                    expect(sent_IQ.toLocaleString()).toBe(
+                        "<iq to='lounge@localhost' type='set' xmlns='jabber:client' id='"+IQ_id+"'>"+
+                            "<query xmlns='http://jabber.org/protocol/muc#admin'>"+
+                                "<item affiliation='owner' jid='annoyingGuy@localhost'>"+
+                                    "<reason>You&apos;re responsible</reason>"+
+                                "</item>"+
+                            "</query>"+
+                        "</iq>");
+                    done();
+                });
+            }));
+
+            it("/ban to ban a user",
+                mock.initConverseWithPromises(
+                    null, ['rosterGroupsFetched'], {},
+                    function (done, _converse) {
+
+                test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () {
+                    var sent_IQ, IQ_id;
+                    var sendIQ = _converse.connection.sendIQ;
+                    spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
+                        sent_IQ = iq;
+                        IQ_id = sendIQ.bind(this)(iq, callback, errback);
+                    });
+                    var view = _converse.chatboxviews.get('lounge@localhost');
+                    spyOn(view, 'onMessageSubmitted').and.callThrough();
+                    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}));
+                    expect(view.onMessageSubmitted).toHaveBeenCalled();
+                    expect(view.validateRoleChangeCommand).toHaveBeenCalled();
+                    expect(view.showStatusNotification).toHaveBeenCalledWith(
+                        "Error: the \"ban\" command takes two arguments, the user's nickname and optionally a reason.",
+                        true
+                    );
+                    expect(view.setAffiliation).not.toHaveBeenCalled();
+                    // Call now with the correct amount of arguments.
+                    // XXX: Calling onMessageSubmitted directly, trying
+                    // again via triggering Event doesn't work for some weird
+                    // reason.
+                    view.onMessageSubmitted('/ban annoyingGuy@localhost You\'re annoying');
+                    expect(view.validateRoleChangeCommand.calls.count()).toBe(2);
+                    expect(view.showStatusNotification.calls.count()).toBe(1);
+                    expect(view.setAffiliation).toHaveBeenCalled();
+                    // Check that the member list now gets updated
+                    expect(sent_IQ.toLocaleString()).toBe(
+                        "<iq to='lounge@localhost' type='set' xmlns='jabber:client' id='"+IQ_id+"'>"+
+                            "<query xmlns='http://jabber.org/protocol/muc#admin'>"+
+                                "<item affiliation='outcast' jid='annoyingGuy@localhost'>"+
+                                    "<reason>You&apos;re annoying</reason>"+
+                                "</item>"+
+                            "</query>"+
+                        "</iq>");
+                    done();
+                });
+            }));
+
+            it("/kick to kick a user",
+                mock.initConverseWithPromises(
+                    null, ['rosterGroupsFetched'], {},
+                    function (done, _converse) {
+
+                test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () {
+                    var sent_IQ, IQ_id;
+                    var sendIQ = _converse.connection.sendIQ;
+                    spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
+                        sent_IQ = iq;
+                        IQ_id = sendIQ.bind(this)(iq, callback, errback);
+                    });
+                    var view = _converse.chatboxviews.get('lounge@localhost');
+                    spyOn(view, 'onMessageSubmitted').and.callThrough();
+                    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}));
+                    expect(view.onMessageSubmitted).toHaveBeenCalled();
+                    expect(view.validateRoleChangeCommand).toHaveBeenCalled();
+                    expect(view.showStatusNotification).toHaveBeenCalledWith(
+                        "Error: the \"kick\" command takes two arguments, the user's nickname and optionally a reason.",
+                        true
+                    );
+                    expect(view.modifyRole).not.toHaveBeenCalled();
+                    // Call now with the correct amount of arguments.
+                    // XXX: Calling onMessageSubmitted directly, trying
+                    // again via triggering Event doesn't work for some weird
+                    // reason.
+                    view.onMessageSubmitted('/kick annoyingGuy You\'re annoying');
+                    expect(view.validateRoleChangeCommand.calls.count()).toBe(2);
+                    expect(view.showStatusNotification.calls.count()).toBe(1);
+                    expect(view.modifyRole).toHaveBeenCalled();
+                    expect(sent_IQ.toLocaleString()).toBe(
+                        "<iq to='lounge@localhost' type='set' xmlns='jabber:client' id='"+IQ_id+"'>"+
+                            "<query xmlns='http://jabber.org/protocol/muc#admin'>"+
+                                "<item nick='annoyingGuy' role='none'>"+
+                                    "<reason>You&apos;re annoying</reason>"+
+                                "</item>"+
+                            "</query>"+
+                        "</iq>");
+
+                    /* <presence
+                     *     from='harfleur@chat.shakespeare.lit/pistol'
+                     *     to='gower@shakespeare.lit/cell'
+                     *     type='unavailable'>
+                     *       <x xmlns='http://jabber.org/protocol/muc#user'>
+                     *         <item affiliation='none' role='none'/>
+                     *         <status code='307'/>
+                     *       </x>
+                     *     </presence>
+                     */
+                    var features_stanza = $pres({
+                            'from': 'lounge@localhost/annoyingGuy',
+                            'to': 'dummy@localhost/desktop',
+                            'type': 'unavailable'
+                        })
+                        .c('x', { 'xmlns': 'http://jabber.org/protocol/muc#user'})
+                            .c('item', {
+                                'affiliation': 'none',
+                                'role': 'none'
+                            }).up()
+                            .c('status', {'code': '307'});
+                    _converse.connection._dataRecv(test_utils.createRequest(features_stanza));
+                    expect(
+                        view.el.querySelectorAll('.chat-info')[2].textContent, 
+                        "annoyingGuy has been kicked out");
+                    done();
+                });
+            }));
+
+            it("/mute to mute a user",
+                mock.initConverseWithPromises(
+                    null, ['rosterGroupsFetched'], {},
+                    function (done, _converse) {
+
+                test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () {
+                    var sent_IQ, IQ_id;
+                    var sendIQ = _converse.connection.sendIQ;
+                    spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
+                        sent_IQ = iq;
+                        IQ_id = sendIQ.bind(this)(iq, callback, errback);
+                    });
+                    var view = _converse.chatboxviews.get('lounge@localhost');
+                    spyOn(view, 'onMessageSubmitted').and.callThrough();
+                    spyOn(view, 'modifyRole').and.callThrough();
+                    spyOn(view, 'showStatusNotification').and.callThrough();
+                    spyOn(view, 'validateRoleChangeCommand').and.callThrough();
+                    view.$el.find('.chat-textarea').text('/mute');
+                    view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13}));
+                    expect(view.onMessageSubmitted).toHaveBeenCalled();
+                    expect(view.validateRoleChangeCommand).toHaveBeenCalled();
+                    expect(view.showStatusNotification).toHaveBeenCalledWith(
+                        "Error: the \"mute\" command takes two arguments, the user's nickname and optionally a reason.",
+                        true
+                    );
+                    expect(view.modifyRole).not.toHaveBeenCalled();
+                    // Call now with the correct amount of arguments.
+                    // XXX: Calling onMessageSubmitted directly, trying
+                    // again via triggering Event doesn't work for some weird
+                    // reason.
+                    view.onMessageSubmitted('/mute annoyingGuy You\'re annoying');
+                    expect(view.validateRoleChangeCommand.calls.count()).toBe(2);
+                    expect(view.showStatusNotification.calls.count()).toBe(1);
+                    expect(view.modifyRole).toHaveBeenCalled();
+                    expect(sent_IQ.toLocaleString()).toBe(
+                        "<iq to='lounge@localhost' type='set' xmlns='jabber:client' id='"+IQ_id+"'>"+
+                            "<query xmlns='http://jabber.org/protocol/muc#admin'>"+
+                                "<item nick='annoyingGuy' role='visitor'>"+
+                                    "<reason>You&apos;re annoying</reason>"+
+                                "</item>"+
+                            "</query>"+
+                        "</iq>");
+                    done();
                 });
                 });
-                test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy');
-                var view = _converse.chatboxviews.get('lounge@localhost');
-                spyOn(view, 'onMessageSubmitted').and.callThrough();
-                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}));
-                expect(view.onMessageSubmitted).toHaveBeenCalled();
-                expect(view.validateRoleChangeCommand).toHaveBeenCalled();
-                expect(view.showStatusNotification).toHaveBeenCalledWith(
-                    "Error: the \"ban\" command takes two arguments, the user's nickname and optionally a reason.",
-                    true
-                );
-                expect(view.setAffiliation).not.toHaveBeenCalled();
-                // Call now with the correct amount of arguments.
-                // XXX: Calling onMessageSubmitted directly, trying
-                // again via triggering Event doesn't work for some weird
-                // reason.
-                view.onMessageSubmitted('/ban annoyingGuy@localhost You\'re annoying');
-                expect(view.validateRoleChangeCommand.calls.count()).toBe(2);
-                expect(view.showStatusNotification.calls.count()).toBe(1);
-                expect(view.setAffiliation).toHaveBeenCalled();
-                // Check that the member list now gets updated
-                expect(sent_IQ.toLocaleString()).toBe(
-                    "<iq to='lounge@localhost' type='set' xmlns='jabber:client' id='"+IQ_id+"'>"+
-                        "<query xmlns='http://jabber.org/protocol/muc#admin'>"+
-                            "<item affiliation='outcast' jid='annoyingGuy@localhost'>"+
-                                "<reason>You&apos;re annoying</reason>"+
-                            "</item>"+
-                        "</query>"+
-                    "</iq>");
-                done();
             }));
             }));
         });
         });
 
 

+ 22 - 15
src/converse-muc.js

@@ -947,7 +947,7 @@
                     const item = $build("item", {nick, role});
                     const item = $build("item", {nick, role});
                     const iq = $iq({to: room, type: "set"}).c("query", {xmlns: Strophe.NS.MUC_ADMIN}).cnode(item.node);
                     const iq = $iq({to: room, type: "set"}).c("query", {xmlns: Strophe.NS.MUC_ADMIN}).cnode(item.node);
                     if (reason !== null) { iq.c("reason", reason); }
                     if (reason !== null) { iq.c("reason", reason); }
-                    return _converse.connection.sendIQ(iq.tree(), onSuccess, onError);
+                    return _converse.connection.sendIQ(iq, onSuccess, onError);
                 },
                 },
 
 
                 validateRoleChangeCommand (command, args) {
                 validateRoleChangeCommand (command, args) {
@@ -1261,7 +1261,8 @@
                     _.each(container_el.children, u.hideElement);
                     _.each(container_el.children, u.hideElement);
                     container_el.insertAdjacentHTML('beforeend', tpl_chatroom_form());
                     container_el.insertAdjacentHTML('beforeend', tpl_chatroom_form());
 
 
-                    const $form = $(container_el).find('form.chatroom-form');
+                    const form = container_el.querySelector('form.chatroom-form');
+                    const $form = $(form);
                     let $fieldset = $form.children('fieldset:first');
                     let $fieldset = $form.children('fieldset:first');
                     const $stanza = $(stanza),
                     const $stanza = $(stanza),
                           $fields = $stanza.find('field'),
                           $fields = $stanza.find('field'),
@@ -1283,12 +1284,15 @@
                         ev.preventDefault();
                         ev.preventDefault();
                         this.closeForm();
                         this.closeForm();
                     });
                     });
-                    $form.on('submit', (ev) => {
-                        ev.preventDefault();
-                        this.saveConfiguration(ev.target).then(
-                            this.getRoomFeatures.bind(this)
-                        );
-                    });
+
+                    form.addEventListener('submit', (ev) => {
+                            ev.preventDefault();
+                            this.saveConfiguration(ev.target).then(
+                                this.getRoomFeatures.bind(this)
+                            );
+                        },
+                        false
+                    );
                 },
                 },
 
 
                 sendConfiguration(config, onSuccess, onError) {
                 sendConfiguration(config, onSuccess, onError) {
@@ -1620,7 +1624,7 @@
                     this.model.save('connection_status', converse.ROOMSTATUS.NICKNAME_REQUIRED);
                     this.model.save('connection_status', converse.ROOMSTATUS.NICKNAME_REQUIRED);
 
 
                     const form_el = this.el.querySelector('.chatroom-form');
                     const form_el = this.el.querySelector('.chatroom-form');
-                    form_el.addEventListener('submit', this.submitNickname.bind(this));
+                    form_el.addEventListener('submit', this.submitNickname.bind(this), false);
                 },
                 },
 
 
                 submitPassword (ev) {
                 submitPassword (ev) {
@@ -1643,7 +1647,8 @@
                         }));
                         }));
 
 
                     this.model.save('connection_status', converse.ROOMSTATUS.PASSWORD_REQUIRED);
                     this.model.save('connection_status', converse.ROOMSTATUS.PASSWORD_REQUIRED);
-                    this.el.querySelector('.chatroom-form').addEventListener('submit', this.submitPassword.bind(this));
+                    this.el.querySelector('.chatroom-form').addEventListener(
+                        'submit', this.submitPassword.bind(this), false);
                 },
                 },
 
 
                 showDisconnectMessage (msg) {
                 showDisconnectMessage (msg) {
@@ -1796,9 +1801,9 @@
                         // occupant model. Doing so avoids showing duplicate
                         // occupant model. Doing so avoids showing duplicate
                         // join messages.
                         // join messages.
                         if (!_.isNull(stat) && stat.textContent) {
                         if (!_.isNull(stat) && stat.textContent) {
-                            return [{'messages': [__(nick+' has joined the room. "'+stat.textContent+'"')]}];
+                            return [{'messages': [__(nick+' has entered the room. "'+stat.textContent+'"')]}];
                         } else {
                         } else {
-                            return [{'messages': [__(nick+' has joined the room.')]}];
+                            return [{'messages': [__(nick+' has entered the room.')]}];
                         }
                         }
                     }
                     }
                 },
                 },
@@ -2382,7 +2387,7 @@
                     if (_.isNull(form)) {
                     if (_.isNull(form)) {
                         return;
                         return;
                     }
                     }
-                    form.addEventListener('submit', this.inviteFormSubmitted.bind(this));
+                    form.addEventListener('submit', this.inviteFormSubmitted.bind(this), false);
                     const el = this.el.querySelector('input.invited-contact');
                     const el = this.el.querySelector('input.invited-contact');
                     const list = _converse.roster.map(function (item) {
                     const list = _converse.roster.map(function (item) {
                             const label = item.get('fullname') || item.get('jid');
                             const label = item.get('fullname') || item.get('jid');
@@ -2494,8 +2499,10 @@
                 },
                 },
 
 
                 onNickChange (model) {
                 onNickChange (model) {
-                    const $nick = this.$el.find('input.new-chatroom-nick');
-                    $nick.val(model.get('nick'));
+                    const nick = this.el.querySelector('input.new-chatroom-nick');
+                    if (!_.isNull(nick)) {
+                        nick.value = model.get('nick');
+                    }
                 },
                 },
 
 
                 informNoRoomsFound () {
                 informNoRoomsFound () {