notification.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*global mock */
  2. const _ = converse.env._;
  3. const $msg = converse.env.$msg;
  4. const u = converse.env.utils;
  5. describe("Notifications", function () {
  6. // Implement the protocol defined in https://xmpp.org/extensions/xep-0313.html#config
  7. describe("When show_desktop_notifications is set to true", function () {
  8. describe("And the desktop is not focused", function () {
  9. describe("an HTML5 Notification", function () {
  10. it("is shown when a new private message is received",
  11. mock.initConverse(['rosterGroupsFetched'], {}, async (done, _converse) => {
  12. await mock.waitForRoster(_converse, 'current');
  13. spyOn(_converse, 'showMessageNotification').and.callThrough();
  14. spyOn(_converse, 'areDesktopNotificationsEnabled').and.returnValue(true);
  15. spyOn(_converse, 'isMessageToHiddenChat').and.returnValue(true);
  16. const message = 'This message will show a desktop notification';
  17. const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit',
  18. msg = $msg({
  19. from: sender_jid,
  20. to: _converse.connection.jid,
  21. type: 'chat',
  22. id: u.getUniqueId()
  23. }).c('body').t(message).up()
  24. .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
  25. await _converse.handleMessageStanza(msg); // This will emit 'message'
  26. await u.waitUntil(() => _converse.api.chatviews.get(sender_jid));
  27. expect(_converse.areDesktopNotificationsEnabled).toHaveBeenCalled();
  28. expect(_converse.showMessageNotification).toHaveBeenCalled();
  29. done();
  30. }));
  31. it("is shown when you are mentioned in a groupchat",
  32. mock.initConverse(['rosterGroupsFetched'], {}, async (done, _converse) => {
  33. await mock.waitForRoster(_converse, 'current');
  34. await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
  35. const view = _converse.api.chatviews.get('lounge@montague.lit');
  36. if (!view.el.querySelectorAll('.chat-area').length) {
  37. view.renderChatArea();
  38. }
  39. let no_notification = false;
  40. if (typeof window.Notification === 'undefined') {
  41. no_notification = true;
  42. window.Notification = function () {
  43. return {
  44. 'close': function () {}
  45. };
  46. };
  47. }
  48. spyOn(_converse, 'showMessageNotification').and.callThrough();
  49. spyOn(_converse, 'areDesktopNotificationsEnabled').and.returnValue(true);
  50. const message = 'romeo: This message will show a desktop notification';
  51. const nick = mock.chatroom_names[0],
  52. msg = $msg({
  53. from: 'lounge@montague.lit/'+nick,
  54. id: u.getUniqueId(),
  55. to: 'romeo@montague.lit',
  56. type: 'groupchat'
  57. }).c('body').t(message).tree();
  58. _converse.connection._dataRecv(mock.createRequest(msg));
  59. await new Promise(resolve => view.model.messages.once('rendered', resolve));
  60. await u.waitUntil(() => _converse.areDesktopNotificationsEnabled.calls.count() === 1);
  61. expect(_converse.showMessageNotification).toHaveBeenCalled();
  62. if (no_notification) {
  63. delete window.Notification;
  64. }
  65. done();
  66. }));
  67. it("is shown for headline messages",
  68. mock.initConverse(['rosterGroupsFetched'], {}, async (done, _converse) => {
  69. spyOn(_converse, 'showMessageNotification').and.callThrough();
  70. spyOn(_converse, 'isMessageToHiddenChat').and.returnValue(true);
  71. spyOn(_converse, 'areDesktopNotificationsEnabled').and.returnValue(true);
  72. const stanza = $msg({
  73. 'type': 'headline',
  74. 'from': 'notify.example.com',
  75. 'to': 'romeo@montague.lit',
  76. 'xml:lang': 'en'
  77. })
  78. .c('subject').t('SIEVE').up()
  79. .c('body').t('<juliet@example.com> You got mail.').up()
  80. .c('x', {'xmlns': 'jabber:x:oob'})
  81. .c('url').t('imap://romeo@example.com/INBOX;UIDVALIDITY=385759043/;UID=18');
  82. _converse.connection._dataRecv(mock.createRequest(stanza));
  83. await u.waitUntil(() => _converse.chatboxviews.keys().length);
  84. const view = _converse.chatboxviews.get('notify.example.com');
  85. await new Promise(resolve => view.model.messages.once('rendered', resolve));
  86. expect(_converse.chatboxviews.keys().includes('notify.example.com')).toBeTruthy();
  87. expect(_converse.showMessageNotification).toHaveBeenCalled();
  88. done();
  89. }));
  90. it("is not shown for full JID headline messages if allow_non_roster_messaging is false", mock.initConverse((done, _converse) => {
  91. _converse.allow_non_roster_messaging = false;
  92. spyOn(_converse, 'showMessageNotification').and.callThrough();
  93. spyOn(_converse, 'areDesktopNotificationsEnabled').and.returnValue(true);
  94. const stanza = $msg({
  95. 'type': 'headline',
  96. 'from': 'someone@notify.example.com',
  97. 'to': 'romeo@montague.lit',
  98. 'xml:lang': 'en'
  99. })
  100. .c('subject').t('SIEVE').up()
  101. .c('body').t('<juliet@example.com> You got mail.').up()
  102. .c('x', {'xmlns': 'jabber:x:oob'})
  103. .c('url').t('imap://romeo@example.com/INBOX;UIDVALIDITY=385759043/;UID=18');
  104. _converse.connection._dataRecv(mock.createRequest(stanza));
  105. expect(
  106. _.includes(_converse.chatboxviews.keys(),
  107. 'someone@notify.example.com')
  108. ).toBeFalsy();
  109. expect(_converse.showMessageNotification).not.toHaveBeenCalled();
  110. done();
  111. }));
  112. it("is shown when a user changes their chat state (if show_chat_state_notifications is true)",
  113. mock.initConverse(['rosterGroupsFetched'], {show_chat_state_notifications: true},
  114. async (done, _converse) => {
  115. await mock.waitForRoster(_converse, 'current', 3);
  116. spyOn(_converse, 'areDesktopNotificationsEnabled').and.returnValue(true);
  117. spyOn(_converse, 'showChatStateNotification');
  118. const jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@montague.lit';
  119. _converse.roster.get(jid).presence.set('show', 'busy'); // This will emit 'contactStatusChanged'
  120. await u.waitUntil(() => _converse.areDesktopNotificationsEnabled.calls.count() === 1);
  121. expect(_converse.showChatStateNotification).toHaveBeenCalled();
  122. done()
  123. }));
  124. });
  125. });
  126. describe("When a new contact request is received", function () {
  127. it("an HTML5 Notification is received", mock.initConverse((done, _converse) => {
  128. spyOn(_converse, 'areDesktopNotificationsEnabled').and.returnValue(true);
  129. spyOn(_converse, 'showContactRequestNotification');
  130. _converse.api.trigger('contactRequest', {'fullname': 'Peter Parker', 'jid': 'peter@parker.com'});
  131. expect(_converse.areDesktopNotificationsEnabled).toHaveBeenCalled();
  132. expect(_converse.showContactRequestNotification).toHaveBeenCalled();
  133. done();
  134. }));
  135. });
  136. });
  137. describe("When play_sounds is set to true", function () {
  138. describe("A notification sound", function () {
  139. it("is played when the current user is mentioned in a groupchat",
  140. mock.initConverse(['rosterGroupsFetched'], {}, async (done, _converse) => {
  141. mock.createContacts(_converse, 'current');
  142. await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
  143. _converse.play_sounds = true;
  144. spyOn(_converse, 'playSoundNotification');
  145. const view = _converse.chatboxviews.get('lounge@montague.lit');
  146. if (!view.el.querySelectorAll('.chat-area').length) {
  147. view.renderChatArea();
  148. }
  149. let text = 'This message will play a sound because it mentions romeo';
  150. let message = $msg({
  151. from: 'lounge@montague.lit/otheruser',
  152. id: '1',
  153. to: 'romeo@montague.lit',
  154. type: 'groupchat'
  155. }).c('body').t(text);
  156. await view.model.handleMessageStanza(message.nodeTree);
  157. await u.waitUntil(() => _converse.playSoundNotification.calls.count());
  158. expect(_converse.playSoundNotification).toHaveBeenCalled();
  159. text = "This message won't play a sound";
  160. message = $msg({
  161. from: 'lounge@montague.lit/otheruser',
  162. id: '2',
  163. to: 'romeo@montague.lit',
  164. type: 'groupchat'
  165. }).c('body').t(text);
  166. await view.model.handleMessageStanza(message.nodeTree);
  167. expect(_converse.playSoundNotification, 1);
  168. _converse.play_sounds = false;
  169. text = "This message won't play a sound because it is sent by romeo";
  170. message = $msg({
  171. from: 'lounge@montague.lit/romeo',
  172. id: '3',
  173. to: 'romeo@montague.lit',
  174. type: 'groupchat'
  175. }).c('body').t(text);
  176. await view.model.handleMessageStanza(message.nodeTree);
  177. expect(_converse.playSoundNotification, 1);
  178. _converse.play_sounds = false;
  179. done();
  180. }));
  181. });
  182. });
  183. });