Browse Source

Show chat state notifications inside the scrollable area

Rename CSS class to conform to convention
JC Brand 5 years ago
parent
commit
7812d4e7b6

+ 10 - 10
sass/_chatbox.scss

@@ -222,6 +222,16 @@
             background-color: var(--chat-content-background-color);
             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 {
                 width: 100%
             }
@@ -235,16 +245,6 @@
             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 */
             background-color: var(--light-background-color);
             dd {

+ 11 - 11
spec/chatbox.js

@@ -689,7 +689,7 @@
                         _converse.connection._dataRecv(test_utils.createRequest(msg));
                         const view = _converse.chatboxviews.get(sender_jid);
                         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);
 
                         // <paused> state
@@ -701,7 +701,7 @@
                             }).c('paused', {'xmlns': Strophe.NS.CHATSTATES}).tree();
                         _converse.connection._dataRecv(test_utils.createRequest(msg));
                         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({
                                 from: sender_jid,
@@ -711,7 +711,7 @@
                             }).c('body').t('hello world').tree();
                         await _converse.handleMessageStanza(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');
                         done();
                     }));
@@ -748,7 +748,7 @@
 
                         await u.waitUntil(() => u.shouldCreateMessage.calls.count());
                         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('');
                         done();
                     }));
@@ -833,7 +833,7 @@
 
                         _converse.connection._dataRecv(test_utils.createRequest(msg));
                         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);
                         done();
                     }));
@@ -867,7 +867,7 @@
                         _converse.connection._dataRecv(test_utils.createRequest(msg));
                         await u.waitUntil(() => u.shouldCreateMessage.calls.count());
                         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('');
                         done();
                         done();
@@ -1007,7 +1007,7 @@
                             .c('composing', {'xmlns': Strophe.NS.CHATSTATES}).up()
                             .tree();
                         _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(view.model.messages.length).toBe(0);
 
@@ -1019,7 +1019,7 @@
                             }).c('inactive', {'xmlns': Strophe.NS.CHATSTATES}).tree();
                         _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();
                     }));
                 });
@@ -1045,7 +1045,7 @@
                         _converse.connection._dataRecv(test_utils.createRequest(msg));
 
                         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');
                         done();
                     }));
@@ -1092,7 +1092,7 @@
                         }).c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
                         _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');
 
                         // Edited message
@@ -1107,7 +1107,7 @@
                             .c('replace', {'xmlns': Strophe.NS.MESSAGE_CORRECT, 'id': original_id }).tree();
 
                         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();
                     }));
                 });

+ 5 - 6
spec/emojis.js

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

+ 93 - 108
spec/messages.js

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

+ 114 - 126
spec/muc.js

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

+ 2 - 2
src/converse-chatview.js

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

+ 1 - 1
src/converse-headlines-view.js

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

+ 2 - 2
src/converse-muc-views.js

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

+ 4 - 2
src/templates/chatbox.js

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

+ 2 - 1
src/templates/chatroom.js

@@ -11,8 +11,9 @@ export default (o) => html`
             <div class="chat-area col">
                 <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>`  : '' }
+                    <div class="chat-content__messages"></div>
+                    <div class="chat-content__notifications"></div>
                 </div>
-                <div class="chat-state-notifications"></div>
                 <div class="bottom-panel"></div>
             </div>
             <div class="disconnect-container hidden"></div>