Show chat state notifications inside the scrollable area

Rename CSS class to conform to convention
This commit is contained in:
JC Brand 2020-03-24 10:20:11 +01:00
parent 4727f3b3bb
commit 7812d4e7b6
10 changed files with 244 additions and 269 deletions

View File

@ -222,6 +222,16 @@
background-color: var(--chat-content-background-color); background-color: var(--chat-content-background-color);
line-height: 1.3em; line-height: 1.3em;
.chat-content__notifications {
white-space: pre;
background-color: var(--chat-content-background-color);
color: var(--subdued-color);
font-size: 90%;
font-style: italic;
line-height: var(--line-height-small);
padding: 0 1em 0.3em;
}
video { video {
width: 100% width: 100%
} }
@ -235,16 +245,6 @@
height: calc(100% - (var(--chat-textarea-height) + var(--send-button-height) + 2 * var(--send-button-margin))); height: calc(100% - (var(--chat-textarea-height) + var(--send-button-height) + 2 * var(--send-button-margin)));
} }
.chat-state-notifications {
white-space: pre;
background-color: var(--chat-content-background-color);
color: var(--subdued-color);
font-size: 90%;
font-style: italic;
line-height: var(--line-height-small);
padding: 0 1em 0.3em;
}
.dropdown { /* status dropdown styles */ .dropdown { /* status dropdown styles */
background-color: var(--light-background-color); background-color: var(--light-background-color);
dd { dd {

View File

@ -689,7 +689,7 @@
_converse.connection._dataRecv(test_utils.createRequest(msg)); _converse.connection._dataRecv(test_utils.createRequest(msg));
const view = _converse.chatboxviews.get(sender_jid); const view = _converse.chatboxviews.get(sender_jid);
let csn = mock.cur_names[1] + ' is typing'; let csn = mock.cur_names[1] + ' is typing';
await u.waitUntil( () => view.el.querySelector('.chat-state-notifications').innerText === csn); await u.waitUntil( () => view.el.querySelector('.chat-content__notifications').innerText === csn);
expect(view.model.messages.length).toEqual(0); expect(view.model.messages.length).toEqual(0);
// <paused> state // <paused> state
@ -701,7 +701,7 @@
}).c('paused', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('paused', {'xmlns': Strophe.NS.CHATSTATES}).tree();
_converse.connection._dataRecv(test_utils.createRequest(msg)); _converse.connection._dataRecv(test_utils.createRequest(msg));
csn = mock.cur_names[1] + ' has stopped typing'; csn = mock.cur_names[1] + ' has stopped typing';
await u.waitUntil( () => view.el.querySelector('.chat-state-notifications').innerText === csn); await u.waitUntil( () => view.el.querySelector('.chat-content__notifications').innerText === csn);
msg = $msg({ msg = $msg({
from: sender_jid, from: sender_jid,
@ -711,7 +711,7 @@
}).c('body').t('hello world').tree(); }).c('body').t('hello world').tree();
await _converse.handleMessageStanza(msg); await _converse.handleMessageStanza(msg);
const msg_el = await u.waitUntil(() => view.content.querySelector('.chat-msg')); const msg_el = await u.waitUntil(() => view.content.querySelector('.chat-msg'));
await u.waitUntil( () => view.el.querySelector('.chat-state-notifications').innerText === ''); await u.waitUntil( () => view.el.querySelector('.chat-content__notifications').innerText === '');
expect(msg_el.querySelector('.chat-msg__text').textContent).toBe('hello world'); expect(msg_el.querySelector('.chat-msg__text').textContent).toBe('hello world');
done(); done();
})); }));
@ -748,7 +748,7 @@
await u.waitUntil(() => u.shouldCreateMessage.calls.count()); await u.waitUntil(() => u.shouldCreateMessage.calls.count());
expect(view.model.messages.length).toEqual(0); expect(view.model.messages.length).toEqual(0);
const el = view.el.querySelector('.chat-state-notifications'); const el = view.el.querySelector('.chat-content__notifications');
expect(el.textContent).toBe(''); expect(el.textContent).toBe('');
done(); done();
})); }));
@ -833,7 +833,7 @@
_converse.connection._dataRecv(test_utils.createRequest(msg)); _converse.connection._dataRecv(test_utils.createRequest(msg));
const csn = mock.cur_names[1] + ' has stopped typing'; const csn = mock.cur_names[1] + ' has stopped typing';
await u.waitUntil( () => view.el.querySelector('.chat-state-notifications').innerText === csn); await u.waitUntil( () => view.el.querySelector('.chat-content__notifications').innerText === csn);
expect(view.model.messages.length).toEqual(0); expect(view.model.messages.length).toEqual(0);
done(); done();
})); }));
@ -867,7 +867,7 @@
_converse.connection._dataRecv(test_utils.createRequest(msg)); _converse.connection._dataRecv(test_utils.createRequest(msg));
await u.waitUntil(() => u.shouldCreateMessage.calls.count()); await u.waitUntil(() => u.shouldCreateMessage.calls.count());
expect(view.model.messages.length).toEqual(0); expect(view.model.messages.length).toEqual(0);
const el = view.el.querySelector('.chat-state-notifications'); const el = view.el.querySelector('.chat-content__notifications');
expect(el.textContent).toBe(''); expect(el.textContent).toBe('');
done(); done();
done(); done();
@ -1007,7 +1007,7 @@
.c('composing', {'xmlns': Strophe.NS.CHATSTATES}).up() .c('composing', {'xmlns': Strophe.NS.CHATSTATES}).up()
.tree(); .tree();
_converse.connection._dataRecv(test_utils.createRequest(msg)); _converse.connection._dataRecv(test_utils.createRequest(msg));
const csntext = await u.waitUntil(() => view.el.querySelector('.chat-state-notifications').textContent); const csntext = await u.waitUntil(() => view.el.querySelector('.chat-content__notifications').textContent);
expect(csntext).toEqual(mock.cur_names[1] + ' is typing'); expect(csntext).toEqual(mock.cur_names[1] + ' is typing');
expect(view.model.messages.length).toBe(0); expect(view.model.messages.length).toBe(0);
@ -1019,7 +1019,7 @@
}).c('inactive', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('inactive', {'xmlns': Strophe.NS.CHATSTATES}).tree();
_converse.connection._dataRecv(test_utils.createRequest(msg)); _converse.connection._dataRecv(test_utils.createRequest(msg));
await u.waitUntil(() => !view.el.querySelector('.chat-state-notifications').textContent); await u.waitUntil(() => !view.el.querySelector('.chat-content__notifications').textContent);
done(); done();
})); }));
}); });
@ -1045,7 +1045,7 @@
_converse.connection._dataRecv(test_utils.createRequest(msg)); _converse.connection._dataRecv(test_utils.createRequest(msg));
const view = _converse.chatboxviews.get(sender_jid); const view = _converse.chatboxviews.get(sender_jid);
const csntext = await u.waitUntil(() => view.el.querySelector('.chat-state-notifications').textContent); const csntext = await u.waitUntil(() => view.el.querySelector('.chat-content__notifications').textContent);
expect(csntext).toEqual(mock.cur_names[1] + ' has gone away'); expect(csntext).toEqual(mock.cur_names[1] + ' has gone away');
done(); done();
})); }));
@ -1092,7 +1092,7 @@
}).c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
_converse.connection._dataRecv(test_utils.createRequest(msg)); _converse.connection._dataRecv(test_utils.createRequest(msg));
const csntext = await u.waitUntil(() => view.el.querySelector('.chat-state-notifications').textContent); const csntext = await u.waitUntil(() => view.el.querySelector('.chat-content__notifications').textContent);
expect(csntext).toEqual(mock.cur_names[1] + ' is typing'); expect(csntext).toEqual(mock.cur_names[1] + ' is typing');
// Edited message // Edited message
@ -1107,7 +1107,7 @@
.c('replace', {'xmlns': Strophe.NS.MESSAGE_CORRECT, 'id': original_id }).tree(); .c('replace', {'xmlns': Strophe.NS.MESSAGE_CORRECT, 'id': original_id }).tree();
await _converse.handleMessageStanza(edited); await _converse.handleMessageStanza(edited);
await u.waitUntil(() => !view.el.querySelector('.chat-state-notifications').textContent); await u.waitUntil(() => !view.el.querySelector('.chat-content__notifications').textContent);
done(); done();
})); }));
}); });

View File

@ -173,8 +173,7 @@
await new Promise(resolve => _converse.on('chatBoxViewInitialized', resolve)); await new Promise(resolve => _converse.on('chatBoxViewInitialized', resolve));
const view = _converse.api.chatviews.get(sender_jid); const view = _converse.api.chatviews.get(sender_jid);
await new Promise(resolve => view.once('messageInserted', resolve)); await new Promise(resolve => view.once('messageInserted', resolve));
const chat_content = view.el.querySelector('.chat-content'); let message = view.content.querySelector('.chat-msg__text');
let message = chat_content.querySelector('.chat-msg__text');
expect(u.hasClass('chat-msg__text--larger', message)).toBe(true); expect(u.hasClass('chat-msg__text--larger', message)).toBe(true);
_converse.handleMessageStanza($msg({ _converse.handleMessageStanza($msg({
@ -185,7 +184,7 @@
}).c('body').t('😇 Hello world! 😇 😇').up() }).c('body').t('😇 Hello world! 😇 😇').up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
await new Promise(resolve => view.once('messageInserted', resolve)); await new Promise(resolve => view.once('messageInserted', resolve));
message = chat_content.querySelector('.message:last-child .chat-msg__text'); message = view.content.querySelector('.message:last-child .chat-msg__text');
expect(u.hasClass('chat-msg__text--larger', message)).toBe(false); expect(u.hasClass('chat-msg__text--larger', message)).toBe(false);
// Test that a modified message that no longer contains only // Test that a modified message that no longer contains only
@ -199,7 +198,7 @@
}); });
await new Promise(resolve => view.once('messageInserted', resolve)); await new Promise(resolve => view.once('messageInserted', resolve));
expect(view.el.querySelectorAll('.chat-msg').length).toBe(3); expect(view.el.querySelectorAll('.chat-msg').length).toBe(3);
expect(chat_content.querySelector('.message:last-child .chat-msg__text').textContent).toBe('💩 😇'); expect(view.content.querySelector('.message:last-child .chat-msg__text').textContent).toBe('💩 😇');
expect(textarea.value).toBe(''); expect(textarea.value).toBe('');
view.onKeyDown({ view.onKeyDown({
target: textarea, target: textarea,
@ -216,7 +215,7 @@
}); });
await new Promise(resolve => view.model.messages.once('rendered', resolve)); await new Promise(resolve => view.model.messages.once('rendered', resolve));
expect(view.model.messages.models.length).toBe(3); expect(view.model.messages.models.length).toBe(3);
message = chat_content.querySelector('.message:last-child .chat-msg__text'); message = view.content.querySelector('.message:last-child .chat-msg__text');
expect(u.hasClass('chat-msg__text--larger', message)).toBe(false); expect(u.hasClass('chat-msg__text--larger', message)).toBe(false);
textarea.value = ':smile: Hello world!'; textarea.value = ':smile: Hello world!';
@ -235,7 +234,7 @@
}); });
await new Promise(resolve => view.once('messageInserted', resolve)); await new Promise(resolve => view.once('messageInserted', resolve));
message = chat_content.querySelector('.message:last-child .chat-msg__text'); message = view.content.querySelector('.message:last-child .chat-msg__text');
expect(u.hasClass('chat-msg__text--larger', message)).toBe(true); expect(u.hasClass('chat-msg__text--larger', message)).toBe(true);
done() done()
})); }));

