diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 9375a5e172ab1..5ed7d3c969ff8 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -5,6 +5,7 @@ title: "" labels: "" assignees: "" --- + **Describe the bug** A clear and concise description of what the bug is. @@ -18,9 +19,8 @@ If applicable, add screenshots to help explain your problem. **Additional context** Add any other context about the problem here. - diff --git a/.github/workflows/empty-issues-closer.yaml b/.github/workflows/empty-issues-closer.yaml new file mode 100644 index 0000000000000..5f050fe067abc --- /dev/null +++ b/.github/workflows/empty-issues-closer.yaml @@ -0,0 +1,30 @@ +name: Close empty issues and templates +on: + issues: + types: + - reopened + - opened + - edited + +jobs: + closeEmptyIssuesAndTemplates: + name: Close empty issues + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 # NOTE: Retrieve issue templates. + - name: Run empty issues closer action + uses: rickstaa/empty-issues-closer-action@v1 + env: + github_token: ${{ secrets.GITHUB_TOKEN }} + with: + close_comment: + Closing this issue because it appears to be empty. Please update the + issue for it to be reopened. + open_comment: + Reopening this issue because the author provided more information. + check_templates: true + template_close_comment: + Closing this issue since the issue template was not filled in. + Please provide us with more information to have this issue reopened. + template_open_comment: + Reopening this issue because the author provided more information. diff --git a/.github/workflows/preview-theme.yml b/.github/workflows/preview-theme.yml index a1c9b06592fe8..85f7d29593d1d 100644 --- a/.github/workflows/preview-theme.yml +++ b/.github/workflows/preview-theme.yml @@ -6,9 +6,9 @@ on: branches: - master - theme-preview-script - - "themes/index.js" paths: - - 'themes/**' + - 'themes/index.js' + - 'scripts/preview-theme.js' jobs: build: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 89df34e6006e6..0911168f33754 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,5 +25,9 @@ jobs: npm install npm run test + - name: Run Prettier + run: | + npm run format:check + - name: Code Coverage uses: codecov/codecov-action@v1 diff --git a/.github/workflows/top-issues-dashboard.yml b/.github/workflows/top-issues-dashboard.yml new file mode 100644 index 0000000000000..a9fca7f3e2787 --- /dev/null +++ b/.github/workflows/top-issues-dashboard.yml @@ -0,0 +1,22 @@ +name: Update top issues dashboard +on: + schedule: + - cron: "0 0 */7 * *" + +jobs: + showAndLabelTopIssues: + name: Update top issues Dashboard. + runs-on: ubuntu-latest + steps: + - name: Run top issues action + uses: rickstaa/top-issues-action@v1 + env: + github_token: ${{ secrets.GITHUB_TOKEN }} + with: + label: false + dashboard: true + dashboard_show_total_reactions: true + top_issues: true + top_bugs: true + top_features: true + top_pull_requests: true diff --git a/LICENSE b/LICENSE index 83b114d1e2ed6..14d9ba34bcbdc 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 Anurag Hazra +Copyright (c) 2020 Anurag Hazra Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/api/index.js b/api/index.js index 6563dbcc8f9e1..2315dddaa302d 100644 --- a/api/index.js +++ b/api/index.js @@ -17,6 +17,7 @@ module.exports = async (req, res) => { hide, hide_title, hide_border, + card_width, hide_rank, show_icons, count_private, @@ -25,9 +26,11 @@ module.exports = async (req, res) => { title_color, icon_color, text_color, + text_bold, bg_color, theme, cache_seconds, + exclude_repo, custom_title, locale, disable_animations, @@ -49,6 +52,7 @@ module.exports = async (req, res) => { username, parseBoolean(count_private), parseBoolean(include_all_commits), + parseArray(exclude_repo), ); const cacheSeconds = clampValue( @@ -65,12 +69,14 @@ module.exports = async (req, res) => { show_icons: parseBoolean(show_icons), hide_title: parseBoolean(hide_title), hide_border: parseBoolean(hide_border), + card_width: parseInt(card_width, 10), hide_rank: parseBoolean(hide_rank), include_all_commits: parseBoolean(include_all_commits), line_height, title_color, icon_color, text_color, + text_bold: parseBoolean(text_bold), bg_color, theme, custom_title, diff --git a/package.json b/package.json index e2f13552e80ad..be9e43541aae0 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,9 @@ "test:watch": "jest --watch", "theme-readme-gen": "node scripts/generate-theme-doc", "preview-theme": "node scripts/preview-theme", - "generate-langs-json": "node scripts/generate-langs-json" + "generate-langs-json": "node scripts/generate-langs-json", + "format": "./node_modules/.bin/prettier --write .", + "format:check": "./node_modules/.bin/prettier --check ." }, "author": "Anurag Hazra", "license": "MIT", diff --git a/readme.md b/readme.md index ec31fdfc128ce..3ef407248312e 100644 --- a/readme.md +++ b/readme.md @@ -67,12 +67,12 @@ Give india logo -Are you considering supporting the project by donating? Please DON'T!! +Are you considering supporting the project by donating? Please DON'T!! -Instead, Help India fight the 2nd deadly wave of COVID-19. -Thousands of people are dying in India because of a lack of Oxygen & also COVID-related infrastructure. +Instead, Help India fight the 2nd deadly wave of COVID-19. +Thousands of people are dying in India because of a lack of Oxygen & also COVID-related infrastructure. -Visit [https://indiafightscorona.giveindia.org](https://indiafightscorona.giveindia.org) and make a small donation to help us fight COVID and overcome this crisis. +Visit [https://indiafightscorona.giveindia.org](https://indiafightscorona.giveindia.org) and make a small donation to help us fight COVID and overcome this crisis. A small donation goes a long way. :heart:

