From 1d51f38e646673c0d3e7670f7fcf26fa70656b03 Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 10 Apr 2026 16:17:38 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=BB=9A=E5=8A=A8):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=88=86=E7=B1=BB=E5=88=87=E6=8D=A2=E6=97=B6=E9=87=8D=E7=BD=AE?= =?UTF-8?q?=E8=99=9A=E6=8B=9F=E6=BB=9A=E5=8A=A8=E4=BD=8D=E7=BD=AE=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加 scrollKey 属性到 AppGrid 组件,当分类变化时自动重置滚动位置 添加相关单元测试验证滚动重置功能 --- src/App.vue | 1 + src/__tests__/unit/AppGrid.test.ts | 101 +++++++++++++++++++++++++++++ src/components/AppGrid.vue | 22 ++++++- 3 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 src/__tests__/unit/AppGrid.test.ts diff --git a/src/App.vue b/src/App.vue index 73d2f3c6..95993248 100644 --- a/src/App.vue +++ b/src/App.vue @@ -60,6 +60,7 @@ diff --git a/src/__tests__/unit/AppGrid.test.ts b/src/__tests__/unit/AppGrid.test.ts new file mode 100644 index 00000000..1ff1936b --- /dev/null +++ b/src/__tests__/unit/AppGrid.test.ts @@ -0,0 +1,101 @@ +import { render } from "@testing-library/vue"; +import { defineComponent, h, nextTick } from "vue"; +import { describe, expect, it, vi } from "vitest"; + +import AppGrid from "@/components/AppGrid.vue"; +import type { App } from "@/global/typedefinition"; + +vi.mock("@/components/AppCard.vue", () => ({ + default: defineComponent({ + name: "AppCard", + props: { + app: { + type: Object, + required: true, + }, + }, + setup(props) { + return () => h("div", props.app.name); + }, + }), +})); + +vi.mock("vue-virtual-scroller", () => ({ + RecycleScroller: defineComponent({ + name: "RecycleScroller", + props: { + items: { + type: Array, + required: true, + }, + }, + setup(props, { attrs, slots }) { + return () => + h( + "div", + { + ...attrs, + style: "max-height: 320px; overflow-y: auto;", + }, + (props.items as Array<{ id: number; apps: App[] }>).map((item) => + slots.default?.({ item }), + ), + ); + }, + }), +})); + +const createApp = (index: number, category: string): App => ({ + name: `App ${index}`, + pkgname: `app-${category}-${index}`, + version: "1.0.0", + filename: "app.deb", + torrent_address: "", + author: "", + contributor: "", + website: "", + update: "", + size: "1 MB", + more: "", + tags: "", + img_urls: [], + icons: "", + category, + origin: "spark", + currentStatus: "not-installed", +}); + +const createApps = (count: number, category: string): App[] => + Array.from({ length: count }, (_, index) => createApp(index, category)); + +describe("AppGrid", () => { + it("resets the virtual scroller when the category changes", async () => { + const { container, rerender } = render(AppGrid, { + props: { + apps: createApps(60, "development"), + loading: false, + scrollKey: "development", + } as Record, + }); + + const scroller = container.querySelector(".scroller"); + + expect(scroller).toBeInstanceOf(HTMLElement); + + if (!(scroller instanceof HTMLElement)) { + throw new Error("Expected virtual scroller element to exist"); + } + + scroller.scrollTop = 240; + expect(scroller.scrollTop).toBe(240); + + await rerender({ + apps: createApps(60, "games"), + loading: false, + scrollKey: "games", + } as Record); + await nextTick(); + + expect(scroller.scrollTop).toBe(0); + }); +}); diff --git a/src/components/AppGrid.vue b/src/components/AppGrid.vue index acc7485c..18de0ca8 100644 --- a/src/components/AppGrid.vue +++ b/src/components/AppGrid.vue @@ -34,6 +34,7 @@