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 @@