fix: address code review feedback for VirtualGrid

- Fix rowsToHeight to use Math.ceil for partial row calculation
- Use vi.hoisted pattern for test mocks with proper beforeEach reset
- Add wrapper.unmount() to prevent DOM state leaks in tests
- Remove !important prefix from disabled outline class
- Use i18n for maxSelectionReached toast message

Amp-Thread-ID: https://ampcode.com/threads/T-019c7db7-6d68-711e-b2f5-b6211343697a
This commit is contained in:
bymyself
2026-02-21 01:11:37 +00:00
parent 6a3d06214e
commit 9463371fc1
5 changed files with 20 additions and 9 deletions

View File

@@ -1,14 +1,15 @@
import { mount } from '@vue/test-utils'
import { describe, expect, it, vi } from 'vitest'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import type { Ref } from 'vue'
import { nextTick, ref } from 'vue'
import VirtualGrid from './VirtualGrid.vue'
type TestItem = { key: string; name: string }
const mockedWidth = ref(400)
const mockedHeight = ref(200)
const mockedScrollY = ref(0)
let mockedWidth: Ref<number>
let mockedHeight: Ref<number>
let mockedScrollY: Ref<number>
vi.mock('@vueuse/core', async () => {
const actual = await vi.importActual<Record<string, unknown>>('@vueuse/core')
@@ -19,6 +20,12 @@ vi.mock('@vueuse/core', async () => {
}
})
beforeEach(() => {
mockedWidth = ref(400)
mockedHeight = ref(200)
mockedScrollY = ref(0)
})
function createItems(count: number): TestItem[] {
return Array.from({ length: count }, (_, i) => ({
key: `item-${i}`,
@@ -144,6 +151,8 @@ describe('VirtualGrid', () => {
const renderedItems = wrapper.findAll('.test-item')
expect(renderedItems.length).toBe(0)
wrapper.unmount()
})
it('forces cols to maxColumns when maxColumns is finite', async () => {

View File

@@ -101,8 +101,9 @@ const renderedItems = computed(() =>
isValidGrid.value ? items.slice(state.value.start, state.value.end) : []
)
function rowsToHeight(rows: number): string {
return `${(rows / cols.value) * itemHeight.value}px`
function rowsToHeight(itemsCount: number): string {
const rows = Math.ceil(itemsCount / cols.value)
return `${rows * itemHeight.value}px`
}
const topSpacerStyle = computed<CSSProperties>(() => ({
height: rowsToHeight(state.value.start)

View File

@@ -2447,7 +2447,8 @@
"placeholderVideo": "Select video...",
"placeholderMesh": "Select mesh...",
"placeholderModel": "Select model...",
"placeholderUnknown": "Select media..."
"placeholderUnknown": "Select media...",
"maxSelectionReached": "Maximum selection limit reached"
},
"valueControl": {
"header": {

View File

@@ -161,7 +161,7 @@ function handleSelection(item: FormDropdownItem, index: number) {
sel.clear()
sel.add(item.id)
} else {
toastStore.addAlert(`Maximum selection limit reached`)
toastStore.addAlert(t('widgets.uploadSelect.maxSelectionReached'))
return
}
}

View File

@@ -49,7 +49,7 @@ const theButtonStyle = computed(() =>
<div
:class="
cn(WidgetInputBaseClass, 'flex text-base leading-none', {
'opacity-50 cursor-not-allowed !outline-zinc-300/10': disabled
'opacity-50 cursor-not-allowed outline-zinc-300/10': disabled
})
"
>