test(tree-menu): [tree-menu] Optimizing e2e test cases for TreeMenu components (#1031)

This commit is contained in:
MomoPoppy 2023-12-05 17:11:38 +08:00 committed by GitHub
parent d2cd75a587
commit 884185001a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 354 additions and 172 deletions

View File

@ -4,7 +4,9 @@ test('手风琴', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#accordion')
const treeMenu = page.locator('#preview .tiny-tree-menu')
const wrap = page.locator('#accordion')
const treeMenu = wrap.locator('.tiny-tree-menu')
await treeMenu.getByTitle('指南').click()
await expect(treeMenu.getByTitle('引入组件')).toBeVisible()
await expect(treeMenu.getByTitle('构建部署')).toBeVisible()

View File

@ -4,7 +4,9 @@ test('基本使用,无数据场景', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#basic-usage')
const treeMenu = page.locator('#preview .tiny-tree-menu')
await expect(treeMenu.getByPlaceholder('请输入内容进行筛选').locator('input')).toBeVisible()
const wrap = page.locator('#basic-usage')
const treeMenu = wrap.locator('.tiny-tree-menu')
await expect(treeMenu.locator('.tiny-input__inner')).toBeVisible()
await expect(treeMenu).toContainText('暂无数据')
})

View File

@ -4,9 +4,13 @@
<tiny-button @click="setCurrentKey" title="点击设置当前节点">setCurrentKey</tiny-button>
<p>场景2通过 setCurrentNode(node:ITreeNode) 设置当前节点</p>
<tiny-button @click="setCurrentNode" title="点击设置当前节点">setCurrentNode</tiny-button>
<p>场景3通过 getCurrentKey() 获取当前节点的 key {{ currentKey }}</p>
<p>
场景3通过 getCurrentKey() 获取当前节点的 key <span class="current-node-key">{{ currentKey }}</span>
</p>
<tiny-button @click="getCurrentKey" title="点击获取当前节点的 key">getCurrentKey</tiny-button>
<p>场景4通过 getCurrentNode() 获取当前节点的数据为{{ currentNode }}</p>
<p>
场景4通过 getCurrentNode() 获取当前节点的数据为<span class="current-node">{{ currentNode }}</span>
</p>
<tiny-button @click="getCurrentNode" title="点击获取当前节点数据">getCurrentNode</tiny-button>
<tiny-tree-menu
@ -20,7 +24,7 @@
<script setup>
import { ref, reactive } from 'vue'
import { TreeMenu as TinyTreeMenu, Button as TinyButton, Row as TinyRow, Col as TinyCol } from '@opentiny/vue'
import { TreeMenu as TinyTreeMenu, Button as TinyButton } from '@opentiny/vue'
const treeMenu = ref(null)
const treeData = reactive([

View File

@ -4,22 +4,29 @@ test('设置当前节点', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#current-node')
const treeMenu = page.locator('#preview .tiny-tree-menu')
const wrap = page.locator('#current-node')
const treeMenu = wrap.locator('.tiny-tree-menu')
const treeNode = treeMenu.locator('.tiny-tree-node__wrapper > .tiny-tree-node')
const button = wrap.locator('.tiny-button')
const currentCls = /is-current/
// 通过key设置当前节点
await page.getByRole('button', { name: '设置当前选中的节点的 key' }).click()
await expect(treeMenu.locator('.tiny-tree-node').filter({ hasText: '按需引入' }).nth(2)).toHaveClass(currentCls)
await page.getByRole('button', { name: '获取当前被选中节点的 key' }).click()
await expect(page.locator('#current-node-key')).toHaveText('20101')
await page.getByRole('button', { name: '获取当前选中的节点' }).click()
await expect(page.locator('#current-node')).toHaveText('{ "id": 20101, "label": "按需引入" }')
await button.nth(0).click()
await expect(treeNode.filter({ hasText: /^按需引入$/ })).toHaveClass(currentCls)
// 获取当前被选中节点的 key
await button.nth(2).click()
await expect(wrap.locator('.current-node-key')).toHaveText('20101')
// 获取当前节点的数据
await button.nth(3).click()
await expect(wrap.locator('.current-node')).toHaveText('{ "id": 20101, "label": "按需引入" }')
// 通过node设置当前节点
await page.getByRole('button', { name: '设置当前选中的节点' }).nth(1).click()
await expect(treeMenu.locator('.tiny-tree-node').filter({ hasText: '规范' })).toHaveClass(currentCls)
await page.getByRole('button', { name: '获取当前被选中节点的 key' }).click()
await expect(page.locator('#current-node-key')).toHaveText('500')
await page.getByRole('button', { name: '获取当前选中的节点' }).click()
await expect(page.locator('#current-node')).toHaveText('{ "id": 500, "label": "规范" }')
await button.nth(1).click()
await expect(treeNode.filter({ hasText: /^规范$/ })).toHaveClass(currentCls)
// 获取当前被选中节点的 key
await button.nth(2).click()
await expect(wrap.locator('.current-node-key')).toHaveText('500')
// 获取当前节点的数据
await button.nth(3).click()
await expect(wrap.locator('.current-node')).toHaveText('{ "id": 500, "label": "规范" }')
})

View File

@ -4,9 +4,13 @@
<tiny-button @click="setCurrentKey" title="点击设置当前节点">setCurrentKey</tiny-button>
<p>场景2通过 setCurrentNode(node:ITreeNode) 设置当前节点</p>
<tiny-button @click="setCurrentNode" title="点击设置当前节点">setCurrentNode</tiny-button>
<p>场景3通过 getCurrentKey() 获取当前节点的 key {{ currentKey }}</p>
<p>
场景3通过 getCurrentKey() 获取当前节点的 key <span class="current-node-key">{{ currentKey }}</span>
</p>
<tiny-button @click="getCurrentKey" title="点击获取当前节点的 key">getCurrentKey</tiny-button>
<p>场景4通过 getCurrentNode() 获取当前节点的数据为{{ currentNode }}</p>
<p>
场景4通过 getCurrentNode() 获取当前节点的数据为<span class="current-node">{{ currentNode }}</span>
</p>
<tiny-button @click="getCurrentNode" title="点击获取当前节点数据">getCurrentNode</tiny-button>
<tiny-tree-menu
@ -19,14 +23,12 @@
</template>
<script>
import { TreeMenu, Button, Row, Col } from '@opentiny/vue'
import { TreeMenu, Button } from '@opentiny/vue'
export default {
components: {
TinyTreeMenu: TreeMenu,
TinyButton: Button,
TinyRow: Row,
TinyCol: Col
TinyButton: Button
},
data() {
return {

View File

@ -2,8 +2,18 @@ import { test, expect } from '@playwright/test'
test('自定义搜索图标', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#search-icon')
await page.goto('tree-menu#custom-icon')
const wrap = page.locator('#custom-icon')
const treeMenu = wrap.locator('.tiny-tree-menu')
const treeMenu = page.locator('#preview .tiny-tree-menu')
await expect(treeMenu.locator('.tiny-input__prefix .tiny-input__icon')).toBeVisible()
})
test('自定义前置图标', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#custom-icon')
const wrap = page.locator('#custom-icon')
const treeMenu = wrap.locator('.tiny-tree-menu')
})

View File

@ -2,34 +2,46 @@ import { test, expect } from '@playwright/test'
test('静态数据', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('http://localhost:7130/pc/tree-menu/data-resource')
await page.goto('tree-menu#data-resource')
await page.getByTitle('指南', { exact: true }).click()
await expect(page.getByTitle('后端适配器')).toBeVisible()
await page.getByTitle('后端适配器').click()
await expect(page.getByRole('treeitem', { name: '后端适配器' }).first()).toHaveClass(/is-current/)
await page.getByTitle('指南', { exact: true }).click()
await expect(page.getByTitle('后端适配器')).not.toBeVisible()
const wrap = page.locator('#data-resource')
const treeMenu = wrap.locator('.tiny-tree-menu').nth(0)
const treeNode = treeMenu.locator('.tiny-tree-node__wrapper > .tiny-tree-node')
const treeNodeContent = treeNode.locator('> .tiny-tree-node__content')
await expect(treeNode.filter({ hasText: /^后端适配器$/ })).toBeHidden()
await treeNodeContent.filter({ hasText: /^指南$/ }).click()
await expect(treeNode.filter({ hasText: /^后端适配器$/ })).toBeVisible()
await treeNode.filter({ hasText: /^后端适配器$/ }).click()
await expect(treeNode.filter({ hasText: /^后端适配器$/ })).toHaveClass(/is-current/)
await treeNodeContent.filter({ hasText: /^指南$/ }).click()
await expect(treeNode.filter({ hasText: /^后端适配器$/ })).toBeHidden()
// 过滤功能
await page.locator('#preview').getByPlaceholder('请输入内容进行筛选').locator('input').fill('添加标签页')
await treeMenu.locator('.tiny-input__inner').fill('添加标签页')
await expect(page.getByTitle('添加标签页')).toBeVisible()
await expect(page.getByTitle('指南', { exact: true })).not.toBeVisible()
await page.locator('#preview').getByPlaceholder('请输入内容进行筛选').locator('input').clear()
await expect(page.getByTitle('指南', { exact: true })).toBeVisible()
await expect(treeNodeContent.filter({ hasText: /^指南$/ })).toBeHidden()
await treeMenu.locator('.tiny-input__inner').clear()
await expect(treeNodeContent.filter({ hasText: /^指南$/ })).toBeVisible()
})
test('服务端数据', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('http://localhost:7130/pc/tree-menu/get-menu-data-sync')
await page.goto('tree-menu#data-resource')
await page.getByTitle('指南', { exact: true }).click()
await expect(page.getByTitle('引入组件')).toBeVisible()
await expect(page.getByRole('treeitem', { name: '按需引入' })).not.toBeVisible()
await page.getByTitle('引入组件').click()
await expect(page.getByRole('treeitem', { name: '按需引入' }).first()).toBeVisible()
await page.getByTitle('指南', { exact: true }).click()
await expect(page.getByTitle('按需引入')).not.toBeVisible()
await expect(page.getByTitle('组件', { exact: true })).toBeVisible()
await expect(page.getByTitle('规范')).toBeVisible()
const wrap = page.locator('#data-resource')
const treeMenu = wrap.locator('.tiny-tree-menu').nth(1)
const treeNode = treeMenu.locator('.tiny-tree-node__wrapper > .tiny-tree-node')
const treeNodeContent = treeNode.locator('> .tiny-tree-node__content')
await expect(treeNodeContent.filter({ hasText: /^引入组件$/ })).toBeHidden()
await treeNodeContent.filter({ hasText: /^指南$/ }).click()
await expect(treeNodeContent.filter({ hasText: /^引入组件$/ })).toBeVisible()
await expect(treeNode.filter({ hasText: /^按需引入$/ })).toBeHidden()
await treeNodeContent.filter({ hasText: /^引入组件$/ }).click()
await expect(treeNode.filter({ hasText: /^按需引入$/ })).toBeVisible()
await treeNodeContent.filter({ hasText: /^指南$/ }).click()
await expect(treeNode.filter({ hasText: /^按需引入$/ })).toBeHidden()
await expect(treeNodeContent.filter({ hasText: /^组件$/ })).toBeVisible()
await expect(treeNode.filter({ hasText: /^规范$/ })).toBeVisible()
})

View File

@ -4,12 +4,29 @@ test('默认展开全部菜单', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#default-expand-all')
const treeMenu = page.locator('#preview .tiny-tree-menu')
await expect(treeMenu.getByTitle('首页')).toBeVisible()
await expect(treeMenu.getByTitle('组件').first()).toBeVisible()
await expect(treeMenu.getByTitle('引入组件')).toBeVisible()
await expect(treeMenu.getByRole('link', { name: 'Button 按钮' })).toBeVisible()
await expect(treeMenu.getByTitle('教程')).toBeVisible()
await expect(treeMenu.getByTitle('页面布局')).toBeVisible()
await expect(treeMenu.getByTitle('列表属性配置')).toBeVisible()
const wrap = page.locator('#default-expand-all')
const treeMenu = wrap.locator('.tiny-tree-menu')
const treeNode = treeMenu.locator('.tiny-tree-node__wrapper > .tiny-tree-node')
const treeNodeContent = treeNode.locator('> .tiny-tree-node__content')
await expect(treeNode.filter({ hasText: /^指南/ })).toHaveClass(/is-expanded/)
await expect(treeNode.filter({ hasText: /^引入组件/ })).toHaveClass(/is-expanded/)
await expect(treeNode.filter({ hasText: /^组件/ })).toHaveClass(/is-expanded/)
await expect(treeNode.filter({ hasText: /^表单组件/ })).toHaveClass(/is-expanded/)
await expect(treeNode.filter({ hasText: /^教程/ })).toHaveClass(/is-expanded/)
await expect(treeNode.filter({ hasText: /^页面布局/ })).toHaveClass(/is-expanded/)
await expect(treeNode.filter({ hasText: /^查询功能/ })).toHaveClass(/is-expanded/)
await expect(treeNode.filter({ hasText: /^新增功能/ })).toHaveClass(/is-expanded/)
await expect(treeNode.filter({ hasText: /^编辑功能/ })).toHaveClass(/is-expanded/)
await expect(treeNodeContent.filter({ hasText: /^首页$/ })).toBeVisible()
await expect(treeNodeContent.filter({ hasText: /^按需引入$/ })).toBeVisible()
await expect(treeNodeContent.filter({ hasText: /^引入组件$/ })).toBeVisible()
await expect(treeNodeContent.filter({ hasText: /^Button 按钮$/ })).toBeVisible()
await expect(treeNodeContent.filter({ hasText: /^业务组件$/ })).toBeVisible()
await expect(treeNodeContent.filter({ hasText: /^添加标签页$/ })).toBeVisible()
await expect(treeNodeContent.filter({ hasText: /^添加查询页面$/ })).toBeVisible()
await expect(treeNodeContent.filter({ hasText: /^表单新增功能$/ })).toBeVisible()
await expect(treeNodeContent.filter({ hasText: /^开启编辑功能$/ })).toBeVisible()
await expect(treeNodeContent.filter({ hasText: /^更新日志$/ })).toBeVisible()
})

