spoilers.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. (function (root, factory) {
  2. define(["jasmine", "mock", "test-utils"], factory);
  3. } (this, function (jasmine, mock, test_utils) {
  4. const _ = converse.env._;
  5. const Strophe = converse.env.Strophe;
  6. const $msg = converse.env.$msg;
  7. const $pres = converse.env.$pres;
  8. const u = converse.env.utils;
  9. describe("A spoiler message", function () {
  10. it("can be received with a hint",
  11. mock.initConverse(
  12. null, ['rosterGroupsFetched', 'chatBoxViewsInitialized'], {},
  13. async (done, _converse) => {
  14. test_utils.createContacts(_converse, 'current');
  15. _converse.emit('rosterContactsFetched');
  16. await test_utils.createContacts(_converse, 'current');
  17. const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
  18. /* <message to='romeo@montague.net/orchard' from='juliet@capulet.net/balcony' id='spoiler2'>
  19. * <body>And at the end of the story, both of them die! It is so tragic!</body>
  20. * <spoiler xmlns='urn:xmpp:spoiler:0'>Love story end</spoiler>
  21. * </message>
  22. */
  23. const spoiler_hint = "Love story end"
  24. const spoiler = "And at the end of the story, both of them die! It is so tragic!";
  25. const msg = $msg({
  26. 'xmlns': 'jabber:client',
  27. 'to': _converse.bare_jid,
  28. 'from': sender_jid,
  29. 'type': 'chat'
  30. }).c('body').t(spoiler).up()
  31. .c('spoiler', {
  32. 'xmlns': 'urn:xmpp:spoiler:0',
  33. }).t(spoiler_hint)
  34. .tree();
  35. _converse.chatboxes.onMessage(msg);
  36. await test_utils.waitUntil(() => _converse.api.chats.get().length === 2);
  37. const view = _converse.api.chatviews.get(sender_jid);
  38. await new Promise((resolve, reject) => view.once('messageInserted', resolve));
  39. await test_utils.waitUntil(() => view.model.vcard.get('fullname') === 'Max Frankfurter')
  40. expect(view.el.querySelector('.chat-msg__author').textContent.trim()).toBe('Max Frankfurter');
  41. const message_content = view.el.querySelector('.chat-msg__text');
  42. expect(message_content.textContent).toBe(spoiler);
  43. const spoiler_hint_el = view.el.querySelector('.spoiler-hint');
  44. expect(spoiler_hint_el.textContent).toBe(spoiler_hint);
  45. done();
  46. }));
  47. it("can be received without a hint",
  48. mock.initConverse(
  49. null, ['rosterGroupsFetched'], {},
  50. async (done, _converse) => {
  51. await test_utils.createContacts(_converse, 'current');
  52. _converse.emit('rosterContactsFetched');
  53. const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
  54. /* <message to='romeo@montague.net/orchard' from='juliet@capulet.net/balcony' id='spoiler2'>
  55. * <body>And at the end of the story, both of them die! It is so tragic!</body>
  56. * <spoiler xmlns='urn:xmpp:spoiler:0'>Love story end</spoiler>
  57. * </message>
  58. */
  59. const spoiler = "And at the end of the story, both of them die! It is so tragic!";
  60. const msg = $msg({
  61. 'xmlns': 'jabber:client',
  62. 'to': _converse.bare_jid,
  63. 'from': sender_jid,
  64. 'type': 'chat'
  65. }).c('body').t(spoiler).up()
  66. .c('spoiler', {
  67. 'xmlns': 'urn:xmpp:spoiler:0',
  68. }).tree();
  69. _converse.chatboxes.onMessage(msg);
  70. await test_utils.waitUntil(() => _converse.api.chats.get().length === 2);
  71. const view = _converse.api.chatviews.get(sender_jid);
  72. await new Promise((resolve, reject) => view.once('messageInserted', resolve));
  73. await test_utils.waitUntil(() => view.model.vcard.get('fullname') === 'Max Frankfurter')
  74. expect(_.includes(view.el.querySelector('.chat-msg__author').textContent, 'Max Frankfurter')).toBeTruthy();
  75. const message_content = view.el.querySelector('.chat-msg__text');
  76. expect(message_content.textContent).toBe(spoiler);
  77. const spoiler_hint_el = view.el.querySelector('.spoiler-hint');
  78. expect(spoiler_hint_el.textContent).toBe('');
  79. done();
  80. }));
  81. it("can be sent without a hint",
  82. mock.initConverse(
  83. null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
  84. async (done, _converse) => {
  85. await test_utils.createContacts(_converse, 'current', 1);
  86. _converse.emit('rosterContactsFetched');
  87. test_utils.openControlBox();
  88. const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
  89. // XXX: We need to send a presence from the contact, so that we
  90. // have a resource, that resource is then queried to see
  91. // whether Strophe.NS.SPOILER is supported, in which case
  92. // the spoiler button will appear.
  93. const presence = $pres({
  94. 'from': contact_jid+'/phone',
  95. 'to': 'dummy@localhost'
  96. });
  97. _converse.connection._dataRecv(test_utils.createRequest(presence));
  98. await test_utils.openChatBoxFor(_converse, contact_jid);
  99. await test_utils.waitUntilDiscoConfirmed(_converse, contact_jid+'/phone', [], [Strophe.NS.SPOILER]);
  100. const view = _converse.api.chatviews.get(contact_jid);
  101. spyOn(view, 'onMessageSubmitted').and.callThrough();
  102. spyOn(_converse.connection, 'send');
  103. await test_utils.waitUntil(() => view.el.querySelector('.toggle-compose-spoiler'));
  104. let spoiler_toggle = view.el.querySelector('.toggle-compose-spoiler');
  105. spoiler_toggle.click();
  106. const textarea = view.el.querySelector('.chat-textarea');
  107. textarea.value = 'This is the spoiler';
  108. view.keyPressed({
  109. target: textarea,
  110. preventDefault: _.noop,
  111. keyCode: 13
  112. });
  113. await new Promise((resolve, reject) => view.once('messageInserted', resolve));
  114. /* Test the XML stanza
  115. *
  116. * <message from="dummy@localhost/resource"
  117. * to="max.frankfurter@localhost"
  118. * type="chat"
  119. * id="4547c38b-d98b-45a5-8f44-b4004dbc335e"
  120. * xmlns="jabber:client">
  121. * <body>This is the spoiler</body>
  122. * <active xmlns="http://jabber.org/protocol/chatstates"/>
  123. * <spoiler xmlns="urn:xmpp:spoiler:0"/>
  124. * </message>"
  125. */
  126. const stanza = _converse.connection.send.calls.argsFor(0)[0].tree();
  127. const spoiler_el = stanza.querySelector('spoiler[xmlns="urn:xmpp:spoiler:0"]');
  128. expect(_.isNull(spoiler_el)).toBeFalsy();
  129. expect(spoiler_el.textContent).toBe('');
  130. const body_el = stanza.querySelector('body');
  131. expect(body_el.textContent).toBe('This is the spoiler');
  132. /* Test the HTML spoiler message */
  133. expect(view.el.querySelector('.chat-msg__author').textContent.trim()).toBe('Max Mustermann');
  134. const spoiler_msg_el = view.el.querySelector('.chat-msg__text.spoiler');
  135. expect(spoiler_msg_el.textContent).toBe('This is the spoiler');
  136. expect(_.includes(spoiler_msg_el.classList, 'collapsed')).toBeTruthy();
  137. spoiler_toggle = view.el.querySelector('.spoiler-toggle');
  138. expect(spoiler_toggle.textContent).toBe('Show more');
  139. spoiler_toggle.click();
  140. expect(_.includes(spoiler_msg_el.classList, 'collapsed')).toBeFalsy();
  141. expect(spoiler_toggle.textContent).toBe('Show less');
  142. spoiler_toggle.click();
  143. expect(_.includes(spoiler_msg_el.classList, 'collapsed')).toBeTruthy();
  144. done();
  145. }));
  146. it("can be sent with a hint",
  147. mock.initConverse(
  148. null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
  149. async (done, _converse) => {
  150. await test_utils.createContacts(_converse, 'current', 1);
  151. _converse.emit('rosterContactsFetched');
  152. test_utils.openControlBox();
  153. const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
  154. // XXX: We need to send a presence from the contact, so that we
  155. // have a resource, that resource is then queried to see
  156. // whether Strophe.NS.SPOILER is supported, in which case
  157. // the spoiler button will appear.
  158. const presence = $pres({
  159. 'from': contact_jid+'/phone',
  160. 'to': 'dummy@localhost'
  161. });
  162. _converse.connection._dataRecv(test_utils.createRequest(presence));
  163. await test_utils.openChatBoxFor(_converse, contact_jid);
  164. await test_utils.waitUntilDiscoConfirmed(_converse, contact_jid+'/phone', [], [Strophe.NS.SPOILER]);
  165. const view = _converse.api.chatviews.get(contact_jid);
  166. await test_utils.waitUntil(() => view.el.querySelector('.toggle-compose-spoiler'));
  167. let spoiler_toggle = view.el.querySelector('.toggle-compose-spoiler');
  168. spoiler_toggle.click();
  169. spyOn(_converse.connection, 'send');
  170. const textarea = view.el.querySelector('.chat-textarea');
  171. textarea.value = 'This is the spoiler';
  172. const hint_input = view.el.querySelector('.spoiler-hint');
  173. hint_input.value = 'This is the hint';
  174. view.keyPressed({
  175. target: textarea,
  176. preventDefault: _.noop,
  177. keyCode: 13
  178. });
  179. await new Promise((resolve, reject) => view.once('messageInserted', resolve));
  180. /* Test the XML stanza
  181. *
  182. * <message from="dummy@localhost/resource"
  183. * to="max.frankfurter@localhost"
  184. * type="chat"
  185. * id="4547c38b-d98b-45a5-8f44-b4004dbc335e"
  186. * xmlns="jabber:client">
  187. * <body>This is the spoiler</body>
  188. * <active xmlns="http://jabber.org/protocol/chatstates"/>
  189. * <spoiler xmlns="urn:xmpp:spoiler:0">This is the hint</spoiler>
  190. * </message>"
  191. */
  192. const stanza = _converse.connection.send.calls.argsFor(0)[0].tree();
  193. const spoiler_el = stanza.querySelector('spoiler[xmlns="urn:xmpp:spoiler:0"]');
  194. expect(_.isNull(spoiler_el)).toBeFalsy();
  195. expect(spoiler_el.textContent).toBe('This is the hint');
  196. const body_el = stanza.querySelector('body');
  197. expect(body_el.textContent).toBe('This is the spoiler');
  198. /* Test the HTML spoiler message */
  199. expect(view.el.querySelector('.chat-msg__author').textContent.trim()).toBe('Max Mustermann');
  200. const spoiler_msg_el = view.el.querySelector('.chat-msg__text.spoiler');
  201. expect(spoiler_msg_el.textContent).toBe('This is the spoiler');
  202. expect(_.includes(spoiler_msg_el.classList, 'collapsed')).toBeTruthy();
  203. spoiler_toggle = view.el.querySelector('.spoiler-toggle');
  204. expect(spoiler_toggle.textContent).toBe('Show more');
  205. spoiler_toggle.click();
  206. expect(_.includes(spoiler_msg_el.classList, 'collapsed')).toBeFalsy();
  207. expect(spoiler_toggle.textContent).toBe('Show less');
  208. spoiler_toggle.click();
  209. expect(_.includes(spoiler_msg_el.classList, 'collapsed')).toBeTruthy();
  210. done();
  211. }));
  212. });
  213. }));