Browse Source

Fixes #472 Cannot read property 'splitOnce' of undefined

JC Brand 9 years ago
parent
commit
12d6785d02
3 changed files with 92 additions and 3 deletions
  1. 27 2
      converse.js
  2. 2 1
      docs/CHANGES.rst
  3. 63 0
      spec/chatroom.js

+ 27 - 2
converse.js

@@ -2896,6 +2896,21 @@
                 return this.setAffiliation(room, jid, 'admin', reason, handler_cb, error_cb);
             },
 
+            validateRoleChangeCommand: function (command, args) {
+                /* Check that a command to change a chat room user's role or
+                 * affiliation has anough arguments.
+                 */
+                // TODO check if first argument is valid
+                if (args.length < 1 || args.length > 2) {
+                    this.showStatusNotification(
+                        __("Error: the \""+command+"\" command takes two arguments, the user's nickname and optionally a reason."),
+                        true
+                    );
+                    return false;
+                }
+                return true;
+            },
+
             onChatRoomMessageSubmitted: function (text) {
                 /* Gets called when the user presses enter to send off a
                  * message in a chat room.
@@ -2903,15 +2918,17 @@
                  * Parameters:
                  *    (String) text - The message text.
                  */
-                var match = text.replace(/^\s*/, "").match(/^\/(.*?)(?: (.*))?$/) || [false, '', ''];
-                var args = match[2].splitOnce(' ');
+                var match = text.replace(/^\s*/, "").match(/^\/(.*?)(?: (.*))?$/) || [false, '', ''],
+                    args = match[2] && match[2].splitOnce(' ') || [];
                 switch (match[1]) {
                     case 'admin':
+                        if (!this.validateRoleChangeCommand(match[1], args)) { break; }
                         this.setAffiliation(
                                 this.model.get('jid'), args[0], 'admin', args[1],
                                 undefined, this.onCommandError.bind(this));
                         break;
                     case 'ban':
+                        if (!this.validateRoleChangeCommand(match[1], args)) { break; }
                         this.setAffiliation(
                                 this.model.get('jid'), args[0], 'outcast', args[1],
                                 undefined, this.onCommandError.bind(this));
@@ -2920,6 +2937,7 @@
                         this.clearChatRoomMessages();
                         break;
                     case 'deop':
+                        if (!this.validateRoleChangeCommand(match[1], args)) { break; }
                         this.modifyRole(
                                 this.model.get('jid'), args[0], 'participant', args[1],
                                 undefined, this.onCommandError.bind(this));
@@ -2944,16 +2962,19 @@
                         ]);
                         break;
                     case 'kick':
+                        if (!this.validateRoleChangeCommand(match[1], args)) { break; }
                         this.modifyRole(
                                 this.model.get('jid'), args[0], 'none', args[1],
                                 undefined, this.onCommandError.bind(this));
                         break;
                     case 'mute':
+                        if (!this.validateRoleChangeCommand(match[1], args)) { break; }
                         this.modifyRole(
                                 this.model.get('jid'), args[0], 'visitor', args[1],
                                 undefined, this.onCommandError.bind(this));
                         break;
                     case 'member':
+                        if (!this.validateRoleChangeCommand(match[1], args)) { break; }
                         this.setAffiliation(
                                 this.model.get('jid'), args[0], 'member', args[1],
                                 undefined, this.onCommandError.bind(this));
@@ -2966,16 +2987,19 @@
                         }).tree());
                         break;
                     case 'owner':
+                        if (!this.validateRoleChangeCommand(match[1], args)) { break; }
                         this.setAffiliation(
                                 this.model.get('jid'), args[0], 'owner', args[1],
                                 undefined, this.onCommandError.bind(this));
                         break;
                     case 'op':
+                        if (!this.validateRoleChangeCommand(match[1], args)) { break; }
                         this.modifyRole(
                                 this.model.get('jid'), args[0], 'moderator', args[1],
                                 undefined, this.onCommandError.bind(this));
                         break;
                     case 'revoke':
+                        if (!this.validateRoleChangeCommand(match[1], args)) { break; }
                         this.setAffiliation(
                                 this.model.get('jid'), args[0], 'none', args[1],
                                 undefined, this.onCommandError.bind(this));
@@ -2990,6 +3014,7 @@
                         );
                         break;
                     case 'voice':
+                        if (!this.validateRoleChangeCommand(match[1], args)) { break; }
                         this.modifyRole(
                                 this.model.get('jid'), args[0], 'participant', args[1],
                                 undefined, this.onCommandError.bind(this));

+ 2 - 1
docs/CHANGES.rst

@@ -4,11 +4,12 @@ Changelog
 0.9.6 (Unreleased)
 ------------------
 
+* Bugfix. Spinner doesn't disappear when scrolling up (when server doesn't support XEP-0313). [jcbrand]
 * #462 Fix MUC rooms with names containing special characters not working [1st8]
 * #468 Fix [object Object] being sometimes shown as status [1st8]
+* #472 Fix "Cannot read property 'splitOnce' of undefined" when typing /clear in a chat room. [jcbrand]
 * #493 Roster wasn't being updated after a Roster push update [teseo, jcbrand]
 * #496 Bugfix. Pings weren't being sent out. [teseo, jcbrand]
-* Bugfix. Spinner doesn't disappear when scrolling up (when server doesn't support XEP-0313). [jcbrand]
 
 0.9.5 (2015-08-24)
 ------------------

+ 63 - 0
spec/chatroom.js

@@ -14,6 +14,13 @@
     var Strophe = converse_api.env.Strophe;
 
     return describe("ChatRooms", function (mock, test_utils) {
+        beforeEach(function () {
+            runs(function () {
+                test_utils.closeAllChatBoxes();
+                test_utils.clearBrowserStorage();
+            });
+        });
+
         describe("A Chat Room", function () {
             beforeEach(function () {
                 runs(function () {
@@ -478,6 +485,62 @@
                 }.bind(converse));
             }.bind(converse));
         }.bind(converse));
+        
+        
+        describe("Each chat room can take special commands", function () {
+            beforeEach(function () {
+                runs(function () {
+                    test_utils.closeAllChatBoxes();
+                    test_utils.clearBrowserStorage();
+                });
+            });
+
+            it("to clear messages", function () {
+                test_utils.openChatRoom('lounge', 'localhost', 'dummy');
+                var view = converse.chatboxviews.get('lounge@localhost'),
+                    chatroom = view.model,
+                    $chat_content = view.$el.find('.chat-content');
+
+                spyOn(view, 'onChatRoomMessageSubmitted').andCallThrough();
+                spyOn(view, 'clearChatRoomMessages');
+                view.$el.find('.chat-textarea').text('/clear');
+                view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13}));
+                expect(view.onChatRoomMessageSubmitted).toHaveBeenCalled();
+                expect(view.clearChatRoomMessages).toHaveBeenCalled();
+
+            });
+
+            it("to ban a user", function () {
+                test_utils.openChatRoom('lounge', 'localhost', 'dummy');
+                var view = converse.chatboxviews.get('lounge@localhost'),
+                    chatroom = view.model,
+                    $chat_content = view.$el.find('.chat-content');
+
+                spyOn(view, 'onChatRoomMessageSubmitted').andCallThrough();
+                spyOn(view, 'setAffiliation').andCallThrough();
+                spyOn(view, 'showStatusNotification').andCallThrough();
+                spyOn(view, 'validateRoleChangeCommand').andCallThrough();
+                view.$el.find('.chat-textarea').text('/ban');
+                view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13}));
+                expect(view.onChatRoomMessageSubmitted).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 onChatRoomMessageSubmitted directly, trying
+                // again via triggering Event doesn't work for some weird
+                // reason.
+                view.onChatRoomMessageSubmitted('/ban jid This is the reason');
+                expect(view.validateRoleChangeCommand.callCount).toBe(2);
+                expect(view.showStatusNotification.callCount).toBe(1);
+                expect(view.setAffiliation).toHaveBeenCalled();
+            });
+
+        }.bind(converse));
 
         describe("When attempting to enter a chatroom", function () {
             beforeEach(function () {