123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648 |
- /*global mock, converse */
- const { Promise, Strophe, $msg, $pres, sizzle } = converse.env;
- const u = converse.env.utils;
- const original_timeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
- describe("A Groupchat Message", function () {
- beforeEach(() => (jasmine.DEFAULT_TIMEOUT_INTERVAL = 7000));
- afterEach(() => (jasmine.DEFAULT_TIMEOUT_INTERVAL = original_timeout));
- describe("which is succeeded by an error message", function () {
- it("will have the error displayed below it",
- mock.initConverse(
- ['rosterGroupsFetched'], {},
- async function (done, _converse) {
- const muc_jid = 'lounge@montague.lit';
- await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
- const view = _converse.api.chatviews.get(muc_jid);
- const textarea = view.el.querySelector('textarea.chat-textarea');
- textarea.value = 'hello world'
- const enter_event = {
- 'target': textarea,
- 'preventDefault': function preventDefault () {},
- 'stopPropagation': function stopPropagation () {},
- 'keyCode': 13 // Enter
- }
- view.onKeyDown(enter_event);
- await new Promise(resolve => view.model.messages.once('rendered', resolve));
- const msg = view.model.messages.at(0);
- const err_msg_text = "Message rejected because you're sending messages too quickly";
- const error = u.toStanza(`
- <message xmlns="jabber:client" id="${msg.get('msgid')}" from="${muc_jid}" to="${_converse.jid}" type="error">
- <error type="wait">
- <policy-violation xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
- <text xmlns="urn:ietf:params:xml:ns:xmpp-stanzas">${err_msg_text}</text>
- </error>
- <body>hello world</body>
- </message>
- `);
- _converse.connection._dataRecv(mock.createRequest(error));
- expect(await u.waitUntil(() => view.el.querySelector('.chat-msg__error')?.textContent?.trim())).toBe(err_msg_text);
- expect(view.model.messages.length).toBe(1);
- const message = view.model.messages.at(0);
- expect(message.get('received')).toBeUndefined();
- expect(message.get('body')).toBe('hello world');
- expect(message.get('error_text')).toBe(err_msg_text);
- expect(message.get('editable')).toBe(false);
- done();
- }));
- });
- describe("an info message", function () {
- it("is not rendered as a followup message",
- mock.initConverse(
- ['rosterGroupsFetched', 'chatBoxesFetched'], {},
- async function (done, _converse) {
- const muc_jid = 'lounge@montague.lit';
- await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
- const view = _converse.api.chatviews.get(muc_jid);
- let presence = u.toStanza(`
- <presence xmlns="jabber:client" to="${_converse.jid}" from="${muc_jid}/romeo">
- <x xmlns="http://jabber.org/protocol/muc#user">
- <status code="201"/>
- <item role="moderator" affiliation="owner" jid="${_converse.jid}"/>
- <status code="110"/>
- </x>
- </presence>
- `);
- _converse.connection._dataRecv(mock.createRequest(presence));
- await u.waitUntil(() => view.el.querySelectorAll('.chat-info').length === 1);
- presence = u.toStanza(`
- <presence xmlns="jabber:client" to="${_converse.jid}" from="${muc_jid}/romeo1">
- <x xmlns="http://jabber.org/protocol/muc#user">
- <status code="210"/>
- <item role="moderator" affiliation="owner" jid="${_converse.jid}"/>
- <status code="110"/>
- </x>
- </presence>
- `);
- _converse.connection._dataRecv(mock.createRequest(presence));
- await u.waitUntil(() => view.el.querySelectorAll('.chat-info').length === 2);
- const messages = view.el.querySelectorAll('.chat-info');
- expect(u.hasClass('chat-msg--followup', messages[0])).toBe(false);
- expect(u.hasClass('chat-msg--followup', messages[1])).toBe(false);
- done();
- }));
- it("is not shown if its a duplicate",
- mock.initConverse(
- ['rosterGroupsFetched', 'chatBoxesFetched'], {},
- async function (done, _converse) {
- const muc_jid = 'lounge@montague.lit';
- await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
- const view = _converse.api.chatviews.get(muc_jid);
- const presence = u.toStanza(`
- <presence xmlns="jabber:client" to="${_converse.jid}" from="${muc_jid}/romeo">
- <x xmlns="http://jabber.org/protocol/muc#user">
- <status code="201"/>
- <item role="moderator" affiliation="owner" jid="${_converse.jid}"/>
- <status code="110"/>
- </x>
- </presence>
- `);
- // XXX: We wait for createInfoMessages to complete, if we don't
- // we still get two info messages due to messages
- // created from presences not being queued and run
- // sequentially (i.e. by waiting for promises to resolve)
- // like we do with message stanzas.
- spyOn(view.model, 'createInfoMessages').and.callThrough();
- _converse.connection._dataRecv(mock.createRequest(presence));
- await u.waitUntil(() => view.model.createInfoMessages.calls.count());
- await u.waitUntil(() => view.el.querySelectorAll('.chat-info').length === 1);
- _converse.connection._dataRecv(mock.createRequest(presence));
- await u.waitUntil(() => view.model.createInfoMessages.calls.count() === 2);
- expect(view.el.querySelectorAll('.chat-info').length).toBe(1);
- done();
- }));
- });
- it("is rejected if it's an unencapsulated forwarded message",
- mock.initConverse(
- ['rosterGroupsFetched', 'chatBoxesFetched'], {},
- async function (done, _converse) {
- const muc_jid = 'lounge@montague.lit';
- await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
- const impersonated_jid = `${muc_jid}/alice`;
- const received_stanza = u.toStanza(`
- <message to='${_converse.jid}' from='${muc_jid}/mallory' type='groupchat' id='${_converse.connection.getUniqueId()}'>
- <forwarded xmlns='urn:xmpp:forward:0'>
- <delay xmlns='urn:xmpp:delay' stamp='2019-07-10T23:08:25Z'/>
- <message from='${impersonated_jid}'
- id='0202197'
- to='${_converse.bare_jid}'
- type='groupchat'
- xmlns='jabber:client'>
- <body>Yet I should kill thee with much cherishing.</body>
- </message>
- </forwarded>
- </message>
- `);
- const view = _converse.api.chatviews.get(muc_jid);
- spyOn(view.model, 'onMessage').and.callThrough();
- spyOn(converse.env.log, 'error');
- _converse.connection._dataRecv(mock.createRequest(received_stanza));
- await u.waitUntil(() => view.model.onMessage.calls.count() === 1);
- expect(converse.env.log.error).toHaveBeenCalledWith(
- `Ignoring unencapsulated forwarded message from ${muc_jid}/mallory`
- );
- expect(view.el.querySelectorAll('.chat-msg').length).toBe(0);
- expect(view.model.messages.length).toBe(0);
- done();
- }));
- it("can contain a chat state notification and will still be shown",
- mock.initConverse(
- ['rosterGroupsFetched', 'chatBoxesFetched'], {},
- async function (done, _converse) {
- const muc_jid = 'lounge@montague.lit';
- await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
- const view = _converse.api.chatviews.get(muc_jid);
- if (!view.el.querySelectorAll('.chat-area').length) { view.renderChatArea(); }
- const message = 'romeo: Your attention is required';
- const nick = mock.chatroom_names[0],
- msg = $msg({
- from: 'lounge@montague.lit/'+nick,
- id: u.getUniqueId(),
- to: 'romeo@montague.lit',
- type: 'groupchat'
- }).c('body').t(message)
- .c('active', {'xmlns': "http://jabber.org/protocol/chatstates"})
- .tree();
- await view.model.handleMessageStanza(msg);
- await new Promise(resolve => view.model.messages.once('rendered', resolve));
- expect(view.el.querySelector('.chat-msg')).not.toBe(null);
- done();
- }));
- it("can not be expected to have a unique id attribute",
- mock.initConverse(
- ['rosterGroupsFetched', 'chatBoxesFetched'], {},
- async function (done, _converse) {
- const muc_jid = 'lounge@montague.lit';
- await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
- const view = _converse.api.chatviews.get(muc_jid);
- if (!view.el.querySelectorAll('.chat-area').length) { view.renderChatArea(); }
- const id = u.getUniqueId();
- let msg = $msg({
- from: 'lounge@montague.lit/some1',
- id: id,
- to: 'romeo@montague.lit',
- type: 'groupchat'
- }).c('body').t('First message').tree();
- await view.model.handleMessageStanza(msg);
- await u.waitUntil(() => view.el.querySelectorAll('.chat-msg').length === 1);
- msg = $msg({
- from: 'lounge@montague.lit/some2',
- id: id,
- to: 'romeo@montague.lit',
- type: 'groupchat'
- }).c('body').t('Another message').tree();
- await view.model.handleMessageStanza(msg);
- await u.waitUntil(() => view.el.querySelectorAll('.chat-msg').length === 2);
- expect(view.model.messages.length).toBe(2);
- done();
- }));
- it("is ignored if it has the same archive-id of an already received one",
- mock.initConverse(
- ['rosterGroupsFetched'], {},
- async function (done, _converse) {
- const muc_jid = 'room@muc.example.com';
- await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
- const view = _converse.api.chatviews.get(muc_jid);
- spyOn(view.model, 'getDuplicateMessage').and.callThrough();
- let stanza = u.toStanza(`
- <message xmlns="jabber:client"
- from="room@muc.example.com/some1"
- to="${_converse.connection.jid}"
- type="groupchat">
- <body>Typical body text</body>
- <stanza-id xmlns="urn:xmpp:sid:0"
- id="5f3dbc5e-e1d3-4077-a492-693f3769c7ad"
- by="room@muc.example.com"/>
- </message>`);
- _converse.connection._dataRecv(mock.createRequest(stanza));
- await u.waitUntil(() => view.model.messages.length === 1);
- await u.waitUntil(() => view.model.getDuplicateMessage.calls.count() === 1);
- let result = await view.model.getDuplicateMessage.calls.all()[0].returnValue;
- expect(result).toBe(undefined);
- stanza = u.toStanza(`
- <message xmlns="jabber:client"
- to="${_converse.connection.jid}"
- from="room@muc.example.com">
- <result xmlns="urn:xmpp:mam:2" queryid="82d9db27-6cf8-4787-8c2c-5a560263d823" id="5f3dbc5e-e1d3-4077-a492-693f3769c7ad">
- <forwarded xmlns="urn:xmpp:forward:0">
- <delay xmlns="urn:xmpp:delay" stamp="2018-01-09T06:17:23Z"/>
- <message from="room@muc.example.com/some1" type="groupchat">
- <body>Typical body text</body>
- </message>
- </forwarded>
- </result>
- </message>`);
- spyOn(view.model, 'updateMessage');
- view.model.handleMAMResult({ 'messages': [stanza] });
- await u.waitUntil(() => view.model.getDuplicateMessage.calls.count() === 2);
- result = await view.model.getDuplicateMessage.calls.all()[1].returnValue;
- expect(result instanceof _converse.Message).toBe(true);
- expect(view.model.messages.length).toBe(1);
- await u.waitUntil(() => view.model.updateMessage.calls.count());
- done();
- }));
- it("is ignored if it has the same stanza-id of an already received one",
- mock.initConverse(
- ['rosterGroupsFetched'], {},
- async function (done, _converse) {
- const muc_jid = 'room@muc.example.com';
- await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
- const view = _converse.api.chatviews.get(muc_jid);
- spyOn(view.model, 'getStanzaIdQueryAttrs').and.callThrough();
- let stanza = u.toStanza(`
- <message xmlns="jabber:client"
- from="room@muc.example.com/some1"
- to="${_converse.connection.jid}"
- type="groupchat">
- <body>Typical body text</body>
- <stanza-id xmlns="urn:xmpp:sid:0"
- id="5f3dbc5e-e1d3-4077-a492-693f3769c7ad"
- by="room@muc.example.com"/>
- </message>`);
- _converse.connection._dataRecv(mock.createRequest(stanza));
- await u.waitUntil(() => view.model.messages.length === 1);
- await u.waitUntil(() => view.model.getStanzaIdQueryAttrs.calls.count() === 1);
- let result = await view.model.getStanzaIdQueryAttrs.calls.all()[0].returnValue;
- expect(result instanceof Array).toBe(true);
- expect(result[0] instanceof Object).toBe(true);
- expect(result[0]['stanza_id room@muc.example.com']).toBe("5f3dbc5e-e1d3-4077-a492-693f3769c7ad");
- stanza = u.toStanza(`
- <message xmlns="jabber:client"
- from="room@muc.example.com/some1"
- to="${_converse.connection.jid}"
- type="groupchat">
- <body>Typical body text</body>
- <stanza-id xmlns="urn:xmpp:sid:0"
- id="5f3dbc5e-e1d3-4077-a492-693f3769c7ad"
- by="room@muc.example.com"/>
- </message>`);
- spyOn(view.model, 'updateMessage');
- spyOn(view.model, 'getDuplicateMessage').and.callThrough();
- _converse.connection._dataRecv(mock.createRequest(stanza));
- await u.waitUntil(() => view.model.getDuplicateMessage.calls.count());
- result = await view.model.getDuplicateMessage.calls.all()[0].returnValue;
- expect(result instanceof _converse.Message).toBe(true);
- expect(view.model.messages.length).toBe(1);
- await u.waitUntil(() => view.model.updateMessage.calls.count());
- done();
- }));
- it("will be discarded if it's a malicious message meant to look like a carbon copy",
- mock.initConverse(
- ['rosterGroupsFetched'], {},
- async function (done, _converse) {
- await mock.waitForRoster(_converse, 'current');
- await mock.openControlBox(_converse);
- const muc_jid = 'xsf@muc.xmpp.org';
- const sender_jid = `${muc_jid}/romeo`;
- const impersonated_jid = `${muc_jid}/i_am_groot`
- await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
- const stanza = $pres({
- to: 'romeo@montague.lit/_converse.js-29092160',
- from: sender_jid
- })
- .c('x', {xmlns: Strophe.NS.MUC_USER})
- .c('item', {
- 'affiliation': 'owner',
- 'jid': 'newguy@montague.lit/_converse.js-290929789',
- 'role': 'participant'
- }).tree();
- _converse.connection._dataRecv(mock.createRequest(stanza));
- /*
- * <message to="romeo@montague.im/poezio" id="718d40df-3948-4798-a99b-35cc9f03cc4f-641" type="groupchat" from="xsf@muc.xmpp.org/romeo">
- * <received xmlns="urn:xmpp:carbons:2">
- * <forwarded xmlns="urn:xmpp:forward:0">
- * <message xmlns="jabber:client" to="xsf@muc.xmpp.org" type="groupchat" from="xsf@muc.xmpp.org/i_am_groot">
- * <body>I am groot.</body>
- * </message>
- * </forwarded>
- * </received>
- * </message>
- */
- const msg = $msg({
- 'from': sender_jid,
- 'id': _converse.connection.getUniqueId(),
- 'to': _converse.connection.jid,
- 'type': 'groupchat',
- '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': muc_jid,
- 'type': 'groupchat'
- }).c('body').t('I am groot').tree();
- const view = _converse.api.chatviews.get(muc_jid);
- spyOn(converse.env.log, 'error');
- await view.model.handleMAMResult({ 'messages': [msg] });
- await u.waitUntil(() => converse.env.log.error.calls.count());
- expect(converse.env.log.error).toHaveBeenCalledWith(
- 'Invalid Stanza: MUC messages SHOULD NOT be XEP-0280 carbon copied'
- );
- expect(view.el.querySelectorAll('.chat-msg').length).toBe(0);
- expect(view.model.messages.length).toBe(0);
- done();
- }));
- it("keeps track of the sender's role and affiliation",
- mock.initConverse(
- ['rosterGroupsFetched'], {},
- async function (done, _converse) {
- const muc_jid = 'lounge@montague.lit';
- await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
- const view = _converse.api.chatviews.get(muc_jid);
- let msg = $msg({
- from: 'lounge@montague.lit/romeo',
- id: u.getUniqueId(),
- to: 'romeo@montague.lit',
- type: 'groupchat'
- }).c('body').t('I wrote this message!').tree();
- await view.model.handleMessageStanza(msg);
- await u.waitUntil(() => view.el.querySelectorAll('.chat-msg').length);
- expect(view.model.messages.last().occupant.get('affiliation')).toBe('owner');
- expect(view.model.messages.last().occupant.get('role')).toBe('moderator');
- expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
- expect(sizzle('.chat-msg', view.el).pop().classList.value.trim()).toBe('message chat-msg groupchat chat-msg--with-avatar moderator owner');
- let presence = $pres({
- to:'romeo@montague.lit/orchard',
- from:'lounge@montague.lit/romeo',
- id: u.getUniqueId()
- }).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
- .c('item').attrs({
- affiliation: 'member',
- jid: 'romeo@montague.lit/orchard',
- role: 'participant'
- }).up()
- .c('status').attrs({code:'110'}).up()
- .c('status').attrs({code:'210'}).nodeTree;
- _converse.connection._dataRecv(mock.createRequest(presence));
- msg = $msg({
- from: 'lounge@montague.lit/romeo',
- id: u.getUniqueId(),
- to: 'romeo@montague.lit',
- type: 'groupchat'
- }).c('body').t('Another message!').tree();
- await view.model.handleMessageStanza(msg);
- await new Promise(resolve => view.model.messages.once('rendered', resolve));
- expect(view.model.messages.last().occupant.get('affiliation')).toBe('member');
- expect(view.model.messages.last().occupant.get('role')).toBe('participant');
- expect(view.el.querySelectorAll('.chat-msg').length).toBe(2);
- expect(sizzle('.chat-msg', view.el).pop().classList.value.trim()).toBe('message chat-msg groupchat chat-msg--with-avatar participant member');
- presence = $pres({
- to:'romeo@montague.lit/orchard',
- from:'lounge@montague.lit/romeo',
- id: u.getUniqueId()
- }).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
- .c('item').attrs({
- affiliation: 'owner',
- jid: 'romeo@montague.lit/orchard',
- role: 'moderator'
- }).up()
- .c('status').attrs({code:'110'}).up()
- .c('status').attrs({code:'210'}).nodeTree;
- _converse.connection._dataRecv(mock.createRequest(presence));
- view.model.sendMessage('hello world');
- await u.waitUntil(() => view.el.querySelectorAll('.chat-msg').length === 3);
- const occupant = await u.waitUntil(() => view.model.messages.filter(m => m.get('type') === 'groupchat')[2].occupant);
- expect(occupant.get('affiliation')).toBe('owner');
- expect(occupant.get('role')).toBe('moderator');
- expect(view.el.querySelectorAll('.chat-msg').length).toBe(3);
- await u.waitUntil(() => sizzle('.chat-msg', view.el).pop().classList.value.trim() === 'message chat-msg groupchat chat-msg--with-avatar moderator owner');
- const add_events = view.model.occupants._events.add.length;
- msg = $msg({
- from: 'lounge@montague.lit/some1',
- id: u.getUniqueId(),
- to: 'romeo@montague.lit',
- type: 'groupchat'
- }).c('body').t('Message from someone not in the MUC right now').tree();
- await view.model.handleMessageStanza(msg);
- await new Promise(resolve => view.model.messages.once('rendered', resolve));
- expect(view.model.messages.last().occupant).toBeUndefined();
- // Check that there's a new "add" event handler, for when the occupant appears.
- expect(view.model.occupants._events.add.length).toBe(add_events+1);
- // Check that the occupant gets added/removed to the message as it
- // gets removed or added.
- presence = $pres({
- to:'romeo@montague.lit/orchard',
- from:'lounge@montague.lit/some1',
- id: u.getUniqueId()
- }).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
- .c('item').attrs({jid: 'some1@montague.lit/orchard'});
- _converse.connection._dataRecv(mock.createRequest(presence));
- await u.waitUntil(() => view.model.messages.last().occupant);
- expect(view.model.messages.last().get('message')).toBe('Message from someone not in the MUC right now');
- expect(view.model.messages.last().occupant.get('nick')).toBe('some1');
- // Check that the "add" event handler was removed.
- expect(view.model.occupants._events.add.length).toBe(add_events);
- presence = $pres({
- to:'romeo@montague.lit/orchard',
- type: 'unavailable',
- from:'lounge@montague.lit/some1',
- id: u.getUniqueId()
- }).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
- .c('item').attrs({jid: 'some1@montague.lit/orchard'});
- _converse.connection._dataRecv(mock.createRequest(presence));
- await u.waitUntil(() => !view.model.messages.last().occupant);
- expect(view.model.messages.last().get('message')).toBe('Message from someone not in the MUC right now');
- expect(view.model.messages.last().occupant).toBeUndefined();
- // Check that there's a new "add" event handler, for when the occupant appears.
- expect(view.model.occupants._events.add.length).toBe(add_events+1);
- presence = $pres({
- to:'romeo@montague.lit/orchard',
- from:'lounge@montague.lit/some1',
- id: u.getUniqueId()
- }).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
- .c('item').attrs({jid: 'some1@montague.lit/orchard'});
- _converse.connection._dataRecv(mock.createRequest(presence));
- await u.waitUntil(() => view.model.messages.last().occupant);
- expect(view.model.messages.last().get('message')).toBe('Message from someone not in the MUC right now');
- expect(view.model.messages.last().occupant.get('nick')).toBe('some1');
- // Check that the "add" event handler was removed.
- expect(view.model.occupants._events.add.length).toBe(add_events);
- done();
- }));
- it("keeps track whether you are the sender or not",
- mock.initConverse(
- ['rosterGroupsFetched'], {},
- async function (done, _converse) {
- const muc_jid = 'lounge@montague.lit';
- await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
- const view = _converse.api.chatviews.get(muc_jid);
- const msg = $msg({
- from: 'lounge@montague.lit/romeo',
- id: u.getUniqueId(),
- to: 'romeo@montague.lit',
- type: 'groupchat'
- }).c('body').t('I wrote this message!').tree();
- await view.model.handleMessageStanza(msg);
- expect(view.model.messages.last().get('sender')).toBe('me');
- done();
- }));
- it("will be shown as received upon MUC reflection",
- mock.initConverse(
- ['rosterGroupsFetched'], {},
- async function (done, _converse) {
- await mock.waitForRoster(_converse, 'current');
- const muc_jid = 'lounge@montague.lit';
- await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
- const view = _converse.api.chatviews.get(muc_jid);
- const textarea = view.el.querySelector('textarea.chat-textarea');
- textarea.value = 'But soft, what light through yonder airlock breaks?';
- view.onKeyDown({
- target: textarea,
- preventDefault: function preventDefault () {},
- keyCode: 13 // Enter
- });
- await new Promise(resolve => view.model.messages.once('rendered', resolve));
- expect(view.el.querySelectorAll('.chat-msg__body.chat-msg__body--received').length).toBe(0);
- const msg_obj = view.model.messages.at(0);
- const stanza = u.toStanza(`
- <message xmlns="jabber:client"
- from="${msg_obj.get('from')}"
- to="${_converse.connection.jid}"
- type="groupchat">
- <body>${msg_obj.get('message')}</body>
- <stanza-id xmlns="urn:xmpp:sid:0"
- id="5f3dbc5e-e1d3-4077-a492-693f3769c7ad"
- by="lounge@montague.lit"/>
- <origin-id xmlns="urn:xmpp:sid:0" id="${msg_obj.get('origin_id')}"/>
- </message>`);
- await view.model.handleMessageStanza(stanza);
- await u.waitUntil(() => view.el.querySelectorAll('.chat-msg__body.chat-msg__body--received').length, 500);
- expect(view.el.querySelectorAll('.chat-msg__receipt').length).toBe(0);
- expect(view.el.querySelectorAll('.chat-msg__body.chat-msg__body--received').length).toBe(1);
- expect(view.model.messages.length).toBe(1);
- const message = view.model.messages.at(0);
- expect(message.get('stanza_id lounge@montague.lit')).toBe('5f3dbc5e-e1d3-4077-a492-693f3769c7ad');
- expect(message.get('origin_id')).toBe(msg_obj.get('origin_id'));
- done();
- }));
- it("gets updated with its stanza-id upon MUC reflection",
- mock.initConverse(
- ['rosterGroupsFetched'], {},
- async function (done, _converse) {
- const muc_jid = 'room@muc.example.com';
- await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
- const view = _converse.api.chatviews.get(muc_jid);
- view.model.sendMessage('hello world');
- await u.waitUntil(() => view.model.messages.length === 1);
- const msg = view.model.messages.at(0);
- expect(msg.get('stanza_id')).toBeUndefined();
- expect(msg.get('origin_id')).toBe(msg.get('origin_id'));
- const stanza = u.toStanza(`
- <message xmlns="jabber:client"
- from="room@muc.example.com/romeo"
- to="${_converse.connection.jid}"
- type="groupchat">
- <body>Hello world</body>
- <stanza-id xmlns="urn:xmpp:sid:0"
- id="5f3dbc5e-e1d3-4077-a492-693f3769c7ad"
- by="room@muc.example.com"/>
- <origin-id xmlns="urn:xmpp:sid:0" id="${msg.get('origin_id')}"/>
- </message>`);
- spyOn(view.model, 'updateMessage').and.callThrough();
- _converse.connection._dataRecv(mock.createRequest(stanza));
- await u.waitUntil(() => view.model.updateMessage.calls.count() === 1);
- expect(view.model.messages.length).toBe(1);
- expect(view.model.messages.at(0).get('stanza_id room@muc.example.com')).toBe("5f3dbc5e-e1d3-4077-a492-693f3769c7ad");
- expect(view.model.messages.at(0).get('origin_id')).toBe(msg.get('origin_id'));
- done();
- }));
- it("can cause a delivery receipt to be returned",
- mock.initConverse(
- ['rosterGroupsFetched'], {},
- async function (done, _converse) {
- await mock.waitForRoster(_converse, 'current');
- const muc_jid = 'lounge@montague.lit';
- await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
- const view = _converse.api.chatviews.get(muc_jid);
- const textarea = view.el.querySelector('textarea.chat-textarea');
- textarea.value = 'But soft, what light through yonder airlock breaks?';
- view.onKeyDown({
- target: textarea,
- preventDefault: function preventDefault () {},
- keyCode: 13 // Enter
- });
- await new Promise(resolve => view.model.messages.once('rendered', resolve));
- expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
- const msg_obj = view.model.messages.at(0);
- let stanza = u.toStanza(`
- <message xmlns="jabber:client"
- from="${msg_obj.get('from')}"
- to="${_converse.connection.jid}"
- type="groupchat">
- <body>${msg_obj.get('message')}</body>
- <stanza-id xmlns="urn:xmpp:sid:0"
- id="5f3dbc5e-e1d3-4077-a492-693f3769c7ad"
- by="lounge@montague.lit"/>
- <origin-id xmlns="urn:xmpp:sid:0" id="${msg_obj.get('origin_id')}"/>
- </message>`);
- await view.model.handleMessageStanza(stanza);
- await u.waitUntil(() => view.model.messages.last().get('received'));
- stanza = u.toStanza(`
- <message xml:lang="en" to="romeo@montague.lit/orchard"
- from="lounge@montague.lit/some1" type="groupchat" xmlns="jabber:client">
- <received xmlns="urn:xmpp:receipts" id="${msg_obj.get('msgid')}"/>
- <origin-id xmlns="urn:xmpp:sid:0" id="CE08D448-5ED8-4B6A-BB5B-07ED9DFE4FF0"/>
- </message>`);
- _converse.connection._dataRecv(mock.createRequest(stanza));
- expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
- done();
- }));
- });
|