Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/andreijiroh-dev/gh-readme-stats-patches. gh-readme-stats-patches.vercel.app
Something went wrong. Try again.
17 kB · 472 lines
JavaScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473import { describe, expect, it } from "@jest/globals";import { getByTestId, queryAllByTestId, queryByTestId,} from "@testing-library/dom";import "@testing-library/jest-dom";import { cssToObject } from "@uppercod/css-to-object";import { renderStatsCard } from "../src/cards/stats.js";import { CustomError } from "../src/common/error.js";import { themes } from "../themes/index.js";
const stats = { name: "Anurag Hazra", totalStars: 100, totalCommits: 200, totalIssues: 300, totalPRs: 400, totalPRsMerged: 320, mergedPRsPercentage: 80, totalReviews: 50, totalDiscussionsStarted: 10, totalDiscussionsAnswered: 50, contributedTo: 500, rank: { level: "A+", percentile: 40 },};
describe("Test renderStatsCard", () => { it("should render correctly", () => { document.body.innerHTML = renderStatsCard(stats);
expect(document.getElementsByClassName("header")[0].textContent).toBe( "Anurag Hazra's GitHub Stats", );
expect( document.body.getElementsByTagName("svg")[0].getAttribute("height"), ).toBe("195"); expect(getByTestId(document.body, "stars").textContent).toBe("100"); expect(getByTestId(document.body, "commits").textContent).toBe("200"); expect(getByTestId(document.body, "issues").textContent).toBe("300"); expect(getByTestId(document.body, "prs").textContent).toBe("400"); expect(getByTestId(document.body, "contribs").textContent).toBe("500"); expect(queryByTestId(document.body, "card-bg")).toBeInTheDocument(); expect(queryByTestId(document.body, "rank-circle")).toBeInTheDocument();
// Default hidden stats expect(queryByTestId(document.body, "reviews")).not.toBeInTheDocument(); expect( queryByTestId(document.body, "discussions_started"), ).not.toBeInTheDocument(); expect( queryByTestId(document.body, "discussions_answered"), ).not.toBeInTheDocument(); expect(queryByTestId(document.body, "prs_merged")).not.toBeInTheDocument(); expect( queryByTestId(document.body, "prs_merged_percentage"), ).not.toBeInTheDocument(); });
it("should have proper name apostrophe", () => { document.body.innerHTML = renderStatsCard({ ...stats, name: "Anil Das" });
expect(document.getElementsByClassName("header")[0].textContent).toBe( "Anil Das' GitHub Stats", );
document.body.innerHTML = renderStatsCard({ ...stats, name: "Felix" });
expect(document.getElementsByClassName("header")[0].textContent).toBe( "Felix's GitHub Stats", ); });
it("should hide individual stats", () => { document.body.innerHTML = renderStatsCard(stats, { hide: ["issues", "prs", "contribs"], });
expect( document.body.getElementsByTagName("svg")[0].getAttribute("height"), ).toBe("150"); // height should be 150 because we clamped it.
expect(queryByTestId(document.body, "stars")).toBeDefined(); expect(queryByTestId(document.body, "commits")).toBeDefined(); expect(queryByTestId(document.body, "issues")).toBeNull(); expect(queryByTestId(document.body, "prs")).toBeNull(); expect(queryByTestId(document.body, "contribs")).toBeNull(); expect(queryByTestId(document.body, "reviews")).toBeNull(); expect(queryByTestId(document.body, "discussions_started")).toBeNull(); expect(queryByTestId(document.body, "discussions_answered")).toBeNull(); expect(queryByTestId(document.body, "prs_merged")).toBeNull(); expect(queryByTestId(document.body, "prs_merged_percentage")).toBeNull(); });
it("should show additional stats", () => { document.body.innerHTML = renderStatsCard(stats, { show: [ "reviews", "discussions_started", "discussions_answered", "prs_merged", "prs_merged_percentage", ], });
expect( document.body.getElementsByTagName("svg")[0].getAttribute("height"), ).toBe("320");
expect(queryByTestId(document.body, "stars")).toBeDefined(); expect(queryByTestId(document.body, "commits")).toBeDefined(); expect(queryByTestId(document.body, "issues")).toBeDefined(); expect(queryByTestId(document.body, "prs")).toBeDefined(); expect(queryByTestId(document.body, "contribs")).toBeDefined(); expect(queryByTestId(document.body, "reviews")).toBeDefined(); expect(queryByTestId(document.body, "discussions_started")).toBeDefined(); expect(queryByTestId(document.body, "discussions_answered")).toBeDefined(); expect(queryByTestId(document.body, "prs_merged")).toBeDefined(); expect(queryByTestId(document.body, "prs_merged_percentage")).toBeDefined(); });
it("should hide_rank", () => { document.body.innerHTML = renderStatsCard(stats, { hide_rank: true });
expect(queryByTestId(document.body, "rank-circle")).not.toBeInTheDocument(); });
it("should render with custom width set", () => { document.body.innerHTML = renderStatsCard(stats); expect(document.querySelector("svg")).toHaveAttribute("width", "450");
document.body.innerHTML = renderStatsCard(stats, { card_width: 500 }); expect(document.querySelector("svg")).toHaveAttribute("width", "500"); });
it("should render with custom width set and limit minimum width", () => { document.body.innerHTML = renderStatsCard(stats, { card_width: 1 }); expect(document.querySelector("svg")).toHaveAttribute("width", "420");
// Test default minimum card width without rank circle. document.body.innerHTML = renderStatsCard(stats, { card_width: 1, hide_rank: true, }); expect(document.querySelector("svg")).toHaveAttribute( "width", "305.81250000000006", );
// Test minimum card width with rank and icons. document.body.innerHTML = renderStatsCard(stats, { card_width: 1, hide_rank: true, show_icons: true, }); expect(document.querySelector("svg")).toHaveAttribute( "width", "322.81250000000006", );
// Test minimum card width with icons but without rank. document.body.innerHTML = renderStatsCard(stats, { card_width: 1, hide_rank: false, show_icons: true, }); expect(document.querySelector("svg")).toHaveAttribute("width", "437");
// Test minimum card width without icons or rank. document.body.innerHTML = renderStatsCard(stats, { card_width: 1, hide_rank: false, show_icons: false, }); expect(document.querySelector("svg")).toHaveAttribute("width", "420"); });
it("should render default colors properly", () => { document.body.innerHTML = renderStatsCard(stats);
const styleTag = document.querySelector("style"); const stylesObject = cssToObject(styleTag.textContent);
const headerClassStyles = stylesObject[":host"][".header "]; const statClassStyles = stylesObject[":host"][".stat "]; const iconClassStyles = stylesObject[":host"][".icon "];
expect(headerClassStyles.fill.trim()).toBe("#2f80ed"); expect(statClassStyles.fill.trim()).toBe("#434d58"); expect(iconClassStyles.fill.trim()).toBe("#4c71f2"); expect(queryByTestId(document.body, "card-bg")).toHaveAttribute( "fill", "#fffefe", ); });
it("should render custom colors properly", () => { const customColors = { title_color: "5a0", icon_color: "1b998b", text_color: "9991", bg_color: "252525", };
document.body.innerHTML = renderStatsCard(stats, { ...customColors });
const styleTag = document.querySelector("style"); const stylesObject = cssToObject(styleTag.innerHTML);
const headerClassStyles = stylesObject[":host"][".header "]; const statClassStyles = stylesObject[":host"][".stat "]; const iconClassStyles = stylesObject[":host"][".icon "];
expect(headerClassStyles.fill.trim()).toBe(`#${customColors.title_color}`); expect(statClassStyles.fill.trim()).toBe(`#${customColors.text_color}`); expect(iconClassStyles.fill.trim()).toBe(`#${customColors.icon_color}`); expect(queryByTestId(document.body, "card-bg")).toHaveAttribute( "fill", "#252525", ); });
it("should render custom colors with themes", () => { document.body.innerHTML = renderStatsCard(stats, { title_color: "5a0", theme: "radical", });
const styleTag = document.querySelector("style"); const stylesObject = cssToObject(styleTag.innerHTML);
const headerClassStyles = stylesObject[":host"][".header "]; const statClassStyles = stylesObject[":host"][".stat "]; const iconClassStyles = stylesObject[":host"][".icon "];
expect(headerClassStyles.fill.trim()).toBe("#5a0"); expect(statClassStyles.fill.trim()).toBe(`#${themes.radical.text_color}`); expect(iconClassStyles.fill.trim()).toBe(`#${themes.radical.icon_color}`); expect(queryByTestId(document.body, "card-bg")).toHaveAttribute( "fill", `#${themes.radical.bg_color}`, ); });
it("should render with all the themes", () => { Object.keys(themes).forEach((name) => { document.body.innerHTML = renderStatsCard(stats, { theme: name, });
const styleTag = document.querySelector("style"); const stylesObject = cssToObject(styleTag.innerHTML);
const headerClassStyles = stylesObject[":host"][".header "]; const statClassStyles = stylesObject[":host"][".stat "]; const iconClassStyles = stylesObject[":host"][".icon "];
expect(headerClassStyles.fill.trim()).toBe( `#${themes[name].title_color}`, ); expect(statClassStyles.fill.trim()).toBe(`#${themes[name].text_color}`); expect(iconClassStyles.fill.trim()).toBe(`#${themes[name].icon_color}`); const backgroundElement = queryByTestId(document.body, "card-bg"); const backgroundElementFill = backgroundElement.getAttribute("fill"); expect([`#${themes[name].bg_color}`, "url(#gradient)"]).toContain( backgroundElementFill, ); }); });
it("should render custom colors with themes and fallback to default colors if invalid", () => { document.body.innerHTML = renderStatsCard(stats, { title_color: "invalid color", text_color: "invalid color", theme: "radical", });
const styleTag = document.querySelector("style"); const stylesObject = cssToObject(styleTag.innerHTML);
const headerClassStyles = stylesObject[":host"][".header "]; const statClassStyles = stylesObject[":host"][".stat "]; const iconClassStyles = stylesObject[":host"][".icon "];
expect(headerClassStyles.fill.trim()).toBe( `#${themes.default.title_color}`, ); expect(statClassStyles.fill.trim()).toBe(`#${themes.default.text_color}`); expect(iconClassStyles.fill.trim()).toBe(`#${themes.radical.icon_color}`); expect(queryByTestId(document.body, "card-bg")).toHaveAttribute( "fill", `#${themes.radical.bg_color}`, ); });
it("should render custom ring_color properly", () => { const customColors = { title_color: "5a0", ring_color: "0000ff", icon_color: "1b998b", text_color: "9991", bg_color: "252525", };
document.body.innerHTML = renderStatsCard(stats, { ...customColors });
const styleTag = document.querySelector("style"); const stylesObject = cssToObject(styleTag.innerHTML);
const headerClassStyles = stylesObject[":host"][".header "]; const statClassStyles = stylesObject[":host"][".stat "]; const iconClassStyles = stylesObject[":host"][".icon "]; const rankCircleStyles = stylesObject[":host"][".rank-circle "]; const rankCircleRimStyles = stylesObject[":host"][".rank-circle-rim "];
expect(headerClassStyles.fill.trim()).toBe(`#${customColors.title_color}`); expect(statClassStyles.fill.trim()).toBe(`#${customColors.text_color}`); expect(iconClassStyles.fill.trim()).toBe(`#${customColors.icon_color}`); expect(rankCircleStyles.stroke.trim()).toBe(`#${customColors.ring_color}`); expect(rankCircleRimStyles.stroke.trim()).toBe( `#${customColors.ring_color}`, ); expect(queryByTestId(document.body, "card-bg")).toHaveAttribute( "fill", "#252525", ); });
it("should render icons correctly", () => { document.body.innerHTML = renderStatsCard(stats, { show_icons: true, });
expect(queryAllByTestId(document.body, "icon")[0]).toBeDefined(); expect(queryByTestId(document.body, "stars")).toBeDefined(); expect( queryByTestId(document.body, "stars").previousElementSibling, // the label ).toHaveAttribute("x", "25"); });
it("should not have icons if show_icons is false", () => { document.body.innerHTML = renderStatsCard(stats, { show_icons: false });
expect(queryAllByTestId(document.body, "icon")[0]).not.toBeDefined(); expect(queryByTestId(document.body, "stars")).toBeDefined(); expect( queryByTestId(document.body, "stars").previousElementSibling, // the label ).not.toHaveAttribute("x"); });
it("should auto resize if hide_rank is true", () => { document.body.innerHTML = renderStatsCard(stats, { hide_rank: true, });
expect( document.body.getElementsByTagName("svg")[0].getAttribute("width"), ).toBe("305.81250000000006"); });
it("should auto resize if hide_rank is true & custom_title is set", () => { document.body.innerHTML = renderStatsCard(stats, { hide_rank: true, custom_title: "Hello world", });
expect( document.body.getElementsByTagName("svg")[0].getAttribute("width"), ).toBe("287"); });
it("should render translations", () => { document.body.innerHTML = renderStatsCard(stats, { locale: "cn" }); expect(document.getElementsByClassName("header")[0].textContent).toBe( "Anurag Hazra 的 GitHub 统计数据", ); expect( document.querySelector( 'g[transform="translate(0, 0)"]>.stagger>.stat.bold', ).textContent, ).toMatchInlineSnapshot(`"获标星数:"`); expect( document.querySelector( 'g[transform="translate(0, 25)"]>.stagger>.stat.bold', ).textContent, ).toMatchInlineSnapshot(`"累计提交总数 (去年):"`); expect( document.querySelector( 'g[transform="translate(0, 50)"]>.stagger>.stat.bold', ).textContent, ).toMatchInlineSnapshot(`"发起的 PR 总数:"`); expect( document.querySelector( 'g[transform="translate(0, 75)"]>.stagger>.stat.bold', ).textContent, ).toMatchInlineSnapshot(`"提出的 issue 总数:"`); expect( document.querySelector( 'g[transform="translate(0, 100)"]>.stagger>.stat.bold', ).textContent, ).toMatchInlineSnapshot(`"贡献的项目数(去年):"`); });
it("should render without rounding", () => { document.body.innerHTML = renderStatsCard(stats, { border_radius: "0" }); expect(document.querySelector("rect")).toHaveAttribute("rx", "0"); document.body.innerHTML = renderStatsCard(stats, {}); expect(document.querySelector("rect")).toHaveAttribute("rx", "4.5"); });
it("should shorten values", () => { stats["totalCommits"] = 1999;
document.body.innerHTML = renderStatsCard(stats); expect(getByTestId(document.body, "commits").textContent).toBe("2k"); document.body.innerHTML = renderStatsCard(stats, { number_format: "long" }); expect(getByTestId(document.body, "commits").textContent).toBe("1999"); document.body.innerHTML = renderStatsCard(stats, { number_precision: 2 }); expect(getByTestId(document.body, "commits").textContent).toBe("2.00k"); document.body.innerHTML = renderStatsCard(stats, { number_format: "long", number_precision: 2, }); expect(getByTestId(document.body, "commits").textContent).toBe("1999"); });
it("should render default rank icon with level A+", () => { document.body.innerHTML = renderStatsCard(stats, { rank_icon: "default", }); expect(queryByTestId(document.body, "level-rank-icon")).toBeDefined(); expect( queryByTestId(document.body, "level-rank-icon").textContent.trim(), ).toBe("A+"); });
it("should render github rank icon", () => { document.body.innerHTML = renderStatsCard(stats, { rank_icon: "github", }); expect(queryByTestId(document.body, "github-rank-icon")).toBeDefined(); });
it("should show the rank percentile", () => { document.body.innerHTML = renderStatsCard(stats, { rank_icon: "percentile", }); expect(queryByTestId(document.body, "percentile-top-header")).toBeDefined(); expect( queryByTestId(document.body, "percentile-top-header").textContent.trim(), ).toBe("Top"); expect(queryByTestId(document.body, "rank-percentile-text")).toBeDefined(); expect( queryByTestId(document.body, "percentile-rank-value").textContent.trim(), ).toBe(stats.rank.percentile.toFixed(1) + "%"); });
it("should throw error if all stats and rank icon are hidden", () => { expect(() => renderStatsCard(stats, { hide: ["stars", "commits", "prs", "issues", "contribs"], hide_rank: true, }), ).toThrow( new CustomError( "Could not render stats card.", "Either stats or rank are required.", ), ); });});