Commit c583678c authored by JC Brand's avatar JC Brand

Use `_coverse.api.sendIQ` instead of `_converse.connection.sendIQ`

So that we know an event will be emitted when the stanza is sent.
parent 6ebf6f6e
......@@ -63028,13 +63028,15 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_3__["default"].plugins
updateRoomsList() {
/* Send an IQ stanza to the server asking for all groupchats
*/
_converse.connection.sendIQ($iq({
const iq = $iq({
'to': this.model.get('muc_domain'),
'from': _converse.connection.jid,
'type': "get"
}).c("query", {
xmlns: Strophe.NS.DISCO_ITEMS
}), this.onRoomsFound.bind(this), this.informNoRoomsFound.bind(this), 5000);
});
_converse.api.sendIQ(iq).then(iq => this.onRoomsFound(iq)).catch(iq => this.informNoRoomsFound());
},
showRooms(ev) {
......@@ -63512,7 +63514,7 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_3__["default"].plugins
iq.c("reason", reason);
}
return _converse.connection.sendIQ(iq, onSuccess, onError);
return _converse.api.sendIQ(iq).then(onSuccess).catch(onError);
},
verifyRoles(roles) {
......@@ -73262,9 +73264,9 @@ _converse.api = {
* @returns {Promise} A promise which resolves when we receive a `result` stanza
* or is rejected when we receive an `error` stanza.
*/
'sendIQ'(stanza) {
'sendIQ'(stanza, timeout) {
return new es6_promise_dist_es6_promise_auto__WEBPACK_IMPORTED_MODULE_2___default.a((resolve, reject) => {
_converse.connection.sendIQ(stanza, resolve, reject, _converse.IQ_TIMEOUT);
_converse.connection.sendIQ(stanza, resolve, reject, timeout || _converse.IQ_TIMEOUT);
_converse.emit('send', stanza);
});
......@@ -74295,7 +74297,7 @@ function queryForArchivedMessages(_converse, options, callback, errback) {
return true;
}, Strophe.NS.MAM);
_converse.connection.sendIQ(stanza, function (iq) {
_converse.api.sendIQ(stanza, _converse.message_archiving_timeout).then(iq => {
_converse.connection.deleteHandler(message_handler);
if (_.isFunction(callback)) {
......@@ -74312,13 +74314,15 @@ function queryForArchivedMessages(_converse, options, callback, errback) {
callback(messages, rsm);
}
}, function () {
}).catch(e => {
_converse.connection.deleteHandler(message_handler);
if (_.isFunction(errback)) {
errback.apply(this, arguments);
}
}, _converse.message_archiving_timeout);
return;
});
}
_converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam', {
......@@ -74556,7 +74560,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
});
_converse.onMAMError = function (model, iq) {
_converse.onMAMError = function (iq) {
if (iq.querySelectorAll('feature-not-implemented').length) {
_converse.log("Message Archive Management (XEP-0313) not supported by this server", Strophe.LogLevel.WARN);
} else {
......@@ -74588,20 +74592,16 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
'default': _converse.message_archiving
});
_.each(preference.children, function (child) {
stanza.cnode(child).up();
});
_converse.connection.sendIQ(stanza, _.partial(function (feature, iq) {
// XXX: Strictly speaking, the server should respond with the updated prefs
_.each(preference.children, child => stanza.cnode(child).up()); // XXX: Strictly speaking, the server should respond with the updated prefs
// (see example 18: https://xmpp.org/extensions/xep-0313.html#config)
// but Prosody doesn't do this, so we don't rely on it.
feature.save({
_converse.api.sendIQ(stanza).then(() => feature.save({
'preferences': {
'default': _converse.message_archiving
}
});
}, feature), _converse.onMAMError);
})).catch(_converse.onMAMError);
} else {
feature.save({
'preferences': {
......@@ -74619,11 +74619,11 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
if (feature.get('var') === Strophe.NS.MAM && prefs['default'] !== _converse.message_archiving && // eslint-disable-line dot-notation
!_.isUndefined(_converse.message_archiving)) {
// Ask the server for archiving preferences
_converse.connection.sendIQ($iq({
_converse.api.sendIQ($iq({
'type': 'get'
}).c('prefs', {
'xmlns': Strophe.NS.MAM
}), _.partial(_converse.onMAMPreferences, feature), _.partial(_converse.onMAMError, feature));
})).then(_.partial(_converse.onMAMPreferences, feature)).catch(_converse.onMAMError);
}
});
......@@ -75552,14 +75552,12 @@ _converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].plugins.add('converse-muc
* Returns a promise which resolves once the response IQ
* has been received.
*/
return new Promise((resolve, reject) => {
_converse.connection.sendIQ($iq({
return _converse.api.sendIQ($iq({
'to': this.get('jid'),
'type': "get"
}).c("query", {
xmlns: Strophe.NS.MUC_OWNER
}), resolve, reject);
});
}));
},
sendConfiguration(config, callback, errback) {
......@@ -75592,7 +75590,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].plugins.add('converse-muc
callback = _.isUndefined(callback) ? _.noop : _.partial(callback, iq.nodeTree);
errback = _.isUndefined(errback) ? _.noop : _.partial(errback, iq.nodeTree);
return _converse.connection.sendIQ(iq, callback, errback);
return _converse.api.sendIQ(iq).then(callback).catch(errback);
},
saveAffiliationAndRole(pres) {
......@@ -75632,7 +75630,6 @@ _converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].plugins.add('converse-muc
* (Object) member: Map containing the member's jid and
* optionally a reason and affiliation.
*/
return new Promise((resolve, reject) => {
const iq = $iq({
to: this.get('jid'),
type: "set"
......@@ -75648,8 +75645,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].plugins.add('converse-muc
iq.c("reason", member.reason);
}
_converse.connection.sendIQ(iq, resolve, reject);
});
return _converse.api.sendIQ(iq);
},
setAffiliations(members) {
......@@ -77073,7 +77069,7 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
subscription: "remove"
});
_converse.connection.sendIQ(iq, callback, errback);
_converse.api.sendIQ(iq).then(callback).catch(errback);
return this;
}
......@@ -77197,7 +77193,7 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
this.addContactToRoster(jid, name, groups, attributes).then(handler, handler);
},
sendContactAddIQ(jid, name, groups, callback, errback) {
sendContactAddIQ(jid, name, groups) {
/* Send an IQ stanza to the XMPP server to add a new roster contact.
*
* Parameters:
......@@ -77209,22 +77205,20 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
*/
name = _.isEmpty(name) ? jid : name;
const iq = $iq({
type: 'set'
'type': 'set'
}).c('query', {
xmlns: Strophe.NS.ROSTER
'xmlns': Strophe.NS.ROSTER
}).c('item', {
jid,
name
});
_.each(groups, function (group) {
iq.c('group').t(group).up();
});
_.each(groups, group => iq.c('group').t(group).up());
_converse.connection.sendIQ(iq, callback, errback);
_converse.api.sendIQ(iq);
},
addContactToRoster(jid, name, groups, attributes) {
async addContactToRoster(jid, name, groups, attributes) {
/* Adds a RosterContact instance to _converse.roster and
* registers the contact on the XMPP server.
* Returns a promise which is resolved once the XMPP server has
......@@ -77236,10 +77230,18 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
* (Array of Strings) groups - Any roster groups the user might belong to
* (Object) attributes - Any additional attributes to be stored on the user's model.
*/
return new Promise((resolve, reject) => {
groups = groups || [];
this.sendContactAddIQ(jid, name, groups, () => {
const contact = this.create(_.assignIn({
try {
await this.sendContactAddIQ(jid, name, groups);
} catch (e) {
_converse.log(e, Strophe.LogLevel.ERROR);
alert(__('Sorry, there was an error while trying to add %1$s as a contact.', name));
return e;
}
return this.create(_.assignIn({
'ask': undefined,
'nickname': name,
groups,
......@@ -77247,16 +77249,7 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
'requesting': false,
'subscription': 'none'
}, attributes), {
sort: false
});
resolve(contact);
}, function (err) {
alert(__('Sorry, there was an error while trying to add %1$s as a contact.', name));
_converse.log(err, Strophe.LogLevel.ERROR);
resolve(err);
});
'sort': false
});
},
......@@ -77346,10 +77339,9 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
return _converse.api.disco.stream.getFeature('ver', 'urn:xmpp:features:rosterver') && this.data.get('version');
},
fetchFromServer() {
async fetchFromServer() {
/* Fetch the roster from the XMPP server */
return new Promise((resolve, reject) => {
const iq = $iq({
const stanza = $iq({
'type': 'get',
'id': _converse.connection.getUniqueId('roster')
}).c('query', {
......@@ -77357,23 +77349,22 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
});
if (this.rosterVersioningSupported()) {
iq.attrs({
stanza.attrs({
'ver': this.data.get('version')
});
}
const callback = _.flow(this.onReceivedFromServer.bind(this), resolve);
const errback = function errback(iq) {
const errmsg = "Error while trying to fetch roster from the server";
let iq;
_converse.log(errmsg, Strophe.LogLevel.ERROR);
try {
iq = await _converse.api.sendIQ(stanza);
} catch (e) {
_converse.log(e, Strophe.LogLevel.ERROR);
reject(new Error(errmsg));
};
return _converse.log("Error while trying to fetch roster from the server", Strophe.LogLevel.ERROR);
}
return _converse.connection.sendIQ(iq, callback, errback);
});
return this.onReceivedFromServer(iq);
},
onReceivedFromServer(iq) {
......@@ -77834,7 +77825,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins.add('converse-vca
});
function onVCardData(jid, iq, callback) {
async function onVCardData(jid, iq) {
const vcard = iq.querySelector('vCard');
let result = {};
......@@ -77855,23 +77846,11 @@ _converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins.add('converse-vca
if (result.image) {
const buffer = u.base64ToArrayBuffer(result['image']);
crypto.subtle.digest('SHA-1', buffer).then(ab => {
const ab = await crypto.subtle.digest('SHA-1', buffer);
result['image_hash'] = u.arrayBufferToHex(ab);
if (callback) callback(result);
});
} else {
if (callback) callback(result);
}
}
function onVCardError(jid, iq, errback) {
if (errback) {
errback({
'stanza': iq,
'jid': jid,
'vcard_error': moment().format()
});
}
return result;
}
function createStanza(type, jid, vcard_el) {
......@@ -77902,7 +77881,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins.add('converse-vca
return _converse.api.sendIQ(createStanza("set", jid, vcard_el));
}
function getVCard(_converse, jid) {
async function getVCard(_converse, jid) {
/* Request the VCard of another user. Returns a promise.
*
* Parameters:
......@@ -77910,9 +77889,19 @@ _converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins.add('converse-vca
* is being requested.
*/
const to = Strophe.getBareJidFromJid(jid) === _converse.bare_jid ? null : jid;
return new Promise((resolve, reject) => {
_converse.connection.sendIQ(createStanza("get", to), _.partial(onVCardData, jid, _, resolve), _.partial(onVCardError, jid, _, resolve), _converse.IQ_TIMEOUT);
});
let iq;
try {
iq = await _converse.api.sendIQ(createStanza("get", to));
} catch (iq) {
return {
'stanza': iq,
'jid': jid,
'vcard_error': moment().format()
};
}
return onVCardData(jid, iq);
}
/* Event handlers */
......@@ -3739,7 +3739,7 @@
it("contains a link to a modal which can list groupchats publically available on the server",
mock.initConverseWithPromises(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) {
async function (done, _converse) {
var sendIQ = _converse.connection.sendIQ;
var sent_stanza, IQ_id;
......@@ -3753,8 +3753,7 @@
roomspanel.el.querySelector('.show-list-muc-modal').click();
test_utils.closeControlBox(_converse);
const modal = roomspanel.list_rooms_modal;
test_utils.waitUntil(() => u.isVisible(modal.el), 1000)
.then(() => {
await test_utils.waitUntil(() => u.isVisible(modal.el), 1000);
spyOn(_converse.ChatRoom.prototype, 'getRoomFeatures').and.callFake(() => Promise.resolve());
roomspanel.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
......@@ -3763,15 +3762,14 @@
const input = modal.el.querySelector('input[name="server"]').value = 'chat.shakespear.lit';
modal.el.querySelector('input[type="submit"]').click();
return test_utils.waitUntil(() => _converse.chatboxes.length);
}).then(() => {
await test_utils.waitUntil(() => _converse.chatboxes.length);
expect(sent_stanza.toLocaleString()).toBe(
`<iq from="dummy@localhost/resource" id="${IQ_id}" to="chat.shakespear.lit" type="get" xmlns="jabber:client">`+
`<query xmlns="http://jabber.org/protocol/disco#items"/>`+
`</iq>`
);
var iq = $iq({
const iq = $iq({
from:'muc.localhost',
to:'dummy@localhost/pda',
id: IQ_id,
......@@ -3783,7 +3781,7 @@
.c('item', { jid:'inverness@chat.shakespeare.lit', name:'Macbeth&apos;s Castle'}).nodeTree;
_converse.connection._dataRecv(test_utils.createRequest(iq));
expect(modal.el.querySelectorAll('.available-chatrooms li').length).toBe(5);
await test_utils.waitUntil(() => modal.el.querySelectorAll('.available-chatrooms li').length === 5);
const rooms = modal.el.querySelectorAll('.available-chatrooms li');
expect(rooms[0].textContent.trim()).toBe("Groupchats found:");
......@@ -3793,13 +3791,11 @@
expect(rooms[4].textContent.trim()).toBe("Macbeth's Castle");
rooms[4].querySelector('.open-room').click();
return test_utils.waitUntil(() => _converse.chatboxes.length > 1);
}).then(() => {
await test_utils.waitUntil(() => _converse.chatboxes.length > 1);
expect(sizzle('.chatroom', _converse.el).filter(u.isVisible).length).toBe(1); // There should now be an open chatroom
var view = _converse.chatboxviews.get('inverness@chat.shakespeare.lit');
expect(view.el.querySelector('.chat-head-chatroom').textContent.trim()).toBe("Macbeth's Castle");
done();
}).catch(_.partial(console.error, _));
}));
it("shows the number of unread mentions received",
......
......@@ -157,14 +157,14 @@
it("checks whether returned MAM messages from a MUC room are from the right JID",
mock.initConverseWithPromises(
null, [], {},
function (done, _converse) {
async function (done, _converse) {
_converse.api.disco.entities.get(_converse.domain).then(function (entity) {
const entity = await _converse.api.disco.entities.get(_converse.domain);
if (!entity.features.findWhere({'var': Strophe.NS.MAM})) {
_converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
}
var sent_stanza, IQ_id;
var sendIQ = _converse.connection.sendIQ;
const sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_stanza = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback);
......@@ -217,7 +217,7 @@
* </set>
* </iq>
*/
var stanza = $iq({'type': 'result', 'id': IQ_id})
const stanza = $iq({'type': 'result', 'id': IQ_id})
.c('fin', {'xmlns': 'urn:xmpp:mam:2'})
.c('set', {'xmlns': 'http://jabber.org/protocol/rsm'})
.c('first', {'index': '0'}).t('23452-4534-1').up()
......@@ -225,11 +225,11 @@
.c('count').t('16');
_converse.connection._dataRecv(test_utils.createRequest(stanza));
await test_utils.waitUntil(() => callback.calls.count());
expect(callback).toHaveBeenCalled();
var args = callback.calls.argsFor(0);
expect(args[0].length).toBe(0);
done();
});
}));
it("can be used to query for all messages in a certain timespan",
......@@ -279,9 +279,9 @@
it("throws a TypeError if an invalid date is provided",
mock.initConverseWithPromises(
null, [], {},
function (done, _converse) {
async function (done, _converse) {
_converse.api.disco.entities.get(_converse.domain).then(function (entity) {
const entity = await _converse.api.disco.entities.get(_converse.domain);
if (!entity.features.findWhere({'var': Strophe.NS.MAM})) {
_converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
}
......@@ -289,7 +289,6 @@
new TypeError('archive.query: invalid date provided for: start')
);
done();
});
}));
it("can be used to query for all messages after a certain time",
......@@ -500,22 +499,22 @@
it("accepts a callback function, which it passes the messages and a Strophe.RSM object",
mock.initConverseWithPromises(
null, [], {},
function (done, _converse) {
async function (done, _converse) {
_converse.api.disco.entities.get(_converse.domain).then(function (entity) {
const entity = await _converse.api.disco.entities.get(_converse.domain);
if (!entity.features.findWhere({'var': Strophe.NS.MAM})) {
_converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
}
var sent_stanza, IQ_id;
var sendIQ = _converse.connection.sendIQ;
let sent_stanza, IQ_id;
const sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_stanza = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback);
});
var callback = jasmine.createSpy('callback');
const callback = jasmine.createSpy('callback');
_converse.api.archive.query({'with': 'romeo@capulet.lit', 'max':'10'}, callback);
var queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
const queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
/* <message id='aeb213' to='juliet@capulet.lit/chamber'>
* <result xmlns='urn:xmpp:mam:2' queryid='f27' id='28482-98726-73623'>
......@@ -566,7 +565,7 @@
* </set>
* </iq>
*/
var stanza = $iq({'type': 'result', 'id': IQ_id})
const stanza = $iq({'type': 'result', 'id': IQ_id})
.c('fin', {'xmlns': 'urn:xmpp:mam:2'})
.c('set', {'xmlns': 'http://jabber.org/protocol/rsm'})
.c('first', {'index': '0'}).t('23452-4534-1').up()
......@@ -574,6 +573,7 @@
.c('count').t('16');
_converse.connection._dataRecv(test_utils.createRequest(stanza));
await test_utils.waitUntil(() => callback.calls.count());
expect(callback).toHaveBeenCalled();
var args = callback.calls.argsFor(0);
expect(args[0].length).toBe(2);
......@@ -585,7 +585,6 @@
expect(args[1].first).toBe('23452-4534-1');
expect(args[1].last).toBe('09af3-cc343-b409f');
done()
});
}));
});
......@@ -594,11 +593,11 @@
it("is set once server support for MAM has been confirmed",
mock.initConverseWithPromises(
null, [], {},
function (done, _converse) {
async function (done, _converse) {
_converse.api.disco.entities.get(_converse.domain).then(function (entity) {
var sent_stanza, IQ_id;
var sendIQ = _converse.connection.sendIQ;
const entity = await _converse.api.disco.entities.get(_converse.domain);
let sent_stanza, IQ_id;
const sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_stanza = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback);
......@@ -628,12 +627,13 @@
* </prefs>
* </iq>
*/
var stanza = $iq({'type': 'result', 'id': IQ_id})
let stanza = $iq({'type': 'result', 'id': IQ_id})
.c('prefs', {'xmlns': Strophe.NS.MAM, 'default':'roster'})
.c('always').c('jid').t('romeo@montague.lit').up().up()
.c('never').c('jid').t('montague@montague.lit');
_converse.connection._dataRecv(test_utils.createRequest(stanza));
await test_utils.waitUntil(() => _converse.onMAMPreferences.calls.count());
expect(_converse.onMAMPreferences).toHaveBeenCalled();
expect(_converse.connection.sendIQ.calls.count()).toBe(2);
......@@ -661,12 +661,12 @@
stanza = $iq({'type': 'result', 'id': IQ_id})
.c('prefs', {'xmlns': Strophe.NS.MAM, 'default':'always'})
.c('always').up()
.c('never').up();
.c('never');
_converse.connection._dataRecv(test_utils.createRequest(stanza));
await test_utils.waitUntil(() => feature.save.calls.count());
expect(feature.save).toHaveBeenCalled();
expect(feature.get('preferences')['default']).toBe('never'); // eslint-disable-line dot-notation
done();
});
}));
});
});
......
......@@ -52,27 +52,23 @@
mock.initConverseWithPromises(
null, ['rosterGroupsFetched'],
{ roster_groups: false },
function (done, _converse) {
async function (done, _converse) {
var contact, sent_stanza, IQ_id, stanza, modal;
test_utils.waitUntilDiscoConfirmed(_converse, 'localhost', [], ['vcard-temp'])
.then(function () {
return test_utils.waitUntil(function () {
return _converse.xmppstatus.vcard.get('fullname');
}, 300);
}).then(function () {
await test_utils.waitUntilDiscoConfirmed(_converse, 'localhost', [], ['vcard-temp']);
await test_utils.waitUntil(() => _converse.xmppstatus.vcard.get('fullname'), 300);
/* The process by which a user subscribes to a contact, including
* the interaction between roster items and subscription states.
*/
test_utils.openControlBox(_converse);
var cbview = _converse.chatboxviews.get('controlbox');
const cbview = _converse.chatboxviews.get('controlbox');
spyOn(_converse.roster, "addAndSubscribe").and.callThrough();
spyOn(_converse.roster, "addContactToRoster").and.callThrough();
spyOn(_converse.roster, "sendContactAddIQ").and.callThrough();
spyOn(_converse.api.vcard, "get").and.callThrough();
var sendIQ = _converse.connection.sendIQ;
const sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_stanza = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback);
......@@ -80,15 +76,12 @@
cbview.el.querySelector('.add-contact').click()
modal = _converse.rosterview.add_contact_modal;
return test_utils.waitUntil(function () {
return u.isVisible(modal.el);
}, 1000);
}).then(function () {
await test_utils.waitUntil(() => u.isVisible(modal.el), 1000);
spyOn(modal, "addContactFromForm").and.callThrough();
modal.delegateEvents();
// Fill in the form and submit
var form = modal.el.querySelector('form.add-xmpp-contact');
const form = modal.el.querySelector('form.add-xmpp-contact');
form.querySelector('input').value = 'contact@example.org';
form.querySelector('[type="submit"]').click();
......@@ -145,8 +138,8 @@
* </query>
* </iq>
*/
var create = _converse.roster.create;
var sent_stanzas = [];
const create = _converse.roster.create;
const sent_stanzas = [];
spyOn(_converse.connection, 'send').and.callFake(function (stanza) {
sent_stanza = stanza;
sent_stanzas.push(stanza.toLocaleString());
......@@ -162,12 +155,13 @@
'subscription': 'none',
'name': 'contact@example.org'});
_converse.connection._dataRecv(test_utils.createRequest(stanza));
/*
* <iq type='result' id='set1'/>
/* <iq type='result' id='set1'/>
*/
stanza = $iq({'type': 'result', 'id':IQ_id});
_converse.connection._dataRecv(test_utils.createRequest(stanza));
await test_utils.waitUntil(() => _converse.roster.create.calls.count());
// A contact should now have been created
expect(_converse.roster.get('contact@example.org') instanceof _converse.RosterContact).toBeTruthy();
expect(contact.get('jid')).toBe('contact@example.org');
......@@ -179,10 +173,7 @@
*
* <presence to='contact@example.org' type='subscribe'/>
*/
return test_utils.waitUntil(function () {
return sent_stanzas.length == 1;
}, 300);
}).then(function () {
await test_utils.waitUntil(() => sent_stanzas.filter(s => s.match('presence')));
expect(contact.subscribe).toHaveBeenCalled();
expect(sent_stanza.toLocaleString()).toBe( // Strophe adds the xmlns attr (although not in spec)
`<presence to="contact@example.org" type="subscribe" xmlns="jabber:client">`+
......@@ -220,12 +211,12 @@
expect(_converse.roster.updateContact).toHaveBeenCalled();
// Check that the user is now properly shown as a pending
// contact in the roster.
return test_utils.waitUntil(function () {
await test_utils.waitUntil(function () {
var $header = $('a:contains("Pending contacts")');
var $contacts = $header.parent().find('li:visible');
return $contacts.length;
}, 600);
}).then(function () {
var $header = $('a:contains("Pending contacts")');
var $contacts = $header.parent().find('li');
expect($contacts.length).toBe(1);
......@@ -289,16 +280,15 @@
// The contact should now be visible as an existing
// contact (but still offline).
return test_utils.waitUntil(function () {
await test_utils.waitUntil(function () {
var $header = $('a:contains("My contacts")');
var $contacts = $header.parent().find('li:visible');
return $contacts.length;
}, 600);
}).then(function () {
var $header = $('a:contains("My contacts")');
$header = $('a:contains("My contacts")');
expect($header.length).toBe(1);
expect($header.is(":visible")).toBeTruthy();
var $contacts = $header.parent().find('li');
$contacts = $header.parent().find('li');
expect($contacts.length).toBe(1);
// Check that it has the right classes and text
expect($contacts.hasClass('to')).toBeTruthy();
......@@ -372,7 +362,7 @@
expect($contacts.hasClass('to')).toBeFalsy();
expect($contacts.hasClass('both')).toBeTruthy();
done();
});
}));
it("Alternate Flow: Contact Declines Subscription Request",
......@@ -466,7 +456,7 @@
mock.initConverseWithPromises(
null, ['rosterGroupsFetched'],
{ roster_groups: false },
function (done, _converse) {
async function (done, _converse) {
var sent_IQ, IQ_id, jid = 'annegreet.gomez@localhost';
test_utils.openControlBox(_converse);
......@@ -480,13 +470,9 @@
sent_IQ = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback);
});
return test_utils.waitUntil(function () {
var $header = $('a:contains("My contacts")');
var $contacts = $header.parent().find('li');
return $contacts.length;
}, 600).then(function () {
const $header = $('a:contains("My contacts")');
await test_utils.waitUntil(() => $header.parent().find('li').length);
var $header = $('a:contains("My contacts")');
// remove the first user
$header.parent().find('li .remove-xmpp-contact').get(0).click();
expect(window.confirm).toHaveBeenCalled();
......@@ -519,12 +505,11 @@
// Receive confirmation from the contact's server
// <iq type='result' id='remove1'/>
var stanza = $iq({'type': 'result', 'id':IQ_id});
const stanza = $iq({'type': 'result', 'id':IQ_id});
_converse.connection._dataRecv(test_utils.createRequest(stanza));
// Our contact has now been removed
expect(typeof _converse.roster.get(jid) === "undefined").toBeTruthy();
await test_utils.waitUntil(() => typeof _converse.roster.get(jid) === "undefined");
done();
});
}));
it("Receiving a subscription request", mock.initConverseWithPromises(
......
(function (root, factory) {
define(["jquery", "jasmine", "mock", "test-utils"], factory);
} (this, function ($, jasmine, mock, test_utils) {
var _ = converse.env._;
var Strophe = converse.env.Strophe;
var $pres = converse.env.$pres;
var $msg = converse.env.$msg;
var $iq = converse.env.$iq;
var u = converse.env.utils;
var checkHeaderToggling = function (group) {
const $iq = converse.env.$iq;
const $msg = converse.env.$msg;
const $pres = converse.env.$pres;
const Strophe = converse.env.Strophe;
const _ = converse.env._;
const sizzle = converse.env.sizzle;
const u = converse.env.utils;
const checkHeaderToggling = function (group) {
var $group = $(group);
var toggle = group.querySelector('a.group-toggle');
expect(u.isVisible($group[0])).toBeTruthy();
......@@ -38,12 +40,12 @@
it("supports roster versioning",
mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {},
function (done, _converse) {
async function (done, _converse) {
const IQ_stanzas = _converse.connection.IQ_stanzas;
test_utils.waitUntil(
let node = await test_utils.waitUntil(
() => _.filter(IQ_stanzas, iq => iq.nodeTree.querySelector('iq query[xmlns="jabber:iq:roster"]')).pop()
).then(node => {
);
let stanza = node.nodeTree;
expect(_converse.roster.data.get('version')).toBeUndefined();
expect(node.toLocaleString()).toBe(
......@@ -60,6 +62,8 @@
}).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.roster.models.length > 1);
expect(_converse.roster.data.get('version')).toBe('ver7');
expect(_converse.roster.models.length).toBe(2);
......@@ -88,7 +92,6 @@
expect(_converse.roster.models.length).toBe(1);
expect(_converse.roster.at(0).get('jid')).toBe('nurse@example.com');
done();
});
}));
describe("The live filter", function () {
......@@ -549,17 +552,15 @@
it("can be collapsed under their own header",
mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {},
function (done, _converse) {
async function (done, _converse) {
_addContacts(_converse);
test_utils.waitUntil(function () {
return $(_converse.rosterview.el).find('.roster-group:visible li').length;
}, 500).then(function () {
checkHeaderToggling.apply(
await test_utils.waitUntil(() => $(_converse.rosterview.el).find('.roster-group:visible li').length, 1000);
await checkHeaderToggling.apply(
_converse,
[_converse.rosterview.get('Pending contacts').el]
).then(done);
});
);
done();
}));
it("can be added to the roster",
......@@ -662,10 +663,10 @@
it("do not have a header if there aren't any",
mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {},
function (done, _converse) {
async function (done, _converse) {
test_utils.openControlBox();
var name = mock.pend_names[0];
const name = mock.pend_names[0];
_converse.roster.create({
jid: name.replace(/ /g,'.').toLowerCase() + '@localhost',
subscription: 'none',
......@@ -676,17 +677,18 @@
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback) {
if (typeof callback === "function") { return callback(); }
});
test_utils.waitUntil(function () {
await test_utils.waitUntil(function () {
var $pending_contacts = $(_converse.rosterview.get('Pending contacts').el);
return $pending_contacts.is(':visible') && $pending_contacts.find('li:visible').length;
}, 700).then(function () {
}, 700)
$(_converse.rosterview.el).find(".pending-contact-name:contains('"+name+"')")
.parent().siblings('.remove-xmpp-contact')[0].click();
expect(window.confirm).toHaveBeenCalled();
expect(_converse.connection.sendIQ).toHaveBeenCalled();
expect(u.isVisible(_converse.rosterview.get('Pending contacts').el)).toEqual(false);
await test_utils.waitUntil(() => !u.isVisible(_converse.rosterview.get('Pending contacts').el));
done();
});
}));
it("is shown when a new private message is received",
......@@ -822,20 +824,18 @@
it("can be removed by the user",
mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {},
function (done, _converse) {
async function (done, _converse) {
var sent_IQ;
_addContacts(_converse);
test_utils.waitUntil(function () {
return $(_converse.rosterview.el).find('li').length;
}, 500).then(function () {
var name = mock.cur_names[0];
var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
var contact = _converse.roster.get(jid);
await test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('li').length);
const name = mock.cur_names[0];
const jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
const contact = _converse.roster.get(jid);
spyOn(window, 'confirm').and.returnValue(true);
spyOn(contact, 'removeFromRoster').and.callThrough();
var sendIQ = _converse.connection.sendIQ;
const sendIQ = _converse.connection.sendIQ;
let sent_IQ;
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_IQ = iq;
callback();
......@@ -849,15 +849,14 @@
`<query xmlns="jabber:iq:roster"><item jid="max.frankfurter@localhost" subscription="remove"/></query>`+
`</iq>`);
expect(contact.removeFromRoster).toHaveBeenCalled();
expect($(_converse.rosterview.el).find(".open-chat:contains('"+name+"')").length).toEqual(0);
await test_utils.waitUntil(() => $(_converse.rosterview.el).find(".open-chat:contains('"+name+"')").length === 0);
done();
});
}));
it("do not have a header if there aren't any",
mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {},
function (done, _converse) {
async function (done, _converse) {
test_utils.openControlBox();
var name = mock.cur_names[0];
......@@ -868,24 +867,20 @@
ask: null,
fullname: name
});
test_utils.waitUntil(function () {
return $(_converse.rosterview.el).find('.roster-group:visible li').length;
}, 700).then(function () {
await test_utils.waitUntil(() => $(_converse.rosterview.el).find('.roster-group:visible li').length, 1000);
spyOn(window, 'confirm').and.returnValue(true);
spyOn(contact, 'removeFromRoster').and.callThrough();
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback) {
if (typeof callback === "function") { return callback(); }
});
expect($(_converse.rosterview.el).find('.roster-group').css('display')).toEqual('block');
$(_converse.rosterview.el).find(".open-chat:contains('"+name+"')")
.parent().find('.remove-xmpp-contact')[0].click();
expect(window.confirm).toHaveBeenCalled();
expect(_converse.connection.sendIQ).toHaveBeenCalled();
expect(contact.removeFromRoster).toHaveBeenCalled();
expect($(_converse.rosterview.el).find('.roster-group').length).toEqual(0);
await test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length === 0);
done();
});
}));
it("can change their status to online and be sorted alphabetically",
......
......@@ -367,16 +367,14 @@ converse.plugins.add('converse-muc-views', {
updateRoomsList () {
/* Send an IQ stanza to the server asking for all groupchats
*/
_converse.connection.sendIQ(
$iq({
const iq = $iq({
'to': this.model.get('muc_domain'),
'from': _converse.connection.jid,
'type': "get"
}).c("query", {xmlns: Strophe.NS.DISCO_ITEMS}),
this.onRoomsFound.bind(this),
this.informNoRoomsFound.bind(this),
5000
);
}).c("query", {xmlns: Strophe.NS.DISCO_ITEMS});
_converse.api.sendIQ(iq)
.then(iq => this.onRoomsFound(iq))
.catch(iq => this.informNoRoomsFound())
},
showRooms (ev) {
......@@ -805,7 +803,7 @@ converse.plugins.add('converse-muc-views', {
const item = $build("item", {nick, role});
const iq = $iq({to: groupchat, type: "set"}).c("query", {xmlns: Strophe.NS.MUC_ADMIN}).cnode(item.node);
if (reason !== null) { iq.c("reason", reason); }
return _converse.connection.sendIQ(iq, onSuccess, onError);
return _converse.api.sendIQ(iq).then(onSuccess).catch(onError);
},
verifyRoles (roles) {
......
......@@ -1651,9 +1651,9 @@ _converse.api = {
* @returns {Promise} A promise which resolves when we receive a `result` stanza
* or is rejected when we receive an `error` stanza.
*/
'sendIQ' (stanza) {
'sendIQ' (stanza, timeout) {
return new Promise((resolve, reject) => {
_converse.connection.sendIQ(stanza, resolve, reject, _converse.IQ_TIMEOUT);
_converse.connection.sendIQ(stanza, resolve, reject, timeout || _converse.IQ_TIMEOUT);
_converse.emit('send', stanza);
});
}
......
......@@ -99,9 +99,8 @@ function queryForArchivedMessages (_converse, options, callback, errback) {
return true;
}, Strophe.NS.MAM);
_converse.connection.sendIQ(
stanza,
function (iq) {
_converse.api.sendIQ(stanza, _converse.message_archiving_timeout)
.then(iq => {
_converse.connection.deleteHandler(message_handler);
if (_.isFunction(callback)) {
const set = iq.querySelector('set');
......@@ -112,13 +111,13 @@ function queryForArchivedMessages (_converse, options, callback, errback) {
}
callback(messages, rsm);
}
},
function () {
}).catch(e => {
_converse.connection.deleteHandler(message_handler);
if (_.isFunction(errback)) { errback.apply(this, arguments); }
},
_converse.message_archiving_timeout
);
if (_.isFunction(errback)) {
errback.apply(this, arguments);
}
return;
});
}
......@@ -333,7 +332,7 @@ converse.plugins.add('converse-mam', {
message_archiving_timeout: 8000, // Time (in milliseconds) to wait before aborting MAM request
});
_converse.onMAMError = function (model, iq) {
_converse.onMAMError = function (iq) {
if (iq.querySelectorAll('feature-not-implemented').length) {
_converse.log(
"Message Archive Management (XEP-0313) not supported by this server",
......@@ -365,17 +364,14 @@ converse.plugins.add('converse-mam', {
'xmlns':Strophe.NS.MAM,
'default':_converse.message_archiving
});
_.each(preference.children, function (child) {
stanza.cnode(child).up();
});
_converse.connection.sendIQ(stanza, _.partial(function (feature, iq) {
_.each(preference.children, child => stanza.cnode(child).up());
// XXX: Strictly speaking, the server should respond with the updated prefs
// (see example 18: https://xmpp.org/extensions/xep-0313.html#config)
// but Prosody doesn't do this, so we don't rely on it.
feature.save({'preferences': {'default':_converse.message_archiving}});
}, feature),
_converse.onMAMError
);
_converse.api.sendIQ(stanza)
.then(() => feature.save({'preferences': {'default':_converse.message_archiving}}))
.catch(_converse.onMAMError);
} else {
feature.save({'preferences': {'default':_converse.message_archiving}});
}
......@@ -388,11 +384,9 @@ converse.plugins.add('converse-mam', {
prefs['default'] !== _converse.message_archiving && // eslint-disable-line dot-notation
!_.isUndefined(_converse.message_archiving) ) {
// Ask the server for archiving preferences
_converse.connection.sendIQ(
$iq({'type': 'get'}).c('prefs', {'xmlns': Strophe.NS.MAM}),
_.partial(_converse.onMAMPreferences, feature),
_.partial(_converse.onMAMError, feature)
);
_converse.api.sendIQ($iq({'type': 'get'}).c('prefs', {'xmlns': Strophe.NS.MAM}))
.then(_.partial(_converse.onMAMPreferences, feature))
.catch(_converse.onMAMError);
}
});
......
......@@ -620,16 +620,10 @@ converse.plugins.add('converse-muc', {
* Returns a promise which resolves once the response IQ
* has been received.
*/
return new Promise((resolve, reject) => {
_converse.connection.sendIQ(
$iq({
'to': this.get('jid'),
'type': "get"
}).c("query", {xmlns: Strophe.NS.MUC_OWNER}),
resolve,
reject
return _converse.api.sendIQ(
$iq({'to': this.get('jid'), 'type': "get"})
.c("query", {xmlns: Strophe.NS.MUC_OWNER})
);
});
},
sendConfiguration (config, callback, errback) {
......@@ -652,7 +646,7 @@ converse.plugins.add('converse-muc', {
_.each(config || [], function (node) { iq.cnode(node).up(); });
callback = _.isUndefined(callback) ? _.noop : _.partial(callback, iq.nodeTree);
errback = _.isUndefined(errback) ? _.noop : _.partial(errback, iq.nodeTree);
return _converse.connection.sendIQ(iq, callback, errback);
return _converse.api.sendIQ(iq).then(callback).catch(errback);
},
saveAffiliationAndRole (pres) {
......@@ -685,7 +679,6 @@ converse.plugins.add('converse-muc', {
* (Object) member: Map containing the member's jid and
* optionally a reason and affiliation.
*/
return new Promise((resolve, reject) => {
const iq = $iq({to: this.get('jid'), type: "set"})
.c("query", {xmlns: Strophe.NS.MUC_ADMIN})
.c("item", {
......@@ -696,8 +689,7 @@ converse.plugins.add('converse-muc', {
if (!_.isUndefined(member.reason)) {
iq.c("reason", member.reason);
}
_converse.connection.sendIQ(iq, resolve, reject);
});
return _converse.api.sendIQ(iq);
},
setAffiliations (members) {
......
......@@ -329,7 +329,7 @@ converse.plugins.add('converse-roster', {
const iq = $iq({type: 'set'})
.c('query', {xmlns: Strophe.NS.ROSTER})
.c('item', {jid: this.get('jid'), subscription: "remove"});
_converse.connection.sendIQ(iq, callback, errback);
_converse.api.sendIQ(iq).then(callback).catch(errback);
return this;
}
});
......@@ -451,7 +451,7 @@ converse.plugins.add('converse-roster', {
this.addContactToRoster(jid, name, groups, attributes).then(handler, handler);
},
sendContactAddIQ (jid, name, groups, callback, errback) {
sendContactAddIQ (jid, name, groups) {
/* Send an IQ stanza to the XMPP server to add a new roster contact.
*
* Parameters:
......@@ -462,14 +462,14 @@ converse.plugins.add('converse-roster', {
* (Function) errback - A function to call if an error occurred
*/
name = _.isEmpty(name)? jid: name;
const iq = $iq({type: 'set'})
.c('query', {xmlns: Strophe.NS.ROSTER})
const iq = $iq({'type': 'set'})
.c('query', {'xmlns': Strophe.NS.ROSTER})
.c('item', { jid, name });
_.each(groups, function (group) { iq.c('group').t(group).up(); });
_converse.connection.sendIQ(iq, callback, errback);
_.each(groups, group => iq.c('group').t(group).up());
_converse.api.sendIQ(iq);
},
addContactToRoster (jid, name, groups, attributes) {
async addContactToRoster (jid, name, groups, attributes) {
/* Adds a RosterContact instance to _converse.roster and
* registers the contact on the XMPP server.
* Returns a promise which is resolved once the XMPP server has
......@@ -481,27 +481,22 @@ converse.plugins.add('converse-roster', {
* (Array of Strings) groups - Any roster groups the user might belong to
* (Object) attributes - Any additional attributes to be stored on the user's model.
*/
return new Promise((resolve, reject) => {
groups = groups || [];
this.sendContactAddIQ(jid, name, groups,
() => {
const contact = this.create(_.assignIn({
try {
await this.sendContactAddIQ(jid, name, groups);
} catch (e) {
_converse.log(e, Strophe.LogLevel.ERROR);
alert(__('Sorry, there was an error while trying to add %1$s as a contact.', name));
return e;
}
return this.create(_.assignIn({
'ask': undefined,
'nickname': name,
groups,
jid,
'requesting': false,
'subscription': 'none'
}, attributes), {sort: false});
resolve(contact);
},
function (err) {
alert(__('Sorry, there was an error while trying to add %1$s as a contact.', name));
_converse.log(err, Strophe.LogLevel.ERROR);
resolve(err);
}
);
});
}, attributes), {'sort': false});
},
subscribeBack (bare_jid, presence) {
......@@ -570,24 +565,26 @@ converse.plugins.add('converse-roster', {
return _converse.api.disco.stream.getFeature('ver', 'urn:xmpp:features:rosterver') && this.data.get('version');
},
fetchFromServer () {
async fetchFromServer () {
/* Fetch the roster from the XMPP server */
return new Promise((resolve, reject) => {
const iq = $iq({
const stanza = $iq({
'type': 'get',
'id': _converse.connection.getUniqueId('roster')
}).c('query', {xmlns: Strophe.NS.ROSTER});
if (this.rosterVersioningSupported()) {
iq.attrs({'ver': this.data.get('version')});
}
const callback = _.flow(this.onReceivedFromServer.bind(this), resolve);
const errback = function (iq) {
const errmsg = "Error while trying to fetch roster from the server";
_converse.log(errmsg, Strophe.LogLevel.ERROR);
reject(new Error(errmsg));
stanza.attrs({'ver': this.data.get('version')});
}
let iq;
try {
iq = await _converse.api.sendIQ(stanza);
} catch (e) {
_converse.log(e, Strophe.LogLevel.ERROR);
return _converse.log(
"Error while trying to fetch roster from the server",
Strophe.LogLevel.ERROR
);
}
return _converse.connection.sendIQ(iq, callback, errback);
});
return this.onReceivedFromServer(iq);
},
onReceivedFromServer (iq) {
......
......@@ -56,7 +56,7 @@ converse.plugins.add('converse-vcard', {
});
function onVCardData (jid, iq, callback) {
async function onVCardData (jid, iq) {
const vcard = iq.querySelector('vCard');
let result = {};
if (!_.isNull(vcard)) {
......@@ -75,24 +75,10 @@ converse.plugins.add('converse-vcard', {
}
if (result.image) {
const buffer = u.base64ToArrayBuffer(result['image']);
crypto.subtle.digest('SHA-1', buffer)
.then(ab => {
const ab = await crypto.subtle.digest('SHA-1', buffer);
result['image_hash'] = u.arrayBufferToHex(ab);
if (callback) callback(result);
});
} else {
if (callback) callback(result);
}
}
function onVCardError (jid, iq, errback) {
if (errback) {
errback({
'stanza': iq,
'jid': jid,
'vcard_error': moment().format()
});
}
return result;
}
function createStanza (type, jid, vcard_el) {
......@@ -113,7 +99,7 @@ converse.plugins.add('converse-vcard', {
return _converse.api.sendIQ(createStanza("set", jid, vcard_el));
}
function getVCard (_converse, jid) {
async function getVCard (_converse, jid) {
/* Request the VCard of another user. Returns a promise.
*
* Parameters:
......@@ -121,14 +107,17 @@ converse.plugins.add('converse-vcard', {
* is being requested.
*/
const to = Strophe.getBareJidFromJid(jid) === _converse.bare_jid ? null : jid;
return new Promise((resolve, reject) => {
_converse.connection.sendIQ(
createStanza("get", to),
_.partial(onVCardData, jid, _, resolve),
_.partial(onVCardError, jid, _, resolve),
_converse.IQ_TIMEOUT
);
});
let iq;
try {
iq = await _converse.api.sendIQ(createStanza("get", to))
} catch (iq) {
return {
'stanza': iq,
'jid': jid,
'vcard_error': moment().format()
}
}
return onVCardData(jid, iq);
}
/* Event handlers */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment