Skip to content

Commit

Permalink
feat(virtual-scroll): demo with tests (#1986)
Browse files Browse the repository at this point in the history
  • Loading branch information
necoxrr authored Aug 26, 2024
1 parent 7612e75 commit f646fe7
Show file tree
Hide file tree
Showing 24 changed files with 741 additions and 191 deletions.
87 changes: 83 additions & 4 deletions examples/sites/demos/apis/virtual-scroll.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,100 @@ export default {
name: 'virtual-scroll',
type: 'component',
props: [
{
name: 'buffer',
type: 'Number',
defaultValue: '1',
desc: {
'zh-CN': '显示区域条数的比例值为缓冲区设置',
'en-US': 'Scale value of the number of bars in the display area is set for the buffer.'
},
mode: ['pc'],
pcDemo: 'basic-usage'
},
{
name: 'data',
type: 'Array',
defaultValue: '',
defaultValue: '[]',
desc: {
'zh-CN': '需要展示的数据',
'en-US': 'Data to be displayed'
},
mode: ['pc'],
pcDemo: 'basic-usage'
},
{
name: 'direction',
type: 'String',
defaultValue: 'vertical',
desc: {
'zh-CN': '滚动方向',
'en-US': 'scrolling direction'
},
mode: ['pc'],
pcDemo: 'basic-usage'
},
{
name: 'estimatedItemSize',
type: 'Number',
defaultValue: '--',
desc: {
'zh-CN': '是否启动动态尺寸,你不需关注每个项目的大小,它会自动计算',
'en-US':
'Whether or not dynamic sizing is activated, you dont need to be concerned about the size of each item, it will be automatically calculated.'
},
mode: ['pc'],
pcDemo: 'dynamic-height'
},
{
name: 'itemSize',
type: 'Number',
defaultValue: '--',
desc: {
'zh-CN': '设置数据源, 默认通过data属性来传入,在item中显示数据',
'zh-CN': '以像素为单位定义每个项目的高度,用于计算滚动条的大小和位置。',
'en-US':
'Set the data source, which is passed through the data attribute by default, to display the data in the item.'
'Defines the height of each item in pixels, which is used to calculate the size and position of the scrollbar.'
},
mode: ['pc'],
pcDemo: 'basic-usage'
},
{
name: 'itemIndex',
type: 'String',
defaultValue: 'id',
desc: {
'zh-CN': '默认滚动的index',
'en-US': 'Default scrolling index'
},
mode: ['pc'],
pcDemo: 'basic-usage'
},
{
name: 'prerender',
type: 'Number',
defaultValue: '0',
desc: {
'zh-CN': 'SSR渲染区域的项目条数',
'en-US': 'Number of item strips in the SSR rendering area.'
},
mode: ['pc'],
pcDemo: 'basic-usage'
}
],
events: [],
methods: [],
methods: [
{
name: 'scrollToItem',
type: '(index:number)=> Promise',
defaultValue: '',
desc: {
'zh-CN': '滚动到对应索引的项目',
'en-US': 'Scroll to the item corresponding to the index.'
},
mode: ['pc'],
pcDemo: 'specified-item'
}
],
slots: []
}
],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
<template>
<div>
<!-- vue3 -->
<p>虚拟滚动组件demo</p>
<TinyVirtualScroll :data="showData" :itemHeight="30" :viewHeight="180" itemIndex="key">
<TinyVirtualScroll :data="showData" :itemSize="50" itemIndex="key" class="tiny-virtual-scroll" direction="vertical">
<template #default="props">
<div class="scroll-item">
<div class="tiny-virtual-scroll-item">
{{ props.item.value }}
</div>
</template>
Expand All @@ -21,8 +20,26 @@ const showData = ref([])
// 生成模拟数据
showData.value = Array.from(Array(1000), (v, k) => {
return {
value: k,
key: k
value: `${k + 1}`,
key: k + 1
}
})
</script>

<style>
.virtual-scroll-demo {
height: 100%;
overflow: hidden;
/* display: flex; */
}
.tiny-virtual-scroll {
height: 300px;
}
.tiny-virtual-scroll-item {
padding: 10px;
border-bottom: 2px solid #ddd;
align-content: center;
}
</style>
39 changes: 39 additions & 0 deletions examples/sites/demos/pc/app/virtual-scroll/basic-usage.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { test, expect } from '@playwright/test'

test('基本用法', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('virtual-scroll#basic-usage')
const virtualScroll = page.locator('#basic-usage .tiny-virtual-scroll')
const virtualScrollItem = virtualScroll.locator('.tiny-virtual-scroll-item')
await expect(virtualScroll).toBeVisible()
await expect(virtualScrollItem.nth(0)).toBeVisible()
await expect(virtualScrollItem.nth(0)).toHaveText('第1项')
await page.waitForTimeout(500)
const containerBox = await virtualScroll.boundingBox()
let visibleCount = 0
let visibleItems = []
const visibleItemsCount = await virtualScrollItem.count()
for (let i = 0; i < visibleItemsCount; i++) {
const itemBox = await virtualScrollItem.nth(i).boundingBox()
if (itemBox && containerBox) {
if (itemBox.y >= containerBox.y && itemBox.y + itemBox.height <= containerBox.y + containerBox.height) {
visibleCount++
const itemText = await virtualScrollItem.nth(i).textContent()
visibleItems.push(itemText.trim())
}
}
}
console.log('Visible items:', visibleItems)
await expect(visibleCount).toBe(6)
for (let i = 0; i < visibleItems.length; i++) {
console.log(`Item ${i + 1}:`, visibleItems[i])
}
await virtualScroll.evaluate((scroll) => scroll.scrollTo(0, 25000))
await page.waitForTimeout(500)
const targetItem = virtualScroll.locator('.tiny-virtual-scroll-item', { hasText: '第500项' })
await expect(targetItem).toBeVisible()
await virtualScroll.evaluate((scroll) => scroll.scrollTo(0, 50000))
await expect(virtualScrollItem.last()).toHaveText('第1000项')
let errors = []
expect(errors.length).toBe(0)
})
18 changes: 10 additions & 8 deletions examples/sites/demos/pc/app/virtual-scroll/basic-usage.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
<template>
<div class="virtual-scroll-demo">
<!-- Vue2的选项式API -->
<p>虚拟滚动组件demo</p>
<TinyVirtualScroll :data="showData" :itemSize="50" :viewSize="300" itemIndex="key" class="ho" direction="vertical">
<TinyVirtualScroll :data="showData" :itemSize="50" itemIndex="key" class="tiny-virtual-scroll">
<template #default="props">
<div class="scroll-item">
<div class="tiny-virtual-scroll-item">
{{ props.item.value }}
</div>
</template>
Expand All @@ -26,10 +25,10 @@ export default {
},
created() {
// 生成模拟数据
this.showData = Array.from(Array(10000), (v, k) => {
this.showData = Array.from(Array(1000), (v, k) => {
return {
value: k,
key: k
value: `${k + 1}`,
key: k + 1
}
})
}
Expand All @@ -43,8 +42,11 @@ export default {
/* display: flex; */
}
.scroll-item {
width: 600px;
.tiny-virtual-scroll {
height: 300px;
}
.tiny-virtual-scroll-item {
padding: 10px;
border-bottom: 2px solid #ddd;
align-content: center;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
<template>
<div class="virtual-scroll-demo">
<p>虚拟滚动组件demo</p>
<TinyVirtualScroll :data="showData" :estimatedItemSize="50" :viewSize="600" itemIndex="id" class="ho"
direction="vertical">
<TinyVirtualScroll :data="showData" :estimatedItemSize="50" itemIndex="id" class="tiny-virtual-scroll"
direction="vertical" :buffer="0.5">
<template #default="props">
<div class="scroll-item">
<div class="tiny-virtual-scroll-item">
{{ props.item.value }}
</div>
</template>
Expand All @@ -19,10 +18,10 @@ import { VirtualScroll as TinyVirtualScroll } from '@opentiny/vue'
// 创建动态数据
const showData = ref([])
for (let i = 1; i <= 1000; i++) {
for (let i = 1; i <= 10000; i++) {
showData.value.push({
id: i,
value: `${i}字符内容`.repeat(Math.ceil(Math.random() * 20)) // 动态文本内容
value: `${i}字符内容`.repeat(Math.ceil(Math.random() * 30)) // 动态文本内容
})
}
</script>
Expand All @@ -31,11 +30,16 @@ for (let i = 1; i <= 1000; i++) {
.virtual-scroll-demo {
height: 100%;
overflow: hidden;
/* display: flex; */
/* width: 600px; */
}
.scroll-item {
.tiny-virtual-scroll {
height: 300px;
width: 100%;
}
.tiny-virtual-scroll-item {
padding: 10px;
border-bottom: 10px solid #ddd;
border-bottom: 2px solid #ddd;
}
</style>
Empty file.
30 changes: 30 additions & 0 deletions examples/sites/demos/pc/app/virtual-scroll/dynamic-height.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { test, expect } from '@playwright/test'

test('基本用法', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('virtual-scroll#dynamic-height')
const virtualScroll = page.locator('#dynamic-height .tiny-virtual-scroll')
const virtualScrollItem = virtualScroll.locator('.tiny-virtual-scroll-item')
await expect(virtualScroll).toBeVisible()
await expect(virtualScrollItem.nth(0)).toBeVisible()
await virtualScroll.evaluate((scroll) => {
for (let i = 0; i < 50; i++) {
scroll.scrollBy(0, 200)
}
})
await expect(virtualScrollItem.last()).toBeVisible()
const midItem = virtualScrollItem.nth(0)
await expect(midItem).toBeVisible()
const midItemText = await midItem.textContent()
expect(midItemText).not.toBeNull()
let allVisibleItems = await virtualScrollItem.all()
await virtualScroll.evaluate((scroll) => scroll.scrollTo(0, scroll.scrollHeight))
const lastItem = virtualScrollItem.last()
await expect(lastItem).toBeVisible()
const lastItemText = await lastItem.textContent()
expect(lastItemText).not.toBeNull()
allVisibleItems = await virtualScrollItem.all()
for (const item of allVisibleItems) {
await expect(item).toBeVisible()
}
})
17 changes: 8 additions & 9 deletions examples/sites/demos/pc/app/virtual-scroll/dynamic-height.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
<template>
<div class="virtual-scroll-demo">
<!-- Vue2的选项式API -->
<p>虚拟滚动组件demo</p>
<TinyVirtualScroll :data="showData" :estimatedItemSize="50" :viewSize="600" itemIndex="id" class="ho"
direction="vertical">
<TinyVirtualScroll :data="showData" :estimatedItemSize="50" itemIndex="id" class="tiny-virtual-scroll"
direction="vertical" :buffer="0.5">
<template #default="props">
<div class="scroll-item">
<div class="tiny-virtual-scroll-item">
{{ props.item.value }}
</div>
</template>
Expand All @@ -28,8 +27,8 @@ export default {
created() {
// 生成动态高度的数据
this.showData = Array.from({ length: 10000 }, (_, i) => ({
id: i,
value: `${i}字符内容`.repeat(Math.ceil(Math.random() * 30)) // 动态文本内容
id: i + 1,
value: `${i + 1}字符内容`.repeat(Math.ceil(Math.random() * 30)) // 动态文本内容
}))
}
}
Expand All @@ -42,11 +41,11 @@ export default {
/* width: 600px; */
}
.ho {
height: 100px;
.tiny-virtual-scroll {
height: 400px;
}
.scroll-item {
.tiny-virtual-scroll-item {
padding: 10px;
border-bottom: 2px solid #ddd;
}
Expand Down
Loading

0 comments on commit f646fe7

Please sign in to comment.