172 lines
6.5 KiB
TypeScript
172 lines
6.5 KiB
TypeScript
import { expect, test } from '@playwright/test'
|
||
|
||
/**
|
||
* 数据展示类组件的交互回归。
|
||
*
|
||
* 注意:用 page.mouse.* 之前必须先 scrollIntoViewIfNeeded ——
|
||
* mouse 事件按视口坐标派发,元素在视口外时事件会落到别的元素上
|
||
* (表现为「拖拽/点击完全没反应」,很容易被误判成组件 bug)。
|
||
*/
|
||
|
||
test.describe('Tabs', () => {
|
||
test('面板懒渲染,切换后保留旧面板(表单状态不丢)', async ({ page }) => {
|
||
await page.goto('/')
|
||
const tabs = page.getByTestId('tabs')
|
||
|
||
await expect(tabs.locator('.g3-tabs__pane')).toHaveCount(1)
|
||
await tabs.locator('.g3-tabs__tab').nth(1).click()
|
||
await expect(tabs.locator('.g3-tabs__pane')).toHaveCount(2)
|
||
await expect(tabs.locator('.g3-tabs__pane').first()).toBeHidden()
|
||
})
|
||
|
||
test('禁用标签不可点击(回归:空值布尔属性被 Boolean("") 判成 false)', async ({ page }) => {
|
||
await page.goto('/')
|
||
const tabs = page.getByTestId('tabs')
|
||
const disabled = tabs.locator('.g3-tabs__tab').nth(2)
|
||
|
||
await expect(disabled).toBeDisabled()
|
||
await expect(disabled).toHaveAttribute('aria-disabled', 'true')
|
||
await expect(tabs.locator('.g3-tabs__pane')).toHaveCount(1)
|
||
})
|
||
})
|
||
|
||
test.describe('Tree', () => {
|
||
test('勾选父节点后子节点全选(父子联动)', async ({ page }) => {
|
||
await page.goto('/')
|
||
const tree = page.getByTestId('tree')
|
||
const checkboxes = tree.locator('.g3-tree-node__checkbox .g3-checkbox')
|
||
|
||
await expect(checkboxes).toHaveCount(6)
|
||
await checkboxes.first().click()
|
||
|
||
const checkedCount = await tree.locator('.g3-tree-node__checkbox .g3-checkbox.is-checked').count()
|
||
// 「前端」及其 3 个子孙(Vue / 组合式 API / React)
|
||
expect(checkedCount).toBe(4)
|
||
})
|
||
|
||
test('收起父节点后其子孙不再渲染(后端仍展开,所以剩下 3 个)', async ({ page }) => {
|
||
await page.goto('/')
|
||
const tree = page.getByTestId('tree')
|
||
|
||
await expect(tree.locator('.g3-tree-node')).toHaveCount(6)
|
||
await tree.locator('.g3-tree-node__switcher').first().click()
|
||
await expect(tree.locator('.g3-tree-node')).toHaveCount(3)
|
||
})
|
||
})
|
||
|
||
test.describe('Pagination', () => {
|
||
test('省略号点击跳 5 页', async ({ page }) => {
|
||
await page.goto('/')
|
||
const pagination = page.getByTestId('pagination')
|
||
|
||
await expect(pagination.locator('[aria-current="page"]')).toHaveText('1')
|
||
await pagination.locator('.g3-pagination__ellipsis').click()
|
||
await expect(pagination.locator('[aria-current="page"]')).toHaveText('6')
|
||
})
|
||
|
||
test('显示总数与跳页控件', async ({ page }) => {
|
||
await page.goto('/')
|
||
const pagination = page.getByTestId('pagination')
|
||
|
||
await expect(pagination.locator('.g3-pagination__total')).toContainText('126')
|
||
await expect(pagination.locator('.g3-pagination__jumper')).toBeVisible()
|
||
})
|
||
})
|
||
|
||
test.describe('Splitter', () => {
|
||
test('拖拽分隔条同时改变分隔条位置与两侧尺寸', async ({ page }) => {
|
||
await page.goto('/')
|
||
const splitter = page.getByTestId('splitter')
|
||
await splitter.scrollIntoViewIfNeeded()
|
||
|
||
const panels = splitter.locator('.g3-splitter-panel')
|
||
const bar = splitter.locator('.g3-splitter__bar')
|
||
|
||
// 探针:区分「pointerdown 没落到分隔条上」与「落上了但逻辑没生效」
|
||
await page.evaluate(() => {
|
||
;(window as unknown as { __barDown: number }).__barDown = 0
|
||
document.querySelector('.g3-splitter__bar')?.addEventListener('pointerdown', () => {
|
||
;(window as unknown as { __barDown: number }).__barDown += 1
|
||
})
|
||
})
|
||
|
||
const before = (await panels.first().boundingBox())!.width
|
||
const box = (await bar.boundingBox())!
|
||
const centerX = box.x + box.width / 2
|
||
const centerY = box.y + box.height / 2
|
||
|
||
await page.mouse.move(centerX, centerY)
|
||
await page.mouse.down()
|
||
await page.mouse.move(centerX + 40, centerY, { steps: 3 })
|
||
await page.mouse.move(centerX + 80, centerY, { steps: 3 })
|
||
await page.mouse.up()
|
||
await page.waitForTimeout(150)
|
||
|
||
const barDown = await page.evaluate(() => (window as unknown as { __barDown: number }).__barDown)
|
||
expect(barDown).toBe(1)
|
||
expect((await panels.first().boundingBox())!.width).toBeGreaterThan(before + 20)
|
||
})
|
||
|
||
test('分隔条可键盘调整(方向键 ±10px)', async ({ page }) => {
|
||
await page.goto('/')
|
||
const splitter = page.getByTestId('splitter')
|
||
await splitter.scrollIntoViewIfNeeded()
|
||
|
||
const panels = splitter.locator('.g3-splitter-panel')
|
||
const before = (await panels.first().boundingBox())!.width
|
||
|
||
await splitter.locator('.g3-splitter__bar').focus()
|
||
await page.keyboard.press('ArrowRight')
|
||
await page.keyboard.press('ArrowRight')
|
||
|
||
expect((await panels.first().boundingBox())!.width).toBeGreaterThan(before + 10)
|
||
})
|
||
})
|
||
|
||
test.describe('Scrollbar', () => {
|
||
test('点击轨道跳转滚动(clickScroll 默认开启)', async ({ page }) => {
|
||
await page.goto('/')
|
||
const scrollbar = page.getByTestId('scrollbar')
|
||
await scrollbar.scrollIntoViewIfNeeded()
|
||
|
||
const view = scrollbar.locator('.g3-scrollbar__view')
|
||
expect(await view.evaluate((el) => el.scrollTop)).toBe(0)
|
||
|
||
const track = (await scrollbar.locator('.g3-scrollbar__track-v').boundingBox())!
|
||
await page.mouse.click(track.x + track.width / 2, track.y + track.height * 0.7)
|
||
await page.waitForTimeout(100)
|
||
|
||
expect(await view.evaluate((el) => el.scrollTop)).toBeGreaterThan(0)
|
||
})
|
||
|
||
test('拖动滑块同步滚动位置', async ({ page }) => {
|
||
await page.goto('/')
|
||
const scrollbar = page.getByTestId('scrollbar')
|
||
await scrollbar.scrollIntoViewIfNeeded()
|
||
|
||
const view = scrollbar.locator('.g3-scrollbar__view')
|
||
const box = (await scrollbar.locator('.g3-scrollbar__thumb-v').boundingBox())!
|
||
const centerX = box.x + box.width / 2
|
||
const centerY = box.y + box.height / 2
|
||
|
||
await page.mouse.move(centerX, centerY)
|
||
await page.mouse.down()
|
||
await page.mouse.move(centerX, centerY + 60, { steps: 5 })
|
||
await page.mouse.up()
|
||
await page.waitForTimeout(100)
|
||
|
||
expect(await view.evaluate((el) => el.scrollTop)).toBeGreaterThan(0)
|
||
})
|
||
})
|
||
|
||
test.describe('Segmented', () => {
|
||
test('点击选项切换选中态(滑块跟随)', async ({ page }) => {
|
||
await page.goto('/')
|
||
const segmented = page.getByTestId('segmented')
|
||
|
||
await expect(segmented.locator('.g3-segmented__item.is-selected')).toHaveText('日')
|
||
await segmented.locator('.g3-segmented__item').filter({ hasText: '周' }).click()
|
||
await expect(segmented.locator('.g3-segmented__item.is-selected')).toHaveText('周')
|
||
})
|
||
})
|