From b5850775c07456e41cd4d3e1643547fe6d861172 Mon Sep 17 00:00:00 2001 From: Wattachai Kanawitoon <117723407+wattachai-lseg@users.noreply.github.com> Date: Wed, 22 Feb 2023 17:37:04 +0700 Subject: [PATCH 01/16] fix(tooltip): add new a test case for row of buttons --- .../elements/src/tooltip/__demo__/index.html | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/packages/elements/src/tooltip/__demo__/index.html b/packages/elements/src/tooltip/__demo__/index.html index 794a4e6e5f..bba0e0c885 100644 --- a/packages/elements/src/tooltip/__demo__/index.html +++ b/packages/elements/src/tooltip/__demo__/index.html @@ -110,6 +110,26 @@ + + side by side buttons: testing tooltip display + + +
+ Tooltip1 + Tooltip2 +
+
+
Tooltip can have different transition styles, which may be overridden by changing `transitionStyle`.

From b883cb315a3c841c4d58a5094ff94f3ec9da6633 Mon Sep 17 00:00:00 2001 From: Wattachai Kanawitoon <117723407+wattachai-lseg@users.noreply.github.com> Date: Wed, 22 Feb 2023 17:40:32 +0700 Subject: [PATCH 02/16] fix(tooltip): add native ResizeObserver detection and polyfill fallback --- packages/core/src/elements/ResponsiveElement.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/core/src/elements/ResponsiveElement.ts b/packages/core/src/elements/ResponsiveElement.ts index e6bb324c07..3c34094f4a 100644 --- a/packages/core/src/elements/ResponsiveElement.ts +++ b/packages/core/src/elements/ResponsiveElement.ts @@ -1,5 +1,6 @@ import { BasicElement } from './BasicElement.js'; -import { ResizeObserver, ResizeObserverEntry } from '@juggle/resize-observer'; +// If ResizeObserver native API works fine, this package should be removed in future +import { ResizeObserver as PolyfillResizeObserver } from '@juggle/resize-observer'; export type ElementSize = { width: number; @@ -48,13 +49,21 @@ const triggerResize = (entry: ResizeObserverEntry): void => { entry.target.dispatchEvent(event); }; +/** + * Trigger Resize all entries from ResizeObserver + * @param entries array of ResizeObserverEntry + * @returns {void} + */ +const entriesResize = (entries: ResizeObserverEntry[]): void => { + entries.forEach(entry => triggerResize(entry)); +}; + /** * Global resize observer, * used to watch changes in element dimensions */ -const resizeObserver = new ResizeObserver(entries => { - entries.forEach(entry => triggerResize(entry)); -}); +const resizeObserver = typeof ResizeObserver === 'function' ? new ResizeObserver(entriesResize) : new PolyfillResizeObserver(entriesResize); + /** * Responsive element base class. From 272b499ec2d65977cb0a3e0667b95140c2c2d28a Mon Sep 17 00:00:00 2001 From: Wattachai Kanawitoon <117723407+wattachai-lseg@users.noreply.github.com> Date: Thu, 16 Mar 2023 15:57:39 +0700 Subject: [PATCH 03/16] feat(test-helpers): add frame count param to nextFrame & inNear util --- .../__test__/test-helpers.test.js | 54 ++++++++++++++++++- packages/test-helpers/src/test-helpers.ts | 33 +++++++++++- 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/packages/test-helpers/__test__/test-helpers.test.js b/packages/test-helpers/__test__/test-helpers.test.js index 32a2e6416b..43e93758e6 100644 --- a/packages/test-helpers/__test__/test-helpers.test.js +++ b/packages/test-helpers/__test__/test-helpers.test.js @@ -1,4 +1,5 @@ -import { fixture, expect, keyboardEvent, oneEvent } from '../lib/test-helpers'; +import { fixture, expect, keyboardEvent, oneEvent, isNear, nextFrame } from '../lib/test-helpers'; +import { createSandbox } from 'sinon'; describe('TestHelpersTest', () => { @@ -48,4 +49,55 @@ describe('TestHelpersTest', () => { }); }); + describe('Test nextFrame helper', () => { + const sandbox = createSandbox(); + + beforeEach(async () => { + sandbox.spy(window, "requestAnimationFrame"); + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('Calling nextFrame without param', async () => { + await nextFrame(); + expect(window.requestAnimationFrame.calledOnce).to.equal(true, 'requestAnimationFrame should be called once'); + }); + it('Calling nextFrame with 1 as param', async () => { + await nextFrame(1); + expect(window.requestAnimationFrame.calledOnce).to.equal(true, 'requestAnimationFrame should be called once'); + }); + it('Calling nextFrame with 2 as param', async () => { + await nextFrame(2); + expect(window.requestAnimationFrame.calledTwice).to.equal(true, 'requestAnimationFrame should be called twice'); + }); + }); + + describe('Test isNear helper', () => { + it('Calling isNear with numbers & distance', async () => { + expect(isNear(10, 10, 0)).to.equal(true, 'isNear at boundary distance of 0 should be true'); + expect(isNear(10, 10.1, 0)).to.equal(false, 'isNear beyond boundary distance of 0 should be false'); + expect(isNear(10, 14.9, 5)).to.equal(true, 'isNear within boundary distance greater than 0 should be true'); + expect(isNear(10, 15, 5)).to.equal(true, 'isNear at boundary distance greater than 0 should be true'); + expect(isNear(10, 15.1, 5)).to.equal(false, 'isNear beyond boundary distance greater than 0 should be true'); + }); + + it('Calling isNear with numbers, distance & inclusive as true', async () => { + expect(isNear(10, 10, 0, true)).to.equal(true, 'isNear at boundary distance of 0 should be true'); + expect(isNear(10, 10.1, 0, true)).to.equal(false, 'isNear beyond boundary distance of 0 should be false'); + expect(isNear(10, 14.9, 5, true)).to.equal(true, 'isNear within boundary distance greater than 0 should be true'); + expect(isNear(10, 15, 5, true)).to.equal(true, 'isNear at boundary distance greater than 0 should be true'); + expect(isNear(10, 15.1, 5, true)).to.equal(false, 'isNear beyond boundary distance greater than 0 should be true'); + }); + + it('Calling isNear with numbers, distance & inclusive as false', async () => { + expect(isNear(10, 10, 0, false)).to.equal(true, 'isNear at boundary distance of 0 should be true'); + expect(isNear(10, 10.1, 0, false)).to.equal(false, 'isNear beyond boundary distance of 0 should be false'); + expect(isNear(10, 14.9, 5, false)).to.equal(true, 'isNear within boundary distance greater than 0 should be true'); + expect(isNear(10, 15, 5, false)).to.equal(false, 'isNear at boundary distance greater than 0 should be true'); + expect(isNear(10, 15.1, 5, false)).to.equal(false, 'isNear beyond boundary distance greater than 0 should be true'); + }); + }); + }); diff --git a/packages/test-helpers/src/test-helpers.ts b/packages/test-helpers/src/test-helpers.ts index c2b1672bbe..717e510508 100644 --- a/packages/test-helpers/src/test-helpers.ts +++ b/packages/test-helpers/src/test-helpers.ts @@ -14,7 +14,6 @@ export { defineCE, aTimeout, waitUntil, - nextFrame, litFixture, litFixtureSync, fixture, @@ -22,6 +21,7 @@ export { fixtureCleanup, elementUpdated } from '@open-wc/testing'; +import { nextFrame as _nextFrame } from '@open-wc/testing'; export interface CustomKeyboardEvent extends CustomEvent { key: string; @@ -56,3 +56,34 @@ export const keyboardEvent = (type: string, init: KeyboardEventInit = {}): Keybo return event; }; + +/** + * Resolves after requestAnimationFrame. + * @param [frameCount = 1] number of animationFrame to be requested + * + * @returns {Promise} Promise that resolved after requestAnimationFrame + */ +export const nextFrame = async (frameCount = 1): Promise => { + for (let i = 0; i < frameCount; i++) { + await _nextFrame(); + } +}; + +/** + * Check value difference between 2 number. + * If it's within `distance` value, they are near. + * @param a 1 of the 2 numbers to be checked + * @param b 1 of the 2 numbers to be checked + * @param distance maximum value difference of `a` & `b` to be considered near, must equal or greater than 0 + * @param [inclusive = true] `true`: value difference must be smaller or equal to `distance` , `false`: value difference must be smaller than `distance` + * If `distance` is 0, inclusive would be overwritten as `true`. + * + * @returns {boolean} equality result + */ +export const isNear = (a: number, b: number, distance: number, inclusive = true): boolean => { + if (distance === 0) { + inclusive = true; + } + const diff = Math.abs(a - b); + return inclusive ? diff <= distance : diff < distance; +}; From 029443f86bd655f5bb2770bf512650834a805372 Mon Sep 17 00:00:00 2001 From: Wattachai Kanawitoon <117723407+wattachai-lseg@users.noreply.github.com> Date: Thu, 16 Mar 2023 15:59:31 +0700 Subject: [PATCH 04/16] test(canvas): add wait another frame --- packages/elements/src/canvas/__test__/canvas.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/elements/src/canvas/__test__/canvas.test.js b/packages/elements/src/canvas/__test__/canvas.test.js index 562d863871..292b3254ba 100644 --- a/packages/elements/src/canvas/__test__/canvas.test.js +++ b/packages/elements/src/canvas/__test__/canvas.test.js @@ -45,7 +45,7 @@ describe('canvas/Canvas', () => { Object.defineProperty(window, 'devicePixelRatio', { value: null }); - await nextFrame(); + await nextFrame(2); // Chrome 111 & Firefox 111 needs another frame to complete canvas rendering expect(el.canvas.width).equal(Math.floor(el.width * dpr)); expect(el.canvas.height).equal(Math.floor(el.height * dpr)); }); @@ -55,7 +55,7 @@ describe('canvas/Canvas', () => { Object.defineProperty(window, 'devicePixelRatio', { value: 3 }); - await nextFrame(); + await nextFrame(2); // Chrome 111 & Firefox 111 needs another frame to complete canvas rendering expect(el.canvas.width).equal(Math.floor(el.width * devicePixelRatio)); expect(el.canvas.height).equal(Math.floor(el.height * devicePixelRatio)); Object.defineProperty(window, 'devicePixelRatio', { @@ -70,7 +70,7 @@ describe('canvas/Canvas', () => { it('Handles fractional pixelation', async () => { el.style.width = '300.5px'; - await elementUpdated(); + await elementUpdated(el); const listener = function () { el.removeEventListener('resize', listener); expect(el.style.width, 'ef-canvas\'s width should be fractional').equal('300.5px'); From 0688252e6e52c6e9559cde1773dc40a5bc110a11 Mon Sep 17 00:00:00 2001 From: Wattachai Kanawitoon <117723407+wattachai-lseg@users.noreply.github.com> Date: Thu, 16 Mar 2023 17:24:41 +0700 Subject: [PATCH 05/16] test: fix incorrect param of nextFrame --- packages/elements/src/datetime-field/__test__/utils.js | 2 +- packages/elements/src/select/__test__/select.events.test.js | 2 +- packages/translate/__test__/elf-translate-element.test.js | 6 +++--- packages/translate/__test__/elf-translate.navigator.test.js | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/elements/src/datetime-field/__test__/utils.js b/packages/elements/src/datetime-field/__test__/utils.js index 826620bb12..8f366b6414 100644 --- a/packages/elements/src/datetime-field/__test__/utils.js +++ b/packages/elements/src/datetime-field/__test__/utils.js @@ -4,7 +4,7 @@ const inputValue = (el) => el.inputValue; // Access private property const inputElement = (el) => el.inputElement; // Access private property const focusInput = async (el) => { await triggerFocusFor(inputElement(el)); - await nextFrame(el); + await nextFrame(); }; const arrowRight = async (el) => { diff --git a/packages/elements/src/select/__test__/select.events.test.js b/packages/elements/src/select/__test__/select.events.test.js index c76441ef7d..5f5c921771 100644 --- a/packages/elements/src/select/__test__/select.events.test.js +++ b/packages/elements/src/select/__test__/select.events.test.js @@ -110,7 +110,7 @@ describe('select/Events', () => { it('opened-changed event on keyboard pressed', async () => { const el = await fixture(`${getOptions()}`); el.focus(); - await nextFrame(el); + await nextFrame(); let counter = 0; let opened = false; diff --git a/packages/translate/__test__/elf-translate-element.test.js b/packages/translate/__test__/elf-translate-element.test.js index 3017ba5904..0538472864 100644 --- a/packages/translate/__test__/elf-translate-element.test.js +++ b/packages/translate/__test__/elf-translate-element.test.js @@ -47,7 +47,7 @@ describe('Elf Translate Element Lang Test', () => { expect(el.defaultEl.innerText).to.equal('Региональные настройки: ru'); el.lang = 'en'; await elementUpdated(el); - await nextFrame(el); // need for IE11 + await nextFrame(); // need for IE11 expect(el.defaultEl.innerText).to.equal('This is en locale'); }); @@ -56,11 +56,11 @@ describe('Elf Translate Element Lang Test', () => { expect(el.numberEl.innerText).to.equal('Long number: 0'); el.number = 1000; await elementUpdated(el); - await nextFrame(el); + await nextFrame(); expect(el.numberEl.innerText).to.equal('Long number: 1,000'); el.number = 1000000; await elementUpdated(el); - await nextFrame(el); + await nextFrame(); expect(el.numberEl.innerText).to.equal('Long number: 1,000,000'); }); diff --git a/packages/translate/__test__/elf-translate.navigator.test.js b/packages/translate/__test__/elf-translate.navigator.test.js index 42460baf66..f56bcc8f07 100644 --- a/packages/translate/__test__/elf-translate.navigator.test.js +++ b/packages/translate/__test__/elf-translate.navigator.test.js @@ -20,13 +20,13 @@ describe('Elf Translate Navigator Test', () => { } document.documentElement.lang = 'en-US'; - await nextFrame(el); + await nextFrame(); expect(el.defaultEl.innerText).to.equal('This is en-US locale', 'Document locale should take priority over navigator'); el.lang = 'en-GB'; await elementUpdated(el); - await nextFrame(el); // need for IE11 + await nextFrame(); // need for IE11 expect(el.defaultEl.innerText).to.equal('This is en locale', 'Element locale should take priority over document locale'); }); }); From 79d5f2e73099bed051d6bd64318ce1691b1fcebd Mon Sep 17 00:00:00 2001 From: Wattachai Kanawitoon <117723407+wattachai-lseg@users.noreply.github.com> Date: Thu, 16 Mar 2023 17:48:26 +0700 Subject: [PATCH 06/16] test(clock): wait one more frame to complete rendering --- .../src/clock/__test__/clock.analogue.test.js | 12 ++++++------ packages/elements/src/clock/__test__/clock.test.js | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/elements/src/clock/__test__/clock.analogue.test.js b/packages/elements/src/clock/__test__/clock.analogue.test.js index ad305b48cf..e165b8ebe8 100644 --- a/packages/elements/src/clock/__test__/clock.analogue.test.js +++ b/packages/elements/src/clock/__test__/clock.analogue.test.js @@ -48,11 +48,11 @@ describe('clock/Analogue', () => { it('Shows small size clock when width is less than 130px', async () => { expect(el.shadowRoot.querySelector('[part="digital"]'), 'digital clock should display inside a default analog clock').not.to.be.null; - + // make size smaller than defined break point el.style.width = '129px'; await elementUpdated(el); - await nextFrame(); + await nextFrame(2); // Chrome 111 & Firefox 111 needs another frame to complete rendering expect(el.shadowRoot.querySelector('[part="digital"]'), 'digital clock should not display inside small clock').to.be.null; expect(el.amPm, 'am-pm should be hidden by default on small clock').to.be.equal(false); @@ -63,18 +63,18 @@ describe('clock/Analogue', () => { el.style.width = '129px'; await elementUpdated(el); await nextFrame(); - + // test default behavior expect(el.hasAttribute('am-pm')).to.be.equal(false); expect(el.amPm).to.be.equal(false); expect(el.shadowRoot.querySelector('[part="segment am-pm"]')).to.be.null; - + // test when it has am-pm attribute el = await fixture(''); el.style.width = '129px'; await elementUpdated(el); await nextFrame(); - + expect(el.amPm, 'amPm property should be true if am-pm attribute is set').to.be.equal(true); expect(el.shadowRoot.querySelector('[part="segment am-pm"]'), 'AM/PM should display on clock').not.to.be.null; @@ -92,7 +92,7 @@ describe('clock/Analogue', () => { await nextFrame(); expect(el.hasAttribute('size'), 'size attribute should not show if not analog').to.be.equal(false); - + el.style.width = '129px'; await elementUpdated(el); await nextFrame(); diff --git a/packages/elements/src/clock/__test__/clock.test.js b/packages/elements/src/clock/__test__/clock.test.js index 2dbc0ac110..dca0ce0c0d 100644 --- a/packages/elements/src/clock/__test__/clock.test.js +++ b/packages/elements/src/clock/__test__/clock.test.js @@ -25,7 +25,7 @@ describe('clock/Clock', () => { el = await fixture(''); el.style.width = '129px'; await elementUpdated(el); - await nextFrame(); + await nextFrame(2); // Chrome 111 & Firefox 111 needs another frame to complete rendering expect(el).shadowDom.to.equalSnapshot(); }); From 62a91e25e6789d10157c31f4b9087eb8b3264d86 Mon Sep 17 00:00:00 2001 From: Wattachai Kanawitoon <117723407+wattachai-lseg@users.noreply.github.com> Date: Thu, 16 Mar 2023 17:53:32 +0700 Subject: [PATCH 07/16] test(interactive-chart): add wait for element update & a few more frames --- .../__test__/interactive-chart.test.js | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/packages/elements/src/interactive-chart/__test__/interactive-chart.test.js b/packages/elements/src/interactive-chart/__test__/interactive-chart.test.js index 6998d1dc85..7ac5088005 100644 --- a/packages/elements/src/interactive-chart/__test__/interactive-chart.test.js +++ b/packages/elements/src/interactive-chart/__test__/interactive-chart.test.js @@ -833,8 +833,8 @@ describe('interactive-chart/InteractiveChart', () => { it('Should has dynamic left position in legend when the chart set y axis at left', async () => { el.config = linePositionLeft; - await elementUpdated(); - await nextFrame(); + await elementUpdated(el); + await nextFrame(3); // Chrome 111 & Firefox 111 requires 3 frames to complete rendering expect(el.chart).to.not.be.undefined; expect(el.chart).to.not.be.null; @@ -846,8 +846,8 @@ describe('interactive-chart/InteractiveChart', () => { it('Should has dynamic left position in legend when the chart set y axis at both edge', async () => { el.config = twoPriceScales; - await elementUpdated(); - await nextFrame(); + await elementUpdated(el); + await nextFrame(3); // Chrome 111 & Firefox 111 requires 3 frames to complete rendering expect(el.chart).to.not.be.undefined; expect(el.chart).to.not.be.null; @@ -859,8 +859,8 @@ describe('interactive-chart/InteractiveChart', () => { it('Should has fixed left position in legend when the chart set y axis at right edge', async () => { el.config = line; - await elementUpdated(); - await nextFrame(); + await elementUpdated(el); + await nextFrame(3); // Chrome 111 & Firefox 111 requires 3 frames to complete rendering expect(el.chart).to.not.be.undefined; expect(el.chart).to.not.be.null; @@ -873,32 +873,36 @@ describe('interactive-chart/InteractiveChart', () => { describe('Test deprecated attribute', () => { it('Switch attribute legendstyle horizontal to vertical, it should display vertical style', async () => { el = await fixture(''); - + el.config = line; - await elementUpdated(); + await elementUpdated(el); + await nextFrame(2); // Chrome 111 & Firefox 111 requires 2 frames to complete rendering + expect(el.chart).to.not.be.undefined; expect(el.chart).to.not.be.null; - + el.setAttribute('legendstyle','vertical'); - + await nextFrame(); - await elementUpdated(); + await elementUpdated(el); expect(el.getAttribute('legend-style')).to.null; expect(el.shadowRoot.querySelector('[part=legend]').className).to.not.include('horizontal'); }); it('Set legend-style to vertical when legendstyle horizontal, it should display vertical style', async () => { el = await fixture(''); - + el.config = line; - await elementUpdated(); + await elementUpdated(el); + await nextFrame(2); // Chrome 111 & Firefox 111 requires 2 frames to complete rendering + expect(el.chart).to.not.be.undefined; expect(el.chart).to.not.be.null; expect(el.getAttribute('legendstyle')).to.equal('horizontal'); - + el.setAttribute('legend-style','vertical'); - + await nextFrame(); - await elementUpdated(); + await elementUpdated(el); expect(el.shadowRoot.querySelector('[part=legend]').className).to.not.include('horizontal'); }); }); From 248f30b2f3b85d1c331595dc48160d8ca1478fe8 Mon Sep 17 00:00:00 2001 From: Wattachai Kanawitoon <117723407+wattachai-lseg@users.noreply.github.com> Date: Thu, 16 Mar 2023 18:02:31 +0700 Subject: [PATCH 08/16] test(tab-bar): wait a frame for rendering --- .../elements/src/tab-bar/__test__/tab-bar.template.test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/elements/src/tab-bar/__test__/tab-bar.template.test.js b/packages/elements/src/tab-bar/__test__/tab-bar.template.test.js index c4f9da444d..4fa769c30c 100644 --- a/packages/elements/src/tab-bar/__test__/tab-bar.template.test.js +++ b/packages/elements/src/tab-bar/__test__/tab-bar.template.test.js @@ -1,4 +1,4 @@ -import { fixture, expect, elementUpdated, aTimeout } from '@refinitiv-ui/test-helpers'; +import { fixture, expect, elementUpdated, aTimeout, nextFrame } from '@refinitiv-ui/test-helpers'; import '@refinitiv-ui/elements/tab-bar'; import '@refinitiv-ui/elemental-theme/light/ef-tab-bar'; @@ -100,6 +100,7 @@ describe('tab-bar/TabBar', () => { }); it('Should show only right scroll button', async () => { + await nextFrame(); // wait for rendering expect(getElementStyle(leftScrollBtn, 'display')).equal('none'); expect(getElementStyle(rightScrollBtn, 'display')).equal('flex'); }); From e83801947137c32ff7c0100d60939fdd70adf17a Mon Sep 17 00:00:00 2001 From: Wattachai Kanawitoon <117723407+wattachai-lseg@users.noreply.github.com> Date: Thu, 16 Mar 2023 18:04:04 +0700 Subject: [PATCH 09/16] test(tree-select): wait for element update --- .../src/tree-select/__test__/tree-select.interaction.test.js | 2 +- packages/elements/src/tree-select/__test__/utils.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/elements/src/tree-select/__test__/tree-select.interaction.test.js b/packages/elements/src/tree-select/__test__/tree-select.interaction.test.js index 38d25f8b4a..02c9fa6ff4 100644 --- a/packages/elements/src/tree-select/__test__/tree-select.interaction.test.js +++ b/packages/elements/src/tree-select/__test__/tree-select.interaction.test.js @@ -153,7 +153,7 @@ describe('tree-select/Interaction', () => { el.data = flatData; el.opened = true; changeItemSelection(el, flatSelection); - await nextFrame(); + await openedUpdated(el); const elementToRemove = [...el.shadowRoot.querySelectorAll('ef-pill')].find(el => el.value === itemToRemove.value); // Austria elementToRemove.dispatchEvent(new CustomEvent('clear', { detail: { diff --git a/packages/elements/src/tree-select/__test__/utils.js b/packages/elements/src/tree-select/__test__/utils.js index 5c9823ee81..34860b84e0 100644 --- a/packages/elements/src/tree-select/__test__/utils.js +++ b/packages/elements/src/tree-select/__test__/utils.js @@ -3,7 +3,7 @@ import { elementUpdated, expect, nextFrame } from '@refinitiv-ui/test-helpers'; /** * Cross browser function to wait while select element becomes opened/closed and resized * @param {TreeSelect} el Tree select - * @returns {void} + * @returns {Promise} */ export const openedUpdated = async (el) => { await elementUpdated(el); From 2af85d54a5719d3c24de0ad17d308e934e2777c5 Mon Sep 17 00:00:00 2001 From: Wattachai Kanawitoon <117723407+wattachai-lseg@users.noreply.github.com> Date: Thu, 16 Mar 2023 18:07:49 +0700 Subject: [PATCH 10/16] test(sparkline): wait for element update & a few more frame to complete rendering --- packages/elements/src/sparkline/__test__/sparkline.test.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/elements/src/sparkline/__test__/sparkline.test.js b/packages/elements/src/sparkline/__test__/sparkline.test.js index e5e8500a42..040cdc72e0 100644 --- a/packages/elements/src/sparkline/__test__/sparkline.test.js +++ b/packages/elements/src/sparkline/__test__/sparkline.test.js @@ -1,4 +1,4 @@ -import { fixture, expect, elementUpdated } from '@refinitiv-ui/test-helpers'; +import { fixture, expect, elementUpdated, nextFrame } from '@refinitiv-ui/test-helpers'; // import element and theme import '@refinitiv-ui/elements/sparkline'; @@ -75,7 +75,8 @@ describe('sparkline/Sparkline', () => { expect(isCanvasBlank(canvas)).to.be.true; el.data = data; - await elementUpdated(); + await elementUpdated(el); + await nextFrame(3); // ensure that the rendering's completed expect(countDataChanged).to.equal(1); expect(countDataError).to.equal(0); expect(isCanvasBlank(canvas)).to.be.false; From 5441b80d1749de3da5e59b73d5f6741bfde2ea5d Mon Sep 17 00:00:00 2001 From: Wattachai Kanawitoon <117723407+wattachai-lseg@users.noreply.github.com> Date: Fri, 17 Mar 2023 09:23:19 +0700 Subject: [PATCH 11/16] test(led-gauge): fix waiting for element update --- .../src/led-gauge/__test__/led-gauge.test.js | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/elements/src/led-gauge/__test__/led-gauge.test.js b/packages/elements/src/led-gauge/__test__/led-gauge.test.js index 9bdb16b575..43768c5afd 100644 --- a/packages/elements/src/led-gauge/__test__/led-gauge.test.js +++ b/packages/elements/src/led-gauge/__test__/led-gauge.test.js @@ -56,7 +56,7 @@ describe('led-gauge/LedGauge', () => { el.setAttribute('top-label', 'NewTopLabel'); el.setAttribute('bottom-label', 'NewBottomLabel'); - await elementUpdated(); + await elementUpdated(el); top = el.shadowRoot.querySelector('#top'); bottom = el.shadowRoot.querySelector('#bottom'); @@ -72,7 +72,7 @@ describe('led-gauge/LedGauge', () => { el.topLabel = 'NewTopLabel'; el.bottomLabel = 'NewBottomLabel'; - await elementUpdated(); + await elementUpdated(el); top = el.shadowRoot.querySelector('#top'); bottom = el.shadowRoot.querySelector('#bottom'); @@ -87,7 +87,7 @@ describe('led-gauge/LedGauge', () => { el.removeAttribute('top-label'); el.removeAttribute('bottom-label'); - await elementUpdated(); + await elementUpdated(el); top = el.shadowRoot.querySelector('#top'); bottom = el.shadowRoot.querySelector('#bottom'); @@ -111,7 +111,7 @@ describe('led-gauge/LedGauge', () => { it('Should be able to set topValue and bottomValue via property', async () => { const el = await fixture(full); - await nextFrame(); + await nextFrame(2); // Chrome 111 & Firefox 111 needs another frame to complete rendering top = el.shadowRoot.querySelector('#top'); bottom = el.shadowRoot.querySelector('#bottom'); let topTextPos = parseInt(window.getComputedStyle(top).getPropertyValue('left'), 10); @@ -122,7 +122,7 @@ describe('led-gauge/LedGauge', () => { el.topValue = 50; el.bottomValue = -50; - await elementUpdated(); + await elementUpdated(el); let newTopTextPos = parseInt(window.getComputedStyle(top).getPropertyValue('left'), 10); let newBottomTextPos = parseInt(window.getComputedStyle(bottom).getPropertyValue('left'), 10); @@ -133,7 +133,7 @@ describe('led-gauge/LedGauge', () => { it('Should be able to set topValue and bottomValue via attribute', async () => { const el = await fixture(full); - await nextFrame(); + await nextFrame(2); // Chrome 111 & Firefox 111 needs another frame to complete rendering top = el.shadowRoot.querySelector('#top'); bottom = el.shadowRoot.querySelector('#bottom'); let topTextPos = parseInt(window.getComputedStyle(top).getPropertyValue('left'), 10); @@ -144,7 +144,7 @@ describe('led-gauge/LedGauge', () => { el.setAttribute('top-value', '50'); el.setAttribute('bottom-value', '-50'); - await elementUpdated(); + await elementUpdated(el); let newTopTextPos = parseInt(window.getComputedStyle(top).getPropertyValue('left'), 10); let newBottomTextPos = parseInt(window.getComputedStyle(bottom).getPropertyValue('left'), 10); @@ -161,7 +161,7 @@ describe('led-gauge/LedGauge', () => { it('Should update range label when range-label changed by attribute', async () => { const el = await fixture(rangeFixture); el.setAttribute('range-label', 'NewRangeLabel'); - await elementUpdated(); + await elementUpdated(el); range = el.shadowRoot.querySelector('#range'); expect(range).to.not.equal(null); @@ -171,7 +171,7 @@ describe('led-gauge/LedGauge', () => { it('Should update range label when range-label changed by property', async () => { const el = await fixture(rangeFixture); el.rangeLabel = 'NewRangeLabel'; - await elementUpdated(); + await elementUpdated(el); range = el.shadowRoot.querySelector('#range'); expect(range).to.not.equal(null); @@ -186,7 +186,7 @@ describe('led-gauge/LedGauge', () => { expect(range).to.not.equal(null); el.setAttribute('bottom-label', 'Bottom Text'); - await elementUpdated(); + await elementUpdated(el); expect(bottom).to.equal(null); expect(range).to.not.equal(null); }); @@ -200,20 +200,20 @@ describe('led-gauge/LedGauge', () => { it('Should have min=0 and max=100 when set zero=left by property', async () => { const el = await fixture(zero); el.zero = 'left'; - await elementUpdated(); + await elementUpdated(el); expect(el.zero).to.equal('left'); }); it('Should set zero to center when invalid value is set', async () => { const el = await fixture(zero); el.zero = 'left'; - await elementUpdated(); + await elementUpdated(el); expect(el.zero).to.equal('left'); expect(el.min).to.equal(0); expect(el.max).to.equal(100); el.zero = 'invalid'; - await elementUpdated(); + await elementUpdated(el); expect(el.zero).to.equal('center'); expect(el.min).to.equal(-100); expect(el.max).to.equal(100); From 24aabd7c2636a7cf51176b268c96c35360aa8087 Mon Sep 17 00:00:00 2001 From: Wattachai Kanawitoon <117723407+wattachai-lseg@users.noreply.github.com> Date: Fri, 17 Mar 2023 09:35:19 +0700 Subject: [PATCH 12/16] test(tornado-chart): fix waiting for element update --- .../elements/src/tornado-chart/__test__/tornado-chart.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/elements/src/tornado-chart/__test__/tornado-chart.test.js b/packages/elements/src/tornado-chart/__test__/tornado-chart.test.js index 56e788efa1..b07c2d5be5 100644 --- a/packages/elements/src/tornado-chart/__test__/tornado-chart.test.js +++ b/packages/elements/src/tornado-chart/__test__/tornado-chart.test.js @@ -48,7 +48,7 @@ describe('tornado-chart/TornadoChart', () => { const legend = element.shadowRoot.querySelector('[part="legend"]'); await oneEvent(element, 'resize'); - await elementUpdated(); + await elementUpdated(element); expect(legend.hasAttribute('vertical')).to.equal(true); }); @@ -62,7 +62,7 @@ describe('tornado-chart/TornadoChart', () => { ); await oneEvent(element, 'resize'); - await elementUpdated(); + await elementUpdated(element); const items = element.querySelectorAll('ef-tornado-item'); items.forEach((item) => { From acd1ad7587251d09abf3eedac4941a9fa8d3ba7c Mon Sep 17 00:00:00 2001 From: Wattachai Kanawitoon <117723407+wattachai-lseg@users.noreply.github.com> Date: Fri, 17 Mar 2023 09:35:41 +0700 Subject: [PATCH 13/16] test(tornado-chart): align test file to naming convention --- .../__test__/{tornado-item.test.js => tornado-chart-item.test.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/elements/src/tornado-chart/__test__/{tornado-item.test.js => tornado-chart-item.test.js} (100%) diff --git a/packages/elements/src/tornado-chart/__test__/tornado-item.test.js b/packages/elements/src/tornado-chart/__test__/tornado-chart-item.test.js similarity index 100% rename from packages/elements/src/tornado-chart/__test__/tornado-item.test.js rename to packages/elements/src/tornado-chart/__test__/tornado-chart-item.test.js From 012212518dd2d995f09bda3c42dfed1fae451fd5 Mon Sep 17 00:00:00 2001 From: Wattachai Kanawitoon <117723407+wattachai-lseg@users.noreply.github.com> Date: Fri, 17 Mar 2023 10:01:39 +0700 Subject: [PATCH 14/16] test(test-helpers): add unit test for replaceWhitespace util --- packages/test-helpers/__test__/test-helpers.test.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/test-helpers/__test__/test-helpers.test.js b/packages/test-helpers/__test__/test-helpers.test.js index 43e93758e6..bca94d8c70 100644 --- a/packages/test-helpers/__test__/test-helpers.test.js +++ b/packages/test-helpers/__test__/test-helpers.test.js @@ -1,4 +1,4 @@ -import { fixture, expect, keyboardEvent, oneEvent, isNear, nextFrame } from '../lib/test-helpers'; +import { fixture, expect, keyboardEvent, oneEvent, isNear, nextFrame, replaceWhitespace } from '../lib/test-helpers'; import { createSandbox } from 'sinon'; describe('TestHelpersTest', () => { @@ -100,4 +100,12 @@ describe('TestHelpersTest', () => { }); }); + describe('Test Method helper', () => { + it('Replace spacial whitespace to normal whitespace correctly', () => { + // Remove whitespace character U+202F from Chrome 111 and U+00A0 from Safari + const specialWhitespace = '  '; + expect(replaceWhitespace(specialWhitespace)).to.equal(' ', 'Remove whitespace should work correctly'); + }); + }); + }); From 8ace5fd7810e4f304a5beb92226270fcd3efdb3a Mon Sep 17 00:00:00 2001 From: Wattachai Kanawitoon <117723407+wattachai-lseg@users.noreply.github.com> Date: Fri, 17 Mar 2023 10:03:26 +0700 Subject: [PATCH 15/16] refactor(test-helpers): combine import statement + descope code coverage ignore --- packages/test-helpers/src/test-helpers.ts | 32 +++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/test-helpers/src/test-helpers.ts b/packages/test-helpers/src/test-helpers.ts index 6b5a643b2b..3a643772ea 100644 --- a/packages/test-helpers/src/test-helpers.ts +++ b/packages/test-helpers/src/test-helpers.ts @@ -1,5 +1,4 @@ -/* istanbul ignore file */ -import { isIE } from '@open-wc/testing'; +import { isIE, nextFrame as _nextFrame } from '@open-wc/testing'; export { html, @@ -21,7 +20,6 @@ export { fixtureCleanup, elementUpdated } from '@open-wc/testing'; -import { nextFrame as _nextFrame } from '@open-wc/testing'; export interface CustomKeyboardEvent extends CustomEvent { key: string; @@ -38,23 +36,25 @@ export interface CustomKeyboardEvent extends CustomEvent { * @returns {KeyboardEvent|CustomKeyboardEvent} keyboard event */ export const keyboardEvent = (type: string, init: KeyboardEventInit = {}): KeyboardEvent|CustomKeyboardEvent => { + /* istanbul ignore else */ if (!isIE()) { return new KeyboardEvent(type, init); } + else { + const event = new CustomEvent(type, { + detail: 0, + bubbles: true, + cancelable: true, + composed: true + }) as CustomKeyboardEvent; + event.key = init.key || ''; + event.shiftKey = init.shiftKey || false; + event.altKey = init.altKey || false; + event.ctrlKey = init.ctrlKey || false; + event.metaKey = init.metaKey || false; - const event = new CustomEvent(type, { - detail: 0, - bubbles: true, - cancelable: true, - composed: true - }) as CustomKeyboardEvent; - event.key = init.key || ''; - event.shiftKey = init.shiftKey || false; - event.altKey = init.altKey || false; - event.ctrlKey = init.ctrlKey || false; - event.metaKey = init.metaKey || false; - - return event; + return event; + } }; /** From 043d737e72b8c53785e91aacfd9db3de52b1416b Mon Sep 17 00:00:00 2001 From: Wattachai Kanawitoon <117723407+wattachai-lseg@users.noreply.github.com> Date: Tue, 21 Mar 2023 16:04:58 +0700 Subject: [PATCH 16/16] test: clarity nextFrame usage --- packages/elements/src/canvas/__test__/canvas.test.js | 4 ++-- .../elements/src/clock/__test__/clock.analogue.test.js | 2 +- packages/elements/src/clock/__test__/clock.test.js | 2 +- .../__test__/interactive-chart.test.js | 10 +++++----- .../elements/src/led-gauge/__test__/led-gauge.test.js | 4 ++-- .../elements/src/sparkline/__test__/sparkline.test.js | 2 +- .../src/tab-bar/__test__/tab-bar.template.test.js | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/elements/src/canvas/__test__/canvas.test.js b/packages/elements/src/canvas/__test__/canvas.test.js index 292b3254ba..3b0e134ccc 100644 --- a/packages/elements/src/canvas/__test__/canvas.test.js +++ b/packages/elements/src/canvas/__test__/canvas.test.js @@ -45,7 +45,7 @@ describe('canvas/Canvas', () => { Object.defineProperty(window, 'devicePixelRatio', { value: null }); - await nextFrame(2); // Chrome 111 & Firefox 111 needs another frame to complete canvas rendering + await nextFrame(2); // wait for resize observer & rendering completion expect(el.canvas.width).equal(Math.floor(el.width * dpr)); expect(el.canvas.height).equal(Math.floor(el.height * dpr)); }); @@ -55,7 +55,7 @@ describe('canvas/Canvas', () => { Object.defineProperty(window, 'devicePixelRatio', { value: 3 }); - await nextFrame(2); // Chrome 111 & Firefox 111 needs another frame to complete canvas rendering + await nextFrame(2); // wait for resize observer & rendering completion expect(el.canvas.width).equal(Math.floor(el.width * devicePixelRatio)); expect(el.canvas.height).equal(Math.floor(el.height * devicePixelRatio)); Object.defineProperty(window, 'devicePixelRatio', { diff --git a/packages/elements/src/clock/__test__/clock.analogue.test.js b/packages/elements/src/clock/__test__/clock.analogue.test.js index e165b8ebe8..fb10e2deb5 100644 --- a/packages/elements/src/clock/__test__/clock.analogue.test.js +++ b/packages/elements/src/clock/__test__/clock.analogue.test.js @@ -52,7 +52,7 @@ describe('clock/Analogue', () => { // make size smaller than defined break point el.style.width = '129px'; await elementUpdated(el); - await nextFrame(2); // Chrome 111 & Firefox 111 needs another frame to complete rendering + await nextFrame(2); // wait for resize observer & rendering completion expect(el.shadowRoot.querySelector('[part="digital"]'), 'digital clock should not display inside small clock').to.be.null; expect(el.amPm, 'am-pm should be hidden by default on small clock').to.be.equal(false); diff --git a/packages/elements/src/clock/__test__/clock.test.js b/packages/elements/src/clock/__test__/clock.test.js index dca0ce0c0d..3a96b35e2b 100644 --- a/packages/elements/src/clock/__test__/clock.test.js +++ b/packages/elements/src/clock/__test__/clock.test.js @@ -25,7 +25,7 @@ describe('clock/Clock', () => { el = await fixture(''); el.style.width = '129px'; await elementUpdated(el); - await nextFrame(2); // Chrome 111 & Firefox 111 needs another frame to complete rendering + await nextFrame(2); // wait for resize observer & rendering completion expect(el).shadowDom.to.equalSnapshot(); }); diff --git a/packages/elements/src/interactive-chart/__test__/interactive-chart.test.js b/packages/elements/src/interactive-chart/__test__/interactive-chart.test.js index 7ac5088005..60b34fb05a 100644 --- a/packages/elements/src/interactive-chart/__test__/interactive-chart.test.js +++ b/packages/elements/src/interactive-chart/__test__/interactive-chart.test.js @@ -834,7 +834,7 @@ describe('interactive-chart/InteractiveChart', () => { it('Should has dynamic left position in legend when the chart set y axis at left', async () => { el.config = linePositionLeft; await elementUpdated(el); - await nextFrame(3); // Chrome 111 & Firefox 111 requires 3 frames to complete rendering + await nextFrame(3); // wait for resize observer & rendering completion expect(el.chart).to.not.be.undefined; expect(el.chart).to.not.be.null; @@ -847,7 +847,7 @@ describe('interactive-chart/InteractiveChart', () => { it('Should has dynamic left position in legend when the chart set y axis at both edge', async () => { el.config = twoPriceScales; await elementUpdated(el); - await nextFrame(3); // Chrome 111 & Firefox 111 requires 3 frames to complete rendering + await nextFrame(3); // wait for resize observer & rendering completion expect(el.chart).to.not.be.undefined; expect(el.chart).to.not.be.null; @@ -860,7 +860,7 @@ describe('interactive-chart/InteractiveChart', () => { it('Should has fixed left position in legend when the chart set y axis at right edge', async () => { el.config = line; await elementUpdated(el); - await nextFrame(3); // Chrome 111 & Firefox 111 requires 3 frames to complete rendering + await nextFrame(3); // wait for resize observer & rendering completion expect(el.chart).to.not.be.undefined; expect(el.chart).to.not.be.null; @@ -876,7 +876,7 @@ describe('interactive-chart/InteractiveChart', () => { el.config = line; await elementUpdated(el); - await nextFrame(2); // Chrome 111 & Firefox 111 requires 2 frames to complete rendering + await nextFrame(2); // wait for resize observer & rendering completion expect(el.chart).to.not.be.undefined; expect(el.chart).to.not.be.null; @@ -893,7 +893,7 @@ describe('interactive-chart/InteractiveChart', () => { el.config = line; await elementUpdated(el); - await nextFrame(2); // Chrome 111 & Firefox 111 requires 2 frames to complete rendering + await nextFrame(2); // wait for resize observer & rendering completion expect(el.chart).to.not.be.undefined; expect(el.chart).to.not.be.null; diff --git a/packages/elements/src/led-gauge/__test__/led-gauge.test.js b/packages/elements/src/led-gauge/__test__/led-gauge.test.js index 43768c5afd..684ea23d29 100644 --- a/packages/elements/src/led-gauge/__test__/led-gauge.test.js +++ b/packages/elements/src/led-gauge/__test__/led-gauge.test.js @@ -111,7 +111,7 @@ describe('led-gauge/LedGauge', () => { it('Should be able to set topValue and bottomValue via property', async () => { const el = await fixture(full); - await nextFrame(2); // Chrome 111 & Firefox 111 needs another frame to complete rendering + await nextFrame(2); // wait for resize observer & rendering completion top = el.shadowRoot.querySelector('#top'); bottom = el.shadowRoot.querySelector('#bottom'); let topTextPos = parseInt(window.getComputedStyle(top).getPropertyValue('left'), 10); @@ -133,7 +133,7 @@ describe('led-gauge/LedGauge', () => { it('Should be able to set topValue and bottomValue via attribute', async () => { const el = await fixture(full); - await nextFrame(2); // Chrome 111 & Firefox 111 needs another frame to complete rendering + await nextFrame(2); // wait for resize observer & rendering completion top = el.shadowRoot.querySelector('#top'); bottom = el.shadowRoot.querySelector('#bottom'); let topTextPos = parseInt(window.getComputedStyle(top).getPropertyValue('left'), 10); diff --git a/packages/elements/src/sparkline/__test__/sparkline.test.js b/packages/elements/src/sparkline/__test__/sparkline.test.js index 040cdc72e0..650cc41479 100644 --- a/packages/elements/src/sparkline/__test__/sparkline.test.js +++ b/packages/elements/src/sparkline/__test__/sparkline.test.js @@ -76,7 +76,7 @@ describe('sparkline/Sparkline', () => { el.data = data; await elementUpdated(el); - await nextFrame(3); // ensure that the rendering's completed + await nextFrame(2); // wait for rendering completion expect(countDataChanged).to.equal(1); expect(countDataError).to.equal(0); expect(isCanvasBlank(canvas)).to.be.false; diff --git a/packages/elements/src/tab-bar/__test__/tab-bar.template.test.js b/packages/elements/src/tab-bar/__test__/tab-bar.template.test.js index 4fa769c30c..a428c66614 100644 --- a/packages/elements/src/tab-bar/__test__/tab-bar.template.test.js +++ b/packages/elements/src/tab-bar/__test__/tab-bar.template.test.js @@ -100,7 +100,7 @@ describe('tab-bar/TabBar', () => { }); it('Should show only right scroll button', async () => { - await nextFrame(); // wait for rendering + await nextFrame(); // wait for resize observer & rendering completion expect(getElementStyle(leftScrollBtn, 'display')).equal('none'); expect(getElementStyle(rightScrollBtn, 'display')).equal('flex'); });