mirror of
https://gitee.com/spark-store-project/spark-store
synced 2026-06-22 06:03:49 +08:00
fix(sync): resolve restore item edge cases
This commit is contained in:
+5
-4
@@ -1583,12 +1583,13 @@ const openRestoreFromAccount = async (): Promise<void> => {
|
|||||||
|
|
||||||
const installCloudItems = (items: SyncedAppListItem[]): void => {
|
const installCloudItems = (items: SyncedAppListItem[]): void => {
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
const app = apps.value.find(
|
const candidates = apps.value.filter(
|
||||||
(candidate) =>
|
(candidate) =>
|
||||||
candidate.pkgname === item.pkgname &&
|
candidate.pkgname === item.pkgname && candidate.origin === item.origin,
|
||||||
candidate.origin === item.origin &&
|
|
||||||
candidate.category === item.category,
|
|
||||||
);
|
);
|
||||||
|
const app =
|
||||||
|
candidates.find((candidate) => candidate.category === item.category) ??
|
||||||
|
candidates[0];
|
||||||
if (!app) continue;
|
if (!app) continue;
|
||||||
void onDetailInstall(app);
|
void onDetailInstall(app);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,11 @@ import { fireEvent, render, screen, waitFor } from "@testing-library/vue";
|
|||||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
import App from "@/App.vue";
|
import App from "@/App.vue";
|
||||||
import { listDownloadedApps, listFavoriteFolders } from "@/modules/backendApi";
|
import {
|
||||||
|
fetchSyncedAppList,
|
||||||
|
listDownloadedApps,
|
||||||
|
listFavoriteFolders,
|
||||||
|
} from "@/modules/backendApi";
|
||||||
import { setAuthSession } from "@/global/authState";
|
import { setAuthSession } from "@/global/authState";
|
||||||
import type {
|
import type {
|
||||||
DownloadedAppList,
|
DownloadedAppList,
|
||||||
@@ -97,10 +101,11 @@ vi.mock("axios", () => {
|
|||||||
}
|
}
|
||||||
return { data: [] };
|
return { data: [] };
|
||||||
});
|
});
|
||||||
|
const post = vi.fn(async () => ({ data: { ok: true } }));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
default: {
|
default: {
|
||||||
create: () => ({ get }),
|
create: () => ({ get, post }),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -138,9 +143,11 @@ vi.mock("@/modules/backendApi", () => ({
|
|||||||
bulkDeleteFavoriteItems: vi.fn(),
|
bulkDeleteFavoriteItems: vi.fn(),
|
||||||
createFavoriteFolder: vi.fn(),
|
createFavoriteFolder: vi.fn(),
|
||||||
exchangeFlarumToken: vi.fn(),
|
exchangeFlarumToken: vi.fn(),
|
||||||
|
fetchSyncedAppList: vi.fn(async () => null),
|
||||||
listDownloadedApps: vi.fn(async () => downloadedList([])),
|
listDownloadedApps: vi.fn(async () => downloadedList([])),
|
||||||
listFavoriteFolders: vi.fn(async () => favoriteFolders),
|
listFavoriteFolders: vi.fn(async () => favoriteFolders),
|
||||||
listFavoriteItems: vi.fn(async () => favoriteItems),
|
listFavoriteItems: vi.fn(async () => favoriteItems),
|
||||||
|
uploadSyncedAppList: vi.fn(),
|
||||||
setBackendToken: vi.fn(),
|
setBackendToken: vi.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -437,4 +444,52 @@ describe("App account placeholders", () => {
|
|||||||
expect(screen.queryByText("旧账号应用")).toBeNull();
|
expect(screen.queryByText("旧账号应用")).toBeNull();
|
||||||
expect(screen.getByText("暂无下载记录。")).toBeTruthy();
|
expect(screen.getByText("暂无下载记录。")).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("restores cloud apps by origin and package when category changed", async () => {
|
||||||
|
vi.mocked(fetchSyncedAppList).mockResolvedValueOnce({
|
||||||
|
snapshotName: "默认列表",
|
||||||
|
clientArch: "amd64",
|
||||||
|
distro: "deepin 25",
|
||||||
|
updatedAt: "2026-05-18T00:00:00Z",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
pkgname: "wps",
|
||||||
|
origin: "apm",
|
||||||
|
category: "legacy-office",
|
||||||
|
version: "1.0.0",
|
||||||
|
packageArch: "amd64",
|
||||||
|
appName: "WPS Cloud",
|
||||||
|
iconUrl: "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
invoke.mockImplementation(async (channel: string, payload?: unknown) => {
|
||||||
|
if (channel === "get-store-filter") return "apm";
|
||||||
|
if (channel === "check-spark-available") return false;
|
||||||
|
if (channel === "check-apm-available") return true;
|
||||||
|
if (channel === "get-app-version") return "5.0.0";
|
||||||
|
if (channel === "get-system-info") return { distro: "deepin 25" };
|
||||||
|
if (channel === "check-installed") return false;
|
||||||
|
if (channel === "list-installed") {
|
||||||
|
const request = payload as { origin?: string };
|
||||||
|
if (request.origin === "apm") return { success: true, apps: [] };
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
});
|
||||||
|
render(App);
|
||||||
|
|
||||||
|
await fireEvent.click(await screen.findByText("应用管理"));
|
||||||
|
await fireEvent.click(
|
||||||
|
await screen.findByRole("button", { name: /从账号恢复/ }),
|
||||||
|
);
|
||||||
|
await fireEvent.click(await screen.findByLabelText("WPS Cloud"));
|
||||||
|
await fireEvent.click(screen.getByRole("button", { name: "加入安装队列" }));
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(window.ipcRenderer.send).toHaveBeenCalledWith(
|
||||||
|
"queue-install",
|
||||||
|
expect.stringContaining('"pkgname":"wps"'),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -54,4 +54,22 @@ describe("AppListRestoreModal", () => {
|
|||||||
expect(screen.getByLabelText("Spark Notes")).toBeDisabled();
|
expect(screen.getByLabelText("Spark Notes")).toBeDisabled();
|
||||||
expect(screen.getByText("已安装")).toBeTruthy();
|
expect(screen.getByText("已安装")).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("removes selected items when they become installed", async () => {
|
||||||
|
const rendered = render(AppListRestoreModal, {
|
||||||
|
props: {
|
||||||
|
show: true,
|
||||||
|
loading: false,
|
||||||
|
error: "",
|
||||||
|
items: [createItem()],
|
||||||
|
installedKeys: new Set<string>(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await fireEvent.click(screen.getByLabelText("Spark Notes"));
|
||||||
|
await rendered.rerender({ installedKeys: new Set(["spark:spark-notes"]) });
|
||||||
|
|
||||||
|
expect(screen.getByLabelText("Spark Notes")).toBeDisabled();
|
||||||
|
expect(screen.getByRole("button", { name: "加入安装队列" })).toBeDisabled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -150,9 +150,17 @@ const isInstalled = (item: SyncedAppListItem): boolean =>
|
|||||||
props.installedKeys.has(cloudItemKey(item));
|
props.installedKeys.has(cloudItemKey(item));
|
||||||
|
|
||||||
const selectedItems = computed(() =>
|
const selectedItems = computed(() =>
|
||||||
props.items.filter((item) => selectedKeys.value.has(cloudItemKey(item))),
|
props.items.filter(
|
||||||
|
(item) => selectedKeys.value.has(cloudItemKey(item)) && !isInstalled(item),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const pruneSelectedKeys = (): void => {
|
||||||
|
selectedKeys.value = new Set(
|
||||||
|
[...selectedKeys.value].filter((key) => !props.installedKeys.has(key)),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const toggleSelection = (item: SyncedAppListItem): void => {
|
const toggleSelection = (item: SyncedAppListItem): void => {
|
||||||
if (isInstalled(item)) return;
|
if (isInstalled(item)) return;
|
||||||
const key = cloudItemKey(item);
|
const key = cloudItemKey(item);
|
||||||
@@ -169,4 +177,12 @@ watch(
|
|||||||
},
|
},
|
||||||
{ deep: true },
|
{ deep: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.installedKeys,
|
||||||
|
() => {
|
||||||
|
pruneSelectedKeys();
|
||||||
|
},
|
||||||
|
{ deep: true },
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user