Fix more tests

This commit is contained in:
JC Brand 2021-01-29 14:15:27 +01:00
parent 22b6b4b502
commit f33fa1e9fc
14 changed files with 179 additions and 265 deletions

View File

@ -25,48 +25,49 @@ module.exports = function(config) {
{ pattern: "node_modules/sinon/pkg/sinon.js", type: 'module' }, { pattern: "node_modules/sinon/pkg/sinon.js", type: 'module' },
{ pattern: "spec/mock.js", type: 'module' }, { pattern: "spec/mock.js", type: 'module' },
// { pattern: "spec/user-details-modal.js", type: 'module' }, { pattern: "spec/user-details-modal.js", type: 'module' },
// { pattern: "spec/spoilers.js", type: 'module' }, { pattern: "spec/spoilers.js", type: 'module' },
// { pattern: "spec/emojis.js", type: 'module' }, { pattern: "spec/emojis.js", type: 'module' },
// { pattern: "spec/muclist.js", type: 'module' }, { pattern: "spec/muclist.js", type: 'module' },
// { pattern: "spec/converse.js", type: 'module' }, { pattern: "spec/utils.js", type: 'module' },
// { pattern: "spec/bookmarks.js", type: 'module' }, { pattern: "spec/converse.js", type: 'module' },
// { pattern: "spec/headline.js", type: 'module' }, { pattern: "spec/bookmarks.js", type: 'module' },
// { pattern: "spec/disco.js", type: 'module' }, { pattern: "spec/headline.js", type: 'module' },
// { pattern: "spec/protocol.js", type: 'module' }, { pattern: "spec/disco.js", type: 'module' },
// { pattern: "spec/presence.js", type: 'module' }, { pattern: "spec/protocol.js", type: 'module' },
// { pattern: "spec/eventemitter.js", type: 'module' }, { pattern: "spec/presence.js", type: 'module' },
// { pattern: "spec/smacks.js", type: 'module' }, { pattern: "spec/eventemitter.js", type: 'module' },
// { pattern: "spec/ping.js", type: 'module' }, { pattern: "spec/smacks.js", type: 'module' },
// { pattern: "spec/push.js", type: 'module' }, { pattern: "spec/ping.js", type: 'module' },
// { pattern: "spec/xmppstatus.js", type: 'module' }, { pattern: "spec/push.js", type: 'module' },
// { pattern: "spec/mam.js", type: 'module' }, { pattern: "spec/xmppstatus.js", type: 'module' },
// { pattern: "spec/omemo.js", type: 'module' }, { pattern: "spec/mam.js", type: 'module' },
// { pattern: "spec/controlbox.js", type: 'module' }, { pattern: "spec/omemo.js", type: 'module' },
// { pattern: "spec/roster.js", type: 'module' }, { pattern: "spec/controlbox.js", type: 'module' },
{ pattern: "spec/roster.js", type: 'module' },
{ pattern: "spec/chatbox.js", type: 'module' }, { pattern: "spec/chatbox.js", type: 'module' },
// { pattern: "spec/messages.js", type: 'module' }, { pattern: "spec/messages.js", type: 'module' },
// { pattern: "spec/corrections.js", type: 'module' }, { pattern: "spec/corrections.js", type: 'module' },
// { pattern: "spec/styling.js", type: 'module' }, { pattern: "spec/styling.js", type: 'module' },
// { pattern: "spec/receipts.js", type: 'module' }, { pattern: "spec/receipts.js", type: 'module' },
// { pattern: "spec/markers.js", type: 'module' }, { pattern: "spec/markers.js", type: 'module' },
// { pattern: "spec/rai.js", type: 'module' }, { pattern: "spec/rai.js", type: 'module' },
// { pattern: "spec/muc_messages.js", type: 'module' }, { pattern: "spec/muc_messages.js", type: 'module' },
// { pattern: "spec/muc-mentions.js", type: 'module' }, { pattern: "spec/muc-mentions.js", type: 'module' },
// { pattern: "spec/me-messages.js", type: 'module' }, { pattern: "spec/me-messages.js", type: 'module' },
// { pattern: "spec/mentions.js", type: 'module' }, { pattern: "spec/mentions.js", type: 'module' },
// { pattern: "spec/retractions.js", type: 'module' }, { pattern: "spec/retractions.js", type: 'module' },
// { pattern: "spec/muc.js", type: 'module' }, { pattern: "spec/muc.js", type: 'module' },
// { pattern: "spec/modtools.js", type: 'module' }, { pattern: "spec/modtools.js", type: 'module' },
// { pattern: "spec/room_registration.js", type: 'module' }, { pattern: "spec/room_registration.js", type: 'module' },
// { pattern: "spec/autocomplete.js", type: 'module' }, { pattern: "spec/autocomplete.js", type: 'module' },
// { pattern: "spec/minchats.js", type: 'module' }, { pattern: "spec/minchats.js", type: 'module' },
// { pattern: "spec/notification.js", type: 'module' }, { pattern: "spec/notification.js", type: 'module' },
// { pattern: "spec/login.js", type: 'module' }, { pattern: "spec/login.js", type: 'module' },
// { pattern: "spec/register.js", type: 'module' }, { pattern: "spec/register.js", type: 'module' },
// { pattern: "spec/hats.js", type: 'module' }, { pattern: "spec/hats.js", type: 'module' },
// { pattern: "spec/http-file-upload.js", type: 'module' }, { pattern: "spec/http-file-upload.js", type: 'module' },
// { pattern: "spec/xss.js", type: 'module' } { pattern: "spec/xss.js", type: 'module' }
], ],
proxies: { proxies: {

View File

@ -8,9 +8,8 @@ const u = converse.env.utils;
describe("The nickname autocomplete feature", function () { describe("The nickname autocomplete feature", function () {
it("shows all autocompletion options when the user presses @", it("shows all autocompletion options when the user presses @",
mock.initConverse( mock.initConverse(['chatBoxesFetched'], {},
['rosterContactsFetched', 'chatBoxesFetched'], {}, async function (done, _converse) {
async function (done, _converse) {
await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'tom'); await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'tom');
const view = _converse.chatboxviews.get('lounge@montague.lit'); const view = _converse.chatboxviews.get('lounge@montague.lit');
@ -62,9 +61,8 @@ describe("The nickname autocomplete feature", function () {
})); }));
it("shows all autocompletion options when the user presses @ right after a new line", it("shows all autocompletion options when the user presses @ right after a new line",
mock.initConverse( mock.initConverse(['chatBoxesFetched'], {},
['rosterContactsFetched', 'chatBoxesFetched'], {}, async function (done, _converse) {
async function (done, _converse) {
await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'tom'); await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'tom');
const view = _converse.chatboxviews.get('lounge@montague.lit'); const view = _converse.chatboxviews.get('lounge@montague.lit');
@ -118,8 +116,8 @@ describe("The nickname autocomplete feature", function () {
it("shows all autocompletion options when the user presses @ right after an allowed character", it("shows all autocompletion options when the user presses @ right after an allowed character",
mock.initConverse( mock.initConverse(
['rosterContactsFetched', 'chatBoxesFetched'], {'opening_mention_characters':['(']}, ['chatBoxesFetched'], {'opening_mention_characters':['(']},
async function (done, _converse) { async function (done, _converse) {
await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'tom'); await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'tom');
const view = _converse.chatboxviews.get('lounge@montague.lit'); const view = _converse.chatboxviews.get('lounge@montague.lit');
@ -172,7 +170,7 @@ describe("The nickname autocomplete feature", function () {
})); }));
it("should order by query index position and length", mock.initConverse( it("should order by query index position and length", mock.initConverse(
['rosterContactsFetched', 'chatBoxesFetched'], {}, async function (done, _converse) { ['chatBoxesFetched'], {}, async function (done, _converse) {
await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'tom'); await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'tom');
const view = _converse.chatboxviews.get('lounge@montague.lit'); const view = _converse.chatboxviews.get('lounge@montague.lit');
@ -219,9 +217,7 @@ describe("The nickname autocomplete feature", function () {
})); }));
it("autocompletes when the user presses tab", it("autocompletes when the user presses tab",
mock.initConverse( mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
['rosterContactsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo'); await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
const view = _converse.chatboxviews.get('lounge@montague.lit'); const view = _converse.chatboxviews.get('lounge@montague.lit');
@ -331,9 +327,7 @@ describe("The nickname autocomplete feature", function () {
})); }));
it("autocompletes when the user presses backspace", it("autocompletes when the user presses backspace",
mock.initConverse( mock.initConverse([], {}, async function (done, _converse) {
['rosterContactsFetched'], {},
async function (done, _converse) {
await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo'); await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
const view = _converse.chatboxviews.get('lounge@montague.lit'); const view = _converse.chatboxviews.get('lounge@montague.lit');

View File

@ -394,10 +394,10 @@ describe("Chatboxes", function () {
await u.waitUntil(() => rosterview.querySelectorAll('.roster-group').length); await u.waitUntil(() => rosterview.querySelectorAll('.roster-group').length);
await mock.openChatBoxFor(_converse, contact_jid); await mock.openChatBoxFor(_converse, contact_jid);
const view = _converse.chatboxviews.get(contact_jid); const view = _converse.chatboxviews.get(contact_jid);
view.model.minimize(); _converse.minimize.minimize(view.model);
expect(view.model.get('chat_state')).toBe('inactive'); expect(view.model.get('chat_state')).toBe('inactive');
spyOn(_converse.connection, 'send'); spyOn(_converse.connection, 'send');
view.model.maximize(); _converse.minimize.maximize(view.model);
await u.waitUntil(() => view.model.get('chat_state') === 'active', 1000); await u.waitUntil(() => view.model.get('chat_state') === 'active', 1000);
expect(_converse.connection.send).toHaveBeenCalled(); expect(_converse.connection.send).toHaveBeenCalled();
const calls = _.filter(_converse.connection.send.calls.all(), function (call) { const calls = _.filter(_converse.connection.send.calls.all(), function (call) {
@ -750,7 +750,7 @@ describe("Chatboxes", function () {
await mock.openChatBoxFor(_converse, contact_jid); await mock.openChatBoxFor(_converse, contact_jid);
const view = _converse.chatboxviews.get(contact_jid); const view = _converse.chatboxviews.get(contact_jid);
spyOn(_converse.connection, 'send'); spyOn(_converse.connection, 'send');
view.minimize(); _converse.minimize.minimize(view.model);
expect(view.model.get('chat_state')).toBe('inactive'); expect(view.model.get('chat_state')).toBe('inactive');
expect(_converse.connection.send).toHaveBeenCalled(); expect(_converse.connection.send).toHaveBeenCalled();
var stanza = _converse.connection.send.calls.argsFor(0)[0].tree(); var stanza = _converse.connection.send.calls.argsFor(0)[0].tree();
@ -1125,8 +1125,7 @@ describe("Chatboxes", function () {
await u.waitUntil(() => rosterview.querySelectorAll('.roster-group').length, 500); await u.waitUntil(() => rosterview.querySelectorAll('.roster-group').length, 500);
await mock.openChatBoxFor(_converse, sender_jid); await mock.openChatBoxFor(_converse, sender_jid);
const chatbox = _converse.chatboxes.get(sender_jid); const chatbox = _converse.chatboxes.get(sender_jid);
var chatboxview = _converse.chatboxviews.get(sender_jid); _converse.minimize.minimize(chatbox);
chatboxview.minimize();
msg = mock.createChatMessage(_converse, sender_jid, 'This message will be unread'); msg = mock.createChatMessage(_converse, sender_jid, 'This message will be unread');
await _converse.handleMessageStanza(msg); await _converse.handleMessageStanza(msg);
@ -1156,14 +1155,14 @@ describe("Chatboxes", function () {
const view = _converse.chatboxviews.get(sender_jid); const view = _converse.chatboxviews.get(sender_jid);
const selector = 'a.open-chat:contains("' + chatbox.get('nickname') + '") .msgs-indicator'; const selector = 'a.open-chat:contains("' + chatbox.get('nickname') + '") .msgs-indicator';
const select_msgs_indicator = () => sizzle(selector, rosterview.el).pop(); const select_msgs_indicator = () => sizzle(selector, rosterview.el).pop();
view.minimize(); _converse.minimize.minimize(view.model);
_converse.handleMessageStanza(msgFactory()); _converse.handleMessageStanza(msgFactory());
await u.waitUntil(() => chatbox.messages.length); await u.waitUntil(() => chatbox.messages.length);
expect(select_msgs_indicator().textContent).toBe('1'); expect(select_msgs_indicator().textContent).toBe('1');
_converse.handleMessageStanza(msgFactory()); _converse.handleMessageStanza(msgFactory());
await u.waitUntil(() => chatbox.messages.length > 1); await u.waitUntil(() => chatbox.messages.length > 1);
expect(select_msgs_indicator().textContent).toBe('2'); expect(select_msgs_indicator().textContent).toBe('2');
view.model.maximize(); _converse.minimize.minimize(view.model);
u.waitUntil(() => typeof select_msgs_indicator() === 'undefined'); u.waitUntil(() => typeof select_msgs_indicator() === 'undefined');
done(); done();
})); }));

View File

@ -1,4 +1,4 @@
/*global mock, converse, _ */ /*global mock, converse */
const $msg = converse.env.$msg; const $msg = converse.env.$msg;
const u = converse.env.utils; const u = converse.env.utils;
@ -9,25 +9,19 @@ const sizzle = converse.env.sizzle;
describe("The Controlbox", function () { describe("The Controlbox", function () {
it("can be opened by clicking a DOM element with class 'toggle-controlbox'", it("can be opened by clicking a DOM element with class 'toggle-controlbox'",
mock.initConverse( mock.initConverse([], {}, function (done, _converse) {
['rosterContactsFetched'], {},
function (done, _converse) {
// This spec will only pass if the controlbox is not currently const toggle = document.querySelector('converse-controlbox-toggle');
// open yet. spyOn(toggle, 'onClick').and.callThrough();
let el = document.querySelector("div#controlbox"); spyOn(toggle, 'showControlBox').and.callThrough();
expect(_.isElement(el)).toBe(true);
expect(u.isVisible(el)).toBe(false);
spyOn(_converse.controlboxtoggle, 'onClick').and.callThrough();
spyOn(_converse.controlboxtoggle, 'showControlBox').and.callThrough();
spyOn(_converse.api, "trigger").and.callThrough(); spyOn(_converse.api, "trigger").and.callThrough();
// Redelegate so that the spies are now registered as the event handlers (specifically for 'onClick') // Redelegate so that the spies are now registered as the event handlers (specifically for 'onClick')
_converse.controlboxtoggle.delegateEvents(); toggle.delegateEvents();
document.querySelector('.toggle-controlbox').click(); document.querySelector('.toggle-controlbox').click();
expect(_converse.controlboxtoggle.onClick).toHaveBeenCalled(); expect(toggle.onClick).toHaveBeenCalled();
expect(_converse.controlboxtoggle.showControlBox).toHaveBeenCalled(); expect(toggle.showControlBox).toHaveBeenCalled();
expect(_converse.api.trigger).toHaveBeenCalledWith('controlBoxOpened', jasmine.any(Object)); expect(_converse.api.trigger).toHaveBeenCalledWith('controlBoxOpened', jasmine.any(Object));
el = document.querySelector("div#controlbox"); const el = document.querySelector("#controlbox");
expect(u.isVisible(el)).toBe(true); expect(u.isVisible(el)).toBe(true);
done(); done();
})); }));
@ -37,18 +31,17 @@ describe("The Controlbox", function () {
mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) { mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
const controlview = _converse.chatboxviews.get('controlbox'); const view = _converse.chatboxviews.get('controlbox');
spyOn(controlview, 'close').and.callThrough(); spyOn(view, 'close').and.callThrough();
spyOn(_converse.api, "trigger").and.callThrough(); spyOn(_converse.api, "trigger").and.callThrough();
// We need to rebind all events otherwise our spy won't be called // We need to rebind all events otherwise our spy won't be called
controlview.delegateEvents(); view.delegateEvents();
controlview.querySelector('.close-chatbox-button').click(); view.querySelector('.close-chatbox-button').click();
expect(controlview.close).toHaveBeenCalled(); expect(view.close).toHaveBeenCalled();
await new Promise(resolve => _converse.api.listen.once('chatBoxClosed', resolve)); expect(_converse.api.trigger).toHaveBeenCalledWith('controlBoxClosed', jasmine.any(Object));
expect(_converse.api.trigger).toHaveBeenCalledWith('chatBoxClosed', jasmine.any(Object));
done(); done();
})); }));
@ -56,12 +49,10 @@ describe("The Controlbox", function () {
describe("The \"Contacts\" section", function () { describe("The \"Contacts\" section", function () {
it("can be used to add contact and it checks for case-sensivity", it("can be used to add contact and it checks for case-sensivity",
mock.initConverse( mock.initConverse([], {}, async function (done, _converse) {
['rosterContactsFetched'], {},
async function (done, _converse) {
spyOn(_converse.api, "trigger").and.callThrough(); spyOn(_converse.api, "trigger").and.callThrough();
spyOn(_converse.rosterview, 'update').and.callThrough(); await mock.waitForRoster(_converse, 'all', 0);
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
// Adding two contacts one with Capital initials and one with small initials of same JID (Case sensitive check) // Adding two contacts one with Capital initials and one with small initials of same JID (Case sensitive check)
_converse.roster.create({ _converse.roster.create({
@ -76,17 +67,15 @@ describe("The Controlbox", function () {
ask: 'subscribe', ask: 'subscribe',
fullname: mock.pend_names[0] fullname: mock.pend_names[0]
}); });
await u.waitUntil(() => _.filter(_converse.rosterview.querySelectorAll('.roster-group li'), u.isVisible).length, 700); const rosterview = document.querySelector('converse-roster');
await u.waitUntil(() => Array.from(rosterview.querySelectorAll('.roster-group li')).filter(u.isVisible).length, 700);
// Checking that only one entry is created because both JID is same (Case sensitive check) // Checking that only one entry is created because both JID is same (Case sensitive check)
expect(_.filter(_converse.rosterview.querySelectorAll('li'), u.isVisible).length).toBe(1); expect(Array.from(rosterview.querySelectorAll('li')).filter(u.isVisible).length).toBe(1);
expect(_converse.rosterview.update).toHaveBeenCalled();
done(); done();
})); }));
it("shows the number of unread mentions received", it("shows the number of unread mentions received",
mock.initConverse( mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
['rosterContactsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
await mock.waitForRoster(_converse, 'all'); await mock.waitForRoster(_converse, 'all');
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
@ -97,8 +86,10 @@ describe("The Controlbox", function () {
const chatview = _converse.chatboxviews.get(sender_jid); const chatview = _converse.chatboxviews.get(sender_jid);
chatview.model.set({'minimized': true}); chatview.model.set({'minimized': true});
expect(_converse.chatboxviews.el.querySelector('.restore-chat .message-count') === null).toBeTruthy(); const el = document.querySelector('converse-chats');
expect(_converse.rosterview.querySelector('.msgs-indicator') === null).toBeTruthy(); expect(el.querySelector('.restore-chat .message-count') === null).toBeTruthy();
const rosterview = document.querySelector('converse-roster');
expect(rosterview.querySelector('.msgs-indicator') === null).toBeTruthy();
let msg = $msg({ let msg = $msg({
from: sender_jid, from: sender_jid,
@ -108,10 +99,10 @@ describe("The Controlbox", function () {
}).c('body').t('hello').up() }).c('body').t('hello').up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
_converse.handleMessageStanza(msg); _converse.handleMessageStanza(msg);
await u.waitUntil(() => _converse.rosterview.querySelectorAll(".msgs-indicator").length); await u.waitUntil(() => rosterview.querySelectorAll(".msgs-indicator").length);
spyOn(chatview.model, 'handleUnreadMessage').and.callThrough(); spyOn(chatview.model, 'handleUnreadMessage').and.callThrough();
await u.waitUntil(() => _converse.chatboxviews.el.querySelector('.restore-chat .message-count')?.textContent === '1'); await u.waitUntil(() => el.querySelector('.restore-chat .message-count')?.textContent === '1');
expect(_converse.rosterview.querySelector('.msgs-indicator').textContent).toBe('1'); expect(rosterview.querySelector('.msgs-indicator').textContent).toBe('1');
msg = $msg({ msg = $msg({
from: sender_jid, from: sender_jid,
@ -122,11 +113,11 @@ describe("The Controlbox", function () {
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
_converse.handleMessageStanza(msg); _converse.handleMessageStanza(msg);
await u.waitUntil(() => chatview.model.handleUnreadMessage.calls.count()); await u.waitUntil(() => chatview.model.handleUnreadMessage.calls.count());
await u.waitUntil(() => _converse.chatboxviews.el.querySelector('.restore-chat .message-count')?.textContent === '2'); await u.waitUntil(() => el.querySelector('.restore-chat .message-count')?.textContent === '2');
expect(_converse.rosterview.querySelector('.msgs-indicator').textContent).toBe('2'); expect(rosterview.querySelector('.msgs-indicator').textContent).toBe('2');
chatview.model.set({'minimized': false}); chatview.model.set({'minimized': false});
expect(_converse.chatboxviews.el.querySelector('.restore-chat .message-count')).toBe(null); expect(_converse.chatboxviews.el.querySelector('.restore-chat .message-count')).toBe(null);
await u.waitUntil(() => _converse.rosterview.querySelector('.msgs-indicator') === null); await u.waitUntil(() => rosterview.querySelector('.msgs-indicator') === null);
done(); done();
})); }));
}); });
@ -134,28 +125,22 @@ describe("The Controlbox", function () {
describe("The Status Widget", function () { describe("The Status Widget", function () {
it("shows the user's chat status, which is online by default", it("shows the user's chat status, which is online by default",
mock.initConverse( mock.initConverse([], {}, async function (done, _converse) {
['rosterContactsFetched'], {},
function (done, _converse) {
mock.openControlBox(_converse); mock.openControlBox(_converse);
var view = _converse.xmppstatusview; const view = await u.waitUntil(() => document.querySelector('converse-user-profile'));
expect(u.hasClass('online', view.querySelector('.xmpp-status span:first-child'))).toBe(true); expect(u.hasClass('online', view.querySelector('.xmpp-status span:first-child'))).toBe(true);
expect(view.querySelector('.xmpp-status span.online').textContent.trim()).toBe('I am online'); expect(view.querySelector('.xmpp-status span.online').textContent.trim()).toBe('I am online');
done(); done();
})); }));
it("can be used to set the current user's chat status", it("can be used to set the current user's chat status",
mock.initConverse( mock.initConverse([], {}, async function (done, _converse) {
['rosterContactsFetched'], {},
async function (done, _converse) {
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
var cbview = _converse.chatboxviews.get('controlbox'); var cbview = _converse.chatboxviews.get('controlbox');
cbview.querySelector('.change-status').click() cbview.querySelector('.change-status').click()
const modal = _converse.api.modal.get('modal-status-change'); const modal = _converse.api.modal.get('modal-status-change');
await u.waitUntil(() => u.isVisible(modal.el), 1000); await u.waitUntil(() => u.isVisible(modal.el), 1000);
const view = _converse.xmppstatusview;
modal.el.querySelector('label[for="radio-busy"]').click(); // Change status to "dnd" modal.el.querySelector('label[for="radio-busy"]').click(); // Change status to "dnd"
modal.el.querySelector('[type="submit"]').click(); modal.el.querySelector('[type="submit"]').click();
const sent_stanzas = _converse.connection.sent_stanzas; const sent_stanzas = _converse.connection.sent_stanzas;
@ -166,6 +151,7 @@ describe("The Controlbox", function () {
`<priority>0</priority>`+ `<priority>0</priority>`+
`<c hash="sha-1" node="https://conversejs.org" ver="PxXfr6uz8ClMWIga0OB/MhKNH/M=" xmlns="http://jabber.org/protocol/caps"/>`+ `<c hash="sha-1" node="https://conversejs.org" ver="PxXfr6uz8ClMWIga0OB/MhKNH/M=" xmlns="http://jabber.org/protocol/caps"/>`+
`</presence>`); `</presence>`);
const view = await u.waitUntil(() => document.querySelector('converse-user-profile'));
const first_child = view.querySelector('.xmpp-status span:first-child'); const first_child = view.querySelector('.xmpp-status span:first-child');
expect(u.hasClass('online', first_child)).toBe(false); expect(u.hasClass('online', first_child)).toBe(false);
expect(u.hasClass('dnd', first_child)).toBe(true); expect(u.hasClass('dnd', first_child)).toBe(true);
@ -174,9 +160,7 @@ describe("The Controlbox", function () {
})); }));
it("can be used to set a custom status message", it("can be used to set a custom status message",
mock.initConverse( mock.initConverse([], {}, async function (done, _converse) {
['rosterContactsFetched'], {},
async function (done, _converse) {
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
const cbview = _converse.chatboxviews.get('controlbox'); const cbview = _converse.chatboxviews.get('controlbox');
@ -184,7 +168,6 @@ describe("The Controlbox", function () {
const modal = _converse.api.modal.get('modal-status-change'); const modal = _converse.api.modal.get('modal-status-change');
await u.waitUntil(() => u.isVisible(modal.el), 1000); await u.waitUntil(() => u.isVisible(modal.el), 1000);
const view = _converse.xmppstatusview;
const msg = 'I am happy'; const msg = 'I am happy';
modal.el.querySelector('input[name="status_message"]').value = msg; modal.el.querySelector('input[name="status_message"]').value = msg;
modal.el.querySelector('[type="submit"]').click(); modal.el.querySelector('[type="submit"]').click();
@ -197,6 +180,7 @@ describe("The Controlbox", function () {
`<c hash="sha-1" node="https://conversejs.org" ver="PxXfr6uz8ClMWIga0OB/MhKNH/M=" xmlns="http://jabber.org/protocol/caps"/>`+ `<c hash="sha-1" node="https://conversejs.org" ver="PxXfr6uz8ClMWIga0OB/MhKNH/M=" xmlns="http://jabber.org/protocol/caps"/>`+
`</presence>`); `</presence>`);
const view = await u.waitUntil(() => document.querySelector('converse-user-profile'));
const first_child = view.querySelector('.xmpp-status span:first-child'); const first_child = view.querySelector('.xmpp-status span:first-child');
expect(u.hasClass('online', first_child)).toBe(true); expect(u.hasClass('online', first_child)).toBe(true);
expect(view.querySelector('.xmpp-status span:first-child').textContent.trim()).toBe(msg); expect(view.querySelector('.xmpp-status span:first-child').textContent.trim()).toBe(msg);
@ -208,9 +192,7 @@ describe("The Controlbox", function () {
describe("The 'Add Contact' widget", function () { describe("The 'Add Contact' widget", function () {
it("opens up an add modal when you click on it", it("opens up an add modal when you click on it",
mock.initConverse( mock.initConverse([], {}, async function (done, _converse) {
['rosterContactsFetched'], {},
async function (done, _converse) {
await mock.waitForRoster(_converse, 'all'); await mock.waitForRoster(_converse, 'all');
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
@ -242,9 +224,7 @@ describe("The 'Add Contact' widget", function () {
})); }));
it("can be configured to not provide search suggestions", it("can be configured to not provide search suggestions",
mock.initConverse( mock.initConverse([], {'autocomplete_add_contact': false}, async function (done, _converse) {
['rosterContactsFetched'], {'autocomplete_add_contact': false},
async function (done, _converse) {
await mock.waitForRoster(_converse, 'all', 0); await mock.waitForRoster(_converse, 'all', 0);
mock.openControlBox(_converse); mock.openControlBox(_converse);
@ -274,9 +254,7 @@ describe("The 'Add Contact' widget", function () {
it("integrates with xhr_user_search_url to search for contacts", it("integrates with xhr_user_search_url to search for contacts",
mock.initConverse( mock.initConverse([], { 'xhr_user_search_url': 'http://example.org/?' },
['rosterContactsFetched'],
{ 'xhr_user_search_url': 'http://example.org/?' },
async function (done, _converse) { async function (done, _converse) {
await mock.waitForRoster(_converse, 'all', 0); await mock.waitForRoster(_converse, 'all', 0);
@ -330,8 +308,7 @@ describe("The 'Add Contact' widget", function () {
})); }));
it("can be configured to not provide search suggestions for XHR search results", it("can be configured to not provide search suggestions for XHR search results",
mock.initConverse( mock.initConverse([],
['rosterContactsFetched'],
{ 'autocomplete_add_contact': false, { 'autocomplete_add_contact': false,
'xhr_user_search_url': 'http://example.org/?' }, 'xhr_user_search_url': 'http://example.org/?' },
async function (done, _converse) { async function (done, _converse) {

View File

@ -1,14 +1,11 @@
/*global mock */ /*global mock, converse */
const u = converse.env.utils; const u = converse.env.utils;
describe("A XEP-0317 MUC Hat", function () { describe("A XEP-0317 MUC Hat", function () {
it("can be included in a presence stanza", it("can be included in a presence stanza",
mock.initConverse( mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
['rosterContactsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
const muc_jid = 'lounge@montague.lit'; const muc_jid = 'lounge@montague.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.chatboxviews.get(muc_jid); const view = _converse.chatboxviews.get(muc_jid);

View File

@ -9,10 +9,7 @@ describe("XEP-0363: HTTP File Upload", function () {
describe("Discovering support", function () { describe("Discovering support", function () {
it("is done automatically", it("is done automatically", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
mock.initConverse(
['rosterContactsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
const IQ_stanzas = _converse.connection.IQ_stanzas; const IQ_stanzas = _converse.connection.IQ_stanzas;
await mock.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, [], []); await mock.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, [], []);
let selector = 'iq[to="montague.lit"] query[xmlns="http://jabber.org/protocol/disco#info"]'; let selector = 'iq[to="montague.lit"] query[xmlns="http://jabber.org/protocol/disco#info"]';
@ -162,10 +159,7 @@ describe("XEP-0363: HTTP File Upload", function () {
done(); done();
})); }));
it("does not appear in MUC chats", mock.initConverse( it("does not appear in MUC chats", mock.initConverse([], {}, async (done, _converse) => {
['rosterContactsFetched'], {},
async (done, _converse) => {
await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo'); await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
mock.waitUntilDiscoConfirmed( mock.waitUntilDiscoConfirmed(
_converse, _converse.domain, _converse, _converse.domain,
@ -203,10 +197,7 @@ describe("XEP-0363: HTTP File Upload", function () {
done(); done();
})); }));
it("appears in MUC chats", mock.initConverse( it("appears in MUC chats", mock.initConverse(['chatBoxesFetched'], {}, async (done, _converse) => {
['rosterContactsFetched', 'chatBoxesFetched'], {},
async (done, _converse) => {
await mock.waitUntilDiscoConfirmed( await mock.waitUntilDiscoConfirmed(
_converse, _converse.domain, _converse, _converse.domain,
[{'category': 'server', 'type':'IM'}], [{'category': 'server', 'type':'IM'}],
@ -215,7 +206,7 @@ describe("XEP-0363: HTTP File Upload", function () {
await mock.waitUntilDiscoConfirmed(_converse, _converse.domain, [], [], ['upload.montague.lit'], 'items'); await mock.waitUntilDiscoConfirmed(_converse, _converse.domain, [], [], ['upload.montague.lit'], 'items');
await mock.waitUntilDiscoConfirmed(_converse, 'upload.montague.lit', [], [Strophe.NS.HTTPUPLOAD], []); await mock.waitUntilDiscoConfirmed(_converse, 'upload.montague.lit', [], [Strophe.NS.HTTPUPLOAD], []);
await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo'); await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
await u.waitUntil(() => _converse.chatboxviews.get('lounge@montague.lit').el.querySelector('.fileupload')); await u.waitUntil(() => _converse.chatboxviews.get('lounge@montague.lit').querySelector('.fileupload'));
const view = _converse.chatboxviews.get('lounge@montague.lit'); const view = _converse.chatboxviews.get('lounge@montague.lit');
expect(view.querySelector('.chat-toolbar .fileupload')).not.toBe(null); expect(view.querySelector('.chat-toolbar .fileupload')).not.toBe(null);
done(); done();
@ -223,9 +214,7 @@ describe("XEP-0363: HTTP File Upload", function () {
describe("when clicked and a file chosen", function () { describe("when clicked and a file chosen", function () {
it("is uploaded and sent out", mock.initConverse( it("is uploaded and sent out", mock.initConverse(['chatBoxesFetched'], {} ,async (done, _converse) => {
['rosterContactsFetched', 'chatBoxesFetched'], {} ,async (done, _converse) => {
const base_url = 'https://conversejs.org'; const base_url = 'https://conversejs.org';
await mock.waitUntilDiscoConfirmed( await mock.waitUntilDiscoConfirmed(
_converse, _converse.domain, _converse, _converse.domain,
@ -560,10 +549,7 @@ describe("XEP-0363: HTTP File Upload", function () {
describe("While a file is being uploaded", function () { describe("While a file is being uploaded", function () {
it("shows a progress bar", mock.initConverse( it("shows a progress bar", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
['rosterContactsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
await mock.waitUntilDiscoConfirmed( await mock.waitUntilDiscoConfirmed(
_converse, _converse.domain, _converse, _converse.domain,
[{'category': 'server', 'type':'IM'}], [{'category': 'server', 'type':'IM'}],

View File

@ -148,7 +148,6 @@ describe("A Chatbox", function () {
spyOn(_converse.minimize, 'trimChats'); spyOn(_converse.minimize, 'trimChats');
await mock.waitForRoster(_converse, 'current'); await mock.waitForRoster(_converse, 'current');
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
expect(_converse.minimize.trimChats.calls.count()).toBe(1);
let jid, chatboxview; let jid, chatboxview;
// openControlBox was called earlier, so the controlbox is // openControlBox was called earlier, so the controlbox is
@ -179,7 +178,6 @@ describe("A Chatbox", function () {
spyOn(_converse.minimize, 'maximize').and.callThrough(); spyOn(_converse.minimize, 'maximize').and.callThrough();
const minimized_chats = document.querySelector("converse-minimized-chats") const minimized_chats = document.querySelector("converse-minimized-chats")
minimized_chats.querySelector("a.restore-chat").click(); minimized_chats.querySelector("a.restore-chat").click();
expect(_converse.minimize.maximize).toHaveBeenCalled();
expect(_converse.minimize.trimChats.calls.count()).toBe(17); expect(_converse.minimize.trimChats.calls.count()).toBe(17);
done(); done();
})); }));
@ -202,6 +200,7 @@ describe("A Minimized ChatBoxView's Unread Message Count", function () {
_converse.handleMessageStanza(msgFactory()); _converse.handleMessageStanza(msgFactory());
await u.waitUntil(() => chatbox.messages.length); await u.waitUntil(() => chatbox.messages.length);
const view = _converse.chatboxviews.get(sender_jid); const view = _converse.chatboxviews.get(sender_jid);
expect(view.model.get('num_unread')).toBe(1);
_converse.minimize.minimize(view.model); _converse.minimize.minimize(view.model);
const unread_count = selectUnreadMsgCount(); const unread_count = selectUnreadMsgCount();
expect(u.isVisible(unread_count)).toBeTruthy(); expect(u.isVisible(unread_count)).toBeTruthy();

View File

@ -148,9 +148,7 @@ window.addEventListener('converse-loaded', () => {
const model = await _converse.api.controlbox.open('controlbox'); const model = await _converse.api.controlbox.open('controlbox');
await u.waitUntil(() => model.get('connected')); await u.waitUntil(() => model.get('connected'));
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
const view = await _converse.chatboxviews.get('controlbox'); document.querySelector('converse-rooms-list .show-add-muc-modal').click();
const roomspanel = view.roomspanel;
roomspanel.el.querySelector('.show-add-muc-modal').click();
mock.closeControlBox(_converse); mock.closeControlBox(_converse);
const modal = _converse.api.modal.get('add-chatroom-modal'); const modal = _converse.api.modal.get('add-chatroom-modal');
await u.waitUntil(() => u.isVisible(modal.el), 1500) await u.waitUntil(() => u.isVisible(modal.el), 1500)

View File

@ -21,9 +21,7 @@ async function openModtools (_converse, view) {
describe("The groupchat moderator tool", function () { describe("The groupchat moderator tool", function () {
it("allows you to set affiliations and roles", it("allows you to set affiliations and roles",
mock.initConverse( mock.initConverse([], {}, async function (done, _converse) {
['rosterContactsFetched'], {},
async function (done, _converse) {
spyOn(_converse.ChatRoomView.prototype, 'showModeratorToolsModal').and.callThrough(); spyOn(_converse.ChatRoomView.prototype, 'showModeratorToolsModal').and.callThrough();
const muc_jid = 'lounge@montague.lit'; const muc_jid = 'lounge@montague.lit';
@ -142,9 +140,7 @@ describe("The groupchat moderator tool", function () {
})); }));
it("allows you to filter affiliation search results", it("allows you to filter affiliation search results",
mock.initConverse( mock.initConverse([], {}, async function (done, _converse) {
['rosterContactsFetched'], {},
async function (done, _converse) {
spyOn(_converse.ChatRoomView.prototype, 'showModeratorToolsModal').and.callThrough(); spyOn(_converse.ChatRoomView.prototype, 'showModeratorToolsModal').and.callThrough();
const muc_jid = 'lounge@montague.lit'; const muc_jid = 'lounge@montague.lit';
@ -198,9 +194,7 @@ describe("The groupchat moderator tool", function () {
})); }));
it("allows you to filter role search results", it("allows you to filter role search results",
mock.initConverse( mock.initConverse([], {}, async function (done, _converse) {
['rosterContactsFetched'], {},
async function (done, _converse) {
spyOn(_converse.ChatRoomView.prototype, 'showModeratorToolsModal').and.callThrough(); spyOn(_converse.ChatRoomView.prototype, 'showModeratorToolsModal').and.callThrough();
const muc_jid = 'lounge@montague.lit'; const muc_jid = 'lounge@montague.lit';
@ -309,9 +303,7 @@ describe("The groupchat moderator tool", function () {
})); }));
it("shows an error message if a particular affiliation list may not be retrieved", it("shows an error message if a particular affiliation list may not be retrieved",
mock.initConverse( mock.initConverse([], {}, async function (done, _converse) {
['rosterContactsFetched'], {},
async function (done, _converse) {
spyOn(_converse.ChatRoomView.prototype, 'showModeratorToolsModal').and.callThrough(); spyOn(_converse.ChatRoomView.prototype, 'showModeratorToolsModal').and.callThrough();
const muc_jid = 'lounge@montague.lit'; const muc_jid = 'lounge@montague.lit';
@ -361,9 +353,7 @@ describe("The groupchat moderator tool", function () {
})); }));
it("shows an error message if a particular affiliation may not be set", it("shows an error message if a particular affiliation may not be set",
mock.initConverse( mock.initConverse([], {}, async function (done, _converse) {
['rosterContactsFetched'], {},
async function (done, _converse) {
spyOn(_converse.ChatRoomView.prototype, 'showModeratorToolsModal').and.callThrough(); spyOn(_converse.ChatRoomView.prototype, 'showModeratorToolsModal').and.callThrough();
const muc_jid = 'lounge@montague.lit'; const muc_jid = 'lounge@montague.lit';
@ -428,9 +418,7 @@ describe("The groupchat moderator tool", function () {
it("doesn't allow admins to make more admins", it("doesn't allow admins to make more admins",
mock.initConverse( mock.initConverse([], {}, async function (done, _converse) {
['rosterContactsFetched'], {},
async function (done, _converse) {
spyOn(_converse.ChatRoomView.prototype, 'showModeratorToolsModal').and.callThrough(); spyOn(_converse.ChatRoomView.prototype, 'showModeratorToolsModal').and.callThrough();
const muc_jid = 'lounge@montague.lit'; const muc_jid = 'lounge@montague.lit';
@ -465,9 +453,7 @@ describe("The groupchat moderator tool", function () {
})); }));
it("lets the assignable affiliations and roles be configured via modtools_disable_assign", it("lets the assignable affiliations and roles be configured via modtools_disable_assign",
mock.initConverse( mock.initConverse([], {}, async function (done, _converse) {
['rosterContactsFetched'], {},
async function (done, _converse) {
spyOn(_converse.ChatRoomView.prototype, 'showModeratorToolsModal').and.callThrough(); spyOn(_converse.ChatRoomView.prototype, 'showModeratorToolsModal').and.callThrough();
const muc_jid = 'lounge@montague.lit'; const muc_jid = 'lounge@montague.lit';

View File

@ -13,7 +13,7 @@ describe("Groupchats", function () {
describe("The \"rooms\" API", function () { describe("The \"rooms\" API", function () {
fit("has a method 'close' which closes rooms by JID or all rooms when called with no arguments", it("has a method 'close' which closes rooms by JID or all rooms when called with no arguments",
mock.initConverse([], {}, async function (done, _converse) { mock.initConverse([], {}, async function (done, _converse) {
await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo'); await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
@ -51,7 +51,8 @@ describe("Groupchats", function () {
mock.initConverse([], {}, async function (done, _converse) { mock.initConverse([], {}, async function (done, _converse) {
await mock.waitForRoster(_converse, 'current'); await mock.waitForRoster(_converse, 'current');
await u.waitUntil(() => _converse.rosterview.querySelectorAll('.roster-group .group-toggle').length, 300); const rosterview = document.querySelector('converse-roster');
await u.waitUntil(() => rosterview.querySelectorAll('.roster-group .group-toggle').length, 300);
let muc_jid = 'chillout@montague.lit'; let muc_jid = 'chillout@montague.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
let room = await _converse.api.rooms.get(muc_jid); let room = await _converse.api.rooms.get(muc_jid);
@ -103,7 +104,8 @@ describe("Groupchats", function () {
let chatroomview, IQ_id; let chatroomview, IQ_id;
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
await mock.waitForRoster(_converse, 'current'); await mock.waitForRoster(_converse, 'current');
await u.waitUntil(() => _converse.rosterview.querySelectorAll('.roster-group .group-toggle').length); const rosterview = document.querySelector('converse-roster');
await u.waitUntil(() => rosterview.querySelectorAll('.roster-group .group-toggle').length);
let room = await _converse.api.rooms.open(jid); let room = await _converse.api.rooms.open(jid);
// Test on groupchat that's not yet open // Test on groupchat that's not yet open
@ -196,7 +198,7 @@ describe("Groupchats", function () {
expect(_converse.connection.sendIQ).toHaveBeenCalled(); expect(_converse.connection.sendIQ).toHaveBeenCalled();
const IQ_stanzas = _converse.connection.IQ_stanzas; const IQ_stanzas = _converse.connection.IQ_stanzas;
const iq = IQ_stanzas.filter(s => s.querySelector(`query[xmlns="${Strophe.NS.MUC_OWNER}"]`)).pop(); const iq = await u.waitUntil(() => IQ_stanzas.filter(s => s.querySelector(`query[xmlns="${Strophe.NS.MUC_OWNER}"]`)).pop());
expect(Strophe.serialize(iq)).toBe( expect(Strophe.serialize(iq)).toBe(
`<iq id="${iq.getAttribute('id')}" to="room@conference.example.org" type="get" xmlns="jabber:client">`+ `<iq id="${iq.getAttribute('id')}" to="room@conference.example.org" type="get" xmlns="jabber:client">`+
`<query xmlns="http://jabber.org/protocol/muc#owner"/></iq>`); `<query xmlns="http://jabber.org/protocol/muc#owner"/></iq>`);
@ -378,14 +380,14 @@ describe("Groupchats", function () {
'time': '2021-02-02T12:00:00Z' 'time': '2021-02-02T12:00:00Z'
}); });
expect(view.model.session.get('connection_status')).toBe(converse.ROOMSTATUS.NICKNAME_REQUIRED); expect(view.model.session.get('connection_status')).toBe(converse.ROOMSTATUS.NICKNAME_REQUIRED);
await u.waitUntil(() => view.el.querySelectorAll('converse-chat-message').length === 1); await u.waitUntil(() => view.querySelectorAll('converse-chat-message').length === 1);
const sel = 'converse-message-history converse-chat-message .chat-msg__text'; const sel = 'converse-message-history converse-chat-message .chat-msg__text';
await u.waitUntil(() => view.el.querySelector(sel)?.textContent.trim()); await u.waitUntil(() => view.querySelector(sel)?.textContent.trim());
expect(view.el.querySelector(sel).textContent.trim()).toBe('Hello world') expect(view.querySelector(sel).textContent.trim()).toBe('Hello world')
view.el.querySelector('[name="nick"]').value = nick; view.querySelector('[name="nick"]').value = nick;
view.el.querySelector('.muc-nickname-form input[type="submit"]').click(); view.querySelector('.muc-nickname-form input[type="submit"]').click();
_converse.connection.IQ_stanzas = []; _converse.connection.IQ_stanzas = [];
await mock.getRoomFeatures(_converse, muc_jid); await mock.getRoomFeatures(_converse, muc_jid);
await u.waitUntil(() => view.model.session.get('connection_status') === converse.ROOMSTATUS.CONNECTING); await u.waitUntil(() => view.model.session.get('connection_status') === converse.ROOMSTATUS.CONNECTING);
@ -1432,6 +1434,7 @@ describe("Groupchats", function () {
})); }));
it("can be configured if you're its owner", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) { it("can be configured if you're its owner", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
let sent_IQ, IQ_id; let sent_IQ, IQ_id;
const sendIQ = _converse.connection.sendIQ; const sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
@ -2722,7 +2725,7 @@ describe("Groupchats", function () {
_converse.connection._dataRecv(mock.createRequest(presence)); _converse.connection._dataRecv(mock.createRequest(presence));
expect(u.isVisible(view.querySelector('.chat-area'))).toBeFalsy(); await u.waitUntil(() => !u.isVisible(view.querySelector('.chat-area')));
expect(u.isVisible(view.querySelector('.occupants'))).toBeFalsy(); expect(u.isVisible(view.querySelector('.occupants'))).toBeFalsy();
const chat_body = view.querySelector('.chatroom-body'); const chat_body = view.querySelector('.chatroom-body');
expect(chat_body.querySelectorAll('.disconnect-msg').length).toBe(3); expect(chat_body.querySelectorAll('.disconnect-msg').length).toBe(3);
@ -2775,7 +2778,7 @@ describe("Groupchats", function () {
_converse.connection._dataRecv(mock.createRequest(presence)); _converse.connection._dataRecv(mock.createRequest(presence));
const view = _converse.chatboxviews.get('lounge@montague.lit'); const view = _converse.chatboxviews.get('lounge@montague.lit');
expect(u.isVisible(view.querySelector('.chat-area'))).toBeFalsy(); await u.waitUntil(() => !u.isVisible(view.querySelector('.chat-area')));
expect(u.isVisible(view.querySelector('.occupants'))).toBeFalsy(); expect(u.isVisible(view.querySelector('.occupants'))).toBeFalsy();
const chat_body = view.querySelector('.chatroom-body'); const chat_body = view.querySelector('.chatroom-body');
expect(chat_body.querySelectorAll('.disconnect-msg').length).toBe(2); expect(chat_body.querySelectorAll('.disconnect-msg').length).toBe(2);
@ -2815,7 +2818,6 @@ describe("Groupchats", function () {
// only on the right. // only on the right.
expect(_.isEqual(new_attrs.sort(), old_attrs.sort())).toEqual(true); expect(_.isEqual(new_attrs.sort(), old_attrs.sort())).toEqual(true);
} }
_converse.rosterview.render();
done(); done();
})); }));
@ -4552,7 +4554,7 @@ describe("Groupchats", function () {
await mock.waitForRoster(_converse, 'current', 0); await mock.waitForRoster(_converse, 'current', 0);
const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list'); const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list');
roomspanel.el.querySelector('.show-add-muc-modal').click(); roomspanel.querySelector('.show-add-muc-modal').click();
mock.closeControlBox(_converse); mock.closeControlBox(_converse);
const modal = _converse.api.modal.get('add-chatroom-modal'); const modal = _converse.api.modal.get('add-chatroom-modal');
await u.waitUntil(() => u.isVisible(modal.el), 1000) await u.waitUntil(() => u.isVisible(modal.el), 1000)
@ -4577,7 +4579,7 @@ describe("Groupchats", function () {
await u.waitUntil(() => sizzle('.chatroom', _converse.el).filter(u.isVisible).length === 1); await u.waitUntil(() => sizzle('.chatroom', _converse.el).filter(u.isVisible).length === 1);
roomspanel.model.set('muc_domain', 'muc.example.org'); roomspanel.model.set('muc_domain', 'muc.example.org');
roomspanel.el.querySelector('.show-add-muc-modal').click(); roomspanel.querySelector('.show-add-muc-modal').click();
label_name = modal.el.querySelector('label[for="chatroom"]'); label_name = modal.el.querySelector('label[for="chatroom"]');
expect(label_name.textContent.trim()).toBe('Groupchat address:'); expect(label_name.textContent.trim()).toBe('Groupchat address:');
name_input = modal.el.querySelector('input[name="chatroom"]'); name_input = modal.el.querySelector('input[name="chatroom"]');
@ -4591,7 +4593,7 @@ describe("Groupchats", function () {
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
await mock.waitForRoster(_converse, 'current', 0); await mock.waitForRoster(_converse, 'current', 0);
const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list'); const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list');
roomspanel.el.querySelector('.show-add-muc-modal').click(); roomspanel.querySelector('.show-add-muc-modal').click();
mock.closeControlBox(_converse); mock.closeControlBox(_converse);
const modal = _converse.api.modal.get('add-chatroom-modal'); const modal = _converse.api.modal.get('add-chatroom-modal');
await u.waitUntil(() => u.isVisible(modal.el), 1000) await u.waitUntil(() => u.isVisible(modal.el), 1000)
@ -4612,7 +4614,7 @@ describe("Groupchats", function () {
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
await mock.waitForRoster(_converse, 'current', 0); await mock.waitForRoster(_converse, 'current', 0);
const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list'); const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list');
roomspanel.el.querySelector('.show-add-muc-modal').click(); roomspanel.querySelector('.show-add-muc-modal').click();
mock.closeControlBox(_converse); mock.closeControlBox(_converse);
const modal = _converse.api.modal.get('add-chatroom-modal'); const modal = _converse.api.modal.get('add-chatroom-modal');
await u.waitUntil(() => u.isVisible(modal.el), 1000) await u.waitUntil(() => u.isVisible(modal.el), 1000)
@ -4629,7 +4631,7 @@ describe("Groupchats", function () {
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
await mock.waitForRoster(_converse, 'current', 0); await mock.waitForRoster(_converse, 'current', 0);
const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list'); const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list');
roomspanel.el.querySelector('.show-add-muc-modal').click(); roomspanel.querySelector('.show-add-muc-modal').click();
mock.closeControlBox(_converse); mock.closeControlBox(_converse);
const modal = _converse.api.modal.get('add-chatroom-modal'); const modal = _converse.api.modal.get('add-chatroom-modal');
await u.waitUntil(() => u.isVisible(modal.el), 1000) await u.waitUntil(() => u.isVisible(modal.el), 1000)
@ -4645,7 +4647,7 @@ describe("Groupchats", function () {
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list'); const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list');
roomspanel.el.querySelector('.show-add-muc-modal').click(); roomspanel.querySelector('.show-add-muc-modal').click();
const modal = _converse.api.modal.get('add-chatroom-modal'); const modal = _converse.api.modal.get('add-chatroom-modal');
await u.waitUntil(() => u.isVisible(modal.el), 1000) await u.waitUntil(() => u.isVisible(modal.el), 1000)
expect(modal.el.querySelector('.modal-title').textContent.trim()).toBe('Enter a new Groupchat'); expect(modal.el.querySelector('.modal-title').textContent.trim()).toBe('Enter a new Groupchat');
@ -4665,7 +4667,7 @@ describe("Groupchats", function () {
expect(_.includes(_converse.chatboxes.models.map(m => m.get('id')), 'lounge@muc.example.org')).toBe(true); expect(_.includes(_converse.chatboxes.models.map(m => m.get('id')), 'lounge@muc.example.org')).toBe(true);
// However, you can still open MUCs with different domains // However, you can still open MUCs with different domains
roomspanel.el.querySelector('.show-add-muc-modal').click(); roomspanel.querySelector('.show-add-muc-modal').click();
await u.waitUntil(() => u.isVisible(modal.el), 1000); await u.waitUntil(() => u.isVisible(modal.el), 1000);
name_input = modal.el.querySelector('input[name="chatroom"]'); name_input = modal.el.querySelector('input[name="chatroom"]');
name_input.value = 'lounge@conference.example.org'; name_input.value = 'lounge@conference.example.org';
@ -4684,7 +4686,7 @@ describe("Groupchats", function () {
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list'); const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list');
roomspanel.el.querySelector('.show-add-muc-modal').click(); roomspanel.querySelector('.show-add-muc-modal').click();
const modal = _converse.api.modal.get('add-chatroom-modal'); const modal = _converse.api.modal.get('add-chatroom-modal');
await u.waitUntil(() => u.isVisible(modal.el), 1000) await u.waitUntil(() => u.isVisible(modal.el), 1000)
expect(modal.el.querySelector('.modal-title').textContent.trim()).toBe('Enter a new Groupchat'); expect(modal.el.querySelector('.modal-title').textContent.trim()).toBe('Enter a new Groupchat');
@ -4703,7 +4705,7 @@ describe("Groupchats", function () {
expect(_.includes(_converse.chatboxes.models.map(m => m.get('id')), 'lounge@muc.example.org')).toBe(true); expect(_.includes(_converse.chatboxes.models.map(m => m.get('id')), 'lounge@muc.example.org')).toBe(true);
// However, you can still open MUCs with different domains // However, you can still open MUCs with different domains
roomspanel.el.querySelector('.show-add-muc-modal').click(); roomspanel.querySelector('.show-add-muc-modal').click();
await u.waitUntil(() => u.isVisible(modal.el), 1000); await u.waitUntil(() => u.isVisible(modal.el), 1000);
name_input = modal.el.querySelector('input[name="chatroom"]'); name_input = modal.el.querySelector('input[name="chatroom"]');
name_input.value = 'lounge@conference'; name_input.value = 'lounge@conference';
@ -4724,7 +4726,7 @@ describe("Groupchats", function () {
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list'); const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list');
roomspanel.el.querySelector('.show-list-muc-modal').click(); roomspanel.querySelector('.show-list-muc-modal').click();
mock.closeControlBox(_converse); mock.closeControlBox(_converse);
const modal = _converse.api.modal.get('muc-list-modal'); const modal = _converse.api.modal.get('muc-list-modal');
await u.waitUntil(() => u.isVisible(modal.el), 1000); await u.waitUntil(() => u.isVisible(modal.el), 1000);
@ -4801,7 +4803,7 @@ describe("Groupchats", function () {
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list'); const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list');
roomspanel.el.querySelector('.show-list-muc-modal').click(); roomspanel.querySelector('.show-list-muc-modal').click();
mock.closeControlBox(_converse); mock.closeControlBox(_converse);
const modal = _converse.api.modal.get('muc-list-modal'); const modal = _converse.api.modal.get('muc-list-modal');
await u.waitUntil(() => u.isVisible(modal.el), 1000); await u.waitUntil(() => u.isVisible(modal.el), 1000);
@ -4818,7 +4820,7 @@ describe("Groupchats", function () {
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list'); const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list');
roomspanel.el.querySelector('.show-list-muc-modal').click(); roomspanel.querySelector('.show-list-muc-modal').click();
mock.closeControlBox(_converse); mock.closeControlBox(_converse);
const modal = _converse.api.modal.get('muc-list-modal'); const modal = _converse.api.modal.get('muc-list-modal');
await u.waitUntil(() => u.isVisible(modal.el), 1000); await u.waitUntil(() => u.isVisible(modal.el), 1000);
@ -4868,15 +4870,15 @@ describe("Groupchats", function () {
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list'); const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list');
expect(roomspanel.el.querySelectorAll('.available-room').length).toBe(0); expect(roomspanel.querySelectorAll('.available-room').length).toBe(0);
const muc_jid = 'kitchen@conference.shakespeare.lit'; const muc_jid = 'kitchen@conference.shakespeare.lit';
const message = 'fires: Your attention is required'; const message = 'fires: Your attention is required';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'fires'); await mock.openAndEnterChatRoom(_converse, muc_jid, 'fires');
const view = _converse.api.chatviews.get(muc_jid); const view = _converse.api.chatviews.get(muc_jid);
await u.waitUntil(() => roomspanel.el.querySelectorAll('.available-room').length); await u.waitUntil(() => roomspanel.querySelectorAll('.available-room').length);
expect(roomspanel.el.querySelectorAll('.available-room').length).toBe(1); expect(roomspanel.querySelectorAll('.available-room').length).toBe(1);
expect(roomspanel.el.querySelectorAll('.msgs-indicator').length).toBe(0); expect(roomspanel.querySelectorAll('.msgs-indicator').length).toBe(0);
view.model.set({'minimized': true}); view.model.set({'minimized': true});
@ -4888,9 +4890,9 @@ describe("Groupchats", function () {
type: 'groupchat' type: 'groupchat'
}).c('body').t(message).tree()); }).c('body').t(message).tree());
await u.waitUntil(() => view.model.messages.length); await u.waitUntil(() => view.model.messages.length);
expect(roomspanel.el.querySelectorAll('.available-room').length).toBe(1); expect(roomspanel.querySelectorAll('.available-room').length).toBe(1);
expect(roomspanel.el.querySelectorAll('.msgs-indicator').length).toBe(1); expect(roomspanel.querySelectorAll('.msgs-indicator').length).toBe(1);
expect(roomspanel.el.querySelector('.msgs-indicator').textContent.trim()).toBe('1'); expect(roomspanel.querySelector('.msgs-indicator').textContent.trim()).toBe('1');
await view.model.handleMessageStanza($msg({ await view.model.handleMessageStanza($msg({
'from': muc_jid+'/'+nick, 'from': muc_jid+'/'+nick,
@ -4899,12 +4901,12 @@ describe("Groupchats", function () {
'type': 'groupchat' 'type': 'groupchat'
}).c('body').t(message).tree()); }).c('body').t(message).tree());
await u.waitUntil(() => view.model.messages.length > 1); await u.waitUntil(() => view.model.messages.length > 1);
expect(roomspanel.el.querySelectorAll('.available-room').length).toBe(1); expect(roomspanel.querySelectorAll('.available-room').length).toBe(1);
expect(roomspanel.el.querySelectorAll('.msgs-indicator').length).toBe(1); expect(roomspanel.querySelectorAll('.msgs-indicator').length).toBe(1);
expect(roomspanel.el.querySelector('.msgs-indicator').textContent.trim()).toBe('2'); expect(roomspanel.querySelector('.msgs-indicator').textContent.trim()).toBe('2');
view.model.set({'minimized': false}); view.model.set({'minimized': false});
expect(roomspanel.el.querySelectorAll('.available-room').length).toBe(1); expect(roomspanel.querySelectorAll('.available-room').length).toBe(1);
expect(roomspanel.el.querySelectorAll('.msgs-indicator').length).toBe(0); expect(roomspanel.querySelectorAll('.msgs-indicator').length).toBe(0);
done(); done();
})); }));
}); });
@ -4953,7 +4955,7 @@ describe("Groupchats", function () {
_converse.connection._dataRecv(mock.createRequest(presence)); _converse.connection._dataRecv(mock.createRequest(presence));
const occupant = view.model.occupants.findWhere({'jid': _converse.bare_jid}); const occupant = view.model.occupants.findWhere({'jid': _converse.bare_jid});
expect(occupant.get('role')).toBe('visitor'); await u.waitUntil(() => occupant.get('role') === 'visitor');
spyOn(_converse.connection, 'send'); spyOn(_converse.connection, 'send');
view.model.setChatState(_converse.INACTIVE); view.model.setChatState(_converse.INACTIVE);
@ -5260,7 +5262,7 @@ describe("Groupchats", function () {
</presence>`); </presence>`);
_converse.connection._dataRecv(mock.createRequest(stanza)); _converse.connection._dataRecv(mock.createRequest(stanza));
expect(view.querySelector('.chat-textarea')).toBe(null); await u.waitUntil(() => view.querySelector('.chat-textarea') === null);
let bottom_panel = view.querySelector('.muc-bottom-panel'); let bottom_panel = view.querySelector('.muc-bottom-panel');
expect(bottom_panel.textContent.trim()).toBe("You're not allowed to send messages in this room"); expect(bottom_panel.textContent.trim()).toBe("You're not allowed to send messages in this room");
@ -5295,8 +5297,7 @@ describe("Groupchats", function () {
</x> </x>
</presence>`); </presence>`);
_converse.connection._dataRecv(mock.createRequest(stanza)); _converse.connection._dataRecv(mock.createRequest(stanza));
bottom_panel = view.querySelector('.muc-bottom-panel'); await u.waitUntil(() => view.querySelector('.muc-bottom-panel') === null);
expect(bottom_panel).toBe(null);
textarea = view.querySelector('.chat-textarea'); textarea = view.querySelector('.chat-textarea');
expect(textarea === null).toBe(false); expect(textarea === null).toBe(false);

View File

@ -390,6 +390,8 @@ describe("A Groupchat Message", function () {
.c('status').attrs({code:'210'}).nodeTree; .c('status').attrs({code:'210'}).nodeTree;
_converse.connection._dataRecv(mock.createRequest(presence)); _converse.connection._dataRecv(mock.createRequest(presence));
await u.waitUntil(() => view.model.messages.length === 4);
msg = $msg({ msg = $msg({
from: 'lounge@montague.lit/romeo', from: 'lounge@montague.lit/romeo',
id: u.getUniqueId(), id: u.getUniqueId(),

View File

@ -12,7 +12,7 @@ describe("Notifications", function () {
describe("an HTML5 Notification", function () { describe("an HTML5 Notification", function () {
it("is shown when a new private message is received", it("is shown when a new private message is received",
mock.initConverse(['rosterContactsFetched'], {}, async (done, _converse) => { mock.initConverse([], {}, async (done, _converse) => {
await mock.waitForRoster(_converse, 'current'); await mock.waitForRoster(_converse, 'current');
const stub = jasmine.createSpyObj('MyNotification', ['onclick', 'close']); const stub = jasmine.createSpyObj('MyNotification', ['onclick', 'close']);
@ -34,7 +34,7 @@ describe("Notifications", function () {
})); }));
it("is shown when you are mentioned in a groupchat", it("is shown when you are mentioned in a groupchat",
mock.initConverse(['rosterContactsFetched'], {}, async (done, _converse) => { mock.initConverse([], {}, async (done, _converse) => {
await mock.waitForRoster(_converse, 'current'); await mock.waitForRoster(_converse, 'current');
await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo'); await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
@ -78,11 +78,12 @@ describe("Notifications", function () {
done(); done();
})); }));
it("is shown for headline messages", it("is shown for headline messages", mock.initConverse([], {}, async (done, _converse) => {
mock.initConverse(['rosterContactsFetched'], {}, async (done, _converse) => {
const stub = jasmine.createSpyObj('MyNotification', ['onclick', 'close']); const stub = jasmine.createSpyObj('MyNotification', ['onclick', 'close']);
spyOn(window, 'Notification').and.returnValue(stub); spyOn(window, 'Notification').and.returnValue(stub);
await mock.waitForRoster(_converse, 'current', 0);
const stanza = $msg({ const stanza = $msg({
'type': 'headline', 'type': 'headline',
'from': 'notify.example.com', 'from': 'notify.example.com',
@ -95,7 +96,7 @@ describe("Notifications", function () {
.c('url').t('imap://romeo@example.com/INBOX;UIDVALIDITY=385759043/;UID=18'); .c('url').t('imap://romeo@example.com/INBOX;UIDVALIDITY=385759043/;UID=18');
_converse.connection._dataRecv(mock.createRequest(stanza)); _converse.connection._dataRecv(mock.createRequest(stanza));
await u.waitUntil(() => _converse.chatboxviews.keys().length); await u.waitUntil(() => _converse.chatboxviews.keys().length === 2);
const view = _converse.chatboxviews.get('notify.example.com'); const view = _converse.chatboxviews.get('notify.example.com');
await new Promise(resolve => view.model.messages.once('rendered', resolve)); await new Promise(resolve => view.model.messages.once('rendered', resolve));
expect(_converse.chatboxviews.keys().includes('notify.example.com')).toBeTruthy(); expect(_converse.chatboxviews.keys().includes('notify.example.com')).toBeTruthy();
@ -124,7 +125,7 @@ describe("Notifications", function () {
})); }));
it("is shown when a user changes their chat state (if show_chat_state_notifications is true)", it("is shown when a user changes their chat state (if show_chat_state_notifications is true)",
mock.initConverse(['rosterContactsFetched'], {show_chat_state_notifications: true}, mock.initConverse([], {show_chat_state_notifications: true},
async (done, _converse) => { async (done, _converse) => {
await mock.waitForRoster(_converse, 'current', 3); await mock.waitForRoster(_converse, 'current', 3);
@ -152,9 +153,7 @@ describe("Notifications", function () {
describe("When play_sounds is set to true", function () { describe("When play_sounds is set to true", function () {
describe("A notification sound", function () { describe("A notification sound", function () {
it("is played when the current user is mentioned in a groupchat", it("is played when the current user is mentioned in a groupchat", mock.initConverse([], {}, async (done, _converse) => {
mock.initConverse(['rosterContactsFetched'], {}, async (done, _converse) => {
mock.createContacts(_converse, 'current'); mock.createContacts(_converse, 'current');
await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo'); await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
_converse.play_sounds = true; _converse.play_sounds = true;
@ -208,9 +207,7 @@ describe("Notifications", function () {
describe("A Favicon Message Counter", function () { describe("A Favicon Message Counter", function () {
it("is incremented when the message is received and the window is not focused", it("is incremented when the message is received and the window is not focused",
mock.initConverse( mock.initConverse([], {'show_tab_notifications': false}, async function (done, _converse) {
['rosterContactsFetched'], {'show_tab_notifications': false},
async function (done, _converse) {
await mock.waitForRoster(_converse, 'current'); await mock.waitForRoster(_converse, 'current');
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
@ -264,9 +261,7 @@ describe("Notifications", function () {
})); }));
it("is not incremented when the message is received and the window is focused", it("is not incremented when the message is received and the window is focused",
mock.initConverse( mock.initConverse([], {}, async function (done, _converse) {
['rosterContactsFetched'], {},
async function (done, _converse) {
await mock.waitForRoster(_converse, 'current'); await mock.waitForRoster(_converse, 'current');
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
@ -295,15 +290,11 @@ describe("Notifications", function () {
})); }));
it("is incremented from zero when chatbox was closed after viewing previously received messages and the window is not focused now", it("is incremented from zero when chatbox was closed after viewing previously received messages and the window is not focused now",
mock.initConverse( mock.initConverse([], {}, async function (done, _converse) {
['rosterContactsFetched'], {},
async function (done, _converse) {
await mock.waitForRoster(_converse, 'current'); await mock.waitForRoster(_converse, 'current');
const favico = jasmine.createSpyObj('favico', ['badge']); const favico = jasmine.createSpyObj('favico', ['badge']);
spyOn(converse.env, 'Favico').and.returnValue(favico); spyOn(converse.env, 'Favico').and.returnValue(favico);
const message = 'This message will always increment the message counter from zero'; const message = 'This message will always increment the message counter from zero';
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
const msgFactory = function () { const msgFactory = function () {

View File

@ -11,8 +11,7 @@ describe("Chatrooms", function () {
describe("The /register commmand", function () { describe("The /register commmand", function () {
it("allows you to register your nickname in a room", it("allows you to register your nickname in a room",
mock.initConverse( mock.initConverse(['chatBoxesFetched'], {'auto_register_muc_nickname': true},
['rosterContactsFetched', 'chatBoxesFetched'], {'auto_register_muc_nickname': true},
async function (done, _converse) { async function (done, _converse) {
const muc_jid = 'coven@chat.shakespeare.lit'; const muc_jid = 'coven@chat.shakespeare.lit';
@ -68,8 +67,7 @@ describe("Chatrooms", function () {
describe("The auto_register_muc_nickname option", function () { describe("The auto_register_muc_nickname option", function () {
it("allows you to automatically register your nickname when joining a room", it("allows you to automatically register your nickname when joining a room",
mock.initConverse( mock.initConverse(['chatBoxesFetched'], {'auto_register_muc_nickname': true},
['rosterContactsFetched', 'chatBoxesFetched'], {'auto_register_muc_nickname': true},
async function (done, _converse) { async function (done, _converse) {
const muc_jid = 'coven@chat.shakespeare.lit'; const muc_jid = 'coven@chat.shakespeare.lit';

View File

@ -7,11 +7,7 @@ const u = converse.env.utils;
describe("XSS", function () { describe("XSS", function () {
describe("A Chat Message", function () { describe("A Chat Message", function () {
it("will escape IMG payload XSS attempts", it("will escape IMG payload XSS attempts", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
mock.initConverse(
['rosterContactsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
spyOn(window, 'alert').and.callThrough(); spyOn(window, 'alert').and.callThrough();
await mock.waitForRoster(_converse, 'current'); await mock.waitForRoster(_converse, 'current');
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
@ -67,11 +63,7 @@ describe("XSS", function () {
done(); done();
})); }));
it("will escape SVG payload XSS attempts", it("will escape SVG payload XSS attempts", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
mock.initConverse(
['rosterContactsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
spyOn(window, 'alert').and.callThrough(); spyOn(window, 'alert').and.callThrough();
await mock.waitForRoster(_converse, 'current'); await mock.waitForRoster(_converse, 'current');
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
@ -127,9 +119,7 @@ describe("XSS", function () {
})); }));
it("will have properly escaped URLs", it("will have properly escaped URLs",
mock.initConverse( mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
['rosterContactsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
await mock.waitForRoster(_converse, 'current'); await mock.waitForRoster(_converse, 'current');
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
@ -185,9 +175,7 @@ describe("XSS", function () {
})); }));
it("will avoid malformed and unsafe urls urls from rendering as anchors", it("will avoid malformed and unsafe urls urls from rendering as anchors",
mock.initConverse( mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
['rosterContactsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
await mock.waitForRoster(_converse, 'current'); await mock.waitForRoster(_converse, 'current');
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
@ -270,8 +258,7 @@ describe("XSS", function () {
describe("A Groupchat", function () { describe("A Groupchat", function () {
it("escapes occupant nicknames when rendering them, to avoid JS-injection attacks", it("escapes occupant nicknames when rendering them, to avoid JS-injection attacks",
mock.initConverse(['rosterContactsFetched'], {}, mock.initConverse([], {}, async function (done, _converse) {
async function (done, _converse) {
await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo'); await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
/* <presence xmlns="jabber:client" to="jc@chat.example.org/converse.js-17184538" /* <presence xmlns="jabber:client" to="jc@chat.example.org/converse.js-17184538"
@ -294,17 +281,15 @@ describe("XSS", function () {
_converse.connection._dataRecv(mock.createRequest(presence)); _converse.connection._dataRecv(mock.createRequest(presence));
const view = _converse.chatboxviews.get('lounge@montague.lit'); const view = _converse.chatboxviews.get('lounge@montague.lit');
await u.waitUntil(() => view.querySelectorAll('li .occupant-nick').length, 500); await u.waitUntil(() => view.querySelectorAll('.occupant-list .occupant-nick').length === 2);
const occupants = view.querySelector('.occupant-list').querySelectorAll('li .occupant-nick'); const occupants = view.querySelectorAll('.occupant-list li .occupant-nick');
expect(occupants.length).toBe(2); expect(occupants.length).toBe(2);
expect(occupants[0].textContent.trim()).toBe("&lt;img src=&quot;x&quot; onerror=&quot;alert(123)&quot;/&gt;"); expect(occupants[0].textContent.trim()).toBe("&lt;img src=&quot;x&quot; onerror=&quot;alert(123)&quot;/&gt;");
done(); done();
})); }));
it("escapes the subject before rendering it, to avoid JS-injection attacks", it("escapes the subject before rendering it, to avoid JS-injection attacks",
mock.initConverse( mock.initConverse([], {}, async function (done, _converse) {
['rosterContactsFetched'], {},
async function (done, _converse) {
await mock.openAndEnterChatRoom(_converse, 'jdev@conference.jabber.org', 'jc'); await mock.openAndEnterChatRoom(_converse, 'jdev@conference.jabber.org', 'jc');
spyOn(window, 'alert'); spyOn(window, 'alert');