fix: label trending counts as downloads (#3334)

This commit is contained in:
Patrick Erichsen
2026-07-30 20:37:46 -07:00
committed by GitHub
parent bd95e24030
commit 29549947f6
4 changed files with 33 additions and 9 deletions
@@ -78,7 +78,7 @@ describe("HomeListingSection", () => {
fetchCanonicalTrendingPageMock.mockResolvedValue(canonicalPage([]));
});
it("defaults the homepage to Skills and canonical Trending with exact tab order", () => {
it("labels canonical Trending values as downloads without changing order or values", () => {
const first = makeTrending("first", "First Skill", 17, 9000);
const second = makeTrending("second", "Second Skill", 3, 8000);
render(<HomeListingSection initialListing={initialTrending([first, second])} />);
@@ -112,9 +112,16 @@ describe("HomeListingSection", () => {
).toEqual(["First Skill", "Second Skill"]);
expect(screen.getByText("17")).toBeTruthy();
expect(screen.getByText("3")).toBeTruthy();
expect(screen.getByText("24h downloads")).toBeTruthy();
expect(screen.getAllByLabelText("24-hour downloads")).toHaveLength(2);
expect(screen.queryByText("24h installs")).toBeNull();
expect(screen.queryByLabelText("24-hour installs")).toBeNull();
expect(screen.queryByText("9K")).toBeNull();
expect(screen.queryByText("8K")).toBeNull();
expect(screen.queryByText("skills.sh")).toBeNull();
fireEvent.click(screen.getByRole("button", { name: "Grid view" }));
expect(screen.getAllByLabelText("24-hour downloads")).toHaveLength(2);
});
it("hides unavailable Trending and falls back to the Featured feed", async () => {
+19 -2
View File
@@ -110,7 +110,7 @@ describe("SkillsIndex", () => {
expect(screen.queryByLabelText("Skill categories")).toBeNull();
});
it("renders canonical Trending rows in API order with only 24-hour installs", async () => {
it("labels canonical Trending rows as downloads without changing API order or values", async () => {
fetchCanonicalTrendingPageMock.mockResolvedValue(
canonicalPage([
makeTrending("first", "First Skill", 17, 9000),
@@ -120,7 +120,7 @@ describe("SkillsIndex", () => {
render(<SkillsIndex />);
expect(await screen.findByTitle("First Skill")).toBeTruthy();
expect(await screen.findByText("First Skill")).toBeTruthy();
const names = Array.from(
document.querySelectorAll(".skill-list-item-name"),
(node) => node.textContent,
@@ -128,12 +128,29 @@ describe("SkillsIndex", () => {
expect(names).toEqual(["First Skill", "Second Skill"]);
expect(screen.getByText("17")).toBeTruthy();
expect(screen.getByText("3")).toBeTruthy();
expect(screen.getByText("24h downloads")).toBeTruthy();
expect(screen.getAllByLabelText("24-hour downloads")).toHaveLength(2);
expect(screen.queryByText("24h installs")).toBeNull();
expect(screen.queryByLabelText("24-hour installs")).toBeNull();
expect(screen.queryByText("9K")).toBeNull();
expect(screen.queryByText("8K")).toBeNull();
expect(screen.queryByText("skills.sh")).toBeNull();
expect(screen.queryByText(/Not scanned by ClawHub/i)).toBeNull();
});
it("labels canonical Trending grid cards as downloads", async () => {
searchMock = { view: "grid" };
fetchCanonicalTrendingPageMock.mockResolvedValue(
canonicalPage([makeTrending("first", "First Skill", 17, 9000)]),
);
render(<SkillsIndex />);
expect(await screen.findByText("First Skill")).toBeTruthy();
expect(screen.getByLabelText("24-hour downloads").textContent).toContain("17");
expect(screen.queryByLabelText("24-hour installs")).toBeNull();
});
it("hides disabled Trending and falls back to the Featured feed", async () => {
fetchCatalogDiscoveryCapabilitiesMock.mockResolvedValue({
apiVersion: 0,
+3 -3
View File
@@ -220,7 +220,7 @@ function HomeListingSkillRow({ entry, showStats }: { entry: SkillPageEntry; show
</p>
</div>
{typeof item.metrics.trending24hInstalls === "number" ? (
<div className="home-v2-listing-row-stats" aria-label="24-hour installs">
<div className="home-v2-listing-row-stats" aria-label="24-hour downloads">
<span>
<Download size={13} aria-hidden="true" />
{formatCompactStat(item.metrics.trending24hInstalls)}
@@ -334,7 +334,7 @@ function HomeListingSkillCard({ entry, showStats }: { entry: SkillPageEntry; sho
{truncateText(item.summary || "Agent-ready skill pack.", 80)}
</p>
{typeof item.metrics.trending24hInstalls === "number" ? (
<div className="home-v2-listing-card-stats" aria-label="24-hour installs">
<div className="home-v2-listing-card-stats" aria-label="24-hour downloads">
<span>
<Download size={13} aria-hidden="true" />
{formatCompactStat(item.metrics.trending24hInstalls)}
@@ -990,7 +990,7 @@ export function HomeListingSection({ initialListing = null }: HomeListingSection
{kind === "skills" ? "Skill" : "Plugin"}
</span>
{kind === "skills" && tab === "trending" ? (
<span className="home-v2-listing-head-stat">24h installs</span>
<span className="home-v2-listing-head-stat">24h downloads</span>
) : showSkillStats ? (
<span className="home-v2-listing-head-stat">Popularity</span>
) : null}
+3 -3
View File
@@ -58,7 +58,7 @@ function TrendingSkillListItem({ item }: { item: TrendingSkillListEntry }) {
<p className="skill-list-item-summary">{truncateText(trending.summary, 80)}</p>
) : null}
</div>
<div className="skill-list-item-meta" aria-label="24-hour installs">
<div className="skill-list-item-meta" aria-label="24-hour downloads">
{typeof trending.metrics.trending24hInstalls === "number" ? (
<span className="skill-list-item-meta-item">
<Download size={14} aria-hidden="true" />
@@ -95,7 +95,7 @@ function TrendingSkillCard({ item }: { item: TrendingSkillListEntry }) {
</p>
) : null}
{typeof trending.metrics.trending24hInstalls === "number" ? (
<div className="skill-card-grid-meta" aria-label="24-hour installs">
<div className="skill-card-grid-meta" aria-label="24-hour downloads">
<span>
<Download size={14} aria-hidden="true" />
{formatCompactStat(trending.metrics.trending24hInstalls)}
@@ -275,7 +275,7 @@ export function SkillsResults({
<span className="browse-list-head-label">Skill</span>
{showTrendingLayout ? null : <span className="browse-list-head-label">Category</span>}
<span className="browse-list-head-label browse-list-head-stat">
{showTrendingLayout ? "24h installs" : "Popularity"}
{showTrendingLayout ? "24h downloads" : "Popularity"}
</span>
</div>
<div className="results-list">