fix: await initial market synchronization

This commit is contained in:
wxs
2026-07-17 16:06:51 +08:00
parent 01efa9f847
commit 8ca9f95583
2 changed files with 149 additions and 33 deletions
+79
View File
@@ -4975,6 +4975,85 @@ describe("market-content-entry", () => {
expect(buildCsv).toHaveBeenCalledTimes(1);
});
test("awaits a scheduled initial hydration before ready enables an immediate export", async () => {
document.body.innerHTML = buildRealMarketFixture([
{ authorId: "111", authorName: "达人 A", price21To60s: "¥11,000" }
]);
const repository = createTestFavoritesRepository();
const originalRead = repository.read.bind(repository);
const observer = createMutationObserverFactory();
const successfulMetrics = {
rates: {
personalVideoAfterSearchRate: "0.2%",
singleVideoAfterSearchRate: "0.1%"
},
success: true as const
};
const deferredMetrics = createDeferred<typeof successfulMetrics>();
let shouldReplaceInitialPage = true;
let activeMetricLoads = 0;
let maxActiveMetricLoads = 0;
repository.read = async () => {
const state = await originalRead();
if (shouldReplaceInitialPage) {
shouldReplaceInitialPage = false;
document.body.innerHTML = buildRealMarketFixture([
{ authorId: "222", authorName: "达人 B", price21To60s: "¥22,000" }
]);
observer.trigger();
}
return state;
};
const loadAuthorMetrics = vi.fn(async (authorId: string) => {
activeMetricLoads += 1;
maxActiveMetricLoads = Math.max(maxActiveMetricLoads, activeMetricLoads);
try {
if (authorId === "222") {
return await deferredMetrics.promise;
}
return successfulMetrics;
} finally {
activeMetricLoads -= 1;
}
});
const buildCsv = vi.fn(() => "csv-output");
const { createMarketController } = await import("../src/content/market/index");
const controller = trackController(createMarketController({
buildCsv,
document,
favoritesRepository: repository,
loadAuthorMetrics,
mutationObserverFactory: observer.factory,
onCsvReady: vi.fn(),
window
}));
let readySettled = false;
void controller.ready.then(() => {
readySettled = true;
});
await waitForCondition(() =>
loadAuthorMetrics.mock.calls.some(([authorId]) => authorId === "222")
);
await Promise.resolve();
expect(readySettled).toBe(false);
deferredMetrics.resolve(successfulMetrics);
await controller.ready;
setSelectValue('[data-plugin-export-range="select"]', "current");
dispatchChange('[data-plugin-export-range="select"]');
removeDefaultSpreadMetricFilter();
click('[data-plugin-export="button"]');
await waitForMockCall(buildCsv, 40, 50);
expect(buildCsv).toHaveBeenCalledTimes(1);
expect(loadAuthorMetrics.mock.calls.map(([authorId]) => authorId)).toEqual(["111", "222"]);
expect(maxActiveMetricLoads).toBe(1);
});
test("keeps the friendly drawer error when a direct folder mutation has no message", async () => {
document.body.innerHTML = buildRealMarketFixture([
{ authorId: "111", authorName: "达人 A", price21To60s: "¥11,000" }