Browse Source

Stop using the Jasmine "done" callback

JC Brand 4 years ago
parent
commit
335a491e0d
68 changed files with 475 additions and 950 deletions
  1. 2 3
      spec/mock.js
  2. 4 8
      spec/push.js
  3. 2 4
      spec/user-details-modal.js
  4. 2 4
      src/headless/plugins/caps/tests/caps.js
  5. 2 4
      src/headless/plugins/chat/tests/api.js
  6. 2 4
      src/headless/plugins/disco/tests/disco.js
  7. 1 1
      src/headless/plugins/disco/utils.js
  8. 1 2
      src/headless/plugins/muc/tests/affiliations.js
  9. 1 2
      src/headless/plugins/muc/tests/pruning.js
  10. 2 4
      src/headless/plugins/muc/tests/registration.js
  11. 2 4
      src/headless/plugins/ping/tests/ping.js
  12. 1 2
      src/headless/plugins/roster/tests/presence.js
  13. 3 6
      src/headless/plugins/smacks/tests/smacks.js
  14. 1 2
      src/headless/plugins/status/tests/status.js
  15. 17 34
      src/headless/tests/converse.js
  16. 3 6
      src/headless/tests/eventemitter.js
  17. 1 2
      src/headless/tests/persistence.js
  18. 12 24
      src/plugins/bookmark-views/tests/bookmarks.js
  19. 34 69
      src/plugins/chatview/tests/chatbox.js
  20. 3 6
      src/plugins/chatview/tests/corrections.js
  21. 5 9
      src/plugins/chatview/tests/emojis.js
  22. 6 12
      src/plugins/chatview/tests/http-file-upload.js
  23. 3 6
      src/plugins/chatview/tests/markers.js
  24. 2 4
      src/plugins/chatview/tests/me-messages.js
  25. 1 2
      src/plugins/chatview/tests/message-audio.js
  26. 6 12
      src/plugins/chatview/tests/message-images.js
  27. 3 6
      src/plugins/chatview/tests/message-videos.js
  28. 24 48
      src/plugins/chatview/tests/messages.js
  29. 4 8
      src/plugins/chatview/tests/oob.js
  30. 4 8
      src/plugins/chatview/tests/receipts.js
  31. 4 8
      src/plugins/chatview/tests/spoilers.js
  32. 6 12
      src/plugins/chatview/tests/styling.js
  33. 7 14
      src/plugins/chatview/tests/unreads.js
  34. 4 8
      src/plugins/chatview/tests/xss.js
  35. 11 22
      src/plugins/controlbox/tests/controlbox.js
  36. 2 4
      src/plugins/controlbox/tests/login.js
  37. 5 10
      src/plugins/headlines-view/tests/headline.js
  38. 22 44
      src/plugins/mam-views/tests/mam.js
  39. 2 4
      src/plugins/mam-views/tests/placeholder.js
  40. 12 27
      src/plugins/minimize/tests/minchats.js
  41. 6 12
      src/plugins/muc-views/tests/autocomplete.js
  42. 2 4
      src/plugins/muc-views/tests/component.js
  43. 3 6
      src/plugins/muc-views/tests/corrections.js
  44. 4 8
      src/plugins/muc-views/tests/emojis.js
  45. 1 2
      src/plugins/muc-views/tests/hats.js
  46. 3 6
      src/plugins/muc-views/tests/http-file-upload.js
  47. 1 2
      src/plugins/muc-views/tests/markers.js
  48. 10 20
      src/plugins/muc-views/tests/mentions.js
  49. 7 14
      src/plugins/muc-views/tests/modtools.js
  50. 3 6
      src/plugins/muc-views/tests/muc-api.js
  51. 1 2
      src/plugins/muc-views/tests/muc-mentions.js
  52. 14 28
      src/plugins/muc-views/tests/muc-messages.js
  53. 1 2
      src/plugins/muc-views/tests/muc-registration.js
  54. 74 147
      src/plugins/muc-views/tests/muc.js
  55. 6 12
      src/plugins/muc-views/tests/muclist.js
  56. 3 6
      src/plugins/muc-views/tests/rai.js
  57. 18 36
      src/plugins/muc-views/tests/retractions.js
  58. 2 4
      src/plugins/muc-views/tests/styling.js
  59. 1 2
      src/plugins/muc-views/tests/toolbar.js
  60. 8 16
      src/plugins/muc-views/tests/unfurls.js
  61. 2 4
      src/plugins/muc-views/tests/xss.js
  62. 10 20
      src/plugins/notifications/tests/notification.js
  63. 12 24
      src/plugins/omemo/tests/omemo.js
  64. 8 16
      src/plugins/register/tests/register.js
  65. 1 2
      src/plugins/rootview/tests/root.js
  66. 1 2
      src/plugins/rosterview/tests/presence.js
  67. 4 8
      src/plugins/rosterview/tests/protocol.js
  68. 40 80
      src/plugins/rosterview/tests/roster.js

+ 2 - 3
spec/mock.js

@@ -15,7 +15,7 @@ mock.initConverse = function (promise_names=[], settings=null, func) {
         settings = null;
     }
 
-    return async done => {
+    return async () => {
         if (_converse && _converse.api.connection.connected()) {
             await _converse.api.user.logout();
         }
@@ -28,11 +28,10 @@ mock.initConverse = function (promise_names=[], settings=null, func) {
         await initConverse(settings);
         await Promise.all((promise_names || []).map(_converse.api.waitUntil));
         try {
-            await func(done, _converse);
+            await func(_converse);
         } catch(e) {
             console.error(e);
             fail(e);
-            await done();
         }
     }
 };

+ 4 - 8
spec/push.js

@@ -18,7 +18,7 @@ describe("XEP-0357 Push Notifications", function () {
                     'jid': 'push-5@client.example',
                     'node': 'yxs32uqsflafdk3iuqo'
                 }]
-            }, async function (done, _converse) {
+            }, async function (_converse) {
 
         const IQ_stanzas = _converse.connection.IQ_stanzas;
         expect(_converse.session.get('push_enabled')).toBeFalsy();
@@ -46,7 +46,6 @@ describe("XEP-0357 Push Notifications", function () {
             'id': stanza.getAttribute('id')
         })));
         await u.waitUntil(() => _converse.session.get('push_enabled'));
-        done();
     }));
 
     it("can be enabled for a MUC domain",
@@ -57,7 +56,7 @@ describe("XEP-0357 Push Notifications", function () {
                     'jid': 'push-5@client.example',
                     'node': 'yxs32uqsflafdk3iuqo'
                 }]
-            }, async function (done, _converse) {
+            }, async function (_converse) {
 
         const IQ_stanzas = _converse.connection.IQ_stanzas;
         await mock.waitUntilDiscoConfirmed(
@@ -103,7 +102,6 @@ describe("XEP-0357 Push Notifications", function () {
             'id': iq.getAttribute('id')
         })));
         await u.waitUntil(() => _.includes(_converse.session.get('push_enabled'), 'chat.shakespeare.lit'));
-        done();
     }));
 
     it("can be disabled",
@@ -114,7 +112,7 @@ describe("XEP-0357 Push Notifications", function () {
                     'node': 'yxs32uqsflafdk3iuqo',
                     'disable': true
                 }]
-            }, async function (done, _converse) {
+            }, async function (_converse) {
 
         const IQ_stanzas = _converse.connection.IQ_stanzas;
         expect(_converse.session.get('push_enabled')).toBeFalsy();
@@ -136,7 +134,6 @@ describe("XEP-0357 Push Notifications", function () {
             'id': stanza.getAttribute('id')
         })));
         await u.waitUntil(() => _converse.session.get('push_enabled'))
-        done();
     }));
 
 
@@ -147,7 +144,7 @@ describe("XEP-0357 Push Notifications", function () {
                     'node': 'yxs32uqsflafdk3iuqo',
                     'secret': 'eruio234vzxc2kla-91'
                 }]
-            }, async function (done, _converse) {
+            }, async function (_converse) {
 
         const IQ_stanzas = _converse.connection.IQ_stanzas;
         expect(_converse.session.get('push_enabled')).toBeFalsy();
@@ -179,6 +176,5 @@ describe("XEP-0357 Push Notifications", function () {
             'id': stanza.getAttribute('id')
         })));
         await u.waitUntil(() => _converse.session.get('push_enabled'))
-        done();
     }));
 });

+ 2 - 4
spec/user-details-modal.js

@@ -5,7 +5,7 @@ const u = converse.env.utils;
 describe("The User Details Modal", function () {
 
     it("can be used to remove a contact",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 1);
         _converse.api.trigger('rosterContactsFetched');
@@ -30,11 +30,10 @@ describe("The User Details Modal", function () {
         show_modal_button.click();
         remove_contact_button = modal.el.querySelector('button.remove-contact');
         expect(remove_contact_button === null).toBeTruthy();
-        done();
     }));
 
     it("shows an alert when an error happened while removing the contact",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 1);
         _converse.api.trigger('rosterContactsFetched');
@@ -71,6 +70,5 @@ describe("The User Details Modal", function () {
 
         remove_contact_button = modal.el.querySelector('button.remove-contact');
         expect(u.isVisible(remove_contact_button)).toBeTruthy();
-        done();
     }));
 });

+ 2 - 4
src/headless/plugins/caps/tests/caps.js

