Restore and persist the package-based link collector with progressive metadata, bounded high-volume updates, safe hydration, visible selection, and complete localization. Harden download controls, snapshot ordering, history pagination, statistics recovery, settings saves, backup imports, notification persistence, and Windows storage races with regression coverage.
73 lines
2.8 KiB
TypeScript
73 lines
2.8 KiB
TypeScript
import { performance } from "node:perf_hooks";
|
|
import { describe, expect, it } from "vitest";
|
|
import * as historyModelModule from "../src/renderer/views/history/history-model";
|
|
import { buildHistoryViewModel, type HistoryViewEntry } from "../src/renderer/views/history/history-model";
|
|
|
|
function createLargeHistory(count: number, now: number): HistoryViewEntry[] {
|
|
return Array.from({ length: count }, (_, index) => ({
|
|
id: `history-${index}`,
|
|
name: `Package ${index}`,
|
|
totalBytes: 2_097_152,
|
|
downloadedBytes: 1_572_864,
|
|
fileCount: 1,
|
|
provider: "realdebrid",
|
|
completedAt: now - index,
|
|
durationSeconds: 60,
|
|
status: index % 5 === 0 ? "failed" : "completed",
|
|
outputDir: `C:\\Downloads\\Package ${index}`,
|
|
urls: [`https://rapidgator.net/file/${index}`]
|
|
}));
|
|
}
|
|
|
|
describe("history 100k performance contract", () => {
|
|
it("keeps an unchanged second tick and cached page below one frame", () => {
|
|
const getHistoryPage = (historyModelModule as unknown as {
|
|
getHistoryPage?: (
|
|
model: ReturnType<typeof buildHistoryViewModel>,
|
|
requestedPage: number
|
|
) => { rows: unknown[] };
|
|
}).getHistoryPage;
|
|
expect(getHistoryPage).toBeTypeOf("function");
|
|
if (!getHistoryPage) return;
|
|
|
|
const now = new Date(2026, 7, 10, 12, 0, 0, 0).getTime();
|
|
const entries = createLargeHistory(100_000, now);
|
|
const initial = buildHistoryViewModel(entries, "all", "", [], [], false, "", now);
|
|
const initialPage = getHistoryPage(initial, 500);
|
|
expect(initialPage.rows).toHaveLength(100);
|
|
|
|
const startedAt = performance.now();
|
|
const next = buildHistoryViewModel(entries, "all", "", [], [], false, "", now + 1_000);
|
|
const nextPage = getHistoryPage(next, 500);
|
|
const elapsedMs = performance.now() - startedAt;
|
|
|
|
expect(next.rows).toBe(initial.rows);
|
|
expect(nextPage).toBe(initialPage);
|
|
expect(elapsedMs).toBeLessThan(10);
|
|
});
|
|
|
|
it("keeps a warmed 100k search interaction below one frame", () => {
|
|
const getHistoryPage = (historyModelModule as unknown as {
|
|
getHistoryPage?: (
|
|
model: ReturnType<typeof buildHistoryViewModel>,
|
|
requestedPage: number
|
|
) => { rows: unknown[] };
|
|
}).getHistoryPage;
|
|
expect(getHistoryPage).toBeTypeOf("function");
|
|
if (!getHistoryPage) return;
|
|
|
|
const now = new Date(2026, 7, 10, 12, 0, 0, 0).getTime();
|
|
const entries = createLargeHistory(100_000, now);
|
|
buildHistoryViewModel(entries, "all", "", [], [], false, "", now);
|
|
|
|
const startedAt = performance.now();
|
|
const searched = buildHistoryViewModel(entries, "all", "99999", [], [], false, "", now);
|
|
const page = getHistoryPage(searched, 1);
|
|
const elapsedMs = performance.now() - startedAt;
|
|
|
|
expect(searched.rows).toHaveLength(1);
|
|
expect(page.rows).toHaveLength(1);
|
|
expect(elapsedMs).toBeLessThan(16);
|
|
});
|
|
});
|