View File

@ -4,9 +4,11 @@ test('默认展开某节点', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#default-expanded-keys-highlight')
const treeMenu = page.locator('#preview .tiny-tree-menu')
const node = treeMenu.locator('.tiny-tree-node').filter({ hasText: '按需引入' }).nth(2)
const wrap = page.locator('#default-expanded-keys-highlight')
const treeMenu = wrap.locator('.tiny-tree-menu')
const treeNode = treeMenu.locator('.tiny-tree-node__wrapper > .tiny-tree-node')
await page.getByRole('button', { name: 'highlight' }).click()
await expect(node).toHaveClass(/is-current/)
await expect(treeNode.filter({ hasText: /^Button 按钮$/ })).toHaveClass(/is-current/)
await wrap.getByRole('button', { name: '设置展开并高亮' }).click()
await expect(treeNode.filter({ hasText: /^页面布局/ })).toHaveClass(/is-current/)
})

View File

@ -4,15 +4,19 @@ test('默认展开某节点', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#default-expanded-keys')
const treeMenu = page.locator('#preview .tiny-tree-menu')
const wrap = page.locator('#default-expanded-keys')
const treeMenu = wrap.locator('.tiny-tree-menu')
const treeNode = treeMenu.locator('.tiny-tree-node__wrapper > .tiny-tree-node')
const treeNodeContent = treeNode.locator('> .tiny-tree-node__content')
// 默认展开节点
await expect(treeMenu.getByTitle('数据组件')).toBeVisible()
await expect(treeNodeContent.filter({ hasText: /^数据组件$/ })).toBeVisible()
// 默认展开节点的祖先节点展开
await expect(treeMenu.getByTitle('组件', { exact: true }).first()).toBeVisible()
await expect(treeNodeContent.filter({ hasText: /^组件/ })).toBeVisible()
// 默认展开节点兄弟节点展开
await expect(treeMenu.getByTitle('导航组件')).toBeVisible()
await expect(treeNodeContent.filter({ hasText: /^导航组件$/ })).toBeVisible()
// 默认展开节点的下一层次节点不展开
await expect(treeMenu.getByTitle('Datepicker 日期')).not.toBeVisible()
await expect(treeNodeContent.filter({ hasText: /^Datepicker 日期$/ })).toBeVisible()
// 非默认展开节点子的祖先节点的子节点不展开
await expect(treeMenu.getByTitle('页面布局')).not.toBeVisible()
await expect(treeNodeContent.filter({ hasText: /^页面布局/ })).toBeHidden()
})

