spoilers.js 12 KB

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