diff --git a/.eslintrc.json b/.eslintrc.json
index ebee35649..0c61c2b72 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -30,7 +30,7 @@
"accessor-pairs": "error",
"array-bracket-spacing": "off",
"array-callback-return": "error",
- "arrow-body-style": "error",
+ "arrow-body-style": "off",
"arrow-parens": "error",
"arrow-spacing": "error",
"block-scoped-var": "off",
diff --git a/spec/disco.js b/spec/disco.js
index 1d216b316..74ec50ea3 100644
--- a/spec/disco.js
+++ b/spec/disco.js
@@ -20,7 +20,7 @@
var IQ_ids = _converse.connection.IQ_ids;
test_utils.waitUntil(function () {
return _.filter(IQ_stanzas, function (iq) {
- return iq.nodeTree.querySelector('query[xmlns="http://jabber.org/protocol/disco#info"]');
+ return iq.nodeTree.querySelector('iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]');
}).length > 0;
}, 300).then(function () {
/*
*
*/
- var info_IQ_id = IQ_ids[0];
- var stanza = $iq({
+ var stanza = _.filter(IQ_stanzas, function (iq) {
+ return iq.nodeTree.querySelector('iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]');
+ })[0];
+ var info_IQ_id = IQ_ids[IQ_stanzas.indexOf(stanza)];
+ stanza = $iq({
'type': 'result',
'from': 'localhost',
'to': 'dummy@localhost/resource',
@@ -79,92 +82,97 @@
'var': 'jabber:iq:version'});
_converse.connection._dataRecv(test_utils.createRequest(stanza));
- var entities = _converse.disco_entities;
- expect(entities.length).toBe(2); // We have an extra entity, which is the user's JID
- expect(entities.get(_converse.domain).features.length).toBe(5);
- expect(entities.get(_converse.domain).identities.length).toBe(3);
- expect(entities.get('localhost').features.where({'var': 'jabber:iq:version'}).length).toBe(1);
- expect(entities.get('localhost').features.where({'var': 'jabber:iq:time'}).length).toBe(1);
- expect(entities.get('localhost').features.where({'var': 'jabber:iq:register'}).length).toBe(1);
- expect(entities.get('localhost').features.where(
- {'var': 'http://jabber.org/protocol/disco#items'}).length).toBe(1);
- expect(entities.get('localhost').features.where(
- {'var': 'http://jabber.org/protocol/disco#info'}).length).toBe(1);
+ _converse.api.disco.entities.get().then(function (entities) {
+ expect(entities.length).toBe(2); // We have an extra entity, which is the user's JID
+ expect(entities.get(_converse.domain).features.length).toBe(5);
+ expect(entities.get(_converse.domain).identities.length).toBe(3);
+ expect(entities.get('localhost').features.where({'var': 'jabber:iq:version'}).length).toBe(1);
+ expect(entities.get('localhost').features.where({'var': 'jabber:iq:time'}).length).toBe(1);
+ expect(entities.get('localhost').features.where({'var': 'jabber:iq:register'}).length).toBe(1);
+ expect(entities.get('localhost').features.where(
+ {'var': 'http://jabber.org/protocol/disco#items'}).length).toBe(1);
+ expect(entities.get('localhost').features.where(
+ {'var': 'http://jabber.org/protocol/disco#info'}).length).toBe(1);
- test_utils.waitUntil(function () {
- // Converse.js sees that the entity has a disco#items feature,
- // so it will make a query for it.
- return _.filter(IQ_stanzas, function (iq) {
- return iq.nodeTree.querySelector('query[xmlns="http://jabber.org/protocol/disco#items"]');
- }).length > 0;
- }, 300).then(function () {
- /*
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- */
- var items_IQ_id = IQ_ids.pop();
- stanza = $iq({
- 'type': 'result',
- 'from': 'localhost',
- 'to': 'dummy@localhost/resource',
- 'id': items_IQ_id
- }).c('query', {'xmlns': 'http://jabber.org/protocol/disco#items'})
- .c('item', {
- 'jid': 'people.shakespeare.lit',
- 'name': 'Directory of Characters'}).up()
- .c('item', {
- 'jid': 'plays.shakespeare.lit',
- 'name': 'Play-Specific Chatrooms'}).up()
- .c('item', {
- 'jid': 'words.shakespeare.lit',
- 'name': 'Gateway to Marlowe IM'}).up()
- .c('item', {
- 'jid': 'localhost',
- 'name': 'Shakespearean Lexicon'}).up()
+ test_utils.waitUntil(function () {
+ // Converse.js sees that the entity has a disco#items feature,
+ // so it will make a query for it.
+ return _.filter(IQ_stanzas, function (iq) {
+ return iq.nodeTree.querySelector('query[xmlns="http://jabber.org/protocol/disco#items"]');
+ }).length > 0;
+ }, 300).then(function () {
+ /*
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+ var stanza = _.filter(IQ_stanzas, function (iq) {
+ return iq.nodeTree.querySelector('iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#items"]');
+ })[0];
+ var items_IQ_id = IQ_ids[IQ_stanzas.indexOf(stanza)];
+ stanza = $iq({
+ 'type': 'result',
+ 'from': 'localhost',
+ 'to': 'dummy@localhost/resource',
+ 'id': items_IQ_id
+ }).c('query', {'xmlns': 'http://jabber.org/protocol/disco#items'})
+ .c('item', {
+ 'jid': 'people.shakespeare.lit',
+ 'name': 'Directory of Characters'}).up()
+ .c('item', {
+ 'jid': 'plays.shakespeare.lit',
+ 'name': 'Play-Specific Chatrooms'}).up()
+ .c('item', {
+ 'jid': 'words.shakespeare.lit',
+ 'name': 'Gateway to Marlowe IM'}).up()
- .c('item', {
- 'jid': 'localhost',
- 'node': 'books',
- 'name': 'Books by and about Shakespeare'}).up()
- .c('item', {
- 'node': 'localhost',
- 'name': 'Wear your literary taste with pride'}).up()
- .c('item', {
- 'jid': 'localhost',
- 'node': 'music',
- 'name': 'Music from the time of Shakespeare'
- });
- _converse.connection._dataRecv(test_utils.createRequest(stanza));
+ .c('item', {
+ 'jid': 'localhost',
+ 'node': 'books',
+ 'name': 'Books by and about Shakespeare'}).up()
+ .c('item', {
+ 'node': 'localhost',
+ 'name': 'Wear your literary taste with pride'}).up()
+ .c('item', {
+ 'jid': 'localhost',
+ 'node': 'music',
+ 'name': 'Music from the time of Shakespeare'
+ });
+ _converse.connection._dataRecv(test_utils.createRequest(stanza));
- entities = _converse.disco_entities;
- expect(entities.length).toBe(5); // We have an extra entity, which is the user's JID
- 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();
- });
+ entities = _converse.disco_entities;
+ expect(entities.length).toBe(2); // We have an extra entity, which is the user's JID
+ expect(entities.get(_converse.domain).items.length).toBe(3);
+ expect(_.includes(entities.get(_converse.domain).items.pluck('jid'), 'people.shakespeare.lit')).toBeTruthy();
+ expect(_.includes(entities.get(_converse.domain).items.pluck('jid'), 'plays.shakespeare.lit')).toBeTruthy();
+ expect(_.includes(entities.get(_converse.domain).items.pluck('jid'), '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();
+ });
+ });
});
}));
});
diff --git a/spec/http-file-upload.js b/spec/http-file-upload.js
index 61cb34622..ee2d750ba 100644
--- a/spec/http-file-upload.js
+++ b/spec/http-file-upload.js
@@ -10,6 +10,7 @@
var Strophe = converse.env.Strophe;
var $iq = converse.env.$iq;
var _ = converse.env._;
+ var f = converse.env.f;
describe("XEP-0363: HTTP File Upload", function () {
@@ -18,135 +19,171 @@
it("is done automatically", mock.initConverseWithAsync(function (done, _converse) {
var IQ_stanzas = _converse.connection.IQ_stanzas;
var IQ_ids = _converse.connection.IQ_ids;
- test_utils.waitUntil(function () {
- return _.filter(IQ_stanzas, function (iq) {
- return iq.nodeTree.querySelector('query[xmlns="http://jabber.org/protocol/disco#info"]');
- }).length > 0;
- }, 300).then(function () {
- /*
- *
- *
- *
- *
- *
- *
- */
- var info_IQ_id = IQ_ids[0];
- var stanza = $iq({
+
+ test_utils.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, [], []).then(function () {
+ test_utils.waitUntil(function () {
+ return _.filter(IQ_stanzas, function (iq) {
+ return iq.nodeTree.querySelector('iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]');
+ }).length > 0;
+ }, 300).then(function () {
+ /*
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+ var stanza = _.filter(IQ_stanzas, function (iq) {
+ return iq.nodeTree.querySelector('iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]');
+ })[0];
+ var info_IQ_id = IQ_ids[IQ_stanzas.indexOf(stanza)];
+
+ stanza = $iq({
+ 'type': 'result',
+ 'from': 'localhost',
+ 'to': 'dummy@localhost/resource',
+ 'id': info_IQ_id
+ }).c('query', {'xmlns': 'http://jabber.org/protocol/disco#info'})
+ .c('identity', {
+ 'category': 'server',
+ 'type': 'im'}).up()
+ .c('feature', {
+ 'var': 'http://jabber.org/protocol/disco#info'}).up()
+ .c('feature', {
+ 'var': 'http://jabber.org/protocol/disco#items'});
+ _converse.connection._dataRecv(test_utils.createRequest(stanza));
+
+ _converse.api.disco.entities.get().then(function(entities) {
+ expect(entities.length).toBe(2);
+ expect(_.includes(entities.pluck('jid'), 'localhost')).toBe(true);
+ expect(_.includes(entities.pluck('jid'), 'dummy@localhost')).toBe(true);
+
+ expect(entities.get(_converse.domain).features.length).toBe(2);
+ expect(entities.get(_converse.domain).identities.length).toBe(1);
+
+ return test_utils.waitUntil(function () {
+ // Converse.js sees that the entity has a disco#items feature,
+ // so it will make a query for it.
+ return _.filter(IQ_stanzas, function (iq) {
+ return iq.nodeTree.querySelector('iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#items"]');
+ }).length > 0;
+ }, 300);
+ });
+ }).then(function () {
+ /*
+ *
+ *
+ *
+ *
+ *
+ */
+ var stanza = _.filter(IQ_stanzas, function (iq) {
+ return iq.nodeTree.querySelector('iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#items"]');
+ })[0];
+ var items_IQ_id = IQ_ids[IQ_stanzas.indexOf(stanza)];
+ stanza = $iq({
'type': 'result',
'from': 'localhost',
'to': 'dummy@localhost/resource',
- 'id': info_IQ_id
- }).c('query', {'xmlns': 'http://jabber.org/protocol/disco#info'})
- .c('identity', {
- 'category': 'server',
- 'type': 'im'}).up()
- .c('feature', {
- 'var': 'http://jabber.org/protocol/disco#info'}).up()
- .c('feature', {
- 'var': 'http://jabber.org/protocol/disco#items'});
- _converse.connection._dataRecv(test_utils.createRequest(stanza));
+ 'id': items_IQ_id
+ }).c('query', {'xmlns': 'http://jabber.org/protocol/disco#items'})
+ .c('item', {
+ 'jid': 'upload.localhost',
+ 'name': 'HTTP File Upload'});
+ _converse.connection._dataRecv(test_utils.createRequest(stanza));
- var entities = _converse.disco_entities;
- expect(entities.length).toBe(2); // We have an extra entity, which is the user's JID
- expect(entities.get(_converse.domain).features.length).toBe(2);
- expect(entities.get(_converse.domain).identities.length).toBe(1);
-
- return test_utils.waitUntil(function () {
- // Converse.js sees that the entity has a disco#items feature,
- // so it will make a query for it.
- return _.filter(IQ_stanzas, function (iq) {
- return iq.nodeTree.querySelector('query[xmlns="http://jabber.org/protocol/disco#items"]');
- }).length > 0;
- }, 300);
- }).then(function () {
- /*
- *
- *
- *
- *
- *
- */
- var items_IQ_id = IQ_ids[IQ_ids.length-1];
- var stanza = $iq({
- 'type': 'result',
- 'from': 'localhost',
- 'to': 'dummy@localhost/resource',
- 'id': items_IQ_id
- }).c('query', {'xmlns': 'http://jabber.org/protocol/disco#items'})
- .c('item', {
- 'jid': 'upload.localhost',
- 'name': 'HTTP File Upload'}).up()
- .c('item', {
- 'jid': 'conference.localhost',
- 'name': 'Chatrooms Service'});
- _converse.connection._dataRecv(test_utils.createRequest(stanza));
-
- var entities = _converse.disco_entities;
- expect(entities.length).toBe(4); // We have an extra entity, which is the user's JID
-
- return test_utils.waitUntil(function () {
- // Converse.js sees that the entity has a disco#items feature,
- // so it will make a query for it.
- return _.filter(IQ_stanzas, function (iq) {
+ _converse.api.disco.entities.get().then(function (entities) {
+ expect(entities.length).toBe(2);
+ expect(entities.get('localhost').items.length).toBe(1);
+ return test_utils.waitUntil(function () {
+ // Converse.js sees that the entity has a disco#info feature,
+ // so it will make a query for it.
+ return _.filter(IQ_stanzas, function (iq) {
+ return iq.nodeTree.querySelector('iq[to="upload.localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]');
+ }).length > 0;
+ }, 300);
+ });
+ }).then(function () {
+ var stanza = _.filter(IQ_stanzas, function (iq) {
return iq.nodeTree.querySelector('iq[to="upload.localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]');
- }).length > 0;
- }, 300);
- }).then(function () {
- var stanza = _.filter(IQ_stanzas, function (iq) {
- return iq.nodeTree.querySelector('iq[to="upload.localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]');
- })[0];
- var IQ_id = IQ_ids[IQ_stanzas.indexOf(stanza)];
- expect(stanza.toLocaleString()).toBe(
- ""+
- ""+
- "");
+ })[0];
+ var IQ_id = IQ_ids[IQ_stanzas.indexOf(stanza)];
+ expect(stanza.toLocaleString()).toBe(
+ ""+
+ ""+
+ "");
- // Upload service responds and reports a maximum file size of 5MiB
- /*
- *
- *
- *
- *
- *
- * urn:xmpp:http:upload:0
- *
- *
- * 5242880
- *
- *
- *
- *
- */
- stanza = $iq({'type': 'result', 'to': 'dummy@localhost/resource', 'id': IQ_id, 'from': 'upload.localhost'})
- .c('query', {'xmlns': 'http://jabber.org/protocol/disco#info'})
- .c('identity', {'category':'store', 'type':'file', 'name':'HTTP File Upload'}).up()
- .c('feature', {'var':'urn:xmpp:http:upload:0'}).up()
- .c('x', {'type':'result', 'xmlns':'jabber:x:data'})
- .c('field', {'var':'FORM_TYPE', 'type':'hidden'})
- .c('value').t('urn:xmpp:http:upload:0').up().up()
- .c('field', {'var':'max-file-size'})
- .c('value').t('5242880');
- _converse.connection._dataRecv(test_utils.createRequest(stanza));
+ // Upload service responds and reports a maximum file size of 5MiB
+ /*
+ *
+ *
+ *
+ *
+ *
+ * urn:xmpp:http:upload:0
+ *
+ *
+ * 5242880
+ *
+ *
+ *
+ *
+ */
+ stanza = $iq({'type': 'result', 'to': 'dummy@localhost/resource', 'id': IQ_id, 'from': 'upload.localhost'})
+ .c('query', {'xmlns': 'http://jabber.org/protocol/disco#info'})
+ .c('identity', {'category':'store', 'type':'file', 'name':'HTTP File Upload'}).up()
+ .c('feature', {'var':'urn:xmpp:http:upload:0'}).up()
+ .c('x', {'type':'result', 'xmlns':'jabber:x:data'})
+ .c('field', {'var':'FORM_TYPE', 'type':'hidden'})
+ .c('value').t('urn:xmpp:http:upload:0').up().up()
+ .c('field', {'var':'max-file-size'})
+ .c('value').t('5242880');
+ _converse.connection._dataRecv(test_utils.createRequest(stanza));
- var entities = _converse.disco_entities;
- expect(entities.get('upload.localhost').identities.where({'category': 'store'}).length).toBe(1);
- done();
+ _converse.api.disco.entities.get().then(function (entities) {
+ expect(entities.get('localhost').items.get('upload.localhost').identities.where({'category': 'store'}).length).toBe(1);
+ _converse.api.disco.supports(Strophe.NS.HTTPUPLOAD, _converse.domain).then(
+ function (result) {
+ expect(result.length).toBe(1);
+ expect(result[0].get('jid')).toBe('upload.localhost');
+ done();
+ }
+ );
+ }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+ })
})
}));
});
+
+ describe("When supported", function () {
+
+ describe("A file upload toolbar button", function () {
+
+ it("appears in private chats", mock.initConverseWithAsync(function (done, _converse) {
+ test_utils.createContacts(_converse, 'current');
+ var contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost';
+ test_utils.openChatBoxFor(_converse, contact_jid);
+ done();
+ }));
+
+ it("appears in MUC chats", mock.initConverseWithAsync(function (done, _converse) {
+ done();
+ }));
+ });
+ });
});
}));
diff --git a/spec/mam.js b/spec/mam.js
index e4219d0d4..6d56011b3 100644
--- a/spec/mam.js
+++ b/spec/mam.js
@@ -69,507 +69,593 @@
done();
}));
- it("can be used to query for all messages to/from a particular JID", mock.initConverse(function (_converse) {
- var sent_stanza, IQ_id;
- var 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);
- });
- if (!_converse.disco_entities.get(_converse.domain).features.findWhere({'var': Strophe.NS.MAM})) {
- _converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
- }
- _converse.api.archive.query({'with':'juliet@capulet.lit'});
- var queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
- expect(sent_stanza.toString()).toBe(
- ""+
- ""+
- ""+
- ""+
- "urn:xmpp:mam:2"+
- ""+
- ""+
- "juliet@capulet.lit"+
- ""+
- ""+
- ""+
- ""
- );
- }));
+ it("can be used to query for all messages to/from a particular JID",
+ mock.initConverseWithPromises(
+ null, [], {},
+ function (done, _converse) {
- it("can be used to query for archived messages from a chat room", mock.initConverse(function (_converse) {
- if (!_converse.disco_entities.get(_converse.domain).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;
- 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');
-
- _converse.api.archive.query({'with': 'coven@chat.shakespeare.lit', 'groupchat': true}, callback);
- var queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
-
- expect(sent_stanza.toString()).toBe(
- ""+
- ""+
- ""+
- ""+
- "urn:xmpp:mam:2"+
- ""+
- ""+
- ""+
- "");
- }));
-
- it("checks whether returned MAM messages from a MUC room are from the right JID", mock.initConverse(function (_converse) {
- if (!_converse.disco_entities.get(_converse.domain).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;
- 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');
-
- _converse.api.archive.query({'with': 'coven@chat.shakespear.lit', 'groupchat': true, 'max':'10'}, callback);
- var queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
-
- /*
- *
- *
- *
- *
- * Thrice the brinded cat hath mew'd.
- *
- *
- *
- *
- *
- *
- *
- */
- var msg1 = $msg({'id':'iasd207', 'from': 'other@chat.shakespear.lit', 'to': 'dummy@localhost'})
- .c('result', {'xmlns': 'urn:xmpp:mam:2', 'queryid':queryid, 'id':'34482-21985-73620'})
- .c('forwarded', {'xmlns':'urn:xmpp:forward:0'})
- .c('delay', {'xmlns':'urn:xmpp:delay', 'stamp':'2010-07-10T23:08:25Z'}).up()
- .c('message', {
- 'xmlns':'jabber:client',
- 'to':'dummy@localhost',
- 'id':'162BEBB1-F6DB-4D9A-9BD8-CFDCC801A0B2',
- 'from':'coven@chat.shakespeare.lit/firstwitch',
- 'type':'groupchat' })
- .c('body').t("Thrice the brinded cat hath mew'd.");
- _converse.connection._dataRecv(test_utils.createRequest(msg1));
-
- /* Send an stanza to indicate the end of the result set.
- *
- *
- *
- *
- * 28482-98726-73623
- * 09af3-cc343-b409f
- * 20
- *
- *
- */
- var 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()
- .c('last').t('09af3-cc343-b409f').up()
- .c('count').t('16');
- _converse.connection._dataRecv(test_utils.createRequest(stanza));
-
- expect(callback).toHaveBeenCalled();
- var args = callback.calls.argsFor(0);
- expect(args[0].length).toBe(0);
- }));
-
- it("can be used to query for all messages in a certain timespan", mock.initConverse(function (_converse) {
- var sent_stanza, IQ_id;
- var 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);
- });
- if (!_converse.disco_entities.get(_converse.domain).features.findWhere({'var': Strophe.NS.MAM})) {
- _converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
- }
- var start = '2010-06-07T00:00:00Z';
- var end = '2010-07-07T13:23:54Z';
- _converse.api.archive.query({
- 'start': start,
- 'end': end
-
- });
- var queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
- expect(sent_stanza.toString()).toBe(
- ""+
- ""+
- ""+
- ""+
- "urn:xmpp:mam:2"+
- ""+
- ""+
- ""+moment(start).format()+""+
- ""+
- ""+
- ""+moment(end).format()+""+
- ""+
- ""+
- ""+
- ""
- );
- }));
-
- it("throws a TypeError if an invalid date is provided", mock.initConverse(function (_converse) {
- if (!_converse.disco_entities.get(_converse.domain).features.findWhere({'var': Strophe.NS.MAM})) {
- _converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
- }
- expect(_.partial(_converse.api.archive.query, {'start': 'not a real date'})).toThrow(
- new TypeError('archive.query: invalid date provided for: start')
- );
- }));
-
- it("can be used to query for all messages after a certain time", mock.initConverse(function (_converse) {
- var sent_stanza, IQ_id;
- var 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);
- });
- if (!_converse.disco_entities.get(_converse.domain).features.findWhere({'var': Strophe.NS.MAM})) {
- _converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
- }
- var start = '2010-06-07T00:00:00Z';
- _converse.api.archive.query({'start': start});
- var queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
- expect(sent_stanza.toString()).toBe(
- ""+
- ""+
- ""+
- ""+
- "urn:xmpp:mam:2"+
- ""+
- ""+
- ""+moment(start).format()+""+
- ""+
- ""+
- ""+
- ""
- );
- }));
-
- it("can be used to query for a limited set of results", mock.initConverse(function (_converse) {
- var sent_stanza, IQ_id;
- var 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);
- });
- if (!_converse.disco_entities.get(_converse.domain).features.findWhere({'var': Strophe.NS.MAM})) {
- _converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
- }
- var start = '2010-06-07T00:00:00Z';
- _converse.api.archive.query({'start': start, 'max':10});
- var queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
- expect(sent_stanza.toString()).toBe(
- ""+
- ""+
- ""+
- ""+
- "urn:xmpp:mam:2"+
- ""+
- ""+
- ""+moment(start).format()+""+
- ""+
- ""+
- ""+
- "10"+
- ""+
- ""+
- ""
- );
- }));
-
- it("can be used to page through results", mock.initConverse(function (_converse) {
- var sent_stanza, IQ_id;
- var 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);
- });
- if (!_converse.disco_entities.get(_converse.domain).features.findWhere({'var': Strophe.NS.MAM})) {
- _converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
- }
- var start = '2010-06-07T00:00:00Z';
- _converse.api.archive.query({
- 'start': start,
- 'after': '09af3-cc343-b409f',
- 'max':10
- });
- var queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
- expect(sent_stanza.toString()).toBe(
- ""+
- ""+
- ""+
- ""+
- "urn:xmpp:mam:2"+
- ""+
- ""+
- ""+moment(start).format()+""+
- ""+
- ""+
- ""+
- "10"+
- "09af3-cc343-b409f"+
- ""+
- ""+
- ""
- );
- }));
-
- it("accepts \"before\" with an empty string as value to reverse the order", mock.initConverse(function (_converse) {
- var sent_stanza, IQ_id;
- var 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);
- });
- if (!_converse.disco_entities.get(_converse.domain).features.findWhere({'var': Strophe.NS.MAM})) {
- _converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
- }
- _converse.api.archive.query({'before': '', 'max':10});
- var queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
- expect(sent_stanza.toString()).toBe(
- ""+
- ""+
- ""+
- ""+
- "urn:xmpp:mam:2"+
- ""+
- ""+
- ""+
- "10"+
- ""+
- ""+
- ""+
- ""
- );
- }));
-
- it("accepts a Strophe.RSM object for the query options", mock.initConverse(function (_converse) {
- // Normally the user wouldn't manually make a Strophe.RSM object
- // and pass it in. However, in the callback method an RSM object is
- // returned which can be reused for easy paging. This test is
- // more for that usecase.
- if (!_converse.disco_entities.get(_converse.domain).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;
- spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
- sent_stanza = iq;
- IQ_id = sendIQ.bind(this)(iq, callback, errback);
- });
- var rsm = new Strophe.RSM({'max': '10'});
- rsm['with'] = 'romeo@montague.lit'; // eslint-disable-line dot-notation
- rsm.start = '2010-06-07T00:00:00Z';
- _converse.api.archive.query(rsm);
-
- var queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
- expect(sent_stanza.toString()).toBe(
- ""+
- ""+
- ""+
+ _converse.api.disco.entities.get(_converse.domain).then(function (entity) {
+ 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;
+ spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
+ sent_stanza = iq;
+ IQ_id = sendIQ.bind(this)(iq, callback, errback);
+ });
+ _converse.api.archive.query({'with':'juliet@capulet.lit'});
+ var queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
+ expect(sent_stanza.toString()).toBe(
+ ""+
+ ""+
+ ""+
""+
"urn:xmpp:mam:2"+
""+
""+
- "romeo@montague.lit"+
+ "juliet@capulet.lit"+
""+
- ""+
- ""+moment(rsm.start).format()+""+
- ""+
- ""+
- ""+
- "10"+
- ""+
- ""+
- ""
- );
+ ""+
+ ""+
+ ""
+ );
+ done();
+ });
+ }));
+
+ it("can be used to query for archived messages from a chat room",
+ mock.initConverseWithPromises(
+ null, [], {},
+ function (done, _converse) {
+
+ _converse.api.disco.entities.get(_converse.domain).then(function (entity) {
+ 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;
+ 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');
+
+ _converse.api.archive.query({'with': 'coven@chat.shakespeare.lit', 'groupchat': true}, callback);
+ var queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
+
+ expect(sent_stanza.toString()).toBe(
+ ""+
+ ""+
+ ""+
+ ""+
+ "urn:xmpp:mam:2"+
+ ""+
+ ""+
+ ""+
+ "");
+ done();
+ });
}));
- it("accepts a callback function, which it passes the messages and a Strophe.RSM object", mock.initConverse(function (_converse) {
- if (!_converse.disco_entities.get(_converse.domain).features.findWhere({'var': Strophe.NS.MAM})) {
- _converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
- }
+ it("checks whether returned MAM messages from a MUC room are from the right JID",
+ mock.initConverseWithPromises(
+ null, [], {},
+ function (done, _converse) {
+
+ _converse.api.disco.entities.get(_converse.domain).then(function (entity) {
+ 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;
+ 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');
+
+ _converse.api.archive.query({'with': 'coven@chat.shakespear.lit', 'groupchat': true, 'max':'10'}, callback);
+ var queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
+
+ /*
+ *
+ *
+ *
+ *
+ * Thrice the brinded cat hath mew'd.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+ var msg1 = $msg({'id':'iasd207', 'from': 'other@chat.shakespear.lit', 'to': 'dummy@localhost'})
+ .c('result', {'xmlns': 'urn:xmpp:mam:2', 'queryid':queryid, 'id':'34482-21985-73620'})
+ .c('forwarded', {'xmlns':'urn:xmpp:forward:0'})
+ .c('delay', {'xmlns':'urn:xmpp:delay', 'stamp':'2010-07-10T23:08:25Z'}).up()
+ .c('message', {
+ 'xmlns':'jabber:client',
+ 'to':'dummy@localhost',
+ 'id':'162BEBB1-F6DB-4D9A-9BD8-CFDCC801A0B2',
+ 'from':'coven@chat.shakespeare.lit/firstwitch',
+ 'type':'groupchat' })
+ .c('body').t("Thrice the brinded cat hath mew'd.");
+ _converse.connection._dataRecv(test_utils.createRequest(msg1));
+
+ /* Send an stanza to indicate the end of the result set.
+ *
+ *
+ *
+ *
+ * 28482-98726-73623
+ * 09af3-cc343-b409f
+ * 20
+ *
+ *
+ */
+ var 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()
+ .c('last').t('09af3-cc343-b409f').up()
+ .c('count').t('16');
+ _converse.connection._dataRecv(test_utils.createRequest(stanza));
+
+ 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",
+ mock.initConverseWithPromises(
+ null, [], {},
+ function (done, _converse) {
+
var sent_stanza, IQ_id;
var 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');
+ _converse.api.disco.entities.get().then(function (entities) {
+ if (!entities.get(_converse.domain).features.findWhere({'var': Strophe.NS.MAM})) {
+ _converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
+ }
+ var start = '2010-06-07T00:00:00Z';
+ var end = '2010-07-07T13:23:54Z';
+ _converse.api.archive.query({
+ 'start': start,
+ 'end': end
- _converse.api.archive.query({'with': 'romeo@capulet.lit', 'max':'10'}, callback);
- var queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
-
- /*
- *
- *
- *
- *
- * Call me but love, and I'll be new baptized; Henceforth I never will be Romeo.
- *
- *
- *
- *
- */
- var msg1 = $msg({'id':'aeb213', 'to':'juliet@capulet.lit/chamber'})
- .c('result', {'xmlns': 'urn:xmpp:mam:2', 'queryid':queryid, 'id':'28482-98726-73623'})
- .c('forwarded', {'xmlns':'urn:xmpp:forward:0'})
- .c('delay', {'xmlns':'urn:xmpp:delay', 'stamp':'2010-07-10T23:08:25Z'}).up()
- .c('message', {
- 'xmlns':'jabber:client',
- 'to':'juliet@capulet.lit/balcony',
- 'from':'romeo@montague.lit/orchard',
- 'type':'chat' })
- .c('body').t("Call me but love, and I'll be new baptized;");
- _converse.connection._dataRecv(test_utils.createRequest(msg1));
-
- var msg2 = $msg({'id':'aeb213', 'to':'juliet@capulet.lit/chamber'})
- .c('result', {'xmlns': 'urn:xmpp:mam:2', 'queryid':queryid, 'id':'28482-98726-73624'})
- .c('forwarded', {'xmlns':'urn:xmpp:forward:0'})
- .c('delay', {'xmlns':'urn:xmpp:delay', 'stamp':'2010-07-10T23:08:25Z'}).up()
- .c('message', {
- 'xmlns':'jabber:client',
- 'to':'juliet@capulet.lit/balcony',
- 'from':'romeo@montague.lit/orchard',
- 'type':'chat' })
- .c('body').t("Henceforth I never will be Romeo.");
- _converse.connection._dataRecv(test_utils.createRequest(msg2));
-
- /* Send an stanza to indicate the end of the result set.
- *
- *
- *
- *
- * 28482-98726-73623
- * 09af3-cc343-b409f
- * 20
- *
- *
- */
- var 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()
- .c('last').t('09af3-cc343-b409f').up()
- .c('count').t('16');
- _converse.connection._dataRecv(test_utils.createRequest(stanza));
-
- expect(callback).toHaveBeenCalled();
- var args = callback.calls.argsFor(0);
- expect(args[0].length).toBe(2);
- expect(args[0][0].outerHTML).toBe(msg1.nodeTree.outerHTML);
- expect(args[0][1].outerHTML).toBe(msg2.nodeTree.outerHTML);
- expect(args[1]['with']).toBe('romeo@capulet.lit'); // eslint-disable-line dot-notation
- expect(args[1].max).toBe('10');
- expect(args[1].count).toBe('16');
- expect(args[1].first).toBe('23452-4534-1');
- expect(args[1].last).toBe('09af3-cc343-b409f');
+ });
+ var queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
+ expect(sent_stanza.toString()).toBe(
+ ""+
+ ""+
+ ""+
+ ""+
+ "urn:xmpp:mam:2"+
+ ""+
+ ""+
+ ""+moment(start).format()+""+
+ ""+
+ ""+
+ ""+moment(end).format()+""+
+ ""+
+ ""+
+ ""+
+ ""
+ );
+ done();
+ });
}));
+ it("throws a TypeError if an invalid date is provided",
+ mock.initConverseWithPromises(
+ null, [], {},
+ function (done, _converse) {
+
+ _converse.api.disco.entities.get(_converse.domain).then(function (entity) {
+ if (!entity.features.findWhere({'var': Strophe.NS.MAM})) {
+ _converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
+ }
+ expect(_.partial(_converse.api.archive.query, {'start': 'not a real date'})).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.initConverseWithPromises(
+ null, [], {},
+ function (done, _converse) {
+
+ _converse.api.disco.entities.get(_converse.domain).then(function (entity) {
+ 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;
+ spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
+ sent_stanza = iq;
+ IQ_id = sendIQ.bind(this)(iq, callback, errback);
+ });
+ if (!_converse.disco_entities.get(_converse.domain).features.findWhere({'var': Strophe.NS.MAM})) {
+ _converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
+ }
+ var start = '2010-06-07T00:00:00Z';
+ _converse.api.archive.query({'start': start});
+ var queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
+ expect(sent_stanza.toString()).toBe(
+ ""+
+ ""+
+ ""+
+ ""+
+ "urn:xmpp:mam:2"+
+ ""+
+ ""+
+ ""+moment(start).format()+""+
+ ""+
+ ""+
+ ""+
+ ""
+ );
+ done();
+ });
+ }));
+
+ it("can be used to query for a limited set of results",
+ mock.initConverseWithPromises(
+ null, [], {},
+ function (done, _converse) {
+
+ _converse.api.disco.entities.get(_converse.domain).then(function (entity) {
+ 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;
+ spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
+ sent_stanza = iq;
+ IQ_id = sendIQ.bind(this)(iq, callback, errback);
+ });
+ var start = '2010-06-07T00:00:00Z';
+ _converse.api.archive.query({'start': start, 'max':10});
+ var queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
+ expect(sent_stanza.toString()).toBe(
+ ""+
+ ""+
+ ""+
+ ""+
+ "urn:xmpp:mam:2"+
+ ""+
+ ""+
+ ""+moment(start).format()+""+
+ ""+
+ ""+
+ ""+
+ "10"+
+ ""+
+ ""+
+ ""
+ );
+ done();
+ });
+ }));
+
+ it("can be used to page through results",
+ mock.initConverseWithPromises(
+ null, [], {},
+ function (done, _converse) {
+
+ _converse.api.disco.entities.get(_converse.domain).then(function (entity) {
+ 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;
+ spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
+ sent_stanza = iq;
+ IQ_id = sendIQ.bind(this)(iq, callback, errback);
+ });
+ var start = '2010-06-07T00:00:00Z';
+ _converse.api.archive.query({
+ 'start': start,
+ 'after': '09af3-cc343-b409f',
+ 'max':10
+ });
+ var queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
+ expect(sent_stanza.toString()).toBe(
+ ""+
+ ""+
+ ""+
+ ""+
+ "urn:xmpp:mam:2"+
+ ""+
+ ""+
+ ""+moment(start).format()+""+
+ ""+
+ ""+
+ ""+
+ "10"+
+ "09af3-cc343-b409f"+
+ ""+
+ ""+
+ ""
+ );
+ done();
+ });
+ }));
+
+ it("accepts \"before\" with an empty string as value to reverse the order",
+ mock.initConverseWithPromises(
+ null, [], {},
+ function (done, _converse) {
+
+ _converse.api.disco.entities.get(_converse.domain).then(function (entity) {
+ 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;
+ spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
+ sent_stanza = iq;
+ IQ_id = sendIQ.bind(this)(iq, callback, errback);
+ });
+ _converse.api.archive.query({'before': '', 'max':10});
+ var queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
+ expect(sent_stanza.toString()).toBe(
+ ""+
+ ""+
+ ""+
+ ""+
+ "urn:xmpp:mam:2"+
+ ""+
+ ""+
+ ""+
+ "10"+
+ ""+
+ ""+
+ ""+
+ ""
+ );
+ done();
+ });
+ }));
+
+ it("accepts a Strophe.RSM object for the query options",
+ mock.initConverseWithPromises(
+ null, [], {},
+ function (done, _converse) {
+
+ _converse.api.disco.entities.get(_converse.domain).then(function (entity) {
+ 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;
+ spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
+ sent_stanza = iq;
+ IQ_id = sendIQ.bind(this)(iq, callback, errback);
+ });
+ // Normally the user wouldn't manually make a Strophe.RSM object
+ // and pass it in. However, in the callback method an RSM object is
+ // returned which can be reused for easy paging. This test is
+ // more for that usecase.
+ var rsm = new Strophe.RSM({'max': '10'});
+ rsm['with'] = 'romeo@montague.lit'; // eslint-disable-line dot-notation
+ rsm.start = '2010-06-07T00:00:00Z';
+ _converse.api.archive.query(rsm);
+
+ var queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
+ expect(sent_stanza.toString()).toBe(
+ ""+
+ ""+
+ ""+
+ ""+
+ "urn:xmpp:mam:2"+
+ ""+
+ ""+
+ "romeo@montague.lit"+
+ ""+
+ ""+
+ ""+moment(rsm.start).format()+""+
+ ""+
+ ""+
+ ""+
+ "10"+
+ ""+
+ ""+
+ ""
+ );
+ done();
+ });
+ }));
+
+ it("accepts a callback function, which it passes the messages and a Strophe.RSM object",
+ mock.initConverseWithPromises(
+ null, [], {},
+ function (done, _converse) {
+
+ _converse.api.disco.entities.get(_converse.domain).then(function (entity) {
+ 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;
+ 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');
+
+ _converse.api.archive.query({'with': 'romeo@capulet.lit', 'max':'10'}, callback);
+ var queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
+
+ /*
+ *
+ *
+ *
+ *
+ * Call me but love, and I'll be new baptized; Henceforth I never will be Romeo.
+ *
+ *
+ *
+ *
+ */
+ var msg1 = $msg({'id':'aeb213', 'to':'juliet@capulet.lit/chamber'})
+ .c('result', {'xmlns': 'urn:xmpp:mam:2', 'queryid':queryid, 'id':'28482-98726-73623'})
+ .c('forwarded', {'xmlns':'urn:xmpp:forward:0'})
+ .c('delay', {'xmlns':'urn:xmpp:delay', 'stamp':'2010-07-10T23:08:25Z'}).up()
+ .c('message', {
+ 'xmlns':'jabber:client',
+ 'to':'juliet@capulet.lit/balcony',
+ 'from':'romeo@montague.lit/orchard',
+ 'type':'chat' })
+ .c('body').t("Call me but love, and I'll be new baptized;");
+ _converse.connection._dataRecv(test_utils.createRequest(msg1));
+
+ var msg2 = $msg({'id':'aeb213', 'to':'juliet@capulet.lit/chamber'})
+ .c('result', {'xmlns': 'urn:xmpp:mam:2', 'queryid':queryid, 'id':'28482-98726-73624'})
+ .c('forwarded', {'xmlns':'urn:xmpp:forward:0'})
+ .c('delay', {'xmlns':'urn:xmpp:delay', 'stamp':'2010-07-10T23:08:25Z'}).up()
+ .c('message', {
+ 'xmlns':'jabber:client',
+ 'to':'juliet@capulet.lit/balcony',
+ 'from':'romeo@montague.lit/orchard',
+ 'type':'chat' })
+ .c('body').t("Henceforth I never will be Romeo.");
+ _converse.connection._dataRecv(test_utils.createRequest(msg2));
+
+ /* Send an stanza to indicate the end of the result set.
+ *
+ *
+ *
+ *
+ * 28482-98726-73623
+ * 09af3-cc343-b409f
+ * 20
+ *
+ *
+ */
+ var 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()
+ .c('last').t('09af3-cc343-b409f').up()
+ .c('count').t('16');
+ _converse.connection._dataRecv(test_utils.createRequest(stanza));
+
+ expect(callback).toHaveBeenCalled();
+ var args = callback.calls.argsFor(0);
+ expect(args[0].length).toBe(2);
+ expect(args[0][0].outerHTML).toBe(msg1.nodeTree.outerHTML);
+ expect(args[0][1].outerHTML).toBe(msg2.nodeTree.outerHTML);
+ expect(args[1]['with']).toBe('romeo@capulet.lit'); // eslint-disable-line dot-notation
+ expect(args[1].max).toBe('10');
+ expect(args[1].count).toBe('16');
+ expect(args[1].first).toBe('23452-4534-1');
+ expect(args[1].last).toBe('09af3-cc343-b409f');
+ done()
+ });
+ }));
});
describe("The default preference", function () {
- it("is set once server support for MAM has been confirmed", mock.initConverse(function (_converse) {
- var sent_stanza, IQ_id;
- var 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);
+ it("is set once server support for MAM has been confirmed",
+ mock.initConverseWithPromises(
+ null, [], {},
+ function (done, _converse) {
+
+ _converse.api.disco.entities.get(_converse.domain).then(function (entity) {
+ var sent_stanza, IQ_id;
+ var 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);
+ });
+ spyOn(_converse, 'onMAMPreferences').and.callThrough();
+ _converse.message_archiving = 'never';
+
+ var feature = new Backbone.Model({
+ 'var': Strophe.NS.MAM
+ });
+ spyOn(feature, 'save').and.callFake(feature.set); // Save will complain about a url not being set
+
+ entity.onFeatureAdded(feature);
+
+ expect(_converse.connection.sendIQ).toHaveBeenCalled();
+ expect(sent_stanza.toLocaleString()).toBe(
+ ""+
+ ""+
+ ""
+ );
+
+ /* Example 20. Server responds with current preferences
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+ var 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));
+
+ expect(_converse.onMAMPreferences).toHaveBeenCalled();
+ expect(_converse.connection.sendIQ.calls.count()).toBe(2);
+
+ expect(sent_stanza.toString()).toBe(
+ ""+
+ ""+
+ "romeo@montague.lit"+
+ "montague@montague.lit"+
+ ""+
+ ""
+ );
+
+ expect(feature.get('preference')).toBe(undefined);
+ /*
+ *
+ *
+ * romeo@montague.lit
+ *
+ *
+ * montague@montague.lit
+ *
+ *
+ *
+ */
+ stanza = $iq({'type': 'result', 'id': IQ_id})
+ .c('prefs', {'xmlns': Strophe.NS.MAM, 'default':'always'})
+ .c('always').up()
+ .c('never').up();
+ _converse.connection._dataRecv(test_utils.createRequest(stanza));
+ expect(feature.save).toHaveBeenCalled();
+ expect(feature.get('preferences')['default']).toBe('never'); // eslint-disable-line dot-notation
+ done();
});
- spyOn(_converse, 'onMAMPreferences').and.callThrough();
- _converse.message_archiving = 'never';
-
- var feature = new Backbone.Model({
- 'var': Strophe.NS.MAM
- });
- spyOn(feature, 'save').and.callFake(feature.set); // Save will complain about a url not being set
- _converse.disco_entities.get(_converse.domain).onFeatureAdded(feature);
-
- expect(_converse.connection.sendIQ).toHaveBeenCalled();
- expect(sent_stanza.toLocaleString()).toBe(
- ""+
- ""+
- ""
- );
-
- /* Example 20. Server responds with current preferences
- *
- *
- *
- *
- *
- *
- *
- */
- var 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));
-
- expect(_converse.onMAMPreferences).toHaveBeenCalled();
-
- expect(_converse.connection.sendIQ.calls.count()).toBe(2);
- expect(sent_stanza.toString()).toBe(
- ""+
- ""+
- "romeo@montague.lit"+
- "montague@montague.lit"+
- ""+
- ""
- );
-
- expect(feature.get('preference')).toBe(undefined);
- /*
- *
- *
- * romeo@montague.lit
- *
- *
- * montague@montague.lit
- *
- *
- *
- */
- stanza = $iq({'type': 'result', 'id': IQ_id})
- .c('prefs', {'xmlns': Strophe.NS.MAM, 'default':'always'})
- .c('always').up()
- .c('never').up();
- _converse.connection._dataRecv(test_utils.createRequest(stanza));
- expect(feature.save).toHaveBeenCalled();
- expect(feature.get('preferences')['default']).toBe('never'); // eslint-disable-line dot-notation
-
- // Restore
- _converse.message_archiving = 'never';
}));
});
});
diff --git a/src/converse-bookmarks.js b/src/converse-bookmarks.js
index dd08f1ce2..7d665dfb2 100644
--- a/src/converse-bookmarks.js
+++ b/src/converse-bookmarks.js
@@ -550,7 +550,7 @@
_converse.api.disco.getIdentity('pubsub', 'pep', _converse.bare_jid),
_converse.api.disco.supports(Strophe.NS.PUBSUB+'#publish-options', _converse.bare_jid)
]).then((args) => {
- resolve(args[0] && (args[1].supported || _converse.allow_public_bookmarks));
+ resolve(args[0] && (args[1].length || _converse.allow_public_bookmarks));
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
}
diff --git a/src/converse-chatview.js b/src/converse-chatview.js
index 450e10a97..57c081604 100644
--- a/src/converse-chatview.js
+++ b/src/converse-chatview.js
@@ -341,8 +341,7 @@
Promise.all(_.map(_.keys(resources), (resource) =>
_converse.api.disco.supports(Strophe.NS.SPOILER, `${contact_jid}/${resource}`)
)).then((results) => {
- const supported = _.every(f.map(f.get('supported'))(results));
- if (supported) {
+ if (results.length) {
const html = tpl_spoiler_button(this.model.toJSON());
if (_converse.visible_toolbar_buttons.emoji) {
this.el.querySelector('.toggle-smiley').insertAdjacentHTML('afterEnd', html);
diff --git a/src/converse-disco.js b/src/converse-disco.js
index 72854db6d..dea095302 100644
--- a/src/converse-disco.js
+++ b/src/converse-disco.js
@@ -12,7 +12,7 @@
define(["converse-core", "sizzle", "strophe.disco"], factory);
}(this, function (converse, sizzle) {
- const { Backbone, Promise, Strophe, b64_sha1, utils, _ } = converse.env;
+ const { Backbone, Promise, Strophe, b64_sha1, utils, _, f } = converse.env;
converse.plugins.add('converse-disco', {
@@ -22,24 +22,10 @@
*/
const { _converse } = this;
- function onDiscoItems (stanza) {
- _.each(stanza.querySelectorAll('query item'), (item) => {
- if (item.getAttribute("node")) {
- // XXX: ignore nodes for now.
- // See: https://xmpp.org/extensions/xep-0030.html#items-nodes
- return;
- }
- const jid = item.getAttribute('jid');
- const entities = _converse.disco_entities;
- if (_.isUndefined(entities.get(jid))) {
- entities.create({'jid': jid});
- }
- });
- }
-
// Promises exposed by this plugin
_converse.api.promises.add('discoInitialized');
+
_converse.DiscoEntity = Backbone.Model.extend({
/* A Disco Entity is a JID addressable entity that can be queried
* for features.
@@ -63,6 +49,10 @@
);
this.fetchFeatures();
+ this.items = new _converse.DiscoEntities();
+ this.items.browserStorage = new Backbone.BrowserStorage[_converse.storage](
+ b64_sha1(`converse.disco-items-${this.get('jid')}`)
+ );
},
getIdentity (category, type) {
@@ -98,17 +88,10 @@
const entity = this;
return new Promise((resolve, reject) => {
function fulfillPromise () {
- const model = entity.features.findWhere({'var': feature });
- if (model) {
- resolve({
- 'supported': true,
- 'feature': model
- });
+ if (entity.features.findWhere({'var': feature})) {
+ resolve(entity);
} else {
- resolve({
- 'supported': false,
- 'feature': null
- });
+ resolve();
}
}
entity.waitUntilFeaturesDiscovered
@@ -141,13 +124,27 @@
_converse.connection.disco.info(this.get('jid'), null, this.onInfo.bind(this));
},
+ onDiscoItems (stanza) {
+ _.each(stanza.querySelectorAll('query item'), (item) => {
+ if (item.getAttribute("node")) {
+ // XXX: ignore nodes for now.
+ // See: https://xmpp.org/extensions/xep-0030.html#items-nodes
+ return;
+ }
+ const jid = item.getAttribute('jid');
+ if (_.isUndefined(this.items.get(jid))) {
+ this.items.create({'jid': jid});
+ }
+ });
+ },
+
queryForItems () {
if (_.isEmpty(this.identities.where({'category': 'server'}))) {
// Don't fetch features and items if this is not a
// server or a conference component.
return;
}
- _converse.connection.disco.items(this.get('jid'), null, onDiscoItems);
+ _converse.connection.disco.items(this.get('jid'), null, this.onDiscoItems.bind(this));
},
onInfo (stanza) {
@@ -175,26 +172,11 @@
_converse.DiscoEntities = Backbone.Collection.extend({
model: _converse.DiscoEntity,
- initialize () {
- this.browserStorage = new Backbone.BrowserStorage[_converse.storage](
- b64_sha1(`converse.disco-entities-${_converse.bare_jid}`)
- );
- this.fetchEntities().then(
- _.partial(_converse.emit, 'discoInitialized'),
- _.partial(_converse.emit, 'discoInitialized')
- ).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
- },
-
fetchEntities () {
return new Promise((resolve, reject) => {
this.fetch({
add: true,
- success: function (collection) {
- if (collection.length === 0 || !collection.get(_converse.domain)) {
- this.create({'jid': _converse.domain});
- }
- resolve();
- }.bind(this),
+ success: resolve,
error () {
reject (new Error("Could not fetch disco entities"));
}
@@ -227,6 +209,18 @@
function initializeDisco () {
addClientFeatures();
_converse.disco_entities = new _converse.DiscoEntities();
+ _converse.disco_entities.browserStorage = new Backbone.BrowserStorage[_converse.storage](
+ b64_sha1(`converse.disco-entities-${_converse.bare_jid}`)
+ );
+
+ _converse.disco_entities.fetchEntities().then((collection) => {
+ if (collection.length === 0 || !collection.get(_converse.domain)) {
+ // If we don't have an entity for our own XMPP server,
+ // create one.
+ _converse.disco_entities.create({'jid': _converse.domain});
+ }
+ _converse.emit('discoInitialized');
+ }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
}
_converse.api.listen.on('reconnected', initializeDisco);
_converse.api.listen.on('connected', initializeDisco);
@@ -247,28 +241,49 @@
'disco': {
'entities': {
'get' (entity_jid, create=false) {
- const entity = _converse.disco_entities.get(entity_jid);
- if (entity || !create) {
- return entity;
- }
- return _converse.disco_entities.create({'jid': entity_jid});
+ return _converse.api.waitUntil('discoInitialized').then(() => {
+ if (_.isNil(entity_jid)) {
+ return _converse.disco_entities;
+ }
+ const entity = _converse.disco_entities.get(entity_jid);
+ if (entity || !create) {
+ return entity;
+ }
+ return _converse.disco_entities.create({'jid': entity_jid});
+ });
}
},
'supports' (feature, entity_jid) {
- /* Returns a Promise which resolves with a map indicating
- * whether a given feature is supported.
+ /* Returns a Promise which resolves with a list containing
+ * _converse.Entity instances representing the entity
+ * itself or those items associated with the entity if
+ * they support the given feature.
*
* Parameters:
* (String) feature - The feature that might be
- * supported. In the XML stanza, this is the `var`
- * attribute of the `` element. For
- * example: 'http://jabber.org/protocol/muc'
- * (String) entity_jid - The JID of the entity which might support the feature.
+ * supported. In the XML stanza, this is the `var`
+ * attribute of the `` element. For
+ * example: 'http://jabber.org/protocol/muc'
+ * (String) entity_jid - The JID of the entity
+ * (and its associated items) which should be queried
*/
- return _converse.api.waitUntil('discoInitialized').then(() => {
- const entity = _converse.api.disco.entities.get(entity_jid, true);
- return entity.hasFeature(feature);
+ if (_.isNil(entity_jid)) {
+ throw new TypeError('disco.supports: You need to provide an entity JID');
+ }
+ return _converse.api.waitUntil('discoInitialized').then((entity) => {
+ return new Promise((resolve, reject) => {
+ _converse.api.disco.entities.get(entity_jid, true).then((entity) => {
+ Promise.all(
+ _.concat(
+ entity.items.map((item) => item.hasFeature(feature)),
+ entity.hasFeature(feature)
+ )
+ ).then((result) => {
+ resolve(f.filter(f.isObject, result));
+ }).catch(reject);
+ })
+ });
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
},
@@ -286,10 +301,13 @@
* In the XML stanza, this is the `type`
* attribute of the `` element.
* For example: 'pep'
+ * (String) entity_jid - The JID of the entity which might have the identity
*/
- return _converse.api.waitUntil('discoInitialized').then(() => {
- const entity = _converse.api.disco.entities.get(entity_jid, true);
- return entity.getIdentity(category, type);
+ return new Promise((resolve, reject) => {
+ _converse.api.waitUntil('discoInitialized').then(() => {
+ _converse.api.disco.entities.get(entity_jid, true)
+ .then((entity) => resolve(entity.getIdentity(category, type)));
+ })
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
}
}
diff --git a/src/converse-http-file-upload.js b/src/converse-http-file-upload.js
index f380365a4..7ba4d8998 100644
--- a/src/converse-http-file-upload.js
+++ b/src/converse-http-file-upload.js
@@ -1,16 +1,48 @@
(function (root, factory) {
- define(["converse-http-file-upload"], factory);
+ define(["converse-core"], factory);
}(this, function (converse) {
"use strict";
+ const { Promise, Strophe, _ } = converse.env;
+ const u = converse.env.utils;
+
+ Strophe.addNamespace('HTTPUPLOAD', 'urn:xmpp:http:upload:0');
+
converse.plugins.add('converse-http-file-upload', {
+ /* Plugin dependencies are other plugins which might be
+ * overridden or relied upon, and therefore need to be loaded before
+ * this plugin.
+ *
+ * If the setting "strict_plugin_dependencies" is set to true,
+ * an error will be raised if the plugin is not found. By default it's
+ * false, which means these plugins are only loaded opportunistically.
+ *
+ * NB: These plugins need to have already been loaded via require.js.
+ */
+ dependencies: ["converse-chatview"],
+
+ overrides: {
+
+ ChatBoxView: {
+ addFileUploadButton (options) {
+ },
+
+ renderToolbar (toolbar, options) {
+ const { _converse } = this.__super__;
+ const result = this.__super__.renderToolbar.apply(this, arguments);
+ // TODO: check results.length
+ _converse.api.disco.supports(Strophe.NS.HTTPUPLOAD, _converse.domain)
+ .then(this.addFileUploadButton.bind(this));
+ return result;
+ }
+ }
+ },
initialize () {
/* The initialize function gets called as soon as the plugin is
* loaded by converse.js's plugin machinery.
*/
const { _converse } = this;
-
}
});
}));
diff --git a/src/converse-mam.js b/src/converse-mam.js
index 7ddc56c1e..90ad4b71e 100644
--- a/src/converse-mam.js
+++ b/src/converse-mam.js
@@ -154,8 +154,8 @@
if (this.disable_mam) { return; }
const { _converse } = this.__super__;
_converse.api.disco.supports(Strophe.NS.MAM, _converse.bare_jid).then(
- (result) => { // Success
- if (result.supported) {
+ (results) => { // Success
+ if (result.length) {
const most_recent_msg = utils.getMostRecentMessage(this.model);
if (_.isNil(most_recent_msg)) {
this.fetchArchivedMessages();
@@ -193,7 +193,7 @@
const { _converse } = this.__super__;
_converse.api.disco.supports(Strophe.NS.MAM, _converse.bare_jid).then(
(result) => { // Success
- if (result.supported) {
+ if (result.length) {
this.fetchArchivedMessages();
}
this.model.save({'mam_initialized': true});
diff --git a/src/converse-vcard.js b/src/converse-vcard.js
index ec46e7a5e..d59411c43 100644
--- a/src/converse-vcard.js
+++ b/src/converse-vcard.js
@@ -186,7 +186,7 @@
if (_.isNil(_converse.xmppstatus.get('vcard_updated'))) {
_converse.api.disco.supports(Strophe.NS.VCARD, _converse.domain)
.then((result) => {
- if (result.supported) {
+ if (result.length) {
_converse.api.vcard.get(_converse.bare_jid)
.then((vcard) => _converse.xmppstatus.save(vcard));
}})
diff --git a/src/converse.js b/src/converse.js
index 1e918f763..e5aad3f23 100644
--- a/src/converse.js
+++ b/src/converse.js
@@ -7,24 +7,25 @@ if (typeof define !== 'undefined') {
* --------------------
* Any of the following components may be removed if they're not needed.
*/
- "converse-chatview", // Renders standalone chat boxes for single user chat
- "converse-controlbox", // The control box
- "converse-bookmarks", // XEP-0048 Bookmarks
- "converse-roomslist", // Show currently open chat rooms
- "converse-mam", // XEP-0313 Message Archive Management
- "converse-muc", // XEP-0045 Multi-user chat
- "converse-muc-views", // Views related to MUC
+ "converse-bookmarks", // XEP-0048 Bookmarks
+ "converse-chatview", // Renders standalone chat boxes for single user chat
+ "converse-controlbox", // The control box
+ "converse-dragresize", // Allows chat boxes to be resized by dragging them
+ "converse-fullscreen",
+ "converse-headline", // Support for headline messages
+ "converse-http-file-upload",
+ "converse-mam", // XEP-0313 Message Archive Management
+ "converse-minimize", // Allows chat boxes to be minimized
+ "converse-muc", // XEP-0045 Multi-user chat
"converse-muc-embedded",
"converse-muc-views",
- "converse-vcard", // XEP-0054 VCard-temp
- "converse-otr", // Off-the-record encryption for one-on-one messages
- "converse-register", // XEP-0077 In-band registration
- "converse-ping", // XEP-0199 XMPP Ping
- "converse-notification",// HTML5 Notifications
- "converse-minimize", // Allows chat boxes to be minimized
- "converse-dragresize", // Allows chat boxes to be resized by dragging them
- "converse-headline", // Support for headline messages
- "converse-fullscreen"
+ "converse-muc-views", // Views related to MUC
+ "converse-notification", // HTML5 Notifications
+ "converse-otr", // Off-the-record encryption for one-on-one messages
+ "converse-ping", // XEP-0199 XMPP Ping
+ "converse-register", // XEP-0077 In-band registration
+ "converse-roomslist", // Show currently open chat rooms
+ "converse-vcard", // XEP-0054 VCard-temp
/* END: Removable components */
], function (converse) {
return converse;