(function (root, factory) { define([ "mock", "utils" ], function (mock, utils) { return factory(mock, utils); } ); } (this, function (mock, utils) { return describe("Chatboxes", $.proxy(function(mock, utils) { describe("A Chatbox", $.proxy(function () { beforeEach(function () { runs(function () { utils.closeAllChatBoxes(); utils.removeControlBox(); converse.roster.browserStorage._clear(); utils.initConverse(); utils.createCurrentContacts(); utils.openControlBox(); utils.openContactsPanel(); }); }); it("is created when you click on a roster item", $.proxy(function () { var i, $el, click, jid, view, chatboxview; // openControlBox was called earlier, so the controlbox is // visible, but no other chat boxes have been created. expect(this.chatboxes.length).toEqual(1); spyOn(this.chatboxviews, 'trimChats'); expect($("#conversejs .chatbox").length).toBe(1); // Controlbox is open var online_contacts = this.rosterview.$el.find('dt#xmpp-contacts').siblings('dd.current-xmpp-contact').find('a.open-chat'); for (i=0; i:)'); expect($($items[6]).children('a').data('emoticon')).toBe(':S'); expect($($items[7]).children('a').data('emoticon')).toBe(':\\'); expect($($items[8]).children('a').data('emoticon')).toBe('>:('); expect($($items[9]).children('a').data('emoticon')).toBe(':('); expect($($items[10]).children('a').data('emoticon')).toBe(':O'); expect($($items[11]).children('a').data('emoticon')).toBe('(^.^)b'); expect($($items[12]).children('a').data('emoticon')).toBe('<3'); $items.first().click(); }); waits(250); runs(function () { expect(view.insertEmoticon).toHaveBeenCalled(); expect($textarea.val()).toBe(':) '); expect(view.$el.find('.toggle-smiley ul').is(':visible')).toBeFalsy(); $toolbar.children('li.toggle-smiley').click(); }); waits(250); runs(function () { expect(view.toggleEmoticonMenu).toHaveBeenCalled(); expect(view.$el.find('.toggle-smiley ul').is(':visible')).toBeTruthy(); view.$el.find('.toggle-smiley ul').children('li').last().click(); }); waits(250); runs(function () { expect(view.insertEmoticon).toHaveBeenCalled(); expect(view.$el.find('.toggle-smiley ul').is(':visible')).toBeFalsy(); expect($textarea.val()).toBe(':) <3 '); }); }, converse)); it("contains a button for starting an encrypted chat session", $.proxy(function () { // TODO: More tests can be added here... var contact_jid = mock.cur_names[2].replace(' ','.').toLowerCase() + '@localhost'; utils.openChatBoxFor(contact_jid); var view = this.chatboxviews.get(contact_jid); var $toolbar = view.$el.find('ul.chat-toolbar'); expect($toolbar.children('li.toggle-otr').length).toBe(1); // Register spies spyOn(view, 'toggleOTRMenu').andCallThrough(); view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called runs(function () { $toolbar.children('li.toggle-otr').click(); }); waits(250); runs(function () { expect(view.toggleOTRMenu).toHaveBeenCalled(); var $menu = view.$el.find('.toggle-otr ul'); expect($menu.is(':visible')).toBeTruthy(); expect($menu.children('li').length).toBe(2); }); }, converse)); it("can contain a button for starting a call", $.proxy(function () { var view, callButton, $toolbar; var contact_jid = mock.cur_names[2].replace(' ','.').toLowerCase() + '@localhost'; spyOn(converse, 'emit'); // First check that the button doesn't show if it's not enabled // via "visible_toolbar_buttons" converse.visible_toolbar_buttons.call = false; utils.openChatBoxFor(contact_jid); view = this.chatboxviews.get(contact_jid); $toolbar = view.$el.find('ul.chat-toolbar'); callButton = $toolbar.find('.toggle-call'); expect(callButton.length).toBe(0); view.close(); // Now check that it's shown if enabled and that it emits // onCallButtonClicked converse.visible_toolbar_buttons.call = true; // enable the button utils.openChatBoxFor(contact_jid); view = this.chatboxviews.get(contact_jid); $toolbar = view.$el.find('ul.chat-toolbar'); callButton = $toolbar.find('.toggle-call'); expect(callButton.length).toBe(1); callButton.click(); expect(converse.emit).toHaveBeenCalledWith('onCallButtonClicked', jasmine.any(Object)); }, converse)); it("can contain a button for clearing messages", $.proxy(function () { var view, clearButton, $toolbar; var contact_jid = mock.cur_names[2].replace(' ','.').toLowerCase() + '@localhost'; // First check that the button doesn't show if it's not enabled // via "visible_toolbar_buttons" converse.visible_toolbar_buttons.clear = false; utils.openChatBoxFor(contact_jid); view = this.chatboxviews.get(contact_jid); view = this.chatboxviews.get(contact_jid); $toolbar = view.$el.find('ul.chat-toolbar'); clearButton = $toolbar.find('.toggle-clear'); expect(clearButton.length).toBe(0); view.close(); // Now check that it's shown if enabled and that it calls // clearMessages converse.visible_toolbar_buttons.clear = true; // enable the button utils.openChatBoxFor(contact_jid); view = this.chatboxviews.get(contact_jid); $toolbar = view.$el.find('ul.chat-toolbar'); clearButton = $toolbar.find('.toggle-clear'); expect(clearButton.length).toBe(1); spyOn(view, 'clearMessages'); view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called clearButton.click(); expect(view.clearMessages).toHaveBeenCalled(); }, converse)); }, converse)); describe("A Chat Message", $.proxy(function () { beforeEach(function () { runs(function () { utils.closeAllChatBoxes(); }); waits(250); runs(function () {}); }); it("can be received which will open a chatbox and be displayed inside it", $.proxy(function () { spyOn(converse, 'emit'); var message = 'This is a received message'; var sender_jid = mock.cur_names[0].replace(' ','.').toLowerCase() + '@localhost'; msg = $msg({ from: sender_jid, to: this.connection.jid, type: 'chat', id: (new Date()).getTime() }).c('body').t(message).up() .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); // We don't already have an open chatbox for this user expect(this.chatboxes.get(sender_jid)).not.toBeDefined(); runs($.proxy(function () { // onMessage is a handler for received XMPP messages this.chatboxes.onMessage(msg); expect(converse.emit).toHaveBeenCalledWith('onMessage', msg); }, converse)); waits(250); runs($.proxy(function () { // Check that the chatbox and its view now exist var chatbox = this.chatboxes.get(sender_jid); var chatboxview = this.chatboxviews.get(sender_jid); expect(chatbox).toBeDefined(); expect(chatboxview).toBeDefined(); // Check that the message was received and check the // message parameters expect(chatbox.messages.length).toEqual(1); var msg_obj = chatbox.messages.models[0]; expect(msg_obj.get('message')).toEqual(message); // XXX: This is stupid, fullname is actually only the // users first name expect(msg_obj.get('fullname')).toEqual(mock.cur_names[0].split(' ')[0]); expect(msg_obj.get('sender')).toEqual('them'); expect(msg_obj.get('delayed')).toEqual(false); // Now check that the message appears inside the // chatbox in the DOM var $chat_content = chatboxview.$el.find('.chat-content'); var msg_txt = $chat_content.find('.chat-message').find('.chat-message-content').text(); expect(msg_txt).toEqual(message); var sender_txt = $chat_content.find('span.chat-message-them').text(); expect(sender_txt.match(/^[0-9][0-9]:[0-9][0-9] /)).toBeTruthy(); }, converse)); }, converse)); it("received for a minimized chat box will increment a counter on its header", $.proxy(function () { var contact_name = mock.cur_names[0]; var contact_jid = contact_name.replace(' ','.').toLowerCase() + '@localhost'; spyOn(this, 'emit'); runs(function () { utils.openChatBoxFor(contact_jid); var chatview = converse.chatboxviews.get(contact_jid); expect(chatview.model.get('minimized')).toBeFalsy(); chatview.$el.find('.toggle-chatbox-button').click(); }); waits(50); runs($.proxy(function () { var chatview = this.chatboxviews.get(contact_jid); expect(chatview.model.get('minimized')).toBeTruthy(); var message = 'This message is sent to a minimized chatbox'; var sender_jid = mock.cur_names[0].replace(' ','.').toLowerCase() + '@localhost'; msg = $msg({ from: sender_jid, to: this.connection.jid, type: 'chat', id: (new Date()).getTime() }).c('body').t(message).up() .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); this.chatboxes.onMessage(msg); expect(this.emit).toHaveBeenCalledWith('onMessage', msg); }, converse)); waits(50); runs($.proxy(function () { var trimmed_chatboxes = this.minimized_chats; var trimmedview = trimmed_chatboxes.get(contact_jid); var $count = trimmedview.$el.find('.chat-head-message-count'); expect(trimmedview.model.get('minimized')).toBeTruthy(); expect($count.is(':visible')).toBeTruthy(); expect($count.html()).toBe('1'); this.chatboxes.onMessage( $msg({ from: mock.cur_names[0].replace(' ','.').toLowerCase() + '@localhost', to: this.connection.jid, type: 'chat', id: (new Date()).getTime() }).c('body').t('This message is also sent to a minimized chatbox').up() .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree() ); }, converse)); waits(50); runs($.proxy(function () { var trimmed_chatboxes = this.minimized_chats; var trimmedview = trimmed_chatboxes.get(contact_jid); var $count = trimmedview.$el.find('.chat-head-message-count'); expect(trimmedview.model.get('minimized')).toBeTruthy(); expect($count.is(':visible')).toBeTruthy(); expect($count.html()).toBe('2'); trimmedview.$el.find('.restore-chat').click(); }, converse)); waits(250); runs($.proxy(function () { var trimmed_chatboxes = this.minimized_chats; expect(trimmed_chatboxes.keys().length).toBe(0); }, converse)); }, converse)); it("will indicate when it has a time difference of more than a day between it and its predecessor", $.proxy(function () { spyOn(converse, 'emit'); var contact_name = mock.cur_names[1]; var contact_jid = contact_name.replace(' ','.').toLowerCase() + '@localhost'; utils.openChatBoxFor(contact_jid); utils.clearChatBoxMessages(contact_jid); var one_day_ago = moment(); one_day_ago.subtract('days', 1); var message = 'This is a day old message'; var chatbox = this.chatboxes.get(contact_jid); var chatboxview = this.chatboxviews.get(contact_jid); var $chat_content = chatboxview.$el.find('.chat-content'); var msg_obj; var msg_txt; var sender_txt; var msg = $msg({ from: contact_jid, to: this.connection.jid, type: 'chat', id: one_day_ago.unix() }).c('body').t(message).up() .c('delay', { xmlns:'urn:xmpp:delay', from: 'localhost', stamp: one_day_ago.format() }) .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); this.chatboxes.onMessage(msg); expect(converse.emit).toHaveBeenCalledWith('onMessage', msg); expect(chatbox.messages.length).toEqual(1); msg_obj = chatbox.messages.models[0]; expect(msg_obj.get('message')).toEqual(message); expect(msg_obj.get('fullname')).toEqual(contact_name.split(' ')[0]); expect(msg_obj.get('sender')).toEqual('them'); expect(msg_obj.get('delayed')).toEqual(true); msg_txt = $chat_content.find('.chat-message').find('.chat-message-content').text(); expect(msg_txt).toEqual(message); sender_txt = $chat_content.find('span.chat-message-them').text(); expect(sender_txt.match(/^[0-9][0-9]:[0-9][0-9] /)).toBeTruthy(); message = 'This is a current message'; msg = $msg({ from: contact_jid, to: this.connection.jid, type: 'chat', id: new Date().getTime() }).c('body').t(message).up() .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); this.chatboxes.onMessage(msg); expect(converse.emit).toHaveBeenCalledWith('onMessage', msg); // Check that there is a