- main.ts 补上 dialog 与 message-box 的样式导入:自 #10 起 ElDialog/ElMessageBox 一直 缺少样式,退化成列表后面的普通块(用户报告「编辑区显示在章节列表下面」) - 新增 e2e/overlay.ts:expectModalOverlay / expectMessageBoxOverlay 断言弹窗位于 .el-overlay(position: fixed)、在视口内且横向不溢出 - attachments.spec.ts(章节编辑对话框、插图弹窗)与 edit.spec.ts(书名对话框、删除确认) 都改用该断言,堵住「只看可见性、不看是否浮层」的验证盲区 - 真实链路确认:对话框遮罩为 rgba(0,0,0,0.5)、居中于视口;确认框同样为固定浮层 - 文档:Local-Development 记录缺陷、根因、修复与新增回归断言
43 lines
2.1 KiB
TypeScript
43 lines
2.1 KiB
TypeScript
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<void> {
|
|
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<void> {
|
|
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')
|
|
}
|