|
@@ -1,6 +1,6 @@
|
|
|
/* global mock, converse */
|
|
|
|
|
|
-const { $msg, u } = converse.env;
|
|
|
+const { $msg, u, Strophe, $iq, sizzle } = converse.env;
|
|
|
|
|
|
|
|
|
describe("A list of open groupchats", function () {
|
|
@@ -149,7 +149,7 @@ describe("A list of open groupchats", function () {
|
|
|
expect(Array.from(list.classList).includes('hidden')).toBeFalsy();
|
|
|
const items = list.querySelectorAll('.list-item');
|
|
|
expect(items.length).toBe(1);
|
|
|
- await u.waitUntil(() => list.querySelector('.list-item').textContent.trim() === 'Bookmarked Lounge');
|
|
|
+ await u.waitUntil(() => list.querySelector('.list-item .open-room').textContent.trim() === 'Bookmarked Lounge');
|
|
|
expect(_converse.bookmarks.fetchBookmarks).toHaveBeenCalled();
|
|
|
}));
|
|
|
});
|
|
@@ -175,7 +175,7 @@ describe("A groupchat shown in the groupchats list", function () {
|
|
|
let item = room_els[0];
|
|
|
await u.waitUntil(() => _converse.chatboxes.get(muc_jid).get('hidden') === false);
|
|
|
await u.waitUntil(() => u.hasClass('open', item), 1000);
|
|
|
- expect(item.textContent.trim()).toBe('coven@chat.shakespeare.lit');
|
|
|
+ expect(item.querySelector('.open-room').textContent.trim()).toBe('coven@chat.shakespeare.lit');
|
|
|
await _converse.api.rooms.open('balcony@chat.shakespeare.lit', {'nick': 'some1'}, true);
|
|
|
await u.waitUntil(() => lview.querySelectorAll(".open-room").length > 1);
|
|
|
room_els = lview.querySelectorAll(".open-room");
|
|
@@ -184,125 +184,134 @@ describe("A groupchat shown in the groupchats list", function () {
|
|
|
room_els = lview.querySelectorAll(".available-chatroom.open");
|
|
|
expect(room_els.length).toBe(1);
|
|
|
item = room_els[0];
|
|
|
- expect(item.textContent.trim()).toBe('balcony@chat.shakespeare.lit');
|
|
|
+ expect(item.querySelector('a').textContent.trim()).toBe('balcony@chat.shakespeare.lit');
|
|
|
}));
|
|
|
|
|
|
- it("has an info icon which opens a details modal when clicked", mock.initConverse(
|
|
|
+ it("shows the MUC avatar", mock.initConverse(
|
|
|
['chatBoxesFetched'],
|
|
|
{ whitelisted_plugins: ['converse-roomslist'],
|
|
|
allow_bookmarks: false // Makes testing easier, otherwise we
|
|
|
// have to mock stanza traffic.
|
|
|
}, async function (_converse) {
|
|
|
|
|
|
- const { Strophe, $iq, $pres } = converse.env;
|
|
|
const u = converse.env.utils;
|
|
|
- const IQ_stanzas = _converse.api.connection.get().IQ_stanzas;
|
|
|
- const room_jid = 'coven@chat.shakespeare.lit';
|
|
|
+ const muc_jid = 'coven@chat.shakespeare.lit';
|
|
|
await mock.waitForRoster(_converse, 'current', 0);
|
|
|
await mock.openControlBox(_converse);
|
|
|
- await _converse.api.rooms.open(room_jid, {'nick': 'some1'});
|
|
|
-
|
|
|
- const selector = `iq[to="${room_jid}"] query[xmlns="http://jabber.org/protocol/disco#info"]`;
|
|
|
- const features_query = await u.waitUntil(() => IQ_stanzas.filter(iq => iq.querySelector(selector)).pop());
|
|
|
- const features_stanza = $iq({
|
|
|
- 'from': 'coven@chat.shakespeare.lit',
|
|
|
- 'id': features_query.getAttribute('id'),
|
|
|
- 'to': 'romeo@montague.lit/desktop',
|
|
|
- 'type': 'result'
|
|
|
- })
|
|
|
- .c('query', { 'xmlns': 'http://jabber.org/protocol/disco#info'})
|
|
|
- .c('identity', {
|
|
|
- 'category': 'conference',
|
|
|
- 'name': 'A Dark Cave',
|
|
|
- 'type': 'text'
|
|
|
- }).up()
|
|
|
- .c('feature', {'var': 'http://jabber.org/protocol/muc'}).up()
|
|
|
- .c('feature', {'var': 'muc_passwordprotected'}).up()
|
|
|
- .c('feature', {'var': 'muc_hidden'}).up()
|
|
|
- .c('feature', {'var': 'muc_temporary'}).up()
|
|
|
- .c('feature', {'var': 'muc_open'}).up()
|
|
|
- .c('feature', {'var': 'muc_unmoderated'}).up()
|
|
|
- .c('feature', {'var': 'muc_nonanonymous'}).up()
|
|
|
- .c('feature', {'var': 'urn:xmpp:mam:0'}).up()
|
|
|
- .c('x', { 'xmlns':'jabber:x:data', 'type':'result'})
|
|
|
- .c('field', {'var':'FORM_TYPE', 'type':'hidden'})
|
|
|
- .c('value').t('http://jabber.org/protocol/muc#roominfo').up().up()
|
|
|
- .c('field', {'type':'text-single', 'var':'muc#roominfo_description', 'label':'Description'})
|
|
|
- .c('value').t('This is the description').up().up()
|
|
|
- .c('field', {'type':'text-single', 'var':'muc#roominfo_occupants', 'label':'Number of occupants'})
|
|
|
- .c('value').t(0);
|
|
|
- _converse.api.connection.get()._dataRecv(mock.createRequest(features_stanza));
|
|
|
-
|
|
|
- const view = _converse.chatboxviews.get(room_jid);
|
|
|
- await u.waitUntil(() => view.model.session.get('connection_status') === converse.ROOMSTATUS.CONNECTING)
|
|
|
- let presence = $pres({
|
|
|
- to: _converse.api.connection.get().jid,
|
|
|
- from: 'coven@chat.shakespeare.lit/some1',
|
|
|
- id: 'DC352437-C019-40EC-B590-AF29E879AF97'
|
|
|
- }).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
|
|
|
- .c('item').attrs({
|
|
|
- affiliation: 'member',
|
|
|
- jid: _converse.bare_jid,
|
|
|
- role: 'participant'
|
|
|
- }).up()
|
|
|
- .c('status').attrs({code:'110'});
|
|
|
- _converse.api.connection.get()._dataRecv(mock.createRequest(presence));
|
|
|
+ await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
|
|
|
|
|
|
const rooms_list = document.querySelector('converse-rooms-list');
|
|
|
await u.waitUntil(() => rooms_list.querySelectorAll(".open-room").length, 500);
|
|
|
const room_els = rooms_list.querySelectorAll(".open-room");
|
|
|
expect(room_els.length).toBe(1);
|
|
|
- const info_el = rooms_list.querySelector(".room-info");
|
|
|
- info_el.click();
|
|
|
-
|
|
|
- const modal = _converse.api.modal.get('converse-muc-details-modal');
|
|
|
- await u.waitUntil(() => u.isVisible(modal), 1000);
|
|
|
- let els = modal.querySelectorAll('p.room-info');
|
|
|
- expect(els[0].textContent).toBe("Name: A Dark Cave")
|
|
|
-
|
|
|
- expect(els[1].querySelector('strong').textContent).toBe("XMPP address");
|
|
|
- expect(els[1].querySelector('converse-rich-text').textContent.trim()).toBe("xmpp:coven@chat.shakespeare.lit?join");
|
|
|
- expect(els[2].querySelector('strong').textContent).toBe("Description");
|
|
|
- expect(els[2].querySelector('converse-rich-text').textContent).toBe("This is the description");
|
|
|
-
|
|
|
- expect(els[3].textContent).toBe("Online users: 1")
|
|
|
- const features_list = modal.querySelector('.features-list');
|
|
|
- expect(features_list.textContent.replace(/(\n|\s{2,})/g, '')).toBe(
|
|
|
- 'Password protected - This groupchat requires a password before entry'+
|
|
|
- 'Hidden - This groupchat is not publicly searchable'+
|
|
|
- 'Open - Anyone can join this groupchat'+
|
|
|
- 'Temporary - This groupchat will disappear once the last person leaves '+
|
|
|
- 'Not anonymous - All other groupchat participants can see your XMPP address'+
|
|
|
- 'Not moderated - Participants entering this groupchat can write right away '
|
|
|
- );
|
|
|
- presence = $pres({
|
|
|
- to: 'romeo@montague.lit/_converse.js-29092160',
|
|
|
- from: 'coven@chat.shakespeare.lit/newguy'
|
|
|
- })
|
|
|
- .c('x', {xmlns: Strophe.NS.MUC_USER})
|
|
|
- .c('item', {
|
|
|
- 'affiliation': 'none',
|
|
|
- 'jid': 'newguy@montague.lit/_converse.js-290929789',
|
|
|
- 'role': 'participant'
|
|
|
- });
|
|
|
- _converse.api.connection.get()._dataRecv(mock.createRequest(presence));
|
|
|
+ const avatar_el = rooms_list.querySelector("converse-avatar");
|
|
|
+ expect(avatar_el).toBeDefined();
|
|
|
+
|
|
|
+ let initials_el = rooms_list.querySelector('converse-avatar .avatar-initials');
|
|
|
+ expect(initials_el.textContent).toBe('C');
|
|
|
+ expect(getComputedStyle(initials_el).backgroundColor).toBe('rgb(75, 103, 255)');
|
|
|
+
|
|
|
+ const muc_el = _converse.chatboxviews.get(muc_jid);
|
|
|
+ let muc_initials_el = muc_el.querySelector('converse-muc-heading converse-avatar .avatar-initials');
|
|
|
+ expect(muc_initials_el.textContent).toBe(initials_el.textContent);
|
|
|
+ expect(getComputedStyle(muc_initials_el).backgroundColor).toBe(getComputedStyle(initials_el).backgroundColor);
|
|
|
+
|
|
|
+ // Change MUC name
|
|
|
+ // ---------------
|
|
|
+ muc_el.querySelector('.configure-chatroom-button').click();
|
|
|
+ const { IQ_stanzas } = _converse.api.connection.get();
|
|
|
+ const sel = 'iq query[xmlns="http://jabber.org/protocol/muc#owner"]';
|
|
|
+ let iq = await u.waitUntil(() => IQ_stanzas.filter(iq => sizzle(sel, iq).length).pop());
|
|
|
+
|
|
|
+ // Check that an IQ is sent out, asking for the configuration form.
|
|
|
+ expect(Strophe.serialize(iq)).toBe(
|
|
|
+ `<iq id="${iq.getAttribute('id')}" to="${muc_jid}" type="get" xmlns="jabber:client">`+
|
|
|
+ `<query xmlns="http://jabber.org/protocol/muc#owner"/>`+
|
|
|
+ `</iq>`);
|
|
|
+
|
|
|
+ const jid = _converse.session.get('jid');
|
|
|
+
|
|
|
+ /* Server responds with the configuration form.
|
|
|
+ * See: // https://xmpp.org/extensions/xep-0045.html#example-165
|
|
|
+ */
|
|
|
+ const config_stanza = $iq({from: 'coven@chat.shakespeare.lit',
|
|
|
+ 'id': iq.getAttribute('id'),
|
|
|
+ 'to': jid,
|
|
|
+ 'type': 'result'})
|
|
|
+ .c('query', { 'xmlns': 'http://jabber.org/protocol/muc#owner'})
|
|
|
+ .c('x', { 'xmlns': 'jabber:x:data', 'type': 'form'})
|
|
|
+ .c('title').t('Configuration for "coven" Room').up()
|
|
|
+ .c('instructions').t('Complete this form to modify the configuration of your room.').up()
|
|
|
+ .c('field', {'type': 'hidden', 'var': 'FORM_TYPE'})
|
|
|
+ .c('value').t('http://jabber.org/protocol/muc#roomconfig').up().up()
|
|
|
+ .c('field', {
|
|
|
+ 'label': 'Natural-Language Room Name',
|
|
|
+ 'type': 'text-single',
|
|
|
+ 'var': 'muc#roomconfig_roomname'})
|
|
|
+ .c('value').t('Coven').up().up()
|
|
|
+ _converse.api.connection.get()._dataRecv(mock.createRequest(config_stanza));
|
|
|
+
|
|
|
+ const name_el = await u.waitUntil(() => muc_el.querySelector('input[name="muc#roomconfig_roomname"]'));
|
|
|
+ name_el.value = 'New room name';
|
|
|
+ muc_el.querySelector('.chatroom-form input[type="submit"]').click();
|
|
|
+
|
|
|
+ iq = await u.waitUntil(() => IQ_stanzas.filter(iq => iq.matches(`iq[to="${muc_jid}"][type="set"]`)).pop());
|
|
|
+ IQ_stanzas.length = 0; // Empty the array
|
|
|
+ const result = $iq({
|
|
|
+ "xmlns": "jabber:client",
|
|
|
+ "type": "result",
|
|
|
+ "to": jid,
|
|
|
+ "from": muc_jid,
|
|
|
+ "id": iq.getAttribute('id')
|
|
|
+ });
|
|
|
+ _converse.api.connection.get()._dataRecv(mock.createRequest(result));
|
|
|
+
|
|
|
+ iq = await u.waitUntil(() => IQ_stanzas.filter(
|
|
|
+ iq => iq.querySelector(
|
|
|
+ `iq[to="${muc_jid}"] query[xmlns="http://jabber.org/protocol/disco#info"]`
|
|
|
+ )).pop());
|
|
|
+
|
|
|
+ const features_stanza = $iq({
|
|
|
+ 'from': muc_jid,
|
|
|
+ 'id': iq.getAttribute('id'),
|
|
|
+ 'to': 'romeo@montague.lit/desktop',
|
|
|
+ 'type': 'result'
|
|
|
+ }).c('query', { 'xmlns': 'http://jabber.org/protocol/disco#info'})
|
|
|
+ .c('identity', {
|
|
|
+ 'category': 'conference',
|
|
|
+ 'name': 'New room name',
|
|
|
+ 'type': 'text'
|
|
|
+ }).up();
|
|
|
+ _converse.api.connection.get()._dataRecv(mock.createRequest(features_stanza));
|
|
|
+
|
|
|
+ await u.waitUntil(() => new Promise(success => muc_el.model.features.on('change', success)));
|
|
|
+
|
|
|
+ initials_el = rooms_list.querySelector('converse-avatar .avatar-initials');
|
|
|
+ expect(initials_el.textContent).toBe('NN');
|
|
|
+ expect(getComputedStyle(initials_el).backgroundColor).toBe('rgb(75, 103, 255)');
|
|
|
+
|
|
|
+ muc_initials_el = muc_el.querySelector('converse-muc-heading converse-avatar .avatar-initials');
|
|
|
+ expect(muc_initials_el.textContent).toBe(initials_el.textContent);
|
|
|
+ expect(getComputedStyle(muc_initials_el).backgroundColor).toBe(getComputedStyle(initials_el).backgroundColor);
|
|
|
|
|
|
- els = modal.querySelectorAll('p.room-info');
|
|
|
- expect(els[3].textContent).toBe("Online users: 2")
|
|
|
+ // eslint-disable-next-line max-len
|
|
|
+ const image = 'PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCI+CiA8cmVjdCB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgZmlsbD0iIzU1NSIvPgogPGNpcmNsZSBjeD0iNjQiIGN5PSI0MSIgcj0iMjQiIGZpbGw9IiNmZmYiLz4KIDxwYXRoIGQ9Im0yOC41IDExMiB2LTEyIGMwLTEyIDEwLTI0IDI0LTI0IGgyMyBjMTQgMCAyNCAxMiAyNCAyNCB2MTIiIGZpbGw9IiNmZmYiLz4KPC9zdmc+Cg==';
|
|
|
+ const image_type = 'image/svg+xml';
|
|
|
|
|
|
- view.model.set({'subject': {'author': 'someone', 'text': 'Hatching dark plots'}});
|
|
|
- els = modal.querySelectorAll('p.room-info');
|
|
|
- expect(els[0].textContent).toBe("Name: A Dark Cave")
|
|
|
+ // Change MUC avatar and check that it reflects
|
|
|
+ muc_el.model.vcard.set({
|
|
|
+ image,
|
|
|
+ image_type,
|
|
|
+ vcard_updated: (new Date()).toISOString()
|
|
|
+ });
|
|
|
|
|
|
- expect(els[1].querySelector('strong').textContent).toBe("XMPP address");
|
|
|
- expect(els[1].querySelector('converse-rich-text').textContent.trim()).toBe("xmpp:coven@chat.shakespeare.lit?join");
|
|
|
- expect(els[2].querySelector('strong').textContent).toBe("Description");
|
|
|
- expect(els[2].querySelector('converse-rich-text').textContent).toBe("This is the description");
|
|
|
- expect(els[3].querySelector('strong').textContent).toBe("Topic");
|
|
|
- await u.waitUntil(() => els[3].querySelector('converse-rich-text').textContent === "Hatching dark plots");
|
|
|
+ const muc_heading_avatar = await u.waitUntil(() => muc_el.querySelector(
|
|
|
+ `converse-muc-heading converse-avatar svg image`
|
|
|
+ ));
|
|
|
+ expect(muc_heading_avatar.getAttribute('href')).toBe(`data:image/svg+xml;base64,${image}`);
|
|
|
|
|
|
- expect(els[4].textContent).toBe("Topic author: someone")
|
|
|
- expect(els[5].textContent).toBe("Online users: 2")
|
|
|
+ const list_el_image = rooms_list.querySelector('converse-avatar svg image');
|
|
|
+ expect(list_el_image.getAttribute('href')).toBe(`data:image/svg+xml;base64,${image}`);
|
|
|
}));
|
|
|
|
|
|
it("can be closed", mock.initConverse(
|