spoilers.js 11 KB

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