notification.js 12 KB

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