mirror of
https://github.com/openclaw/clawhub.git
synced 2026-08-14 00:47:57 +00:00
fix: default unavailable trending to featured (#3319)
This commit is contained in:
@@ -117,7 +117,7 @@ describe("HomeListingSection", () => {
|
||||
expect(screen.queryByText("skills.sh")).toBeNull();
|
||||
});
|
||||
|
||||
it("hides unavailable Trending and falls back to the native New feed", async () => {
|
||||
it("hides unavailable Trending and falls back to the Featured feed", async () => {
|
||||
render(<HomeListingSection initialListing={initialTrending([], false, "unavailable")} />);
|
||||
|
||||
expect(screen.queryByRole("tab", { name: "Trending" })).toBeNull();
|
||||
@@ -126,12 +126,14 @@ describe("HomeListingSection", () => {
|
||||
"Official",
|
||||
"New",
|
||||
]);
|
||||
expect(screen.getByRole("tab", { name: "New" }).getAttribute("aria-selected")).toBe("true");
|
||||
expect(screen.getByRole("tab", { name: "Featured" }).getAttribute("aria-selected")).toBe(
|
||||
"true",
|
||||
);
|
||||
expect(screen.queryByText("24-hour Trending unavailable")).toBeNull();
|
||||
await waitFor(() =>
|
||||
expect(convexQueryMock).toHaveBeenCalledWith(
|
||||
"skills:listPublicPageV4",
|
||||
expect.objectContaining({ sort: "newest", createdAfter: expect.any(Number) }),
|
||||
expect.objectContaining({ highlightedOnly: true }),
|
||||
),
|
||||
);
|
||||
});
|
||||
@@ -150,12 +152,26 @@ describe("HomeListingSection", () => {
|
||||
"Official",
|
||||
"New",
|
||||
]);
|
||||
expect(screen.getByRole("tab", { name: "New" }).getAttribute("aria-selected")).toBe("true");
|
||||
expect(screen.getByRole("tab", { name: "Featured" }).getAttribute("aria-selected")).toBe(
|
||||
"true",
|
||||
);
|
||||
expect(screen.queryByText("24-hour Trending unavailable")).toBeNull();
|
||||
expect(fetchCanonicalTrendingPageMock).not.toHaveBeenCalled();
|
||||
expect(convexQueryMock).toHaveBeenCalledWith(
|
||||
"skills:listPublicPageV4",
|
||||
expect.objectContaining({ sort: "newest", createdAfter: expect.any(Number) }),
|
||||
expect.objectContaining({ highlightedOnly: true }),
|
||||
);
|
||||
});
|
||||
|
||||
it("returns from Plugins to Featured when Trending is unavailable", async () => {
|
||||
render(<HomeListingSection initialListing={initialTrending([], false, "unavailable")} />);
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: "Plugins" }));
|
||||
expect(screen.getByRole("tab", { name: "New" }).getAttribute("aria-selected")).toBe("true");
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: "Skills" }));
|
||||
expect(screen.getByRole("tab", { name: "Featured" }).getAttribute("aria-selected")).toBe(
|
||||
"true",
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ describe("SkillsIndex", () => {
|
||||
expect(screen.queryByText(/Not scanned by ClawHub/i)).toBeNull();
|
||||
});
|
||||
|
||||
it("hides disabled Trending and falls back to the native New feed", async () => {
|
||||
it("hides disabled Trending and falls back to the Featured feed", async () => {
|
||||
fetchCatalogDiscoveryCapabilitiesMock.mockResolvedValue({
|
||||
apiVersion: 0,
|
||||
canonicalTrendingEnabled: false,
|
||||
@@ -144,10 +144,14 @@ describe("SkillsIndex", () => {
|
||||
|
||||
await waitFor(() => expect(screen.queryByRole("radio", { name: "Trending" })).toBeNull());
|
||||
expect(tabLabels()).toEqual(["Featured", "Official", "New"]);
|
||||
expect(screen.getByRole("radio", { name: "New" }).getAttribute("aria-checked")).toBe("true");
|
||||
expect(screen.getByRole("radio", { name: "Featured" }).getAttribute("aria-checked")).toBe(
|
||||
"true",
|
||||
);
|
||||
expect(screen.queryByText("24-hour Trending unavailable")).toBeNull();
|
||||
expect(fetchCanonicalTrendingPageMock).not.toHaveBeenCalled();
|
||||
expect(convexHttpMock.query).toHaveBeenCalled();
|
||||
await waitFor(() =>
|
||||
expect(getLastListPageArgs()).toEqual(expect.objectContaining({ highlightedOnly: true })),
|
||||
);
|
||||
});
|
||||
|
||||
it("hides stale Trending and falls back without a legacy retry", async () => {
|
||||
@@ -157,9 +161,13 @@ describe("SkillsIndex", () => {
|
||||
|
||||
await waitFor(() => expect(screen.queryByRole("radio", { name: "Trending" })).toBeNull());
|
||||
expect(tabLabels()).toEqual(["Featured", "Official", "New"]);
|
||||
expect(screen.getByRole("radio", { name: "New" }).getAttribute("aria-checked")).toBe("true");
|
||||
expect(screen.getByRole("radio", { name: "Featured" }).getAttribute("aria-checked")).toBe(
|
||||
"true",
|
||||
);
|
||||
expect(screen.queryByText("24-hour Trending unavailable")).toBeNull();
|
||||
expect(convexHttpMock.query).toHaveBeenCalled();
|
||||
await waitFor(() =>
|
||||
expect(getLastListPageArgs()).toEqual(expect.objectContaining({ highlightedOnly: true })),
|
||||
);
|
||||
});
|
||||
|
||||
it("labels an empty canonical 24-hour window honestly", async () => {
|
||||
|
||||
@@ -471,7 +471,7 @@ export function HomeListingSection({ initialListing = null }: HomeListingSection
|
||||
const [kind, setKind] = useState<ListingKind>(initialListing?.kind ?? "skills");
|
||||
const initialTab =
|
||||
initialListing?.kind === "skills" && initialListing.trendingState === "unavailable"
|
||||
? "new"
|
||||
? "featured"
|
||||
: (initialListing?.tab ?? "trending");
|
||||
const [tab, setTab] = useState<ListingTab>(initialTab);
|
||||
const [view, setView] = useState<ListingView>("list");
|
||||
@@ -577,7 +577,7 @@ export function HomeListingSection({ initialListing = null }: HomeListingSection
|
||||
if (tab === "trending") {
|
||||
const unavailable = cached.trendingState === "unavailable";
|
||||
setCanonicalTrendingUnavailable(unavailable);
|
||||
if (unavailable) setTab("new");
|
||||
if (unavailable) setTab("featured");
|
||||
}
|
||||
} else {
|
||||
setPlugins(cached.items);
|
||||
@@ -616,7 +616,7 @@ export function HomeListingSection({ initialListing = null }: HomeListingSection
|
||||
if (tab === "trending") {
|
||||
const unavailable = result.trendingState === "unavailable";
|
||||
setCanonicalTrendingUnavailable(unavailable);
|
||||
if (unavailable) setTab("new");
|
||||
if (unavailable) setTab("featured");
|
||||
}
|
||||
setListingHasMore(result.hasMore);
|
||||
setStatus("idle");
|
||||
@@ -795,7 +795,9 @@ export function HomeListingSection({ initialListing = null }: HomeListingSection
|
||||
if (nextKind === kind) return;
|
||||
setKind(nextKind);
|
||||
setCategorySlugs([]);
|
||||
setTab(nextKind === "skills" && !canonicalTrendingUnavailable ? "trending" : "new");
|
||||
setTab(
|
||||
nextKind === "skills" ? (canonicalTrendingUnavailable ? "featured" : "trending") : "new",
|
||||
);
|
||||
};
|
||||
|
||||
const removeCategory = (slug: string) => {
|
||||
|
||||
@@ -130,7 +130,7 @@ export function useSkillsBrowseModel({
|
||||
const requestedCatalogTab = normalizeSkillsCatalogTab(search.tab, search);
|
||||
const catalogTab =
|
||||
requestedCatalogTab === "trending" && canonicalTrendingUnavailable
|
||||
? "new"
|
||||
? "featured"
|
||||
: requestedCatalogTab;
|
||||
const requestedSort = hasQuery
|
||||
? search.sort === "default"
|
||||
|
||||
Reference in New Issue
Block a user