2
0

disco.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*global mock, converse */
  2. describe("Service Discovery", function () {
  3. describe("Whenever converse.js queries a server for its features", function () {
  4. it("stores the features it receives",
  5. mock.initConverse(
  6. ['discoInitialized'], {},
  7. async function (done, _converse) {
  8. const { u, $iq } = converse.env;
  9. const IQ_stanzas = _converse.connection.IQ_stanzas;
  10. const IQ_ids = _converse.connection.IQ_ids;
  11. await u.waitUntil(function () {
  12. return IQ_stanzas.filter(function (iq) {
  13. return iq.querySelector('iq[to="montague.lit"] query[xmlns="http://jabber.org/protocol/disco#info"]');
  14. }).length > 0;
  15. });
  16. /* <iq type='result'
  17. * from='plays.shakespeare.lit'
  18. * to='romeo@montague.net/orchard'
  19. * id='info1'>
  20. * <query xmlns='http://jabber.org/protocol/disco#info'>
  21. * <identity
  22. * category='server'
  23. * type='im'/>
  24. * <identity
  25. * category='conference'
  26. * type='text'
  27. * name='Play-Specific Chatrooms'/>
  28. * <identity
  29. * category='directory'
  30. * type='chatroom'
  31. * name='Play-Specific Chatrooms'/>
  32. * <feature var='http://jabber.org/protocol/disco#info'/>
  33. * <feature var='http://jabber.org/protocol/disco#items'/>
  34. * <feature var='http://jabber.org/protocol/muc'/>
  35. * <feature var='jabber:iq:register'/>
  36. * <feature var='jabber:iq:search'/>
  37. * <feature var='jabber:iq:time'/>
  38. * <feature var='jabber:iq:version'/>
  39. * </query>
  40. * </iq>
  41. */
  42. let stanza = IQ_stanzas.find(function (iq) {
  43. return iq.querySelector('iq[to="montague.lit"] query[xmlns="http://jabber.org/protocol/disco#info"]');
  44. });
  45. const info_IQ_id = IQ_ids[IQ_stanzas.indexOf(stanza)];
  46. stanza = $iq({
  47. 'type': 'result',
  48. 'from': 'montague.lit',
  49. 'to': 'romeo@montague.lit/orchard',
  50. 'id': info_IQ_id
  51. }).c('query', {'xmlns': 'http://jabber.org/protocol/disco#info'})
  52. .c('identity', {
  53. 'category': 'server',
  54. 'type': 'im'}).up()
  55. .c('identity', {
  56. 'category': 'conference',
  57. 'type': 'text',
  58. 'name': 'Play-Specific Chatrooms'}).up()
  59. .c('identity', {
  60. 'category': 'directory',
  61. 'type': 'chatroom',
  62. 'name': 'Play-Specific Chatrooms'}).up()
  63. .c('feature', {
  64. 'var': 'http://jabber.org/protocol/disco#info'}).up()
  65. .c('feature', {
  66. 'var': 'http://jabber.org/protocol/disco#items'}).up()
  67. .c('feature', {
  68. 'var': 'jabber:iq:register'}).up()
  69. .c('feature', {
  70. 'var': 'jabber:iq:time'}).up()
  71. .c('feature', {
  72. 'var': 'jabber:iq:version'});
  73. _converse.connection._dataRecv(mock.createRequest(stanza));
  74. let entities = await _converse.api.disco.entities.get()
  75. expect(entities.length).toBe(2); // We have an extra entity, which is the user's JID
  76. expect(entities.get(_converse.domain).features.length).toBe(5);
  77. expect(entities.get(_converse.domain).identities.length).toBe(3);
  78. expect(entities.get('montague.lit').features.where({'var': 'jabber:iq:version'}).length).toBe(1);
  79. expect(entities.get('montague.lit').features.where({'var': 'jabber:iq:time'}).length).toBe(1);
  80. expect(entities.get('montague.lit').features.where({'var': 'jabber:iq:register'}).length).toBe(1);
  81. expect(entities.get('montague.lit').features.where(
  82. {'var': 'http://jabber.org/protocol/disco#items'}).length).toBe(1);
  83. expect(entities.get('montague.lit').features.where(
  84. {'var': 'http://jabber.org/protocol/disco#info'}).length).toBe(1);
  85. await u.waitUntil(function () {
  86. // Converse.js sees that the entity has a disco#items feature,
  87. // so it will make a query for it.
  88. return IQ_stanzas.filter(iq => iq.querySelector('query[xmlns="http://jabber.org/protocol/disco#items"]')).length > 0;
  89. });
  90. /* <iq type='result'
  91. * from='catalog.shakespeare.lit'
  92. * to='romeo@montague.net/orchard'
  93. * id='items2'>
  94. * <query xmlns='http://jabber.org/protocol/disco#items'>
  95. * <item jid='people.shakespeare.lit'
  96. * name='Directory of Characters'/>
  97. * <item jid='plays.shakespeare.lit'
  98. * name='Play-Specific Chatrooms'/>
  99. * <item jid='mim.shakespeare.lit'
  100. * name='Gateway to Marlowe IM'/>
  101. * <item jid='words.shakespeare.lit'
  102. * name='Shakespearean Lexicon'/>
  103. *
  104. * <item jid='catalog.shakespeare.lit'
  105. * node='books'
  106. * name='Books by and about Shakespeare'/>
  107. * <item jid='catalog.shakespeare.lit'
  108. * node='clothing'
  109. * name='Wear your literary taste with pride'/>
  110. * <item jid='catalog.shakespeare.lit'
  111. * node='music'
  112. * name='Music from the time of Shakespeare'/>
  113. * </query>
  114. * </iq>
  115. */
  116. stanza = IQ_stanzas.find(function (iq) {
  117. return iq.querySelector('iq[to="montague.lit"] query[xmlns="http://jabber.org/protocol/disco#items"]');
  118. });
  119. const items_IQ_id = IQ_ids[IQ_stanzas.indexOf(stanza)];
  120. stanza = $iq({
  121. 'type': 'result',
  122. 'from': 'montague.lit',
  123. 'to': 'romeo@montague.lit/orchard',
  124. 'id': items_IQ_id
  125. }).c('query', {'xmlns': 'http://jabber.org/protocol/disco#items'})
  126. .c('item', {
  127. 'jid': 'people.shakespeare.lit',
  128. 'name': 'Directory of Characters'}).up()
  129. .c('item', {
  130. 'jid': 'plays.shakespeare.lit',
  131. 'name': 'Play-Specific Chatrooms'}).up()
  132. .c('item', {
  133. 'jid': 'words.shakespeare.lit',
  134. 'name': 'Gateway to Marlowe IM'}).up()
  135. .c('item', {
  136. 'jid': 'montague.lit',
  137. 'node': 'books',
  138. 'name': 'Books by and about Shakespeare'}).up()
  139. .c('item', {
  140. 'node': 'montague.lit',
  141. 'name': 'Wear your literary taste with pride'}).up()
  142. .c('item', {
  143. 'jid': 'montague.lit',
  144. 'node': 'music',
  145. 'name': 'Music from the time of Shakespeare'
  146. });
  147. _converse.connection._dataRecv(mock.createRequest(stanza));
  148. await u.waitUntil(() => _converse.disco_entities);
  149. entities = _converse.disco_entities;
  150. expect(entities.length).toBe(2); // We have an extra entity, which is the user's JID
  151. expect(entities.get(_converse.domain).items.length).toBe(3);
  152. expect(entities.get(_converse.domain).items.pluck('jid').includes('people.shakespeare.lit')).toBeTruthy();
  153. expect(entities.get(_converse.domain).items.pluck('jid').includes('plays.shakespeare.lit')).toBeTruthy();
  154. expect(entities.get(_converse.domain).items.pluck('jid').includes('words.shakespeare.lit')).toBeTruthy();
  155. expect(entities.get(_converse.domain).identities.where({'category': 'conference'}).length).toBe(1);
  156. expect(entities.get(_converse.domain).identities.where({'category': 'directory'}).length).toBe(1);
  157. done();
  158. }));
  159. });
  160. describe("Whenever converse.js discovers a new server feature", function () {
  161. it("emits the serviceDiscovered event",
  162. mock.initConverse(
  163. ['discoInitialized'], {},
  164. function (done, _converse) {
  165. const { Strophe } = converse.env;
  166. sinon.spy(_converse.api, "trigger");
  167. _converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
  168. expect(_converse.api.trigger.called).toBe(true);
  169. expect(_converse.api.trigger.args[0][0]).toBe('serviceDiscovered');
  170. expect(_converse.api.trigger.args[0][1].get('var')).toBe(Strophe.NS.MAM);
  171. done();
  172. }));
  173. });
  174. });