123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- /*global mock, converse */
- const { Strophe } = converse.env;
- const $msg = converse.env.$msg;
- const u = converse.env.utils;
- describe("Notifications", function () {
- // Implement the protocol defined in https://xmpp.org/extensions/xep-0313.html#config
- describe("When show_desktop_notifications is set to true", function () {
- describe("And the desktop is not focused", function () {
- describe("an HTML5 Notification", function () {
- it("is shown when a new private message is received",
- mock.initConverse([], {}, async (done, _converse) => {
- await mock.waitForRoster(_converse, 'current');
- const stub = jasmine.createSpyObj('MyNotification', ['onclick', 'close']);
- spyOn(window, 'Notification').and.returnValue(stub);
- const message = 'This message will show a desktop notification';
- const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit',
- msg = $msg({
- from: sender_jid,
- to: _converse.connection.jid,
- type: 'chat',
- id: u.getUniqueId()
- }).c('body').t(message).up()
- .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
- await _converse.handleMessageStanza(msg); // This will emit 'message'
- await u.waitUntil(() => _converse.api.chatviews.get(sender_jid));
- expect(window.Notification).toHaveBeenCalled();
- done();
- }));
- it("is shown when you are mentioned in a groupchat",
- mock.initConverse([], {}, async (done, _converse) => {
- await mock.waitForRoster(_converse, 'current');
- await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
- const view = _converse.api.chatviews.get('lounge@montague.lit');
- if (!view.querySelectorAll('.chat-area').length) {
- view.renderChatArea();
- }
- const stub = jasmine.createSpyObj('MyNotification', ['onclick', 'close']);
- spyOn(window, 'Notification').and.returnValue(stub);
- // Test mention with setting false
- const nick = mock.chatroom_names[0];
- const makeMsg = text => $msg({
- from: 'lounge@montague.lit/'+nick,
- id: u.getUniqueId(),
- to: 'romeo@montague.lit',
- type: 'groupchat'
- }).c('body').t(text).tree();
- _converse.connection._dataRecv(mock.createRequest(makeMsg('romeo: this will NOT show a notification')));
- await new Promise(resolve => view.model.messages.once('rendered', resolve));
- expect(window.Notification).not.toHaveBeenCalled();
- // Test reference
- const message_with_ref = $msg({
- from: 'lounge@montague.lit/'+nick,
- id: u.getUniqueId(),
- to: 'romeo@montague.lit',
- type: 'groupchat'
- }).c('body').t('romeo: this will show a notification').up()
- .c('reference', {'xmlns':'urn:xmpp:reference:0', 'begin':'0', 'end':'5', 'type':'mention', 'uri':'xmpp:romeo@montague.lit'}).tree();
- _converse.connection._dataRecv(mock.createRequest(message_with_ref));
- await new Promise(resolve => view.model.messages.once('rendered', resolve));
- expect(window.Notification.calls.count()).toBe(1);
- // Test mention with setting true
- _converse.api.settings.set('notify_all_room_messages', true);
- _converse.connection._dataRecv(mock.createRequest(makeMsg('romeo: this will show a notification')));
- await new Promise(resolve => view.model.messages.once('rendered', resolve));
- expect(window.Notification.calls.count()).toBe(2);
- done();
- }));
- it("is shown for headline messages", mock.initConverse([], {}, async (done, _converse) => {
- const stub = jasmine.createSpyObj('MyNotification', ['onclick', 'close']);
- spyOn(window, 'Notification').and.returnValue(stub);
- await mock.waitForRoster(_converse, 'current', 0);
- const stanza = $msg({
- 'type': 'headline',
- 'from': 'notify.example.com',
- 'to': 'romeo@montague.lit',
- 'xml:lang': 'en'
- })
- .c('subject').t('SIEVE').up()
- .c('body').t('<juliet@example.com> You got mail.').up()
- .c('x', {'xmlns': 'jabber:x:oob'})
- .c('url').t('imap://romeo@example.com/INBOX;UIDVALIDITY=385759043/;UID=18');
- _converse.connection._dataRecv(mock.createRequest(stanza));
- await u.waitUntil(() => _converse.chatboxviews.keys().length === 2);
- const view = _converse.chatboxviews.get('notify.example.com');
- await new Promise(resolve => view.model.messages.once('rendered', resolve));
- expect(_converse.chatboxviews.keys().includes('notify.example.com')).toBeTruthy();
- expect(window.Notification).toHaveBeenCalled();
- done();
- }));
- it("is not shown for full JID headline messages if allow_non_roster_messaging is false", mock.initConverse((done, _converse) => {
- _converse.allow_non_roster_messaging = false;
- const stub = jasmine.createSpyObj('MyNotification', ['onclick', 'close']);
- spyOn(window, 'Notification').and.returnValue(stub);
- const stanza = $msg({
- 'type': 'headline',
- 'from': 'someone@notify.example.com',
- 'to': 'romeo@montague.lit',
- 'xml:lang': 'en'
- })
- .c('subject').t('SIEVE').up()
- .c('body').t('<juliet@example.com> You got mail.').up()
- .c('x', {'xmlns': 'jabber:x:oob'})
- .c('url').t('imap://romeo@example.com/INBOX;UIDVALIDITY=385759043/;UID=18');
- _converse.connection._dataRecv(mock.createRequest(stanza));
- expect(_converse.chatboxviews.keys().includes('someone@notify.example.com')).toBeFalsy();
- expect(window.Notification).not.toHaveBeenCalled();
- done();
- }));
- it("is shown when a user changes their chat state (if show_chat_state_notifications is true)",
- mock.initConverse([], {show_chat_state_notifications: true},
- async (done, _converse) => {
- await mock.waitForRoster(_converse, 'current', 3);
- const stub = jasmine.createSpyObj('MyNotification', ['onclick', 'close']);
- spyOn(window, 'Notification').and.returnValue(stub);
- const jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@montague.lit';
- _converse.roster.get(jid).presence.set('show', 'dnd');
- expect(window.Notification).toHaveBeenCalled();
- done()
- }));
- });
- });
- describe("When a new contact request is received", function () {
- it("an HTML5 Notification is received", mock.initConverse((done, _converse) => {
- const stub = jasmine.createSpyObj('MyNotification', ['onclick', 'close']);
- spyOn(window, 'Notification').and.returnValue(stub);
- _converse.api.trigger('contactRequest', {'getDisplayName': () => 'Peter Parker'});
- expect(window.Notification).toHaveBeenCalled();
- done();
- }));
- });
- });
- describe("When play_sounds is set to true", function () {
- describe("A notification sound", function () {
- it("is played when the current user is mentioned in a groupchat", mock.initConverse([], {}, async (done, _converse) => {
- mock.createContacts(_converse, 'current');
- await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
- _converse.play_sounds = true;
- const stub = jasmine.createSpyObj('MyAudio', ['play', 'canPlayType']);
- spyOn(window, 'Audio').and.returnValue(stub);
- const view = _converse.chatboxviews.get('lounge@montague.lit');
- if (!view.querySelectorAll('.chat-area').length) {
- view.renderChatArea();
- }
- let text = 'This message will play a sound because it mentions romeo';
- let message = $msg({
- from: 'lounge@montague.lit/otheruser',
- id: '1',
- to: 'romeo@montague.lit',
- type: 'groupchat'
- }).c('body').t(text);
- _converse.api.settings.set('notify_all_room_messages', true);
- await view.model.handleMessageStanza(message.nodeTree);
- await u.waitUntil(() => window.Audio.calls.count());
- expect(window.Audio).toHaveBeenCalled();
- text = "This message won't play a sound";
- message = $msg({
- from: 'lounge@montague.lit/otheruser',
- id: '2',
- to: 'romeo@montague.lit',
- type: 'groupchat'
- }).c('body').t(text);
- await view.model.handleMessageStanza(message.nodeTree);
- expect(window.Audio, 1);
- _converse.play_sounds = false;
- text = "This message won't play a sound because it is sent by romeo";
- message = $msg({
- from: 'lounge@montague.lit/romeo',
- id: '3',
- to: 'romeo@montague.lit',
- type: 'groupchat'
- }).c('body').t(text);
- await view.model.handleMessageStanza(message.nodeTree);
- expect(window.Audio, 1);
- _converse.play_sounds = false;
- done();
- }));
- });
- });
- describe("A Favicon Message Counter", function () {
- it("is incremented when the message is received and the window is not focused",
- mock.initConverse([], {'show_tab_notifications': false}, async function (done, _converse) {
- await mock.waitForRoster(_converse, 'current');
- await mock.openControlBox(_converse);
- const favico = jasmine.createSpyObj('favico', ['badge']);
- spyOn(converse.env, 'Favico').and.returnValue(favico);
- const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
- const previous_state = _converse.windowState;
- const msg = $msg({
- from: sender_jid,
- to: _converse.connection.jid,
- type: 'chat',
- id: u.getUniqueId()
- }).c('body').t('This message will increment the message counter').up()
- .c('active', {'xmlns': Strophe.NS.CHATSTATES}).tree();
- _converse.windowState = 'hidden';
- spyOn(_converse.api, "trigger").and.callThrough();
- await _converse.handleMessageStanza(msg);
- expect(_converse.api.trigger).toHaveBeenCalledWith('message', jasmine.any(Object));
- expect(favico.badge.calls.count()).toBe(0);
- _converse.api.settings.set('show_tab_notifications', true);
- const msg2 = $msg({
- from: sender_jid,
- to: _converse.connection.jid,
- type: 'chat',
- id: u.getUniqueId()
- }).c('body').t('This message increment the message counter AND update the page title').up()
- .c('active', {'xmlns': Strophe.NS.CHATSTATES}).tree();
- await _converse.handleMessageStanza(msg2);
- await u.waitUntil(() => favico.badge.calls.count() === 1);
- expect(favico.badge.calls.mostRecent().args.pop()).toBe(2);
- const view = _converse.chatboxviews.get(sender_jid);
- expect(view.model.get('num_unread')).toBe(2);
- // Check that it's cleared when the window is focused
- _converse.windowState = 'hidden';
- _converse.saveWindowState({'type': 'focus'});
- await u.waitUntil(() => favico.badge.calls.count() === 2);
- expect(favico.badge.calls.mostRecent().args.pop()).toBe(0);
- expect(view.model.get('num_unread')).toBe(0);
- _converse.windowSate = previous_state;
- done();
- }));
- it("is not incremented when the message is received and the window is focused",
- mock.initConverse([], {}, async function (done, _converse) {
- await mock.waitForRoster(_converse, 'current');
- await mock.openControlBox(_converse);
- const favico = jasmine.createSpyObj('favico', ['badge']);
- spyOn(converse.env, 'Favico').and.returnValue(favico);
- _converse.saveWindowState({'type': 'focus'});
- const message = 'This message will not increment the message counter';
- const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit',
- msg = $msg({
- from: sender_jid,
- to: _converse.connection.jid,
- type: 'chat',
- id: u.getUniqueId()
- }).c('body').t(message).up()
- .c('active', {'xmlns': Strophe.NS.CHATSTATES}).tree();
- await _converse.handleMessageStanza(msg);
- setTimeout(() => {
- const view = _converse.chatboxviews.get(sender_jid);
- expect(view.model.get('num_unread')).toBe(0);
- expect(favico.badge.calls.count()).toBe(0);
- done();
- }, 500);
- }));
- it("is incremented from zero when chatbox was closed after viewing previously received messages and the window is not focused now",
- mock.initConverse([], {}, async function (done, _converse) {
- await mock.waitForRoster(_converse, 'current');
- const favico = jasmine.createSpyObj('favico', ['badge']);
- spyOn(converse.env, 'Favico').and.returnValue(favico);
- const message = 'This message will always increment the message counter from zero';
- const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
- const msgFactory = function () {
- return $msg({
- from: sender_jid,
- to: _converse.connection.jid,
- type: 'chat',
- id: u.getUniqueId()
- })
- .c('body').t(message).up()
- .c('active', {'xmlns': Strophe.NS.CHATSTATES})
- .tree();
- };
- // leave converse-chat page
- _converse.windowState = 'hidden';
- await _converse.handleMessageStanza(msgFactory());
- let view = _converse.chatboxviews.get(sender_jid);
- await u.waitUntil(() => favico.badge.calls.count() === 1, 1000);
- expect(favico.badge.calls.mostRecent().args.pop()).toBe(1);
- // come back to converse-chat page
- _converse.saveWindowState({'type': 'focus'});
- await u.waitUntil(() => u.isVisible(view));
- await u.waitUntil(() => favico.badge.calls.count() === 2);
- expect(favico.badge.calls.mostRecent().args.pop()).toBe(0);
- // close chatbox and leave converse-chat page again
- view.close();
- _converse.windowState = 'hidden';
- // check that msg_counter is incremented from zero again
- await _converse.handleMessageStanza(msgFactory());
- view = _converse.chatboxviews.get(sender_jid);
- await u.waitUntil(() => u.isVisible(view));
- await u.waitUntil(() => favico.badge.calls.count() === 3);
- expect(favico.badge.calls.mostRecent().args.pop()).toBe(1);
- done();
- }));
- });
- });
|