fix: recover favorites controller refresh
This commit is contained in:
@@ -236,6 +236,7 @@ export function createMarketController(options: CreateMarketControllerOptions) {
|
||||
let favoritesRefreshVersion = 0;
|
||||
let favoriteActionButtons: HTMLButtonElement[] = [];
|
||||
let needsFavoritesRefresh = false;
|
||||
let favoritesUnavailable = false;
|
||||
const favoritesDrawer: FavoritesDrawerController = createFavoritesDrawer(
|
||||
options.document,
|
||||
{
|
||||
@@ -272,16 +273,19 @@ export function createMarketController(options: CreateMarketControllerOptions) {
|
||||
const favoriteControlsMissing =
|
||||
cachedFavoritesState !== undefined &&
|
||||
favoriteActionButtons.some((button) => !button.isConnected);
|
||||
const needsUnavailableFavoritesRecovery =
|
||||
favoritesUnavailable && nextPageSignature !== lastKnownPageSignature;
|
||||
if (
|
||||
nextPageSignature === lastKnownPageSignature &&
|
||||
!toolbarNeedsRemount &&
|
||||
!selectionControlsMissing &&
|
||||
!favoriteControlsMissing
|
||||
!favoriteControlsMissing &&
|
||||
!needsUnavailableFavoritesRecovery
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (favoriteControlsMissing) {
|
||||
if (favoriteControlsMissing || needsUnavailableFavoritesRecovery) {
|
||||
needsFavoritesRefresh = true;
|
||||
}
|
||||
scheduleSync();
|
||||
@@ -529,6 +533,7 @@ export function createMarketController(options: CreateMarketControllerOptions) {
|
||||
const ready = (async () => {
|
||||
await runSyncCycle();
|
||||
await refreshFavorites();
|
||||
await waitForDomSettled();
|
||||
})();
|
||||
|
||||
return {
|
||||
@@ -722,6 +727,7 @@ export function createMarketController(options: CreateMarketControllerOptions) {
|
||||
}
|
||||
|
||||
cachedFavoritesState = state;
|
||||
favoritesUnavailable = false;
|
||||
favoritesDrawer.setError("");
|
||||
favoritesDrawer.render(state);
|
||||
runWithoutMutationSync(() => {
|
||||
@@ -734,6 +740,7 @@ export function createMarketController(options: CreateMarketControllerOptions) {
|
||||
|
||||
cachedFavoritesState = undefined;
|
||||
favoriteActionButtons = [];
|
||||
favoritesUnavailable = true;
|
||||
disposeFavoriteRowPickers(options.document);
|
||||
favoritesDrawer.setError("收藏夹暂不可用");
|
||||
}
|
||||
|
||||
@@ -4872,7 +4872,7 @@ describe("market-content-entry", () => {
|
||||
expect(document.querySelector('[data-plugin-batch-submit="button"]')).not.toBeNull();
|
||||
});
|
||||
|
||||
test("clears stale favorite pickers when a later repository refresh fails", async () => {
|
||||
test("recovers favorite pickers after a later refresh failure and page replacement", async () => {
|
||||
document.body.innerHTML = buildRealMarketFixture([
|
||||
{ authorId: "111", authorName: "达人 A", price21To60s: "¥11,000" }
|
||||
]);
|
||||
@@ -4881,12 +4881,13 @@ describe("market-content-entry", () => {
|
||||
await repository.setCreatorFolderIds({ authorId: "111", authorName: "达人 A" }, [folder.id]);
|
||||
const originalRead = repository.read.bind(repository);
|
||||
let shouldRejectRead = false;
|
||||
repository.read = async () => {
|
||||
const read = vi.fn(async () => {
|
||||
if (shouldRejectRead) {
|
||||
throw new Error("storage unavailable");
|
||||
}
|
||||
return originalRead();
|
||||
};
|
||||
});
|
||||
repository.read = read;
|
||||
const observer = createMutationObserverFactory();
|
||||
|
||||
const { createMarketController } = await import("../src/content/market/index");
|
||||
@@ -4916,6 +4917,62 @@ describe("market-content-entry", () => {
|
||||
|
||||
expect(document.querySelector('[data-sces-favorite-row-action="button"]')).toBeNull();
|
||||
expect(document.querySelector('[data-plugin-export="button"]')).not.toBeNull();
|
||||
|
||||
shouldRejectRead = false;
|
||||
document.documentElement.setAttribute("data-test-page-index", "2");
|
||||
document.querySelector('[data-testid="action-cell-111"]')!.replaceChildren(
|
||||
document.createTextNode("下单")
|
||||
);
|
||||
observer.trigger();
|
||||
await waitForCondition(
|
||||
() =>
|
||||
document.querySelector('[data-sces-favorite-row-action="button"]')?.dataset
|
||||
.scesFavoriteState === "saved"
|
||||
);
|
||||
|
||||
expect(read).toHaveBeenCalledTimes(3);
|
||||
expect(document.querySelector('[data-sces-favorites-drawer="error"]')).toBeNull();
|
||||
});
|
||||
|
||||
test("settles the initial observer resync 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();
|
||||
let shouldScheduleInitialResync = true;
|
||||
repository.read = async () => {
|
||||
if (shouldScheduleInitialResync) {
|
||||
shouldScheduleInitialResync = false;
|
||||
document.querySelector('[data-plugin-toolbar="root"]')?.remove();
|
||||
observer.trigger();
|
||||
}
|
||||
return originalRead();
|
||||
};
|
||||
const buildCsv = vi.fn(() => "csv-output");
|
||||
|
||||
const { createMarketController } = await import("../src/content/market/index");
|
||||
const controller = trackController(createMarketController({
|
||||
buildCsv,
|
||||
document,
|
||||
favoritesRepository: repository,
|
||||
loadAuthorMetrics: async () => ({ success: false, reason: "request-failed" }),
|
||||
mutationObserverFactory: observer.factory,
|
||||
onCsvReady: vi.fn(),
|
||||
window
|
||||
}));
|
||||
|
||||
await controller.ready;
|
||||
|
||||
expect(document.querySelector('[data-plugin-toolbar="root"]')).not.toBeNull();
|
||||
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);
|
||||
});
|
||||
|
||||
test("keeps the friendly drawer error when a direct folder mutation has no message", async () => {
|
||||
|
||||
Reference in New Issue
Block a user