/*global mock, converse */ const Model = converse.env.Model; const { $pres, $iq, Strophe, sizzle, u } = converse.env; describe("Groupchats", function () { describe("The \"rooms\" API", function () { it("has a method 'close' which closes rooms by JID or all rooms when called with no arguments", mock.initConverse([], {}, async function (done, _converse) { await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo'); _converse.connection.IQ_stanzas = []; await mock.openAndEnterChatRoom(_converse, 'leisure@montague.lit', 'romeo'); _converse.connection.IQ_stanzas = []; await mock.openAndEnterChatRoom(_converse, 'news@montague.lit', 'romeo'); expect(u.isVisible(_converse.chatboxviews.get('lounge@montague.lit'))).toBeTruthy(); expect(u.isVisible(_converse.chatboxviews.get('leisure@montague.lit'))).toBeTruthy(); expect(u.isVisible(_converse.chatboxviews.get('news@montague.lit'))).toBeTruthy(); await _converse.api.roomviews.close('lounge@montague.lit'); expect(_converse.chatboxviews.get('lounge@montague.lit')).toBeUndefined(); expect(u.isVisible(_converse.chatboxviews.get('leisure@montague.lit'))).toBeTruthy(); expect(u.isVisible(_converse.chatboxviews.get('news@montague.lit'))).toBeTruthy(); await _converse.api.roomviews.close(['leisure@montague.lit', 'news@montague.lit']); expect(_converse.chatboxviews.get('lounge@montague.lit')).toBeUndefined(); expect(_converse.chatboxviews.get('leisure@montague.lit')).toBeUndefined(); expect(_converse.chatboxviews.get('news@montague.lit')).toBeUndefined(); await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo'); await mock.openAndEnterChatRoom(_converse, 'leisure@montague.lit', 'romeo'); expect(u.isVisible(_converse.chatboxviews.get('lounge@montague.lit'))).toBeTruthy(); expect(u.isVisible(_converse.chatboxviews.get('leisure@montague.lit'))).toBeTruthy(); await _converse.api.roomviews.close(); expect(_converse.chatboxviews.get('lounge@montague.lit')).toBeUndefined(); expect(_converse.chatboxviews.get('leisure@montague.lit')).toBeUndefined(); done(); })); it("has a method 'get' which returns a wrapped groupchat (if it exists)", mock.initConverse([], {}, async function (done, _converse) { await mock.waitForRoster(_converse, 'current'); const rosterview = document.querySelector('converse-roster'); await u.waitUntil(() => rosterview.querySelectorAll('.roster-group .group-toggle').length, 300); let muc_jid = 'chillout@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); let room = await _converse.api.rooms.get(muc_jid); expect(room instanceof Object).toBeTruthy(); let chatroomview = _converse.chatboxviews.get(muc_jid); expect(chatroomview.is_chatroom).toBeTruthy(); expect(u.isVisible(chatroomview)).toBeTruthy(); await chatroomview.close(); // Test with mixed case muc_jid = 'Leisure@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); room = await _converse.api.rooms.get(muc_jid); expect(room instanceof Object).toBeTruthy(); chatroomview = _converse.chatboxviews.get(muc_jid.toLowerCase()); expect(u.isVisible(chatroomview)).toBeTruthy(); muc_jid = 'leisure@montague.lit'; room = await _converse.api.rooms.get(muc_jid); expect(room instanceof Object).toBeTruthy(); chatroomview = _converse.chatboxviews.get(muc_jid.toLowerCase()); expect(u.isVisible(chatroomview)).toBeTruthy(); muc_jid = 'leiSure@montague.lit'; room = await _converse.api.rooms.get(muc_jid); expect(room instanceof Object).toBeTruthy(); chatroomview = _converse.chatboxviews.get(muc_jid.toLowerCase()); expect(u.isVisible(chatroomview)).toBeTruthy(); chatroomview.close(); // Non-existing room muc_jid = 'chillout2@montague.lit'; room = await _converse.api.rooms.get(muc_jid); expect(room).toBe(null); done(); })); it("has a method 'open' which opens (optionally configures) and returns a wrapped chat box", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) { // Mock 'getDiscoInfo', otherwise the room won't be // displayed as it waits first for the features to be returned // (when it's a new room being created). spyOn(_converse.ChatRoom.prototype, 'getDiscoInfo').and.callFake(() => Promise.resolve()); let jid = 'lounge@montague.lit'; let chatroomview, IQ_id; await mock.openControlBox(_converse); await mock.waitForRoster(_converse, 'current'); const rosterview = document.querySelector('converse-roster'); await u.waitUntil(() => rosterview.querySelectorAll('.roster-group .group-toggle').length); let room = await _converse.api.rooms.open(jid); // Test on groupchat that's not yet open expect(room instanceof Model).toBeTruthy(); chatroomview = _converse.chatboxviews.get(jid); expect(chatroomview.is_chatroom).toBeTruthy(); await u.waitUntil(() => u.isVisible(chatroomview)); // Test again, now that the room exists. room = await _converse.api.rooms.open(jid); expect(room instanceof Model).toBeTruthy(); chatroomview = _converse.chatboxviews.get(jid); expect(chatroomview.is_chatroom).toBeTruthy(); expect(u.isVisible(chatroomview)).toBeTruthy(); await chatroomview.close(); // Test with mixed case in JID jid = 'Leisure@montague.lit'; room = await _converse.api.rooms.open(jid); expect(room instanceof Model).toBeTruthy(); chatroomview = _converse.chatboxviews.get(jid.toLowerCase()); await u.waitUntil(() => u.isVisible(chatroomview)); jid = 'leisure@montague.lit'; room = await _converse.api.rooms.open(jid); expect(room instanceof Model).toBeTruthy(); chatroomview = _converse.chatboxviews.get(jid.toLowerCase()); await u.waitUntil(() => u.isVisible(chatroomview)); jid = 'leiSure@montague.lit'; room = await _converse.api.rooms.open(jid); expect(room instanceof Model).toBeTruthy(); chatroomview = _converse.chatboxviews.get(jid.toLowerCase()); await u.waitUntil(() => u.isVisible(chatroomview)); chatroomview.close(); _converse.muc_instant_rooms = false; const sendIQ = _converse.connection.sendIQ; spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) { IQ_id = sendIQ.bind(this)(iq, callback, errback); }); // Test with configuration room = await _converse.api.rooms.open('room@conference.example.org', { 'nick': 'some1', 'auto_configure': true, 'roomconfig': { 'getmemberlist': ['moderator', 'participant'], 'changesubject': false, 'membersonly': true, 'persistentroom': true, 'publicroom': true, 'roomdesc': 'Welcome to this groupchat', 'whois': 'anyone' } }); expect(room instanceof Model).toBeTruthy(); chatroomview = _converse.chatboxviews.get('room@conference.example.org'); // We pretend this is a new room, so no disco info is returned. const features_stanza = $iq({ from: 'room@conference.example.org', 'id': IQ_id, 'to': 'romeo@montague.lit/desktop', 'type': 'error' }).c('error', {'type': 'cancel'}) .c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"}); _converse.connection._dataRecv(mock.createRequest(features_stanza)); /* * * * * * * */ const presence = $pres({ from:'room@conference.example.org/some1', to:'romeo@montague.lit/pda' }) .c('x', {xmlns:'http://jabber.org/protocol/muc#user'}) .c('item', { affiliation: 'owner', jid: 'romeo@montague.lit/pda', role: 'moderator' }).up() .c('status', {code:'110'}).up() .c('status', {code:'201'}); _converse.connection._dataRecv(mock.createRequest(presence)); expect(_converse.connection.sendIQ).toHaveBeenCalled(); const IQ_stanzas = _converse.connection.IQ_stanzas; const iq = await u.waitUntil(() => IQ_stanzas.filter(s => s.querySelector(`query[xmlns="${Strophe.NS.MUC_OWNER}"]`)).pop()); expect(Strophe.serialize(iq)).toBe( ``+ ``); const node = u.toStanza(` Configuration for room@conference.example.org Complete and submit this form to configure the room. http://jabber.org/protocol/muc#roomconfig Room 1 moderator participant visitor 20 `); spyOn(chatroomview.model, 'sendConfiguration').and.callThrough(); _converse.connection._dataRecv(mock.createRequest(node)); await u.waitUntil(() => chatroomview.model.sendConfiguration.calls.count() === 1); const sent_stanza = IQ_stanzas.filter(s => s.getAttribute('type') === 'set').pop(); expect(sizzle('field[var="muc#roomconfig_roomname"] value', sent_stanza).pop().textContent.trim()).toBe('Room'); expect(sizzle('field[var="muc#roomconfig_roomdesc"] value', sent_stanza).pop().textContent.trim()).toBe('Welcome to this groupchat'); expect(sizzle('field[var="muc#roomconfig_persistentroom"] value', sent_stanza).pop().textContent.trim()).toBe('1'); expect(sizzle('field[var="muc#roomconfig_getmemberlist"] value', sent_stanza).map(e => e.textContent.trim()).join(' ')).toBe('moderator participant'); expect(sizzle('field[var="muc#roomconfig_publicroom"] value ', sent_stanza).pop().textContent.trim()).toBe('1'); expect(sizzle('field[var="muc#roomconfig_changesubject"] value', sent_stanza).pop().textContent.trim()).toBe('0'); expect(sizzle('field[var="muc#roomconfig_whois"] value ', sent_stanza).pop().textContent.trim()).toBe('anyone'); expect(sizzle('field[var="muc#roomconfig_membersonly"] value', sent_stanza).pop().textContent.trim()).toBe('1'); expect(sizzle('field[var="muc#roomconfig_historylength"] value', sent_stanza).pop().textContent.trim()).toBe('20'); done(); })); }); });