import { expect, type Locator, type Page } from '@playwright/test' /** * Asserts that a dialog is a modal overlay rather than a block in the document flow. * * A missing Element Plus stylesheet is invisible to `toBeVisible()` and to the unit tests, but it * turns every dialog into content appended after the list it was opened from — which is exactly how * a reader reported it. These checks need a real browser with the real stylesheets. */ export async function expectModalOverlay(page: Page, dialog: Locator): Promise { await expect(dialog).toBeVisible() const layout = await dialog.evaluate(element => { const box = element.getBoundingClientRect() const overlay = element.closest('.el-overlay') return { overlay: overlay ? getComputedStyle(overlay).position : 'none', position: getComputedStyle(element).position, top: Math.round(box.top), left: Math.round(box.left), width: Math.round(box.width), viewportHeight: window.innerHeight, viewportWidth: window.innerWidth, } }) expect(layout.overlay, 'the dialog must render inside a fixed overlay').toBe('fixed') expect(layout.position, 'the dialog itself is positioned by the overlay').not.toBe('static') // It is laid out over the viewport, not below the page content that opened it. expect(layout.top, 'the dialog must start inside the viewport').toBeGreaterThanOrEqual(0) expect(layout.top, 'the dialog must not be pushed below the viewport').toBeLessThan(layout.viewportHeight) expect(layout.viewportWidth - (layout.left + layout.width), 'the dialog must fit horizontally').toBeGreaterThanOrEqual(-2) } /** Asserts that a message box is a modal overlay as well. */ export async function expectMessageBoxOverlay(page: Page): Promise { const box = page.locator('.el-message-box') await expect(box).toBeVisible() const overlay = await box.evaluate(element => { const wrapper = element.closest('.el-overlay') return wrapper ? getComputedStyle(wrapper).position : 'none' }) expect(overlay, 'the confirmation must render inside a fixed overlay').toBe('fixed') }