@@ -169,9 +169,9 @@ You can customize the appearance of your `Stats Card` or `Repo Card` however you - `theme` - name of the theme, choose from [all available themes](./themes/README.md) - `cache_seconds` - set the cache header manually _(min: 7200, max: 86400)_ - `locale` - set the language in the card _(e.g. cn, de, es, etc.)_ -- `border_radius` - Corner rounding on the card_ +- `border_radius` - Corner rounding on the card -> Note: The minimum of cache_seconds is currently 4 hours as a temporary fix for PATs exhaustion. +> Note: The minimum of cache_seconds is currently 4 hours as a temporary fix for PATs exhaustion. ##### Gradient in bg_color @@ -187,12 +187,15 @@ You can provide multiple comma-separated values in the bg_color option to render - `hide` - Hides the [specified items](#hiding-individual-stats) from stats _(Comma-separated values)_ - `hide_title` - _(boolean)_ +- `card_width` - Set the card's width manually _(number)_ - `hide_rank` - _(boolean)_ hides the rank and automatically resizes the card width - `show_icons` - _(boolean)_ - `include_all_commits` - Count total commits instead of just the current year commits _(boolean)_ - `count_private` - Count private commits _(boolean)_ - `line_height` - Sets the line-height between text _(number)_ +- `exclude_repo` - Exclude stars from specified repositories _(Comma-separated values)_ - `custom_title` - Sets a custom title for the card +- `text_bold` - Use bold text _(boolean)_ - `disable_animations` - Disables all animations in the card _(boolean)_ #### Repo Card Exclusive Options: @@ -451,3 +454,4 @@ Thanks! :heart: Contributions are welcome! <3 Made with :heart: and JavaScript. + diff --git a/scripts/generate-langs-json.js b/scripts/generate-langs-json.js index 0705080d9c47d..bd210a3c53fe9 100644 --- a/scripts/generate-langs-json.js +++ b/scripts/generate-langs-json.js @@ -1,26 +1,30 @@ -const fs = require('fs'); -const jsYaml = require('js-yaml'); -const axios = require('axios'); +const fs = require("fs"); +const jsYaml = require("js-yaml"); +const axios = require("axios"); -const LANGS_FILEPATH = "./src/common/languageColors.json" +const LANGS_FILEPATH = "./src/common/languageColors.json"; //Retrieve languages from github linguist repository yaml file //@ts-ignore -axios.get("https://raw.githubusercontent.com/github/linguist/master/lib/linguist/languages.yml") -.then((response) => { +axios + .get( + "https://raw.githubusercontent.com/github/linguist/master/lib/linguist/languages.yml", + ) + .then((response) => { + //and convert them to a JS Object + const languages = jsYaml.load(response.data); - //and convert them to a JS Object - const languages = jsYaml.load(response.data); + const languageColors = {}; - const languageColors = {}; + //Filter only language colors from the whole file + Object.keys(languages).forEach((lang) => { + languageColors[lang] = languages[lang].color; + }); - //Filter only language colors from the whole file - Object.keys(languages).forEach((lang) => { - languageColors[lang] = languages[lang].color; + //Debug Print + //console.dir(languageColors); + fs.writeFileSync( + LANGS_FILEPATH, + JSON.stringify(languageColors, null, " "), + ); }); - - //Debug Print - //console.dir(languageColors); - fs.writeFileSync(LANGS_FILEPATH, JSON.stringify(languageColors, null, ' ')); - -}); diff --git a/src/calculateRank.js b/src/calculateRank.js index 76909d09547cd..742b9ab17509d 100644 --- a/src/calculateRank.js +++ b/src/calculateRank.js @@ -63,29 +63,13 @@ function calculateRank({ const normalizedScore = normalcdf(score, TOTAL_VALUES, ALL_OFFSETS) * 100; - let level = ""; - - if (normalizedScore < RANK_S_VALUE) { - level = "S+"; - } - if ( - normalizedScore >= RANK_S_VALUE && - normalizedScore < RANK_DOUBLE_A_VALUE - ) { - level = "S"; - } - if ( - normalizedScore >= RANK_DOUBLE_A_VALUE && - normalizedScore < RANK_A2_VALUE - ) { - level = "A++"; - } - if (normalizedScore >= RANK_A2_VALUE && normalizedScore < RANK_A3_VALUE) { - level = "A+"; - } - if (normalizedScore >= RANK_A3_VALUE && normalizedScore < RANK_B_VALUE) { - level = "B+"; - } + const level = (() => { + if (normalizedScore < RANK_S_VALUE) return "S+"; + if (normalizedScore < RANK_DOUBLE_A_VALUE) return "S"; + if (normalizedScore < RANK_A2_VALUE) return "A++"; + if (normalizedScore < RANK_A3_VALUE) return "A+"; + return "B+"; + })(); return { level, score: normalizedScore }; } diff --git a/src/cards/repo-card.js b/src/cards/repo-card.js index bb5c178affbdf..034ee1f6cdf79 100644 --- a/src/cards/repo-card.js +++ b/src/cards/repo-card.js @@ -67,8 +67,8 @@ const iconWithLabel = (icon, label, testid) => { }; /** - * @param {import('../fetchers/types').RepositoryData} repo - * @param {Partial} options + * @param {import('../fetchers/types').RepositoryData} repo + * @param {Partial} options * @returns {string} */ const renderRepoCard = (repo, options = {}) => { @@ -167,11 +167,11 @@ const renderRepoCard = (repo, options = {}) => { return card.render(` ${ isTemplate - // @ts-ignore - ? getBadgeSVG(i18n.t("repocard.template"), colors.textColor) + ? // @ts-ignore + getBadgeSVG(i18n.t("repocard.template"), colors.textColor) : isArchived - // @ts-ignore - ? getBadgeSVG(i18n.t("repocard.archived"), colors.textColor) + ? // @ts-ignore + getBadgeSVG(i18n.t("repocard.archived"), colors.textColor) : "" } diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js index 9db456236a7fe..30056b8526af6 100644 --- a/src/cards/stats-card.js +++ b/src/cards/stats-card.js @@ -20,6 +20,7 @@ const createTextNode = ({ index, showIcons, shiftValuePos, + bold, }) => { const kValue = kFormatter(value); const staggerDelay = (index + 3) * 150; @@ -35,11 +36,13 @@ const createTextNode = ({ return ` ${iconSvg} - ${label}: - ${label}: + ${kValue} @@ -66,12 +69,14 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => { show_icons = false, hide_title = false, hide_border = false, + card_width, hide_rank = false, include_all_commits = false, line_height = 25, title_color, icon_color, text_color, + text_bold = true, bg_color, theme = "default", custom_title, @@ -164,6 +169,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => { showIcons: show_icons, shiftValuePos: (!include_all_commits ? 50 : 35) + (isLongLocale ? 50 : 0), + bold: text_bold, }), ); @@ -174,26 +180,6 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => { hide_rank ? 0 : 150, ); - // Conditionally rendered elements - const rankCircle = hide_rank - ? "" - : ` - - - - - ${rank.level} - - - `; - // the better user's score the the rank will be closer to zero so // subtracting 100 to get the progress in 100% const progress = 100 - rank.score; @@ -209,13 +195,20 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => { return measureText(custom_title ? custom_title : i18n.t("statcard.title")); }; - const width = hide_rank - ? clampValue( - 50 /* padding */ + calculateTextWidth() * 2, - 270 /* min */, - Infinity, - ) - : 495; + /* + When hide_rank=true, the minimum card width is 270 px + the title length and padding. + When hide_rank=false, the minimum card_width is 340 px + the icon width (if show_icons=true). + Numbers are picked by looking at existing dimensions on production. + */ + const iconWidth = show_icons ? 16 : 0; + const minCardWidth = hide_rank + ? clampValue(50 /* padding */ + calculateTextWidth() * 2, 270, Infinity) + : 340 + iconWidth; + const defaultCardWidth = hide_rank ? 270 : 495; + let width = isNaN(card_width) ? defaultCardWidth : card_width; + if (width < minCardWidth) { + width = minCardWidth; + } const card = new Card({ customTitle: custom_title, @@ -238,6 +231,45 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => { if (disable_animations) card.disableAnimations(); + /** + * Calculates the right rank circle translation values such that the rank circle + * keeps respecting the padding. + * + * width > 450: The default left padding of 50 px will be used. + * width < 450: The left and right padding will shrink equally. + * + * @returns {number} - Rank circle translation value. + */ + const calculateRankXTranslation = () => { + if (width < 450) { + return width - 95 + (45 * (450 - 340)) / 110; + } else { + return width - 95; + } + }; + + // Conditionally rendered elements + const rankCircle = hide_rank + ? "" + : ` + + + + + ${rank.level} + + + `; + // Accessibility Labels const labels = Object.keys(STATS) .filter((key) => !hide.includes(key)) @@ -264,7 +296,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => { gap: lheight, direction: "column", }).join("")} - + `); }; diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js index 4e079ff2738a4..b2f5c362dd47f 100644 --- a/src/cards/top-languages-card.js +++ b/src/cards/top-languages-card.js @@ -13,6 +13,7 @@ const { } = require("../common/utils"); const DEFAULT_CARD_WIDTH = 300; +const MIN_CARD_WIDTH = 230; const DEFAULT_LANGS_COUNT = 5; const DEFAULT_LANG_COLOR = "#858585"; const CARD_PADDING = 25; @@ -24,12 +25,12 @@ const CARD_PADDING = 25; /** * @param {Lang[]} arr */ - const getLongestLang = (arr) => - arr.reduce( - (savedLang, lang) => - lang.name.length > savedLang.name.length ? lang : savedLang, - { name: "", size: null, color: "" }, - ); +const getLongestLang = (arr) => + arr.reduce( + (savedLang, lang) => + lang.name.length > savedLang.name.length ? lang : savedLang, + { name: "", size: null, color: "" }, + ); /** * @param {{ @@ -214,7 +215,7 @@ const useLanguages = (topLangs, hide, langs_count) => { }); } - // filter out langauges to be hidden + // filter out languages to be hidden langs = langs .sort((a, b) => b.size - a.size) .filter((lang) => { @@ -261,7 +262,11 @@ const renderTopLanguages = (topLangs, options = {}) => { String(langs_count), ); - let width = isNaN(card_width) ? DEFAULT_CARD_WIDTH : card_width; + let width = isNaN(card_width) + ? DEFAULT_CARD_WIDTH + : card_width < MIN_CARD_WIDTH + ? MIN_CARD_WIDTH + : card_width; let height = calculateNormalLayoutHeight(langs.length); let finalLayout = ""; @@ -307,3 +312,4 @@ const renderTopLanguages = (topLangs, options = {}) => { }; module.exports = renderTopLanguages; +module.exports.MIN_CARD_WIDTH = MIN_CARD_WIDTH; diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts index 4580a2eaa2083..46bf6659c07d0 100644 --- a/src/cards/types.d.ts +++ b/src/cards/types.d.ts @@ -16,6 +16,7 @@ export type StatCardOptions = CommonOptions & { show_icons: boolean; hide_title: boolean; hide_border: boolean; + card_width: number; hide_rank: boolean; include_all_commits: boolean; line_height: number | string; diff --git a/src/fetchers/stats-fetcher.js b/src/fetchers/stats-fetcher.js index 04b4b3e58e928..dc9be5bb4f89c 100644 --- a/src/fetchers/stats-fetcher.js +++ b/src/fetchers/stats-fetcher.js @@ -47,6 +47,7 @@ const fetcher = (variables, token) => { repositories(first: 100, ownerAffiliations: OWNER, orderBy: {direction: DESC, field: STARGAZERS}) { totalCount nodes { + name stargazers { totalCount } @@ -86,15 +87,16 @@ const totalCommitsFetcher = async (username) => { try { let res = await retryer(fetchTotalCommits, { login: username }); - if (res.data.total_count) { + let total_count = res.data.total_count; + if (!!total_count && !isNaN(total_count)) { return res.data.total_count; } } catch (err) { logger.log(err); - // just return 0 if there is something wrong so that - // we don't break the whole app - return 0; } + // just return 0 if there is something wrong so that + // we don't break the whole app + return 0; }; /** @@ -107,6 +109,7 @@ async function fetchStats( username, count_private = false, include_all_commits = false, + exclude_repo = [], ) { if (!username) throw new MissingParamError(["username"]); @@ -132,6 +135,15 @@ async function fetchStats( const user = res.data.data.user; + // populate repoToHide map for quick lookup + // while filtering out + let repoToHide = {}; + if (exclude_repo) { + exclude_repo.forEach((repoName) => { + repoToHide[repoName] = true; + }); + } + stats.name = user.name || user.login; stats.totalIssues = user.openIssues.totalCount + user.closedIssues.totalCount; @@ -153,9 +165,14 @@ async function fetchStats( stats.totalPRs = user.pullRequests.totalCount; stats.contributedTo = user.repositoriesContributedTo.totalCount; - stats.totalStars = user.repositories.nodes.reduce((prev, curr) => { - return prev + curr.stargazers.totalCount; - }, 0); + // Retrieve stars while filtering out repositories to be hidden + stats.totalStars = user.repositories.nodes + .filter((data) => { + return !repoToHide[data.name]; + }) + .reduce((prev, curr) => { + return prev + curr.stargazers.totalCount; + }, 0); stats.rank = calculateRank({ totalCommits: stats.totalCommits, diff --git a/src/fetchers/top-languages-fetcher.js b/src/fetchers/top-languages-fetcher.js index 9dd109e22ee2b..7c4c8785c87f9 100644 --- a/src/fetchers/top-languages-fetcher.js +++ b/src/fetchers/top-languages-fetcher.js @@ -68,14 +68,10 @@ async function fetchTopLanguages(username, exclude_repo = []) { // filter out repositories to be hidden repoNodes = repoNodes .sort((a, b) => b.size - a.size) - .filter((name) => { - return !repoToHide[name.name]; - }); + .filter((name) => !repoToHide[name.name]); repoNodes = repoNodes - .filter((node) => { - return node.languages.edges.length > 0; - }) + .filter((node) => node.languages.edges.length > 0) // flatten the list of language nodes .reduce((acc, curr) => curr.languages.edges.concat(acc), []) .reduce((acc, prev) => { diff --git a/src/fetchers/wakatime-fetcher.js b/src/fetchers/wakatime-fetcher.js index e9779d600429a..fe06c6385e7df 100644 --- a/src/fetchers/wakatime-fetcher.js +++ b/src/fetchers/wakatime-fetcher.js @@ -7,7 +7,7 @@ const { MissingParamError } = require("../common/utils"); */ const fetchWakatimeStats = async ({ username, api_domain, range }) => { if (!username) throw new MissingParamError(["username"]); - + try { const { data } = await axios.get( `https://${ diff --git a/src/getStyles.js b/src/getStyles.js index e5013e567f732..e76b51f4f4de8 100644 --- a/src/getStyles.js +++ b/src/getStyles.js @@ -85,6 +85,7 @@ const getStyles = ({ animation: scaleInAnimation 0.3s ease-in-out forwards; } + .not_bold { font-weight: 400 } .bold { font-weight: 700 } .icon { fill: ${iconColor}; diff --git a/tests/__snapshots__/renderWakatimeCard.test.js.snap b/tests/__snapshots__/renderWakatimeCard.test.js.snap index aa5641a0aa56f..bd62580224b3d 100644 --- a/tests/__snapshots__/renderWakatimeCard.test.js.snap +++ b/tests/__snapshots__/renderWakatimeCard.test.js.snap @@ -41,6 +41,7 @@ exports[`Test Render Wakatime Card should render correctly 1`] = ` animation: scaleInAnimation 0.3s ease-in-out forwards; } + .not_bold { font-weight: 400 } .bold { font-weight: 700 } .icon { fill: #4c71f2; @@ -202,6 +203,7 @@ exports[`Test Render Wakatime Card should render correctly with compact layout 1 animation: scaleInAnimation 0.3s ease-in-out forwards; } + .not_bold { font-weight: 400 } .bold { font-weight: 700 } .icon { fill: #4c71f2; diff --git a/tests/card.test.js b/tests/card.test.js index 002d278ae7b4d..2ef779459e279 100644 --- a/tests/card.test.js +++ b/tests/card.test.js @@ -168,18 +168,18 @@ describe("Card", () => { "fill", "url(#gradient)", ); - expect(document.querySelector("defs linearGradient")).toHaveAttribute( + expect(document.querySelector("defs #gradient")).toHaveAttribute( "gradientTransform", "rotate(90)", ); expect( - document.querySelector("defs linearGradient stop:nth-child(1)"), + document.querySelector("defs #gradient stop:nth-child(1)"), ).toHaveAttribute("stop-color", "#fff"); expect( - document.querySelector("defs linearGradient stop:nth-child(2)"), + document.querySelector("defs #gradient stop:nth-child(2)"), ).toHaveAttribute("stop-color", "#000"); expect( - document.querySelector("defs linearGradient stop:nth-child(3)"), + document.querySelector("defs #gradient stop:nth-child(3)"), ).toHaveAttribute("stop-color", "#f00"); }); }); diff --git a/tests/fetchStats.test.js b/tests/fetchStats.test.js index f732182f8fe5a..fe2fd4d7fd4fc 100644 --- a/tests/fetchStats.test.js +++ b/tests/fetchStats.test.js @@ -20,11 +20,11 @@ const data = { repositories: { totalCount: 5, nodes: [ - { stargazers: { totalCount: 100 } }, - { stargazers: { totalCount: 100 } }, - { stargazers: { totalCount: 100 } }, - { stargazers: { totalCount: 50 } }, - { stargazers: { totalCount: 50 } }, + { name: "test-repo-1", stargazers: { totalCount: 100 } }, + { name: "test-repo-2", stargazers: { totalCount: 100 } }, + { name: "test-repo-3", stargazers: { totalCount: 100 } }, + { name: "test-repo-4", stargazers: { totalCount: 50 } }, + { name: "test-repo-5", stargazers: { totalCount: 50 } }, ], }, }, @@ -134,4 +134,37 @@ describe("Test fetchStats", () => { rank, }); }); + + it("should exclude stars of the `test-repo-1` repository", async () => { + mock.onPost("https://api.github.com/graphql").reply(200, data); + mock + .onGet("https://api.github.com/search/commits?q=author:anuraghazra") + .reply(200, { total_count: 1000 }); + + let stats = await fetchStats( + "anuraghazra", + true, + true, + (exclude_repo = ["test-repo-1"]), + ); + const rank = calculateRank({ + totalCommits: 1050, + totalRepos: 5, + followers: 100, + contributions: 61, + stargazers: 300, + prs: 300, + issues: 200, + }); + + expect(stats).toStrictEqual({ + contributedTo: 61, + name: "Anurag Hazra", + totalCommits: 1050, + totalIssues: 200, + totalPRs: 300, + totalStars: 300, + rank, + }); + }); }); diff --git a/tests/fetchTopLanguages.test.js b/tests/fetchTopLanguages.test.js index 54238df179e25..0792f28ded452 100644 --- a/tests/fetchTopLanguages.test.js +++ b/tests/fetchTopLanguages.test.js @@ -81,7 +81,10 @@ describe("FetchTopLanguages", () => { it("should fetch correct language data while excluding the 'test-repo-1' repository", async () => { mock.onPost("https://api.github.com/graphql").reply(200, data_langs); - let repo = await fetchTopLanguages("anuraghazra", exclude_repo=["test-repo-1"]); + let repo = await fetchTopLanguages( + "anuraghazra", + (exclude_repo = ["test-repo-1"]), + ); expect(repo).toStrictEqual({ HTML: { color: "#0f0", diff --git a/tests/fetchWakatime.test.js b/tests/fetchWakatime.test.js index 6255890c0a5ed..ef8c64c38229f 100644 --- a/tests/fetchWakatime.test.js +++ b/tests/fetchWakatime.test.js @@ -207,7 +207,7 @@ describe("Wakatime fetcher", () => { mock.onGet(/\/https:\/\/wakatime\.com\/api/).reply(404, wakaTimeData); await expect(fetchWakatimeStats("noone")).rejects.toThrow( - "Missing params \"username\" make sure you pass the parameters in URL", + 'Missing params "username" make sure you pass the parameters in URL', ); }); }); diff --git a/tests/renderStatsCard.test.js b/tests/renderStatsCard.test.js index aabf2f6b75b5f..09bd9b044eef4 100644 --- a/tests/renderStatsCard.test.js +++ b/tests/renderStatsCard.test.js @@ -75,6 +75,52 @@ describe("Test renderStatsCard", () => { 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", "495"); + + document.body.innerHTML = renderStatsCard(stats, { card_width: 400 }); + expect(document.querySelector("svg")).toHaveAttribute("width", "400"); + }); + + 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", "340"); + + document.body.innerHTML = renderStatsCard(stats, { + card_width: 1, + hide_rank: true, + }); + expect(document.querySelector("svg")).toHaveAttribute( + "width", + "305.81250000000006", + ); + + document.body.innerHTML = renderStatsCard(stats, { + card_width: 1, + hide_rank: true, + show_icons: true, + }); + expect(document.querySelector("svg")).toHaveAttribute( + "width", + "305.81250000000006", + ); + + document.body.innerHTML = renderStatsCard(stats, { + card_width: 1, + hide_rank: false, + show_icons: true, + }); + expect(document.querySelector("svg")).toHaveAttribute("width", "356"); + + document.body.innerHTML = renderStatsCard(stats, { + card_width: 1, + hide_rank: false, + show_icons: false, + }); + expect(document.querySelector("svg")).toHaveAttribute("width", "340"); + }); + it("should render default colors properly", () => { document.body.innerHTML = renderStatsCard(stats); diff --git a/tests/renderTopLanguages.test.js b/tests/renderTopLanguages.test.js index 36dbf03f9507d..b2ff70f68e7d5 100644 --- a/tests/renderTopLanguages.test.js +++ b/tests/renderTopLanguages.test.js @@ -103,6 +103,21 @@ describe("Test renderTopLanguages", () => { expect(document.querySelector("svg")).toHaveAttribute("width", "400"); }); + it("should render with min width", () => { + document.body.innerHTML = renderTopLanguages(langs, { card_width: 190 }); + + expect(document.querySelector("svg")).toHaveAttribute( + "width", + renderTopLanguages.MIN_CARD_WIDTH.toString(), + ); + + document.body.innerHTML = renderTopLanguages(langs, { card_width: 100 }); + expect(document.querySelector("svg")).toHaveAttribute( + "width", + renderTopLanguages.MIN_CARD_WIDTH.toString(), + ); + }); + it("should render default colors properly", () => { document.body.innerHTML = renderTopLanguages(langs); diff --git a/tests/renderWakatimeCard.test.js b/tests/renderWakatimeCard.test.js index 51d63e6cf14c1..a6d7c85f30975 100644 --- a/tests/renderWakatimeCard.test.js +++ b/tests/renderWakatimeCard.test.js @@ -48,10 +48,15 @@ describe("Test Render Wakatime Card", () => { }); it('should show "no coding activitiy this week" message when there hasn not been activity', () => { - document.body.innerHTML = renderWakatimeCard({ - ...wakaTimeData.data, - languages: undefined - }, {}); - expect(document.querySelector(".stat").textContent).toBe("No coding activity this week") - }) + document.body.innerHTML = renderWakatimeCard( + { + ...wakaTimeData.data, + languages: undefined, + }, + {}, + ); + expect(document.querySelector(".stat").textContent).toBe( + "No coding activity this week", + ); + }); }); diff --git a/themes/index.js b/themes/index.js index 2508c9d2f538c..4312496ac6f86 100644 --- a/themes/index.js +++ b/themes/index.js @@ -355,12 +355,12 @@ const themes = { bg_color: "09131B", border_color: "0c1a25", }, - "rose_pine":{ + rose_pine: { title_color: "9ccfd8", icon_color: "ebbcba", text_color: "e0def4", bg_color: "191724", - } + }, }; module.exports = themes;