u
This commit is contained in:
1 parent
78eb811ff7
commit
97fe2ff306
83 files changed
+10083
-3662
No files matched your search
@@ -14,13 +14,20 @@ import { expect, test, type Page } from '@playwright/test'
|
||||
* 这些都是布局结果,只能放 E2E(happy-dom 没有布局引擎)。
|
||||
*/
|
||||
|
||||
/** 插入表格(cols 为列数,默认 3 行 3 列) */
|
||||
async function insertTable(page: Page, cols?: number): Promise<void> {
|
||||
/**
|
||||
* 插入表格。
|
||||
*
|
||||
* 面板已从「行数 / 列数」两个数字输入框换成**网格选择器**(对齐 TinyMCE):
|
||||
* 移入 (rows, cols) 那个格子即高亮对应矩形,点击插入。所以这里改成点格子,
|
||||
* 不再有「插入」按钮需要按。
|
||||
*/
|
||||
async function insertTable(page: Page, cols = 3, rows = 3): Promise<void> {
|
||||
const editor = page.getByTestId('rich-text')
|
||||
await editor.scrollIntoViewIfNeeded()
|
||||
await editor.locator('button[aria-label="插入表格"]').click()
|
||||
if (cols) await page.locator('.g3-rich-text__table-input').nth(1).fill(String(cols))
|
||||
await page.getByRole('button', { name: '插入', exact: true }).click()
|
||||
const cell = page.locator(`.g3-rich-text__table-grid-cell[data-row="${rows}"][data-col="${cols}"]`)
|
||||
await cell.hover()
|
||||
await cell.click()
|
||||
await expect(editor.locator('table')).toHaveCount(1)
|
||||
await editor.locator('table').scrollIntoViewIfNeeded()
|
||||
}
|
||||
@@ -145,41 +152,64 @@ test.describe('RichText 表格', () => {
|
||||
}
|
||||
})
|
||||
|
||||
test('插入表格面板:label 与输入框上下排列且输入框不溢出', async ({ page }) => {
|
||||
test('插入表格面板:网格选择器高亮矩形并实时显示尺寸', async ({ page }) => {
|
||||
await page.goto('/')
|
||||
const editor = page.getByTestId('rich-text')
|
||||
await editor.scrollIntoViewIfNeeded()
|
||||
await editor.locator('button[aria-label="插入表格"]').click()
|
||||
|
||||
const fields = page.locator('.g3-rich-text__table-field')
|
||||
// 行数 / 列数 / 包含表头行 三个字段
|
||||
await expect(fields).toHaveCount(3)
|
||||
// 8 行 × 10 列的网格
|
||||
const cells = page.locator('.g3-rich-text__table-grid-cell')
|
||||
await expect(cells).toHaveCount(80)
|
||||
|
||||
// 只对含数字输入框的两个字段做上下排列 + 不溢出校验
|
||||
const geometry = await fields.evaluateAll((els) =>
|
||||
els.flatMap((el) => {
|
||||
const label = el.querySelector('.g3-rich-text__table-label')!.getBoundingClientRect()
|
||||
const input = el.querySelector('.g3-rich-text__table-input')
|
||||
if (!input) return []
|
||||
const rect = input.getBoundingClientRect()
|
||||
return [
|
||||
{
|
||||
labelBottom: label.bottom,
|
||||
inputTop: rect.top,
|
||||
inputWidth: rect.width,
|
||||
fieldWidth: el.getBoundingClientRect().width,
|
||||
},
|
||||
]
|
||||
}),
|
||||
// 尺寸提示:未悬停时显示默认 3 × 3
|
||||
const label = page.locator('.g3-rich-text__table-grid-label')
|
||||
await expect(label).toHaveText('3 × 3')
|
||||
|
||||
// 悬停 4 行 6 列 → 高亮 24 格,提示同步
|
||||
await page.locator('.g3-rich-text__table-grid-cell[data-row="4"][data-col="6"]').hover()
|
||||
await expect(label).toHaveText('4 × 6')
|
||||
await expect(page.locator('.g3-rich-text__table-grid-cell.is-table-grid-cell-active')).toHaveCount(
|
||||
24,
|
||||
)
|
||||
|
||||
expect(geometry).toHaveLength(2)
|
||||
for (const item of geometry) {
|
||||
// 输入框在 label 下方
|
||||
expect(item.inputTop).toBeGreaterThanOrEqual(item.labelBottom)
|
||||
// content-box + width:100% 曾让输入框比容器宽 18px(padding + border)
|
||||
expect(Math.round(item.inputWidth)).toBeLessThanOrEqual(Math.round(item.fieldWidth) + 1)
|
||||
}
|
||||
// 悬停更小的区域 → 高亮随之收缩(不是只增不减)
|
||||
await page.locator('.g3-rich-text__table-grid-cell[data-row="2"][data-col="2"]').hover()
|
||||
await expect(label).toHaveText('2 × 2')
|
||||
await expect(page.locator('.g3-rich-text__table-grid-cell.is-table-grid-cell-active')).toHaveCount(
|
||||
4,
|
||||
)
|
||||
})
|
||||
|
||||
test('插入表格面板:不溢出容器,含表头行勾选可用', async ({ page }) => {
|
||||
await page.goto('/')
|
||||
const editor = page.getByTestId('rich-text')
|
||||
await editor.scrollIntoViewIfNeeded()
|
||||
await editor.locator('button[aria-label="插入表格"]').click()
|
||||
|
||||
const form = page.locator('.g3-rich-text__table-form')
|
||||
const grid = page.locator('.g3-rich-text__table-grid')
|
||||
const formBox = (await form.boundingBox())!
|
||||
const gridBox = (await grid.boundingBox())!
|
||||
|
||||
// 网格必须落在面板内(早期手写样式曾让内容比容器宽 18px)
|
||||
expect(gridBox.width).toBeLessThanOrEqual(formBox.width + 1)
|
||||
expect(gridBox.x).toBeGreaterThanOrEqual(formBox.x - 1)
|
||||
|
||||
// 「包含表头行」默认选中;取消后插入的表首行应为 td 而非 th。
|
||||
// 注意:点击**包裹用的 label**,不能对内部 input 调 uncheck() ——
|
||||
// G3Checkbox 的原生 input 是 1px + opacity:0 + pointer-events:none(视觉由 span 承担),
|
||||
// Playwright 认为它不可见 / 不可交互,uncheck() 会直接超时。
|
||||
const toggleInput = page.locator('.g3-rich-text__table-checkbox input')
|
||||
const toggleLabel = page.locator('.g3-rich-text__table-header-toggle')
|
||||
await expect(toggleInput).toBeChecked()
|
||||
await toggleLabel.click()
|
||||
await expect(toggleInput).not.toBeChecked()
|
||||
|
||||
await page.locator('.g3-rich-text__table-grid-cell[data-row="2"][data-col="2"]').click()
|
||||
await expect(editor.locator('table tr')).toHaveCount(2)
|
||||
await expect(editor.locator('table')).toHaveCount(1)
|
||||
await expect(editor.locator('table tr:first-child th')).toHaveCount(0)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -371,7 +401,10 @@ test.describe('RichText 表格 · 操作浮层', () => {
|
||||
// 操作栏里已不再出现单元格对齐按钮(对齐统一走顶部工具条)
|
||||
await expect(menu.getByRole('button', { name: '单元格居中' })).toHaveCount(0)
|
||||
await expect(menu.getByRole('button', { name: '取消单元格对齐' })).toHaveCount(0)
|
||||
// 「表头」整组已移除:切换表头列 / 切换表头单元格都不再提供
|
||||
await expect(menu.getByRole('button', { name: '切换表头行' })).toHaveCount(0)
|
||||
await expect(menu.getByRole('button', { name: '切换表头列' })).toHaveCount(0)
|
||||
await expect(menu.getByRole('button', { name: '切换表头单元格' })).toHaveCount(0)
|
||||
|
||||
// 删除行 / 删除列的图标是自绘 SVG(不再是拆分行列的 lucide 图标)
|
||||
for (const name of ['删除行', '删除列']) {
|
||||
@@ -387,23 +420,6 @@ test.describe('RichText 表格 · 操作浮层', () => {
|
||||
await expect(editor.locator('table tr:first-child th')).toHaveCount(2)
|
||||
})
|
||||
|
||||
test('切换表头列 / 表头单元格', async ({ page }) => { await page.goto('/')
|
||||
await insertTable(page)
|
||||
const editor = page.getByTestId('rich-text')
|
||||
const menu = page.locator('.g3-rich-text-table-menu')
|
||||
|
||||
// 表头单元格:把普通单元格切换为 th
|
||||
await openMenuInCell(page, 1)
|
||||
await menu.getByRole('button', { name: '切换表头单元格' }).click()
|
||||
await expect(editor.locator('table tr').nth(1).locator('th')).toHaveCount(1)
|
||||
|
||||
// 表头列:整列切换为 th(第 2、3 行的首格都变 th;首行本就是表头行不受影响)
|
||||
await menu.getByRole('button', { name: '切换表头列' }).click()
|
||||
await expect(editor.locator('table tr').nth(1).locator('th')).toHaveCount(1)
|
||||
await expect(editor.locator('table tr').nth(2).locator('th')).toHaveCount(1)
|
||||
await expect(editor.locator('table tr').nth(1).locator('td')).toHaveCount(2)
|
||||
})
|
||||
|
||||
test('单元格内文字的对齐走顶部工具条', async ({ page }) => {
|
||||
await page.goto('/')
|
||||
await insertTable(page)
|
||||
@@ -418,28 +434,29 @@ test.describe('RichText 表格 · 操作浮层', () => {
|
||||
await expect(cell.locator('p')).toHaveAttribute('style', /text-align:\s*center/)
|
||||
})
|
||||
|
||||
test('插入面板行列数超界被夹回合法范围,且可关闭表头行', async ({ page }) => {
|
||||
/**
|
||||
* 「超界被夹回」这条用例已随数字输入框一起移除:网格选择器的可选范围由网格本身
|
||||
* 硬性限定(8 行 × 10 列),用户在结构上就填不出 0 行或 99 列 —— 也就没有「夹回」可言。
|
||||
* 这里改为断言这个上限本身,防止有人无意中把网格尺寸改大或改小。
|
||||
*/
|
||||
test('网格选择器的上限为 8 行 × 10 列,且只能选到边界内的格子', async ({ page }) => {
|
||||
await page.goto('/')
|
||||
const editor = page.getByTestId('rich-text')
|
||||
await editor.scrollIntoViewIfNeeded()
|
||||
await editor.locator('button[aria-label="插入表格"]').click()
|
||||
|
||||
// 输入非法值(0 行 / 99 列)
|
||||
await page.locator('.g3-rich-text__table-input').nth(0).fill('0')
|
||||
await page.locator('.g3-rich-text__table-input').nth(1).fill('99')
|
||||
await page.getByRole('button', { name: '插入', exact: true }).click()
|
||||
const cells = page.locator('.g3-rich-text__table-grid-cell')
|
||||
await expect(cells).toHaveCount(80)
|
||||
// 边界格子存在,越界的不存在
|
||||
await expect(page.locator('.g3-rich-text__table-grid-cell[data-row="8"][data-col="10"]')).toHaveCount(1)
|
||||
await expect(page.locator('.g3-rich-text__table-grid-cell[data-row="9"]')).toHaveCount(0)
|
||||
await expect(page.locator('.g3-rich-text__table-grid-cell[data-col="11"]')).toHaveCount(0)
|
||||
|
||||
// 选边界值:8 行 10 列能正常插入
|
||||
await page.locator('.g3-rich-text__table-grid-cell[data-row="8"][data-col="10"]').click()
|
||||
const table = editor.locator('table')
|
||||
await expect(table).toHaveCount(1)
|
||||
// 0 → 1 行,99 → 20 列
|
||||
await expect(table.locator('tr')).toHaveCount(1)
|
||||
await expect(table.locator('tr:first-child th')).toHaveCount(20)
|
||||
|
||||
// 关闭表头行:插入后首行是 td 而非 th
|
||||
await editor.locator('button[aria-label="插入表格"]').click()
|
||||
await page.locator('.g3-rich-text__table-checkbox').uncheck()
|
||||
await page.getByRole('button', { name: '插入', exact: true }).click()
|
||||
await expect(editor.locator('table')).toHaveCount(2)
|
||||
await expect(editor.locator('table').nth(1).locator('tr:first-child th')).toHaveCount(0)
|
||||
await expect(table.locator('tr')).toHaveCount(8)
|
||||
await expect(table.locator('tr:first-child th')).toHaveCount(10)
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user