announce.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. (function (root, factory) {
  2. define([
  3. "jasmine",
  4. "mock",
  5. "test-utils"
  6. ], factory);
  7. } (this, function (jasmine, mock, test_utils) {
  8. "use strict";
  9. const Strophe = converse.env.Strophe,
  10. $iq = converse.env.$iq,
  11. _ = converse.env._,
  12. u = converse.env.utils;
  13. describe("Broadcast-/MOTD-Messages (XEP-0133)", function () {
  14. describe("Discovering support", function () {
  15. it("is done automatically", mock.initConverse(async (done, _converse) => {
  16. const IQ_stanzas = _converse.connection.IQ_stanzas;
  17. const IQ_ids = _converse.connection.IQ_ids;
  18. await test_utils.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, [], [Strophe.NS.COMMANDS], []);
  19. await u.waitUntil(() => _.filter(
  20. IQ_stanzas,
  21. iq => iq.querySelector('iq[to="montague.lit"] query[xmlns="http://jabber.org/protocol/disco#items"]')).length
  22. );
  23. /* <iq from='montague.tld'
  24. * id='step_01'
  25. * to='romeo@montague.tld/garden'
  26. * type='result'>
  27. * <query xmlns='http://jabber.org/protocol/disco#items'>
  28. * <item jid='montague.tld' name='Set message of the day and send to online users' node='http://jabber.org/protocol/admin#set-motd' />
  29. * <item jid='montague.tld' name="Update message of the day (don't send)" node='http://jabber.org/protocol/admin#edit-motd' />
  30. * </query>
  31. * </iq>
  32. */
  33. let stanza = _.find(IQ_stanzas, function (iq) {
  34. return iq.querySelector('iq[to="montague.lit"] query[xmlns="http://jabber.org/protocol/disco#items"]');
  35. });
  36. const items_IQ_id = IQ_ids[IQ_stanzas.indexOf(stanza)];
  37. stanza = $iq({
  38. 'type': 'result',
  39. 'from': 'montague.lit',
  40. 'to': 'romeo@montague.lit/orchard',
  41. 'id': items_IQ_id
  42. }).c('query', {'xmlns': 'http://jabber.org/protocol/disco#items'})
  43. .c('item', {
  44. 'jid': 'montague.lit',
  45. 'name': 'Set message of the day and send to online users',
  46. 'node': 'http://jabber.org/protocol/admin#set-motd'})
  47. .c('item', {
  48. 'jid': 'montague.lit',
  49. 'name': "Update message of the day (don't send)",
  50. 'node': 'http://jabber.org/protocol/admin#edit-motd'});
  51. _converse.connection._dataRecv(test_utils.createRequest(stanza));
  52. expect(_converse.serviceAdminCommands.length).toBe(2);
  53. done();
  54. }))
  55. });
  56. describe("When not supported", function () {
  57. it("the service admin menu is not shown", mock.initConverse(async (done, _converse) => {
  58. const IQ_stanzas = _converse.connection.IQ_stanzas;
  59. const IQ_ids = _converse.connection.IQ_ids;
  60. await test_utils.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, [], [Strophe.NS.COMMANDS], []);
  61. await u.waitUntil(() => _.filter(
  62. IQ_stanzas,
  63. iq => iq.querySelector('iq[to="montague.lit"] query[xmlns="http://jabber.org/protocol/disco#items"]')).length
  64. );
  65. /* <iq from='montague.tld'
  66. * id='step_01'
  67. * to='romeo@montague.tld/garden'
  68. * type='error'>
  69. * <query node='announce' xmlns='http://jabber.org/protocol/disco#items' />
  70. * <error code='404' type='cancel'>
  71. * <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  72. * </error>
  73. * </iq>
  74. */
  75. let stanza = _.find(IQ_stanzas, function (iq) {
  76. return iq.querySelector('iq[to="montague.lit"] query[xmlns="http://jabber.org/protocol/disco#items"]');
  77. });
  78. const items_IQ_id = IQ_ids[IQ_stanzas.indexOf(stanza)];
  79. stanza = $iq({
  80. 'type': 'error',
  81. 'from': 'montague.lit',
  82. 'to': 'romeo@montague.lit/orchard',
  83. 'id': items_IQ_id
  84. }).c('query', {'node':'announce', 'xmlns': 'http://jabber.org/protocol/disco#items'}).up()
  85. .c('error', {'code': '404', 'type': 'cancel'})
  86. .c('item-not-found', {
  87. 'xmlns': 'urn:ietf:params:xml:ns:xmpp-stanzas'});
  88. _converse.connection._dataRecv(test_utils.createRequest(stanza));
  89. const view = _converse.chatboxviews.get('controlbox');
  90. expect(view.el.querySelector('.service-admin-menu')).toBe(null);
  91. done();
  92. }))
  93. });
  94. describe("When supported", function () {
  95. it("the service admin menu is shown", mock.initConverse(async (done, _converse) => {
  96. const IQ_stanzas = _converse.connection.IQ_stanzas;
  97. const IQ_ids = _converse.connection.IQ_ids;
  98. await test_utils.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, [], [Strophe.NS.COMMANDS], []);
  99. await u.waitUntil(() => _.filter(
  100. IQ_stanzas,
  101. iq => iq.querySelector('iq[to="montague.lit"] query[xmlns="http://jabber.org/protocol/disco#items"]')).length
  102. );
  103. /* <iq from='montague.tld'
  104. * id='step_01'
  105. * to='romeo@montague.tld/garden'
  106. * type='result'>
  107. * <query xmlns='http://jabber.org/protocol/disco#items'>
  108. * <item jid='montague.tld' name='Set message of the day and send to online users' node='http://jabber.org/protocol/admin#set-motd' />
  109. * <item jid='montague.tld' name="Update message of the day (don't send)" node='http://jabber.org/protocol/admin#edit-motd' />
  110. * </query>
  111. * </iq>
  112. */
  113. let stanza = _.find(IQ_stanzas, function (iq) {
  114. return iq.querySelector('iq[to="montague.lit"] query[xmlns="http://jabber.org/protocol/disco#items"]');
  115. });
  116. const items_IQ_id = IQ_ids[IQ_stanzas.indexOf(stanza)];
  117. stanza = $iq({
  118. 'type': 'result',
  119. 'from': 'montague.lit',
  120. 'to': 'romeo@montague.lit/orchard',
  121. 'id': items_IQ_id
  122. }).c('query', {'xmlns': 'http://jabber.org/protocol/disco#items'})
  123. .c('item', {
  124. 'jid': 'montague.lit',
  125. 'name': 'Set message of the day and send to online users',
  126. 'node': 'http://jabber.org/protocol/admin#set-motd'})
  127. .c('item', {
  128. 'jid': 'montague.lit',
  129. 'name': "Update message of the day (don't send)",
  130. 'node': 'http://jabber.org/protocol/admin#edit-motd'});
  131. _converse.connection._dataRecv(test_utils.createRequest(stanza));
  132. const view = _converse.chatboxviews.get('controlbox');
  133. expect(view.el.querySelector('.service-admin-menu')).not.toBe(null);
  134. done();
  135. }))
  136. it("a user may send an announce command", mock.initConverse(async (done, _converse) => {
  137. const IQ_stanzas = _converse.connection.IQ_stanzas;
  138. const IQ_ids = _converse.connection.IQ_ids;
  139. await test_utils.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, [], [Strophe.NS.COMMANDS], []);
  140. await u.waitUntil(() => _.filter(
  141. IQ_stanzas,
  142. iq => iq.querySelector('iq[to="montague.lit"] query[xmlns="http://jabber.org/protocol/disco#items"]')).length
  143. );
  144. /* <iq from='montague.tld'
  145. * id='step_01'
  146. * to='romeo@montague.tld/garden'
  147. * type='result'>
  148. * <query xmlns='http://jabber.org/protocol/disco#items'>
  149. * <item jid='montague.tld' name='Set message of the day and send to online users' node='http://jabber.org/protocol/admin#set-motd' />
  150. * <item jid='montague.tld' name="Update message of the day (don't send)" node='http://jabber.org/protocol/admin#edit-motd' />
  151. * </query>
  152. * </iq>
  153. */
  154. let stanza = _.find(IQ_stanzas, function (iq) {
  155. return iq.querySelector('iq[to="montague.lit"] query[xmlns="http://jabber.org/protocol/disco#items"]');
  156. });
  157. const items_IQ_id = IQ_ids[IQ_stanzas.indexOf(stanza)];
  158. stanza = $iq({
  159. 'type': 'result',
  160. 'from': 'montague.lit',
  161. 'to': 'romeo@montague.lit/orchard',
  162. 'id': items_IQ_id
  163. }).c('query', {'xmlns': 'http://jabber.org/protocol/disco#items'})
  164. .c('item', {
  165. 'jid': 'montague.lit',
  166. 'name': 'Set message of the day and send to online users',
  167. 'node': 'http://jabber.org/protocol/admin#set-motd'})
  168. .c('item', {
  169. 'jid': 'montague.lit',
  170. 'name': "Update message of the day (don't send)",
  171. 'node': 'http://jabber.org/protocol/admin#edit-motd'});
  172. _converse.connection._dataRecv(test_utils.createRequest(stanza));
  173. let view = _converse.chatboxviews.get('controlbox');
  174. expect(view.el.querySelector('.service-admin-menu')).not.toBe(null);
  175. await test_utils.openControlBox(_converse);
  176. view.el.querySelector("a[title='edit-motd']").click();
  177. await u.waitUntil(() => _.filter(
  178. IQ_stanzas,
  179. iq => iq.querySelector('iq[to="montague.lit"] command[node="http://jabber.org/protocol/admin#edit-motd"]')).length
  180. );
  181. stanza = _.find(IQ_stanzas, function (iq) {
  182. return iq.querySelector('iq[to="montague.lit"] command[node="http://jabber.org/protocol/admin#edit-motd"]');
  183. });
  184. expect(stanza).not.toBe(null);
  185. const command_IQ_id = IQ_ids[IQ_stanzas.indexOf(stanza)];
  186. stanza = u.toStanza(`
  187. <iq from="montague.lit" id="${command_IQ_id}" to="romeo@montague.lit/orchard" type="result" xmlns="jabber:client">
  188. <command node="http://jabber.org/protocol/admin#edit-motd" status="executing" xmlns="http://jabber.org/protocol/commands">
  189. <actions execute="complete">
  190. <complete/>
  191. </actions>
  192. <x type="form" xmlns="jabber:x:data">
  193. <title>Update message of the day (don't send)</title>
  194. <field type="hidden" var="FORM_TYPE">
  195. <value>http://jabber.org/protocol/admin</value>
  196. </field>
  197. <field label="Subject" type="text-single" var="subject"/>
  198. <field label="Message body" type="text-multi" var="body"/>
  199. </x>
  200. </command>
  201. </iq>`);
  202. _converse.connection._dataRecv(test_utils.createRequest(stanza));
  203. view = _converse.chatboxviews.get(_converse.SERVICE_ADMIN_TYPE);
  204. const inputs = view.el.querySelectorAll('.form-control');
  205. inputs[0].value = 'Intelligent subject';
  206. inputs[1].value = 'Extraordinary content';
  207. spyOn(_converse.connection, 'send');
  208. view.el.querySelector('.send-button').click();
  209. expect(_converse.connection.send).toHaveBeenCalled();
  210. stanza = _converse.connection.send.calls.argsFor(0)[0];
  211. expect(Strophe.serialize(stanza)).toBe(
  212. `<iq from="romeo@montague.lit/orchard" id="${stanza.getAttribute('id')}" to="montague.lit" type="set" xml:lang="en" xmlns="jabber:client">`+
  213. `<command node="http://jabber.org/protocol/admin#edit-motd" xmlns="http://jabber.org/protocol/commands">`+
  214. `<x type="submit" xmlns="jabber:x:data">`+
  215. `<field type="hidden" var="FORM_TYPE"><value>http://jabber.org/protocol/admin</value></field>`+
  216. `<field var="subject"><value>Intelligent subject</value></field>`+
  217. `<field var="body"><value>Extraordinary content</value></field>`+
  218. `</x></command></iq>`
  219. );
  220. done();
  221. }))
  222. });
  223. });
  224. }));