View File

@ -454,55 +454,54 @@
await _converse.handleMessageStanza(msg); await _converse.handleMessageStanza(msg);
await new Promise(resolve => view.once('messageInserted', resolve)); await new Promise(resolve => view.once('messageInserted', resolve));
const chat_content = view.el.querySelector('.chat-content');
view.clearSpinner(); //cleanup view.clearSpinner(); //cleanup
expect(chat_content.querySelectorAll('.date-separator').length).toEqual(4); expect(view.content.querySelectorAll('.date-separator').length).toEqual(4);
let day = sizzle('.date-separator:first', chat_content).pop(); let day = sizzle('.date-separator:first', view.content).pop();
expect(day.getAttribute('data-isodate')).toEqual(dayjs('2017-12-31T00:00:00').toISOString()); expect(day.getAttribute('data-isodate')).toEqual(dayjs('2017-12-31T00:00:00').toISOString());
let time = sizzle('time:first', chat_content).pop(); let time = sizzle('time:first', view.content).pop();
expect(time.textContent).toEqual('Sunday Dec 31st 2017') expect(time.textContent).toEqual('Sunday Dec 31st 2017')
day = sizzle('.date-separator:first', chat_content).pop(); day = sizzle('.date-separator:first', view.content).pop();
expect(day.nextElementSibling.querySelector('.chat-msg__text').textContent).toBe('Older message'); expect(day.nextElementSibling.querySelector('.chat-msg__text').textContent).toBe('Older message');
let el = sizzle('.chat-msg:first', chat_content).pop().querySelector('.chat-msg__text') let el = sizzle('.chat-msg:first', view.content).pop().querySelector('.chat-msg__text')
expect(u.hasClass('chat-msg--followup', el)).toBe(false); expect(u.hasClass('chat-msg--followup', el)).toBe(false);
expect(el.textContent).toEqual('Older message'); expect(el.textContent).toEqual('Older message');
time = sizzle('time.separator-text:eq(1)', chat_content).pop(); time = sizzle('time.separator-text:eq(1)', view.content).pop();
expect(time.textContent).toEqual("Monday Jan 1st 2018"); expect(time.textContent).toEqual("Monday Jan 1st 2018");
day = sizzle('.date-separator:eq(1)', chat_content).pop(); day = sizzle('.date-separator:eq(1)', view.content).pop();
expect(day.getAttribute('data-isodate')).toEqual(dayjs('2018-01-01T00:00:00').toISOString()); expect(day.getAttribute('data-isodate')).toEqual(dayjs('2018-01-01T00:00:00').toISOString());
expect(day.nextElementSibling.querySelector('.chat-msg__text').textContent).toBe('Inbetween message'); expect(day.nextElementSibling.querySelector('.chat-msg__text').textContent).toBe('Inbetween message');
el = sizzle('.chat-msg:eq(1)', chat_content).pop(); el = sizzle('.chat-msg:eq(1)', view.content).pop();
expect(el.querySelector('.chat-msg__text').textContent).toEqual('Inbetween message'); expect(el.querySelector('.chat-msg__text').textContent).toEqual('Inbetween message');
expect(el.nextElementSibling.querySelector('.chat-msg__text').textContent).toEqual('another inbetween message'); expect(el.nextElementSibling.querySelector('.chat-msg__text').textContent).toEqual('another inbetween message');
el = sizzle('.chat-msg:eq(2)', chat_content).pop(); el = sizzle('.chat-msg:eq(2)', view.content).pop();
expect(el.querySelector('.chat-msg__text').textContent) expect(el.querySelector('.chat-msg__text').textContent)
.toEqual('another inbetween message'); .toEqual('another inbetween message');
expect(u.hasClass('chat-msg--followup', el)).toBe(true); expect(u.hasClass('chat-msg--followup', el)).toBe(true);
time = sizzle('time.separator-text:nth(2)', chat_content).pop(); time = sizzle('time.separator-text:nth(2)', view.content).pop();
expect(time.textContent).toEqual("Tuesday Jan 2nd 2018"); expect(time.textContent).toEqual("Tuesday Jan 2nd 2018");
day = sizzle('.date-separator:nth(2)', chat_content).pop(); day = sizzle('.date-separator:nth(2)', view.content).pop();
expect(day.getAttribute('data-isodate')).toEqual(dayjs('2018-01-02T00:00:00').toISOString()); expect(day.getAttribute('data-isodate')).toEqual(dayjs('2018-01-02T00:00:00').toISOString());
expect(day.nextElementSibling.querySelector('.chat-msg__text').textContent).toBe('An earlier message on the next day'); expect(day.nextElementSibling.querySelector('.chat-msg__text').textContent).toBe('An earlier message on the next day');
el = sizzle('.chat-msg:eq(3)', chat_content).pop(); el = sizzle('.chat-msg:eq(3)', view.content).pop();
expect(el.querySelector('.chat-msg__text').textContent).toEqual('An earlier message on the next day'); expect(el.querySelector('.chat-msg__text').textContent).toEqual('An earlier message on the next day');
expect(u.hasClass('chat-msg--followup', el)).toBe(false); expect(u.hasClass('chat-msg--followup', el)).toBe(false);
el = sizzle('.chat-msg:eq(4)', chat_content).pop(); el = sizzle('.chat-msg:eq(4)', view.content).pop();
expect(el.querySelector('.chat-msg__text').textContent).toEqual('message'); expect(el.querySelector('.chat-msg__text').textContent).toEqual('message');
expect(el.nextElementSibling.querySelector('.chat-msg__text').textContent).toEqual('newer message from the next day'); expect(el.nextElementSibling.querySelector('.chat-msg__text').textContent).toEqual('newer message from the next day');
expect(u.hasClass('chat-msg--followup', el)).toBe(false); expect(u.hasClass('chat-msg--followup', el)).toBe(false);
day = sizzle('.date-separator:last', chat_content).pop(); day = sizzle('.date-separator:last', view.content).pop();
expect(day.getAttribute('data-isodate')).toEqual(dayjs().startOf('day').toISOString()); expect(day.getAttribute('data-isodate')).toEqual(dayjs().startOf('day').toISOString());
expect(day.nextElementSibling.querySelector('.chat-msg__text').textContent).toBe('latest message'); expect(day.nextElementSibling.querySelector('.chat-msg__text').textContent).toBe('latest message');
expect(u.hasClass('chat-msg--followup', el)).toBe(false); expect(u.hasClass('chat-msg--followup', el)).toBe(false);
@ -570,7 +569,6 @@
'type': 'chat' 'type': 'chat'
}).c('body').t(msgtext).tree(); }).c('body').t(msgtext).tree();
console.log('AAAAAAAAAAAAAAAAAAAAAAAAAAA')
await _converse.handleMessageStanza(msg); await _converse.handleMessageStanza(msg);
const chatbox = _converse.chatboxes.get(sender_jid); const chatbox = _converse.chatboxes.get(sender_jid);
const view = _converse.chatboxviews.get(sender_jid); const view = _converse.chatboxviews.get(sender_jid);
@ -578,7 +576,6 @@
expect(chatbox).toBeDefined(); expect(chatbox).toBeDefined();
expect(view).toBeDefined(); expect(view).toBeDefined();
// Check that the message was received and check the message parameters // Check that the message was received and check the message parameters
console.log('BBBBBBBBBBBBBBBBBBBBBBBBBBB')
await u.waitUntil(() => chatbox.messages.length); await u.waitUntil(() => chatbox.messages.length);
const msg_obj = chatbox.messages.models[0]; const msg_obj = chatbox.messages.models[0];
expect(msg_obj.get('message')).toEqual(msgtext); expect(msg_obj.get('message')).toEqual(msgtext);
@ -587,15 +584,12 @@
expect(msg_obj.get('sender')).toEqual('them'); expect(msg_obj.get('sender')).toEqual('them');
expect(msg_obj.get('is_delayed')).toEqual(false); expect(msg_obj.get('is_delayed')).toEqual(false);
// Now check that the message appears inside the chatbox in the DOM // Now check that the message appears inside the chatbox in the DOM
const chat_content = view.el.querySelector('.chat-content'); await u.waitUntil(() => view.content.querySelector('.chat-msg .chat-msg__text'));
console.log('CCCCCCCCCCCCCCCCCCCCCCCCCCC')
await u.waitUntil(() => chat_content.querySelector('.chat-msg .chat-msg__text'));
expect(chat_content.querySelector('.chat-msg .chat-msg__text').textContent).toEqual(msgtext); expect(view.content.querySelector('.chat-msg .chat-msg__text').textContent).toEqual(msgtext);
expect(chat_content.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy(); expect(view.content.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy();
console.log('DDDDDDDDDDDDDDDDDDDDDDDDDDD')
await u.waitUntil(() => chatbox.vcard.get('fullname') === 'Juliet Capulet') await u.waitUntil(() => chatbox.vcard.get('fullname') === 'Juliet Capulet')
expect(chat_content.querySelector('span.chat-msg__author').textContent.trim()).toBe('Juliet Capulet'); expect(view.content.querySelector('span.chat-msg__author').textContent.trim()).toBe('Juliet Capulet');
done(); done();
})); }));
@ -794,17 +788,16 @@
expect(msg_obj.get('sender')).toEqual('them'); expect(msg_obj.get('sender')).toEqual('them');
expect(msg_obj.get('is_delayed')).toEqual(true); expect(msg_obj.get('is_delayed')).toEqual(true);
await u.waitUntil(() => chatbox.vcard.get('fullname') === 'Juliet Capulet') await u.waitUntil(() => chatbox.vcard.get('fullname') === 'Juliet Capulet')
const chat_content = view.el.querySelector('.chat-content'); expect(view.content.querySelector('.chat-msg .chat-msg__text').textContent).toEqual(message);
expect(chat_content.querySelector('.chat-msg .chat-msg__text').textContent).toEqual(message); expect(view.content.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy();
expect(chat_content.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy(); expect(view.content.querySelector('span.chat-msg__author').textContent.trim()).toBe('Juliet Capulet');
expect(chat_content.querySelector('span.chat-msg__author').textContent.trim()).toBe('Juliet Capulet');
expect(chat_content.querySelectorAll('.date-separator').length).toEqual(1); expect(view.content.querySelectorAll('.date-separator').length).toEqual(1);
let day = chat_content.querySelector('.date-separator'); let day = view.content.querySelector('.date-separator');
expect(day.getAttribute('class')).toEqual('message date-separator'); expect(day.getAttribute('class')).toEqual('message date-separator');
expect(day.getAttribute('data-isodate')).toEqual(dayjs(one_day_ago.startOf('day')).toISOString()); expect(day.getAttribute('data-isodate')).toEqual(dayjs(one_day_ago.startOf('day')).toISOString());
let time = chat_content.querySelector('time.separator-text'); let time = view.content.querySelector('time.separator-text');
expect(time.textContent).toEqual(dayjs(one_day_ago.startOf('day')).format("dddd MMM Do YYYY")); expect(time.textContent).toEqual(dayjs(one_day_ago.startOf('day')).format("dddd MMM Do YYYY"));
message = 'This is a current message'; message = 'This is a current message';
@ -820,15 +813,15 @@
expect(_converse.api.trigger).toHaveBeenCalledWith('message', jasmine.any(Object)); expect(_converse.api.trigger).toHaveBeenCalledWith('message', jasmine.any(Object));
// Check that there is a <time> element, with the required props. // Check that there is a <time> element, with the required props.
expect(chat_content.querySelectorAll('time.separator-text').length).toEqual(2); // There are now two time elements expect(view.content.querySelectorAll('time.separator-text').length).toEqual(2); // There are now two time elements
const message_date = new Date(); const message_date = new Date();
day = sizzle('.date-separator:last', chat_content); day = sizzle('.date-separator:last', view.content);
expect(day.length).toEqual(1); expect(day.length).toEqual(1);
expect(day[0].getAttribute('class')).toEqual('message date-separator'); expect(day[0].getAttribute('class')).toEqual('message date-separator');
expect(day[0].getAttribute('data-isodate')).toEqual(dayjs(message_date).startOf('day').toISOString()); expect(day[0].getAttribute('data-isodate')).toEqual(dayjs(message_date).startOf('day').toISOString());
time = sizzle('time.separator-text:last', chat_content).pop(); time = sizzle('time.separator-text:last', view.content).pop();
expect(time.textContent).toEqual(dayjs(message_date).startOf('day').format("dddd MMM Do YYYY")); expect(time.textContent).toEqual(dayjs(message_date).startOf('day').format("dddd MMM Do YYYY"));
// Normal checks for the 2nd message // Normal checks for the 2nd message
@ -838,12 +831,12 @@
expect(msg_obj.get('fullname')).toBeUndefined(); expect(msg_obj.get('fullname')).toBeUndefined();
expect(msg_obj.get('sender')).toEqual('them'); expect(msg_obj.get('sender')).toEqual('them');
expect(msg_obj.get('is_delayed')).toEqual(false); expect(msg_obj.get('is_delayed')).toEqual(false);
const msg_txt = sizzle('.chat-msg:last .chat-msg__text', chat_content).pop().textContent; const msg_txt = sizzle('.chat-msg:last .chat-msg__text', view.content).pop().textContent;
expect(msg_txt).toEqual(message); expect(msg_txt).toEqual(message);
expect(chat_content.querySelector('.chat-msg:last-child .chat-msg__text').textContent).toEqual(message); expect(view.content.querySelector('.chat-msg:last-child .chat-msg__text').textContent).toEqual(message);
expect(chat_content.querySelector('.chat-msg:last-child .chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy(); expect(view.content.querySelector('.chat-msg:last-child .chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy();
expect(chat_content.querySelector('.chat-msg:last-child .chat-msg__author').textContent.trim()).toBe('Juliet Capulet'); expect(view.content.querySelector('.chat-msg:last-child .chat-msg__author').textContent.trim()).toBe('Juliet Capulet');
done(); done();
})); }));
@ -905,8 +898,7 @@
</message>`); </message>`);
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
await new Promise(resolve => view.once('messageInserted', resolve)); await new Promise(resolve => view.once('messageInserted', resolve));
const chat_content = view.el.querySelector('.chat-content'); expect(view.content.querySelector('.chat-msg__text').innerHTML).toBe('Hey<br>Have you heard the news?');
expect(chat_content.querySelector('.chat-msg__text').innerHTML).toBe('Hey<br>Have you heard the news?');
stanza = u.toStanza(` stanza = u.toStanza(`
<message from="${contact_jid}" <message from="${contact_jid}"
type="chat" type="chat"
@ -915,7 +907,7 @@
</message>`); </message>`);
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
await new Promise(resolve => view.once('messageInserted', resolve)); await new Promise(resolve => view.once('messageInserted', resolve));
expect(chat_content.querySelector('.message:last-child .chat-msg__text').innerHTML).toBe('Hey<br><br>Have you heard the news?'); expect(view.content.querySelector('.message:last-child .chat-msg__text').innerHTML).toBe('Hey<br><br>Have you heard the news?');
stanza = u.toStanza(` stanza = u.toStanza(`
<message from="${contact_jid}" <message from="${contact_jid}"
type="chat" type="chat"
@ -924,7 +916,7 @@
</message>`); </message>`);
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
await new Promise(resolve => view.once('messageInserted', resolve)); await new Promise(resolve => view.once('messageInserted', resolve));
expect(chat_content.querySelector('.message:last-child .chat-msg__text').innerHTML).toBe('Hey<br>Have you heard<br>the news?'); expect(view.content.querySelector('.message:last-child .chat-msg__text').innerHTML).toBe('Hey<br>Have you heard<br>the news?');
done(); done();
})); }));
@ -966,10 +958,9 @@
// Non-https images aren't rendered // Non-https images aren't rendered
message = base_url+"/logo/conversejs-filled.svg"; message = base_url+"/logo/conversejs-filled.svg";
const chat_content = view.el.querySelector('.chat-content'); expect(view.content.querySelectorAll('img').length).toBe(4);
expect(chat_content.querySelectorAll('img').length).toBe(4);
test_utils.sendMessage(view, message); test_utils.sendMessage(view, message);
expect(chat_content.querySelectorAll('img').length).toBe(4); expect(view.content.querySelectorAll('img').length).toBe(4);
done(); done();
})); }));
@ -1060,24 +1051,23 @@
await new Promise(resolve => view.once('messageInserted', resolve)); await new Promise(resolve => view.once('messageInserted', resolve));
jasmine.clock().tick(1*ONE_MINUTE_LATER); jasmine.clock().tick(1*ONE_MINUTE_LATER);
const chat_content = view.el.querySelector('.chat-content');
await test_utils.sendMessage(view, "Another message within 10 minutes, but from a different person"); await test_utils.sendMessage(view, "Another message within 10 minutes, but from a different person");
expect(chat_content.querySelectorAll('.message').length).toBe(6); expect(view.content.querySelectorAll('.message').length).toBe(6);
expect(chat_content.querySelectorAll('.chat-msg').length).toBe(5); expect(view.content.querySelectorAll('.chat-msg').length).toBe(5);
expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(2)'))).toBe(false); expect(u.hasClass('chat-msg--followup', view.content.querySelector('.message:nth-child(2)'))).toBe(false);
expect(chat_content.querySelector('.message:nth-child(2) .chat-msg__text').textContent).toBe("A message"); expect(view.content.querySelector('.message:nth-child(2) .chat-msg__text').textContent).toBe("A message");
expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(3)'))).toBe(true); expect(u.hasClass('chat-msg--followup', view.content.querySelector('.message:nth-child(3)'))).toBe(true);
expect(chat_content.querySelector('.message:nth-child(3) .chat-msg__text').textContent).toBe( expect(view.content.querySelector('.message:nth-child(3) .chat-msg__text').textContent).toBe(
"Another message 3 minutes later"); "Another message 3 minutes later");
expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(4)'))).toBe(false); expect(u.hasClass('chat-msg--followup', view.content.querySelector('.message:nth-child(4)'))).toBe(false);
expect(chat_content.querySelector('.message:nth-child(4) .chat-msg__text').textContent).toBe( expect(view.content.querySelector('.message:nth-child(4) .chat-msg__text').textContent).toBe(
"Another message 14 minutes since we started"); "Another message 14 minutes since we started");
expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(5)'))).toBe(true); expect(u.hasClass('chat-msg--followup', view.content.querySelector('.message:nth-child(5)'))).toBe(true);
expect(chat_content.querySelector('.message:nth-child(5) .chat-msg__text').textContent).toBe( expect(view.content.querySelector('.message:nth-child(5) .chat-msg__text').textContent).toBe(
"Another message 1 minute and 1 second since the previous one"); "Another message 1 minute and 1 second since the previous one");
expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(6)'))).toBe(false); expect(u.hasClass('chat-msg--followup', view.content.querySelector('.message:nth-child(6)'))).toBe(false);
expect(chat_content.querySelector('.message:nth-child(6) .chat-msg__text').textContent).toBe( expect(view.content.querySelector('.message:nth-child(6) .chat-msg__text').textContent).toBe(
"Another message within 10 minutes, but from a different person"); "Another message within 10 minutes, but from a different person");
// Let's add a delayed, inbetween message // Let's add a delayed, inbetween message
@ -1093,24 +1083,24 @@
.tree()); .tree());
await new Promise(resolve => view.once('messageInserted', resolve)); await new Promise(resolve => view.once('messageInserted', resolve));
expect(chat_content.querySelectorAll('.message').length).toBe(7); expect(view.content.querySelectorAll('.message').length).toBe(7);
expect(chat_content.querySelectorAll('.chat-msg').length).toBe(6); expect(view.content.querySelectorAll('.chat-msg').length).toBe(6);
expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(2)'))).toBe(false); expect(u.hasClass('chat-msg--followup', view.content.querySelector('.message:nth-child(2)'))).toBe(false);
expect(chat_content.querySelector('.message:nth-child(2) .chat-msg__text').textContent).toBe("A message"); expect(view.content.querySelector('.message:nth-child(2) .chat-msg__text').textContent).toBe("A message");
expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(3)'))).toBe(true); expect(u.hasClass('chat-msg--followup', view.content.querySelector('.message:nth-child(3)'))).toBe(true);
expect(chat_content.querySelector('.message:nth-child(3) .chat-msg__text').textContent).toBe( expect(view.content.querySelector('.message:nth-child(3) .chat-msg__text').textContent).toBe(
"Another message 3 minutes later"); "Another message 3 minutes later");
expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(4)'))).toBe(true); expect(u.hasClass('chat-msg--followup', view.content.querySelector('.message:nth-child(4)'))).toBe(true);
expect(chat_content.querySelector('.message:nth-child(4) .chat-msg__text').textContent).toBe( expect(view.content.querySelector('.message:nth-child(4) .chat-msg__text').textContent).toBe(
"A delayed message, sent 5 minutes since we started"); "A delayed message, sent 5 minutes since we started");
expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(5)'))).toBe(false); expect(u.hasClass('chat-msg--followup', view.content.querySelector('.message:nth-child(5)'))).toBe(false);
expect(chat_content.querySelector('.message:nth-child(5) .chat-msg__text').textContent).toBe( expect(view.content.querySelector('.message:nth-child(5) .chat-msg__text').textContent).toBe(
"Another message 14 minutes since we started"); "Another message 14 minutes since we started");
expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(6)'))).toBe(true); expect(u.hasClass('chat-msg--followup', view.content.querySelector('.message:nth-child(6)'))).toBe(true);
expect(chat_content.querySelector('.message:nth-child(6) .chat-msg__text').textContent).toBe( expect(view.content.querySelector('.message:nth-child(6) .chat-msg__text').textContent).toBe(
"Another message 1 minute and 1 second since the previous one"); "Another message 1 minute and 1 second since the previous one");
expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(7)'))).toBe(false); expect(u.hasClass('chat-msg--followup', view.content.querySelector('.message:nth-child(7)'))).toBe(false);
_converse.handleMessageStanza( _converse.handleMessageStanza(
$msg({ $msg({
@ -1124,27 +1114,27 @@
.tree()); .tree());
await new Promise(resolve => view.once('messageInserted', resolve)); await new Promise(resolve => view.once('messageInserted', resolve));
expect(chat_content.querySelectorAll('.message').length).toBe(8); expect(view.content.querySelectorAll('.message').length).toBe(8);
expect(chat_content.querySelectorAll('.chat-msg').length).toBe(7); expect(view.content.querySelectorAll('.chat-msg').length).toBe(7);
expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(2)'))).toBe(false); expect(u.hasClass('chat-msg--followup', view.content.querySelector('.message:nth-child(2)'))).toBe(false);
expect(chat_content.querySelector('.message:nth-child(2) .chat-msg__text').textContent).toBe("A message"); expect(view.content.querySelector('.message:nth-child(2) .chat-msg__text').textContent).toBe("A message");
expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(3)'))).toBe(true); expect(u.hasClass('chat-msg--followup', view.content.querySelector('.message:nth-child(3)'))).toBe(true);
expect(chat_content.querySelector('.message:nth-child(3) .chat-msg__text').textContent).toBe( expect(view.content.querySelector('.message:nth-child(3) .chat-msg__text').textContent).toBe(
"Another message 3 minutes later"); "Another message 3 minutes later");
expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(4)'))).toBe(false); expect(u.hasClass('chat-msg--followup', view.content.querySelector('.message:nth-child(4)'))).toBe(false);
expect(chat_content.querySelector('.message:nth-child(4) .chat-msg__text').textContent).toBe( expect(view.content.querySelector('.message:nth-child(4) .chat-msg__text').textContent).toBe(
"A carbon message 4 minutes later"); "A carbon message 4 minutes later");
expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(5)'))).toBe(false); expect(u.hasClass('chat-msg--followup', view.content.querySelector('.message:nth-child(5)'))).toBe(false);
expect(chat_content.querySelector('.message:nth-child(5) .chat-msg__text').textContent).toBe( expect(view.content.querySelector('.message:nth-child(5) .chat-msg__text').textContent).toBe(
"A delayed message, sent 5 minutes since we started"); "A delayed message, sent 5 minutes since we started");
expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(6)'))).toBe(false); expect(u.hasClass('chat-msg--followup', view.content.querySelector('.message:nth-child(6)'))).toBe(false);
expect(chat_content.querySelector('.message:nth-child(6) .chat-msg__text').textContent).toBe( expect(view.content.querySelector('.message:nth-child(6) .chat-msg__text').textContent).toBe(
"Another message 14 minutes since we started"); "Another message 14 minutes since we started");
expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(7)'))).toBe(true); expect(u.hasClass('chat-msg--followup', view.content.querySelector('.message:nth-child(7)'))).toBe(true);
expect(chat_content.querySelector('.message:nth-child(7) .chat-msg__text').textContent).toBe( expect(view.content.querySelector('.message:nth-child(7) .chat-msg__text').textContent).toBe(
"Another message 1 minute and 1 second since the previous one"); "Another message 1 minute and 1 second since the previous one");
expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(8)'))).toBe(false); expect(u.hasClass('chat-msg--followup', view.content.querySelector('.message:nth-child(8)'))).toBe(false);
expect(chat_content.querySelector('.message:nth-child(8) .chat-msg__text').textContent).toBe( expect(view.content.querySelector('.message:nth-child(8) .chat-msg__text').textContent).toBe(
"Another message within 10 minutes, but from a different person"); "Another message within 10 minutes, but from a different person");
jasmine.clock().uninstall(); jasmine.clock().uninstall();
@ -1345,12 +1335,11 @@
expect(msg_obj.get('sender')).toEqual('them'); expect(msg_obj.get('sender')).toEqual('them');
expect(msg_obj.get('is_delayed')).toEqual(false); expect(msg_obj.get('is_delayed')).toEqual(false);
// Now check that the message appears inside the chatbox in the DOM // Now check that the message appears inside the chatbox in the DOM
const chat_content = view.el.querySelector('.chat-content'); const mel = await u.waitUntil(() => view.content.querySelector('.chat-msg .chat-msg__text'));
const mel = await u.waitUntil(() => chat_content.querySelector('.chat-msg .chat-msg__text'));
expect(mel.textContent).toEqual(message); expect(mel.textContent).toEqual(message);
expect(chat_content.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy(); expect(view.content.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy();
await u.waitUntil(() => chatbox.vcard.get('fullname') === mock.cur_names[0]); await u.waitUntil(() => chatbox.vcard.get('fullname') === mock.cur_names[0]);
expect(chat_content.querySelector('span.chat-msg__author').textContent.trim()).toBe('Mercutio'); expect(view.content.querySelector('span.chat-msg__author').textContent.trim()).toBe('Mercutio');
done(); done();
})); }));
@ -1377,8 +1366,7 @@
expect(view.model.messages.length).toEqual(1); expect(view.model.messages.length).toEqual(1);
const msg_obj = view.model.messages.at(0); const msg_obj = view.model.messages.at(0);
expect(msg_obj.get('message')).toEqual(message.trim()); expect(msg_obj.get('message')).toEqual(message.trim());
const chat_content = view.el.querySelector('.chat-content'); const mel = await u.waitUntil(() => view.content.querySelector('.chat-msg .chat-msg__text'));
const mel = await u.waitUntil(() => chat_content.querySelector('.chat-msg .chat-msg__text'));
expect(mel.textContent).toEqual(message.trim()); expect(mel.textContent).toEqual(message.trim());
done(); done();
})); }));
@ -1547,10 +1535,9 @@
await u.waitUntil(() => view.el.querySelector('.chat-msg__author').textContent.trim() === 'Mercutio'); await u.waitUntil(() => view.el.querySelector('.chat-msg__author').textContent.trim() === 'Mercutio');
// Now check that the message appears inside the chatbox in the DOM // Now check that the message appears inside the chatbox in the DOM
const chat_content = view.el.querySelector('.chat-content'); expect(view.content.querySelector('.chat-msg .chat-msg__text').textContent).toEqual(message);
expect(chat_content.querySelector('.chat-msg .chat-msg__text').textContent).toEqual(message); expect(view.content.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy();
expect(chat_content.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy(); expect(view.content.querySelector('span.chat-msg__author').textContent.trim()).toBe('Mercutio');
expect(chat_content.querySelector('span.chat-msg__author').textContent.trim()).toBe('Mercutio');
done(); done();
})); }));
}); });
@ -1588,8 +1575,7 @@
const view = _converse.api.chatviews.get(sender_jid); const view = _converse.api.chatviews.get(sender_jid);
const message = await view.model.sendMessage(msg_text); const message = await view.model.sendMessage(msg_text);
await new Promise(resolve => view.once('messageInserted', resolve)); await new Promise(resolve => view.once('messageInserted', resolve));
const chat_content = view.el.querySelector('.chat-content'); let msg_txt = sizzle('.chat-msg:last .chat-msg__text', view.content).pop().textContent;
let msg_txt = sizzle('.chat-msg:last .chat-msg__text', chat_content).pop().textContent;
expect(msg_txt).toEqual(msg_text); expect(msg_txt).toEqual(msg_text);
// We send another message, for which an error will // We send another message, for which an error will
@ -1597,8 +1583,8 @@
// after the relevant message. // after the relevant message.
msg_text = 'This message will be sent, and also receive an error'; msg_text = 'This message will be sent, and also receive an error';
const second_message = await view.model.sendMessage(msg_text); const second_message = await view.model.sendMessage(msg_text);
await u.waitUntil(() => sizzle('.chat-msg .chat-msg__text', chat_content).length === 2, 1000); await u.waitUntil(() => sizzle('.chat-msg .chat-msg__text', view.content).length === 2, 1000);
msg_txt = sizzle('.chat-msg:last .chat-msg__text', chat_content).pop().textContent; msg_txt = sizzle('.chat-msg:last .chat-msg__text', view.content).pop().textContent;
expect(msg_txt).toEqual(msg_text); expect(msg_txt).toEqual(msg_text);
/* <message xmlns="jabber:client" /* <message xmlns="jabber:client"
@ -1624,7 +1610,7 @@
.t('Server-to-server connection failed: Connecting failed: connection timeout'); .t('Server-to-server connection failed: Connecting failed: connection timeout');
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
await new Promise(resolve => view.once('messageInserted', resolve)); await new Promise(resolve => view.once('messageInserted', resolve));
expect(chat_content.querySelector('.chat-error').textContent.trim()).toEqual(error_txt); expect(view.content.querySelector('.chat-error').textContent.trim()).toEqual(error_txt);
stanza = $msg({ stanza = $msg({
'to': _converse.connection.jid, 'to': _converse.connection.jid,
'type': 'error', 'type': 'error',
@ -1637,7 +1623,7 @@
.t('Server-to-server connection failed: Connecting failed: connection timeout'); .t('Server-to-server connection failed: Connecting failed: connection timeout');
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
await new Promise(resolve => view.once('messageInserted', resolve)); await new Promise(resolve => view.once('messageInserted', resolve));
expect(chat_content.querySelectorAll('.chat-error').length).toEqual(2); expect(view.content.querySelectorAll('.chat-error').length).toEqual(2);
// We don't render duplicates // We don't render duplicates
stanza = $msg({ stanza = $msg({
@ -1651,12 +1637,12 @@
.c('text', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" }) .c('text', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" })
.t('Server-to-server connection failed: Connecting failed: connection timeout'); .t('Server-to-server connection failed: Connecting failed: connection timeout');
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
expect(chat_content.querySelectorAll('.chat-error').length).toEqual(2); expect(view.content.querySelectorAll('.chat-error').length).toEqual(2);
msg_text = 'This message will be sent, and also receive an error'; msg_text = 'This message will be sent, and also receive an error';
const third_message = await view.model.sendMessage(msg_text); const third_message = await view.model.sendMessage(msg_text);
await new Promise(resolve => view.once('messageInserted', resolve)); await new Promise(resolve => view.once('messageInserted', resolve));
msg_txt = sizzle('.chat-msg:last .chat-msg__text', chat_content).pop().textContent; msg_txt = sizzle('.chat-msg:last .chat-msg__text', view.content).pop().textContent;
expect(msg_txt).toEqual(msg_text); expect(msg_txt).toEqual(msg_text);
// A different error message will however render // A different error message will however render
@ -1673,7 +1659,7 @@
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
await u.waitUntil(() => view.model.messages.length > 3); await u.waitUntil(() => view.model.messages.length > 3);
await new Promise(resolve => view.once('messageInserted', resolve)); await new Promise(resolve => view.once('messageInserted', resolve));
expect(chat_content.querySelectorAll('.chat-error').length).toEqual(3); expect(view.content.querySelectorAll('.chat-error').length).toEqual(3);
done(); done();
})); }));
@ -1709,8 +1695,7 @@
.t('User session not found') .t('User session not found')
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
const view = _converse.chatboxviews.get(contact_jid); const view = _converse.chatboxviews.get(contact_jid);
const chat_content = view.el.querySelector('.chat-content'); expect(view.content.querySelectorAll('.chat-error').length).toEqual(0);
expect(chat_content.querySelectorAll('.chat-error').length).toEqual(0);
done(); done();
})); }));
}); });

View File

@ -567,7 +567,6 @@
await test_utils.waitForReservedNick(_converse, muc_jid, nick); await test_utils.waitForReservedNick(_converse, muc_jid, nick);
const view = _converse.chatboxviews.get(muc_jid); const view = _converse.chatboxviews.get(muc_jid);
const chat_content = view.el.querySelector('.chat-content');
/* <presence to="romeo@montague.lit/_converse.js-29092160" /* <presence to="romeo@montague.lit/_converse.js-29092160"
* from="coven@chat.shakespeare.lit/some1"> * from="coven@chat.shakespeare.lit/some1">
* <x xmlns="http://jabber.org/protocol/muc#user"> * <x xmlns="http://jabber.org/protocol/muc#user">
@ -590,10 +589,10 @@
.c('status', {code: '100'}); .c('status', {code: '100'});
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
await u.waitUntil(() => chat_content.querySelectorAll('.chat-info').length === 2); await u.waitUntil(() => view.content.querySelectorAll('.chat-info').length === 2);
expect(sizzle('div.chat-info:first', chat_content).pop().textContent.trim()) expect(sizzle('div.chat-info:first', view.content).pop().textContent.trim())
.toBe("This groupchat is not anonymous"); .toBe("This groupchat is not anonymous");
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()) expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim())
.toBe("some1 has entered the groupchat"); .toBe("some1 has entered the groupchat");
done(); done();
})); }));
@ -612,7 +611,6 @@
await u.waitUntil(() => sent_stanzas.filter(iq => sizzle('presence history', iq).length).pop()); await u.waitUntil(() => sent_stanzas.filter(iq => sizzle('presence history', iq).length).pop());
const view = _converse.chatboxviews.get('coven@chat.shakespeare.lit'); const view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
const chat_content = view.el.querySelector('.chat-content');
/* We don't show join/leave messages for existing occupants. We /* We don't show join/leave messages for existing occupants. We
* know about them because we receive their presences before we * know about them because we receive their presences before we
* receive our own. * receive our own.
@ -627,7 +625,7 @@
'role': 'participant' 'role': 'participant'
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(0); expect(view.content.querySelectorAll('div.chat-info').length).toBe(0);
/* <presence to="romeo@montague.lit/_converse.js-29092160" /* <presence to="romeo@montague.lit/_converse.js-29092160"
* from="coven@chat.shakespeare.lit/some1"> * from="coven@chat.shakespeare.lit/some1">
@ -648,7 +646,7 @@
}).up() }).up()
.c('status', {code: '110'}); .c('status', {code: '110'});
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(sizzle('div.chat-info:first', chat_content).pop().textContent.trim()) expect(sizzle('div.chat-info:first', view.content).pop().textContent.trim())
.toBe("some1 has entered the groupchat"); .toBe("some1 has entered the groupchat");
await room_creation_promise; await room_creation_promise;
@ -666,8 +664,8 @@
'role': 'participant' 'role': 'participant'
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(2); expect(view.content.querySelectorAll('div.chat-info').length).toBe(2);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()) expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim())
.toBe("newguy has entered the groupchat"); .toBe("newguy has entered the groupchat");
const msg = $msg({ const msg = $msg({
@ -692,8 +690,8 @@
'role': 'participant' 'role': 'participant'
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
await u.waitUntil(() => chat_content.querySelectorAll('div.chat-info').length === 3); await u.waitUntil(() => view.content.querySelectorAll('div.chat-info').length === 3);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()) expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim())
.toBe("newgirl has entered the groupchat"); .toBe("newgirl has entered the groupchat");
// Don't show duplicate join messages // Don't show duplicate join messages
@ -707,7 +705,7 @@
'role': 'participant' 'role': 'participant'
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(3); expect(view.content.querySelectorAll('div.chat-info').length).toBe(3);
/* <presence /* <presence
* from='coven@chat.shakespeare.lit/thirdwitch' * from='coven@chat.shakespeare.lit/thirdwitch'
@ -734,8 +732,8 @@
'role': 'none' 'role': 'none'
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(4); expect(view.content.querySelectorAll('div.chat-info').length).toBe(4);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()).toBe( expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim()).toBe(
'newguy has left the groupchat. '+ 'newguy has left the groupchat. '+
'"Disconnected: Replaced by new connection"'); '"Disconnected: Replaced by new connection"');
@ -751,8 +749,8 @@
'role': 'participant' 'role': 'participant'
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(4); expect(view.content.querySelectorAll('div.chat-info').length).toBe(4);
let msg_el = sizzle('div.chat-info:last', chat_content).pop(); let msg_el = sizzle('div.chat-info:last', view.content).pop();
expect(msg_el.textContent.trim()).toBe("newguy has left and re-entered the groupchat"); expect(msg_el.textContent.trim()).toBe("newguy has left and re-entered the groupchat");
expect(msg_el.getAttribute('data-leavejoin')).toBe('newguy'); expect(msg_el.getAttribute('data-leavejoin')).toBe('newguy');
@ -768,8 +766,8 @@
'role': 'none' 'role': 'none'
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(4); expect(view.content.querySelectorAll('div.chat-info').length).toBe(4);
msg_el = sizzle('div.chat-info', chat_content).pop(); msg_el = sizzle('div.chat-info', view.content).pop();
expect(msg_el.textContent.trim()).toBe('newguy has left the groupchat'); expect(msg_el.textContent.trim()).toBe('newguy has left the groupchat');
expect(msg_el.getAttribute('data-leave')).toBe('newguy'); expect(msg_el.getAttribute('data-leave')).toBe('newguy');
@ -784,8 +782,8 @@
'role': 'participant' 'role': 'participant'
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(5); expect(view.content.querySelectorAll('div.chat-info').length).toBe(5);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()) expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim())
.toBe("nomorenicks has entered the groupchat"); .toBe("nomorenicks has entered the groupchat");
presence = $pres({ presence = $pres({
@ -799,8 +797,8 @@
'role': 'none' 'role': 'none'
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(5); expect(view.content.querySelectorAll('div.chat-info').length).toBe(5);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()) expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim())
.toBe("nomorenicks has entered and left the groupchat"); .toBe("nomorenicks has entered and left the groupchat");
presence = $pres({ presence = $pres({
@ -814,8 +812,8 @@
'role': 'participant' 'role': 'participant'
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(5); expect(view.content.querySelectorAll('div.chat-info').length).toBe(5);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()) expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim())
.toBe("nomorenicks has entered the groupchat"); .toBe("nomorenicks has entered the groupchat");
// Test a member joining and leaving // Test a member joining and leaving
@ -829,7 +827,7 @@
'role': 'participant' 'role': 'participant'
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(6); expect(view.content.querySelectorAll('div.chat-info').length).toBe(6);
/* <presence /* <presence
* from='coven@chat.shakespeare.lit/thirdwitch' * from='coven@chat.shakespeare.lit/thirdwitch'
@ -856,8 +854,8 @@
'role': 'none' 'role': 'none'
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(6); expect(view.content.querySelectorAll('div.chat-info').length).toBe(6);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()).toBe( expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim()).toBe(
'insider has entered and left the groupchat. '+ 'insider has entered and left the groupchat. '+
'"Disconnected: Replaced by new connection"'); '"Disconnected: Replaced by new connection"');
@ -878,8 +876,8 @@
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(6); expect(view.content.querySelectorAll('div.chat-info').length).toBe(6);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()).toBe("newgirl has entered and left the groupchat"); expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim()).toBe("newgirl has entered and left the groupchat");
expect(view.model.occupants.length).toBe(4); expect(view.model.occupants.length).toBe(4);
done(); done();
})); }));
@ -891,10 +889,9 @@
await test_utils.openAndEnterChatRoom(_converse, 'coven@chat.shakespeare.lit', 'romeo') await test_utils.openAndEnterChatRoom(_converse, 'coven@chat.shakespeare.lit', 'romeo')
const view = _converse.chatboxviews.get('coven@chat.shakespeare.lit'); const view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
const chat_content = view.el.querySelector('.chat-content');
expect(sizzle('div.chat-info', chat_content).length).toBe(1); expect(sizzle('div.chat-info', view.content).length).toBe(1);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()).toBe("romeo has entered the groupchat"); expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim()).toBe("romeo has entered the groupchat");
let presence = u.toStanza( let presence = u.toStanza(
`<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" from="coven@chat.shakespeare.lit/fabio"> `<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" from="coven@chat.shakespeare.lit/fabio">
@ -904,8 +901,8 @@
</x> </x>
</presence>`); </presence>`);
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(sizzle('div.chat-info', chat_content).length).toBe(2); expect(sizzle('div.chat-info', view.content).length).toBe(2);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()).toBe("fabio has entered the groupchat"); expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim()).toBe("fabio has entered the groupchat");
presence = u.toStanza( presence = u.toStanza(
`<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" from="coven@chat.shakespeare.lit/Dele Olajide"> `<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" from="coven@chat.shakespeare.lit/Dele Olajide">
@ -914,8 +911,8 @@
</x> </x>
</presence>`); </presence>`);
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(sizzle('div.chat-info', chat_content).length).toBe(3); expect(sizzle('div.chat-info', view.content).length).toBe(3);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()).toBe("Dele Olajide has entered the groupchat"); expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim()).toBe("Dele Olajide has entered the groupchat");
presence = u.toStanza( presence = u.toStanza(
`<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" from="coven@chat.shakespeare.lit/jcbrand"> `<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" from="coven@chat.shakespeare.lit/jcbrand">
@ -925,10 +922,10 @@
</x> </x>
</presence>`); </presence>`);
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
await u.waitUntil(() => sizzle('div.chat-info', chat_content).length > 3); await u.waitUntil(() => sizzle('div.chat-info', view.content).length > 3);
expect(sizzle('div.chat-info', chat_content).length).toBe(4); expect(sizzle('div.chat-info', view.content).length).toBe(4);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()).toBe("jcbrand has entered the groupchat"); expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim()).toBe("jcbrand has entered the groupchat");
presence = u.toStanza( presence = u.toStanza(
`<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" type="unavailable" from="coven@chat.shakespeare.lit/Dele Olajide"> `<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" type="unavailable" from="coven@chat.shakespeare.lit/Dele Olajide">
@ -937,8 +934,8 @@
</x> </x>
</presence>`); </presence>`);
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(sizzle('div.chat-info', chat_content).length).toBe(4); expect(sizzle('div.chat-info', view.content).length).toBe(4);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()).toBe("Dele Olajide has entered and left the groupchat"); expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim()).toBe("Dele Olajide has entered and left the groupchat");
presence = u.toStanza( presence = u.toStanza(
`<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" from="coven@chat.shakespeare.lit/Dele Olajide"> `<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" from="coven@chat.shakespeare.lit/Dele Olajide">
@ -947,8 +944,8 @@
</x> </x>
</presence>`); </presence>`);
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(sizzle('div.chat-info', chat_content).length).toBe(4); expect(sizzle('div.chat-info', view.content).length).toBe(4);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()).toBe("Dele Olajide has entered the groupchat"); expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim()).toBe("Dele Olajide has entered the groupchat");
presence = u.toStanza( presence = u.toStanza(
`<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" from="coven@chat.shakespeare.lit/fuvuv" xml:lang="en"> `<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" from="coven@chat.shakespeare.lit/fuvuv" xml:lang="en">
@ -959,8 +956,8 @@
</x> </x>
</presence>`); </presence>`);
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(sizzle('div.chat-info', chat_content).length).toBe(5); expect(sizzle('div.chat-info', view.content).length).toBe(5);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()).toBe("fuvuv has entered the groupchat"); expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim()).toBe("fuvuv has entered the groupchat");
presence = u.toStanza( presence = u.toStanza(
`<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" type="unavailable" from="coven@chat.shakespeare.lit/fuvuv"> `<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" type="unavailable" from="coven@chat.shakespeare.lit/fuvuv">
@ -969,8 +966,8 @@
</x> </x>
</presence>`); </presence>`);
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(sizzle('div.chat-info', chat_content).length).toBe(5); expect(sizzle('div.chat-info', view.content).length).toBe(5);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()).toBe("fuvuv has entered and left the groupchat"); expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim()).toBe("fuvuv has entered and left the groupchat");
presence = u.toStanza( presence = u.toStanza(
`<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" type="unavailable" from="coven@chat.shakespeare.lit/fabio"> `<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" type="unavailable" from="coven@chat.shakespeare.lit/fabio">
@ -980,8 +977,8 @@
</x> </x>
</presence>`); </presence>`);
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(sizzle('div.chat-info', chat_content).length).toBe(5); expect(sizzle('div.chat-info', view.content).length).toBe(5);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()).toBe( expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim()).toBe(
`fabio has entered and left the groupchat. "Disconnected: Replaced by new connection"`); `fabio has entered and left the groupchat. "Disconnected: Replaced by new connection"`);
presence = u.toStanza( presence = u.toStanza(
@ -993,13 +990,13 @@
</x> </x>
</presence>`); </presence>`);
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(sizzle('div.chat-info', chat_content).length).toBe(5); expect(sizzle('div.chat-info', view.content).length).toBe(5);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()).toBe( expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim()).toBe(
`fabio has entered the groupchat. "Ready for a new day"`); `fabio has entered the groupchat. "Ready for a new day"`);
// XXX: hack so that we can test leave/enter of occupants // XXX: hack so that we can test leave/enter of occupants
// who were already in the room when we joined. // who were already in the room when we joined.
chat_content.innerHTML = ''; view.content.innerHTML = '';
presence = u.toStanza( presence = u.toStanza(
`<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" type="unavailable" from="coven@chat.shakespeare.lit/fabio"> `<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" type="unavailable" from="coven@chat.shakespeare.lit/fabio">
@ -1009,8 +1006,8 @@
</x> </x>
</presence>`); </presence>`);
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(sizzle('div.chat-info', chat_content).length).toBe(1); expect(sizzle('div.chat-info', view.content).length).toBe(1);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()).toBe( expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim()).toBe(
`fabio has left the groupchat. "Disconnected: closed"`); `fabio has left the groupchat. "Disconnected: closed"`);
presence = u.toStanza( presence = u.toStanza(
@ -1020,8 +1017,8 @@
</x> </x>
</presence>`); </presence>`);
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(sizzle('div.chat-info', chat_content).length).toBe(2); expect(sizzle('div.chat-info', view.content).length).toBe(2);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()).toBe( expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim()).toBe(
`Dele Olajide has left the groupchat`); `Dele Olajide has left the groupchat`);
presence = u.toStanza( presence = u.toStanza(
@ -1032,8 +1029,8 @@
</x> </x>
</presence>`); </presence>`);
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(sizzle('div.chat-info', chat_content).length).toBe(2); expect(sizzle('div.chat-info', view.content).length).toBe(2);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()).toBe( expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim()).toBe(
`fabio has left and re-entered the groupchat`); `fabio has left and re-entered the groupchat`);
done(); done();
})); }));
@ -1045,8 +1042,7 @@
await test_utils.openAndEnterChatRoom(_converse, 'coven@chat.shakespeare.lit', 'some1'); await test_utils.openAndEnterChatRoom(_converse, 'coven@chat.shakespeare.lit', 'some1');
const view = _converse.chatboxviews.get('coven@chat.shakespeare.lit'); const view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
const chat_content = view.el.querySelector('.chat-content'); expect(sizzle('div.chat-info', view.content).pop().textContent.trim()).toBe('some1 has entered the groupchat');
expect(sizzle('div.chat-info', chat_content).pop().textContent.trim()).toBe('some1 has entered the groupchat');
let presence = $pres({ let presence = $pres({
to: 'romeo@montague.lit/orchard', to: 'romeo@montague.lit/orchard',
@ -1058,8 +1054,8 @@
'role': 'participant' 'role': 'participant'
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(2); expect(view.content.querySelectorAll('div.chat-info').length).toBe(2);
expect(sizzle('div.chat-info', chat_content).pop().textContent.trim()).toBe('newguy has entered the groupchat'); expect(sizzle('div.chat-info', view.content).pop().textContent.trim()).toBe('newguy has entered the groupchat');
presence = $pres({ presence = $pres({
to: 'romeo@montague.lit/orchard', to: 'romeo@montague.lit/orchard',
@ -1074,8 +1070,8 @@
'role': 'none' 'role': 'none'
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(2); expect(view.content.querySelectorAll('div.chat-info').length).toBe(2);
expect(sizzle('div.chat-info', chat_content).pop().textContent.trim()).toBe('newguy has entered and left the groupchat'); expect(sizzle('div.chat-info', view.content).pop().textContent.trim()).toBe('newguy has entered and left the groupchat');
presence = u.toStanza( presence = u.toStanza(
`<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" from="coven@chat.shakespeare.lit/fabio"> `<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" from="coven@chat.shakespeare.lit/fabio">
@ -1087,7 +1083,7 @@
</presence>`); </presence>`);
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()).toBe(`fabio has entered the groupchat`); expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim()).toBe(`fabio has entered the groupchat`);
presence = u.toStanza( presence = u.toStanza(
`<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" from="coven@chat.shakespeare.lit/Dele Olajide"> `<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" from="coven@chat.shakespeare.lit/Dele Olajide">
@ -1096,8 +1092,8 @@
</x> </x>
</presence>`); </presence>`);
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(sizzle('div.chat-info', chat_content).length).toBe(4); expect(sizzle('div.chat-info', view.content).length).toBe(4);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()).toBe("Dele Olajide has entered the groupchat"); expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim()).toBe("Dele Olajide has entered the groupchat");
await test_utils.sendMessage(view, 'hello world'); await test_utils.sendMessage(view, 'hello world');
presence = u.toStanza( presence = u.toStanza(
@ -1108,8 +1104,8 @@
</x> </x>
</presence>`); </presence>`);
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(sizzle('div.chat-info', chat_content).length).toBe(5); expect(sizzle('div.chat-info', view.content).length).toBe(5);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()).toBe(`Dele Olajide has left the groupchat`); expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim()).toBe(`Dele Olajide has left the groupchat`);
done(); done();
})); }));
@ -1143,7 +1139,7 @@
}).c('body').t('Some message').tree(); }).c('body').t('Some message').tree();
await view.model.queueMessage(msg); await view.model.queueMessage(msg);
await u.waitUntil(() => sizzle('.chat-msg:last .chat-msg__text', view.chat_content).pop()); await u.waitUntil(() => sizzle('.chat-msg:last .chat-msg__text', view.content).pop());
let stanza = u.toStanza( let stanza = u.toStanza(
`<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" type="unavailable" from="conversations@conference.siacs.eu/Guus"> `<presence xmlns="jabber:client" to="romeo@montague.lit/orchard" type="unavailable" from="conversations@conference.siacs.eu/Guus">
@ -1165,8 +1161,7 @@
</presence>`); </presence>`);
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
const chat_content = view.el.querySelector('.chat-content'); const messages = view.content.querySelectorAll('div.chat-info');
const messages = chat_content.querySelectorAll('div.chat-info');
expect(messages.length).toBe(3); expect(messages.length).toBe(3);
expect(messages[0].textContent.trim()).toBe('romeo has entered the groupchat'); expect(messages[0].textContent.trim()).toBe('romeo has entered the groupchat');
expect(messages[1].textContent.trim()).toBe('Guus has entered the groupchat'); expect(messages[1].textContent.trim()).toBe('Guus has entered the groupchat');
@ -1182,14 +1177,13 @@
await test_utils.openAndEnterChatRoom(_converse, 'coven@chat.shakespeare.lit', 'romeo'); await test_utils.openAndEnterChatRoom(_converse, 'coven@chat.shakespeare.lit', 'romeo');
const view = _converse.chatboxviews.get('coven@chat.shakespeare.lit'); const view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
const chat_content = view.el.querySelector('.chat-content'); let indicator = view.content.querySelector('.date-separator');
let indicator = chat_content.querySelector('.date-separator');
expect(indicator).not.toBe(null); expect(indicator).not.toBe(null);
expect(indicator.getAttribute('class')).toEqual('message date-separator'); expect(indicator.getAttribute('class')).toEqual('message date-separator');
expect(indicator.getAttribute('data-isodate')).toEqual(dayjs().startOf('day').toISOString()); expect(indicator.getAttribute('data-isodate')).toEqual(dayjs().startOf('day').toISOString());
expect(indicator.querySelector('time').textContent.trim()).toEqual(dayjs().startOf('day').format("dddd MMM Do YYYY")); expect(indicator.querySelector('time').textContent.trim()).toEqual(dayjs().startOf('day').format("dddd MMM Do YYYY"));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(1); expect(view.content.querySelectorAll('div.chat-info').length).toBe(1);
expect(chat_content.querySelector('div.chat-info').textContent.trim()).toBe("romeo has entered the groupchat"); expect(view.content.querySelector('div.chat-info').textContent.trim()).toBe("romeo has entered the groupchat");
const baseTime = new Date(); const baseTime = new Date();
jasmine.clock().install(); jasmine.clock().install();
@ -1216,15 +1210,15 @@
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
indicator = chat_content.querySelector('.date-separator[data-isodate="'+dayjs().startOf('day').toISOString()+'"]'); indicator = view.content.querySelector('.date-separator[data-isodate="'+dayjs().startOf('day').toISOString()+'"]');
expect(indicator).not.toBe(null); expect(indicator).not.toBe(null);
expect(indicator.getAttribute('class')).toEqual('message date-separator'); expect(indicator.getAttribute('class')).toEqual('message date-separator');
expect(indicator.getAttribute('data-isodate')).toEqual(dayjs().startOf('day').toISOString()); expect(indicator.getAttribute('data-isodate')).toEqual(dayjs().startOf('day').toISOString());
expect(indicator.querySelector('time').getAttribute('class')).toEqual('separator-text'); expect(indicator.querySelector('time').getAttribute('class')).toEqual('separator-text');
expect(indicator.querySelector('time').textContent.trim()).toEqual(dayjs().startOf('day').format("dddd MMM Do YYYY")); expect(indicator.querySelector('time').textContent.trim()).toEqual(dayjs().startOf('day').format("dddd MMM Do YYYY"));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(2); expect(view.content.querySelectorAll('div.chat-info').length).toBe(2);
expect(chat_content.querySelector('div.chat-info:last-child').textContent.trim()).toBe( expect(view.content.querySelector('div.chat-info:last-child').textContent.trim()).toBe(
"some1 has entered the groupchat" "some1 has entered the groupchat"
); );
@ -1245,15 +1239,15 @@
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
indicator = chat_content.querySelector('.date-separator[data-isodate="'+dayjs().startOf('day').toISOString()+'"]'); indicator = view.content.querySelector('.date-separator[data-isodate="'+dayjs().startOf('day').toISOString()+'"]');
expect(indicator).not.toBe(null); expect(indicator).not.toBe(null);
expect(indicator.getAttribute('class')).toEqual('message date-separator'); expect(indicator.getAttribute('class')).toEqual('message date-separator');
expect(indicator.getAttribute('data-isodate')).toEqual(dayjs().startOf('day').toISOString()); expect(indicator.getAttribute('data-isodate')).toEqual(dayjs().startOf('day').toISOString());
expect(indicator.querySelector('time').textContent.trim()).toEqual(dayjs().startOf('day').format("dddd MMM Do YYYY")); expect(indicator.querySelector('time').textContent.trim()).toEqual(dayjs().startOf('day').format("dddd MMM Do YYYY"));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(3); expect(view.content.querySelectorAll('div.chat-info').length).toBe(3);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()).toBe( expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim()).toBe(
'some1 has left the groupchat. '+ 'some1 has left the groupchat. '+
'"Disconnected: Replaced by new connection"'); '"Disconnected: Replaced by new connection"');
@ -1281,15 +1275,15 @@
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
let time = chat_content.querySelectorAll('time.separator-text'); let time = view.content.querySelectorAll('time.separator-text');
expect(time.length).toEqual(4); expect(time.length).toEqual(4);
indicator = sizzle('.date-separator:eq(3)', chat_content).pop(); indicator = sizzle('.date-separator:eq(3)', view.content).pop();
expect(indicator.getAttribute('class')).toEqual('message date-separator'); expect(indicator.getAttribute('class')).toEqual('message date-separator');
expect(indicator.getAttribute('data-isodate')).toEqual(dayjs().startOf('day').toISOString()); expect(indicator.getAttribute('data-isodate')).toEqual(dayjs().startOf('day').toISOString());
expect(indicator.querySelector('time').textContent.trim()).toEqual(dayjs().startOf('day').format("dddd MMM Do YYYY")); expect(indicator.querySelector('time').textContent.trim()).toEqual(dayjs().startOf('day').format("dddd MMM Do YYYY"));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(4); expect(view.content.querySelectorAll('div.chat-info').length).toBe(4);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()) expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim())
.toBe("newguy has entered the groupchat"); .toBe("newguy has entered the groupchat");
jasmine.clock().tick(ONE_DAY_LATER); jasmine.clock().tick(ONE_DAY_LATER);
@ -1321,15 +1315,15 @@
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
time = chat_content.querySelectorAll('time.separator-text'); time = view.content.querySelectorAll('time.separator-text');
expect(time.length).toEqual(6); expect(time.length).toEqual(6);
indicator = sizzle('.date-separator:eq(5)', chat_content).pop(); indicator = sizzle('.date-separator:eq(5)', view.content).pop();
expect(indicator.getAttribute('class')).toEqual('message date-separator'); expect(indicator.getAttribute('class')).toEqual('message date-separator');
expect(indicator.getAttribute('data-isodate')).toEqual(dayjs().startOf('day').toISOString()); expect(indicator.getAttribute('data-isodate')).toEqual(dayjs().startOf('day').toISOString());
expect(indicator.querySelector('time').textContent.trim()).toEqual(dayjs().startOf('day').format("dddd MMM Do YYYY")); expect(indicator.querySelector('time').textContent.trim()).toEqual(dayjs().startOf('day').format("dddd MMM Do YYYY"));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(5); expect(view.content.querySelectorAll('div.chat-info').length).toBe(5);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()).toBe( expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim()).toBe(
'newguy has left the groupchat. '+ 'newguy has left the groupchat. '+
'"Disconnected: Replaced by new connection"'); '"Disconnected: Replaced by new connection"');
jasmine.clock().uninstall(); jasmine.clock().uninstall();
@ -1359,7 +1353,7 @@
'type': 'groupchat' 'type': 'groupchat'
}).c('body').t(message).tree(); }).c('body').t(message).tree();
await view.model.queueMessage(msg); await view.model.queueMessage(msg);
await u.waitUntil(() => sizzle('.chat-msg:last .chat-msg__text', view.chat_content).pop()); await u.waitUntil(() => sizzle('.chat-msg:last .chat-msg__text', view.content).pop());
expect(_.includes(view.el.querySelector('.chat-msg__author').textContent, '**Dyon van de Wege')).toBeTruthy(); expect(_.includes(view.el.querySelector('.chat-msg__author').textContent, '**Dyon van de Wege')).toBeTruthy();
expect(view.el.querySelector('.chat-msg__text').textContent.trim()).toBe('is tired'); expect(view.el.querySelector('.chat-msg__text').textContent.trim()).toBe('is tired');
@ -2059,10 +2053,9 @@
type: 'groupchat' type: 'groupchat'
}).c('body').t(text); }).c('body').t(text);
await view.model.queueMessage(message.nodeTree); await view.model.queueMessage(message.nodeTree);
const chat_content = view.el.querySelector('.chat-content');
await u.waitUntil(() => view.el.querySelectorAll('.chat-msg').length); await u.waitUntil(() => view.el.querySelectorAll('.chat-msg').length);
expect(chat_content.querySelectorAll('.chat-msg').length).toBe(1); expect(view.content.querySelectorAll('.chat-msg').length).toBe(1);
expect(chat_content.querySelector('.chat-msg__text').textContent.trim()).toBe(text); expect(view.content.querySelector('.chat-msg__text').textContent.trim()).toBe(text);
expect(_converse.api.trigger).toHaveBeenCalledWith('message', jasmine.any(Object)); expect(_converse.api.trigger).toHaveBeenCalledWith('message', jasmine.any(Object));
done(); done();
})); }));
@ -2089,8 +2082,7 @@
await new Promise(resolve => view.once('messageInserted', resolve)); await new Promise(resolve => view.once('messageInserted', resolve));
expect(_converse.api.trigger).toHaveBeenCalledWith('messageSend', jasmine.any(_converse.Message)); expect(_converse.api.trigger).toHaveBeenCalledWith('messageSend', jasmine.any(_converse.Message));
const chat_content = view.el.querySelector('.chat-content'); expect(view.content.querySelectorAll('.chat-msg').length).toBe(1);
expect(chat_content.querySelectorAll('.chat-msg').length).toBe(1);
// Let's check that if we receive the same message again, it's // Let's check that if we receive the same message again, it's
// not shown. // not shown.
@ -2106,7 +2098,7 @@
<origin-id xmlns="urn:xmpp:sid:0" id="${view.model.messages.at(0).get('origin_id')}"/> <origin-id xmlns="urn:xmpp:sid:0" id="${view.model.messages.at(0).get('origin_id')}"/>
</message>`); </message>`);
await view.model.queueMessage(stanza); await view.model.queueMessage(stanza);
expect(chat_content.querySelectorAll('.chat-msg').length).toBe(1); expect(view.content.querySelectorAll('.chat-msg').length).toBe(1);
expect(sizzle('.chat-msg__text:last').pop().textContent.trim()).toBe(text); expect(sizzle('.chat-msg__text:last').pop().textContent.trim()).toBe(text);
expect(view.model.messages.length).toBe(1); expect(view.model.messages.length).toBe(1);
// We don't emit an event if it's our own message // We don't emit an event if it's our own message
@ -2149,8 +2141,7 @@
}).c('body').t(message).tree()); }).c('body').t(message).tree());
await new Promise(resolve => view.once('messageInserted', resolve)); await new Promise(resolve => view.once('messageInserted', resolve));
// Now check that the message appears inside the chatbox in the DOM // Now check that the message appears inside the chatbox in the DOM
const chat_content = view.el.querySelector('.chat-content'); const msg_txt = sizzle('.chat-msg:last .chat-msg__text', view.content).pop().textContent;
const msg_txt = sizzle('.chat-msg:last .chat-msg__text', chat_content).pop().textContent;
expect(msg_txt).toEqual(message); expect(msg_txt).toEqual(message);
expect(view.content.scrollTop).toBe(0); expect(view.content.scrollTop).toBe(0);
done(); done();
@ -2329,15 +2320,14 @@
await test_utils.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'oldnick'); await test_utils.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'oldnick');
const view = _converse.chatboxviews.get('lounge@montague.lit'); const view = _converse.chatboxviews.get('lounge@montague.lit');
expect(view.model.session.get('connection_status')).toBe(converse.ROOMSTATUS.ENTERED); expect(view.model.session.get('connection_status')).toBe(converse.ROOMSTATUS.ENTERED);
const chat_content = view.el.querySelector('.chat-content');
await u.waitUntil(() => view.el.querySelectorAll('li .occupant-nick').length, 500); await u.waitUntil(() => view.el.querySelectorAll('li .occupant-nick').length, 500);
let occupants = view.el.querySelector('.occupant-list'); let occupants = view.el.querySelector('.occupant-list');
expect(occupants.childElementCount).toBe(1); expect(occupants.childElementCount).toBe(1);
expect(occupants.firstElementChild.querySelector('.occupant-nick').textContent.trim()).toBe("oldnick"); expect(occupants.firstElementChild.querySelector('.occupant-nick').textContent.trim()).toBe("oldnick");
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(1); expect(view.content.querySelectorAll('div.chat-info').length).toBe(1);
expect(sizzle('div.chat-info:first', chat_content).pop().textContent.trim()) expect(sizzle('div.chat-info:first', view.content).pop().textContent.trim())
.toBe("oldnick has entered the groupchat"); .toBe("oldnick has entered the groupchat");
let presence = $pres().attrs({ let presence = $pres().attrs({
@ -2386,8 +2376,8 @@
// notification for the new nickname. Ideally we'd not have // notification for the new nickname. Ideally we'd not have
// that, but that's probably not possible without some // that, but that's probably not possible without some
// significant refactoring. // significant refactoring.
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(3); expect(view.content.querySelectorAll('div.chat-info').length).toBe(3);
expect(sizzle('div.chat-info', chat_content)[1].textContent.trim()).toBe( expect(sizzle('div.chat-info', view.content)[1].textContent.trim()).toBe(
__(_converse.muc.new_nickname_messages["303"], "newnick") __(_converse.muc.new_nickname_messages["303"], "newnick")
); );
occupants = view.el.querySelector('.occupant-list'); occupants = view.el.querySelector('.occupant-list');
@ -5018,9 +5008,8 @@
]; ];
await test_utils.openAndEnterChatRoom(_converse, muc_jid, 'some1', [], members); await test_utils.openAndEnterChatRoom(_converse, muc_jid, 'some1', [], members);
const view = _converse.api.chatviews.get(muc_jid); const view = _converse.api.chatviews.get(muc_jid);
const chat_content = view.el.querySelector('.chat-content');
expect(sizzle('div.chat-info:first', chat_content).pop().textContent.trim()) expect(sizzle('div.chat-info:first', view.content).pop().textContent.trim())
.toBe("some1 has entered the groupchat"); .toBe("some1 has entered the groupchat");
let presence = $pres({ let presence = $pres({
@ -5034,8 +5023,8 @@
'role': 'participant' 'role': 'participant'
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(2); expect(view.content.querySelectorAll('div.chat-info').length).toBe(2);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()) expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim())
.toBe("newguy has entered the groupchat"); .toBe("newguy has entered the groupchat");
presence = $pres({ presence = $pres({
@ -5049,8 +5038,8 @@
'role': 'participant' 'role': 'participant'
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(3); expect(view.content.querySelectorAll('div.chat-info').length).toBe(3);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()) expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim())
.toBe("nomorenicks has entered the groupchat"); .toBe("nomorenicks has entered the groupchat");
// See XEP-0085 https://xmpp.org/extensions/xep-0085.html#definitions // See XEP-0085 https://xmpp.org/extensions/xep-0085.html#definitions
@ -5071,7 +5060,7 @@
}).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
_converse.connection._dataRecv(test_utils.createRequest(msg)); _converse.connection._dataRecv(test_utils.createRequest(msg));
const csntext = await u.waitUntil(() => view.el.querySelector('.chat-state-notifications').textContent); const csntext = await u.waitUntil(() => view.el.querySelector('.chat-content__notifications').textContent);
expect(csntext.trim()).toEqual('newguy is typing'); expect(csntext.trim()).toEqual('newguy is typing');
expect(timeout_functions.length).toBe(1); expect(timeout_functions.length).toBe(1);
@ -5081,7 +5070,7 @@
expect(events[0].textContent.trim()).toEqual('some1 has entered the groupchat'); expect(events[0].textContent.trim()).toEqual('some1 has entered the groupchat');
expect(events[1].textContent.trim()).toEqual('newguy has entered the groupchat'); expect(events[1].textContent.trim()).toEqual('newguy has entered the groupchat');
expect(events[2].textContent.trim()).toEqual('nomorenicks has entered the groupchat'); expect(events[2].textContent.trim()).toEqual('nomorenicks has entered the groupchat');
expect(view.el.querySelector('.chat-state-notifications').textContent.trim()).toEqual('newguy is typing'); expect(view.el.querySelector('.chat-content__notifications').textContent.trim()).toEqual('newguy is typing');
// <composing> state for a different occupant // <composing> state for a different occupant
msg = $msg({ msg = $msg({
@ -5091,7 +5080,7 @@
type: 'groupchat' type: 'groupchat'
}).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
await view.model.queueMessage(msg); await view.model.queueMessage(msg);
await u.waitUntil(() => view.el.querySelector('.chat-state-notifications').textContent.trim() === 'newguy and nomorenicks are typing'); await u.waitUntil(() => view.el.querySelector('.chat-content__notifications').textContent.trim() === 'newguy and nomorenicks are typing');
// <composing> state for a different occupant // <composing> state for a different occupant
msg = $msg({ msg = $msg({
@ -5101,7 +5090,7 @@
type: 'groupchat' type: 'groupchat'
}).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
await view.model.queueMessage(msg); await view.model.queueMessage(msg);
await u.waitUntil(() => view.el.querySelector('.chat-state-notifications').textContent.trim() === 'newguy, nomorenicks and majortom are typing'); await u.waitUntil(() => view.el.querySelector('.chat-content__notifications').textContent.trim() === 'newguy, nomorenicks and majortom are typing');
// <composing> state for a different occupant // <composing> state for a different occupant
msg = $msg({ msg = $msg({
@ -5111,7 +5100,7 @@
type: 'groupchat' type: 'groupchat'
}).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
await view.model.queueMessage(msg); await view.model.queueMessage(msg);
await u.waitUntil(() => view.el.querySelector('.chat-state-notifications').textContent.trim() === 'newguy, nomorenicks and others are typing'); await u.waitUntil(() => view.el.querySelector('.chat-content__notifications').textContent.trim() === 'newguy, nomorenicks and others are typing');
// Check that new messages appear under the chat state notifications // Check that new messages appear under the chat state notifications
msg = $msg({ msg = $msg({
@ -5130,7 +5119,7 @@
// Test that the composing notifications get removed via timeout. // Test that the composing notifications get removed via timeout.
timeout_functions[0](); timeout_functions[0]();
await u.waitUntil(() => view.el.querySelector('.chat-state-notifications').textContent.trim() === 'nomorenicks, majortom and groundcontrol are typing'); await u.waitUntil(() => view.el.querySelector('.chat-content__notifications').textContent.trim() === 'nomorenicks, majortom and groundcontrol are typing');
done(); done();
})); }));
}); });
@ -5145,7 +5134,6 @@
const muc_jid = 'coven@chat.shakespeare.lit'; const muc_jid = 'coven@chat.shakespeare.lit';
await test_utils.openAndEnterChatRoom(_converse, muc_jid, 'some1'); await test_utils.openAndEnterChatRoom(_converse, muc_jid, 'some1');
const view = _converse.chatboxviews.get('coven@chat.shakespeare.lit'); const view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
const chat_content = view.el.querySelector('.chat-content');
/* <presence to="romeo@montague.lit/_converse.js-29092160" /* <presence to="romeo@montague.lit/_converse.js-29092160"
* from="coven@chat.shakespeare.lit/some1"> * from="coven@chat.shakespeare.lit/some1">
@ -5166,7 +5154,7 @@
}).up() }).up()
.c('status', {code: '110'}); .c('status', {code: '110'});
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(sizzle('div.chat-info:first', chat_content).pop().textContent.trim()) expect(sizzle('div.chat-info:first', view.content).pop().textContent.trim())
.toBe("some1 has entered the groupchat"); .toBe("some1 has entered the groupchat");
presence = $pres({ presence = $pres({
@ -5180,8 +5168,8 @@
'role': 'participant' 'role': 'participant'
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(2); expect(view.content.querySelectorAll('div.chat-info').length).toBe(2);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()) expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim())
.toBe("newguy has entered the groupchat"); .toBe("newguy has entered the groupchat");
presence = $pres({ presence = $pres({
@ -5195,8 +5183,8 @@
'role': 'participant' 'role': 'participant'
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(3); expect(view.content.querySelectorAll('div.chat-info').length).toBe(3);
expect(sizzle('div.chat-info:last', chat_content).pop().textContent.trim()) expect(sizzle('div.chat-info:last', view.content).pop().textContent.trim())
.toBe("nomorenicks has entered the groupchat"); .toBe("nomorenicks has entered the groupchat");
// See XEP-0085 https://xmpp.org/extensions/xep-0085.html#definitions // See XEP-0085 https://xmpp.org/extensions/xep-0085.html#definitions
@ -5209,8 +5197,8 @@
type: 'groupchat' type: 'groupchat'
}).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
await view.model.queueMessage(msg); await view.model.queueMessage(msg);
await u.waitUntil(() => view.el.querySelector('.chat-state-notifications').textContent); await u.waitUntil(() => view.el.querySelector('.chat-content__notifications').textContent);
expect(view.el.querySelector('.chat-state-notifications').textContent.trim()).toBe('newguy is typing'); expect(view.el.querySelector('.chat-content__notifications').textContent.trim()).toBe('newguy is typing');
// <composing> state for a different occupant // <composing> state for a different occupant
msg = $msg({ msg = $msg({
@ -5221,7 +5209,7 @@
}).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
await view.model.queueMessage(msg); await view.model.queueMessage(msg);
await u.waitUntil(() => view.el.querySelector('.chat-state-notifications').textContent.trim() == 'newguy and nomorenicks are typing'); await u.waitUntil(() => view.el.querySelector('.chat-content__notifications').textContent.trim() == 'newguy and nomorenicks are typing');
// <paused> state from occupant who typed first // <paused> state from occupant who typed first
msg = $msg({ msg = $msg({
@ -5231,7 +5219,7 @@
type: 'groupchat' type: 'groupchat'
}).c('body').c('paused', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('body').c('paused', {'xmlns': Strophe.NS.CHATSTATES}).tree();
await view.model.queueMessage(msg); await view.model.queueMessage(msg);
await u.waitUntil(() => view.el.querySelector('.chat-state-notifications').textContent.trim() == 'nomorenicks is typing\n newguy has stopped typing'); await u.waitUntil(() => view.el.querySelector('.chat-content__notifications').textContent.trim() == 'nomorenicks is typing\n newguy has stopped typing');
done(); done();
})); }));
}); });

View File

@ -248,8 +248,8 @@ converse.plugins.add('converse-chatview', {
) )
); );
render(result, this.el); render(result, this.el);
this.content = this.el.querySelector('.chat-content'); this.content = this.el.querySelector('.chat-content__messages');
this.csn = this.el.querySelector('.chat-state-notifications'); this.csn = this.el.querySelector('.chat-content__notifications');
this.renderChatStateNotification(); this.renderChatStateNotification();
this.renderMessageForm(); this.renderMessageForm();
this.renderHeading(); this.renderHeading();

View File

@ -165,7 +165,7 @@ converse.plugins.add('converse-headlines-view', {
} }
)); ));
render(result, this.el); render(result, this.el);
this.content = this.el.querySelector('.chat-content'); this.content = this.el.querySelector('.chat-content__messages');
return this; return this;
}, },

View File

@ -746,8 +746,8 @@ converse.plugins.add('converse-muc-views', {
}), this.el); }), this.el);
this.renderHeading(); this.renderHeading();
this.renderBottomPanel(); this.renderBottomPanel();
this.content = this.el.querySelector('.chat-content'); this.content = this.el.querySelector('.chat-content__messages');
this.csn = this.el.querySelector('.chat-state-notifications'); this.csn = this.el.querySelector('.chat-content__notifications');
if (!_converse.muc_show_logs_before_join) { if (!_converse.muc_show_logs_before_join) {
this.model.session.get('connection_status') !== converse.ROOMSTATUS.ENTERED && this.showSpinner(); this.model.session.get('connection_status') !== converse.ROOMSTATUS.ENTERED && this.showSpinner();
} }

View File

@ -4,8 +4,10 @@ export default (o) => html`
<div class="flyout box-flyout"> <div class="flyout box-flyout">
<div class="chat-head chat-head-chatbox row no-gutters"></div> <div class="chat-head chat-head-chatbox row no-gutters"></div>
<div class="chat-body"> <div class="chat-body">
<div class="chat-content ${ o.show_send_button ? 'chat-content-sendbutton' : '' }" @scroll=${o.markScrolled} aria-live="polite"></div> <div class="chat-content ${ o.show_send_button ? 'chat-content-sendbutton' : '' }" @scroll=${o.markScrolled} aria-live="polite">
<div class="chat-state-notifications"></div> <div class="chat-content__messages"></div>
<div class="chat-content__notifications"></div>
</div>
<div class="bottom-panel"> <div class="bottom-panel">
<div class="emoji-picker__container dropup"></div> <div class="emoji-picker__container dropup"></div>
<div class="message-form-container"> <div class="message-form-container">

View File

@ -11,8 +11,9 @@ export default (o) => html`
<div class="chat-area col"> <div class="chat-area col">
<div class="chat-content ${ o.show_send_button ? 'chat-content-sendbutton' : '' }" aria-live="polite"> <div class="chat-content ${ o.show_send_button ? 'chat-content-sendbutton' : '' }" aria-live="polite">
${ o.muc_show_logs_before_join ? html`<div class="empty-history-feedback"><span>${ i18n_no_history }</span></div>` : '' } ${ o.muc_show_logs_before_join ? html`<div class="empty-history-feedback"><span>${ i18n_no_history }</span></div>` : '' }
<div class="chat-content__messages"></div>
<div class="chat-content__notifications"></div>
</div> </div>
<div class="chat-state-notifications"></div>
<div class="bottom-panel"></div> <div class="bottom-panel"></div>
</div> </div>
<div class="disconnect-container hidden"></div> <div class="disconnect-container hidden"></div>