@@ -9,7 +9,7 @@ describe("A sent presence stanza", function () {
     afterEach(() => (jasmine.DEFAULT_TIMEOUT_INTERVAL = original_timeout));
 
     it("includes a entity capabilities node",
-            mock.initConverse([], {}, async (done, _converse) => {
+            mock.initConverse([], {}, async (_converse) => {
 
         await mock.waitForRoster(_converse, 'current', 0);
         _converse.api.disco.own.identities.clear();
@@ -27,10 +27,9 @@ describe("A sent presence stanza", function () {
                 `<priority>0</priority>`+
                 `<c hash="sha-1" node="https://conversejs.org" ver="QgayPKawpkPSDYmwT/WM94uAlu0=" xmlns="http://jabber.org/protocol/caps"/>`+
             `</presence>`)
-        done();
     }));
 
-    it("has a given priority", mock.initConverse(['statusInitialized'], {}, async (done, _converse) => {
+    it("has a given priority", mock.initConverse(['statusInitialized'], {}, async (_converse) => {
         const { api } = _converse;
         let pres = await _converse.xmppstatus.constructPresence('online', null, 'Hello world');
         expect(pres.toLocaleString()).toBe(
@@ -62,6 +61,5 @@ describe("A sent presence stanza", function () {
                 `<c hash="sha-1" node="https://conversejs.org" ver="PxXfr6uz8ClMWIga0OB/MhKNH/M=" xmlns="http://jabber.org/protocol/caps"/>`+
             `</presence>`
         );
-        done();
     }));
 });

+ 2 - 4
src/headless/plugins/chat/tests/api.js

@@ -4,7 +4,7 @@ describe("The \"chats\" API", function() {
 
     it("has a method 'get' which returns the promise that resolves to a chat model", mock.initConverse(
             ['rosterInitialized', 'chatBoxesInitialized'], {},
-            async (done, _converse) => {
+            async (_converse) => {
 
         const u = converse.env.utils;
 
@@ -34,11 +34,10 @@ describe("The \"chats\" API", function() {
         expect(Array.isArray(list)).toBeTruthy();
         expect(list[0].get('box_id')).toBe(`box-${jid}`);
         expect(list[1].get('box_id')).toBe(`box-${jid2}`);
-        done();
     }));
 
     it("has a method 'open' which opens and returns a promise that resolves to a chat model", mock.initConverse(
-            ['chatBoxesInitialized'], {}, async (done, _converse) => {
+            ['chatBoxesInitialized'], {}, async (_converse) => {
 
         await mock.openControlBox(_converse);
         await mock.waitForRoster(_converse, 'current', 2);
@@ -62,6 +61,5 @@ describe("The \"chats\" API", function() {
         expect(Array.isArray(list)).toBeTruthy();
         expect(list[0].get('box_id')).toBe(`box-${jid}`);
         expect(list[1].get('box_id')).toBe(`box-${jid2}`);
-        done();
     }));
 });

+ 2 - 4
src/headless/plugins/disco/tests/disco.js

@@ -7,7 +7,7 @@ describe("Service Discovery", function () {
         it("stores the features it receives",
             mock.initConverse(
                 ['discoInitialized'], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             const { u, $iq } = converse.env;
             const IQ_stanzas = _converse.connection.IQ_stanzas;
@@ -161,7 +161,6 @@ describe("Service Discovery", function () {
             expect(entities.get(_converse.domain).items.pluck('jid').includes('words.shakespeare.lit')).toBeTruthy();
             expect(entities.get(_converse.domain).identities.where({'category': 'conference'}).length).toBe(1);
             expect(entities.get(_converse.domain).identities.where({'category': 'directory'}).length).toBe(1);
-            done();
         }));
     });
 
@@ -169,7 +168,7 @@ describe("Service Discovery", function () {
        it("emits the serviceDiscovered event",
             mock.initConverse(
                 ['discoInitialized'], {},
-                function (done, _converse) {
+                function (_converse) {
 
             const { Strophe } = converse.env;
             spyOn(_converse.api, "trigger").and.callThrough();
@@ -178,7 +177,6 @@ describe("Service Discovery", function () {
             const last_call = _converse.api.trigger.calls.all().pop();
             expect(last_call.args[0]).toBe('serviceDiscovered');
             expect(last_call.args[1].get('var')).toBe(Strophe.NS.MAM);
-            done();
         }));
     });
 });

+ 1 - 1
src/headless/plugins/disco/utils.js

@@ -112,7 +112,7 @@ export function populateStreamFeatures () {
     // Strophe.js sets the <stream:features> element on the
     // Strophe.Connection instance (_converse.connection).
     //
-    // Once this is done, we populate the _converse.stream_features collection
+    // Once this is we populate the _converse.stream_features collection
     // and trigger streamFeaturesAdded.
     initStreamFeatures();
     Array.from(_converse.connection.features.childNodes).forEach(feature => {

+ 1 - 2
src/headless/plugins/muc/tests/affiliations.js

@@ -6,7 +6,7 @@ const Strophe = converse.env.Strophe;
 describe('The MUC Affiliations API', function () {
 
     it('can be used to set affiliations in MUCs without having to join them first',
-        mock.initConverse([], {}, async function (done, _converse) {
+        mock.initConverse([], {}, async function (_converse) {
             const { api } = _converse;
             const user_jid = 'annoyingguy@montague.lit';
             const muc_jid = 'lounge@montague.lit';
@@ -36,7 +36,6 @@ describe('The MUC Affiliations API', function () {
                     `</query>` +
                 `</iq>`);
 
-            done();
         })
     );
 });

+ 1 - 2
src/headless/plugins/muc/tests/pruning.js

@@ -8,7 +8,7 @@ describe("A Groupchat Message", function () {
         mock.initConverse(
             ['chatBoxesFetched'],
             {'prune_messages_above': 3},
-            async function (done, _converse) {
+            async function (_converse) {
 
         const muc_jid = 'lounge@montague.lit';
         const model = await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
@@ -47,6 +47,5 @@ describe("A Groupchat Message", function () {
         _converse.connection._dataRecv(mock.createRequest(stanza));
         await u.waitUntil(() => model.messages.length === 4);
         await u.waitUntil(() => model.messages.length === 3, 550);
-        done();
     }));
 });

+ 2 - 4
src/headless/plugins/muc/tests/registration.js

@@ -8,7 +8,7 @@ describe("Chatrooms", function () {
 
         it("allows you to automatically register your nickname when joining a room",
                 mock.initConverse(['chatBoxesFetched'], {'auto_register_muc_nickname': true},
-                async function (done, _converse) {
+                async function (_converse) {
 
             const muc_jid = 'coven@chat.shakespeare.lit';
             const room = await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
@@ -47,12 +47,11 @@ describe("Chatrooms", function () {
                         `</x>`+
                     `</query>`+
                 `</iq>`);
-            done();
         }));
 
         it("allows you to automatically deregister your nickname when closing a room",
                 mock.initConverse(['chatBoxesFetched'], {'auto_register_muc_nickname': 'unregister'},
-                async function (done, _converse) {
+                async function (_converse) {
 
             const muc_jid = 'coven@chat.shakespeare.lit';
             const room = await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
@@ -96,7 +95,6 @@ describe("Chatrooms", function () {
             }).c('query', {'xmlns': 'jabber:iq:register'});
             _converse.connection._dataRecv(mock.createRequest(result));
 
-            done();
         }));
     });
 });

+ 2 - 4
src/headless/plugins/ping/tests/ping.js

@@ -9,7 +9,7 @@ describe("XMPP Ping", function () {
     describe("An IQ stanza", function () {
 
         it("is returned when converse.js gets pinged",
-                mock.initConverse(['statusInitialized'], {}, (done, _converse) => {
+                mock.initConverse(['statusInitialized'], {}, (_converse) => {
             const ping = u.toStanza(`
                 <iq from="${_converse.domain}"
                     to="${_converse.jid}" id="s2c1" type="get">
@@ -19,17 +19,15 @@ describe("XMPP Ping", function () {
             const sent_stanza = _converse.connection.IQ_stanzas.pop();
             expect(Strophe.serialize(sent_stanza)).toBe(
                 `<iq id="s2c1" to="${_converse.domain}" type="result" xmlns="jabber:client"/>`);
-            done();
         }));
 
-        it("is sent out when converse.js pings a server", mock.initConverse((done, _converse) => {
+        it("is sent out when converse.js pings a server", mock.initConverse((_converse) => {
             _converse.api.ping();
             const sent_stanza = _converse.connection.IQ_stanzas.pop();
             expect(Strophe.serialize(sent_stanza)).toBe(
                 `<iq id="${sent_stanza.getAttribute('id')}" to="montague.lit" type="get" xmlns="jabber:client">`+
                     `<ping xmlns="urn:xmpp:ping"/>`+
                 `</iq>`);
-            done();
         }));
     });
 });

+ 1 - 2
src/headless/plugins/roster/tests/presence.js

@@ -5,7 +5,7 @@
 describe("A received presence stanza", function () {
 
     it("has its priority taken into account",
-        mock.initConverse([], {}, async (done, _converse) => {
+        mock.initConverse([], {}, async (_converse) => {
 
         const u = converse.env.utils;
         mock.openControlBox(_converse);
@@ -177,6 +177,5 @@ describe("A received presence stanza", function () {
         _converse.connection._dataRecv(mock.createRequest(stanza));
         expect(_converse.roster.get(contact_jid).presence.get('show')).toBe('offline');
         expect(contact.presence.resources.length).toBe(0);
-        done();
     }));
 });

+ 3 - 6
src/headless/plugins/smacks/tests/smacks.js

@@ -16,7 +16,7 @@ describe("XEP-0198 Stream Management", function () {
               'show_controlbox_by_default': true,
               'smacks_max_unacked_stanzas': 2
             },
-            async function (done, _converse) {
+            async function (_converse) {
 
         await _converse.api.user.login('romeo@montague.lit/orchard', 'secret');
         const sent_stanzas = _converse.connection.sent_stanzas;
@@ -119,7 +119,6 @@ describe("XEP-0198 Stream Management", function () {
         expect(Strophe.serialize(iq)).toBe(`<iq id="${iq.getAttribute('id')}" type="get" xmlns="jabber:client"><query xmlns="jabber:iq:roster"/></iq>`);
 
         expect(IQ_stanzas.filter(iq => sizzle('query[xmlns="jabber:iq:roster"]', iq).pop()).length).toBe(0);
-        done();
     }));
 
 
@@ -131,7 +130,7 @@ describe("XEP-0198 Stream Management", function () {
               'show_controlbox_by_default': true,
               'smacks_max_unacked_stanzas': 2
             },
-            async function (done, _converse) {
+            async function (_converse) {
 
         await _converse.api.user.login('romeo@montague.lit/orchard', 'secret');
         const sent_stanzas = _converse.connection.sent_stanzas;
@@ -173,7 +172,6 @@ describe("XEP-0198 Stream Management", function () {
         // Check that the roster gets fetched
         await mock.waitForRoster(_converse, 'current', 1);
         await new Promise(resolve => _converse.api.listen.once('reconnected', resolve));
-        done();
     }));
 
 
@@ -187,7 +185,7 @@ describe("XEP-0198 Stream Management", function () {
               'show_controlbox_by_default': true,
               'smacks_max_unacked_stanzas': 2
             },
-            async function (done, _converse) {
+            async function (_converse) {
 
         const key = "converse-test-session/converse.session-romeo@montague.lit-converse.session-romeo@montague.lit";
         sessionStorage.setItem(
@@ -266,6 +264,5 @@ describe("XEP-0198 Stream Management", function () {
         await u.waitUntil(() => muc.messages.length);
         expect(muc.messages.at(0).get('message')).toBe('First message')
         delete _converse.no_connection_on_bind;
-        done();
     }));
 });

+ 1 - 2
src/headless/plugins/status/tests/status.js

@@ -5,7 +5,7 @@ const u = converse.env.utils;
 describe("The XMPPStatus model", function () {
 
     it("won't send <show>online</show> when setting a custom status message",
-            mock.initConverse(async (done, _converse) => {
+            mock.initConverse(async (_converse) => {
 
         const sent_stanzas = _converse.connection.sent_stanzas;
         await _converse.api.user.status.set('online');
@@ -18,6 +18,5 @@ describe("The XMPPStatus model", function () {
         expect(stanza.querySelectorAll('show').length).toBe(0);
         expect(stanza.querySelectorAll('priority').length).toBe(1);
         expect(stanza.querySelector('priority').textContent).toBe('0');
-        done();
     }));
 });

+ 17 - 34
src/headless/tests/converse.js

@@ -6,7 +6,7 @@ describe("Converse", function() {
 
     describe("Authentication", function () {
 
-        it("needs either a bosh_service_url a websocket_url or both", mock.initConverse(async (done, _converse) => {
+        it("needs either a bosh_service_url a websocket_url or both", mock.initConverse(async (_converse) => {
             const url = _converse.bosh_service_url;
             const connection = _converse.connection;
             _converse.api.settings.set('bosh_service_url', undefined);
@@ -17,7 +17,6 @@ describe("Converse", function() {
                 _converse.api.settings.set('bosh_service_url', url);
                 _converse.connection = connection;
                 expect(e.message).toBe("initConnection: you must supply a value for either the bosh_service_url or websocket_url or both.");
-                done();
             }
         }));
     });
@@ -25,7 +24,7 @@ describe("Converse", function() {
     describe("A chat state indication", function () {
 
         it("are sent out when the client becomes or stops being idle",
-            mock.initConverse(['discoInitialized'], {}, (done, _converse) => {
+            mock.initConverse(['discoInitialized'], {}, (_converse) => {
 
             spyOn(_converse, 'sendCSI').and.callThrough();
             let sent_stanza;
@@ -47,14 +46,13 @@ describe("Converse", function() {
             _converse.onUserActivity();
             expect(_converse.sendCSI).toHaveBeenCalledWith('active');
             expect(Strophe.serialize(sent_stanza)).toBe('<active xmlns="urn:xmpp:csi:0"/>');
-            done();
         }));
     });
 
     describe("Automatic status change", function () {
 
         it("happens when the client is idle for long enough",
-                mock.initConverse(['initialized'], {}, async (done, _converse) => {
+                mock.initConverse(['initialized'], {}, async (_converse) => {
             let i = 0;
             // Usually initialized by registerIntervalHandler
             _converse.idle_seconds = 0;
@@ -120,7 +118,6 @@ describe("Converse", function() {
             _converse.onUserActivity();
             expect(await _converse.api.user.status.get()).toBe('dnd');
             expect(_converse.auto_changed_status).toBe(false);
-            done();
         }));
     });
 
@@ -129,15 +126,14 @@ describe("Converse", function() {
         describe("The \"status\" API", function () {
 
             it("has a method for getting the user's availability",
-                    mock.initConverse(['statusInitialized'], {}, async(done, _converse) => {
+                    mock.initConverse(['statusInitialized'], {}, async(_converse) => {
                 _converse.xmppstatus.set('status', 'online');
                 expect(await _converse.api.user.status.get()).toBe('online');
                 _converse.xmppstatus.set('status', 'dnd');
                 expect(await _converse.api.user.status.get()).toBe('dnd');
-                done();
             }));
 
-            it("has a method for setting the user's availability", mock.initConverse(async (done, _converse) => {
+            it("has a method for setting the user's availability", mock.initConverse(async (_converse) => {
                 await _converse.api.user.status.set('away');
                 expect(await _converse.xmppstatus.get('status')).toBe('away');
                 await _converse.api.user.status.set('dnd');
@@ -149,39 +145,35 @@ describe("Converse", function() {
                 const promise = _converse.api.user.status.set('invalid')
                 promise.catch(e => {
                     expect(e.message).toBe('Invalid availability value. See https://xmpp.org/rfcs/rfc3921.html#rfc.section.2.2.2.1');
-                    done();
                 });
             }));
 
-            it("allows setting the status message as well", mock.initConverse(async (done, _converse) => {
+            it("allows setting the status message as well", mock.initConverse(async (_converse) => {
                 await _converse.api.user.status.set('away', "I'm in a meeting");
                 expect(_converse.xmppstatus.get('status')).toBe('away');
                 expect(_converse.xmppstatus.get('status_message')).toBe("I'm in a meeting");
-                done();
             }));
 
             it("has a method for getting the user's status message",
-                    mock.initConverse(['statusInitialized'], {}, async (done, _converse) => {
+                    mock.initConverse(['statusInitialized'], {}, async (_converse) => {
                 await _converse.xmppstatus.set('status_message', undefined);
                 expect(await _converse.api.user.status.message.get()).toBe(undefined);
                 await _converse.xmppstatus.set('status_message', "I'm in a meeting");
                 expect(await _converse.api.user.status.message.get()).toBe("I'm in a meeting");
-                done();
             }));
 
             it("has a method for setting the user's status message",
-                    mock.initConverse(['statusInitialized'], {}, async (done, _converse) => {
+                    mock.initConverse(['statusInitialized'], {}, async (_converse) => {
                 _converse.xmppstatus.set('status_message', undefined);
                 await _converse.api.user.status.message.set("I'm in a meeting");
                 expect(_converse.xmppstatus.get('status_message')).toBe("I'm in a meeting");
-                done();
             }));
         });
     });
 
     describe("The \"tokens\" API", function () {
 
-        it("has a method for retrieving the next RID", mock.initConverse((done, _converse) => {
+        it("has a method for retrieving the next RID", mock.initConverse((_converse) => {
             mock.createContacts(_converse, 'current');
             const old_connection = _converse.connection;
             _converse.connection._proto.rid = '1234';
@@ -190,10 +182,9 @@ describe("Converse", function() {
             expect(_converse.api.tokens.get('rid')).toBe(null);
             // Restore the connection
             _converse.connection = old_connection;
-            done();
         }));
 
-        it("has a method for retrieving the SID", mock.initConverse((done, _converse) => {
+        it("has a method for retrieving the SID", mock.initConverse((_converse) => {
             mock.createContacts(_converse, 'current');
             const old_connection = _converse.connection;
             _converse.connection._proto.sid = '1234';
@@ -202,14 +193,13 @@ describe("Converse", function() {
             expect(_converse.api.tokens.get('sid')).toBe(null);
             // Restore the connection
             _converse.connection = old_connection;
-            done();
         }));
     });
 
     describe("The \"contacts\" API", function () {
 
         it("has a method 'get' which returns wrapped contacts",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current');
             let contact = await _converse.api.contacts.get('non-existing@jabber.org');
@@ -228,11 +218,10 @@ describe("Converse", function() {
             // Check that all JIDs are returned if you call without any parameters
             list = await _converse.api.contacts.get();
             expect(list.length).toBe(mock.cur_names.length);
-            done();
         }));
 
         it("has a method 'add' with which contacts can be added",
-                mock.initConverse(['rosterInitialized'], {}, async (done, _converse) => {
+                mock.initConverse(['rosterInitialized'], {}, async (_converse) => {
 
             await mock.waitForRoster(_converse, 'current', 0);
             try {
@@ -251,13 +240,12 @@ describe("Converse", function() {
             spyOn(_converse.roster, 'addAndSubscribe');
             await _converse.api.contacts.add("newcontact@example.org");
             expect(_converse.roster.addAndSubscribe).toHaveBeenCalled();
-            done();
         }));
     });
 
     describe("The \"settings\" API", function() {
         it("has methods 'get' and 'set' to set configuration settings",
-                mock.initConverse(null, {'play_sounds': true}, (done, _converse) => {
+                mock.initConverse(null, {'play_sounds': true}, (_converse) => {
 
             expect(Object.keys(_converse.api.settings)).toEqual(["extend", "update", "get", "set"]);
             expect(_converse.api.settings.get("play_sounds")).toBe(true);
@@ -269,11 +257,10 @@ describe("Converse", function() {
             expect(typeof _converse.api.settings.get("non_existing")).toBe("undefined");
             _converse.api.settings.set("non_existing", true);
             expect(typeof _converse.api.settings.get("non_existing")).toBe("undefined");
-            done();
         }));
 
         it("extended via settings.extend don't override settings passed in via converse.initialize",
-                mock.initConverse([], {'emoji_categories': {"travel": ":rocket:"}}, (done, _converse) => {
+                mock.initConverse([], {'emoji_categories': {"travel": ":rocket:"}}, (_converse) => {
 
             expect(_converse.api.settings.get('emoji_categories')?.travel).toBe(':rocket:');
 
@@ -283,7 +270,6 @@ describe("Converse", function() {
 
             expect(_converse.api.settings.get('emoji_categories')?.travel).toBe(':rocket:');
             expect(_converse.api.settings.get('emoji_categories')?.food).toBe(undefined);
-            done();
         }));
 
         it("only overrides the passed in properties",
@@ -292,7 +278,7 @@ describe("Converse", function() {
                     'root': document.createElement('div').attachShadow({ 'mode': 'open' }),
                     'emoji_categories': { 'travel': ':rocket:' },
                 },
-                (done, _converse) => {
+                (_converse) => {
                     expect(_converse.api.settings.get('emoji_categories')?.travel).toBe(':rocket:');
 
                     // Test that the extend command doesn't override user-provided site
@@ -303,7 +289,6 @@ describe("Converse", function() {
 
                     expect(_converse.api.settings.get('emoji_categories').travel).toBe(':rocket:');
                     expect(_converse.api.settings.get('emoji_categories').food).toBe(undefined);
-                    done();
                 }
             )
         );
@@ -311,7 +296,7 @@ describe("Converse", function() {
     });
 
     describe("The \"plugins\" API", function() {
-        it("only has a method 'add' for registering plugins", mock.initConverse((done, _converse) => {
+        it("only has a method 'add' for registering plugins", mock.initConverse((_converse) => {
             expect(Object.keys(converse.plugins)).toEqual(["add"]);
             // Cheating a little bit. We clear the plugins to test more easily.
             const _old_plugins = _converse.pluggable.plugins;
@@ -321,17 +306,15 @@ describe("Converse", function() {
             converse.plugins.add('plugin2', {});
             expect(Object.keys(_converse.pluggable.plugins)).toEqual(['plugin1', 'plugin2']);
             _converse.pluggable.plugins = _old_plugins;
-            done();
         }));
 
         describe("The \"plugins.add\" method", function() {
             it("throws an error when multiple plugins attempt to register with the same name",
-                    mock.initConverse((done, _converse) => {  // eslint-disable-line no-unused-vars
+                    mock.initConverse((_converse) => {  // eslint-disable-line no-unused-vars
 
                 converse.plugins.add('myplugin', {});
                 const error = new TypeError('Error: plugin with name "myplugin" has already been registered!');
                 expect(() => converse.plugins.add('myplugin', {})).toThrow(error);
-                done();
             }));
         });
     });

+ 3 - 6
src/headless/tests/eventemitter.js

@@ -2,7 +2,7 @@
 
 describe("The _converse Event Emitter", function() {
 
-    it("allows you to subscribe to emitted events", mock.initConverse((done, _converse) => {
+    it("allows you to subscribe to emitted events", mock.initConverse((_converse) => {
         this.callback = function () {};
         spyOn(this, 'callback');
         _converse.on('connected', this.callback);
@@ -12,10 +12,9 @@ describe("The _converse Event Emitter", function() {
         expect(this.callback.calls.count(), 2);
         _converse.api.trigger('connected');
         expect(this.callback.calls.count(), 3);
-        done();
     }));
 
-    it("allows you to listen once for an emitted event", mock.initConverse((done, _converse) => {
+    it("allows you to listen once for an emitted event", mock.initConverse((_converse) => {
         this.callback = function () {};
         spyOn(this, 'callback');
         _converse.once('connected', this.callback);
@@ -25,10 +24,9 @@ describe("The _converse Event Emitter", function() {
         expect(this.callback.calls.count(), 1);
         _converse.api.trigger('connected');
         expect(this.callback.calls.count(), 1);
-        done();
     }));
 
-    it("allows you to stop listening or subscribing to an event", mock.initConverse((done, _converse) => {
+    it("allows you to stop listening or subscribing to an event", mock.initConverse((_converse) => {
         this.callback = function () {};
         this.anotherCallback = function () {};
         this.neverCalled = function () {};
@@ -56,6 +54,5 @@ describe("The _converse Event Emitter", function() {
         expect(this.callback.calls.count(), 1);
         expect(this.anotherCallback.calls.count(), 3);
         expect(this.neverCalled).not.toHaveBeenCalled();
-        done();
     }));
 });

+ 1 - 2
src/headless/tests/persistence.js

@@ -3,10 +3,9 @@
 describe("The persistent store", function() {
 
     it("is unique to the user based on their JID",
-            mock.initConverse([], {'persistent_store': 'IndexedDB'}, (done, _converse) => {
+            mock.initConverse([], {'persistent_store': 'IndexedDB'}, (_converse) => {
 
         expect(_converse.storage.persistent.config().storeName).toBe(_converse.bare_jid);
         expect(_converse.storage.persistent.config().description).toBe('indexedDB instance');
-        done();
     }));
 });

+ 12 - 24
src/plugins/bookmark-views/tests/bookmarks.js

@@ -6,7 +6,7 @@ const { Strophe, u, sizzle, $iq } = converse.env;
 describe("A chat room", function () {
 
     it("can be bookmarked", mock.initConverse(
-            ['chatBoxesFetched'], {}, async function (done, _converse) {
+            ['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 0);
         await mock.waitUntilDiscoConfirmed(
@@ -128,12 +128,11 @@ describe("A chat room", function () {
         expect(u.hasClass('on-button', view.querySelector('.toggle-bookmark')), true);
         // We ignore this IQ stanza... (unless it's an error stanza), so
         // nothing to test for here.
-        done();
     }));
 
 
     it("will be automatically opened if 'autojoin' is set on the bookmark", mock.initConverse(
-            ['chatBoxesFetched'], {}, async function (done, _converse) {
+            ['chatBoxesFetched'], {}, async function (_converse) {
 
         const { u } = converse.env;
         await mock.waitForRoster(_converse, 'current', 0);
@@ -172,13 +171,12 @@ describe("A chat room", function () {
             'nick': ' Othello'
         });
         expect(_converse.chatboxviews.get(jid) === undefined).toBe(true);
-        done();
     }));
 
 
     describe("when bookmarked", function () {
 
-        it("will use the nickname from the bookmark", mock.initConverse([], {}, async function (done, _converse) {
+        it("will use the nickname from the bookmark", mock.initConverse([], {}, async function (_converse) {
             const { u } = converse.env;
             await mock.waitForRoster(_converse, 'current', 0);
             await mock.waitUntilBookmarksReturned(_converse);
@@ -195,10 +193,9 @@ describe("A chat room", function () {
             const room = await room_creation_promise;
             await u.waitUntil(() => room.getAndPersistNickname.calls.count());
             expect(room.get('nick')).toBe('Othello');
-            done();
         }));
 
-        it("displays that it's bookmarked through its bookmark icon", mock.initConverse([], {}, async function (done, _converse) {
+        it("displays that it's bookmarked through its bookmark icon", mock.initConverse([], {}, async function (_converse) {
 
             const { u } = converse.env;
             await mock.waitForRoster(_converse, 'current', 0);
@@ -220,10 +217,9 @@ describe("A chat room", function () {
             await u.waitUntil(() => view.querySelector('.chatbox-title__text .fa-bookmark') !== null);
             view.model.set('bookmarked', false);
             await u.waitUntil(() => view.querySelector('.chatbox-title__text .fa-bookmark') === null);
-            done();
         }));
 
-        it("can be unbookmarked", mock.initConverse([], {}, async function (done, _converse) {
+        it("can be unbookmarked", mock.initConverse([], {}, async function (_converse) {
 
             const { u, Strophe } = converse.env;
             await mock.waitForRoster(_converse, 'current', 0);
@@ -282,14 +278,13 @@ describe("A chat room", function () {
                     `</pubsub>`+
                 `</iq>`
             );
-            done();
         }));
     });
 
     describe("and when autojoin is set", function () {
 
         it("will be be opened and joined automatically upon login", mock.initConverse(
-                [], {}, async function (done, _converse) {
+                [], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 0);
             await mock.waitUntilBookmarksReturned(_converse);
@@ -310,7 +305,6 @@ describe("A chat room", function () {
                 'nick': ''
             });
             expect(_converse.api.rooms.create).toHaveBeenCalled();
-            done();
         }));
     });
 });
@@ -318,7 +312,7 @@ describe("A chat room", function () {
 describe("Bookmarks", function () {
 
     it("can be pushed from the XMPP server", mock.initConverse(
-            ['connected', 'chatBoxesFetched'], {}, async function (done, _converse) {
+            ['connected', 'chatBoxesFetched'], {}, async function (_converse) {
 
         const { $msg, u } = converse.env;
         await mock.waitForRoster(_converse, 'current', 0);
@@ -403,13 +397,12 @@ describe("Bookmarks", function () {
         expect(_converse.bookmarks.map(b => b.get('name'))).toEqual(['Second bookmark', 'The Play&apos;s the Thing', 'Yet another bookmark']);
         expect(_converse.chatboxviews.get('theplay@conference.shakespeare.lit')).not.toBeUndefined();
         expect(Object.keys(_converse.chatboxviews.getAll()).length).toBe(2);
-        done();
     }));
 
 
     it("can be retrieved from the XMPP server", mock.initConverse(
             ['chatBoxesFetched'], {},
-            async function (done, _converse) {
+            async function (_converse) {
 
         const { Strophe, sizzle, u, $iq } = converse.env;
         await mock.waitForRoster(_converse, 'current', 0);
@@ -483,13 +476,12 @@ describe("Bookmarks", function () {
         expect(_converse.bookmarks.models.length).toBe(2);
         expect(_converse.bookmarks.findWhere({'jid': 'theplay@conference.shakespeare.lit'}).get('autojoin')).toBe(true);
         expect(_converse.bookmarks.findWhere({'jid': 'another@conference.shakespeare.lit'}).get('autojoin')).toBe(false);
-        done();
     }));
 
     describe("The bookmarks list", function () {
 
         it("shows a list of bookmarks", mock.initConverse(
-                [], {}, async function (done, _converse) {
+                [], {}, async function (_converse) {
 
             await mock.waitUntilDiscoConfirmed(
                 _converse, _converse.bare_jid,
@@ -560,11 +552,10 @@ describe("Bookmarks", function () {
             expect(els[1].textContent).toBe("Bookmark with a very very long name that will be shortened");
             expect(els[2].textContent).toBe("noname@conference.shakespeare.lit");
             expect(els[3].textContent).toBe("The Play's the Thing");
-            done();
         }));
 
         it("can be used to open a MUC from a bookmark", mock.initConverse(
-                [], {'view_mode': 'fullscreen'}, async function (done, _converse) {
+                [], {'view_mode': 'fullscreen'}, async function (_converse) {
 
             const api = _converse.api;
             await mock.waitUntilDiscoConfirmed(
@@ -610,11 +601,10 @@ describe("Bookmarks", function () {
             await u.waitUntil(() => view.querySelector('.list-item.open').getAttribute('data-room-jid') === 'first@conference.shakespeare.lit');
             expect((await api.rooms.get('first@conference.shakespeare.lit')).get('hidden')).toBe(false);
             expect((await api.rooms.get('theplay@conference.shakespeare.lit')).get('hidden')).toBe(true);
-            done();
         }));
 
         it("remembers the toggle state of the bookmarks list", mock.initConverse(
-                [], {}, async function (done, _converse) {
+                [], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 0);
             await mock.openControlBox(_converse);
@@ -665,7 +655,6 @@ describe("Bookmarks", function () {
             expect(u.hasClass('collapsed', sizzle('#chatrooms .bookmarks.rooms-list', chats_el).pop())).toBeFalsy();
             expect(sizzle(selector, chats_el).filter(u.isVisible).length).toBe(1);
             expect(bookmarks_el.model.get('toggle-state')).toBe(_converse.OPENED);
-            done();
         }));
     });
 });
@@ -673,7 +662,7 @@ describe("Bookmarks", function () {
 describe("When hide_open_bookmarks is true and a bookmarked room is opened", function () {
 
     it("can be closed", mock.initConverse(
-            [], { hide_open_bookmarks: true }, async function (done, _converse) {
+            [], { hide_open_bookmarks: true }, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 0);
         await mock.openControlBox(_converse);
@@ -704,6 +693,5 @@ describe("When hide_open_bookmarks is true and a bookmarked room is opened", fun
         const view = _converse.chatboxviews.get(jid);
         view.close();
         await u.waitUntil(() => !u.hasClass('hidden', bookmarks_el.querySelector(".available-chatroom")));
-        done();
     }));
 });

+ 34 - 69
src/plugins/chatview/tests/chatbox.js

@@ -13,7 +13,7 @@ describe("Chatboxes", function () {
 
     describe("A Chatbox", function () {
 
-        it("has a /help command to show the available commands", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+        it("has a /help command to show the available commands", mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 1);
             await mock.openControlBox(_converse);
@@ -40,11 +40,10 @@ describe("Chatboxes", function () {
             await u.waitUntil(() => view.querySelectorAll('.chat-msg').length);
             const msg_txt_sel = 'converse-chat-message:last-child .chat-msg__body';
             await u.waitUntil(() => view.querySelector(msg_txt_sel).textContent.trim() === 'hello world');
-            done();
         }));
 
 
-        it("has a /clear command", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+        it("has a /clear command", mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
             await mock.waitForRoster(_converse, 'current', 1);
             await mock.openControlBox(_converse);
             const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -67,12 +66,11 @@ describe("Chatboxes", function () {
             });
             expect(window.confirm).toHaveBeenCalled();
             await u.waitUntil(() => sizzle('converse-chat-message', view).length === 0);
-            done();
         }));
 
 
         it("is created when you click on a roster item", mock.initConverse(
-                ['chatBoxesFetched'], {}, async function (done, _converse) {
+                ['chatBoxesFetched'], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current');
             await mock.openControlBox(_converse);
@@ -98,12 +96,11 @@ describe("Chatboxes", function () {
             // Check that new chat boxes are created to the left of the
             // controlbox (but to the right of all existing chat boxes)
             expect(document.querySelectorAll("#conversejs .chatbox").length).toBe(3);
-            done();
         }));
 
         it("opens when a new message is received", mock.initConverse(
                 [], {'allow_non_roster_messaging': true},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 0);
             const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -120,10 +117,9 @@ describe("Chatboxes", function () {
             await u.waitUntil(() => message_promise);
             expect(_converse.chatboxviews.keys().length).toBe(2);
             expect(_converse.chatboxviews.keys().pop()).toBe(sender_jid);
-            done();
         }));
 
-        it("doesn't open when a message without body is received", mock.initConverse([], {}, async function (done, _converse) {
+        it("doesn't open when a message without body is received", mock.initConverse([], {}, async function (_converse) {
             await mock.waitForRoster(_converse, 'current', 1);
             const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
             const stanza = u.toStanza(`
@@ -136,11 +132,10 @@ describe("Chatboxes", function () {
             _converse.connection._dataRecv(mock.createRequest(stanza));
             await u.waitUntil(() => message_promise);
             expect(_converse.chatboxviews.keys().length).toBe(1);
-            done();
         }));
 
         it("is focused if its already open and you click on its corresponding roster item",
-                mock.initConverse(['chatBoxesFetched'], {'auto_focus': true}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {'auto_focus': true}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current');
             await mock.openControlBox(_converse);
@@ -159,11 +154,10 @@ describe("Chatboxes", function () {
             await u.waitUntil(() => view.focus.calls.count(), 1000);
             expect(view.focus).toHaveBeenCalled();
             expect(_converse.chatboxes.length).toEqual(2);
-            done();
         }));
 
         it("can be saved to, and retrieved from, browserStorage",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             spyOn(_converse.minimize, 'trimChats');
             await mock.waitForRoster(_converse, 'current');
@@ -192,11 +186,10 @@ describe("Chatboxes", function () {
                 old_attrs = _converse.chatboxes.models.map(m => m.attributes[i]);
                 expect(new_attrs).toEqual(old_attrs);
             }
-            done();
         }));
 
         it("can be closed by clicking a DOM element with class 'close-chatbox-button'",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current');
             await mock.openControlBox(_converse);
@@ -211,11 +204,10 @@ describe("Chatboxes", function () {
             expect(chatview.model.close).toHaveBeenCalled();
             await new Promise(resolve => _converse.api.listen.once('chatBoxClosed', resolve));
             expect(_converse.api.trigger).toHaveBeenCalledWith('chatBoxClosed', jasmine.any(Object));
-            done();
         }));
 
         it("will be removed from browserStorage when closed",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current');
             await mock.openControlBox(_converse);
@@ -248,13 +240,12 @@ describe("Chatboxes", function () {
             await new Promise(resolve => _converse.api.listen.on('chatBoxesFetched', resolve));
             expect(newchatboxes.length).toEqual(1);
             expect(newchatboxes.models[0].id).toBe("controlbox");
-            done();
         }));
 
         describe("A chat toolbar", function () {
 
             it("shows the remaining character count if a message_limit is configured",
-                    mock.initConverse(['chatBoxesFetched'], {'message_limit': 200}, async function (done, _converse) {
+                    mock.initConverse(['chatBoxesFetched'], {'message_limit': 200}, async function (_converse) {
 
                 await mock.waitForRoster(_converse, 'current', 3);
                 await mock.openControlBox(_converse);
@@ -288,12 +279,11 @@ describe("Chatboxes", function () {
                 textarea.value = 'hello world';
                 message_form.onKeyUp(ev);
                 await u.waitUntil(() => counter.textContent === '189');
-                done();
             }));
 
 
             it("does not show a remaining character count if message_limit is zero",
-                    mock.initConverse(['chatBoxesFetched'], {'message_limit': 0}, async function (done, _converse) {
+                    mock.initConverse(['chatBoxesFetched'], {'message_limit': 0}, async function (_converse) {
 
                 await mock.waitForRoster(_converse, 'current', 3);
                 await mock.openControlBox(_converse);
@@ -302,12 +292,11 @@ describe("Chatboxes", function () {
                 const view = _converse.chatboxviews.get(contact_jid);
                 const counter = view.querySelector('.chat-toolbar .message-limit');
                 expect(counter).toBe(null);
-                done();
             }));
 
 
             it("can contain a button for starting a call",
-                    mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                    mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
                 await mock.waitForRoster(_converse, 'current');
                 await mock.openControlBox(_converse);
@@ -333,13 +322,12 @@ describe("Chatboxes", function () {
                 call_button = toolbar.querySelector('.toggle-call');
                 call_button.click();
                 expect(_converse.api.trigger).toHaveBeenCalledWith('callButtonClicked', jasmine.any(Object));
-                done();
             }));
         });
 
         describe("A Chat Status Notification", function () {
 
-            it("does not open a new chatbox", mock.initConverse([], {}, async function (done, _converse) {
+            it("does not open a new chatbox", mock.initConverse([], {}, async function (_converse) {
                 await mock.waitForRoster(_converse, 'current');
                 await mock.openControlBox(_converse);
 
@@ -357,13 +345,12 @@ describe("Chatboxes", function () {
                 await u.waitUntil(() => _converse.api.trigger.calls.count());
                 expect(_converse.api.trigger).toHaveBeenCalledWith('message', jasmine.any(Object));
                 expect(_converse.chatboxviews.keys().length).toBe(1);
-                done();
             }));
 
             describe("An active notification", function () {
 
                 it("is sent when the user opens a chat box",
-                        mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                        mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
                     await mock.waitForRoster(_converse, 'current');
                     const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -381,11 +368,10 @@ describe("Chatboxes", function () {
                     expect(stanza.childNodes[0].tagName).toBe('active');
                     expect(stanza.childNodes[1].tagName).toBe('no-store');
                     expect(stanza.childNodes[2].tagName).toBe('no-permanent-store');
-                    done();
                 }));
 
                 it("is sent when the user maximizes a minimized a chat box", mock.initConverse(
-                        ['chatBoxesFetched'], {}, async function (done, _converse) {
+                        ['chatBoxesFetched'], {}, async function (_converse) {
 
                     await mock.waitForRoster(_converse, 'current', 1);
                     await mock.openControlBox(_converse);
@@ -409,14 +395,13 @@ describe("Chatboxes", function () {
                             `<no-permanent-store xmlns="urn:xmpp:hints"/>`+
                         `</message>`
                     );
-                    done();
                 }));
             });
 
             describe("A composing notification", function () {
 
                 it("is sent as soon as the user starts typing a message which is not a command",
-                        mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                        mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
                     await mock.waitForRoster(_converse, 'current');
                     await mock.openControlBox(_converse);
@@ -452,12 +437,11 @@ describe("Chatboxes", function () {
                     });
                     expect(view.model.get('chat_state')).toBe('composing');
                     expect(_converse.api.trigger.calls.count(), 1);
-                    done();
                 }));
 
                 it("is NOT sent out if send_chat_state_notifications doesn't allow it",
                     mock.initConverse(['chatBoxesFetched'], {'send_chat_state_notifications': []},
-                        async function (done, _converse) {
+                        async function (_converse) {
 
                     await mock.waitForRoster(_converse, 'current');
                     await mock.openControlBox(_converse);
@@ -477,10 +461,9 @@ describe("Chatboxes", function () {
                     });
                     expect(view.model.get('chat_state')).toBe('composing');
                     expect(_converse.connection.send).not.toHaveBeenCalled();
-                    done();
                 }));
 
-                it("will be shown if received", mock.initConverse([], {}, async function (done, _converse) {
+                it("will be shown if received", mock.initConverse([], {}, async function (_converse) {
                     await mock.waitForRoster(_converse, 'current');
                     await mock.openControlBox(_converse);
 
@@ -525,11 +508,10 @@ describe("Chatboxes", function () {
                     const msg_el = await u.waitUntil(() => view.querySelector('.chat-msg'));
                     await u.waitUntil( () => view.querySelector('.chat-content__notifications').innerText === '');
                     expect(msg_el.querySelector('.chat-msg__text').textContent).toBe('hello world');
-                    done();
                 }));
 
                 it("is ignored if it's a composing carbon message sent by this user from a different client",
-                        mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                        mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
                     await mock.waitUntilDiscoConfirmed(_converse, 'montague.lit', [], ['vcard-temp']);
                     await u.waitUntil(() => _converse.xmppstatus.vcard.get('fullname'));
@@ -560,14 +542,13 @@ describe("Chatboxes", function () {
                     expect(view.model.messages.length).toEqual(0);
                     const el = view.querySelector('.chat-content__notifications');
                     expect(el.textContent).toBe('');
-                    done();
                 }));
             });
 
             describe("A paused notification", function () {
 
                 it("is sent if the user has stopped typing since 30 seconds",
-                        mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                        mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
                     await mock.waitForRoster(_converse, 'current');
                     const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -624,10 +605,9 @@ describe("Chatboxes", function () {
                         keyCode: 1
                     });
                     expect(view.model.get('chat_state')).toBe('composing');
-                    done();
                 }));
 
-                it("will be shown if received", mock.initConverse([], {}, async function (done, _converse) {
+                it("will be shown if received", mock.initConverse([], {}, async function (_converse) {
                     await mock.waitForRoster(_converse, 'current');
                     await mock.openControlBox(_converse);
                     const rosterview = document.querySelector('converse-roster');
@@ -649,11 +629,10 @@ describe("Chatboxes", function () {
                     const csn = mock.cur_names[1] +  ' has stopped typing';
                     await u.waitUntil( () => view.querySelector('.chat-content__notifications').innerText === csn);
                     expect(view.model.messages.length).toEqual(0);
-                    done();
                 }));
 
                 it("will not be shown if it's a paused carbon message that this user sent from a different client",
-                        mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                        mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
                     await mock.waitUntilDiscoConfirmed(_converse, 'montague.lit', [], ['vcard-temp']);
                     await u.waitUntil(() => _converse.xmppstatus.vcard.get('fullname'));
@@ -681,15 +660,13 @@ describe("Chatboxes", function () {
                     expect(view.model.messages.length).toEqual(0);
                     const el = view.querySelector('.chat-content__notifications');
                     expect(el.textContent).toBe('');
-                    done();
-                    done();
                 }));
             });
 
             describe("An inactive notification", function () {
 
                 it("is sent if the user has stopped typing since 2 minutes",
-                        mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                        mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
                     const sent_stanzas = _converse.connection.sent_stanzas;
                     // Make the timeouts shorter so that we can test
@@ -750,11 +727,10 @@ describe("Chatboxes", function () {
                             `<no-permanent-store xmlns="urn:xmpp:hints"/>`+
                         `</message>`);
 
-                    done();
                 }));
 
                 it("is sent when the user a minimizes a chat box",
-                    mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                    mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
                     await mock.waitForRoster(_converse, 'current');
                     await mock.openControlBox(_converse);
@@ -769,11 +745,10 @@ describe("Chatboxes", function () {
                     var stanza = _converse.connection.send.calls.argsFor(0)[0];
                     expect(stanza.getAttribute('to')).toBe(contact_jid);
                     expect(stanza.childNodes[0].tagName).toBe('inactive');
-                    done();
                 }));
 
                 it("is sent if the user closes a chat box",
-                        mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                        mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
                     await mock.waitForRoster(_converse, 'current');
                     const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -792,11 +767,10 @@ describe("Chatboxes", function () {
                     expect(stanza.childNodes[0].tagName).toBe('inactive');
                     expect(stanza.childNodes[1].tagName).toBe('no-store');
                     expect(stanza.childNodes[2].tagName).toBe('no-permanent-store');
-                    done();
                 }));
 
                 it("will clear any other chat status notifications",
-                        mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                        mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
                     await mock.waitForRoster(_converse, 'current');
                     await mock.openControlBox(_converse);
@@ -829,13 +803,12 @@ describe("Chatboxes", function () {
                     _converse.connection._dataRecv(mock.createRequest(msg));
 
                     await u.waitUntil(() => !view.querySelector('.chat-content__notifications').textContent);
-                    done();
                 }));
             });
 
             describe("A gone notification", function () {
 
-                it("will be shown if received", mock.initConverse([], {}, async function (done, _converse) {
+                it("will be shown if received", mock.initConverse([], {}, async function (_converse) {
                     await mock.waitForRoster(_converse, 'current', 3);
                     await mock.openControlBox(_converse);
                     const sender_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -852,13 +825,12 @@ describe("Chatboxes", function () {
                     const view = _converse.chatboxviews.get(sender_jid);
                     const csntext = await u.waitUntil(() => view.querySelector('.chat-content__notifications').textContent);
                     expect(csntext).toEqual(mock.cur_names[1] + ' has gone away');
-                    done();
                 }));
             });
 
             describe("On receiving a message correction", function () {
 
-                it("will be removed", mock.initConverse([], {}, async function (done, _converse) {
+                it("will be removed", mock.initConverse([], {}, async function (_converse) {
                     await mock.waitForRoster(_converse, 'current');
                     await mock.openControlBox(_converse);
 
@@ -910,7 +882,6 @@ describe("Chatboxes", function () {
 
                     await _converse.handleMessageStanza(edited);
                     await u.waitUntil(() => !view.querySelector('.chat-content__notifications').textContent);
-                    done();
                 }));
             });
         });
@@ -919,7 +890,7 @@ describe("Chatboxes", function () {
     describe("Special Messages", function () {
 
         it("'/clear' can be used to clear messages in a conversation",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current');
             await mock.openControlBox(_converse);
@@ -948,7 +919,6 @@ describe("Chatboxes", function () {
             expect(window.confirm).toHaveBeenCalledWith('Are you sure you want to clear the messages from this conversation?');
             await u.waitUntil(() => view.model.messages.length === 0);
             await u.waitUntil(() => !view.querySelectorAll('.chat-msg__body').length);
-            done();
         }));
     });
 
@@ -956,7 +926,7 @@ describe("Chatboxes", function () {
     describe("A RosterView's Unread Message Count", function () {
 
         it("is updated when message is received and chatbox is scrolled up",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 1);
             let msg, indicator_el;
@@ -977,11 +947,10 @@ describe("Chatboxes", function () {
             await u.waitUntil(() => chatbox.messages.length > 1);
             indicator_el = sizzle(selector, rosterview).pop();
             expect(indicator_el.textContent).toBe('2');
-            done();
         }));
 
         it("is updated when message is received and chatbox is minimized",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 1);
             const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -1005,11 +974,10 @@ describe("Chatboxes", function () {
             await u.waitUntil(() => chatbox.messages.length === 2);
             indicator_el = sizzle(selector, rosterview).pop();
             expect(indicator_el.textContent).toBe('2');
-            done();
         }));
 
         it("is cleared when chatbox is maximzied after receiving messages in minimized mode",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 1);
             const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -1030,11 +998,10 @@ describe("Chatboxes", function () {
             expect(select_msgs_indicator().textContent).toBe('2');
             _converse.minimize.maximize(view.model);
             u.waitUntil(() => typeof select_msgs_indicator() === 'undefined');
-            done();
         }));
 
         it("is cleared when unread messages are viewed which were received in scrolled-up chatbox",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             await mock.openControlBox(_converse);
             await mock.waitForRoster(_converse, 'current', 1);
@@ -1054,11 +1021,10 @@ describe("Chatboxes", function () {
             const chat_new_msgs_indicator = await u.waitUntil(() => view.querySelector('.new-msgs-indicator'));
             chat_new_msgs_indicator.click();
             await u.waitUntil(() => select_msgs_indicator() === undefined);
-            done();
         }));
 
         it("is not cleared after user clicks on roster view when chatbox is already opened and scrolled up",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 1);
             const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -1077,7 +1043,6 @@ describe("Chatboxes", function () {
             expect(select_msgs_indicator().textContent).toBe('1');
             await mock.openChatBoxFor(_converse, sender_jid);
             expect(select_msgs_indicator().textContent).toBe('1');
-            done();
         }));
     });
 });

+ 3 - 6
src/plugins/chatview/tests/corrections.js

@@ -5,7 +5,7 @@ const { Promise, $msg, Strophe, sizzle, u } = converse.env;
 describe("A Chat Message", function () {
 
     it("can be sent as a correction by using the up arrow",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 1);
         await mock.openControlBox(_converse);
@@ -161,12 +161,11 @@ describe("A Chat Message", function () {
         expect(view.model.messages.at(0).get('correcting')).toBeFalsy();
         expect(view.model.messages.at(1).get('correcting')).toBeFalsy();
         expect(view.model.messages.at(2).get('correcting')).toBeFalsy();
-        done();
     }));
 
 
     it("can be sent as a correction by clicking the pencil icon",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 1);
         await mock.openControlBox(_converse);
@@ -285,14 +284,13 @@ describe("A Chat Message", function () {
             ['You have an unsent message which will be lost if you continue. Are you sure?']);
         expect(window.confirm.calls.argsFor(1)).toEqual(
             ['You have an unsent message which will be lost if you continue. Are you sure?']);
-        done();
     }));
 
 
     describe("when received from someone else", function () {
 
         it("can be replaced with a correction",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 1);
             await mock.openControlBox(_converse);
@@ -346,7 +344,6 @@ describe("A Chat Message", function () {
             expect(older_msgs.length).toBe(2);
             expect(older_msgs[0].textContent.includes('But soft, what light through yonder airlock breaks?')).toBe(true);
             expect(view.model.messages.models.length).toBe(1);
-            done();
         }));
     });
 });

+ 5 - 9
src/plugins/chatview/tests/emojis.js

@@ -11,7 +11,7 @@ describe("Emojis", function () {
         afterEach(() => (jasmine.DEFAULT_TIMEOUT_INTERVAL = original_timeout));
 
         it("can be opened by clicking a button in the chat toolbar",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             const contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@montague.lit';
             await mock.waitForRoster(_converse, 'current');
@@ -25,14 +25,13 @@ describe("Emojis", function () {
             item.click()
             expect(view.querySelector('textarea.chat-textarea').value).toBe(':smiley: ');
             toolbar.querySelector('.toggle-emojis').click(); // Close the panel again
-            done();
         }));
     });
 
     describe("A Chat Message", function () {
 
         it("will display larger if it's only emojis",
-                mock.initConverse(['chatBoxesFetched'], {'use_system_emojis': true}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {'use_system_emojis': true}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current');
             const sender_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -114,13 +113,12 @@ describe("Emojis", function () {
 
             message = view.querySelector('.message:last-child .chat-msg__text');
             expect(u.hasClass('chat-msg__text--larger', message)).toBe(true);
-            done()
         }));
 
         it("can render emojis as images",
                 mock.initConverse(
                     ['chatBoxesFetched'], {'use_system_emojis': false},
-                    async function (done, _converse) {
+                    async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current');
             const contact_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -163,8 +161,7 @@ describe("Emojis", function () {
             const sent_stanzas = _converse.connection.sent_stanzas;
             const sent_stanza = sent_stanzas.filter(s => s.nodeName === 'message').pop();
             expect(sent_stanza.querySelector('body').innerHTML).toBe('💩 😇');
-            done()
-                    }));
+        }));
 
         it("can show custom emojis",
             mock.initConverse(
@@ -181,7 +178,7 @@ describe("Emojis", function () {
                     "flags": ":flag_ac:",
                     "custom": ':xmpp:'
                 } },
-                async function (done, _converse) {
+                async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 1);
             const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -208,7 +205,6 @@ describe("Emojis", function () {
             const body = view.querySelector('converse-chat-message-body');
             await u.waitUntil(() => body.innerHTML.replace(/<!-.*?->/g, '').trim() ===
                 'Running tests for <img class="emoji" draggable="false" title=":converse:" alt=":converse:" src="/dist/images/custom_emojis/converse.png">');
-            done();
         }));
     });
 });

+ 6 - 12
src/plugins/chatview/tests/http-file-upload.js

@@ -8,7 +8,7 @@ describe("XEP-0363: HTTP File Upload", function () {
 
     describe("Discovering support", function () {
 
-        it("is done automatically", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+        it("is done automatically", mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
             const IQ_stanzas = _converse.connection.IQ_stanzas;
             await mock.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, [], []);
             let selector = 'iq[to="montague.lit"] query[xmlns="http://jabber.org/protocol/disco#info"]';
@@ -133,7 +133,6 @@ describe("XEP-0363: HTTP File Upload", function () {
             expect(features.length).toBe(1);
             expect(features[0].get('jid')).toBe('upload.montague.lit');
             expect(features[0].dataforms.where({'FORM_TYPE': {value: "urn:xmpp:http:upload:0", type: "hidden"}}).length).toBe(1);
-            done();
         }));
     });
 
@@ -141,7 +140,7 @@ describe("XEP-0363: HTTP File Upload", function () {
         describe("A file upload toolbar button", function () {
 
             it("does not appear in private chats",
-                    mock.initConverse([], {}, async function (done, _converse) {
+                    mock.initConverse([], {}, async function (_converse) {
 
                 await mock.waitForRoster(_converse, 'current', 3);
                 mock.openControlBox(_converse);
@@ -155,7 +154,6 @@ describe("XEP-0363: HTTP File Upload", function () {
                 await mock.waitUntilDiscoConfirmed(_converse, _converse.domain, [], [], [], 'items');
                 const view = _converse.chatboxviews.get(contact_jid);
                 expect(view.querySelector('.chat-toolbar .fileupload')).toBe(null);
-                done();
             }));
         });
     });
@@ -164,7 +162,7 @@ describe("XEP-0363: HTTP File Upload", function () {
 
         describe("A file upload toolbar button", function () {
 
-            it("appears in private chats", mock.initConverse(async (done, _converse) => {
+            it("appears in private chats", mock.initConverse(async (_converse) => {
                 await mock.waitUntilDiscoConfirmed(
                     _converse, _converse.domain,
                     [{'category': 'server', 'type':'IM'}],
@@ -178,12 +176,11 @@ describe("XEP-0363: HTTP File Upload", function () {
                 const view = _converse.chatboxviews.get(contact_jid);
                 const el = await u.waitUntil(() => view.querySelector('.chat-toolbar .fileupload'));
                 expect(el).not.toEqual(null);
-                done();
             }));
 
             describe("when clicked and a file chosen", function () {
 
-                it("is uploaded and sent out", mock.initConverse(['chatBoxesFetched'], {} ,async (done, _converse) => {
+                it("is uploaded and sent out", mock.initConverse(['chatBoxesFetched'], {} ,async (_converse) => {
                     const base_url = 'https://conversejs.org';
                     await mock.waitUntilDiscoConfirmed(
                         _converse, _converse.domain,
@@ -282,11 +279,10 @@ describe("XEP-0363: HTTP File Upload", function () {
                         `<a target="_blank" rel="noopener" href="${base_url}/logo/conversejs-filled.svg">`+
                         `Download file "conversejs-filled.svg"</a>`);
                     XMLHttpRequest.prototype.send = send_backup;
-                    done();
                 }));
 
                 it("shows an error message if the file is too large",
-                        mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                        mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
                     const IQ_stanzas = _converse.connection.IQ_stanzas;
                     const IQ_ids =  _converse.connection.IQ_ids;
@@ -398,14 +394,13 @@ describe("XEP-0363: HTTP File Upload", function () {
                     expect(messages.length).toBe(1);
                     expect(messages[0].textContent.trim()).toBe(
                         'The size of your file, my-juliet.jpg, exceeds the maximum allowed by your server, which is 5 MB.');
-                    done();
                 }));
             });
         });
 
         describe("While a file is being uploaded", function () {
 
-            it("shows a progress bar", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            it("shows a progress bar", mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
                 await mock.waitUntilDiscoConfirmed(
                     _converse, _converse.domain,
                     [{'category': 'server', 'type':'IM'}],
@@ -466,7 +461,6 @@ describe("XEP-0363: HTTP File Upload", function () {
                     message.set('progress', 1);
                     await u.waitUntil(() => view.querySelector('.chat-content progress').getAttribute('value') === '1');
                     expect(view.querySelector('.chat-content .chat-msg__text').textContent).toBe('Uploading file: my-juliet.jpg, 22.91 KB');
-                    done();
                 });
                 _converse.connection._dataRecv(mock.createRequest(stanza));
             }));

+ 3 - 6
src/plugins/chatview/tests/markers.js

@@ -8,7 +8,7 @@ const u = converse.env.utils;
 describe("A XEP-0333 Chat Marker", function () {
 
     it("is sent when a markable message is received from a roster contact",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 1);
         const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -33,11 +33,10 @@ describe("A XEP-0333 Chat Marker", function () {
                     `to="${contact_jid}" type="chat" xmlns="jabber:client">`+
             `<received id="${msgid}" xmlns="urn:xmpp:chat-markers:0"/>`+
             `</message>`);
-        done();
     }));
 
     it("is not sent when a markable message is received from someone not on the roster",
-            mock.initConverse([], {'allow_non_roster_messaging': true}, async function (done, _converse) {
+            mock.initConverse([], {'allow_non_roster_messaging': true}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 0);
         const contact_jid = 'someone@montague.lit';
@@ -66,11 +65,10 @@ describe("A XEP-0333 Chat Marker", function () {
                 `<no-permanent-store xmlns="urn:xmpp:hints"/>`+
             `</message>`
         );
-        done();
     }));
 
     it("is ignored if it's a carbon copy of one that I sent from a different client",
-        mock.initConverse([], {}, async function (done, _converse) {
+        mock.initConverse([], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 1);
         await mock.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, [], [Strophe.NS.SID]);
@@ -112,6 +110,5 @@ describe("A XEP-0333 Chat Marker", function () {
         await u.waitUntil(() => _converse.api.trigger.calls.count(), 500);
         expect(view.querySelectorAll('.chat-msg').length).toBe(1);
         expect(view.model.messages.length).toBe(1);
-        done();
     }));
 });

+ 2 - 4
src/plugins/chatview/tests/me-messages.js

@@ -4,7 +4,7 @@ const { u, sizzle, $msg } = converse.env;
 
 describe("A Groupchat Message", function () {
 
-    it("supports the /me command", mock.initConverse([], {}, async function (done, _converse) {
+    it("supports the /me command", mock.initConverse([], {}, async function (_converse) {
         await mock.waitUntilDiscoConfirmed(_converse, 'montague.lit', [], ['vcard-temp']);
         await u.waitUntil(() => _converse.xmppstatus.vcard.get('fullname'));
         await mock.waitForRoster(_converse, 'current');
@@ -51,13 +51,12 @@ describe("A Groupchat Message", function () {
         await u.waitUntil(() => view.querySelectorAll('.chat-msg__text').length === 3);
         await u.waitUntil(() => sizzle('.chat-msg__text:last', view).pop().innerHTML.replace(/<!-.*?->/g, '') ===
             'mentions <span class="mention mention--self badge badge-info">romeo</span>');
-        done();
     }));
 });
 
 describe("A Message", function () {
 
-    it("supports the /me command", mock.initConverse([], {}, async function (done, _converse) {
+    it("supports the /me command", mock.initConverse([], {}, async function (_converse) {
         await mock.waitForRoster(_converse, 'current');
         await mock.waitUntilDiscoConfirmed(_converse, 'montague.lit', [], ['vcard-temp']);
         await u.waitUntil(() => _converse.xmppstatus.vcard.get('fullname'));
@@ -105,6 +104,5 @@ describe("A Message", function () {
 
         expect(sizzle('.chat-msg__text:last', view).pop().textContent).toBe('wrote a 3rd person message');
         expect(u.isVisible(sizzle('.chat-msg__author:last', view).pop())).toBeTruthy();
-        done();
     }));
 });

+ 1 - 2
src/plugins/chatview/tests/message-audio.js

@@ -6,7 +6,7 @@ describe("A Chat Message", function () {
 
     it("will render audio files from their URLs",
             mock.initConverse(['chatBoxesFetched'], {},
-            async function (done, _converse) {
+            async function (_converse) {
         await mock.waitForRoster(_converse, 'current');
         const base_url = 'https://conversejs.org';
         const message = base_url+"/logo/audio.mp3";
@@ -20,6 +20,5 @@ describe("A Chat Message", function () {
         expect(msg.innerHTML.replace(/<!-.*?->/g, '').replace(/(\r\n|\n|\r)/gm, "").trim()).toEqual(
             `<audio controls="" src="${message}"></audio>`+
             `<a target="_blank" rel="noopener" href="${message}">${message}</a>`);
-        done();
     }));
 });

+ 6 - 12
src/plugins/chatview/tests/message-images.js

@@ -4,7 +4,7 @@ const { sizzle, u } = converse.env;
 
 describe("A Chat Message", function () {
 
-    it("will render images from their URLs", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+    it("will render images from their URLs", mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
         await mock.waitForRoster(_converse, 'current');
         const base_url = 'https://conversejs.org';
         let message = base_url+"/logo/conversejs-filled.svg";
@@ -49,11 +49,10 @@ describe("A Chat Message", function () {
 
         // Check that the Imgur URL gets a .png attached to make it render
         await u.waitUntil(() => Array.from(view.querySelectorAll('.chat-content .chat-image')).pop().src.endsWith('png'), 1000);
-        done();
     }));
 
     it("will not render images if show_images_inline is false",
-            mock.initConverse(['chatBoxesFetched'], {'show_images_inline': false}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {'show_images_inline': false}, async function (_converse) {
         await mock.waitForRoster(_converse, 'current');
         const base_url = 'https://conversejs.org';
         const message = base_url+"/logo/conversejs-filled.svg";
@@ -65,13 +64,12 @@ describe("A Chat Message", function () {
         const sel = '.chat-content .chat-msg:last .chat-msg__text';
         await u.waitUntil(() => sizzle(sel).pop().innerHTML.replace(/<!-.*?->/g, '').trim() === message);
         expect(true).toBe(true);
-        done();
     }));
 
     it("will render images from approved URLs only",
         mock.initConverse(
             ['chatBoxesFetched'], {'show_images_inline': ['conversejs.org']},
-            async function (done, _converse) {
+            async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current');
         const base_url = 'https://conversejs.org';
@@ -88,13 +86,12 @@ describe("A Chat Message", function () {
         await u.waitUntil(() => view.querySelectorAll('.chat-content .chat-msg').length === 2, 1000);
         await u.waitUntil(() => view.querySelectorAll('.chat-content .chat-image').length === 1, 1000)
         expect(view.querySelectorAll('.chat-content .chat-image').length).toBe(1);
-        done();
     }));
 
     it("will fall back to rendering images as URLs",
         mock.initConverse(
             ['chatBoxesFetched'], {},
-            async function (done, _converse) {
+            async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current');
         const base_url = 'https://conversejs.org';
@@ -109,7 +106,6 @@ describe("A Chat Message", function () {
         const msg = sizzle('.chat-content .chat-msg:last .chat-msg__text').pop();
         await u.waitUntil(() => msg.innerHTML.replace(/<!-.*?->/g, '').trim() ==
             `<a target="_blank" rel="noopener" href="https://conversejs.org/logo/non-existing.svg">https://conversejs.org/logo/non-existing.svg</a>`, 1000);
-        done();
     }));
 
     it("will fall back to rendering URLs that match image_urls_regex as URLs",
@@ -118,7 +114,7 @@ describe("A Chat Message", function () {
                 'show_images_inline': ['twimg.com'],
                 'image_urls_regex': /^https?:\/\/(www.)?(pbs\.twimg\.com\/)/i
             },
-            async function (done, _converse) {
+            async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current');
         const message = "https://pbs.twimg.com/media/string?format=jpg&name=small";
@@ -132,13 +128,12 @@ describe("A Chat Message", function () {
         const msg = view.querySelector('.chat-content .chat-msg .chat-msg__text');
         await u.waitUntil(() => msg.innerHTML.replace(/<!-.*?->/g, '').trim() ==
             `<a target="_blank" rel="noopener" href="https://pbs.twimg.com/media/string?format=jpg&amp;name=small">https://pbs.twimg.com/media/string?format=jpg&amp;name=small</a>`, 1000);
-        done();
     }));
 
     it("will respect a changed setting when re-rendered",
         mock.initConverse(
             ['chatBoxesFetched'], {'show_images_inline': true},
-            async function (done, _converse) {
+            async function (_converse) {
 
         const { api } = _converse;
         await mock.waitForRoster(_converse, 'current');
@@ -152,6 +147,5 @@ describe("A Chat Message", function () {
         view.querySelector('converse-chat-message').requestUpdate();
         await u.waitUntil(() => view.querySelector('converse-chat-message-body .chat-image') === null);
         expect(true).toBe(true);
-        done();
     }));
 });

+ 3 - 6
src/plugins/chatview/tests/message-videos.js

@@ -4,7 +4,7 @@ const { Strophe, sizzle, u } = converse.env;
 
 describe("A Chat Message", function () {
 
-    it("will render videos from their URLs", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+    it("will render videos from their URLs", mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
         await mock.waitForRoster(_converse, 'current');
         // let message = "https://i.imgur.com/Py9ifJE.mp4";
         const base_url = 'https://conversejs.org';
@@ -27,11 +27,10 @@ describe("A Chat Message", function () {
         expect(msg.innerHTML.replace(/<!-.*?->/g, '').trim()).toEqual(
             `<video controls="" preload="metadata" src="${Strophe.xmlescape(message)}"></video>`+
             `<a target="_blank" rel="noopener" href="${Strophe.xmlescape(message)}">${Strophe.xmlescape(message)}</a>`);
-        done();
     }));
 
     it("will not render videos if embed_videos is false",
-            mock.initConverse(['chatBoxesFetched'], {'embed_videos': false}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {'embed_videos': false}, async function (_converse) {
         await mock.waitForRoster(_converse, 'current');
         // let message = "https://i.imgur.com/Py9ifJE.mp4";
         const base_url = 'https://conversejs.org';
@@ -44,13 +43,12 @@ describe("A Chat Message", function () {
         const sel = '.chat-content .chat-msg:last .chat-msg__text';
         await u.waitUntil(() => sizzle(sel).pop().innerHTML.replace(/<!-.*?->/g, '').trim() === message);
         expect(true).toBe(true);
-        done();
     }));
 
     it("will render videos from approved URLs only",
         mock.initConverse(
             ['chatBoxesFetched'], {'embed_videos': ['conversejs.org']},
-            async function (done, _converse) {
+            async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current');
         let message = "https://i.imgur.com/Py9ifJE.mp4";
@@ -69,6 +67,5 @@ describe("A Chat Message", function () {
         expect(msg.innerHTML.replace(/<!-.*?->/g, '').trim()).toEqual(
             `<video controls="" preload="metadata" src="${message}"></video>`+
             `<a target="_blank" rel="noopener" href="${message}">${message}</a>`);
-        done();
     }));
 });

+ 24 - 48
src/plugins/chatview/tests/messages.js

@@ -7,7 +7,7 @@ describe("A Chat Message", function () {
 
     it("will be demarcated if it's the first newly received message",
         mock.initConverse(['chatBoxesFetched'], {},
-            async function (done, _converse) {
+            async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 1);
         const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -28,14 +28,13 @@ describe("A Chat Message", function () {
         await u.waitUntil(() => view.querySelector('converse-chat-message:last-child .chat-msg__text')?.textContent === 'This message will be new');
         const last_msg_el = view.querySelector('converse-chat-message:last-child');
         expect(last_msg_el.firstElementChild?.textContent).toBe('New messages');
-        done();
     }));
 
 
     it("is rejected if it's an unencapsulated forwarded message",
         mock.initConverse(
             ['chatBoxesFetched'], {},
-            async function (done, _converse) {
+            async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 2);
         const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -74,11 +73,10 @@ describe("A Chat Message", function () {
             '</message>');
         models = await _converse.api.chats.get();
         expect(models.length).toBe(1);
-        done();
     }));
 
     it("can be received out of order, and will still be displayed in the right order",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current');
         await mock.openControlBox(_converse);
@@ -238,11 +236,10 @@ describe("A Chat Message", function () {
         expect(day.getAttribute('data-isodate')).toEqual(dayjs().startOf('day').toISOString());
         expect(day.nextElementSibling.querySelector('.chat-msg__text').textContent).toBe('latest message');
         expect(u.hasClass('chat-msg--followup', el)).toBe(false);
-        done();
     }));
 
     it("is ignored if it's a malformed headline message",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current');
         await mock.openControlBox(_converse);
@@ -262,12 +259,11 @@ describe("A Chat Message", function () {
             "handleMessageStanza: Ignoring incoming server message from JID: montague.lit"
         );
         expect(_converse.api.chatboxes.get).not.toHaveBeenCalled();
-        done();
     }));
 
 
     it("can be a carbon message, as defined in XEP-0280",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         const include_nick = false;
         await mock.waitForRoster(_converse, 'current', 2, include_nick);
@@ -312,11 +308,10 @@ describe("A Chat Message", function () {
         expect(view.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy();
         await u.waitUntil(() => chatbox.vcard.get('fullname') === 'Juliet Capulet')
         expect(view.querySelector('span.chat-msg__author').textContent.trim()).toBe('Juliet Capulet');
-        done();
     }));
 
     it("can be a carbon message that this user sent from a different client, as defined in XEP-0280",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         await mock.waitUntilDiscoConfirmed(_converse, 'montague.lit', [], ['vcard-temp']);
         await mock.waitForRoster(_converse, 'current');
@@ -357,11 +352,10 @@ describe("A Chat Message", function () {
         // Now check that the message appears inside the chatbox in the DOM
         const msg_el = await u.waitUntil(() => view.querySelector('.chat-content .chat-msg .chat-msg__text'));
         expect(msg_el.textContent).toEqual(msgtext);
-        done();
     }));
 
     it("will be discarded if it's a malicious message meant to look like a carbon copy",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current');
         await mock.openControlBox(_converse);
@@ -401,11 +395,10 @@ describe("A Chat Message", function () {
         // Check that the chatbox for the malicous user is not created
         chatbox = await _converse.api.chats.get(sender_jid);
         expect(chatbox).toBe(null);
-        done();
     }));
 
     it("will indicate when it has a time difference of more than a day between it and its predecessor",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         const include_nick = false;
         await mock.waitForRoster(_converse, 'current', 2, include_nick);
@@ -492,11 +485,10 @@ describe("A Chat Message", function () {
         expect(view.querySelector('converse-chat-message:last-child .chat-msg__text').textContent).toEqual(message);
         expect(view.querySelector('converse-chat-message:last-child .chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy();
         expect(view.querySelector('converse-chat-message:last-child .chat-msg__author').textContent.trim()).toBe('Juliet Capulet');
-        done();
     }));
 
     it("is sanitized to prevent Javascript injection attacks",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current');
         await mock.openControlBox(_converse);
@@ -510,11 +502,10 @@ describe("A Chat Message", function () {
         const msg = sizzle('.chat-content .chat-msg:last .chat-msg__text', view).pop();
         expect(msg.textContent).toEqual(message);
         expect(msg.innerHTML.replace(/<!-.*?->/g, '')).toEqual('&lt;p&gt;This message contains &lt;em&gt;some&lt;/em&gt; &lt;b&gt;markup&lt;/b&gt;&lt;/p&gt;');
-        done();
     }));
 
     it("can contain hyperlinks, which will be clickable",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current');
         await mock.openControlBox(_converse);
@@ -530,12 +521,11 @@ describe("A Chat Message", function () {
         expect(msg.textContent).toEqual(message);
         await u.waitUntil(() => msg.innerHTML.replace(/<!-.*?->/g, '') ===
             'This message contains a hyperlink: <a target="_blank" rel="noopener" href="http://www.opkode.com">www.opkode.com</a>');
-        done();
     }));
 
     it("will remove url query parameters from hyperlinks as set",
             mock.initConverse(['chatBoxesFetched'], {'filter_url_query_params': ['utm_medium', 'utm_content', 's']},
-            async function (done, _converse) {
+            async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current');
         await mock.openControlBox(_converse);
@@ -559,10 +549,9 @@ describe("A Chat Message", function () {
         await u.waitUntil(() => msg.innerHTML.replace(/<!-.*?->/g, '') ===
             'Another message with a hyperlink with forbidden query params: '+
             '<a target="_blank" rel="noopener" href="https://www.opkode.com/?id=0&amp;utm_content=1&amp;s=1">https://www.opkode.com/?id=0&amp;utm_content=1&amp;s=1</a>');
-        done();
     }));
 
-    it("will render newlines", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+    it("will render newlines", mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
         await mock.waitForRoster(_converse, 'current');
         const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
         const view = await mock.openChatBoxFor(_converse, contact_jid);
@@ -607,13 +596,12 @@ describe("A Chat Message", function () {
             const text = view.querySelector('converse-chat-message:last-child .chat-msg__text').innerHTML.replace(/<!-.*?->/g, '');
             return text === 'Hey\nHave you heard\n\u200B\nthe news?\n<a target="_blank" rel="noopener" href="https://conversejs.org/">https://conversejs.org</a>';
         });
-        done();
     }));
 
     it("will render the message time as configured",
             mock.initConverse(
                 ['chatBoxesFetched'], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
         const { api } = _converse;
         await mock.waitForRoster(_converse, 'current');
@@ -634,13 +622,12 @@ describe("A Chat Message", function () {
         const msg_time = view.querySelector('.chat-content .chat-msg:last-child .chat-msg__time');
         const time = dayjs(msg_object.get('time')).format(api.settings.get('time_format'));
         expect(msg_time.textContent).toBe(time);
-        done();
     }));
 
     it("will be correctly identified and rendered as a followup message",
         mock.initConverse(
             [], {'debounced_content_rendering': false},
-            async function (done, _converse) {
+            async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current');
         await mock.openControlBox(_converse);
@@ -793,7 +780,6 @@ describe("A Chat Message", function () {
             "Another message within 10 minutes, but from a different person");
 
         jasmine.clock().uninstall();
-        done();
     }));
 
 
@@ -802,7 +788,7 @@ describe("A Chat Message", function () {
         it("will appear inside the chatbox it was sent from",
             mock.initConverse(
                 ['chatBoxesFetched'], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current');
             await mock.openControlBox(_converse);
@@ -816,14 +802,13 @@ describe("A Chat Message", function () {
             expect(view.model.sendMessage).toHaveBeenCalled();
             expect(view.model.messages.length, 2);
             expect(sizzle('.chat-content .chat-msg:last .chat-msg__text', view).pop().textContent).toEqual(message);
-            done();
         }));
 
 
         it("will be trimmed of leading and trailing whitespace",
             mock.initConverse(
                 ['chatBoxesFetched'], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 1);
             const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -834,7 +819,6 @@ describe("A Chat Message", function () {
             expect(view.model.messages.at(0).get('message')).toEqual(message.trim());
             const message_el = sizzle('.chat-content .chat-msg:last .chat-msg__text', view).pop();
             expect(message_el.textContent).toEqual(message.trim());
-            done();
         }));
     });
 
@@ -842,7 +826,7 @@ describe("A Chat Message", function () {
     describe("when received from someone else", function () {
 
         it("will open a chatbox and be displayed inside it",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             const include_nick = false;
             await mock.waitForRoster(_converse, 'current', 1, include_nick);
@@ -883,11 +867,10 @@ describe("A Chat Message", function () {
             expect(view.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy();
             await u.waitUntil(() => chatbox.vcard.get('fullname') === mock.cur_names[0]);
             expect(view.querySelector('span.chat-msg__author').textContent.trim()).toBe('Mercutio');
-            done();
         }));
 
         it("will be trimmed of leading and trailing whitespace",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 1, false);
             const rosterview = document.querySelector('converse-roster');
@@ -910,7 +893,6 @@ describe("A Chat Message", function () {
             expect(msg_obj.get('message')).toEqual(message.trim());
             const mel = await u.waitUntil(() => view.querySelector('.chat-msg .chat-msg__text'));
             expect(mel.textContent).toEqual(message.trim());
-            done();
         }));
 
 
@@ -918,7 +900,7 @@ describe("A Chat Message", function () {
 
             it("the VCard for that user is fetched and the chatbox updated with the results",
                 mock.initConverse([], {'allow_non_roster_messaging': true},
-                    async function (done, _converse) {
+                    async function (_converse) {
 
                 await mock.waitForRoster(_converse, 'current', 0);
                 spyOn(_converse.api, "trigger").and.callThrough();
@@ -962,7 +944,6 @@ describe("A Chat Message", function () {
                 await u.waitUntil(() => chatbox.vcard.get('fullname') === mock.cur_names[0])
                 author_el = view.querySelector('.chat-msg__author');
                 expect(author_el.textContent.trim().includes('Mercutio')).toBeTruthy();
-                done();
             }));
         });
 
@@ -972,7 +953,7 @@ describe("A Chat Message", function () {
             it("will open a chatbox and be displayed inside it if allow_non_roster_messaging is true",
                 mock.initConverse(
                     [], {'allow_non_roster_messaging': false},
-                    async function (done, _converse) {
+                    async function (_converse) {
 
                 await mock.waitForRoster(_converse, 'current', 0);
 
@@ -1019,7 +1000,6 @@ describe("A Chat Message", function () {
                 expect(view.querySelector('.chat-msg .chat-msg__text').textContent).toEqual(message);
                 expect(view.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy();
                 expect(view.querySelector('span.chat-msg__author').textContent.trim()).toBe('Mercutio');
-                done();
             }));
         });
 
@@ -1027,7 +1007,7 @@ describe("A Chat Message", function () {
         describe("and for which then an error message is received from the server", function () {
 
             it("will have the error message displayed after itself",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
                 await mock.waitForRoster(_converse, 'current', 1);
 
@@ -1142,13 +1122,12 @@ describe("A Chat Message", function () {
                     expect(el.querySelector('.chat-msg__action-edit')).toBe(null)
                     expect(el.querySelector('.chat-msg__action-retract')).toBe(null)
                 })
-                done();
             }));
 
             it("will not show to the user an error message for a CSI message",
                 mock.initConverse(
                     ['chatBoxesFetched'], {},
-                    async function (done, _converse) {
+                    async function (_converse) {
 
                 // See #1317
                 // https://github.com/conversejs/converse.js/issues/1317
@@ -1181,12 +1160,11 @@ describe("A Chat Message", function () {
                 await view.model.sendMessage(msg_text);
                 await u.waitUntil(() => view.querySelectorAll('.chat-msg__text').length);
                 expect(view.querySelectorAll('.chat-error').length).toEqual(0);
-                done();
             }));
         });
 
         it("will cause the chat area to be scrolled down only if it was at the bottom originally",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current');
             const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -1216,11 +1194,10 @@ describe("A Chat Message", function () {
             indicator_el.click();
             await u.waitUntil(() => !view.querySelector('.new-msgs-indicator'));
             await u.waitUntil(() => !view.model.get('scrolled'));
-            done();
         }));
 
         it("is ignored if it's intended for a different resource and filter_by_resource is set to true",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             const { api } = _converse;
             await mock.waitForRoster(_converse, 'current');
@@ -1262,7 +1239,6 @@ describe("A Chat Message", function () {
             const last_message = await u.waitUntil(() => sizzle('.chat-content:last .chat-msg__text', view).pop());
             const msg_txt = last_message.textContent;
             expect(msg_txt).toEqual(message);
-            done();
         }));
     });
 });

+ 4 - 8
src/plugins/chatview/tests/oob.js

@@ -8,7 +8,7 @@ describe("A Chat Message", function () {
         it("will render audio from oob mp3 URLs",
             mock.initConverse(
                 ['chatBoxesFetched'], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 1);
             const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -52,13 +52,12 @@ describe("A Chat Message", function () {
             expect(media.innerHTML.replace(/<!-.*?->/g, '').replace(/(\r\n|\n|\r)/gm, "").trim()).toEqual(
                 `<audio controls="" src="https://montague.lit/audio.mp3"></audio>`+
                 `<a target="_blank" rel="noopener" href="${url}">${url}</a>`);
-            done();
         }));
 
         it("will render video from oob mp4 URLs",
             mock.initConverse(
                 ['chatBoxesFetched'], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 1);
             const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -100,13 +99,12 @@ describe("A Chat Message", function () {
             expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "").replace(/<!-.*?->/g, '')).toEqual(
                 `<video controls="" preload="metadata" src="${Strophe.xmlescape(url)}"></video>`+
                 `<a target="_blank" rel="noopener" href="${Strophe.xmlescape(url)}">${Strophe.xmlescape(url)}</a>`);
-            done();
         }));
 
         it("will render download links for files from oob URLs",
             mock.initConverse(
                 ['chatBoxesFetched'], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 1);
             const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -129,13 +127,12 @@ describe("A Chat Message", function () {
             const media = view.querySelector('.chat-msg .chat-msg__media');
             expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "").replace(/<!-.*?->/g, '')).toEqual(
                 `<a target="_blank" rel="noopener" href="https://montague.lit/funny.pdf">Download file "funny.pdf"</a>`);
-            done();
         }));
 
         it("will render images from oob URLs",
             mock.initConverse(
                 ['chatBoxesFetched'], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             const base_url = 'https://conversejs.org';
             await mock.waitForRoster(_converse, 'current', 1);
@@ -163,7 +160,6 @@ describe("A Chat Message", function () {
             expect(media.innerHTML.replace(/<!-.*?->/g, '').replace(/(\r\n|\n|\r)/gm, "")).toEqual(
                 `<a target="_blank" rel="noopener" href="${base_url}/logo/conversejs-filled.svg">`+
                 `Download file "conversejs-filled.svg"</a>`);
-            done();
         }));
     });
 });

+ 4 - 8
src/plugins/chatview/tests/receipts.js

@@ -9,7 +9,7 @@ describe("A delivery receipt", function () {
     it("is emitted for a received message which requests it",
         mock.initConverse(
             ['chatBoxesFetched'], {},
-            async function (done, _converse) {
+            async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current');
         const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -29,13 +29,12 @@ describe("A delivery receipt", function () {
         expect(sent_messages.length).toBe(2);
         const receipt = sizzle(`received[xmlns="${Strophe.NS.RECEIPTS}"]`, sent_messages[1]).pop();
         expect(Strophe.serialize(receipt)).toBe(`<received id="${msg_id}" xmlns="${Strophe.NS.RECEIPTS}"/>`);
-        done();
     }));
 
     it("is not emitted for a carbon message",
         mock.initConverse(
             ['chatBoxesFetched'], {},
-            async function (done, _converse) {
+            async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 1);
         const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -59,13 +58,12 @@ describe("A delivery receipt", function () {
             .c('request', {'xmlns': Strophe.NS.RECEIPTS}).tree();
         await _converse.handleMessageStanza(msg);
         expect(view.model.sendReceiptStanza).not.toHaveBeenCalled();
-        done();
     }));
 
     it("is not emitted for an archived message",
         mock.initConverse(
             ['chatBoxesFetched'], {},
-            async function (done, _converse) {
+            async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 1);
         const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -96,13 +94,12 @@ describe("A delivery receipt", function () {
         expect(message_attrs.is_archived).toBe(true);
         expect(message_attrs.is_valid_receipt_request).toBe(false);
         expect(view.model.sendReceiptStanza).not.toHaveBeenCalled();
-        done();
     }));
 
     it("can be received for a sent message",
         mock.initConverse(
             ['chatBoxesFetched'], {},
-            async function (done, _converse) {
+            async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 1);
         const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -150,6 +147,5 @@ describe("A delivery receipt", function () {
         _converse.connection._dataRecv(mock.createRequest(msg));
         await u.waitUntil(() => view.querySelectorAll('.chat-msg__receipt').length === 2);
         expect(_converse.handleMessageStanza.calls.count()).toBe(1);
-        done();
     }));
 });

+ 4 - 8
src/plugins/chatview/tests/spoilers.js

@@ -8,7 +8,7 @@ describe("A spoiler message", function () {
     afterEach(() => (jasmine.DEFAULT_TIMEOUT_INTERVAL = original_timeout));
 
     it("can be received with a hint",
-        mock.initConverse(['chatBoxesFetched'], {}, async (done, _converse) => {
+        mock.initConverse(['chatBoxesFetched'], {}, async (_converse) => {
 
         await mock.waitForRoster(_converse, 'current');
         const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -42,11 +42,10 @@ describe("A spoiler message", function () {
         await u.waitUntil(() => message_content.textContent === spoiler);
         const spoiler_hint_el = view.querySelector('.spoiler-hint');
         expect(spoiler_hint_el.textContent).toBe(spoiler_hint);
-        done();
     }));
 
     it("can be received without a hint",
-            mock.initConverse(['chatBoxesFetched'], {}, async (done, _converse) => {
+            mock.initConverse(['chatBoxesFetched'], {}, async (_converse) => {
 
         await mock.waitForRoster(_converse, 'current');
         const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -79,11 +78,10 @@ describe("A spoiler message", function () {
         await u.waitUntil(() => message_content.textContent === spoiler);
         const spoiler_hint_el = view.querySelector('.spoiler-hint');
         expect(spoiler_hint_el.textContent).toBe('');
-        done();
     }));
 
     it("can be sent without a hint",
-            mock.initConverse(['chatBoxesFetched'], {}, async (done, _converse) => {
+            mock.initConverse(['chatBoxesFetched'], {}, async (_converse) => {
 
         await mock.waitForRoster(_converse, 'current', 1);
         mock.openControlBox(_converse);
@@ -156,11 +154,10 @@ describe("A spoiler message", function () {
         expect(spoiler_toggle.textContent.trim()).toBe('Show less');
         spoiler_toggle.click();
         await u.waitUntil(() => Array.from(spoiler_msg_el.classList).includes('hidden'));
-        done();
     }));
 
     it("can be sent with a hint",
-            mock.initConverse(['chatBoxesFetched'], {}, async (done, _converse) => {
+            mock.initConverse(['chatBoxesFetched'], {}, async (_converse) => {
 
         await mock.waitForRoster(_converse, 'current', 1);
         mock.openControlBox(_converse);
@@ -237,6 +234,5 @@ describe("A spoiler message", function () {
         expect(spoiler_toggle.textContent.trim()).toBe('Show less');
         spoiler_toggle.click();
         await u.waitUntil(() => Array.from(spoiler_msg_el.classList).includes('hidden'));
-        done();
     }));
 });

+ 6 - 12
src/plugins/chatview/tests/styling.js

@@ -6,7 +6,7 @@ describe("An incoming chat Message", function () {
 
     it("can have styling disabled via an \"unstyled\" element",
         mock.initConverse(['chatBoxesFetched'], {},
-            async function (done, _converse) {
+            async function (_converse) {
 
         const include_nick = false;
         await mock.waitForRoster(_converse, 'current', 2, include_nick);
@@ -31,14 +31,13 @@ describe("An incoming chat Message", function () {
         setTimeout(() => {
             const msg_el = view.querySelector('converse-chat-message-body');
             expect(msg_el.innerText).toBe(msg_text);
-            done();
         }, 500);
     }));
 
 
     it("can have styling disabled via the allow_message_styling setting",
         mock.initConverse(['chatBoxesFetched'], {'allow_message_styling': false},
-            async function (done, _converse) {
+            async function (_converse) {
 
         const include_nick = false;
         await mock.waitForRoster(_converse, 'current', 2, include_nick);
@@ -62,13 +61,12 @@ describe("An incoming chat Message", function () {
         setTimeout(() => {
             const msg_el = view.querySelector('converse-chat-message-body');
             expect(msg_el.innerText).toBe(msg_text);
-            done();
         }, 500);
     }));
 
     it("can be styled with span XEP-0393 message styling hints",
         mock.initConverse(['chatBoxesFetched'], {},
-            async function (done, _converse) {
+            async function (_converse) {
 
         let msg_text, msg, msg_el;
         await mock.waitForRoster(_converse, 'current', 1);
@@ -187,12 +185,11 @@ describe("An incoming chat Message", function () {
             '<i><a target="_blank" rel="noopener" href="https://converse_js.org/">https://converse_js.org</a></i>'+
             '<span class="styling-directive">_</span> <span class="styling-directive">_</span><i>please</i><span class="styling-directive">_</span>');
 
-        done();
     }));
 
     it("can be styled with block XEP-0393 message styling hints",
         mock.initConverse(['chatBoxesFetched'], {},
-            async function (done, _converse) {
+            async function (_converse) {
 
         let msg_text, msg, msg_el;
         await mock.waitForRoster(_converse, 'current', 1);
@@ -233,12 +230,11 @@ describe("An incoming chat Message", function () {
             '```ignored\n (println "Hello, world!")\n ```\n\n'+
             ' This should not show up as monospace, '+
             '<span class="styling-directive">*</span><b>preformatted</b><span class="styling-directive">*</span> text ^');
-        done();
     }));
 
     it("can be styled with quote XEP-0393 message styling hints",
         mock.initConverse(['chatBoxesFetched'], {},
-            async function (done, _converse) {
+            async function (_converse) {
 
         let msg_text, msg, msg_el;
         await mock.waitForRoster(_converse, 'current', 1);
@@ -371,12 +367,11 @@ describe("An incoming chat Message", function () {
             `<blockquote>What do you think of it <span class="mention">romeo</span>?</blockquote>\n Did you see this <span class="mention">romeo</span>?`);
 
         expect(true).toBe(true);
-        done();
     }));
 
     it("won't style invalid block quotes",
             mock.initConverse(['chatBoxesFetched'], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 1);
         const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -409,6 +404,5 @@ describe("An incoming chat Message", function () {
         const msg_el = Array.from(view.querySelectorAll('converse-chat-message-body')).pop();
         await u.waitUntil(() => msg_el.innerHTML.replace(/<!-.*?->/g, '') === '```\ncode```');
         expect(true).toBe(true);
-        done();
     }));
 });

+ 7 - 14
src/plugins/chatview/tests/unreads.js

@@ -6,7 +6,7 @@ const { u } = converse.env;
 describe("A ChatBox's Unread Message Count", function () {
 
     it("is incremented when the message is received and ChatBoxView is scrolled up",
-        mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+        mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 1);
         const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit',
@@ -23,11 +23,10 @@ describe("A ChatBox's Unread Message Count", function () {
         expect(view.model.get('first_unread_id')).toBe(msgid);
         await u.waitUntil(() => sent_stanzas.length);
         expect(sent_stanzas[0].querySelector('received')).toBeDefined();
-        done();
     }));
 
     it("is not incremented when the message is received and ChatBoxView is scrolled down",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 1);
         const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -40,11 +39,10 @@ describe("A ChatBox's Unread Message Count", function () {
         expect(chatbox.get('num_unread')).toBe(0);
         await u.waitUntil(() => sent_stanzas.filter(s => s.nodeName === 'message').length === 2);
         expect(sent_stanzas[1].querySelector('displayed')).toBeDefined();
-        done();
     }));
 
     it("is incremented when message is received, chatbox is scrolled down and the window is not focused",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current');
         const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -64,11 +62,10 @@ describe("A ChatBox's Unread Message Count", function () {
         expect(chatbox.get('first_unread_id')).toBe(msgid);
         await u.waitUntil(() => sent_stanzas.filter(s => s.nodeName === 'message').length);
         expect(sent_stanzas[0].querySelector('received')).toBeDefined();
-        done();
     }));
 
     it("is incremented when message is received, chatbox is scrolled up and the window is not focused",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 1);
         const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -87,11 +84,10 @@ describe("A ChatBox's Unread Message Count", function () {
         expect(chatbox.get('first_unread_id')).toBe(msgid);
         await u.waitUntil(() => sent_stanzas.filter(s => s.nodeName === 'message').length === 1);
         expect(sent_stanzas[0].querySelector('received')).toBeDefined();
-        done();
     }));
 
     it("is cleared when the chat was scrolled down and the window become focused",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 1);
         const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -113,12 +109,11 @@ describe("A ChatBox's Unread Message Count", function () {
         await u.waitUntil(() => sent_stanzas.filter(s => s.nodeName === 'message').length === 2);
         expect(sent_stanzas[1].querySelector('displayed')).toBeDefined();
         expect(chatbox.get('num_unread')).toBe(0);
-        done();
     }));
 
     it("is cleared when the chat was hidden in fullscreen mode and then becomes visible",
             mock.initConverse(['chatBoxesFetched'], {'view_mode': 'fullscreen'},
-            async function (done, _converse) {
+            async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 1);
         const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -131,11 +126,10 @@ describe("A ChatBox's Unread Message Count", function () {
         chatbox.save({'hidden': false});
         await u.waitUntil(() => chatbox.get('num_unread') === 0);
         chatbox.close();
-        done();
     }));
 
     it("is not cleared when ChatBoxView was scrolled up and the windows become focused",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 1);
         const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -158,6 +152,5 @@ describe("A ChatBox's Unread Message Count", function () {
         await u.waitUntil(() => chatbox.get('num_unread') === 1);
         expect(chatbox.get('first_unread_id')).toBe(msgid);
         expect(sent_stanzas[0].querySelector('received')).toBeDefined();
-        done();
     }));
 });

+ 4 - 8
src/plugins/chatview/tests/xss.js

@@ -6,7 +6,7 @@ const u = converse.env.utils;
 describe("XSS", function () {
     describe("A Chat Message", function () {
 
-        it("will escape IMG payload XSS attempts", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+        it("will escape IMG payload XSS attempts", mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
             spyOn(window, 'alert').and.callThrough();
             await mock.waitForRoster(_converse, 'current');
             await mock.openControlBox(_converse);
@@ -59,10 +59,9 @@ describe("XSS", function () {
             expect(msg.innerHTML.replace(/<!-.*?->/g, '')).toEqual("&gt;&lt;img src=x onerror=alert(String.fromCharCode(88,83,83));&gt;");
 
             expect(window.alert).not.toHaveBeenCalled();
-            done();
         }));
 
-        it("will escape SVG payload XSS attempts", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+        it("will escape SVG payload XSS attempts", mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
             spyOn(window, 'alert').and.callThrough();
             await mock.waitForRoster(_converse, 'current');
             await mock.openControlBox(_converse);
@@ -114,11 +113,10 @@ describe("XSS", function () {
             expect(msg.innerHTML.replace(/<!-.*?->/g, '')).toEqual('"&gt;&lt;svg/onload=alert(/XSS/)');
 
             expect(window.alert).not.toHaveBeenCalled();
-            done();
         }));
 
         it("will have properly escaped URLs",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current');
             await mock.openControlBox(_converse);
@@ -170,11 +168,10 @@ describe("XSS", function () {
             expect(msg.textContent).toEqual(message);
             await u.waitUntil(() => msg.innerHTML.replace(/<!-.*?->/g, '') ===
                 `<a target="_blank" rel="noopener" href="https://www.google.com/maps/place/Kochstraat+6,+2041+CE+Zandvoort/@52.3775999,4.548971,3a,15y,170.85h,88.39t/data=%213m6%211e1%213m4%211sQ7SdHo_bPLPlLlU8GSGWaQ%212e0%217i13312%218i6656%214m5%213m4%211s0x47c5ec1e56f845ad:0x1de0bc4a5771fb08%218m2%213d52.3773668%214d4.5489388%215m1%211e2">https://www.google.com/maps/place/Kochstraat+6,+2041+CE+Zandvoort/@52.3775999,4.548971,3a,15y,170.85h,88.39t/data=!3m6!1e1!3m4!1sQ7SdHo_bPLPlLlU8GSGWaQ!2e0!7i13312!8i6656!4m5!3m4!1s0x47c5ec1e56f845ad:0x1de0bc4a5771fb08!8m2!3d52.3773668!4d4.5489388!5m1!1e2</a>`);
-            done();
         }));
 
         it("will avoid malformed and unsafe urls urls from rendering as anchors",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current');
             await mock.openControlBox(_converse);
@@ -250,7 +247,6 @@ describe("XSS", function () {
             await mock.sendMessage(view, good_urls[5].entered);
             await checkParsedURL(good_urls[5]);
 
-            done();
         }));
     });
 });

+ 11 - 22
src/plugins/controlbox/tests/controlbox.js

@@ -9,19 +9,18 @@ const sizzle = converse.env.sizzle;
 describe("The Controlbox", function () {
 
     it("can be opened by clicking a DOM element with class 'toggle-controlbox'",
-            mock.initConverse([], {}, function (done, _converse) {
+            mock.initConverse([], {}, function (_converse) {
 
         spyOn(_converse.api, "trigger").and.callThrough();
         document.querySelector('.toggle-controlbox').click();
         expect(_converse.api.trigger).toHaveBeenCalledWith('controlBoxOpened', jasmine.any(Object));
         const el = document.querySelector("#controlbox");
         expect(u.isVisible(el)).toBe(true);
-        done();
     }));
 
 
     it("can be closed by clicking a DOM element with class 'close-chatbox-button'",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.openControlBox(_converse);
         const view = _converse.chatboxviews.get('controlbox');
@@ -32,14 +31,13 @@ describe("The Controlbox", function () {
         view.querySelector('.close-chatbox-button').click();
         expect(view.close).toHaveBeenCalled();
         expect(_converse.api.trigger).toHaveBeenCalledWith('controlBoxClosed', jasmine.any(Object));
-        done();
     }));
 
 
     describe("The \"Contacts\" section", function () {
 
         it("can be used to add contact and it checks for case-sensivity",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             spyOn(_converse.api, "trigger").and.callThrough();
             await mock.waitForRoster(_converse, 'all', 0);
@@ -61,11 +59,10 @@ describe("The Controlbox", function () {
             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)
             expect(Array.from(rosterview.querySelectorAll('li')).filter(u.isVisible).length).toBe(1);
-            done();
         }));
 
         it("shows the number of unread mentions received",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'all');
             await mock.openControlBox(_converse);
@@ -108,23 +105,21 @@ describe("The Controlbox", function () {
             chatview.model.set({'minimized': false});
             expect(el.querySelector('.restore-chat .message-count')).toBe(null);
             await u.waitUntil(() => rosterview.querySelector('.msgs-indicator') === null);
-            done();
         }));
     });
 
     describe("The Status Widget", function () {
 
         it("shows the user's chat status, which is online by default",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
             mock.openControlBox(_converse);
             const view = await u.waitUntil(() => document.querySelector('converse-user-profile'));
             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');
-            done();
         }));
 
         it("can be used to set the current user's chat status",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             await mock.openControlBox(_converse);
             var cbview = _converse.chatboxviews.get('controlbox');
@@ -146,11 +141,10 @@ describe("The Controlbox", function () {
             expect(u.hasClass('online', first_child)).toBe(false);
             expect(u.hasClass('dnd', first_child)).toBe(true);
             expect(view.querySelector('.xmpp-status span:first-child').textContent.trim()).toBe('I am busy');
-            done();
         }));
 
         it("can be used to set a custom status message",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             await mock.openControlBox(_converse);
             const cbview = _converse.chatboxviews.get('controlbox');
@@ -174,7 +168,6 @@ describe("The Controlbox", function () {
             const first_child = view.querySelector('.xmpp-status span:first-child');
             expect(u.hasClass('online', first_child)).toBe(true);
             expect(view.querySelector('.xmpp-status span:first-child').textContent.trim()).toBe(msg);
-            done();
         }));
     });
 });
@@ -182,7 +175,7 @@ describe("The Controlbox", function () {
 describe("The 'Add Contact' widget", function () {
 
     it("opens up an add modal when you click on it",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'all');
         await mock.openControlBox(_converse);
@@ -210,11 +203,10 @@ describe("The 'Add Contact' widget", function () {
             `<iq id="${sent_stanza.getAttribute('id')}" type="set" xmlns="jabber:client">`+
                 `<query xmlns="jabber:iq:roster"><item jid="someone@montague.lit" name="Someone"/></query>`+
             `</iq>`);
-        done();
     }));
 
     it("can be configured to not provide search suggestions",
-            mock.initConverse([], {'autocomplete_add_contact': false}, async function (done, _converse) {
+            mock.initConverse([], {'autocomplete_add_contact': false}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'all', 0);
         await mock.openControlBox(_converse);
@@ -239,13 +231,12 @@ describe("The 'Add Contact' widget", function () {
                 `<query xmlns="jabber:iq:roster"><item jid="someone@montague.lit"/></query>`+
             `</iq>`
         );
-        done();
     }));
 
 
     it("integrates with xhr_user_search_url to search for contacts",
             mock.initConverse([], { 'xhr_user_search_url': 'http://example.org/?' },
-            async function (done, _converse) {
+            async function (_converse) {
 
         await mock.waitForRoster(_converse, 'all', 0);
 
@@ -296,14 +287,13 @@ describe("The 'Add Contact' widget", function () {
             `<query xmlns="jabber:iq:roster"><item jid="marty@mcfly.net" name="Marty McFly"/></query>`+
         `</iq>`);
         window.XMLHttpRequest = XMLHttpRequestBackup;
-        done();
     }));
 
     it("can be configured to not provide search suggestions for XHR search results",
         mock.initConverse([],
             { 'autocomplete_add_contact': false,
               'xhr_user_search_url': 'http://example.org/?' },
-            async function (done, _converse) {
+            async function (_converse) {
 
         await mock.waitForRoster(_converse, 'all');
         await mock.openControlBox(_converse);
@@ -371,6 +361,5 @@ describe("The 'Add Contact' widget", function () {
             `<query xmlns="jabber:iq:roster"><item jid="marty@mcfly.net" name="Marty McFly"/></query>`+
         `</iq>`);
         window.XMLHttpRequest = XMLHttpRequestBackup;
-        done();
     }));
 });

+ 2 - 4
src/plugins/controlbox/tests/login.js

@@ -9,7 +9,7 @@ describe("The Login Form", function () {
             ['chatBoxesInitialized'],
             { auto_login: false,
               allow_registration: false },
-            async function (done, _converse) {
+            async function (_converse) {
 
         const cbview = await u.waitUntil(() => _converse.chatboxviews.get('controlbox'));
         mock.toggleControlBox();
@@ -34,7 +34,6 @@ describe("The Login Form", function () {
         cbview.querySelector('input[type="submit"]').click();
         expect(_converse.config.get('trusted')).toBe(false);
         expect(_converse.getDefaultStore()).toBe('session');
-        done();
     }));
 
     it("checkbox can be set to false by default",
@@ -43,7 +42,7 @@ describe("The Login Form", function () {
             { auto_login: false,
               allow_user_trust_override: 'off',
               allow_registration: false },
-            async function (done, _converse) {
+            async function (_converse) {
 
         await u.waitUntil(() => _converse.chatboxviews.get('controlbox'))
         const cbview = _converse.chatboxviews.get('controlbox');
@@ -67,6 +66,5 @@ describe("The Login Form", function () {
         cbview.querySelector('input[type="submit"]').click();
         expect(_converse.config.get('trusted')).toBe(true);
         expect(_converse.getDefaultStore()).toBe('persistent');
-        done();
     }));
 });

+ 5 - 10
src/plugins/headlines-view/tests/headline.js

@@ -3,7 +3,7 @@
 describe("A headlines box", function () {
 
     it("will not open nor display non-headline messages",
-        mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+        mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 0);
         const { $msg } = converse.env;
@@ -27,11 +27,10 @@ describe("A headlines box", function () {
             .c('body').t('SORRY FOR THIS ADVERT');
         _converse.connection._dataRecv(mock.createRequest(stanza));
         expect(_converse.api.headlines.get().length === 0);
-        done();
     }));
 
     it("will open and display headline messages", mock.initConverse(
-            [], {}, async function (done, _converse) {
+            [], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 0);
         const { u, $msg} = converse.env;
@@ -64,11 +63,10 @@ describe("A headlines box", function () {
         const view = _converse.chatboxviews.get('notify.example.com');
         expect(view.model.get('show_avatar')).toBeFalsy();
         expect(view.querySelector('img.avatar')).toBe(null);
-        done();
     }));
 
     it("will show headline messages in the controlbox", mock.initConverse(
-            [], {}, async function (done, _converse) {
+            [], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 0);
         const { u, $msg} = converse.env;
@@ -101,11 +99,10 @@ describe("A headlines box", function () {
         await u.waitUntil(() => view.querySelectorAll(".open-headline").length);
         expect(view.querySelectorAll('.open-headline').length).toBe(1);
         expect(view.querySelector('.open-headline').text).toBe('notify.example.com');
-        done();
     }));
 
     it("will remove headline messages from the controlbox if closed", mock.initConverse(
-        [], {}, async function (done, _converse) {
+        [], {}, async function (_converse) {
 
         const { u, $msg} = converse.env;
         await mock.waitForRoster(_converse, 'current', 0);
@@ -143,12 +140,11 @@ describe("A headlines box", function () {
         close_el.click();
         await u.waitUntil(() => cbview.querySelectorAll(".open-headline").length === 0);
         expect(cbview.querySelectorAll('.open-headline').length).toBe(0);
-        done();
     }));
 
     it("will not show a headline messages from a full JID if allow_non_roster_messaging is false",
         mock.initConverse(
-            ['chatBoxesFetched'], {}, async function (done, _converse) {
+            ['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 0);
         const { $msg } = converse.env;
@@ -163,6 +159,5 @@ describe("A headlines box", function () {
             .c('body').t('Здравствуйте друзья');
         _converse.connection._dataRecv(mock.createRequest(stanza));
         expect(_.without('controlbox', _converse.chatboxviews.keys()).length).toBe(0);
-        done();
     }));
 });

+ 22 - 44
src/plugins/mam-views/tests/mam.js

@@ -19,7 +19,7 @@ describe("Message Archive Management", function () {
     describe("The XEP-0313 Archive", function () {
 
         it("is queried when the user scrolls up",
-                mock.initConverse(['discoInitialized'], {'archived_messages_page_size': 2}, async function (done, _converse) {
+                mock.initConverse(['discoInitialized'], {'archived_messages_page_size': 2}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 1);
             const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -78,7 +78,6 @@ describe("Message Archive Management", function () {
                     `<set xmlns="http://jabber.org/protocol/rsm"><before>${view.model.messages.at(0).get('stanza_id romeo@montague.lit')}</before><max>2</max></set></query>`+
                 `</iq>`
             );
-            done();
         }));
 
         it("is queried when the user enters a new MUC",
@@ -86,7 +85,7 @@ describe("Message Archive Management", function () {
                 {
                     'archived_messages_page_size': 2,
                     'muc_clear_messages_on_leave': false,
-                }, async function (done, _converse) {
+                }, async function (_converse) {
 
             const sent_IQs = _converse.connection.IQ_stanzas;
             const muc_jid = 'orchard@chat.shakespeare.lit';
@@ -269,7 +268,6 @@ describe("Message Archive Management", function () {
             await u.waitUntil(() => view.querySelectorAll('.chat-msg__text').length);
             await u.waitUntil(() => Array.from(view.querySelectorAll('.chat-msg__text'))
                 .map(e => e.textContent).join(' ') === "2nd Message 3rd Message 4th Message 5th Message 6th Message", 1000);
-            done();
         }));
 
         it("queries for messages since the most recent cached message in a newly entered MUC",
@@ -278,7 +276,7 @@ describe("Message Archive Management", function () {
                     'archived_messages_page_size': 2,
                     'muc_nickname_from_jid': false,
                     'muc_clear_messages_on_leave': false,
-                }, async function (done, _converse) {
+                }, async function (_converse) {
 
             const { api } = _converse;
             const sent_IQs = _converse.connection.IQ_stanzas;
@@ -322,7 +320,6 @@ describe("Message Archive Management", function () {
                         `<set xmlns="http://jabber.org/protocol/rsm"><max>2</max></set>`+
                     `</query>`+
                 `</iq>`);
-            return done();
         }));
     });
 
@@ -332,7 +329,7 @@ describe("Message Archive Management", function () {
             it("is discarded if it doesn't come from the right sender",
                 mock.initConverse(
                     ['discoInitialized'], {},
-                    async function (done, _converse) {
+                    async function (_converse) {
 
                 await mock.waitForRoster(_converse, 'current', 1);
                 const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -382,13 +379,12 @@ describe("Message Archive Management", function () {
                     .filter(el => el.textContent === "Thrice the brinded cat hath mew'd.").length, 1000);
                 expect(view.model.messages.length).toBe(1);
                 expect(view.model.messages.at(0).get('message')).toBe("Thrice the brinded cat hath mew'd.");
-                done();
             }));
 
             it("is not discarded if it comes from the right sender",
                 mock.initConverse(
                     ['discoInitialized'], {},
-                    async function (done, _converse) {
+                    async function (_converse) {
 
                 await mock.waitForRoster(_converse, 'current', 1);
                 const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -437,13 +433,12 @@ describe("Message Archive Management", function () {
                 expect(view.model.messages.length).toBe(2);
                 expect(view.model.messages.at(0).get('message')).toBe("Meet me at the dance");
                 expect(view.model.messages.at(1).get('message')).toBe("Thrice the brinded cat hath mew'd.");
-                done();
             }));
 
             it("updates the is_archived value of an already cached version",
                 mock.initConverse(
                     ['discoInitialized'], {},
-                    async function (done, _converse) {
+                    async function (_converse) {
 
                 await mock.openAndEnterChatRoom(_converse, 'trek-radio@conference.lightwitch.org', 'romeo');
 
@@ -485,13 +480,12 @@ describe("Message Archive Management", function () {
                 expect(view.model.messages.length).toBe(1);
                 expect(view.model.messages.at(0).get('is_archived')).toBe(true);
                 expect(view.model.messages.at(0).get('stanza_id trek-radio@conference.lightwitch.org')).toBe('45fbbf2a-1059-479d-9283-c8effaf05621');
-                done();
             }));
 
             it("isn't shown as duplicate by comparing its stanza id or archive id",
                 mock.initConverse(
                     ['discoInitialized'], {},
-                    async function (done, _converse) {
+                    async function (_converse) {
 
                 await mock.openAndEnterChatRoom(_converse, 'trek-radio@conference.lightwitch.org', 'jcbrand');
                 const view = _converse.chatboxviews.get('trek-radio@conference.lightwitch.org');
@@ -524,13 +518,12 @@ describe("Message Archive Management", function () {
                 const result = await view.model.getDuplicateMessage.calls.all()[0].returnValue
                 expect(result instanceof _converse.Message).toBe(true);
                 expect(view.querySelectorAll('.chat-msg').length).toBe(1);
-                done();
             }));
 
             it("isn't shown as duplicate by comparing only the archive id",
                 mock.initConverse(
                     ['discoInitialized'], {},
-                    async function (done, _converse) {
+                    async function (_converse) {
 
                 await mock.openAndEnterChatRoom(_converse, 'discuss@conference.conversejs.org', 'romeo');
                 const view = _converse.chatboxviews.get('discuss@conference.conversejs.org');
@@ -574,7 +567,6 @@ describe("Message Archive Management", function () {
                 const result = await view.model.getDuplicateMessage.calls.all()[0].returnValue
                 expect(result instanceof _converse.Message).toBe(true);
                 expect(view.querySelectorAll('.chat-msg').length).toBe(1);
-                done();
             }))
         });
     });
@@ -582,7 +574,7 @@ describe("Message Archive Management", function () {
     describe("The archive.query API", function () {
 
        it("can be used to query for all archived messages",
-                mock.initConverse(['discoInitialized'], {}, async function (done, _converse) {
+                mock.initConverse(['discoInitialized'], {}, async function (_converse) {
 
             const sendIQ = _converse.connection.sendIQ;
             await mock.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, null, [Strophe.NS.MAM]);
@@ -596,11 +588,10 @@ describe("Message Archive Management", function () {
             const queryid = sent_stanza.querySelector('query').getAttribute('queryid');
             expect(Strophe.serialize(sent_stanza)).toBe(
                 `<iq id="${IQ_id}" type="set" xmlns="jabber:client"><query queryid="${queryid}" xmlns="urn:xmpp:mam:2"/></iq>`);
-            done();
         }));
 
        it("can be used to query for all messages to/from a particular JID",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             await mock.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, null, [Strophe.NS.MAM]);
             let sent_stanza, IQ_id;
@@ -625,11 +616,10 @@ describe("Message Archive Management", function () {
                         `</x>`+
                     `</query>`+
                 `</iq>`);
-            done();
         }));
 
        it("can be used to query for archived messages from a chat room",
-                mock.initConverse(['statusInitialized'], {}, async function (done, _converse) {
+                mock.initConverse(['statusInitialized'], {}, async function (_converse) {
 
             const room_jid = 'coven@chat.shakespeare.lit';
             _converse.api.archive.query({'with': room_jid, 'groupchat': true});
@@ -650,11 +640,10 @@ describe("Message Archive Management", function () {
                         `</x>`+
                     `</query>`+
                 `</iq>`);
-            done();
        }));
 
         it("checks whether returned MAM messages from a MUC room are from the right JID",
-                mock.initConverse(['statusInitialized'], {}, async function (done, _converse) {
+                mock.initConverse(['statusInitialized'], {}, async function (_converse) {
 
             const room_jid = 'coven@chat.shakespeare.lit';
             const promise = _converse.api.archive.query({'with': room_jid, 'groupchat': true, 'max':'10'});
@@ -719,11 +708,10 @@ describe("Message Archive Management", function () {
 
             const result = await promise;
             expect(result.messages.length).toBe(0);
-            done();
        }));
 
        it("can be used to query for all messages in a certain timespan",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             await mock.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, null, [Strophe.NS.MAM]);
             let sent_stanza, IQ_id;
@@ -757,11 +745,10 @@ describe("Message Archive Management", function () {
                     `</query>`+
                 `</iq>`
             );
-            done();
        }));
 
        it("throws a TypeError if an invalid date is provided",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             await mock.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, null, [Strophe.NS.MAM]);
             try {
@@ -769,11 +756,10 @@ describe("Message Archive Management", function () {
             } catch (e) {
                 expect(() => {throw e}).toThrow(new TypeError('archive.query: invalid date provided for: start'));
             }
-            done();
        }));
 
        it("can be used to query for all messages after a certain time",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             await mock.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, null, [Strophe.NS.MAM]);
             let sent_stanza, IQ_id;
@@ -803,11 +789,10 @@ describe("Message Archive Management", function () {
                     `</query>`+
                 `</iq>`
             );
-            done();
        }));
 
        it("can be used to query for a limited set of results",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             await mock.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, null, [Strophe.NS.MAM]);
             let sent_stanza, IQ_id;
@@ -837,11 +822,10 @@ describe("Message Archive Management", function () {
                     `</query>`+
                 `</iq>`
             );
-            done();
        }));
 
        it("can be used to page through results",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             await mock.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, null, [Strophe.NS.MAM]);
             let sent_stanza, IQ_id;
@@ -875,11 +859,10 @@ describe("Message Archive Management", function () {
                         `</set>`+
                     `</query>`+
                 `</iq>`);
-            done();
        }));
 
        it("accepts \"before\" with an empty string as value to reverse the order",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             await mock.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, null, [Strophe.NS.MAM]);
             let sent_stanza, IQ_id;
@@ -905,11 +888,10 @@ describe("Message Archive Management", function () {
                         `</set>`+
                     `</query>`+
                 `</iq>`);
-            done();
        }));
 
        it("returns an object which includes the messages and a _converse.RSM object",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             await mock.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, null, [Strophe.NS.MAM]);
             let sent_stanza, IQ_id;
@@ -988,14 +970,13 @@ describe("Message Archive Management", function () {
             expect(result.rsm.result.count).toBe(16);
             expect(result.rsm.result.first).toBe('23452-4534-1');
             expect(result.rsm.result.last).toBe('09af3-cc343-b409f');
-            done()
        }));
     });
 
     describe("The default preference", function () {
 
         it("is set once server support for MAM has been confirmed",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             const { api } = _converse;
 
@@ -1065,7 +1046,6 @@ describe("Message Archive Management", function () {
             await u.waitUntil(() => feature.save.calls.count());
             expect(feature.save).toHaveBeenCalled();
             expect(feature.get('preferences')['default']).toBe('never'); // eslint-disable-line dot-notation
-            done();
         }));
     });
 });
@@ -1074,7 +1054,7 @@ describe("Chatboxes", function () {
     describe("A Chatbox", function () {
 
         it("will fetch archived messages once it's opened",
-                mock.initConverse(['discoInitialized'], {}, async function (done, _converse) {
+                mock.initConverse(['discoInitialized'], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 1);
             const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -1130,11 +1110,10 @@ describe("Chatboxes", function () {
                         .c('last').t('09af3-cc343-b409f').up()
                         .c('count').t('16');
             _converse.connection._dataRecv(mock.createRequest(stanza));
-            done();
         }));
 
         it("will show an error message if the MAM query times out",
-                mock.initConverse(['discoInitialized'], {}, async function (done, _converse) {
+                mock.initConverse(['discoInitialized'], {}, async function (_converse) {
 
             const sendIQ = _converse.connection.sendIQ;
 
@@ -1231,7 +1210,6 @@ describe("Chatboxes", function () {
             await u.waitUntil(() => view.model.messages.length === 2, 500);
             err_message = view.querySelector('.message.chat-error');
             expect(err_message).toBe(null);
-            done();
         }));
     });
 });

+ 2 - 4
src/plugins/mam-views/tests/placeholder.js

@@ -14,7 +14,7 @@ describe("Message Archive Management", function () {
                     'persistent_store': 'localStorage',
                     'mam_request_all_pages': false
                 },
-                async function (done, _converse) {
+                async function (_converse) {
 
             const sent_IQs = _converse.connection.IQ_stanzas;
             const muc_jid = 'orchard@chat.shakespeare.lit';
@@ -152,12 +152,11 @@ describe("Message Archive Management", function () {
             _converse.connection._dataRecv(mock.createRequest(result));
             await u.waitUntil(() => view.model.messages.length === 4);
             await u.waitUntil(() => view.querySelector('converse-mam-placeholder') === null);
-            done();
         }));
 
         it("is not created when there isn't a gap because the cached history is empty",
                 mock.initConverse(['discoInitialized'], {'archived_messages_page_size': 2},
-                async function (done, _converse) {
+                async function (_converse) {
 
             const sent_IQs = _converse.connection.IQ_stanzas;
             const muc_jid = 'orchard@chat.shakespeare.lit';
@@ -213,7 +212,6 @@ describe("Message Archive Management", function () {
             _converse.connection._dataRecv(mock.createRequest(result));
             await u.waitUntil(() => view.model.messages.length === 2);
             expect(true).toBe(true);
-            done();
         }));
     });
 });

+ 12 - 27
src/plugins/minimize/tests/minchats.js

@@ -8,11 +8,8 @@ const sizzle = converse.env.sizzle;
 describe("A chat message", function () {
 
     it("received for a minimized chat box will increment a counter on its header",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {'view_mode': 'overlayed'}, async function (_converse) {
 
-        if (_converse.view_mode === 'fullscreen') {
-            return done();
-        }
         await mock.waitForRoster(_converse, 'current');
         const contact_name = mock.cur_names[0];
         const contact_jid = contact_name.replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -65,7 +62,6 @@ describe("A chat message", function () {
         expect(count.textContent).toBe('2');
         document.querySelector("converse-minimized-chat a.restore-chat").click();
         expect(_converse.chatboxes.filter('minimized').length).toBe(0);
-        done();
     }));
 
 });
@@ -73,7 +69,7 @@ describe("A chat message", function () {
 describe("A Groupchat", function () {
 
     it("can be minimized by clicking a DOM element with class 'toggle-chatbox-button'",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.openChatRoom(_converse, 'lounge', 'montague.lit', 'romeo');
         const view = _converse.chatboxviews.get('lounge@montague.lit');
@@ -89,7 +85,6 @@ describe("A Groupchat", function () {
         expect(_converse.api.trigger).toHaveBeenCalledWith('chatBoxMaximized', jasmine.any(Object));
         expect(view.model.get('minimized')).toBeFalsy();
         expect(_converse.api.trigger.calls.count(), 3);
-        done();
     }));
 });
 
@@ -97,7 +92,7 @@ describe("A Groupchat", function () {
 describe("A Chatbox", function () {
 
     it("can be minimized by clicking a DOM element with class 'toggle-chatbox-button'",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current');
         await mock.openControlBox(_converse);
@@ -121,11 +116,10 @@ describe("A Chatbox", function () {
         minimized_chats.querySelector("a.restore-chat").click();
         expect(_converse.api.trigger).toHaveBeenCalledWith('chatBoxMaximized', jasmine.any(Object));
         expect(chatview.model.get('minimized')).toBeFalsy();
-        done();
     }));
 
 
-    it("can be opened in minimized mode initially", mock.initConverse([], {}, async function (done, _converse) {
+    it("can be opened in minimized mode initially", mock.initConverse([], {}, async function (_converse) {
         await mock.waitForRoster(_converse, 'current');
         const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
         const minimized_chats = document.querySelector("converse-minimized-chats")
@@ -136,11 +130,10 @@ describe("A Chatbox", function () {
         expect(u.isVisible(minimized_chats.firstElementChild)).toBe(true);
         expect(minimized_chats.firstElementChild.querySelectorAll('converse-minimized-chat').length).toBe(1);
         expect(_converse.chatboxes.filter('minimized').length).toBe(1);
-        done();
     }));
 
 
-    it("can be trimmed to conserve space", mock.initConverse([], {}, async function (done, _converse) {
+    it("can be trimmed to conserve space", mock.initConverse([], {}, async function (_converse) {
         spyOn(_converse.minimize, 'trimChats');
         await mock.waitForRoster(_converse, 'current');
         await mock.openControlBox(_converse);
@@ -173,7 +166,6 @@ describe("A Chatbox", function () {
         const minimized_chats = document.querySelector("converse-minimized-chats")
         minimized_chats.querySelector("a.restore-chat").click();
         expect(_converse.minimize.trimChats.calls.count()).toBe(17);
-        done();
     }));
 });
 
@@ -181,7 +173,7 @@ describe("A Chatbox", function () {
 describe("A Minimized ChatBoxView's Unread Message Count", function () {
 
     it("is displayed when scrolled up chatbox is minimized after receiving unread messages",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 1);
         const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -199,11 +191,10 @@ describe("A Minimized ChatBoxView's Unread Message Count", function () {
         const unread_count = selectUnreadMsgCount();
         expect(u.isVisible(unread_count)).toBeTruthy();
         expect(unread_count.innerHTML.replace(/<!-.*?->/g, '')).toBe('1');
-        done();
     }));
 
     it("is incremented when message is received and windows is not focused",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 1);
         const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -217,11 +208,10 @@ describe("A Minimized ChatBoxView's Unread Message Count", function () {
         const unread_count = selectUnreadMsgCount();
         expect(u.isVisible(unread_count)).toBeTruthy();
         expect(unread_count.innerHTML.replace(/<!-.*?->/g, '')).toBe('1');
-        done();
     }));
 
     it("will render Openstreetmap-URL from geo-URI",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 1);
         const message = "geo:37.786971,-122.399677";
@@ -236,7 +226,6 @@ describe("A Minimized ChatBoxView's Unread Message Count", function () {
         await u.waitUntil(() => msg.innerHTML.replace(/\<!-.*?-\>/g, '') ===
             '<a target="_blank" rel="noopener" href="https://www.openstreetmap.org/?mlat=37.786971&amp;'+
             'mlon=-122.399677#map=18/37.786971/-122.399677">https://www.openstreetmap.org/?mlat=37.786971&amp;mlon=-122.399677#map=18/37.786971/-122.399677</a>');
-        done();
     }));
 });
 
@@ -244,7 +233,7 @@ describe("A Minimized ChatBoxView's Unread Message Count", function () {
 describe("The Minimized Chats Widget", function () {
 
     it("shows chats that have been minimized",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current');
         await mock.openControlBox(_converse);
@@ -271,11 +260,10 @@ describe("The Minimized Chats Widget", function () {
         expect(u.isVisible(minimized_chats)).toBe(true);
         expect(_converse.chatboxes.filter('minimized').length).toBe(2);
         expect(_converse.chatboxes.filter('minimized').map(c => c.get('jid')).includes(contact_jid)).toBeTruthy();
-        done();
     }));
 
     it("can be toggled to hide or show minimized chats",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current');
         await mock.openControlBox(_converse);
@@ -297,11 +285,10 @@ describe("The Minimized Chats Widget", function () {
         minimized_chats.querySelector('#toggle-minimized-chats').click();
         await u.waitUntil(() => u.isVisible(minimized_chats.querySelector('.minimized-chats-flyout')));
         expect(minimized_chats.minchats.get('collapsed')).toBeTruthy();
-        done();
     }));
 
     it("shows the number messages received to minimized chats",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 4);
         await mock.openControlBox(_converse);
@@ -372,11 +359,10 @@ describe("The Minimized Chats Widget", function () {
             id: u.getUniqueId()
         }).c('inactive', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
         expect(minimized_chats.querySelector('.unread-message-count').textContent).toBe((i).toString());
-        done();
     }));
 
     it("shows the number messages received to minimized groupchats",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         const muc_jid = 'kitchen@conference.shakespeare.lit';
         await mock.openAndEnterChatRoom(_converse, 'kitchen@conference.shakespeare.lit', 'fires');
@@ -395,6 +381,5 @@ describe("The Minimized Chats Widget", function () {
         const minimized_chats = document.querySelector("converse-minimized-chats")
         expect(u.isVisible(minimized_chats.querySelector('.unread-message-count'))).toBeTruthy();
         expect(minimized_chats.querySelector('.unread-message-count').textContent).toBe('1');
-        done();
     }));
 });

+ 6 - 12
src/plugins/muc-views/tests/autocomplete.js

@@ -9,7 +9,7 @@ describe("The nickname autocomplete feature", function () {
 
     it("shows all autocompletion options when the user presses @",
             mock.initConverse(['chatBoxesFetched'], {},
-            async function (done, _converse) {
+            async function (_converse) {
 
         await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'tom');
         const view = _converse.chatboxviews.get('lounge@montague.lit');
@@ -58,12 +58,11 @@ describe("The nickname autocomplete feature", function () {
         expect(view.querySelector('.suggestion-box__results li:nth-child(2)').textContent).toBe('harry');
         expect(view.querySelector('.suggestion-box__results li:nth-child(3)').textContent).toBe('jane');
         expect(view.querySelector('.suggestion-box__results li:nth-child(4)').textContent).toBe('tom');
-        done();
     }));
 
     it("shows all autocompletion options when the user presses @ right after a new line",
             mock.initConverse(['chatBoxesFetched'], {},
-            async function (done, _converse) {
+            async function (_converse) {
 
         await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'tom');
         const view = _converse.chatboxviews.get('lounge@montague.lit');
@@ -113,13 +112,12 @@ describe("The nickname autocomplete feature", function () {
         expect(view.querySelector('.suggestion-box__results li:nth-child(2)').textContent).toBe('harry');
         expect(view.querySelector('.suggestion-box__results li:nth-child(3)').textContent).toBe('jane');
         expect(view.querySelector('.suggestion-box__results li:nth-child(4)').textContent).toBe('tom');
-        done();
     }));
 
     it("shows all autocompletion options when the user presses @ right after an allowed character",
         mock.initConverse(
             ['chatBoxesFetched'], {'opening_mention_characters':['(']},
-            async function (done, _converse) {
+            async function (_converse) {
 
         await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'tom');
         const view = _converse.chatboxviews.get('lounge@montague.lit');
@@ -169,11 +167,10 @@ describe("The nickname autocomplete feature", function () {
         expect(view.querySelector('.suggestion-box__results li:nth-child(2)').textContent).toBe('harry');
         expect(view.querySelector('.suggestion-box__results li:nth-child(3)').textContent).toBe('jane');
         expect(view.querySelector('.suggestion-box__results li:nth-child(4)').textContent).toBe('tom');
-        done();
     }));
 
     it("should order by query index position and length", mock.initConverse(
-            ['chatBoxesFetched'], {}, async function (done, _converse) {
+            ['chatBoxesFetched'], {}, async function (_converse) {
             await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'tom');
             const view = _converse.chatboxviews.get('lounge@montague.lit');
 
@@ -217,11 +214,10 @@ describe("The nickname autocomplete feature", function () {
             await u.waitUntil(() => view.querySelectorAll('.suggestion-box__results li').length === 2);
             expect(view.querySelector('.suggestion-box__results li:first-child').textContent).toBe('john');
             expect(view.querySelector('.suggestion-box__results li:nth-child(2)').textContent).toBe('jones');
-            done();
     }));
 
     it("autocompletes when the user presses tab",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
         const view = _converse.chatboxviews.get('lounge@montague.lit');
@@ -328,11 +324,10 @@ describe("The nickname autocomplete feature", function () {
         message_form.onKeyDown(tab_event);
         message_form.onKeyUp(tab_event);
         await u.waitUntil(() => textarea.value === 'hello @z3r0 ');
-        done();
     }));
 
     it("autocompletes when the user presses backspace",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
         const view = _converse.chatboxviews.get('lounge@montague.lit');
@@ -368,6 +363,5 @@ describe("The nickname autocomplete feature", function () {
         await u.waitUntil(() => view.querySelector('.suggestion-box__results').hidden === false);
         expect(view.querySelectorAll('.suggestion-box__results li').length).toBe(1);
         expect(view.querySelector('.suggestion-box__results li').textContent).toBe('some1');
-        done();
     }));
 });

+ 2 - 4
src/plugins/muc-views/tests/component.js

@@ -6,7 +6,7 @@ const u = converse.env.utils;
 describe("The <converse-muc> component", function () {
 
     it("can be rendered as a standalone component",
-            mock.initConverse([], {'auto_insert': false}, async function (done, _converse) {
+            mock.initConverse([], {'auto_insert': false}, async function (_converse) {
 
         const { api } = _converse;
         const muc_jid = 'lounge@montague.lit';
@@ -33,11 +33,10 @@ describe("The <converse-muc> component", function () {
         await u.waitUntil(() => muc_el.querySelector('converse-muc-bottom-panel'));
         body.removeChild(span_el);
         expect(true).toBe(true);
-        done();
     }));
 
     it("will update correctly when the jid property changes",
-            mock.initConverse([], {'auto_insert': false}, async function (done, _converse) {
+            mock.initConverse([], {'auto_insert': false}, async function (_converse) {
 
         const { api } = _converse;
         const muc_jid = 'lounge@montague.lit';
@@ -89,6 +88,5 @@ describe("The <converse-muc> component", function () {
 
         await u.waitUntil(() => muc_el.querySelector('converse-chat-message-body').textContent.trim() === 'hello from the bar!');
         body.removeChild(span_el);
-        done();
     }));
 });

+ 3 - 6
src/plugins/muc-views/tests/corrections.js

@@ -5,7 +5,7 @@ const { $msg, $pres, Strophe, u } = converse.env;
 describe("A Groupchat Message", function () {
 
     it("can be replaced with a correction",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         const muc_jid = 'lounge@montague.lit';
         await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
@@ -66,11 +66,10 @@ describe("A Groupchat Message", function () {
         expect(older_msgs.length).toBe(2);
         expect(older_msgs[0].textContent.includes('But soft, what light through yonder airlock breaks?')).toBe(true);
         expect(older_msgs[1].textContent.includes('But soft, what light through yonder chimney breaks?')).toBe(true);
-        done();
     }));
 
     it("keeps the same position in history after a correction",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         const muc_jid = 'lounge@montague.lit';
         await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
@@ -158,11 +157,10 @@ describe("A Groupchat Message", function () {
         expect(older_msgs.length).toBe(2);
         expect(older_msgs[0].textContent.includes('But soft, what light through yonder airlock breaks?')).toBe(true);
         expect(older_msgs[1].textContent.includes('But soft, what light through yonder chimney breaks?')).toBe(true);
-        done();
     }));
 
     it("can be sent as a correction by using the up arrow",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         const muc_jid = 'lounge@montague.lit';
         await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
@@ -262,6 +260,5 @@ describe("A Groupchat Message", function () {
         expect(view.model.messages.at(0).get('correcting')).toBe(false);
         expect(view.querySelectorAll('.chat-msg').length).toBe(2);
         await u.waitUntil(() => !u.hasClass('correcting', view.querySelector('.chat-msg')), 500);
-        done();
     }));
 });

+ 4 - 8
src/plugins/muc-views/tests/emojis.js

@@ -6,7 +6,7 @@ const u = converse.env.utils;
 describe("Emojis", function () {
     describe("The emoji picker", function () {
         it("is opened to autocomplete emojis in the textarea",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 0);
             const muc_jid = 'lounge@montague.lit';
@@ -70,11 +70,10 @@ describe("Emojis", function () {
             await u.waitUntil(() => input.value === ':use');
             visible_emojis = sizzle('.insert-emoji:not(.hidden)', picker);
             expect(visible_emojis.length).toBe(0);
-            done();
         }));
 
         it("is focused to autocomplete emojis in the textarea",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             const muc_jid = 'lounge@montague.lit';
             await mock.waitForRoster(_converse, 'current', 0);
@@ -119,12 +118,11 @@ describe("Emojis", function () {
             emoji = sizzle('.emojis-lists__container--search .insert-emoji:not(.hidden) a', view).pop();
             emoji.click();
             await u.waitUntil(() => textarea.value === ':grinning: :grimacing: ');
-            done();
         }));
 
 
         it("properly inserts emojis into the chat textarea",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             const muc_jid = 'lounge@montague.lit';
             await mock.waitForRoster(_converse, 'current', 0);
@@ -164,12 +162,11 @@ describe("Emojis", function () {
             const emoji = sizzle('.emojis-lists__container--search .insert-emoji:not(.hidden) a', view).pop();
             emoji.click();
             expect(textarea.value).toBe(':100: ');
-            done();
         }));
 
 
         it("allows you to search for particular emojis",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             const muc_jid = 'lounge@montague.lit';
             await mock.waitForRoster(_converse, 'current', 0);
@@ -222,7 +219,6 @@ describe("Emojis", function () {
             input.dispatchEvent(new KeyboardEvent('keydown', enter_event));
             await u.waitUntil(() => input.value === '');
             expect(view.querySelector('textarea.chat-textarea').value).toBe(':smiley: ');
-            done();
         }));
     });
 });

+ 1 - 2
src/plugins/muc-views/tests/hats.js

@@ -5,7 +5,7 @@ const u = converse.env.utils;
 describe("A XEP-0317 MUC Hat", function () {
 
     it("can be included in a presence stanza",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
         const muc_jid = 'lounge@montague.lit';
         await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
         const view = _converse.chatboxviews.get(muc_jid);
@@ -70,6 +70,5 @@ describe("A XEP-0317 MUC Hat", function () {
         `)));
         await u.waitUntil(() => view.model.getOccupant("Terry").get('hats').length === 0);
         await u.waitUntil(() => view.querySelectorAll('.chat-msg .badge').length === 0);
-        done();
     }));
 })

+ 3 - 6
src/plugins/muc-views/tests/http-file-upload.js

@@ -8,7 +8,7 @@ describe("XEP-0363: HTTP File Upload", function () {
     describe("When not supported", function () {
         describe("A file upload toolbar button", function () {
 
-            it("does not appear in MUC chats", mock.initConverse([], {}, async (done, _converse) => {
+            it("does not appear in MUC chats", mock.initConverse([], {}, async (_converse) => {
                 await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
                 mock.waitUntilDiscoConfirmed(
                     _converse, _converse.domain,
@@ -19,7 +19,6 @@ describe("XEP-0363: HTTP File Upload", function () {
                 const view = _converse.chatboxviews.get('lounge@montague.lit');
                 await u.waitUntil(() => view.querySelector('.chat-toolbar .fileupload') === null);
                 expect(1).toBe(1);
-                done();
             }));
 
         });
@@ -29,7 +28,7 @@ describe("XEP-0363: HTTP File Upload", function () {
 
         describe("A file upload toolbar button", function () {
 
-            it("appears in MUC chats", mock.initConverse(['chatBoxesFetched'], {}, async (done, _converse) => {
+            it("appears in MUC chats", mock.initConverse(['chatBoxesFetched'], {}, async (_converse) => {
                 await mock.waitUntilDiscoConfirmed(
                     _converse, _converse.domain,
                     [{'category': 'server', 'type':'IM'}],
@@ -41,12 +40,11 @@ describe("XEP-0363: HTTP File Upload", function () {
                 await u.waitUntil(() => _converse.chatboxviews.get('lounge@montague.lit').querySelector('.fileupload'));
                 const view = _converse.chatboxviews.get('lounge@montague.lit');
                 expect(view.querySelector('.chat-toolbar .fileupload')).not.toBe(null);
-                done();
             }));
 
             describe("when clicked and a file chosen", function () {
 
-                it("is uploaded and sent out from a groupchat", mock.initConverse(['chatBoxesFetched'], {} ,async (done, _converse) => {
+                it("is uploaded and sent out from a groupchat", mock.initConverse(['chatBoxesFetched'], {} ,async (_converse) => {
                     const base_url = 'https://conversejs.org';
                     await mock.waitUntilDiscoConfirmed(
                         _converse, _converse.domain,
@@ -148,7 +146,6 @@ describe("XEP-0363: HTTP File Upload", function () {
                         `Download file "conversejs-filled.svg"</a>`);
 
                     XMLHttpRequest.prototype.send = send_backup;
-                    done();
                 }));
 
 

+ 1 - 2
src/plugins/muc-views/tests/markers.js

@@ -6,7 +6,7 @@ const u = converse.env.utils;
 
 describe("A XEP-0333 Chat Marker", function () {
     it("may be returned for a MUC message",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current');
         const muc_jid = 'lounge@montague.lit';
@@ -64,6 +64,5 @@ describe("A XEP-0333 Chat Marker", function () {
         _converse.connection._dataRecv(mock.createRequest(stanza));
         await u.waitUntil(() => view.querySelectorAll('.chat-msg').length === 2);
         expect(view.querySelectorAll('.chat-msg__receipt').length).toBe(0);
-        done();
     }));
 });

+ 10 - 20
src/plugins/muc-views/tests/mentions.js

@@ -7,7 +7,7 @@ const u = converse.env.utils;
 describe("An incoming groupchat message", function () {
 
     it("is specially marked when you are mentioned in it",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         const muc_jid = 'lounge@montague.lit';
         await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
@@ -24,12 +24,11 @@ describe("An incoming groupchat message", function () {
         await view.model.handleMessageStanza(msg);
         await u.waitUntil(() => view.querySelectorAll('.chat-msg__text').length);
         expect(u.hasClass('mentioned', view.querySelector('.chat-msg'))).toBeTruthy();
-        done();
     }));
 
 
     it("highlights all users mentioned via XEP-0372 references",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         const muc_jid = 'lounge@montague.lit';
         await mock.openAndEnterChatRoom(_converse, muc_jid, 'tom');
@@ -79,11 +78,10 @@ describe("An incoming groupchat message", function () {
             'hello <span class="mention">z3r0</span> '+
             '<span class="mention mention--self badge badge-info">tom</span> '+
             '<span class="mention">mr.robot</span>, how are you?');
-        done();
     }));
 
     it("properly renders mentions that contain the pipe character",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         const muc_jid = 'lounge@montague.lit';
         const nick = 'romeo';
@@ -128,11 +126,10 @@ describe("An incoming groupchat message", function () {
 
         const message = await u.waitUntil(() => view.querySelector('.chat-msg__text'));
         expect(message.innerHTML.replace(/<!-.*?->/g, '')).toBe('hello <span class="mention">ThUnD3r|Gr33n</span>');
-        done();
     }));
 
     it("highlights all users mentioned via XEP-0372 references in a quoted message",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         const muc_jid = 'lounge@montague.lit';
         await mock.openAndEnterChatRoom(_converse, muc_jid, 'tom');
@@ -166,7 +163,6 @@ describe("An incoming groupchat message", function () {
             '<blockquote>hello <span class="mention">z3r0</span> <span class="mention mention--self badge badge-info">tom</span> <span class="mention">mr.robot</span>, how are you?</blockquote>');
         const message = view.querySelector('.chat-msg__text');
         expect(message.classList.length).toEqual(1);
-        done();
     }));
 });
 
@@ -176,7 +172,7 @@ describe("A sent groupchat message", function () {
     describe("in which someone is mentioned", function () {
 
         it("gets parsed for mentions which get turned into references",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             const muc_jid = 'lounge@montague.lit';
 
@@ -302,11 +298,10 @@ describe("A sent groupchat message", function () {
             expect(references.length).toBe(1);
             expect(references)
                 .toEqual([{"begin":0,"end":5,"value":"gh0st","type":"mention","uri":"xmpp:lounge@montague.lit/gh0st"}]);
-            done();
         }));
 
         it("gets parsed for mentions as indicated with an @ preceded by a space or at the start of the text",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             const muc_jid = 'lounge@montague.lit';
             await mock.openAndEnterChatRoom(_converse, muc_jid, 'tom');
@@ -334,11 +329,10 @@ describe("A sent groupchat message", function () {
             [text, references] = view.model.parseTextForReferences('nice website https://darnuria.eu/@darnuria');
             expect(references.length).toBe(0);
             expect(text).toBe('nice website https://darnuria.eu/@darnuria');
-            done();
         }));
 
         it("properly encodes the URIs in sent out references",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             const muc_jid = 'lounge@montague.lit';
             await mock.openAndEnterChatRoom(_converse, muc_jid, 'tom');
@@ -377,11 +371,10 @@ describe("A sent groupchat message", function () {
                             `<reference begin="6" end="16" type="mention" uri="xmpp:lounge@montague.lit/Link%20Mauve" xmlns="urn:xmpp:reference:0"/>`+
                             `<origin-id id="${msg.querySelector('origin-id').getAttribute("id")}" xmlns="urn:xmpp:sid:0"/>`+
                         `</message>`);
-            done();
         }));
 
         it("can get corrected and given new references",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             const muc_jid = 'lounge@montague.lit';
 
@@ -474,11 +467,10 @@ describe("A sent groupchat message", function () {
                             `<replace id="${msg.getAttribute("id")}" xmlns="urn:xmpp:message-correct:0"/>`+
                             `<origin-id id="${correction.querySelector('origin-id').getAttribute("id")}" xmlns="urn:xmpp:sid:0"/>`+
                         `</message>`);
-            done();
         }));
 
         it("includes a XEP-0372 references to that person",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             const muc_jid = 'lounge@montague.lit';
             await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
@@ -523,12 +515,11 @@ describe("A sent groupchat message", function () {
                             `<reference begin="18" end="26" type="mention" uri="xmpp:${muc_jid}/mr.robot" xmlns="urn:xmpp:reference:0"/>`+
                             `<origin-id id="${msg.querySelector('origin-id').getAttribute("id")}" xmlns="urn:xmpp:sid:0"/>`+
                         `</message>`);
-            done();
         }));
     });
 
     it("highlights all users mentioned via XEP-0372 references in a quoted message",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         const members = [{'jid': 'gibson@gibson.net', 'nick': 'gibson', 'affiliation': 'member'}];
         const muc_jid = 'lounge@montague.lit';
@@ -549,6 +540,5 @@ describe("A sent groupchat message", function () {
             `Welcome <span class="mention">gibson</span> <span title=":poop:">💩</span> `+
             `We have a guide on how to do that here: `+
             `<a target="_blank" rel="noopener" href="https://conversejs.org/docs/html/index.html">https://conversejs.org/docs/html/index.html</a>`);
-        done();
     }));
 });

+ 7 - 14
src/plugins/muc-views/tests/modtools.js

@@ -21,7 +21,7 @@ async function openModtools (_converse, view) {
 describe("The groupchat moderator tool", function () {
 
     it("allows you to set affiliations and roles",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         const muc_jid = 'lounge@montague.lit';
 
@@ -135,11 +135,10 @@ describe("The groupchat moderator tool", function () {
         user_els = roles_panel.querySelectorAll('.list-group--users > li')
         expect(user_els.length).toBe(1);
         expect(user_els[0].textContent.trim()).toBe('No users with that role found.');
-        done();
     }));
 
     it("allows you to filter affiliation search results",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         const muc_jid = 'lounge@montague.lit';
         const members = [
@@ -188,11 +187,10 @@ describe("The groupchat moderator tool", function () {
         u.triggerEvent(filter, "keyup", "KeyboardEvent");
         await u.waitUntil(() => ( modal.el.querySelectorAll('.list-group--users > li').length === 1));
 
-        done();
     }));
 
     it("allows you to filter role search results",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         const muc_jid = 'lounge@montague.lit';
         await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo', []);
@@ -295,11 +293,10 @@ describe("The groupchat moderator tool", function () {
         filter.value = 'crone';
         u.triggerEvent(filter, "keyup", "KeyboardEvent");
         await u.waitUntil(() => ( modal.el.querySelectorAll('.list-group--users > li').length === 1));
-        done();
     }));
 
     it("shows an error message if a particular affiliation list may not be retrieved",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         const muc_jid = 'lounge@montague.lit';
         const members = [
@@ -344,11 +341,10 @@ describe("The groupchat moderator tool", function () {
         const user_els = modal.el.querySelectorAll('.list-group--users > li');
         expect(user_els.length).toBe(1);
         expect(user_els[0].textContent.trim()).toBe('Error: not allowed to fetch outcast list for MUC lounge@montague.lit');
-        done();
     }));
 
     it("shows an error message if a particular affiliation may not be set",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         const muc_jid = 'lounge@montague.lit';
         const members = [
@@ -407,12 +403,11 @@ describe("The groupchat moderator tool", function () {
             </iq>`);
         _converse.connection._dataRecv(mock.createRequest(error));
 
-        done();
     }));
 
 
     it("doesn't allow admins to make more admins",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         const muc_jid = 'lounge@montague.lit';
         const members = [
@@ -442,11 +437,10 @@ describe("The groupchat moderator tool", function () {
 
         change_affiliation_dropdown = user_els[1].querySelector('.select-affiliation');
         expect(Array.from(change_affiliation_dropdown.options).map(o => o.value)).toEqual(['member', 'outcast', 'none']);
-        done();
     }));
 
     it("lets the assignable affiliations and roles be configured via modtools_disable_assign",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         const muc_jid = 'lounge@montague.lit';
         const members = [{'jid': 'romeo@montague.lit', 'nick': 'romeo', 'affiliation': 'owner'}];
@@ -476,6 +470,5 @@ describe("The groupchat moderator tool", function () {
 
         _converse.api.settings.set('modtools_disable_assign', ['admin', 'moderator']);
         expect(modal.getAssignableRoles(occupant)).toEqual(['participant', 'visitor']);
-        done();
     }));
 });

+ 3 - 6
src/plugins/muc-views/tests/muc-api.js

@@ -8,7 +8,7 @@ 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) {
+                mock.initConverse([], {}, async function (_converse) {
 
             await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
 
@@ -50,11 +50,10 @@ describe("Groupchats", function () {
 
             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) {
+                mock.initConverse([], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current');
             const rosterview = document.querySelector('converse-roster');
@@ -95,11 +94,10 @@ describe("Groupchats", function () {
             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.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             // Mock 'getDiscoInfo', otherwise the room won't be
             // displayed as it waits first for the features to be returned
@@ -261,7 +259,6 @@ describe("Groupchats", function () {
             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();
         }));
     });
 });

+ 1 - 2
src/plugins/muc-views/tests/muc-mentions.js

@@ -12,7 +12,7 @@ describe("MUC Mention Notfications", function () {
                 'allow_bookmarks': false, // Hack to get the rooms list to render
                 'muc_subscribe_to_rai': true,
                 'view_mode': 'fullscreen'},
-            async function (done, _converse) {
+            async function (_converse) {
 
         const { api } = _converse;
 
@@ -81,6 +81,5 @@ describe("MUC Mention Notfications", function () {
         _converse.connection._dataRecv(mock.createRequest(message));
         expect(Array.from(room_el.classList).includes('unread-msgs')).toBeTruthy();
         expect(room_el.querySelector('.msgs-indicator')?.textContent.trim()).toBe('2');
-        done();
     }));
 });

+ 14 - 28
src/plugins/muc-views/tests/muc-messages.js

@@ -12,7 +12,7 @@ describe("A Groupchat Message", function () {
     describe("which is succeeded by an error message", function () {
 
         it("will have the error displayed below it",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             const muc_jid = 'lounge@montague.lit';
             await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
@@ -48,7 +48,6 @@ describe("A Groupchat Message", function () {
             expect(message.get('body')).toBe('hello world');
             expect(message.get('error_text')).toBe(err_msg_text);
             expect(message.get('editable')).toBe(false);
-            done();
         }));
     });
 
@@ -56,7 +55,7 @@ describe("A Groupchat Message", function () {
     describe("an info message", function () {
 
         it("is not rendered as a followup message",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             const muc_jid = 'lounge@montague.lit';
             const nick = 'romeo';
@@ -89,11 +88,10 @@ describe("A Groupchat Message", function () {
             const messages = view.querySelectorAll('.chat-info');
             expect(u.hasClass('chat-msg--followup', messages[0])).toBe(false);
             expect(u.hasClass('chat-msg--followup', messages[1])).toBe(false);
-            done();
         }));
 
         it("is not shown if its a duplicate",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             const muc_jid = 'lounge@montague.lit';
             await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
@@ -120,13 +118,12 @@ describe("A Groupchat Message", function () {
             _converse.connection._dataRecv(mock.createRequest(presence));
             await u.waitUntil(() => view.model.createInfoMessages.calls.count() === 2);
             expect(view.querySelectorAll('.chat-info').length).toBe(1);
-            done();
         }));
     });
 
 
     it("is rejected if it's an unencapsulated forwarded message",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         const muc_jid = 'lounge@montague.lit';
         await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
@@ -155,11 +152,10 @@ describe("A Groupchat Message", function () {
         );
         expect(view.querySelectorAll('.chat-msg').length).toBe(0);
         expect(view.model.messages.length).toBe(0);
-        done();
     }));
 
     it("can contain a chat state notification and will still be shown",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         const muc_jid = 'lounge@montague.lit';
         await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
@@ -178,11 +174,10 @@ describe("A Groupchat Message", function () {
         await view.model.handleMessageStanza(msg);
         const el = await u.waitUntil(() => view.querySelector('.chat-msg__text'));
         expect(el.textContent).toBe(message);
-        done();
     }));
 
     it("can not be expected to have a unique id attribute",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         const muc_jid = 'lounge@montague.lit';
         await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
@@ -207,11 +202,10 @@ describe("A Groupchat Message", function () {
         await view.model.handleMessageStanza(msg);
         await u.waitUntil(() => view.querySelectorAll('.chat-msg').length === 2);
         expect(view.model.messages.length).toBe(2);
-        done();
     }));
 
     it("is ignored if it has the same archive-id of an already received one",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         const muc_jid = 'room@muc.example.com';
         await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
@@ -254,11 +248,10 @@ describe("A Groupchat Message", function () {
         expect(result instanceof _converse.Message).toBe(true);
         expect(view.model.messages.length).toBe(1);
         await u.waitUntil(() => view.model.updateMessage.calls.count());
-        done();
     }));
 
     it("is ignored if it has the same stanza-id of an already received one",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         const muc_jid = 'room@muc.example.com';
         await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
@@ -300,11 +293,10 @@ describe("A Groupchat Message", function () {
         expect(result instanceof _converse.Message).toBe(true);
         expect(view.model.messages.length).toBe(1);
         await u.waitUntil(() => view.model.updateMessage.calls.count());
-        done();
     }));
 
     it("will be discarded if it's a malicious message meant to look like a carbon copy",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current');
         await mock.openControlBox(_converse);
@@ -357,11 +349,10 @@ describe("A Groupchat Message", function () {
         );
         expect(view.querySelectorAll('.chat-msg').length).toBe(0);
         expect(view.model.messages.length).toBe(0);
-        done();
     }));
 
     it("keeps track of the sender's role and affiliation",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         const muc_jid = 'lounge@montague.lit';
         await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
@@ -483,12 +474,11 @@ describe("A Groupchat Message", function () {
         expect(view.model.messages.last().occupant.get('nick')).toBe('some1');
         // Check that the "add" event handler was removed.
         expect(view.model.occupants._events.add.length).toBe(add_events);
-        done();
     }));
 
 
     it("keeps track whether you are the sender or not",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         const muc_jid = 'lounge@montague.lit';
         await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
@@ -502,11 +492,10 @@ describe("A Groupchat Message", function () {
         await view.model.handleMessageStanza(msg);
         await u.waitUntil(() => view.model.messages.last()?.get('received'));
         expect(view.model.messages.last().get('sender')).toBe('me');
-        done();
     }));
 
     it("will be shown as received upon MUC reflection",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current');
         const muc_jid = 'lounge@montague.lit';
@@ -544,11 +533,10 @@ describe("A Groupchat Message", function () {
         const message = view.model.messages.at(0);
         expect(message.get('stanza_id lounge@montague.lit')).toBe('5f3dbc5e-e1d3-4077-a492-693f3769c7ad');
         expect(message.get('origin_id')).toBe(msg_obj.get('origin_id'));
-        done();
     }));
 
     it("gets updated with its stanza-id upon MUC reflection",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         const muc_jid = 'room@muc.example.com';
         await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
@@ -577,11 +565,10 @@ describe("A Groupchat Message", function () {
         expect(view.model.messages.length).toBe(1);
         expect(view.model.messages.at(0).get('stanza_id room@muc.example.com')).toBe("5f3dbc5e-e1d3-4077-a492-693f3769c7ad");
         expect(view.model.messages.at(0).get('origin_id')).toBe(msg.get('origin_id'));
-        done();
     }));
 
     it("can cause a delivery receipt to be returned",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current');
         const muc_jid = 'lounge@montague.lit';
@@ -621,6 +608,5 @@ describe("A Groupchat Message", function () {
             </message>`);
         _converse.connection._dataRecv(mock.createRequest(stanza));
         expect(view.querySelectorAll('.chat-msg').length).toBe(1);
-        done();
     }));
 });

+ 1 - 2
src/plugins/muc-views/tests/muc-registration.js

@@ -8,7 +8,7 @@ describe("Chatrooms", function () {
 
         it("allows you to register your nickname in a room",
                 mock.initConverse(['chatBoxesFetched'], {'auto_register_muc_nickname': true},
-                async function (done, _converse) {
+                async function (_converse) {
 
             const muc_jid = 'coven@chat.shakespeare.lit';
             await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo')
@@ -54,7 +54,6 @@ describe("Chatrooms", function () {
                         `</x>`+
                     `</query>`+
                 `</iq>`);
-            done();
         }));
     });
 });

File diff suppressed because it is too large
+ 74 - 147
src/plugins/muc-views/tests/muc.js


+ 6 - 12
src/plugins/muc-views/tests/muclist.js

@@ -9,7 +9,7 @@ describe("A list of open groupchats", function () {
             ['chatBoxesFetched'],
             { allow_bookmarks: false // Makes testing easier, otherwise we
                                         // have to mock stanza traffic.
-            }, async function (done, _converse) {
+            }, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 0);
         await mock.openControlBox(_converse);
@@ -44,14 +44,13 @@ describe("A list of open groupchats", function () {
 
         list = controlbox.querySelector('.list-container--openrooms');
         expect(Array.from(list.classList).includes('hidden')).toBeTruthy();
-        done();
     }));
 
     it("uses bookmarks to determine groupchat names",
         mock.initConverse(
             ['chatBoxesFetched'],
             {'view_mode': 'fullscreen'},
-            async function (done, _converse) {
+            async function (_converse) {
 
         const { Strophe, $iq, $pres, sizzle } = converse.env;
         const u = converse.env.utils;
@@ -106,7 +105,6 @@ describe("A list of open groupchats", function () {
         expect(items.length).toBe(1);
         await u.waitUntil(() => list.querySelector('.list-item').textContent.trim() === 'Bookmarked Lounge');
         expect(_converse.bookmarks.fetchBookmarks).toHaveBeenCalled();
-        done();
     }));
 });
 
@@ -116,7 +114,7 @@ describe("A groupchat shown in the groupchats list", function () {
             ['chatBoxesFetched'],
             { view_mode: 'fullscreen',
             allow_bookmarks: false // Makes testing easier, otherwise we have to mock stanza traffic.
-            }, async function (done, _converse) {
+            }, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 0);
         const controlbox = _converse.chatboxviews.get('controlbox');
@@ -141,7 +139,6 @@ describe("A groupchat shown in the groupchats list", function () {
         expect(room_els.length).toBe(1);
         item = room_els[0];
         expect(item.textContent.trim()).toBe('balcony@chat.shakespeare.lit');
-        done();
     }));
 
     it("has an info icon which opens a details modal when clicked", mock.initConverse(
@@ -149,7 +146,7 @@ describe("A groupchat shown in the groupchats list", function () {
             { whitelisted_plugins: ['converse-roomslist'],
             allow_bookmarks: false // Makes testing easier, otherwise we
                                     // have to mock stanza traffic.
-            }, async function (done, _converse) {
+            }, async function (_converse) {
 
         const { Strophe, $iq, $pres } = converse.env;
         const u = converse.env.utils;
@@ -250,7 +247,6 @@ describe("A groupchat shown in the groupchats list", function () {
         expect(els[3].textContent).toBe("Topic: Hatching dark plots")
         expect(els[4].textContent).toBe("Topic author: someone")
         expect(els[5].textContent).toBe("Online users: 2")
-        done();
     }));
 
     it("can be closed", mock.initConverse(
@@ -258,7 +254,7 @@ describe("A groupchat shown in the groupchats list", function () {
             { whitelisted_plugins: ['converse-roomslist'],
             allow_bookmarks: false // Makes testing easier, otherwise we have to mock stanza traffic.
             },
-            async function (done, _converse) {
+            async function (_converse) {
 
         const u = converse.env.utils;
         spyOn(window, 'confirm').and.callFake(() => true);
@@ -281,14 +277,13 @@ describe("A groupchat shown in the groupchats list", function () {
 
         await u.waitUntil(() => rooms_list.querySelectorAll(".open-room").length === 0);
         expect(_converse.chatboxes.length).toBe(1);
-        done();
     }));
 
     it("shows unread messages directed at the user", mock.initConverse(
             null,
             { whitelisted_plugins: ['converse-roomslist'],
             allow_bookmarks: false // Makes testing easier, otherwise we have to mock stanza traffic.
-            }, async (done, _converse) => {
+            }, async (_converse) => {
 
         const { $msg } = converse.env;
         const u = converse.env.utils;
@@ -345,6 +340,5 @@ describe("A groupchat shown in the groupchats list", function () {
         expect(indicator_el === null);
         room_el = lview.querySelector(".available-chatroom");
         expect(Array.from(room_el.classList).includes('unread-msgs')).toBeFalsy();
-        done();
     }));
 });

+ 3 - 6
src/plugins/muc-views/tests/rai.js

@@ -13,7 +13,7 @@ describe("XEP-0437 Room Activity Indicators", function () {
                 'allow_bookmarks': false, // Hack to get the rooms list to render
                 'muc_subscribe_to_rai': true,
                 'view_mode': 'fullscreen'},
-            async function (done, _converse) {
+            async function (_converse) {
 
         expect(_converse.session.get('rai_enabled_domains')).toBe(undefined);
 
@@ -110,7 +110,6 @@ describe("XEP-0437 Room Activity Indicators", function () {
 
         await u.waitUntil(() => view.model.get('has_activity'));
         expect(Array.from(room_el.classList).includes('unread-msgs')).toBeTruthy();
-        done();
     }));
 
     it("will be activated for a MUC that starts out hidden",
@@ -119,7 +118,7 @@ describe("XEP-0437 Room Activity Indicators", function () {
                 'allow_bookmarks': false, // Hack to get the rooms list to render
                 'muc_subscribe_to_rai': true,
                 'view_mode': 'fullscreen'},
-            async function (done, _converse) {
+            async function (_converse) {
 
         const { api } = _converse;
         expect(_converse.session.get('rai_enabled_domains')).toBe(undefined);
@@ -173,7 +172,6 @@ describe("XEP-0437 Room Activity Indicators", function () {
 
         await u.waitUntil(() => model.get('has_activity'));
         expect(Array.from(room_el.classList).includes('unread-msgs')).toBeTruthy();
-        done();
     }));
 
 
@@ -183,7 +181,7 @@ describe("XEP-0437 Room Activity Indicators", function () {
                 'allow_bookmarks': false, // Hack to get the rooms list to render
                 'muc_subscribe_to_rai': true,
                 'view_mode': 'fullscreen'},
-            async function (done, _converse) {
+            async function (_converse) {
 
         expect(_converse.session.get('rai_enabled_domains')).toBe(undefined);
 
@@ -218,7 +216,6 @@ describe("XEP-0437 Room Activity Indicators", function () {
         _converse.connection._dataRecv(mock.createRequest(activity_stanza));
 
         await u.waitUntil(() => view.model.session.get('connection_status') === converse.ROOMSTATUS.CONNECTING);
-        done();
     }));
 
 });

+ 18 - 36
src/plugins/muc-views/tests/retractions.js

@@ -37,7 +37,7 @@ describe("Message Retractions", function () {
     describe("A groupchat message retraction", function () {
 
         it("is not applied if it's not from the right author",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             const muc_jid = 'lounge@montague.lit';
             const features = [...mock.default_muc_features, Strophe.NS.MODERATE];
@@ -75,11 +75,10 @@ describe("Message Retractions", function () {
 
             expect(view.model.messages.at(0).get('retracted')).toBeFalsy();
             expect(view.model.messages.at(0).get('is_ephemeral')).toBeFalsy();
-            done();
         }));
 
         it("can be received before the message it pertains to",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             const date = (new Date()).toISOString();
             const muc_jid = 'lounge@montague.lit';
@@ -126,14 +125,13 @@ describe("Message Retractions", function () {
             expect(message.get('time')).toBe(date);
             expect(message.get('type')).toBe('groupchat');
             expect(await view.model.handleRetraction.calls.all().pop().returnValue).toBe(true);
-            done();
         }));
     });
 
     describe("A groupchat message moderator retraction", function () {
 
         it("can be received before the message it pertains to",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             const date = (new Date()).toISOString();
             const muc_jid = 'lounge@montague.lit';
@@ -184,7 +182,6 @@ describe("Message Retractions", function () {
             expect(message.get('time')).toBe(date);
             expect(message.get('type')).toBe('groupchat');
             expect(await view.model.handleModeration.calls.all().pop().returnValue).toBe(true);
-            done();
         }));
     });
 
@@ -192,7 +189,7 @@ describe("Message Retractions", function () {
     describe("A message retraction", function () {
 
         it("can be received before the message it pertains to",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             const date = (new Date()).toISOString();
             await mock.waitForRoster(_converse, 'current', 1);
@@ -241,13 +238,12 @@ describe("Message Retractions", function () {
             expect(message.get('origin_id')).toBe('2e972ea0-0050-44b7-a830-f6638a2595b3');
             expect(message.get('time')).toBe(date);
             expect(message.get('type')).toBe('chat');
-            done();
         }));
     });
 
     describe("A Received Chat Message", function () {
 
-        it("can be followed up by a retraction", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+        it("can be followed up by a retraction", mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
             await mock.waitForRoster(_converse, 'current', 1);
             await mock.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, [], [Strophe.NS.SID]);
             const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -307,13 +303,12 @@ describe("Message Retractions", function () {
             const msg_el = view.querySelector('.chat-msg--retracted .chat-msg__message');
             expect(msg_el.textContent.trim()).toBe('Mercutio has removed this message');
             expect(u.hasClass('chat-msg--followup', view.querySelector('.chat-msg--retracted'))).toBe(true);
-            done();
         }));
     });
 
     describe("A Sent Chat Message", function () {
 
-        it("can be retracted by its author", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+        it("can be retracted by its author", mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
             await mock.waitForRoster(_converse, 'current', 1);
             const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
             const view = await mock.openChatBoxFor(_converse, contact_jid);
@@ -352,14 +347,13 @@ describe("Message Retractions", function () {
             expect(view.querySelectorAll('.chat-msg--retracted').length).toBe(1);
             const el = view.querySelector('.chat-msg--retracted .chat-msg__message');
             expect(el.textContent.trim()).toBe('Romeo Montague has removed this message');
-            done();
         }));
     });
 
 
     describe("A Received Groupchat Message", function () {
 
-        it("can be followed up by a retraction by the author", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+        it("can be followed up by a retraction by the author", mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
             const muc_jid = 'lounge@montague.lit';
             const features = [...mock.default_muc_features, Strophe.NS.MODERATE];
             await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo', features);
@@ -395,12 +389,11 @@ describe("Message Retractions", function () {
             const msg_el = view.querySelector('.chat-msg--retracted .chat-msg__message');
             expect(msg_el.textContent.trim()).toBe('eve has removed this message');
             expect(msg_el.querySelector('.chat-msg--retracted q')).toBe(null);
-            done();
         }));
 
 
         it("can be retracted by a moderator, with the IQ response received before the retraction message",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             const muc_jid = 'lounge@montague.lit';
             const features = [...mock.default_muc_features, Strophe.NS.MODERATE];
@@ -480,11 +473,10 @@ describe("Message Retractions", function () {
             expect(view.model.messages.at(0).get('moderation_reason')).toBe(reason);
             expect(view.model.messages.at(0).get('is_ephemeral')).toBe(false);
             expect(view.model.messages.at(0).get('editable')).toBe(false);
-            done();
         }));
 
         it("can not be retracted if the MUC doesn't support message moderation",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             const muc_jid = 'lounge@montague.lit';
             await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
@@ -503,12 +495,11 @@ describe("Message Retractions", function () {
             expect(view.querySelector('.chat-msg__content .chat-msg__action-retract')).toBe(null);
             const result = await view.model.canModerateMessages();
             expect(result).toBe(false);
-            done();
         }));
 
 
         it("can be retracted by a moderator, with the retraction message received before the IQ response",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             const muc_jid = 'lounge@montague.lit';
             const features = [...mock.default_muc_features, Strophe.NS.MODERATE];
@@ -569,14 +560,13 @@ describe("Message Retractions", function () {
             expect(view.model.messages.at(0).get('moderated_by')).toBe(_converse.bare_jid);
             expect(view.model.messages.at(0).get('moderation_reason')).toBe(reason);
             expect(view.model.messages.at(0).get('editable')).toBe(false);
-            done();
         }));
     });
 
 
     describe("A Sent Groupchat Message", function () {
 
-        it("can be retracted by its author", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+        it("can be retracted by its author", mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
             const muc_jid = 'lounge@montague.lit';
             const features = [...mock.default_muc_features, Strophe.NS.MODERATE];
             await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo', features);
@@ -627,11 +617,10 @@ describe("Message Retractions", function () {
             expect(view.querySelectorAll('.chat-msg--retracted').length).toBe(1);
             const el = view.querySelector('.chat-msg--retracted .chat-msg__message div');
             expect(el.textContent).toBe('romeo has removed this message');
-            done();
         }));
 
         it("can be retracted by its author, causing an error message in response",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             const muc_jid = 'lounge@montague.lit';
             const features = [...mock.default_muc_features, Strophe.NS.MODERATE];
@@ -674,11 +663,10 @@ describe("Message Retractions", function () {
 
             const errmsg = view.querySelector('.chat-msg__error');
             expect(errmsg.textContent.trim()).toBe("You're not allowed to retract your message.");
-            done();
         }));
 
         it("can be retracted by its author, causing a timeout error in response",
-                mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             _converse.STANZA_TIMEOUT = 1;
 
@@ -708,11 +696,10 @@ describe("Message Retractions", function () {
             const error_messages = view.querySelectorAll('.chat-msg__error');
             expect(error_messages.length).toBe(1);
             expect(error_messages[0].textContent.trim()).toBe('A timeout happened while while trying to retract your message.');
-            done();
         }));
 
 
-        it("can be retracted by a moderator", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+        it("can be retracted by a moderator", mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
             const muc_jid = 'lounge@montague.lit';
             const features = [...mock.default_muc_features, Strophe.NS.MODERATE];
             await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo', features);
@@ -757,11 +744,10 @@ describe("Message Retractions", function () {
             expect(view.model.messages.at(0).get('moderation_reason')).toBe(reason);
             expect(view.model.messages.at(0).get('is_ephemeral')).toBe(false);
             expect(view.model.messages.at(0).get('editable')).toBe(false);
-            done();
         }));
 
         it("can be retracted by the sender if they're a moderator",
-                mock.initConverse(['chatBoxesFetched'], {'allow_message_retraction': 'moderator'}, async function (done, _converse) {
+                mock.initConverse(['chatBoxesFetched'], {'allow_message_retraction': 'moderator'}, async function (_converse) {
 
             const muc_jid = 'lounge@montague.lit';
             const features = [...mock.default_muc_features, Strophe.NS.MODERATE];
@@ -840,7 +826,6 @@ describe("Message Retractions", function () {
             expect(view.model.messages.at(0).get('moderation_reason')).toBe(undefined);
             expect(view.model.messages.at(0).get('is_ephemeral')).toBe(false);
             expect(view.model.messages.at(0).get('editable')).toBe(false);
-            done();
         }));
     });
 
@@ -850,7 +835,7 @@ describe("Message Retractions", function () {
         it("may be returned as a tombstone message",
             mock.initConverse(
                 ['discoInitialized'], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 1);
             const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -932,13 +917,12 @@ describe("Message Retractions", function () {
             const el = view.querySelector('.chat-msg--retracted .chat-msg__message div');
             expect(el.textContent.trim()).toBe('Mercutio has removed this message');
             expect(u.hasClass('chat-msg--followup', el.parentElement)).toBe(false);
-            done();
         }));
 
         it("may be returned as a tombstone groupchat message",
             mock.initConverse(
                 ['discoInitialized'], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             const muc_jid = 'lounge@montague.lit';
             const features = [...mock.default_muc_features, Strophe.NS.MODERATE];
@@ -1008,13 +992,12 @@ describe("Message Retractions", function () {
             expect(view.querySelectorAll('.chat-msg--retracted').length).toBe(1);
             const el = view.querySelector('.chat-msg--retracted .chat-msg__message div');
             expect(el.textContent.trim()).toBe('eve has removed this message');
-            done();
         }));
 
         it("may be returned as a tombstone moderated groupchat message",
             mock.initConverse(
                 ['discoInitialized', 'chatBoxesFetched'], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             const muc_jid = 'lounge@montague.lit';
             const features = [...mock.default_muc_features, Strophe.NS.MODERATE];
@@ -1096,7 +1079,6 @@ describe("Message Retractions", function () {
             expect(el.textContent.trim()).toBe('A moderator has removed this message');
             const qel = view.querySelector('.chat-msg--retracted .chat-msg__message q');
             expect(qel.textContent.trim()).toBe('This message contains inappropriate content');
-            done();
         }));
     });
 })

+ 2 - 4
src/plugins/muc-views/tests/styling.js

@@ -6,7 +6,7 @@ describe("An incoming groupchat Message", function () {
 
     it("can be styled with span XEP-0393 message styling hints that contain mentions",
             mock.initConverse(['chatBoxesFetched'], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
         const muc_jid = 'lounge@montague.lit';
         await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
@@ -27,12 +27,11 @@ describe("An incoming groupchat Message", function () {
         expect(msg_el.innerText).toBe(msg_text);
         await u.waitUntil(() => msg_el.innerHTML.replace(/<!-.*?->/g, '') ===
             'This <span class="styling-directive">*</span><b>message mentions <span class="mention mention--self badge badge-info">romeo</span></b><span class="styling-directive">*</span>');
-        done();
     }));
 
     it("will not have styling applied to mentioned nicknames themselves",
             mock.initConverse(['chatBoxesFetched'], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
         const muc_jid = 'lounge@montague.lit';
         await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
@@ -53,6 +52,5 @@ describe("An incoming groupchat Message", function () {
         expect(msg_el.innerText).toBe(msg_text);
         await u.waitUntil(() => msg_el.innerHTML.replace(/<!-.*?->/g, '') ===
             '<span class="mention">x_y_z_</span> hello');
-        done();
     }));
 });

+ 1 - 2
src/plugins/muc-views/tests/toolbar.js

@@ -6,14 +6,13 @@ describe('The visible_toolbar_buttons configuration setting', function () {
 
     it("can be used to show a participants toggle in a MUC's toolbar",
         mock.initConverse([], { 'visible_toolbar_buttons': { 'toggle_occupants': true } },
-        async (done, _converse) => {
+        async (_converse) => {
 
             const muc_jid = 'lounge@montague.lit';
             await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
             const view = _converse.chatboxviews.get(muc_jid);
             await u.waitUntil(() => view.querySelector('converse-chat-toolbar .toggle_occupants'));
             expect(1).toBe(1);
-            done();
         })
     );
 });

+ 8 - 16
src/plugins/muc-views/tests/unfurls.js

@@ -4,7 +4,7 @@ const { u } = converse.env;
 
 describe("A Groupchat Message", function () {
 
-    it("will render an unfurl based on OGP data", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+    it("will render an unfurl based on OGP data", mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
         const nick = 'romeo';
         const muc_jid = 'lounge@montague.lit';
         await mock.openAndEnterChatRoom(_converse, muc_jid, nick);
@@ -44,10 +44,9 @@ describe("A Groupchat Message", function () {
 
         const unfurl = await u.waitUntil(() => view.querySelector('converse-message-unfurl'));
         expect(unfurl.querySelector('.card-img-top').getAttribute('src')).toBe('https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg');
-        done();
     }));
 
-    it("will render an unfurl with limited OGP data", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+    it("will render an unfurl with limited OGP data", mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
         /* Some sites don't include ogp data such as title, description and
          * url. This test is to check that we fall back gracefully */
         const nick = 'romeo';
@@ -82,10 +81,9 @@ describe("A Groupchat Message", function () {
         expect(unfurl.querySelector('.card-img-top').getAttribute('src')).toBe('https://conversejs.org/dist/images/custom_emojis/converse.png');
         expect(unfurl.querySelector('.card-body')).toBe(null);
         expect(unfurl.querySelector('a')).toBe(null);
-        done();
     }));
 
-    it("will render multiple unfurls based on OGP data", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+    it("will render multiple unfurls based on OGP data", mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
         const nick = 'romeo';
         const muc_jid = 'lounge@montague.lit';
         await mock.openAndEnterChatRoom(_converse, muc_jid, nick);
@@ -137,10 +135,9 @@ describe("A Groupchat Message", function () {
         _converse.connection._dataRecv(mock.createRequest(metadata_stanza));
 
         await u.waitUntil(() => view.querySelectorAll('converse-message-unfurl').length === 2);
-        done();
     }));
 
-    it("will not render an unfurl received from a MUC participant", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+    it("will not render an unfurl received from a MUC participant", mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
         const nick = 'romeo';
         const muc_jid = 'lounge@montague.lit';
         await mock.openAndEnterChatRoom(_converse, muc_jid, nick);
@@ -175,13 +172,12 @@ describe("A Groupchat Message", function () {
         await u.waitUntil(() => view.model.handleMetadataFastening.calls.count());
         expect(view.model.handleMetadataFastening.calls.first().returnValue).toBe(false);
         expect(view.querySelector('converse-message-unfurl')).toBe(null);
-        done();
     }));
 
     it("will not render an unfurl based on OGP data if muc_show_ogp_unfurls is false",
             mock.initConverse(['chatBoxesFetched'],
             {'muc_show_ogp_unfurls': false},
-            async function (done, _converse) {
+            async function (_converse) {
         const nick = 'romeo';
         const muc_jid = 'lounge@montague.lit';
         await mock.openAndEnterChatRoom(_converse, muc_jid, nick);
@@ -216,11 +212,10 @@ describe("A Groupchat Message", function () {
         await u.waitUntil(() => view.model.handleMetadataFastening.calls.count());
         expect(view.model.handleMetadataFastening.calls.first().returnValue).toBe(false);
         expect(view.querySelector('converse-message-unfurl')).toBe(null);
-        done();
     }));
 
     it("will only render a single unfurl when receiving the same OGP data multiple times",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
         const nick = 'romeo';
         const muc_jid = 'lounge@montague.lit';
         await mock.openAndEnterChatRoom(_converse, muc_jid, nick);
@@ -257,13 +252,12 @@ describe("A Groupchat Message", function () {
         await u.waitUntil(() => view.model.handleMetadataFastening.calls.count());
         const unfurls = await u.waitUntil(() => view.querySelectorAll('converse-message-unfurl'));
         expect(unfurls.length).toBe(1);
-        done();
     }));
 
     it("will not render an unfurl image if the domain is not in show_images_inline",
             mock.initConverse(['chatBoxesFetched'],
             {'show_images_inline': []},
-            async function (done, _converse) {
+            async function (_converse) {
 
         const nick = 'romeo';
         const muc_jid = 'lounge@montague.lit';
@@ -296,13 +290,12 @@ describe("A Groupchat Message", function () {
 
         const unfurl = await u.waitUntil(() => view.querySelector('converse-message-unfurl'));
         expect(unfurl.querySelector('.card-img-top')).toBe(null);
-        done();
     }));
 
     it("lets the user hide an unfurl",
             mock.initConverse(['chatBoxesFetched'],
             {'show_images_inline': []},
-            async function (done, _converse) {
+            async function (_converse) {
 
         const nick = 'romeo';
         const muc_jid = 'lounge@montague.lit';
@@ -339,6 +332,5 @@ describe("A Groupchat Message", function () {
         await u.waitUntil(() => view.querySelector('converse-message-unfurl') === null, 750);
         button.click();
         await u.waitUntil(() => view.querySelector('converse-message-unfurl'), 750);
-        done();
     }));
 });

+ 2 - 4
src/plugins/muc-views/tests/xss.js

@@ -7,7 +7,7 @@ describe("XSS", function () {
     describe("A Groupchat", function () {
 
         it("escapes occupant nicknames when rendering them, to avoid JS-injection attacks",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
             /* <presence xmlns="jabber:client" to="jc@chat.example.org/converse.js-17184538"
@@ -34,11 +34,10 @@ describe("XSS", function () {
             const occupants = view.querySelectorAll('.occupant-list li .occupant-nick');
             expect(occupants.length).toBe(2);
             expect(occupants[0].textContent.trim()).toBe("&lt;img src=&quot;x&quot; onerror=&quot;alert(123)&quot;/&gt;");
-            done();
         }));
 
         it("escapes the subject before rendering it, to avoid JS-injection attacks",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             await mock.openAndEnterChatRoom(_converse, 'jdev@conference.jabber.org', 'jc');
             spyOn(window, 'alert');
@@ -50,7 +49,6 @@ describe("XSS", function () {
             }});
             const text = await u.waitUntil(() => view.querySelector('.chat-head__desc')?.textContent.trim());
             expect(text).toBe(subject);
-            done();
         }));
     });
 });

+ 10 - 20
src/plugins/notifications/tests/notification.js

@@ -12,7 +12,7 @@ describe("Notifications", function () {
             describe("an HTML5 Notification", function () {
 
                 it("is shown when a new private message is received",
-                        mock.initConverse([], {}, async (done, _converse) => {
+                        mock.initConverse([], {}, async (_converse) => {
 
                     await mock.waitForRoster(_converse, 'current');
                     const stub = jasmine.createSpyObj('MyNotification', ['onclick', 'close']);
@@ -30,11 +30,10 @@ describe("Notifications", function () {
                     await _converse.handleMessageStanza(msg); // This will emit 'message'
                     await u.waitUntil(() => _converse.chatboxviews.get(sender_jid));
                     expect(window.Notification).toHaveBeenCalled();
-                    done();
                 }));
 
                 it("is shown when you are mentioned in a groupchat",
-                        mock.initConverse([], {}, async (done, _converse) => {
+                        mock.initConverse([], {}, async (_converse) => {
 
                     await mock.waitForRoster(_converse, 'current');
                     await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
@@ -75,10 +74,9 @@ describe("Notifications", function () {
                     _converse.connection._dataRecv(mock.createRequest(makeMsg('romeo: this will show a notification')));
                     await new Promise(resolve => view.model.messages.once('rendered', resolve));
                     expect(window.Notification.calls.count()).toBe(2);
-                    done();
                 }));
 
-                it("is shown for headline messages", mock.initConverse([], {}, async (done, _converse) => {
+                it("is shown for headline messages", mock.initConverse([], {}, async (_converse) => {
                     const stub = jasmine.createSpyObj('MyNotification', ['onclick', 'close']);
                     spyOn(window, 'Notification').and.returnValue(stub);
 
@@ -100,10 +98,9 @@ describe("Notifications", function () {
                     await new Promise(resolve => view.model.messages.once('rendered', resolve));
                     expect(_converse.chatboxviews.keys().includes('notify.example.com')).toBeTruthy();
                     expect(window.Notification).toHaveBeenCalled();
-                    done();
                 }));
 
-                it("is not shown for full JID headline messages if allow_non_roster_messaging is false", mock.initConverse((done, _converse) => {
+                it("is not shown for full JID headline messages if allow_non_roster_messaging is false", mock.initConverse((_converse) => {
                     _converse.allow_non_roster_messaging = false;
                     const stub = jasmine.createSpyObj('MyNotification', ['onclick', 'close']);
                     spyOn(window, 'Notification').and.returnValue(stub);
@@ -120,12 +117,11 @@ describe("Notifications", function () {
                     _converse.connection._dataRecv(mock.createRequest(stanza));
                     expect(_converse.chatboxviews.keys().includes('someone@notify.example.com')).toBeFalsy();
                     expect(window.Notification).not.toHaveBeenCalled();
-                    done();
                 }));
 
                 it("is shown when a user changes their chat state (if show_chat_state_notifications is true)",
                         mock.initConverse([], {show_chat_state_notifications: true},
-                        async (done, _converse) => {
+                        async (_converse) => {
 
                     await mock.waitForRoster(_converse, 'current', 3);
                     const stub = jasmine.createSpyObj('MyNotification', ['onclick', 'close']);
@@ -133,18 +129,16 @@ describe("Notifications", function () {
                     const jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@montague.lit';
                     _converse.roster.get(jid).presence.set('show', 'dnd');
                     expect(window.Notification).toHaveBeenCalled();
-                    done()
                 }));
             });
         });
 
         describe("When a new contact request is received", function () {
-            it("an HTML5 Notification is received", mock.initConverse((done, _converse) => {
+            it("an HTML5 Notification is received", mock.initConverse((_converse) => {
                 const stub = jasmine.createSpyObj('MyNotification', ['onclick', 'close']);
                 spyOn(window, 'Notification').and.returnValue(stub);
                 _converse.api.trigger('contactRequest', {'getDisplayName': () => 'Peter Parker'});
                 expect(window.Notification).toHaveBeenCalled();
-                done();
             }));
         });
     });
@@ -152,7 +146,7 @@ describe("Notifications", function () {
     describe("When play_sounds is set to true", function () {
         describe("A notification sound", function () {
 
-            it("is played when the current user is mentioned in a groupchat", mock.initConverse([], {}, async (done, _converse) => {
+            it("is played when the current user is mentioned in a groupchat", mock.initConverse([], {}, async (_converse) => {
 
                 await mock.waitForRoster(_converse, 'current');
                 await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
@@ -198,7 +192,6 @@ describe("Notifications", function () {
                 }).c('body').t(text);
                 await view.model.handleMessageStanza(message.nodeTree);
                 expect(window.Audio, 1);
-                done();
             }));
         });
     });
@@ -207,7 +200,7 @@ describe("Notifications", function () {
     describe("A Favicon Message Counter", function () {
 
         it("is incremented when the message is received and the window is not focused",
-                mock.initConverse([], {'show_tab_notifications': false}, async function (done, _converse) {
+                mock.initConverse([], {'show_tab_notifications': false}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current');
             await mock.openControlBox(_converse);
@@ -257,11 +250,10 @@ describe("Notifications", function () {
 
             expect(view.model.get('num_unread')).toBe(0);
             _converse.windowSate = previous_state;
-            done();
         }));
 
         it("is not incremented when the message is received and the window is focused",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current');
             await mock.openControlBox(_converse);
@@ -285,12 +277,11 @@ describe("Notifications", function () {
                 const view = _converse.chatboxviews.get(sender_jid);
                 expect(view.model.get('num_unread')).toBe(0);
                 expect(favico.badge.calls.count()).toBe(0);
-                done();
             }, 500);
         }));
 
         it("is incremented from zero when chatbox was closed after viewing previously received messages and the window is not focused now",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current');
             const favico = jasmine.createSpyObj('favico', ['badge']);
@@ -335,7 +326,6 @@ describe("Notifications", function () {
             await u.waitUntil(() => u.isVisible(view));
             await u.waitUntil(() => favico.badge.calls.count() === 3);
             expect(favico.badge.calls.mostRecent().args.pop()).toBe(1);
-            done();
         }));
     });
 

+ 12 - 24
src/plugins/omemo/tests/omemo.js

@@ -73,18 +73,17 @@ async function initializedOMEMO (_converse) {
 describe("The OMEMO module", function() {
 
     it("adds methods for encrypting and decrypting messages via AES GCM",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         const message = 'This message will be encrypted'
         await mock.waitForRoster(_converse, 'current', 1);
         const payload = await omemo.encryptMessage(message);
         const result = await omemo.decryptMessage(payload);
         expect(result).toBe(message);
-        done();
     }));
 
     it("enables encrypted messages to be sent and received",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         let sent_stanza;
         await mock.waitForRoster(_converse, 'current', 1);
@@ -217,11 +216,10 @@ describe("The OMEMO module", function() {
         expect(view.model.messages.length).toBe(3);
         expect(view.querySelectorAll('.chat-msg__body')[2].textContent.trim())
             .toBe('Another received encrypted message without fallback');
-        done();
     }));
 
     it("enables encrypted groupchat messages to be sent and received",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         // MEMO encryption works only in members only conferences
         // that are non-anonymous.
@@ -363,11 +361,10 @@ describe("The OMEMO module", function() {
                 `</encrypted>`+
                 `<store xmlns="urn:xmpp:hints"/>`+
             `</message>`);
-        done();
     }));
 
     it("will create a new device based on a received carbon message",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, [], [Strophe.NS.SID]);
         await mock.waitForRoster(_converse, 'current', 1);
@@ -472,11 +469,10 @@ describe("The OMEMO module", function() {
                     `<items node="eu.siacs.conversations.axolotl.bundles:988349631"/>`+
                 `</pubsub>`+
             `</iq>`);
-        done();
     }));
 
     it("gracefully handles auth errors when trying to send encrypted groupchat messages",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         // MEMO encryption works only in members only conferences
         // that are non-anonymous.
@@ -600,11 +596,10 @@ describe("The OMEMO module", function() {
 
         expect(view.model.get('omemo_supported')).toBe(false);
         expect(view.querySelector('.chat-textarea').value).toBe('This message will be encrypted');
-        done();
     }));
 
     it("can receive a PreKeySignalMessage",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         _converse.NUM_PREKEYS = 5; // Restrict to 5, otherwise the resulting stanza is too large to easily test
         await mock.waitForRoster(_converse, 'current', 1);
@@ -695,11 +690,10 @@ describe("The OMEMO module", function() {
         const own_device = _converse.devicelists.get(_converse.bare_jid).devices.get(_converse.omemo_store.get('device_id'));
         expect(own_device.get('bundle').prekeys.length).toBe(5);
         expect(_converse.omemo_store.generateMissingPreKeys).toHaveBeenCalled();
-        done();
     }));
 
     it("updates device lists based on PEP messages",
-            mock.initConverse([], {'allow_non_roster_messaging': true}, async function (done, _converse) {
+            mock.initConverse([], {'allow_non_roster_messaging': true}, async function (_converse) {
 
         await mock.waitUntilDiscoConfirmed(
             _converse, _converse.bare_jid,
@@ -866,12 +860,11 @@ describe("The OMEMO module", function() {
         expect(devices.get('444').get('active')).toBe(true);
         expect(devices.get('555').get('active')).toBe(false);
         expect(devices.get('777').get('active')).toBe(false);
-        done();
     }));
 
 
     it("updates device bundles based on PEP messages",
-            mock.initConverse([], {}, async function (done, _converse) {
+            mock.initConverse([], {}, async function (_converse) {
 
         await mock.waitUntilDiscoConfirmed(
             _converse, _converse.bare_jid,
@@ -1015,11 +1008,10 @@ describe("The OMEMO module", function() {
         expect(device.get('bundle').prekeys[0].id).toBe(3001);
         expect(device.get('bundle').prekeys[1].id).toBe(3002);
         expect(device.get('bundle').prekeys[2].id).toBe(3003);
-        done();
     }));
 
     it("publishes a bundle with which an encrypted session can be created",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitUntilDiscoConfirmed(
             _converse, _converse.bare_jid,
@@ -1090,12 +1082,11 @@ describe("The OMEMO module", function() {
             'type': 'result'});
         _converse.connection._dataRecv(mock.createRequest(stanza));
         await _converse.api.waitUntil('OMEMOInitialized');
-        done();
     }));
 
 
     it("adds a toolbar button for starting an encrypted chat session",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitUntilDiscoConfirmed(
             _converse, _converse.bare_jid,
@@ -1250,11 +1241,10 @@ describe("The OMEMO module", function() {
         icon = toolbar.querySelector('.toggle-omemo converse-icon');
         expect(u.hasClass('fa-lock', icon)).toBe(false);
         expect(u.hasClass('fa-unlock', icon)).toBe(true);
-        done();
     }));
 
     it("adds a toolbar button for starting an encrypted groupchat session",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitForRoster(_converse, 'current', 0);
         await mock.waitUntilDiscoConfirmed(
@@ -1421,12 +1411,11 @@ describe("The OMEMO module", function() {
         expect(u.hasClass('fa-unlock', icon)).toBe(true);
         expect(u.hasClass('fa-lock', icon)).toBe(false);
         expect(toolbar.querySelector('.toggle-omemo').title).toBe('This groupchat needs to be members-only and non-anonymous in order to support OMEMO encrypted messages');
-        done();
     }));
 
 
     it("shows OMEMO device fingerprints in the user details modal",
-            mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+            mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         await mock.waitUntilDiscoConfirmed(
             _converse, _converse.bare_jid,
@@ -1516,6 +1505,5 @@ describe("The OMEMO module", function() {
 
         trusted_radio.click();
         expect(devicelist.devices.get('555').get('trusted')).toBe(1);
-        done();
     }));
 });

+ 8 - 16
src/plugins/register/tests/register.js

@@ -17,12 +17,11 @@ describe("The Registration Panel", function () {
             ['chatBoxesInitialized'],
             { auto_login: false,
               allow_registration: false },
-            async function (done, _converse) {
+            async function (_converse) {
 
         await u.waitUntil(() => _converse.chatboxviews.get('controlbox'));
         const cbview = _converse.api.controlbox.get();
         expect(cbview.querySelectorAll('a.register-account').length).toBe(0);
-        done();
     }));
 
     it("can be opened by clicking on the registration tab",
@@ -30,7 +29,7 @@ describe("The Registration Panel", function () {
             ['chatBoxesInitialized'],
             { auto_login: false,
               allow_registration: true },
-            async function (done, _converse) {
+            async function (_converse) {
 
         const toggle = await u.waitUntil(() => document.querySelector(".toggle-controlbox"));
         if (!u.isVisible(document.querySelector("#controlbox"))) {
@@ -47,7 +46,6 @@ describe("The Registration Panel", function () {
         register_link.click();
 
         expect(cbview.querySelector('converse-register-panel')).toBeDefined();
-        done();
     }));
 
     it("allows the user to choose an XMPP provider's domain",
@@ -56,7 +54,7 @@ describe("The Registration Panel", function () {
             { auto_login: false,
               discover_connection_methods: false,
               allow_registration: true },
-            async function (done, _converse) {
+            async function (_converse) {
 
 
         const toggle = await u.waitUntil(() => document.querySelector(".toggle-controlbox"));
@@ -88,7 +86,6 @@ describe("The Registration Panel", function () {
         expect(registerview.onProviderChosen).toHaveBeenCalled();
         expect(registerview.fetchRegistrationForm).toHaveBeenCalled();
         delete _converse.connection;
-        done();
     }));
 
     it("will render a registration form as received from the XMPP provider",
@@ -97,7 +94,7 @@ describe("The Registration Panel", function () {
             { auto_login: false,
               discover_connection_methods: false,
               allow_registration: true },
-            async function (done, _converse) {
+            async function (_converse) {
 
         const toggle = await u.waitUntil(() => document.querySelector(".toggle-controlbox"));
         toggle.click();
@@ -146,7 +143,6 @@ describe("The Registration Panel", function () {
         expect(registerview.querySelectorAll('input').length).toBe(5);
         expect(registerview.querySelectorAll('input[type=submit]').length).toBe(1);
         expect(registerview.querySelectorAll('input[type=button]').length).toBe(1);
-        done();
     }));
 
     it("will set form_type to legacy and submit it as legacy",
@@ -155,7 +151,7 @@ describe("The Registration Panel", function () {
             { auto_login: false,
               discover_connection_methods: false,
               allow_registration: true },
-            async function (done, _converse) {
+            async function (_converse) {
 
         const toggle = document.querySelector(".toggle-controlbox");
         if (!u.isVisible(document.querySelector("#controlbox"))) {
@@ -209,7 +205,6 @@ describe("The Registration Panel", function () {
         expect(stanza.querySelector('query').firstElementChild.tagName).toBe('username');
 
         delete _converse.connection;
-        done();
     }));
 
     it("will set form_type to xform and submit it as xform",
@@ -218,7 +213,7 @@ describe("The Registration Panel", function () {
             { auto_login: false,
               discover_connection_methods: false,
               allow_registration: true },
-            async function (done, _converse) {
+            async function (_converse) {
 
         const toggle = document.querySelector(".toggle-controlbox");
         if (!u.isVisible(document.querySelector("#controlbox"))) {
@@ -289,7 +284,6 @@ describe("The Registration Panel", function () {
         );
 
         delete _converse.connection;
-        done();
     }));
 
     it("renders the account registration form",
@@ -298,7 +292,7 @@ describe("The Registration Panel", function () {
             { auto_login: false,
               discover_connection_methods: false,
               allow_registration: true },
-            async function (done, _converse) {
+            async function (_converse) {
 
         const toggle = document.querySelector(".toggle-controlbox");
         if (!u.isVisible(document.querySelector("#controlbox"))) {
@@ -358,7 +352,6 @@ describe("The Registration Panel", function () {
         // passed or failed
         u.addClass('hidden', _converse.chatboxviews.get('controlbox').el);
         delete _converse.connection;
-        done();
     }));
 
     it("renders errors",
@@ -368,7 +361,7 @@ describe("The Registration Panel", function () {
               view_mode: 'fullscreen',
               discover_connection_methods: false,
               allow_registration: true },
-            async function (done, _converse) {
+            async function (_converse) {
 
         const toggle = document.querySelector(".toggle-controlbox");
         if (!u.isVisible(document.querySelector("#controlbox"))) {
@@ -439,6 +432,5 @@ describe("The Registration Panel", function () {
         _converse.connection._dataRecv(mock.createRequest(response_IQ));
         expect(view.querySelector('.error')?.textContent.trim()).toBe('Too many CAPTCHA requests');
         delete _converse.connection;
-        done();
     }));
 });

+ 1 - 2
src/plugins/rootview/tests/root.js

@@ -5,12 +5,11 @@ const u = converse.env.utils;
 describe("Converse", function() {
 
     it("Can be inserted into a converse-root custom element after having been initialized",
-            mock.initConverse([], {'root': new DocumentFragment()}, async (done, _converse) => {
+            mock.initConverse([], {'root': new DocumentFragment()}, async (_converse) => {
 
         expect(document.body.querySelector('#conversejs')).toBe(null);
         expect(_converse.root.firstElementChild.nodeName.toLowerCase()).toBe('converse-root');
         document.body.appendChild(document.createElement('converse-root'));
         await u.waitUntil(() => document.body.querySelector('#conversejs') !== null);
-        done();
     }));
 });

+ 1 - 2
src/plugins/rosterview/tests/presence.js

@@ -8,7 +8,7 @@ describe("A sent presence stanza", function () {
     afterEach(() => (jasmine.DEFAULT_TIMEOUT_INTERVAL = original_timeout));
 
     it("includes the saved status message",
-        mock.initConverse([], {}, async (done, _converse) => {
+        mock.initConverse([], {}, async (_converse) => {
 
         const { u, Strophe } = converse.env;
         mock.openControlBox(_converse);
@@ -49,6 +49,5 @@ describe("A sent presence stanza", function () {
                     `<priority>0</priority>`+
                     `<c hash="sha-1" node="https://conversejs.org" ver="PxXfr6uz8ClMWIga0OB/MhKNH/M=" xmlns="http://jabber.org/protocol/caps"/>`+
                 `</presence>`)
-        done();
     }));
 });

+ 4 - 8
src/plugins/rosterview/tests/protocol.js

@@ -39,7 +39,7 @@ describe("The Protocol", function () {
          * stanza of type "result".
          */
         it("Subscribe to contact, contact accepts and subscribes back",
-                mock.initConverse([], { roster_groups: false }, async function (done, _converse) {
+                mock.initConverse([], { roster_groups: false }, async function (_converse) {
 
             const { u, $iq, $pres, sizzle, Strophe } = converse.env;
             let contact, stanza;
@@ -354,12 +354,11 @@ describe("The Protocol", function () {
             // The class on the contact will now have switched.
             await u.waitUntil(() => !u.hasClass('to', contacts[0]));
             expect(u.hasClass('both', contacts[0])).toBe(true);
-            done();
 
         }));
 
         it("Alternate Flow: Contact Declines Subscription Request",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             const { $iq, $pres } = converse.env;
             /* The process by which a user subscribes to a contact, including
@@ -438,11 +437,10 @@ describe("The Protocol", function () {
                     `</query>`+
                 `</iq>`
             );
-            done();
         }));
 
         it("Unsubscribe to a contact when subscription is mutual",
-                mock.initConverse([], { roster_groups: false }, async function (done, _converse) {
+                mock.initConverse([], { roster_groups: false }, async function (_converse) {
 
             const { u, $iq, sizzle, Strophe } = converse.env;
             const jid = 'abram@montague.lit';
@@ -494,11 +492,10 @@ describe("The Protocol", function () {
             _converse.connection._dataRecv(mock.createRequest(stanza));
             // Our contact has now been removed
             await u.waitUntil(() => typeof _converse.roster.get(jid) === "undefined");
-            done();
         }));
 
         it("Receiving a subscription request", mock.initConverse(
-                [], {}, async function (done, _converse) {
+                [], {}, async function (_converse) {
 
             const { u, $pres, sizzle, Strophe } = converse.env;
             spyOn(_converse.api, "trigger").and.callThrough();
@@ -530,7 +527,6 @@ describe("The Protocol", function () {
             expect(u.isVisible(header)).toBe(true);
             const contacts = header.nextElementSibling.querySelectorAll('li');
             expect(contacts.length).toBe(1);
-            done();
         }));
     });
 });

+ 40 - 80
src/plugins/rosterview/tests/roster.js

@@ -26,7 +26,7 @@ const checkHeaderToggling = async function (group) {
 
 describe("The Contacts Roster", function () {
 
-    it("verifies the origin of roster pushes", mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
+    it("verifies the origin of roster pushes", mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         // See: https://gultsch.de/gajim_roster_push_and_message_interception.html
         const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -59,10 +59,9 @@ describe("The Contacts Roster", function () {
         );
         expect(_converse.roster.models.length).toBe(1);
         expect(_converse.roster.at(0).get('jid')).toBe(contact_jid);
-        done();
     }));
 
-    it("is populated once we have registered a presence handler", mock.initConverse([], {}, async function (done, _converse) {
+    it("is populated once we have registered a presence handler", mock.initConverse([], {}, async function (_converse) {
         const IQs = _converse.connection.IQ_stanzas;
         const stanza = await u.waitUntil(
             () => _.filter(IQs, iq => iq.querySelector('iq query[xmlns="jabber:iq:roster"]')).pop());
@@ -81,10 +80,9 @@ describe("The Contacts Roster", function () {
           .c('item', {'jid': 'romeo@example.com'})
         _converse.connection._dataRecv(mock.createRequest(result));
         await u.waitUntil(() => _converse.promises['rosterContactsFetched'].isResolved === true);
-        done();
     }));
 
-    it("supports roster versioning", mock.initConverse([], {}, async function (done, _converse) {
+    it("supports roster versioning", mock.initConverse([], {}, async function (_converse) {
         const IQ_stanzas = _converse.connection.IQ_stanzas;
         let stanza = await u.waitUntil(
             () => _.filter(IQ_stanzas, iq => iq.querySelector('iq query[xmlns="jabber:iq:roster"]')).pop()
@@ -132,10 +130,9 @@ describe("The Contacts Roster", function () {
         expect(_converse.roster.data.get('version')).toBe('ver34');
         expect(_converse.roster.models.length).toBe(1);
         expect(_converse.roster.at(0).get('jid')).toBe('nurse@example.com');
-        done();
     }));
 
-    it("will also show contacts added afterwards", mock.initConverse([], {}, async function (done, _converse) {
+    it("will also show contacts added afterwards", mock.initConverse([], {}, async function (_converse) {
         await mock.openControlBox(_converse);
         await mock.waitForRoster(_converse, 'current');
 
@@ -175,13 +172,12 @@ describe("The Contacts Roster", function () {
         expect(visible_groups[3].textContent.trim()).toBe('newgroup');
         expect(visible_groups[4].textContent.trim()).toBe('ænemies');
         expect(roster.querySelectorAll('.roster-group').length).toBe(5);
-        done();
     }));
 
     describe("The live filter", function () {
 
         it("will only appear when roster contacts flow over the visible area",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             expect(document.querySelector('converse-roster')).toBe(null);
             await mock.waitForRoster(_converse, 'current');
@@ -197,13 +193,12 @@ describe("The Contacts Roster", function () {
             const filter = rosterview.querySelector('.roster-filter');
             const el = rosterview.querySelector('.roster-contacts');
             await u.waitUntil(() => hasScrollBar(el) ? u.isVisible(filter) : !u.isVisible(filter), 900);
-            done();
         }));
 
         it("can be used to filter the contacts shown",
             mock.initConverse(
                 [], {'roster_groups': true},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await mock.openControlBox(_converse);
             await mock.waitForRoster(_converse, 'current');
@@ -250,10 +245,9 @@ describe("The Contacts Roster", function () {
             u.triggerEvent(filter, "keydown", "KeyboardEvent");
             await u.waitUntil(() => (sizzle('li', roster).filter(u.isVisible).length === 17), 600);
             expect(sizzle('ul.roster-group-contacts', roster).filter(u.isVisible).length).toBe(5);
-            done();
         }));
 
-        it("can be used to filter the groups shown", mock.initConverse([], {'roster_groups': true}, async function (done, _converse) {
+        it("can be used to filter the groups shown", mock.initConverse([], {'roster_groups': true}, async function (_converse) {
             await mock.openControlBox(_converse);
             await mock.waitForRoster(_converse, 'current');
             const rosterview = document.querySelector('converse-roster');
@@ -287,11 +281,10 @@ describe("The Contacts Roster", function () {
             u.triggerEvent(filter, "keydown", "KeyboardEvent");
             await u.waitUntil(() => (roster.querySelectorAll('div.roster-group.collapsed').length === 0), 700);
             expect(sizzle('div.roster-group', roster).length).toBe(0);
-            done();
         }));
 
         it("has a button with which its contents can be cleared",
-                mock.initConverse([], {'roster_groups': true}, async function (done, _converse) {
+                mock.initConverse([], {'roster_groups': true}, async function (_converse) {
 
             await mock.openControlBox(_converse);
             await mock.waitForRoster(_converse, 'current');
@@ -307,7 +300,6 @@ describe("The Contacts Roster", function () {
             await u.waitUntil(() => !isHidden(rosterview.querySelector('.roster-filter-form .clear-input')), 900);
             rosterview.querySelector('.clear-input').click();
             expect(document.querySelector('.roster-filter').value).toBe("");
-            done();
         }));
 
         // Disabling for now, because since recently this test consistently
@@ -315,7 +307,7 @@ describe("The Contacts Roster", function () {
         xit("can be used to filter contacts by their chat state",
             mock.initConverse(
                 [], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             mock.waitForRoster(_converse, 'all');
             let jid = mock.cur_names[3].replace(/ /g,'.').toLowerCase() + '@montague.lit';
@@ -342,7 +334,6 @@ describe("The Contacts Roster", function () {
             u.triggerEvent(filter, 'change');
             await u.waitUntil(() => sizzle('li', roster).filter(u.isVisible).pop().textContent.trim() === 'Friar Laurence', 900);
             expect(sizzle('ul.roster-group-contacts', roster).filter(u.isVisible).length).toBe(1);
-            done();
         }));
     });
 
@@ -351,7 +342,7 @@ describe("The Contacts Roster", function () {
         it("is created to show contacts with unread messages",
             mock.initConverse(
                 [], {'roster_groups': true},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await mock.openControlBox(_converse);
             await mock.waitForRoster(_converse, 'all');
@@ -406,14 +397,13 @@ describe("The Contacts Roster", function () {
                 "Ungrouped",
                 "Pending contacts"
             ]);
-            done();
         }));
 
 
         it("can be used to organize existing contacts",
             mock.initConverse(
                 [], {'roster_groups': true},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await mock.openControlBox(_converse);
             await mock.waitForRoster(_converse, 'all');
@@ -438,11 +428,10 @@ describe("The Contacts Roster", function () {
                 const names = contacts.map(o => o.textContent.trim());
                 expect(names).toEqual(_.clone(names).sort());
             });
-            done();
         }));
 
         it("gets created when a contact's \"groups\" attribute changes",
-            mock.initConverse([], {'roster_groups': true}, async function (done, _converse) {
+            mock.initConverse([], {'roster_groups': true}, async function (_converse) {
 
             await mock.openControlBox(_converse);
             await mock.waitForRoster(_converse, 'current', 0);
@@ -480,11 +469,10 @@ describe("The Contacts Roster", function () {
                 }
             }, 1000);
             expect(group_titles).toEqual(['secondgroup']);
-            done();
         }));
 
         it("can share contacts with other roster groups",
-                mock.initConverse( [], {'roster_groups': true}, async function (done, _converse) {
+                mock.initConverse( [], {'roster_groups': true}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 0);
             const groups = ['Colleagues', 'friends'];
@@ -507,11 +495,10 @@ describe("The Contacts Roster", function () {
                 expect(names).toEqual(_.clone(names).sort());
                 expect(names.length).toEqual(mock.cur_names.length);
             });
-            done();
         }));
 
         it("remembers whether it is closed or opened",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 0);
             await mock.openControlBox(_converse);
@@ -544,14 +531,13 @@ describe("The Contacts Roster", function () {
             expect(state.get('collapsed_groups')).toEqual(['Colleagues']);
             toggle.click();
             expect(state.get('collapsed_groups')).toEqual([]);
-            done();
         }));
     });
 
     describe("Pending Contacts", function () {
 
         it("can be collapsed under their own header",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             await mock.openControlBox(_converse);
             await mock.waitForRoster(_converse, 'all');
@@ -559,13 +545,12 @@ describe("The Contacts Roster", function () {
             const rosterview = document.querySelector('converse-roster');
             await u.waitUntil(() => sizzle('.roster-group', rosterview).filter(u.isVisible).map(e => e.querySelector('li')).length, 1000);
             await checkHeaderToggling.apply(_converse, [rosterview.querySelector('[data-group="Pending contacts"]')]);
-            done();
         }));
 
         it("can be added to the roster",
             mock.initConverse(
                 [], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await mock.waitForRoster(_converse, 'all', 0);
             await mock.openControlBox(_converse);
@@ -578,13 +563,12 @@ describe("The Contacts Roster", function () {
             });
             expect(u.isVisible(rosterview)).toBe(true);
             await u.waitUntil(() => sizzle('li', rosterview).filter(u.isVisible).length === 1);
-            done();
         }));
 
         it("are shown in the roster when hide_offline_users",
             mock.initConverse(
                 [], {'hide_offline_users': true},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await mock.openControlBox(_converse);
             await mock.waitForRoster(_converse, 'pending');
@@ -594,11 +578,10 @@ describe("The Contacts Roster", function () {
             expect(u.isVisible(rosterview)).toBe(true);
             expect(sizzle('li', rosterview).filter(u.isVisible).length).toBe(3);
             expect(sizzle('ul.roster-group-contacts', rosterview).filter(u.isVisible).length).toBe(1);
-            done();
         }));
 
         it("can be removed by the user",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             await mock.openControlBox(_converse);
             await mock.waitForRoster(_converse, 'all');
@@ -626,13 +609,12 @@ describe("The Contacts Roster", function () {
                         `<item jid="lord.capulet@montague.lit" subscription="remove"/>`+
                     `</query>`+
                 `</iq>`);
-            done();
         }));
 
         it("do not have a header if there aren't any",
             mock.initConverse(
                 ['VCardsInitialized'], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await mock.openControlBox(_converse);
             await mock.waitForRoster(_converse, 'current', 0);
@@ -665,11 +647,10 @@ describe("The Contacts Roster", function () {
             const stanza = u.toStanza(`<iq id="${iq.getAttribute('id')}" to="romeo@montague.lit/orchard" type="result"/>`);
             _converse.connection._dataRecv(mock.createRequest(stanza));
             await u.waitUntil(() => rosterview.querySelector(`ul[data-group="Pending contacts"]`) === null);
-            done();
         }));
 
         it("is shown when a new private message is received",
-                mock.initConverse([], {}, async function (done, _converse) {
+                mock.initConverse([], {}, async function (_converse) {
 
             await mock.openControlBox(_converse);
             await mock.waitForRoster(_converse, 'all');
@@ -683,13 +664,12 @@ describe("The Contacts Roster", function () {
             }
             await u.waitUntil(() => rosterview.querySelector(`ul[data-group="Pending contacts"]`) === null);
             expect(rosterview.querySelectorAll('ul').length).toBe(5);
-            done();
         }));
 
         it("can be added to the roster and they will be sorted alphabetically",
             mock.initConverse(
                 [], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await mock.openControlBox(_converse);
             await mock.waitForRoster(_converse, 'current');
@@ -710,7 +690,6 @@ describe("The Contacts Roster", function () {
             const spans = el.querySelectorAll('.pending-xmpp-contact span');
             const t = Array.from(spans).reduce((result, value) => result + value.textContent?.trim(), '');
             expect(t).toEqual(mock.pend_names.slice(0,i+1).sort().join(''));
-            done();
         }));
     });
 
@@ -724,19 +703,18 @@ describe("The Contacts Roster", function () {
         it("can be collapsed under their own header",
             mock.initConverse(
                 [], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await _addContacts(_converse);
             const rosterview = document.querySelector('converse-roster');
             await u.waitUntil(() => sizzle('li', rosterview).filter(u.isVisible).length, 500);
             await checkHeaderToggling.apply(_converse, [rosterview.querySelector('.roster-group')]);
-            done();
         }));
 
         it("will be hidden when appearing under a collapsed group",
             mock.initConverse(
                 [], {'roster_groups': false},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await _addContacts(_converse);
             const rosterview = document.querySelector('converse-roster');
@@ -753,13 +731,12 @@ describe("The Contacts Roster", function () {
             });
             const el = rosterview.querySelector(`ul[data-group="My contacts"]`);
             expect(u.hasClass('collapsed', el)).toBe(true);
-            done();
         }));
 
         it("can be added to the roster and they will be sorted alphabetically",
             mock.initConverse(
                 [], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 0);
             await mock.openControlBox(_converse);
@@ -778,13 +755,12 @@ describe("The Contacts Roster", function () {
             const els = sizzle('.current-xmpp-contact.offline a.open-chat', rosterview)
             const t = els.reduce((result, value) => (result + value.textContent.trim()), '');
             expect(t).toEqual(mock.cur_names.slice(0,mock.cur_names.length).sort().join(''));
-            done();
         }));
 
         it("can be removed by the user",
             mock.initConverse(
                 [], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await _addContacts(_converse);
             const rosterview = document.querySelector('converse-roster');
@@ -808,13 +784,12 @@ describe("The Contacts Roster", function () {
                 `</iq>`);
             expect(contact.removeFromRoster).toHaveBeenCalled();
             await u.waitUntil(() => sizzle(".open-chat:contains('"+name+"')", rosterview).length === 0);
-            done();
         }));
 
         it("do not have a header if there aren't any",
             mock.initConverse(
                 [], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await mock.openControlBox(_converse);
             await mock.waitForRoster(_converse, 'current', 0);
@@ -838,13 +813,12 @@ describe("The Contacts Roster", function () {
             expect(_converse.connection.sendIQ).toHaveBeenCalled();
             expect(contact.removeFromRoster).toHaveBeenCalled();
             await u.waitUntil(() => rosterview.querySelectorAll('.roster-group').length === 0);
-            done();
         }));
 
         it("can change their status to online and be sorted alphabetically",
             mock.initConverse(
                 [], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await _addContacts(_converse);
             const rosterview = document.querySelector('converse-roster');
@@ -865,13 +839,12 @@ describe("The Contacts Roster", function () {
                     expect(t).toEqual(mock.groups_map[groupname].slice(0, els.length).sort().join(''));
                 }
             }
-            done();
         }));
 
         it("can change their status to busy and be sorted alphabetically",
             mock.initConverse(
                 [], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await _addContacts(_converse);
             const rosterview = document.querySelector('converse-roster');
@@ -892,13 +865,12 @@ describe("The Contacts Roster", function () {
                     expect(t).toEqual(mock.groups_map[groupname].slice(0, els.length).sort().join(''));
                 }
             }
-            done();
         }));
 
         it("can change their status to away and be sorted alphabetically",
             mock.initConverse(
                 [], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await _addContacts(_converse);
             const rosterview = document.querySelector('converse-roster');
@@ -919,13 +891,12 @@ describe("The Contacts Roster", function () {
                     expect(t).toEqual(mock.groups_map[groupname].slice(0, els.length).sort().join(''));
                 }
             }
-            done();
         }));
 
         it("can change their status to xa and be sorted alphabetically",
             mock.initConverse(
                 [], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await _addContacts(_converse);
             const rosterview = document.querySelector('converse-roster');
@@ -946,13 +917,12 @@ describe("The Contacts Roster", function () {
                     expect(t).toEqual(mock.groups_map[groupname].slice(0, els.length).sort().join(''));
                 }
             }
-            done();
         }));
 
         it("can change their status to unavailable and be sorted alphabetically",
             mock.initConverse(
                 [], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await _addContacts(_converse);
             const rosterview = document.querySelector('converse-roster');
@@ -973,13 +943,12 @@ describe("The Contacts Roster", function () {
                     expect(t).toEqual(mock.groups_map[groupname].slice(0, els.length).sort().join(''));
                 }
             }
-            done();
         }));
 
         it("are ordered according to status: online, busy, away, xa, unavailable, offline",
             mock.initConverse(
                 [], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await _addContacts(_converse);
             const rosterview = document.querySelector('converse-roster');
@@ -1060,7 +1029,6 @@ describe("The Contacts Roster", function () {
                     expect(subscription_classes.join(" ")).toBe("both both");
                 }
             }
-            done();
         }));
     });
 
@@ -1069,7 +1037,7 @@ describe("The Contacts Roster", function () {
         it("can be added to the roster and they will be sorted alphabetically",
             mock.initConverse(
                 [], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await mock.waitForRoster(_converse, "current", 0);
             await mock.openControlBox(_converse);
@@ -1096,10 +1064,9 @@ describe("The Contacts Roster", function () {
             names = [];
             Array.from(children).forEach(addName);
             expect(names.join('')).toEqual(mock.req_names.slice(0,mock.req_names.length+1).sort().join(''));
-            done();
         }));
 
-        it("do not have a header if there aren't any", mock.initConverse([], {}, async function (done, _converse) {
+        it("do not have a header if there aren't any", mock.initConverse([], {}, async function (_converse) {
             await mock.openControlBox(_converse);
             await mock.waitForRoster(_converse, "current", 0);
             const name = mock.req_names[0];
@@ -1118,10 +1085,9 @@ describe("The Contacts Roster", function () {
             sizzle('.roster-group', rosterview).filter(u.isVisible).map(e => e.querySelector('li .decline-xmpp-request'))[0].click();
             expect(window.confirm).toHaveBeenCalled();
             await u.waitUntil(() => rosterview.querySelector(`ul[data-group="Contact requests"]`) === null);
-            done();
         }));
 
-        it("can be collapsed under their own header", mock.initConverse([], {}, async function (done, _converse) {
+        it("can be collapsed under their own header", mock.initConverse([], {}, async function (_converse) {
             await mock.waitForRoster(_converse, 'current', 0);
             mock.createContacts(_converse, 'requesting');
             await mock.openControlBox(_converse);
@@ -1129,13 +1095,12 @@ describe("The Contacts Roster", function () {
             await u.waitUntil(() => sizzle('.roster-group', rosterview).filter(u.isVisible).length, 700);
             const el = await u.waitUntil(() => rosterview.querySelector(`ul[data-group="Contact requests"]`));
             await checkHeaderToggling.apply(_converse, [el.parentElement]);
-            done();
         }));
 
         it("can have their requests accepted by the user",
             mock.initConverse(
                 [], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await mock.openControlBox(_converse);
             await mock.waitForRoster(_converse, 'current', 0);
@@ -1155,13 +1120,12 @@ describe("The Contacts Roster", function () {
             expect(_converse.roster.sendContactAddIQ).toHaveBeenCalled();
             await u.waitUntil(() => contact.authorize.calls.count());
             expect(contact.authorize).toHaveBeenCalled();
-            done();
         }));
 
         it("can have their requests denied by the user",
             mock.initConverse(
                 [], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 0);
             await mock.createContacts(_converse, 'requesting');
@@ -1179,11 +1143,10 @@ describe("The Contacts Roster", function () {
             expect(contact.unauthorize).toHaveBeenCalled();
             // There should now be one less contact
             expect(_converse.roster.length).toEqual(mock.req_names.length-1);
-            done();
         }));
 
         it("are persisted even if other contacts' change their presence ", mock.initConverse(
-            [], {}, async function (done, _converse) {
+            [], {}, async function (_converse) {
 
             const sent_IQs = _converse.connection.IQ_stanzas;
             const stanza = await u.waitUntil(() => sent_IQs.filter(iq => iq.querySelector('iq query[xmlns="jabber:iq:roster"]')).pop());
@@ -1227,7 +1190,6 @@ describe("The Contacts Roster", function () {
             expect(_converse.roster.data.get('version')).toBe('ver34');
             expect(_converse.roster.models.length).toBe(4);
             expect(_converse.roster.pluck('jid').includes('data@enterprise')).toBeTruthy();
-            done();
         }));
     });
 
@@ -1236,7 +1198,7 @@ describe("The Contacts Roster", function () {
         it("are saved to, and can be retrieved from browserStorage",
             mock.initConverse(
                 [], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 0);
             await mock.createContacts(_converse, 'requesting');
@@ -1260,13 +1222,12 @@ describe("The Contacts Roster", function () {
                 // comparison
                 expect(new_attrs.sort()).toEqual(old_attrs.sort());
             }
-            done();
         }));
 
         it("will show fullname and jid properties on tooltip",
             mock.initConverse(
                 [], {},
-                async function (done, _converse) {
+                async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 'all');
             await mock.createContacts(_converse, 'requesting');
@@ -1288,7 +1249,6 @@ describe("The Contacts Roster", function () {
                 expect(child.textContent.trim()).toBe(name);
                 expect(child.firstElementChild.getAttribute('title')).toContain(jid);
             }));
-            done();
         }));
     });
 });

Some files were not shown because too many files changed in this diff