View File

@ -2,10 +2,15 @@ import { test, expect } from '@playwright/test'
test('拖动菜单', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#can-draggable')
await page.goto('tree-menu#draggable')
const treeMenu = page.locator('#preview .tiny-tree-menu')
const node = treeMenu.getByTitle('首页')
const wrap = page.locator('#draggable')
const treeMenu = wrap.locator('.tiny-tree-menu')
const treeNodeWrapper = treeMenu.locator('.tiny-tree-node__wrapper')
const treeNode = treeMenu.locator('.tiny-tree-node__wrapper > .tiny-tree-node')
const node = treeNodeWrapper.filter({ hasText: /^首页$/ })
await page.waitForTimeout(2000)
// 同一层次节点拖拽
const { x: x0, y: y0 } = await node.boundingBox()
@ -15,6 +20,8 @@ test('拖动菜单', async ({ page }) => {
await page.mouse.move(x0, y0 + 80)
await page.mouse.up()
await node.hover()
// 判断位置是否变化
const { x: x1, y: y1 } = await node.boundingBox()
expect(y1).toBeGreaterThan(y0)
@ -26,7 +33,7 @@ test('拖动菜单', async ({ page }) => {
await page.mouse.up()
// 判断是否放到兄弟节点内
await treeMenu.getByTitle('指南').click()
await treeNode.filter({ hasText: /^指南/ }).click()
await expect(treeMenu.getByRole('treeitem', { name: '指南' }).getByRole('treeitem', { name: '首页' })).toBeVisible()
// 拖拽到父节点同级

View File

@ -4,6 +4,6 @@ test('自定义空数据文本', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#empty-text')
const treeMenu = page.locator('#preview .tiny-tree-menu')
const treeMenu = page.locator('#empty-text .tiny-tree-menu')
await expect(treeMenu.locator('.tiny-tree__empty-text')).toHaveText('空数据')
})

View File

@ -4,9 +4,12 @@ test('拖拽菜单回调事件', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#event-allow-draggable')
const treeMenu = page.locator('#preview .tiny-tree-menu')
const wrap = page.locator('#event-allow-draggable')
const treeMenu = wrap.locator('.tiny-tree-menu')
const node = treeMenu.getByTitle('首页')
await page.waitForTimeout(2000)
const { x: x0, y: y0 } = await node.boundingBox()
await page.mouse.move(x0, y0)
await page.mouse.down()

View File

@ -2,61 +2,89 @@ import { test, expect } from '@playwright/test'
test('节点被点击事件', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#event-node-click')
await page.goto('tree-menu#events')
const treeMenu = page.locator('#preview .tiny-tree-menu')
await treeMenu.getByTitle('首页', { exact: true }).click()
await expect(page.locator('div').filter({ hasText: '节点-首页被点击了' }).nth(1)).toBeVisible()
const wrap = page.locator('#events')
const treeMenu = wrap.locator('.tiny-tree-menu')
const treeNode = treeMenu.locator('.tiny-tree-node__wrapper > .tiny-tree-node')
const modal = page.locator('.tiny-modal')
await treeNode.getByTitle('首页', { exact: true }).click()
await expect(modal.filter({ hasText: '节点-首页被点击了' })).toBeVisible()
await treeMenu.getByTitle('指南', { exact: true }).click()
await expect(page.locator('div').filter({ hasText: '节点-指南被点击了' }).nth(1)).toBeVisible()
await expect(modal.filter({ hasText: '节点-指南被点击了' })).toBeVisible()
await treeMenu.getByTitle('后端适配器', { exact: true }).click()
await expect(page.locator('div').filter({ hasText: '节点-后端适配器被点击了' }).nth(1)).toBeVisible()
await expect(modal.filter({ hasText: '节点-后端适配器被点击了' })).toBeVisible()
})
test('当前选中节点变化事件', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#event-current-change')
await page.goto('tree-menu#events')
const treeMenu = page.locator('#preview .tiny-tree-menu')
await treeMenu.getByTitle('指南', { exact: true }).click()
await expect(page.locator('div').filter({ hasText: '选中节点变化为:指南' }).nth(1)).toBeVisible()
await treeMenu.getByTitle('后端适配器', { exact: true }).click()
await expect(page.locator('div').filter({ hasText: '选中节点变化为:后端适配器' }).nth(1)).toBeVisible()
const wrap = page.locator('#events')
const treeMenu = wrap.locator('.tiny-tree-menu')
const treeNode = treeMenu.locator('.tiny-tree-node__wrapper > .tiny-tree-node')
const treeNodeContent = treeNode.locator('> .tiny-tree-node__content')
const modal = page.locator('.tiny-modal')
await treeNodeContent
.filter({ hasText: /^指南$/ })
.locator('.tiny-checkbox')
.click()
await expect(modal.filter({ hasText: '选中节点变化为:指南' })).toBeVisible()
await treeNodeContent.filter({ hasText: /^指南$/ }).click()
await treeNodeContent
.filter({ hasText: /^后端适配器$/ })
.locator('.tiny-checkbox')
.click()
await expect(modal.filter({ hasText: '选中节点变化为:后端适配器' })).toBeVisible()
})
test('节点被折叠时触发的事件', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#event-node-collapse')
await page.goto('tree-menu#events')
const treeMenu = page.locator('#preview .tiny-tree-menu')
await treeMenu.getByTitle('指南', { exact: true }).click()
await treeMenu.getByTitle('指南', { exact: true }).click()
await expect(page.locator('.tiny-modal').filter({ hasText: '节点-指南被关闭了' })).toBeVisible()
const wrap = page.locator('#events')
const treeMenu = wrap.locator('.tiny-tree-menu')
const treeNode = treeMenu.locator('.tiny-tree-node__wrapper > .tiny-tree-node')
const treeNodeContent = treeNode.locator('> .tiny-tree-node__content')
const modal = page.locator('.tiny-modal')
await treeNodeContent.filter({ hasText: /^指南$/ }).click()
await treeNodeContent.filter({ hasText: /^指南$/ }).click()
await expect(modal.filter({ hasText: '节点-指南被关闭了' })).toBeVisible()
})
test('节点被展开时触发的事件', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#event-node-expand')
await page.goto('tree-menu#events')
const treeMenu = page.locator('#preview .tiny-tree-menu')
await treeMenu.getByTitle('指南', { exact: true }).click()
await expect(page.locator('.tiny-modal').filter({ hasText: '节点-指南被打开了' })).toBeVisible()
const wrap = page.locator('#events')
const treeMenu = wrap.locator('.tiny-tree-menu')
const treeNode = treeMenu.locator('.tiny-tree-node__wrapper > .tiny-tree-node')
const treeNodeContent = treeNode.locator('> .tiny-tree-node__content')
const modal = page.locator('.tiny-modal')
await treeNodeContent.filter({ hasText: /^指南$/ }).click()
await expect(modal.filter({ hasText: '节点-指南被打开了' })).toBeVisible()
})
test('节点选中状态发生变化时的回调', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#event-check-change')
await page.goto('tree-menu#events')
const checkBox = page.getByRole('treeitem', { name: '首页' }).locator('span').nth(2)
const wrap = page.locator('#events')
const treeMenu = wrap.locator('.tiny-tree-menu')
const treeNode = treeMenu.locator('.tiny-tree-node__wrapper > .tiny-tree-node')
const treeNodeContent = treeNode.locator('> .tiny-tree-node__content')
const modal = page.locator('.tiny-modal')
const checkBox = treeNodeContent.filter({ hasText: /^首页$/ }).locator('.tiny-checkbox')
// 选中节点
await checkBox.click()
await expect(page.locator('.tiny-modal').filter({ hasText: '节点-首页被选中了' })).toBeVisible()
await expect(modal.filter({ hasText: '节点-首页被选中了' })).toBeVisible()
// 取消选中
await checkBox.click()
await expect(page.locator('.tiny-modal').filter({ hasText: '节点-首页被取消了' })).toBeVisible()
await expect(modal.filter({ hasText: '节点-首页被取消了' })).toBeVisible()
})

