diff options
| author | Sébastien Theys <seb@odoo.com> | 2020-11-16 12:36:47 +0000 |
|---|---|---|
| committer | Sébastien Theys <seb@odoo.com> | 2020-11-16 12:36:47 +0000 |
| commit | 2002c6a599a685f4a18fc670a9f7992c8d595c0f (patch) | |
| tree | e4d273d6cd86496d68e9ebd02c3849d9f52d95d1 /addons/mail/static/src/components/chat_window_manager | |
| parent | 8b32e558fde3cb3aaa1deb40acb07488d04d343e (diff) | |
[FIX] mail: fix race conditions, especially with scroll
The `_update` of some components must take place before the `_update`
of other (usually sibling) components that might directly influence their
layout. This is in particular the case for `_update` that are relying on height.
Prevent force save of scroll position if there are pending hints to adjust it,
and prevent pending hints from overriding new scroll value.
Prevent flicker with message date.
This should fix all known issues related to incorrectly saving or restoring
scroll position.
task-2344226
task-2358066
task-2369332
task-2372339
task-2373741
closes odoo/odoo#61054
Related: odoo/enterprise#14736
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
Diffstat (limited to 'addons/mail/static/src/components/chat_window_manager')
| -rw-r--r-- | addons/mail/static/src/components/chat_window_manager/chat_window_manager_tests.js | 134 |
1 files changed, 96 insertions, 38 deletions
diff --git a/addons/mail/static/src/components/chat_window_manager/chat_window_manager_tests.js b/addons/mail/static/src/components/chat_window_manager/chat_window_manager_tests.js index b70f61475dd..c0a6bf1295f 100644 --- a/addons/mail/static/src/components/chat_window_manager/chat_window_manager_tests.js +++ b/addons/mail/static/src/components/chat_window_manager/chat_window_manager_tests.js @@ -795,11 +795,8 @@ QUnit.test('[technical] chat window: composer state conservation on toggle home QUnit.test('[technical] chat window: scroll conservation on toggle home menu', async function (assert) { // technical as show/hide home menu simulation are involved and home menu implementation // have side-effects on DOM that may make chat window components not work - assert.expect(3); - + assert.expect(2); - // channel that is expected to be found in the messaging menu - // with random unique id that is needed to link messages this.data['mail.channel'].records.push({ id: 20 }); for (let i = 0; i < 10; i++) { this.data['mail.message'].records.push({ @@ -809,9 +806,19 @@ QUnit.test('[technical] chat window: scroll conservation on toggle home menu', a } await this.start(); await afterNextRender(() => document.querySelector(`.o_MessagingMenu_toggler`).click()); - await afterNextRender(() => - document.querySelector(`.o_MessagingMenu_dropdownMenu .o_NotificationList_preview`).click() - ); + await this.afterEvent({ + eventName: 'o-component-message-list-scrolled', + func: () => document.querySelector('.o_NotificationList_preview').click(), + message: "should wait until channel 20 scrolled to its last message after opening it from the messaging menu", + predicate: ({ scrollTop, threadViewer }) => { + const messageList = document.querySelector('.o_ThreadView_messageList'); + return ( + threadViewer.thread.model === 'mail.channel' && + threadViewer.thread.id === 20 && + scrollTop === messageList.scrollHeight - messageList.clientHeight + ); + }, + }); // Set a scroll position to chat window await this.afterEvent({ eventName: 'o-component-message-list-scrolled', @@ -827,12 +834,6 @@ QUnit.test('[technical] chat window: scroll conservation on toggle home menu', a ); }, }); - assert.strictEqual( - document.querySelector(`.o_ThreadView_messageList`).scrollTop, - 142, - "chat window initial scrollTop should be 142px" - ); - await afterNextRender(() => this.hideHomeMenu()); assert.strictEqual( document.querySelector(`.o_ThreadView_messageList`).scrollTop, @@ -843,7 +844,7 @@ QUnit.test('[technical] chat window: scroll conservation on toggle home menu', a await this.afterEvent({ eventName: 'o-component-message-list-scrolled', func: () => this.showHomeMenu(), - message: "should wait until channel 20 restored its scroll to 142 after hiding the home menu", + message: "should wait until channel 20 restored its scroll to 142 after showing the home menu", predicate: ({ scrollTop, threadViewer }) => { return ( threadViewer.thread.model === 'mail.channel' && @@ -1573,9 +1574,19 @@ QUnit.test('chat window with a thread: keep scroll position in message list on f } await this.start(); await afterNextRender(() => document.querySelector(`.o_MessagingMenu_toggler`).click()); - await afterNextRender(() => - document.querySelector(`.o_NotificationList_preview`).click() - ); + await this.afterEvent({ + eventName: 'o-component-message-list-scrolled', + func: () => document.querySelector('.o_NotificationList_preview').click(), + message: "should wait until channel 20 scrolled to its last message after opening it from the messaging menu", + predicate: ({ scrollTop, threadViewer }) => { + const messageList = document.querySelector('.o_ThreadView_messageList'); + return ( + threadViewer.thread.model === 'mail.channel' && + threadViewer.thread.id === 20 && + scrollTop === messageList.scrollHeight - messageList.clientHeight + ); + }, + }); // Set a scroll position to chat window await this.afterEvent({ eventName: 'o-component-message-list-scrolled', @@ -1750,7 +1761,7 @@ QUnit.test('[technical] chat window: composer state conservation on toggle home QUnit.test('[technical] chat window with a thread: keep scroll position in message list on toggle home menu when folded', async function (assert) { // technical as show/hide home menu simulation are involved and home menu implementation // have side-effects on DOM that may make chat window components not work - assert.expect(3); + assert.expect(2); // channel that is expected to be found in the messaging menu // with random unique id, needed to link messages @@ -1763,22 +1774,48 @@ QUnit.test('[technical] chat window with a thread: keep scroll position in messa } await this.start(); await afterNextRender(() => document.querySelector(`.o_MessagingMenu_toggler`).click()); - await afterNextRender(() => - document.querySelector(`.o_MessagingMenu_dropdownMenu .o_NotificationList_preview`).click() - ); + await this.afterEvent({ + eventName: 'o-component-message-list-scrolled', + func: () => document.querySelector('.o_NotificationList_preview').click(), + message: "should wait until channel 20 scrolled to its last message after opening it from the messaging menu", + predicate: ({ scrollTop, threadViewer }) => { + const messageList = document.querySelector('.o_ThreadView_messageList'); + return ( + threadViewer.thread.model === 'mail.channel' && + threadViewer.thread.id === 20 && + scrollTop === messageList.scrollHeight - messageList.clientHeight + ); + }, + }); // Set a scroll position to chat window - document.querySelector(`.o_ThreadView_messageList`).scrollTop = 142; - assert.strictEqual( - document.querySelector(`.o_ThreadView_messageList`).scrollTop, - 142, - "should have scrolled to 142px" - ); - + await this.afterEvent({ + eventName: 'o-component-message-list-scrolled', + func: () => document.querySelector(`.o_ThreadView_messageList`).scrollTop = 142, + message: "should wait until channel 20 scrolled to 142 after setting this value manually", + predicate: ({ scrollTop, threadViewer }) => { + return ( + threadViewer.thread.model === 'mail.channel' && + threadViewer.thread.id === 20 && + scrollTop === 142 + ); + }, + }); // fold chat window await afterNextRender(() => document.querySelector('.o_ChatWindow_header').click()); await this.hideHomeMenu(); // unfold chat window - await afterNextRender(() => document.querySelector('.o_ChatWindow_header').click()); + await this.afterEvent({ + eventName: 'o-component-message-list-scrolled', + func: () => document.querySelector('.o_ChatWindow_header').click(), + message: "should wait until channel 20 restored its scroll to 142 after unfolding it", + predicate: ({ scrollTop, threadViewer }) => { + return ( + threadViewer.thread.model === 'mail.channel' && + threadViewer.thread.id === 20 && + scrollTop === 142 + ); + }, + }); assert.strictEqual( document.querySelector(`.o_ThreadView_messageList`).scrollTop, 142, @@ -1790,7 +1827,18 @@ QUnit.test('[technical] chat window with a thread: keep scroll position in messa // Show home menu await this.showHomeMenu(); // unfold chat window - await afterNextRender(() => document.querySelector('.o_ChatWindow_header').click()); + await this.afterEvent({ + eventName: 'o-component-message-list-scrolled', + func: () => document.querySelector('.o_ChatWindow_header').click(), + message: "should wait until channel 20 restored its scroll position to the last saved value (142)", + predicate: ({ scrollTop, threadViewer }) => { + return ( + threadViewer.thread.model === 'mail.channel' && + threadViewer.thread.id === 20 && + scrollTop === 142 + ); + }, + }); assert.strictEqual( document.querySelector(`.o_ThreadView_messageList`).scrollTop, 142, @@ -1925,8 +1973,8 @@ QUnit.test('new message separator is shown in a chat window of a chat on receivi }); this.data['mail.channel'].records = [ { - id: 10, channel_type: "chat", + id: 10, is_minimized: true, is_pinned: false, members: [this.data.currentPartnerId, 10], @@ -1951,8 +1999,8 @@ QUnit.test('new message separator is shown in a chat window of a chat on receivi context: { mockedUserId: 42, }, - uuid: 'channel-10-uuid', message_content: "hu", + uuid: 'channel-10-uuid', }, })); assert.containsOnce( @@ -1985,28 +2033,28 @@ QUnit.test('focusing a chat window of a chat should make new message separator d name: "Foreigner user", partner_id: 10, }); - this.data['mail.channel'].records = [ + this.data['mail.channel'].records.push( { - id: 10, channel_type: "chat", + id: 10, is_minimized: true, is_pinned: false, members: [this.data.currentPartnerId, 10], message_unread_counter: 0, uuid: 'channel-10-uuid', }, - ]; + ); await this.start(); // simulate receiving a message - await afterNextRender(async () => this.env.services.rpc({ + await afterNextRender(() => this.env.services.rpc({ route: '/mail/chat_post', params: { context: { mockedUserId: 42, }, - uuid: 'channel-10-uuid', message_content: "hu", + uuid: 'channel-10-uuid', }, })); assert.containsOnce( @@ -2015,7 +2063,17 @@ QUnit.test('focusing a chat window of a chat should make new message separator d "should display 'new messages' separator in the conversation, from reception of new messages" ); - await afterNextRender(() => document.querySelector('.o_ComposerTextInput_textarea').focus()); + await afterNextRender(() => this.afterEvent({ + eventName: 'o-thread-last-seen-by-current-partner-message-id-changed', + func: () => document.querySelector('.o_ComposerTextInput_textarea').focus(), + message: "should wait until last seen by current partner message id changed", + predicate: ({ thread }) => { + return ( + thread.id === 10 && + thread.model === 'mail.channel' + ); + }, + })); assert.containsNone( document.body, '.o_MessageList_separatorNewMessages', |
