spoilers.js 11 KB

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