View File

@ -4,7 +4,36 @@ test('点击文字展开菜单', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#expand-on-click-node')
const treeMenu = page.locator('#preview .tiny-tree-menu')
await treeMenu.getByTitle('指南', { exact: true }).click()
await expect(treeMenu.getByTitle('后端适配器')).toBeVisible()
const wrap = page.locator('#expand-on-click-node')
const treeMenu = wrap.locator('.tiny-tree-menu').nth(0)
const treeNode = treeMenu.locator('.tiny-tree-node__wrapper > .tiny-tree-node')
const treeNodeContent = treeNode.locator('> .tiny-tree-node__content')
await treeNodeContent.filter({ hasText: /^指南$/ }).click()
await expect(treeNodeContent.filter({ hasText: /^后端适配器$/ })).toBeVisible()
})
test('点击展开按钮才可展开菜单', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#expand-on-click-node')
const wrap = page.locator('#expand-on-click-node')
const treeMenu = wrap.locator('.tiny-tree-menu').nth(1)
const treeNode = treeMenu.locator('.tiny-tree-node__wrapper > .tiny-tree-node')
const treeNodeContent = treeNode.locator('> .tiny-tree-node__content')
// 点击非展开按钮位置,只高亮,不展开
await treeNodeContent.filter({ hasText: /^指南$/ }).click()
await expect(treeNodeContent.filter({ hasText: /^后端适配器$/ })).toBeHidden()
await expect(treeNode.filter({ hasText: /^指南/ })).toHaveClass(/is-current/)
await expect(treeNode.filter({ hasText: /^指南/ })).not.toHaveClass(/is-expanded/)
// 点击展开按钮,才展开
await treeNodeContent
.filter({ hasText: /^指南$/ })
.locator('.tree-node-icon')
.click()
await expect(treeNodeContent.filter({ hasText: /^后端适配器$/ })).toBeVisible()
await expect(treeNode.filter({ hasText: /^指南/ })).toHaveClass(/is-expanded/)
await expect(treeNode.filter({ hasText: /^指南/ })).toHaveClass(/is-current/)
})

