diff --git a/addons/mail/static/tests/helpers/test_utils.js b/addons/mail/static/tests/helpers/test_utils.js index 286a0c571a2..f196f8ace8c 100644 --- a/addons/mail/static/tests/helpers/test_utils.js +++ b/addons/mail/static/tests/helpers/test_utils.js @@ -1003,6 +1003,23 @@ function pasteFiles(el, files) { }); } +//------------------------------------------------------------------------------ +// Public: DOM utilities +//------------------------------------------------------------------------------ + +/** + * Determine if a DOM element has been totally scrolled + * + * A 1px margin of error is given to accomodate subpixel rounding issues and + * Element.scrollHeight value being either int or decimal + * + * @param {DOM.Element} el + * @returns {boolean} + */ +function isScrolledToBottom(el) { + return Math.abs(el.scrollHeight - el.clientHeight - el.scrollTop) <= 1; +} + //------------------------------------------------------------------------------ // Export //------------------------------------------------------------------------------ @@ -1011,6 +1028,7 @@ export { afterNextRender, dragenterFiles, dropFiles, + isScrolledToBottom, nextAnimationFrame, nextTick, pasteFiles, diff --git a/addons/mail/static/tests/qunit_suite_tests/components/chat_window_manager_tests.js b/addons/mail/static/tests/qunit_suite_tests/components/chat_window_manager_tests.js index a31a40a3ae4..6ec1ec82996 100644 --- a/addons/mail/static/tests/qunit_suite_tests/components/chat_window_manager_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/components/chat_window_manager_tests.js @@ -4,6 +4,7 @@ import { makeDeferred } from '@mail/utils/deferred'; import { patchUiSize, SIZES } from '@mail/../tests/helpers/patch_ui_size'; import { afterNextRender, + isScrolledToBottom, nextAnimationFrame, start, startServer, @@ -958,7 +959,7 @@ QUnit.test('chat window: scroll conservation on toggle discuss', async function thread && thread.model === 'mail.channel' && thread.id === mailChannelId1 && - scrollTop === messageList.scrollHeight - messageList.clientHeight + isScrolledToBottom(messageList) ); }, }); @@ -1694,7 +1695,7 @@ QUnit.test('chat window with a thread: keep scroll position in message list on f thread && thread.model === 'mail.channel' && thread.id === mailChannelId1 && - scrollTop === messageList.scrollHeight - messageList.clientHeight + isScrolledToBottom(messageList) ); }, }); @@ -1782,9 +1783,8 @@ QUnit.test('chat window should scroll to the newly posted message just after pos ) ); const messageList = document.querySelector('.o_MessageList'); - assert.strictEqual( - messageList.scrollHeight - messageList.scrollTop, - messageList.clientHeight, + assert.ok( + isScrolledToBottom(messageList), "chat window should scroll to the newly posted message just after posting it" ); }); @@ -1845,7 +1845,7 @@ QUnit.test('chat window with a thread: keep scroll position in message list on t thread && thread.model === 'mail.channel' && thread.id === mailChannelId1 && - scrollTop === messageList.scrollHeight - messageList.clientHeight + isScrolledToBottom(messageList) ); }, }); @@ -1915,7 +1915,7 @@ QUnit.test('chat window with a thread: keep scroll position in message list on t thread && thread.model === 'mail.channel' && thread.id === mailChannelId1 && - scrollTop === messageList.scrollHeight - messageList.clientHeight + isScrolledToBottom(messageList) ); }, }); diff --git a/addons/mail/static/tests/qunit_suite_tests/components/discuss_tests.js b/addons/mail/static/tests/qunit_suite_tests/components/discuss_tests.js index 8f842d53f8c..dfdcbd8f0bd 100644 --- a/addons/mail/static/tests/qunit_suite_tests/components/discuss_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/components/discuss_tests.js @@ -4,6 +4,7 @@ import BusService from 'bus.BusService'; import { afterNextRender, + isScrolledToBottom, nextAnimationFrame, start, startServer, @@ -1636,7 +1637,7 @@ QUnit.test('auto-scroll to bottom of thread', async function (assert) { thread && thread.model === 'mail.channel' && thread.id === mailChannelId1 && - scrollTop === messageList.scrollHeight - messageList.clientHeight + isScrolledToBottom(messageList) ); }, }, @@ -1649,9 +1650,8 @@ QUnit.test('auto-scroll to bottom of thread', async function (assert) { "should have 25 messages" ); const messageList = document.querySelector(`.o_Discuss_thread .o_ThreadView_messageList`); - assert.strictEqual( - messageList.scrollTop, - messageList.scrollHeight - messageList.clientHeight, + assert.ok( + isScrolledToBottom(messageList), "should have scrolled to bottom of thread" ); }); @@ -1684,7 +1684,7 @@ QUnit.test('load more messages from channel (auto-load on scroll)', async functi thread && thread.model === 'mail.channel' && thread.id === mailChannelId1 && - scrollTop === messageList.scrollHeight - messageList.clientHeight + isScrolledToBottom(messageList) ); }, }, @@ -1764,7 +1764,7 @@ QUnit.test('new messages separator [REQUIRE FOCUS]', async function (assert) { thread && thread.model === 'mail.channel' && thread.id === mailChannelId1 && - scrollTop === messageList.scrollHeight - messageList.clientHeight + isScrolledToBottom(messageList) ); }, }, @@ -1834,7 +1834,7 @@ QUnit.test('new messages separator [REQUIRE FOCUS]', async function (assert) { thread && thread.model === 'mail.channel' && thread.id === mailChannelId1 && - scrollTop === messageList.scrollHeight - messageList.clientHeight + isScrolledToBottom(messageList) ); }, }); @@ -1898,9 +1898,8 @@ QUnit.test('restore thread scroll position', async function (assert) { .o_Discuss_thread .o_ThreadView_messageList `); - assert.strictEqual( - initialMessageList.scrollTop, - initialMessageList.scrollHeight - initialMessageList.clientHeight, + assert.ok( + isScrolledToBottom(initialMessageList), "should have scrolled to bottom of channel 1 initially" ); @@ -1943,7 +1942,7 @@ QUnit.test('restore thread scroll position', async function (assert) { thread && thread.model === 'mail.channel' && thread.id === mailChannelId2 && - scrollTop === messageList.scrollHeight - messageList.clientHeight + isScrolledToBottom(messageList) ); }, }); @@ -2006,14 +2005,13 @@ QUnit.test('restore thread scroll position', async function (assert) { thread && thread.model === 'mail.channel' && thread.id === mailChannelId2 && - scrollTop === messageList.scrollHeight - messageList.clientHeight + isScrolledToBottom(messageList) ); }, }); const messageList = document.querySelector('.o_ThreadView_messageList'); - assert.strictEqual( - messageList.scrollTop, - messageList.scrollHeight - messageList.clientHeight, + assert.ok( + isScrolledToBottom(messageList), "should have recovered scroll position of channel 2 (scroll to bottom)" ); }); @@ -3472,7 +3470,7 @@ QUnit.test('all messages in "Inbox" in "History" after marked all as read', asyn thread.model === 'mail.box' && thread.id === 'inbox' && orderedMessages.length === 30 && - scrollTop === messageList.scrollHeight - messageList.clientHeight + isScrolledToBottom(messageList) ); }, }, @@ -3502,7 +3500,7 @@ QUnit.test('all messages in "Inbox" in "History" after marked all as read', asyn thread.model === 'mail.box' && thread.id === 'history' && orderedMessages.length === 30 && - scrollTop === messageList.scrollHeight - messageList.clientHeight + isScrolledToBottom(messageList) ); }, }); diff --git a/addons/mail/static/tests/qunit_suite_tests/components/thread_view_tests.js b/addons/mail/static/tests/qunit_suite_tests/components/thread_view_tests.js index f6bbfda4ded..091683fb183 100644 --- a/addons/mail/static/tests/qunit_suite_tests/components/thread_view_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/components/thread_view_tests.js @@ -4,6 +4,7 @@ import { insert, insertAndReplace, replace } from '@mail/model/model_field_comma import { afterNextRender, dragenterFiles, + isScrolledToBottom, start, startServer, } from '@mail/../tests/helpers/test_utils'; @@ -794,9 +795,8 @@ QUnit.test('should scroll to bottom on receiving new message if the list is init predicate: data => threadViewer === data.threadViewer, }); const initialMessageList = document.querySelector('.o_ThreadView_messageList'); - assert.strictEqual( - initialMessageList.scrollTop, - initialMessageList.scrollHeight - initialMessageList.clientHeight, + assert.ok( + isScrolledToBottom(initialMessageList), "should have scrolled to bottom of channel 20 initially" ); @@ -818,9 +818,8 @@ QUnit.test('should scroll to bottom on receiving new message if the list is init predicate: data => threadViewer === data.threadViewer, }); const messageList = document.querySelector('.o_ThreadView_messageList'); - assert.strictEqual( - messageList.scrollTop, - messageList.scrollHeight - messageList.clientHeight, + assert.ok( + isScrolledToBottom(messageList), "should scroll to bottom on receiving new message because the list is initially scrolled to bottom" ); }); @@ -866,9 +865,8 @@ QUnit.test('should not scroll on receiving new message if the list is initially predicate: data => threadViewer === data.threadViewer, }); const initialMessageList = document.querySelector('.o_ThreadView_messageList'); - assert.strictEqual( - initialMessageList.scrollTop, - initialMessageList.scrollHeight - initialMessageList.clientHeight, + assert.ok( + isScrolledToBottom(initialMessageList), "should have scrolled to bottom of channel 1 initially" ); diff --git a/addons/mail/static/tests/qunit_suite_tests/widgets/form_renderer_tests.js b/addons/mail/static/tests/qunit_suite_tests/widgets/form_renderer_tests.js index 2c4e8e6fc3e..2f9a9a56989 100644 --- a/addons/mail/static/tests/qunit_suite_tests/widgets/form_renderer_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/widgets/form_renderer_tests.js @@ -4,6 +4,7 @@ import { makeDeferred } from '@mail/utils/deferred'; import { patchUiSize, SIZES } from '@mail/../tests/helpers/patch_ui_size'; import { afterNextRender, + isScrolledToBottom, nextAnimationFrame, start, startServer, @@ -816,9 +817,8 @@ QUnit.test('Form view not scrolled when switching record', async function (asser 'scroll' ); }); - assert.strictEqual( - controllerContentEl.scrollTop, - controllerContentEl.scrollHeight - controllerContentEl.clientHeight, + assert.ok( + isScrolledToBottom(controllerContentEl), "The controller container should be scrolled to its bottom" );