diff --git a/spec/chatbox.js b/spec/chatbox.js index 6f7a28e10..b6a9162ab 100644 --- a/spec/chatbox.js +++ b/spec/chatbox.js @@ -13,8 +13,6 @@ var $iq = converse.env.$iq; var $msg = converse.env.$msg; var Strophe = converse.env.Strophe; - var Promise = converse.env.Promise; - var moment = converse.env.moment; var u = converse.env.utils; return describe("Chatboxes", function () { @@ -547,1295 +545,6 @@ })); }); - describe("A Chat Message", function () { - - describe("when received from someone else", function () { - - it("will open a chatbox and be displayed inside it", - mock.initConverseWithPromises( - null, ['rosterGroupsFetched'], {}, - function (done, _converse) { - - test_utils.createContacts(_converse, 'current'); - test_utils.openControlBox(); - test_utils.waitUntil(function () { - return $(_converse.rosterview.el).find('.roster-group').length; - }, 300) - .then(function () { - spyOn(_converse, 'emit'); - var message = 'This is a received message'; - var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; - var msg = $msg({ - from: sender_jid, - to: _converse.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(_converse.chatboxes.get(sender_jid)).not.toBeDefined(); - - // onMessage is a handler for received XMPP messages - _converse.chatboxes.onMessage(msg); - expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object)); - - // Check that the chatbox and its view now exist - var chatbox = _converse.chatboxes.get(sender_jid); - var chatboxview = _converse.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); - expect(msg_obj.get('fullname')).toEqual(mock.cur_names[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.querySelector('.chat-content'); - expect(chat_content.querySelector('.chat-msg .chat-msg-text').textContent).toEqual(message); - expect(chat_content.querySelector('.chat-msg-time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy(); - expect(chat_content.querySelector('span.chat-msg-author').textContent).toBe('Max Frankfurter'); - done(); - }); - })); - - describe("when a chatbox is opened for someone who is not in the roster", function () { - - it("the VCard for that user is fetched and the chatbox updated with the results", - mock.initConverseWithPromises( - null, ['rosterGroupsFetched'], {}, - function (done, _converse) { - - _converse.allow_non_roster_messaging = true; - spyOn(_converse, 'emit').and.callThrough(); - - var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; - var vcard_fetched = false; - spyOn(_converse.api.vcard, "get").and.callFake(function () { - vcard_fetched = true; - return Promise.resolve({ - 'fullname': mock.cur_names[0], - 'vcard_updated': moment().format(), - 'jid': sender_jid - }); - }); - var message = 'This is a received message from someone not on the roster'; - var msg = $msg({ - from: sender_jid, - to: _converse.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(_converse.chatboxes.get(sender_jid)).not.toBeDefined(); - - _converse.chatboxes.onMessage(msg); - expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object)); - - // Check that the chatbox and its view now exist - var chatbox = _converse.chatboxes.get(sender_jid); - var chatboxview = _converse.chatboxviews.get(sender_jid); - expect(chatbox).toBeDefined(); - expect(chatboxview).toBeDefined(); - - var author_el = chatboxview.el.querySelector('.chat-msg-author'); - expect(chatbox.get('fullname') === sender_jid); - expect( _.includes(author_el.textContent, 'max.frankfurter@localhost')).toBeTruthy(); - - test_utils.waitUntil(function () { return vcard_fetched; }, 100) - .then(function () { - expect(_converse.api.vcard.get).toHaveBeenCalled(); - return test_utils.waitUntil(function () { - return chatbox.get('fullname') === mock.cur_names[0]; - }, 100); - }).then(function () { - var author_el = chatboxview.el.querySelector('.chat-msg-author'); - expect( _.includes(author_el.textContent, 'Max Frankfurter')).toBeTruthy(); - done(); - }); - })); - }); - - describe("who is not on the roster", function () { - - it("will open a chatbox and be displayed inside it if allow_non_roster_messaging is true", - mock.initConverseWithPromises( - null, ['rosterGroupsFetched'], {}, - function (done, _converse) { - - _converse.allow_non_roster_messaging = false; - - spyOn(_converse, 'emit'); - var message = 'This is a received message from someone not on the roster'; - var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; - var msg = $msg({ - from: sender_jid, - to: _converse.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(_converse.chatboxes.get(sender_jid)).not.toBeDefined(); - - var chatbox = _converse.chatboxes.get(sender_jid); - expect(chatbox).not.toBeDefined(); - - // onMessage is a handler for received XMPP messages - _converse.chatboxes.onMessage(msg); - expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object)); - - // onMessage is a handler for received XMPP messages - _converse.allow_non_roster_messaging =true; - _converse.chatboxes.onMessage(msg); - expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object)); - - // Check that the chatbox and its view now exist - chatbox = _converse.chatboxes.get(sender_jid); - var chatboxview = _converse.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); - expect(msg_obj.get('fullname')).toEqual(undefined); - 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.querySelector('.chat-content'); - expect(chat_content.querySelector('.chat-msg .chat-msg-text').textContent).toEqual(message); - expect(chat_content.querySelector('.chat-msg-time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy(); - expect(chat_content.querySelector('span.chat-msg-author').textContent).toBe('max.frankfurter@localhost'); - done(); - })); - }); - - describe("and for which then an error message is received from the server", function () { - - it("will have the error message displayed after itself", - mock.initConverseWithPromises( - null, ['rosterGroupsFetched'], {}, - function (done, _converse) { - - test_utils.createContacts(_converse, 'current'); - test_utils.openControlBox(); - - // TODO: what could still be done for error - // messages... if the element has type - // "cancel", then we know the messages wasn't sent, - // and can give the user a nicer indication of - // that. - - /* - * yo - * - * - */ - var sender_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost'; - var fullname = _converse.xmppstatus.get('fullname'); - fullname = _.isEmpty(fullname)? _converse.bare_jid: fullname; - _converse.api.chats.open(sender_jid); - var msg_text = 'This message will not be sent, due to an error'; - var view = _converse.chatboxviews.get(sender_jid); - var message = view.model.messages.create({ - 'msgid': '82bc02ce-9651-4336-baf0-fa04762ed8d2', - 'fullname': fullname, - 'sender': 'me', - 'time': moment().format(), - 'message': msg_text - }); - view.model.sendMessage(message); - var $chat_content = $(view.el).find('.chat-content'); - var msg_txt = $chat_content.find('.chat-msg:last').find('.chat-msg-text').text(); - expect(msg_txt).toEqual(msg_text); - - // We send another message, for which an error will - // not be received, to test that errors appear - // after the relevant message. - msg_text = 'This message will be sent, and also receive an error'; - message = view.model.messages.create({ - 'msgid': '6fcdeee3-000f-4ce8-a17e-9ce28f0ae104', - 'fullname': fullname, - 'sender': 'me', - 'time': moment().format(), - 'message': msg_text - }); - view.model.sendMessage(message); - msg_txt = $chat_content.find('.chat-msg:last').find('.chat-msg-text').text(); - expect(msg_txt).toEqual(msg_text); - - /* - * - * - * Server-to-server connection failed: Connecting failed: connection timeout - * - * - */ - var error_txt = 'Server-to-server connection failed: Connecting failed: connection timeout'; - var stanza = $msg({ - 'to': _converse.connection.jid, - 'type':'error', - 'id':'82bc02ce-9651-4336-baf0-fa04762ed8d2', - 'from': sender_jid - }) - .c('error', {'type': 'cancel'}) - .c('remote-server-not-found', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" }).up() - .c('text', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" }) - .t('Server-to-server connection failed: Connecting failed: connection timeout'); - _converse.connection._dataRecv(test_utils.createRequest(stanza)); - expect($chat_content.find('.chat-error').text()).toEqual(error_txt); - - stanza = $msg({ - 'to': _converse.connection.jid, - 'type':'error', - 'id':'some-other-unused-id', - 'from': sender_jid - }) - .c('error', {'type': 'cancel'}) - .c('remote-server-not-found', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" }).up() - .c('text', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" }) - .t('Server-to-server connection failed: Connecting failed: connection timeout'); - _converse.connection._dataRecv(test_utils.createRequest(stanza)); - expect($chat_content.find('.chat-error').length).toEqual(2); - - // If the last message is already an error message, - // then we don't render it another time. - stanza = $msg({ - 'to': _converse.connection.jid, - 'type':'error', - 'id':'another-unused-id', - 'from': sender_jid - }) - .c('error', {'type': 'cancel'}) - .c('remote-server-not-found', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" }).up() - .c('text', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" }) - .t('Server-to-server connection failed: Connecting failed: connection timeout'); - _converse.connection._dataRecv(test_utils.createRequest(stanza)); - expect($chat_content.find('.chat-error').length).toEqual(2); - - // A different error message will however render - stanza = $msg({ - 'to': _converse.connection.jid, - 'type':'error', - 'id':'another-id', - 'from': sender_jid - }) - .c('error', {'type': 'cancel'}) - .c('remote-server-not-found', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" }).up() - .c('text', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" }) - .t('Something else went wrong as well'); - _converse.connection._dataRecv(test_utils.createRequest(stanza)); - expect($chat_content.find('.chat-error').length).toEqual(3); - done(); - })); - }); - - it("will cause the chat area to be scrolled down only if it was at the bottom originally", - mock.initConverseWithPromises( - null, ['rosterGroupsFetched'], {}, - function (done, _converse) { - - test_utils.createContacts(_converse, 'current'); - test_utils.openControlBox(); - - var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; - test_utils.openChatBoxFor(_converse, sender_jid); - - var chatboxview = _converse.chatboxviews.get(sender_jid); - spyOn(chatboxview, 'onScrolledDown').and.callThrough(); - - // Create enough messages so that there's a scrollbar. - var message = 'This message is received while the chat area is scrolled up'; - for (var i=0; i<20; i++) { - _converse.chatboxes.onMessage($msg({ - from: sender_jid, - to: _converse.connection.jid, - type: 'chat', - id: (new Date()).getTime() - }).c('body').t('Message: '+i).up() - .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()); - } - return test_utils.waitUntil(function () { - return chatboxview.content.scrollTop; - }, 1000).then(function () { - return test_utils.waitUntil(function () { - return !chatboxview.model.get('auto_scrolled'); - }, 500); - }).then(function () { - chatboxview.content.scrollTop = 0; - return test_utils.waitUntil(function () { - return chatboxview.model.get('scrolled'); - }, 900); - }).then(function () { - _converse.chatboxes.onMessage($msg({ - from: sender_jid, - to: _converse.connection.jid, - type: 'chat', - id: (new Date()).getTime() - }).c('body').t(message).up() - .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()); - - // Now check that the message appears inside the chatbox in the DOM - var $chat_content = $(chatboxview.el).find('.chat-content'); - var msg_txt = $chat_content.find('.chat-msg:last').find('.chat-msg-text').text(); - expect(msg_txt).toEqual(message); - return test_utils.waitUntil(function () { - return u.isVisible(chatboxview.el.querySelector('.new-msgs-indicator')); - }, 500); - }).then(function () { - expect(chatboxview.model.get('scrolled')).toBe(true); - expect(chatboxview.content.scrollTop).toBe(0); - expect(u.isVisible(chatboxview.el.querySelector('.new-msgs-indicator'))).toBeTruthy(); - // Scroll down again - chatboxview.content.scrollTop = chatboxview.content.scrollHeight; - return test_utils.waitUntil(function () { - return !u.isVisible(chatboxview.el.querySelector('.new-msgs-indicator')); - }, 700); - }).then(done); - })); - - it("is ignored if it's intended for a different resource and filter_by_resource is set to true", - mock.initConverseWithPromises( - null, ['rosterGroupsFetched'], {}, - function (done, _converse) { - - test_utils.createContacts(_converse, 'current'); - test_utils.openControlBox(); - - test_utils.waitUntil(function () { - return $(_converse.rosterview.el).find('.roster-group').length; - }, 300) - .then(function () { - // Send a message from a different resource - var message, sender_jid, msg; - spyOn(_converse, 'log'); - spyOn(_converse.chatboxes, 'getChatBox').and.callThrough(); - _converse.filter_by_resource = true; - sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; - msg = $msg({ - from: sender_jid, - to: _converse.bare_jid+"/some-other-resource", - type: 'chat', - id: (new Date()).getTime() - }).c('body').t("This message will not be shown").up() - .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); - _converse.chatboxes.onMessage(msg); - - expect(_converse.log).toHaveBeenCalledWith( - "onMessage: Ignoring incoming message intended for a different resource: dummy@localhost/some-other-resource", - Strophe.LogLevel.INFO); - expect(_converse.chatboxes.getChatBox).not.toHaveBeenCalled(); - _converse.filter_by_resource = false; - - message = "This message sent to a different resource will be shown"; - msg = $msg({ - from: sender_jid, - to: _converse.bare_jid+"/some-other-resource", - type: 'chat', - id: '134234623462346' - }).c('body').t(message).up() - .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); - _converse.chatboxes.onMessage(msg); - - expect(_converse.chatboxes.getChatBox).toHaveBeenCalled(); - var chatboxview = _converse.chatboxviews.get(sender_jid); - var $chat_content = $(chatboxview.el).find('.chat-content:last'); - var msg_txt = $chat_content.find('.chat-msg').find('.chat-msg-text').text(); - expect(msg_txt).toEqual(message); - done(); - }); - })); - }); - - it("can be received out of order, and will still be displayed in the right order", - mock.initConverseWithPromises( - null, ['rosterGroupsFetched'], {}, - function (done, _converse) { - - - test_utils.createContacts(_converse, 'current'); - test_utils.openControlBox(); - - test_utils.waitUntil(function () { - return $(_converse.rosterview.el).find('.roster-group').length; - }, 300) - .then(function () { - var message, msg; - spyOn(_converse, 'log'); - spyOn(_converse.chatboxes, 'getChatBox').and.callThrough(); - _converse.filter_by_resource = true; - var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; - - /* - * - * - * - * Call me but love, and I'll be new baptized; Henceforth I never will be Romeo. - * - * - * - */ - msg = $msg({'id': 'aeb213', 'to': _converse.bare_jid}) - .c('forwarded', {'xmlns': 'urn:xmpp:forward:0'}) - .c('delay', {'xmlns': 'urn:xmpp:delay', 'stamp':'2018-01-02T13:08:25Z'}).up() - .c('message', { - 'xmlns': 'jabber:client', - 'to': _converse.bare_jid, - 'from': sender_jid, - 'type': 'chat'}) - .c('body').t("message") - .tree(); - _converse.chatboxes.onMessage(msg); - - msg = $msg({'id': 'aeb214', 'to': _converse.bare_jid}) - .c('forwarded', {'xmlns': 'urn:xmpp:forward:0'}) - .c('delay', {'xmlns': 'urn:xmpp:delay', 'stamp':'2017-12-31T22:08:25Z'}).up() - .c('message', { - 'xmlns': 'jabber:client', - 'to': _converse.bare_jid, - 'from': sender_jid, - 'type': 'chat'}) - .c('body').t("Older message") - .tree(); - _converse.chatboxes.onMessage(msg); - - msg = $msg({'id': 'aeb215', 'to': _converse.bare_jid}) - .c('forwarded', {'xmlns': 'urn:xmpp:forward:0'}) - .c('delay', {'xmlns': 'urn:xmpp:delay', 'stamp':'2018-01-01T13:18:23Z'}).up() - .c('message', { - 'xmlns': 'jabber:client', - 'to': _converse.bare_jid, - 'from': sender_jid, - 'type': 'chat'}) - .c('body').t("Inbetween message").up() - .tree(); - _converse.chatboxes.onMessage(msg); - - msg = $msg({'id': 'aeb216', 'to': _converse.bare_jid}) - .c('forwarded', {'xmlns': 'urn:xmpp:forward:0'}) - .c('delay', {'xmlns': 'urn:xmpp:delay', 'stamp':'2018-01-01T13:18:23Z'}).up() - .c('message', { - 'xmlns': 'jabber:client', - 'to': _converse.bare_jid, - 'from': sender_jid, - 'type': 'chat'}) - .c('body').t("another inbetween message") - .tree(); - _converse.chatboxes.onMessage(msg); - - msg = $msg({'id': 'aeb217', 'to': _converse.bare_jid}) - .c('forwarded', {'xmlns': 'urn:xmpp:forward:0'}) - .c('delay', {'xmlns': 'urn:xmpp:delay', 'stamp':'2018-01-02T12:18:23Z'}).up() - .c('message', { - 'xmlns': 'jabber:client', - 'to': _converse.bare_jid, - 'from': sender_jid, - 'type': 'chat'}) - .c('body').t("An earlier message on the next day") - .tree(); - _converse.chatboxes.onMessage(msg); - - msg = $msg({'id': 'aeb218', 'to': _converse.bare_jid}) - .c('forwarded', {'xmlns': 'urn:xmpp:forward:0'}) - .c('delay', {'xmlns': 'urn:xmpp:delay', 'stamp':'2018-01-02T22:28:23Z'}).up() - .c('message', { - 'xmlns': 'jabber:client', - 'to': _converse.bare_jid, - 'from': sender_jid, - 'type': 'chat'}) - .c('body').t("newer message from the next day") - .tree(); - _converse.chatboxes.onMessage(msg); - - // Insert message, to also check that - // text messages are inserted correctly with - // temporary chat events in the chat contents. - msg = $msg({ - 'id': 'aeb219', - 'to': _converse.bare_jid, - 'xmlns': 'jabber:client', - 'from': sender_jid, - 'type': 'chat'}) - .c('composing', {'xmlns': Strophe.NS.CHATSTATES}).up() - .tree(); - _converse.chatboxes.onMessage(msg); - - msg = $msg({ - 'id': 'aeb220', - 'to': _converse.bare_jid, - 'xmlns': 'jabber:client', - 'from': sender_jid, - 'type': 'chat'}) - .c('composing', {'xmlns': Strophe.NS.CHATSTATES}).up() - .c('body').t("latest message") - .tree(); - _converse.chatboxes.onMessage(msg); - - var chatboxview = _converse.chatboxviews.get(sender_jid); - var $chat_content = $(chatboxview.el).find('.chat-content'); - chatboxview.clearSpinner(); //cleanup - - expect($chat_content[0].querySelectorAll('.date-separator').length).toEqual(4); - - var $day = $chat_content.find('.date-separator:first'); - expect($day.data('isodate')).toEqual(moment('2017-12-31T00:00:00').format()); - - var $time = $chat_content.find('time:first'); - expect($time.text()).toEqual('Sunday Dec 31st 2017') - - $day = $chat_content.find('.date-separator:first'); - expect($day[0].nextElementSibling.querySelector('.chat-msg-text').textContent).toBe('Older message'); - - var $el = $chat_content.find('.chat-msg:first').find('.chat-msg-text') - expect($el.text()).toEqual('Older message'); - - $time = $chat_content.find('time:eq(1)'); - expect($time.text()).toEqual("Monday Jan 1st 2018"); - - $day = $chat_content.find('.date-separator:eq(1)'); - expect($day.data('isodate')).toEqual(moment('2018-01-01T00:00:00').format()); - expect($day[0].nextElementSibling.querySelector('.chat-msg-text').textContent).toBe('Inbetween message'); - - $el = $chat_content.find('.chat-msg:eq(1)'); - expect($el.find('.chat-msg-text').text()).toEqual('Inbetween message'); - expect($el[0].nextElementSibling.querySelector('.chat-msg-text').textContent).toEqual('another inbetween message'); - $el = $chat_content.find('.chat-msg:eq(2)'); - expect($el.find('.chat-msg-text').text()).toEqual('another inbetween message'); - - $time = $chat_content.find('time:nth(2)'); - expect($time.text()).toEqual("Tuesday Jan 2nd 2018"); - - $day = $chat_content.find('.date-separator:nth(2)'); - expect($day.data('isodate')).toEqual(moment('2018-01-02T00:00:00').format()); - expect($day[0].nextElementSibling.querySelector('.chat-msg-text').textContent).toBe('An earlier message on the next day'); - - $el = $chat_content.find('.chat-msg:eq(3)'); - expect($el.find('.chat-msg-text').text()).toEqual('An earlier message on the next day'); - - $el = $chat_content.find('.chat-msg:eq(4)'); - expect($el.find('.chat-msg-text').text()).toEqual('message'); - expect($el[0].nextElementSibling.querySelector('.chat-msg-text').textContent).toEqual('newer message from the next day'); - - $day = $chat_content.find('.date-separator:last'); - expect($day.data('isodate')).toEqual(moment().startOf('day').format()); - expect($day[0].nextElementSibling.querySelector('.chat-msg-text').textContent).toBe('latest message'); - done(); - }); - })); - - it("is ignored if it's a malformed headline message", - mock.initConverseWithPromises( - null, ['rosterGroupsFetched'], {}, - function (done, _converse) { - - test_utils.createContacts(_converse, 'current'); - test_utils.openControlBox(); - - /* Ideally we wouldn't have to filter out headline - * messages, but Prosody gives them the wrong 'type' :( - */ - sinon.spy(_converse, 'log'); - sinon.spy(_converse.chatboxes, 'getChatBox'); - sinon.spy(utils, 'isHeadlineMessage'); - var msg = $msg({ - from: 'localhost', - to: _converse.bare_jid, - type: 'chat', - id: (new Date()).getTime() - }).c('body').t("This headline message will not be shown").tree(); - _converse.chatboxes.onMessage(msg); - expect(_converse.log.calledWith( - "onMessage: Ignoring incoming headline message sent with type 'chat' from JID: localhost", - Strophe.LogLevel.INFO - )).toBeTruthy(); - expect(utils.isHeadlineMessage.called).toBeTruthy(); - expect(utils.isHeadlineMessage.returned(true)).toBeTruthy(); - expect(_converse.chatboxes.getChatBox.called).toBeFalsy(); - // Remove sinon spies - _converse.log.restore(); - _converse.chatboxes.getChatBox.restore(); - utils.isHeadlineMessage.restore(); - done(); - })); - - - it("can be a carbon message, as defined in XEP-0280", - mock.initConverseWithPromises( - null, ['rosterGroupsFetched'], {}, - function (done, _converse) { - - test_utils.createContacts(_converse, 'current'); - test_utils.openControlBox(); - - // Send a message from a different resource - spyOn(_converse, 'log'); - var msgtext = 'This is a carbon message'; - var sender_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost'; - var msg = $msg({ - 'from': sender_jid, - 'id': (new Date()).getTime(), - 'to': _converse.connection.jid, - 'type': 'chat', - 'xmlns': 'jabber:client' - }).c('received', {'xmlns': 'urn:xmpp:carbons:2'}) - .c('forwarded', {'xmlns': 'urn:xmpp:forward:0'}) - .c('message', { - 'xmlns': 'jabber:client', - 'from': sender_jid, - 'to': _converse.bare_jid+'/another-resource', - 'type': 'chat' - }).c('body').t(msgtext).tree(); - _converse.chatboxes.onMessage(msg); - - // Check that the chatbox and its view now exist - var chatbox = _converse.chatboxes.get(sender_jid); - var chatboxview = _converse.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(msgtext); - expect(msg_obj.get('fullname')).toEqual(mock.cur_names[1]); - 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.querySelector('.chat-content'); - expect(chat_content.querySelector('.chat-msg .chat-msg-text').textContent).toEqual(msgtext); - expect(chat_content.querySelector('.chat-msg-time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy(); - expect(chat_content.querySelector('span.chat-msg-author').textContent).toBe('Candice van der Knijff'); - done(); - })); - - it("can be a carbon message that this user sent from a different client, as defined in XEP-0280", - mock.initConverseWithPromises( - null, ['rosterGroupsFetched'], {}, - function (done, _converse) { - - var contact, sent_stanza, IQ_id, stanza; - test_utils.waitUntilDiscoConfirmed(_converse, 'localhost', [], ['vcard-temp']) - .then(function () { - return test_utils.waitUntil(function () { - return _converse.xmppstatus.get('fullname'); - }, 300); - }).then(function () { - test_utils.createContacts(_converse, 'current'); - test_utils.openControlBox(); - - // Send a message from a different resource - spyOn(_converse, 'log'); - var msgtext = 'This is a sent carbon message'; - var recipient_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost'; - var msg = $msg({ - 'from': _converse.bare_jid, - 'id': (new Date()).getTime(), - 'to': _converse.connection.jid, - 'type': 'chat', - 'xmlns': 'jabber:client' - }).c('sent', {'xmlns': 'urn:xmpp:carbons:2'}) - .c('forwarded', {'xmlns': 'urn:xmpp:forward:0'}) - .c('message', { - 'xmlns': 'jabber:client', - 'from': _converse.bare_jid+'/another-resource', - 'to': recipient_jid, - 'type': 'chat' - }).c('body').t(msgtext).tree(); - _converse.chatboxes.onMessage(msg); - - // Check that the chatbox and its view now exist - var chatbox = _converse.chatboxes.get(recipient_jid); - var chatboxview = _converse.chatboxviews.get(recipient_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(msgtext); - expect(msg_obj.get('fullname')).toEqual(_converse.xmppstatus.get('fullname')); - expect(msg_obj.get('sender')).toEqual('me'); - expect(msg_obj.get('delayed')).toEqual(false); - // Now check that the message appears inside the chatbox in the DOM - var $chat_content = $(chatboxview.el).find('.chat-content'); - var msg_txt = $chat_content.find('.chat-msg').find('.chat-msg-text').text(); - expect(msg_txt).toEqual(msgtext); - done(); - }); - })); - - it("will be discarded if it's a malicious message meant to look like a carbon copy", - mock.initConverseWithPromises( - null, ['rosterGroupsFetched'], {}, - function (done, _converse) { - - test_utils.createContacts(_converse, 'current'); - test_utils.openControlBox(); - /* - * - * - * - * Please come to Creepy Valley tonight, alone! - * - * - * - * - */ - spyOn(_converse, 'log'); - var msgtext = 'Please come to Creepy Valley tonight, alone!'; - var sender_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost'; - var impersonated_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost'; - var msg = $msg({ - 'from': sender_jid, - 'id': (new Date()).getTime(), - 'to': _converse.connection.jid, - 'type': 'chat', - 'xmlns': 'jabber:client' - }).c('received', {'xmlns': 'urn:xmpp:carbons:2'}) - .c('forwarded', {'xmlns': 'urn:xmpp:forward:0'}) - .c('message', { - 'xmlns': 'jabber:client', - 'from': impersonated_jid, - 'to': _converse.connection.jid, - 'type': 'chat' - }).c('body').t(msgtext).tree(); - _converse.chatboxes.onMessage(msg); - - // Check that chatbox for impersonated user is not created. - var chatbox = _converse.chatboxes.get(impersonated_jid); - expect(chatbox).not.toBeDefined(); - - // Check that the chatbox for the malicous user is not created - chatbox = _converse.chatboxes.get(sender_jid); - expect(chatbox).not.toBeDefined(); - done(); - })); - - it("received for a minimized chat box will increment a counter on its header", - mock.initConverseWithPromises( - null, ['rosterGroupsFetched'], {}, - function (done, _converse) { - - test_utils.createContacts(_converse, 'current'); - test_utils.openControlBox(); - test_utils.waitUntil(function () { - return $(_converse.rosterview.el).find('.roster-group').length; - }, 300) - .then(function () { - var contact_name = mock.cur_names[0]; - var contact_jid = contact_name.replace(/ /g,'.').toLowerCase() + '@localhost'; - - spyOn(_converse, 'emit').and.callThrough(); - test_utils.openChatBoxFor(_converse, contact_jid); - var chatview = _converse.chatboxviews.get(contact_jid); - expect(u.isVisible(chatview.el)).toBeTruthy(); - expect(chatview.model.get('minimized')).toBeFalsy(); - chatview.el.querySelector('.toggle-chatbox-button').click(); - expect(chatview.model.get('minimized')).toBeTruthy(); - var message = 'This message is sent to a minimized chatbox'; - var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; - var msg = $msg({ - from: sender_jid, - to: _converse.connection.jid, - type: 'chat', - id: (new Date()).getTime() - }).c('body').t(message).up() - .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); - _converse.chatboxes.onMessage(msg); - expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object)); - var trimmed_chatboxes = _converse.minimized_chats; - var trimmedview = trimmed_chatboxes.get(contact_jid); - var $count = $(trimmedview.el).find('.message-count'); - expect(u.isVisible(chatview.el)).toBeFalsy(); - expect(trimmedview.model.get('minimized')).toBeTruthy(); - expect(u.isVisible($count[0])).toBeTruthy(); - expect($count.html()).toBe('1'); - _converse.chatboxes.onMessage( - $msg({ - from: mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost', - to: _converse.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() - ); - expect(u.isVisible(chatview.el)).toBeFalsy(); - expect(trimmedview.model.get('minimized')).toBeTruthy(); - $count = $(trimmedview.el).find('.message-count'); - expect(u.isVisible($count[0])).toBeTruthy(); - expect($count.html()).toBe('2'); - trimmedview.el.querySelector('.restore-chat').click(); - expect(trimmed_chatboxes.keys().length).toBe(0); - done(); - }); - })); - - it("will indicate when it has a time difference of more than a day between it and its predecessor", - mock.initConverseWithPromises( - null, ['rosterGroupsFetched'], {}, - function (done, _converse) { - - test_utils.createContacts(_converse, 'current'); - test_utils.openControlBox(); - test_utils.waitUntil(function () { - return $(_converse.rosterview.el).find('.roster-group').length; - }, 300) - .then(function () { - spyOn(_converse, 'emit'); - var contact_name = mock.cur_names[1]; - var contact_jid = contact_name.replace(/ /g,'.').toLowerCase() + '@localhost'; - test_utils.openChatBoxFor(_converse, contact_jid); - test_utils.clearChatBoxMessages(_converse, contact_jid); - var one_day_ago = moment(); - one_day_ago.subtract('days', 1); - var message = 'This is a day old message'; - var chatbox = _converse.chatboxes.get(contact_jid); - var chatboxview = _converse.chatboxviews.get(contact_jid); - var $chat_content = $(chatboxview.el).find('.chat-content'); - var msg_obj; - var msg_txt; - var sender_txt; - - var msg = $msg({ - from: contact_jid, - to: _converse.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(); - _converse.chatboxes.onMessage(msg); - expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object)); - 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); - expect(msg_obj.get('sender')).toEqual('them'); - expect(msg_obj.get('delayed')).toEqual(true); - - var chat_content = chatboxview.el.querySelector('.chat-content'); - expect(chat_content.querySelector('.chat-msg .chat-msg-text').textContent).toEqual(message); - expect(chat_content.querySelector('.chat-msg-time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy(); - expect(chat_content.querySelector('span.chat-msg-author').textContent).toBe('Candice van der Knijff'); - - var $day = $chat_content.find('.date-separator'); - expect($day.length).toEqual(1); - expect($day.attr('class')).toEqual('message date-separator'); - expect($day.data('isodate')).toEqual(moment(one_day_ago.startOf('day')).format()); - - var $time = $chat_content.find('time.separator-text'); - expect($time.text()).toEqual(moment(one_day_ago.startOf('day')).format("dddd MMM Do YYYY")); - - message = 'This is a current message'; - msg = $msg({ - from: contact_jid, - to: _converse.connection.jid, - type: 'chat', - id: new Date().getTime() - }).c('body').t(message).up() - .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); - _converse.chatboxes.onMessage(msg); - expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object)); - // Check that there is a