notification.js 12 KB

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