View File

@ -1,12 +1,15 @@
import { test, expect } from '@playwright/test'
test('搜索规则配置 精确匹配', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#filter-node-method')
const treeMenu = page.locator('#preview .tiny-tree-menu')
await treeMenu.getByPlaceholder('请输入内容进行筛选').locator('input').fill('组件')
await expect(treeMenu.getByRole('group').getByTitle('组件', { exact: true })).toBeVisible()
await expect(treeMenu.getByTitle('引入组件')).not.toBeVisible()
await expect(treeMenu.getByTitle('表单组件')).not.toBeVisible()
const wrap = page.locator('#filter-node-method')
const treeMenu = wrap.locator('.tiny-tree-menu')
const treeNode = treeMenu.locator('.tiny-tree-node__wrapper > .tiny-tree-node')
const treeNodeContent = treeNode.locator('> .tiny-tree-node__content')
await treeMenu.locator('.tiny-input__inner').fill('组件')
await expect(treeNodeContent.filter({ hasText: /^组件$/ })).toBeVisible()
await expect(treeNodeContent.filter({ hasText: /^引入组件$/ })).not.toBeVisible()
await expect(treeNodeContent.filter({ hasText: /^表单组件$/ })).not.toBeVisible()
})

View File

@ -37,10 +37,6 @@ export default {
id: 300,
label: '组件',
children: [
{
id: 300,
label: '组件'
},
{
id: 301,
label: '表单组件',

View File

@ -2,10 +2,15 @@ import { test, expect } from '@playwright/test'
test('节点水平缩进', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#tree-menu-indent')
await page.goto('tree-menu#indent')
const wrap = page.locator('#indent')
const treeMenu = wrap.locator('.tiny-tree-menu')
const treeNode = treeMenu.locator('.tiny-tree-node__wrapper > .tiny-tree-node')
const treeNodeContent = treeNode.locator('> .tiny-tree-node__content')
const node = treeNodeContent.filter({ hasText: /^指南$/ })
const childNode = treeNodeContent.filter({ hasText: /^引入组件$/ })
const node = page.locator('#preview .tiny-tree-menu').getByText('指南', { exact: true })
const childNode = page.locator('#preview .tiny-tree-menu').getByRole('treeitem', { name: '引入组件' }).first()
await node.click()
await expect(childNode.locator('.tiny-tree-node__content')).toHaveCSS('padding-left', '50px')
await expect(childNode.locator('.tiny-tree-node__content-indent')).toHaveCSS('width', '50px')
})

View File

@ -4,10 +4,14 @@ test('懒加载', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#lazy-load')
const treeMenu = page.locator('#preview .tiny-tree-menu')
await treeMenu.getByTitle('表单组件', { exact: true }).click()
await expect(treeMenu.getByTitle('表单组件1')).not.toBeVisible()
const wrap = page.locator('#lazy-load')
const treeMenu = wrap.locator('.tiny-tree-menu')
const treeNode = treeMenu.locator('.tiny-tree-node__wrapper > .tiny-tree-node')
const treeNodeContent = treeNode.locator('> .tiny-tree-node__content')
await treeNodeContent.filter({ hasText: /^表单组件$/ }).click()
await expect(treeNodeContent.filter({ hasText: /^表单组件1$/ })).not.toBeVisible()
// 等到异步加载完成
await page.waitForTimeout(600)
await expect(treeMenu.getByTitle('表单组件1')).toBeVisible()
await expect(treeNodeContent.filter({ hasText: /^表单组件1$/ })).toBeVisible()
})

View File

@ -4,8 +4,8 @@ test('菜单可折叠', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#menu-collapsible')
const preview = page.locator('#preview')
const treeMenu = preview.locator('.tiny-tree-menu')
const wrap = page.locator('#menu-collapsible')
const treeMenu = wrap.locator('.tiny-tree-menu')
const toggleBtn = treeMenu.locator('.tiny-tree-menu__toggle-button')
await expect(toggleBtn).toBeVisible()
@ -13,4 +13,7 @@ test('菜单可折叠', async ({ page }) => {
await toggleBtn.click()
await expect(treeMenu).toHaveClass(/is-collapsed/)
await expect(treeMenu).toHaveCSS('width', '0px')
await toggleBtn.click()
await expect(treeMenu).not.toHaveClass(/is-collapsed/)
await expect(treeMenu).toHaveCSS('width', '270px')
})

View File

@ -4,65 +4,103 @@ test('节点可勾选', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#show-checkbox')
const treeMenu = page.locator('#preview .tiny-tree-menu')
const node = treeMenu.getByRole('treeitem', { name: '首页' })
const wrap = page.locator('#show-checkbox')
const treeMenu = wrap.locator('.tiny-tree-menu').nth(0)
const treeNode = treeMenu.locator('.tiny-tree-node__wrapper > .tiny-tree-node')
const treeNodeContent = treeNode.locator('> .tiny-tree-node__content')
const node = treeNodeContent.filter({ hasText: /^首页$/ })
const selectedClass = /is-checked/
await expect(node.locator('.tiny-tree-node__content .tiny-checkbox')).toBeVisible()
await page.getByRole('treeitem', { name: '首页' }).locator('.tiny-checkbox').click()
await expect(node).toHaveClass(/is-current/)
await expect(node.locator('.tiny-tree-node__content .tiny-checkbox')).toHaveClass(selectedClass)
// 可勾选节点显示复选框且默认选中
await expect(node.locator('.tiny-checkbox')).toBeVisible()
await expect(treeNode.filter({ hasText: /^首页$/ })).toHaveClass(selectedClass)
await expect(node.locator('.tiny-checkbox')).toHaveClass(selectedClass)
await node.click()
await expect(treeNode.filter({ hasText: /^首页$/ })).toHaveClass(/is-current/)
// 父级选中, 子孙节点同时都选中
await page.getByRole('treeitem', { name: '指南', exact: true }).locator('.tiny-checkbox').click()
await treeMenu.getByRole('treeitem', { name: '指南' }).click()
await expect(treeMenu.getByRole('treeitem', { name: '引入组件' }).first().locator('.tiny-checkbox')).toHaveClass(
selectedClass
)
await expect(treeMenu.getByRole('treeitem', { name: '后端适配器' }).first().locator('.tiny-checkbox')).toHaveClass(
selectedClass
)
await treeMenu.getByRole('treeitem', { name: '引入组件' }).first().click()
await expect(
treeMenu.getByRole('treeitem', { name: '按需引入' }).first().locator('.tiny-checkbox').first()
).toHaveClass(selectedClass)
await treeNodeContent
.filter({ hasText: /^指南$/ })
.locator('.tiny-checkbox')
.click()
await treeNodeContent.filter({ hasText: /^指南$/ }).click()
await expect(treeNodeContent.filter({ hasText: /^指南$/ }).locator('.tiny-checkbox')).toHaveClass(selectedClass)
await expect(treeNodeContent.filter({ hasText: /^引入组件$/ }).locator('.tiny-checkbox')).toHaveClass(selectedClass)
await expect(treeNodeContent.filter({ hasText: /^后端适配器$/ }).locator('.tiny-checkbox')).toHaveClass(selectedClass)
await treeNodeContent.filter({ hasText: /^引入组件$/ }).click()
await expect(treeNodeContent.filter({ hasText: /^按需引入$/ }).locator('.tiny-checkbox')).toHaveClass(selectedClass)
await expect(treeNodeContent.filter({ hasText: /^完整引入$/ }).locator('.tiny-checkbox')).toHaveClass(selectedClass)
// 子节点取消勾选, 祖先节点改变勾选状态
await treeMenu.getByRole('treeitem', { name: '按需引入' }).first().locator('.tiny-checkbox').first().click()
await treeNodeContent
.filter({ hasText: /^完整引入$/ })
.locator('.tiny-checkbox')
.click()
await expect(
treeMenu.getByRole('treeitem', { name: '引入组件' }).first().locator('.tiny-checkbox__input').first()
treeNodeContent
.filter({ hasText: /^引入组件$/ })
.locator('.tiny-checkbox__input')
.first()
).toHaveClass(/is-indeterminate/)
await expect(treeMenu.getByRole('treeitem', { name: '指南' }).locator('.tiny-checkbox__input').first()).toHaveClass(
await expect(
treeNodeContent
.filter({ hasText: /^指南$/ })
.locator('.tiny-checkbox__input')
.first()
).toHaveClass(/is-indeterminate/)
await treeNodeContent
.filter({ hasText: /^按需引入$/ })
.locator('.tiny-checkbox')
.click()
await expect(treeNodeContent.filter({ hasText: /^引入组件$/ }).locator('.tiny-checkbox__input')).not.toHaveClass(
/is-indeterminate/
)
await treeMenu.getByRole('treeitem', { name: '完整引入' }).first().locator('.tiny-checkbox').first().click()
await expect(
treeMenu.getByRole('treeitem', { name: '引入组件' }).first().locator('.tiny-checkbox__input').first()
).not.toHaveClass(/is-indeterminate/)
await expect(treeNode.filter({ hasText: /^引入组件/ })).not.toHaveClass(selectedClass)
await expect(treeNode.filter({ hasText: /^按需引入$/ })).toHaveClass(/is-current/)
})
test('父子级不相关联', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#check-strictly')
await page.goto('tree-menu#show-checkbox')
const treeMenu = page.locator('#preview .tiny-tree-menu')
const checkedClass = /is-checked/
const wrap = page.locator('#show-checkbox')
const treeMenu = wrap.locator('.tiny-tree-menu').nth(1)
const treeNode = treeMenu.locator('.tiny-tree-node__wrapper > .tiny-tree-node')
const treeNodeContent = treeNode.locator('> .tiny-tree-node__content')
// 父节点勾选不会改变子节点
await treeMenu.getByRole('treeitem', { name: '指南' }).locator('svg').first().click()
await expect(treeMenu.getByRole('treeitem', { name: '引入组件' }).locator('svg').first()).not.toHaveClass(
checkedClass
await treeNodeContent
.filter({ hasText: /^指南$/ })
.locator('.tiny-checkbox')
.click()
await expect(treeNode.filter({ hasText: /^指南/ })).toHaveClass(/is-current is-checked/)
await treeNodeContent.filter({ hasText: /^指南$/ }).click()
await expect(treeNodeContent.filter({ hasText: /^引入组件$/ }).locator('.tiny-checkbox')).not.toHaveClass(
/is-checked/
)
await expect(page.getByRole('treeitem', { name: '构建部署' }).first().locator('span').nth(1)).not.toHaveClass(
checkedClass
await expect(treeNodeContent.filter({ hasText: /^构建部署$/ }).locator('.tiny-checkbox')).not.toHaveClass(
/is-checked/
)
// 子节点勾选不改变父节点
await page.getByRole('treeitem', { name: '引入组件' }).first().click()
await page.getByRole('treeitem', { name: '按需引入' }).locator('span').nth(2).click()
await page.getByRole('treeitem', { name: '完整引入' }).locator('span').nth(2).click()
await expect(page.getByRole('treeitem', { name: '引入组件' }).locator('span').nth(1)).not.toHaveClass(checkedClass)
})
test('可勾选节点默认选中', async ({ page }) => {
await treeNodeContent.filter({ hasText: /^引入组件$/ }).click()
await expect(treeNode.filter({ hasText: /^引入组件/ })).toHaveClass(/is-current is-focusable is-expanded/)
await expect(treeNode.filter({ hasText: /^引入组件/ })).not.toHaveClass(/is-checked/)
await expect(treeNodeContent.filter({ hasText: /^引入组件$/ }).locator('.tiny-checkbox')).not.toHaveClass(
/is-checked/
)
await treeNodeContent
.filter({ hasText: /^按需引入$/ })
.locator('.tiny-checkbox')
.click()
await treeNodeContent
.filter({ hasText: /^完整引入$/ })
.locator('.tiny-checkbox')
.click()
await expect(treeNodeContent.filter({ hasText: /^按需引入$/ }).locator('.tiny-checkbox')).toHaveClass(/is-checked/)
await expect(treeNodeContent.filter({ hasText: /^完整引入$/ }).locator('.tiny-checkbox')).toHaveClass(/is-checked/)
await expect(treeNodeContent.filter({ hasText: /^引入组件$/ }).locator('.tiny-checkbox')).not.toHaveClass(
/is-checked/
)
})

View File

@ -4,15 +4,18 @@ test('文字超长省略显示', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#text-ellipsis')
const treeMenu = page.locator('#preview .tiny-tree-menu')
const wrap = page.locator('#text-ellipsis')
const treeMenu = wrap.locator('.tiny-tree-menu').nth(0)
await expect(treeMenu.locator('.tiny-tree')).toHaveClass(/tiny-tree-menu__overflow/)
})
test('文字超长换行显示', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#text-wrap')
await page.goto('tree-menu#text-ellipsis')
const wrap = page.locator('#text-ellipsis')
const treeMenu = wrap.locator('.tiny-tree-menu').nth(1)
const treeMenu = page.locator('#preview .tiny-tree-menu')
await expect(treeMenu.locator('.tiny-tree')).toHaveClass(/tiny-tree-menu__wrap/)
})

View File

@ -4,9 +4,10 @@ test('插槽', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#tree-menu-slot')
const treeMenu = page.locator('#preview .tiny-tree-menu')
const treeMenu = page.locator('#tree-menu-slot .tiny-tree-menu')
await expect(treeMenu.getByText('首页')).toHaveClass('treeClass')
await expect(treeMenu.getByText('指南')).toHaveClass('treeNodeClass')
await expect(treeMenu.getByTitle('首页').locator('.tiny-svg')).toHaveCSS('margin-right', '4px')
await expect(treeMenu.getByTitle('教程').locator('.tiny-svg')).toHaveCSS('margin-left', '-20px')
await expect(treeMenu.getByTitle('首页').locator('.tiny-svg')).toHaveCSS('margin-left', '8px')
await expect(treeMenu.getByTitle('教程').locator('.tiny-svg')).toHaveCSS('margin-left', '8px')
})