Browse Source

Test that roster groups are fetched before contacts

updates #1405
JC Brand 6 years ago
parent
commit
dfe9d301c6
6 changed files with 49 additions and 27 deletions
  1. 4 8
      dist/converse.js
  2. 3 3
      spec/bookmarks.js
  3. 1 1
      spec/roomslist.js
  4. 28 0
      spec/roster.js
  5. 7 11
      src/headless/converse-roster.js
  6. 6 4
      tests/mock.js

+ 4 - 8
dist/converse.js

@@ -68022,10 +68022,6 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
         }
         }
       } else {
       } else {
         try {
         try {
-          /* Make sure not to run fetchRosterContacts async, since we need
-           * the contacts to exist before processing contacts presence,
-           * which might come in the same BOSH request.
-           */
           await _converse.rostergroups.fetchRosterGroups();
           await _converse.rostergroups.fetchRosterGroups();
 
 
           _converse.emit('rosterGroupsFetched');
           _converse.emit('rosterGroupsFetched');
@@ -68379,7 +68375,7 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
 
 
         if (collection.length === 0 || this.rosterVersioningSupported() && !_converse.session.get('roster_fetched')) {
         if (collection.length === 0 || this.rosterVersioningSupported() && !_converse.session.get('roster_fetched')) {
           _converse.send_initial_presence = true;
           _converse.send_initial_presence = true;
-          await _converse.roster.fetchFromServer();
+          return _converse.roster.fetchFromServer();
         } else {
         } else {
           _converse.emit('cachedRoster', collection);
           _converse.emit('cachedRoster', collection);
         }
         }
@@ -68810,13 +68806,13 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
         * Returns a promise which resolves once the groups have been
         * Returns a promise which resolves once the groups have been
         * returned.
         * returned.
         */
         */
-        return new Promise((resolve, reject) => {
+        return new Promise(success => {
           this.fetch({
           this.fetch({
-            silent: true,
+            success,
             // We need to first have all groups before
             // We need to first have all groups before
             // we can start positioning them, so we set
             // we can start positioning them, so we set
             // 'silent' to true.
             // 'silent' to true.
-            success: resolve
+            silent: true
           });
           });
         });
         });
       }
       }

+ 3 - 3
spec/bookmarks.js

@@ -362,7 +362,7 @@
 
 
 
 
         it("can be retrieved from the XMPP server", mock.initConverse(
         it("can be retrieved from the XMPP server", mock.initConverse(
-            ['send'], ['chatBoxesFetched', 'roomsPanelRendered', 'rosterGroupsFetched'], {},
+            {'connection': ['send']}, ['chatBoxesFetched', 'roomsPanelRendered', 'rosterGroupsFetched'], {},
             async function (done, _converse) {
             async function (done, _converse) {
 
 
             await test_utils.waitUntilDiscoConfirmed(
             await test_utils.waitUntilDiscoConfirmed(
@@ -453,7 +453,7 @@
         describe("The rooms panel", function () {
         describe("The rooms panel", function () {
 
 
             it("shows a list of bookmarks", mock.initConverse(
             it("shows a list of bookmarks", mock.initConverse(
-                ['send'], ['rosterGroupsFetched'], {},
+                {'connection': ['send']}, ['rosterGroupsFetched'], {},
                 async function (done, _converse) {
                 async function (done, _converse) {
 
 
                 await test_utils.waitUntilDiscoConfirmed(
                 await test_utils.waitUntilDiscoConfirmed(
@@ -541,7 +541,7 @@
 
 
 
 
             it("remembers the toggle state of the bookmarks list", mock.initConverse(
             it("remembers the toggle state of the bookmarks list", mock.initConverse(
-                ['send'], ['rosterGroupsFetched'], {},
+                {'connection': ['send']}, ['rosterGroupsFetched'], {},
                 async function (done, _converse) {
                 async function (done, _converse) {
 
 
                 test_utils.openControlBox();
                 test_utils.openControlBox();

+ 1 - 1
spec/roomslist.js

@@ -48,7 +48,7 @@
 
 
         it("uses bookmarks to determine groupchat names",
         it("uses bookmarks to determine groupchat names",
             mock.initConverse(
             mock.initConverse(
-                ['send'], ['rosterGroupsFetched', 'chatBoxesFetched'], {'view_mode': 'fullscreen'},
+                {'connection': ['send']}, ['rosterGroupsFetched', 'chatBoxesFetched'], {'view_mode': 'fullscreen'},
                 async function (done, _converse) {
                 async function (done, _converse) {
 
 
             await test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy');
             await test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy');

+ 28 - 0
spec/roster.js

@@ -30,6 +30,34 @@
 
 
     describe("The Contacts Roster", function () {
     describe("The Contacts Roster", function () {
 
 
+        it("is populated once we have registered a presence handler",
+            mock.initConverse(
+                {'_converse': ['emit']}, null, {},
+                async function (done, _converse) {
+
+            const IQs = _converse.connection.IQ_stanzas;
+            await test_utils.waitUntil(() => _converse.emit.calls.all().map(c => c.args[0]).includes('rosterGroupsFetched'));
+            const node = await test_utils.waitUntil(
+                () => _.filter(IQs, iq => iq.nodeTree.querySelector('iq query[xmlns="jabber:iq:roster"]')).pop());
+            expect(_converse.emit.calls.all().map(c => c.args[0]).includes('rosterContactsFetched')).toBeFalsy();
+
+            expect(node.toLocaleString()).toBe(
+                `<iq id="${node.nodeTree.getAttribute('id')}" type="get" xmlns="jabber:client">`+
+                    `<query xmlns="jabber:iq:roster"/>`+
+                `</iq>`);
+            const result = $iq({
+                'to': _converse.connection.jid,
+                'type': 'result',
+                'id': node.nodeTree.getAttribute('id')
+            }).c('query', {
+                'xmlns': 'jabber:iq:roster'
+            }).c('item', {'jid': 'nurse@example.com'}).up()
+              .c('item', {'jid': 'romeo@example.com'})
+            _converse.connection._dataRecv(test_utils.createRequest(result));
+            await test_utils.waitUntil(() => _converse.emit.calls.all().map(c => c.args[0]).includes('rosterContactsFetched'));
+            done();
+        }));
+
         it("supports roster versioning",
         it("supports roster versioning",
             mock.initConverse(
             mock.initConverse(
                 null, ['rosterGroupsFetched'], {},
                 null, ['rosterGroupsFetched'], {},

+ 7 - 11
src/headless/converse-roster.js

@@ -88,13 +88,8 @@ converse.plugins.add('converse-roster', {
                 }
                 }
             } else {
             } else {
                 try {
                 try {
-                    /* Make sure not to run fetchRosterContacts async, since we need
-                     * the contacts to exist before processing contacts presence,
-                     * which might come in the same BOSH request.
-                     */
                     await _converse.rostergroups.fetchRosterGroups();
                     await _converse.rostergroups.fetchRosterGroups();
                     _converse.emit('rosterGroupsFetched');
                     _converse.emit('rosterGroupsFetched');
-
                     await _converse.roster.fetchRosterContacts();
                     await _converse.roster.fetchRosterContacts();
                     _converse.emit('rosterContactsFetched');
                     _converse.emit('rosterContactsFetched');
                 } catch (reason) {
                 } catch (reason) {
@@ -407,7 +402,7 @@ converse.plugins.add('converse-roster', {
                 if (collection.length === 0 ||
                 if (collection.length === 0 ||
                         (this.rosterVersioningSupported() && !_converse.session.get('roster_fetched'))) {
                         (this.rosterVersioningSupported() && !_converse.session.get('roster_fetched'))) {
                     _converse.send_initial_presence = true;
                     _converse.send_initial_presence = true;
-                    await _converse.roster.fetchFromServer();
+                    return _converse.roster.fetchFromServer();
                 } else {
                 } else {
                     _converse.emit('cachedRoster', collection);
                     _converse.emit('cachedRoster', collection);
                 }
                 }
@@ -780,12 +775,13 @@ converse.plugins.add('converse-roster', {
                 * Returns a promise which resolves once the groups have been
                 * Returns a promise which resolves once the groups have been
                 * returned.
                 * returned.
                 */
                 */
-                return new Promise((resolve, reject) => {
+                return new Promise(success => {
                     this.fetch({
                     this.fetch({
-                        silent: true, // We need to first have all groups before
-                                    // we can start positioning them, so we set
-                                    // 'silent' to true.
-                        success: resolve
+                        success,
+                        // We need to first have all groups before
+                        // we can start positioning them, so we set
+                        // 'silent' to true.
+                        silent: true,
                     });
                     });
                 });
                 });
             }
             }

+ 6 - 4
tests/mock.js

@@ -167,10 +167,8 @@
         }
         }
 
 
         const connection = mock.mock_connection();
         const connection = mock.mock_connection();
-        if (!_.isUndefined(spies)) {
-            _.forEach(spies, function (method) {
-                spyOn(connection, method);
-            });
+        if (!_.isNil(spies)) {
+            _.forEach(spies.connection, method => spyOn(connection, method));
         }
         }
 
 
         const _converse = await converse.initialize(_.extend({
         const _converse = await converse.initialize(_.extend({
@@ -186,6 +184,10 @@
             'debug': false
             'debug': false
         }, settings || {}));
         }, settings || {}));
 
 
+        if (!_.isNil(spies)) {
+            _.forEach(spies._converse, method => spyOn(_converse, method).and.callThrough());
+        }
+
         _converse.ChatBoxViews.prototype.trimChat = function () {};
         _converse.ChatBoxViews.prototype.trimChat = function () {};
 
 
         _converse.api.vcard.get = function (model, force) {
         _converse.api.vcard.get = function (model, force) {