From ea13f5fc2b47e70beb97eab524e277259d253b64 Mon Sep 17 00:00:00 2001 From: web-padawan Date: Tue, 14 May 2024 13:45:27 +0300 Subject: [PATCH] test: add unit tests for popover overlay position --- packages/popover/test/basic.test.js | 1 + packages/popover/test/not-animated-styles.js | 13 ++ packages/popover/test/position.test.js | 172 +++++++++++++++++++ 3 files changed, 186 insertions(+) create mode 100644 packages/popover/test/not-animated-styles.js create mode 100644 packages/popover/test/position.test.js diff --git a/packages/popover/test/basic.test.js b/packages/popover/test/basic.test.js index bcb1e30894..e788735d84 100644 --- a/packages/popover/test/basic.test.js +++ b/packages/popover/test/basic.test.js @@ -1,6 +1,7 @@ import { expect } from '@esm-bundle/chai'; import { esc, fixtureSync, nextRender, nextUpdate, outsideClick } from '@vaadin/testing-helpers'; import sinon from 'sinon'; +import './not-animated-styles.js'; import '../vaadin-popover.js'; describe('popover', () => { diff --git a/packages/popover/test/not-animated-styles.js b/packages/popover/test/not-animated-styles.js new file mode 100644 index 0000000000..7f3e2564e6 --- /dev/null +++ b/packages/popover/test/not-animated-styles.js @@ -0,0 +1,13 @@ +import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; + +registerStyles( + 'vaadin-popover-overlay', + css` + :host([opening]), + :host([closing]), + :host([opening]) [part='overlay'], + :host([closing]) [part='overlay'] { + animation: none !important; + } + `, +); diff --git a/packages/popover/test/position.test.js b/packages/popover/test/position.test.js new file mode 100644 index 0000000000..1a335692bd --- /dev/null +++ b/packages/popover/test/position.test.js @@ -0,0 +1,172 @@ +import { expect } from '@esm-bundle/chai'; +import { fixtureSync, nextRender, nextUpdate, oneEvent } from '@vaadin/testing-helpers'; +import './not-animated-styles.js'; +import '../src/vaadin-popover.js'; + +describe('position', () => { + let popover, target, overlay; + + beforeEach(async () => { + popover = fixtureSync(''); + popover.renderer = (root) => { + root.textContent = 'Content'; + }; + target = fixtureSync('
'); + popover.target = target; + await nextRender(); + overlay = popover.shadowRoot.querySelector('vaadin-popover-overlay'); + }); + + // Overlay above the target (position="top-*") + function assertPlacedAbove(overlayRect, targetRect) { + expect(overlayRect.bottom).to.be.closeTo(targetRect.top, 1); + } + + // Overlay below the target (position="bottom-*") + function assertPlacedBelow(overlayRect, targetRect) { + expect(overlayRect.top).to.be.closeTo(targetRect.bottom, 1); + } + + // Overlay before the target (position="start-*") + function assertPlacedBefore(overlayRect, targetRect, dir) { + const x1 = dir === 'rtl' ? 'left' : 'right'; + const x2 = dir === 'rtl' ? 'right' : 'left'; + expect(overlayRect[x1]).to.be.closeTo(targetRect[x2], 1); + } + + // Overlay after the target (position="end-*") + function assertPlacedAfter(overlayRect, targetRect, dir) { + const x1 = dir === 'rtl' ? 'right' : 'left'; + const x2 = dir === 'rtl' ? 'left' : 'right'; + expect(overlayRect[x1]).to.be.closeTo(targetRect[x2], 1); + } + + function assertStartAligned(overlayRect, targetRect, dir) { + const x = dir === 'rtl' ? 'right' : 'left'; + expect(overlayRect[x]).to.be.closeTo(targetRect[x], 1); + } + + function assertEndAligned(overlayRect, targetRect, dir) { + const x = dir === 'rtl' ? 'left' : 'right'; + expect(overlayRect[x]).to.be.closeTo(targetRect[x], 1); + } + + function assertTopAligned(overlayRect, targetRect) { + expect(overlayRect.top).to.be.closeTo(targetRect.top, 1); + } + + function assertBottomAligned(overlayRect, targetRect) { + expect(overlayRect.bottom).to.be.closeTo(targetRect.bottom, 1); + } + + function assertCenteredHorizontally(overlayRect, targetRect, dir) { + const coord = dir === 'rtl' ? 'right' : 'left'; + const offset = targetRect.width / 2 - overlayRect.width / 2; + expect(overlayRect[coord]).to.be.closeTo(targetRect[coord] + (dir === 'rtl' ? offset * -1 : offset), 1); + } + + function assertCenteredVertically(overlayRect, targetRect) { + const offset = targetRect.height / 2 - overlayRect.height / 2; + expect(overlayRect.top).to.be.closeTo(targetRect.top + offset, 1); + } + + describe('default', () => { + it('should not set position property value by default', () => { + expect(popover.position).to.be.undefined; + }); + + it('should set overlay position to bottom by default', () => { + expect(overlay.position).to.be.equal('bottom'); + }); + }); + + [ + { + position: 'top-start', + assertPlaced: assertPlacedAbove, + assertAligned: assertStartAligned, + }, + { + position: 'top', + assertPlaced: assertPlacedAbove, + assertAligned: assertCenteredHorizontally, + }, + { + position: 'top-end', + assertPlaced: assertPlacedAbove, + assertAligned: assertEndAligned, + }, + { + position: 'bottom-start', + assertPlaced: assertPlacedBelow, + assertAligned: assertStartAligned, + }, + { + position: 'bottom', + assertPlaced: assertPlacedBelow, + assertAligned: assertCenteredHorizontally, + }, + { + position: 'bottom-end', + assertPlaced: assertPlacedBelow, + assertAligned: assertEndAligned, + }, + { + position: 'start-top', + assertPlaced: assertPlacedBefore, + assertAligned: assertTopAligned, + }, + { + position: 'start', + assertPlaced: assertPlacedBefore, + assertAligned: assertCenteredVertically, + }, + { + position: 'start-bottom', + assertPlaced: assertPlacedBefore, + assertAligned: assertBottomAligned, + }, + { + position: 'end-top', + assertPlaced: assertPlacedAfter, + assertAligned: assertTopAligned, + }, + { + position: 'end', + assertPlaced: assertPlacedAfter, + assertAligned: assertCenteredVertically, + }, + { + position: 'end-bottom', + assertPlaced: assertPlacedAfter, + assertAligned: assertBottomAligned, + }, + ].forEach(({ position, assertPlaced, assertAligned }) => { + describe(position, () => { + ['ltr', 'rtl'].forEach((dir) => { + describe(`${position} ${dir}`, () => { + before(() => { + document.documentElement.setAttribute('dir', dir); + }); + + after(() => { + document.documentElement.removeAttribute('dir'); + }); + + it(`should position overlay against target ${position} with ${dir}`, async () => { + popover.position = position; + await nextUpdate(popover); + + target.click(); + await oneEvent(overlay, 'vaadin-overlay-open'); + const overlayRect = overlay.$.overlay.getBoundingClientRect(); + const targetRect = target.getBoundingClientRect(); + + assertPlaced(overlayRect, targetRect, dir); + assertAligned(overlayRect, targetRect, dir); + }); + }); + }); + }); + }); +});