From 42fdff624fb7a3b389792f27352be594c2a45e07 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Jan 2023 15:42:45 +0100 Subject: [PATCH 01/15] build(deps): bump json5 from 2.2.1 to 2.2.3 (#2373) Bumps [json5](https://github.com/json5/json5) from 2.2.1 to 2.2.3. - [Release notes](https://github.com/json5/json5/releases) - [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md) - [Commits](https://github.com/json5/json5/compare/v2.2.1...v2.2.3) --- updated-dependencies: - dependency-name: json5 dependency-type: indirect ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 048c316b..64d79cfb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3929,9 +3929,9 @@ "dev": true }, "node_modules/json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "bin": { "json5": "lib/cli.js" @@ -8656,9 +8656,9 @@ "dev": true }, "json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, "kleur": { From 227711c6289679325b325ba8418a643354b76aa0 Mon Sep 17 00:00:00 2001 From: rickstaa Date: Tue, 10 Jan 2023 10:08:33 +0000 Subject: [PATCH 02/15] test: update snapshots --- tests/renderStatsCard.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/renderStatsCard.test.js b/tests/renderStatsCard.test.js index e39e45b7..5afb1f02 100644 --- a/tests/renderStatsCard.test.js +++ b/tests/renderStatsCard.test.js @@ -329,7 +329,7 @@ describe("Test renderStatsCard", () => { document.querySelector( 'g[transform="translate(0, 25)"]>.stagger>.stat.bold', ).textContent, - ).toMatchInlineSnapshot(`"累计提交数(commit) (2022):"`); + ).toMatchInlineSnapshot(`"累计提交数(commit) (2023):"`); expect( document.querySelector( 'g[transform="translate(0, 50)"]>.stagger>.stat.bold', From 77dcdab42c306fd49e71e32a2335d6c06a90baf1 Mon Sep 17 00:00:00 2001 From: Huzaifa Khilawala <55500003+RedHeadphone@users.noreply.github.com> Date: Tue, 10 Jan 2023 17:51:35 +0530 Subject: [PATCH 03/15] Add loading Animation to Most used Language card (#2197) * add: text animation * compact progress done * cleaned code * non compact animation done * tests fixed + prettier * revert: vercel.json * remove: unnecessary import * added parameter in docs * style: improve syntax Co-authored-by: rickstaa --- api/top-langs.js | 2 + readme.md | 1 + src/cards/top-languages-card.js | 82 ++++++++++++++++++++++++-------- src/cards/types.d.ts | 1 + src/common/createProgressNode.js | 19 ++++---- 5 files changed, 76 insertions(+), 29 deletions(-) diff --git a/api/top-langs.js b/api/top-langs.js index d183d3b4..19cccb89 100644 --- a/api/top-langs.js +++ b/api/top-langs.js @@ -29,6 +29,7 @@ export default async (req, res) => { locale, border_radius, border_color, + disable_animations, } = req.query; res.setHeader("Content-Type", "image/svg+xml"); @@ -75,6 +76,7 @@ export default async (req, res) => { border_radius, border_color, locale: locale ? locale.toLowerCase() : null, + disable_animations: parseBoolean(disable_animations), }), ); } catch (err) { diff --git a/readme.md b/readme.md index bfe042fc..716bda22 100644 --- a/readme.md +++ b/readme.md @@ -304,6 +304,7 @@ You can provide multiple comma-separated values in the bg_color option to render - `langs_count` - Show more languages on the card, between 1-10 _(number)_. Default `5`. - `exclude_repo` - Exclude specified repositories _(Comma-separated values)_. Default: `[] (blank array)`. - `custom_title` - Sets a custom title for the card _(string)_. Default `Most Used Languages`. +- `disable_animations` - Disables all animations in the card _(boolean)_. Default: `false`. > **Warning** > Language names should be URI-escaped, as specified in [Percent Encoding](https://en.wikipedia.org/wiki/Percent-encoding) diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js index 602d1b81..9396ff8e 100644 --- a/src/cards/top-languages-card.js +++ b/src/cards/top-languages-card.js @@ -39,46 +39,53 @@ const getLongestLang = (arr) => * Creates a node to display usage of a programming language in percentage * using text and a horizontal progress bar. * - * @param {object[]} props Function properties. + * @param {object} props Function properties. * @param {number} props.width The card width * @param {string} props.name Name of the programming language. * @param {string} props.color Color of the programming language. * @param {string} props.progress Usage of the programming language in percentage. + * @param {number} props.index Index of the programming language. * @returns {string} Programming language SVG node. */ -const createProgressTextNode = ({ width, color, name, progress }) => { +const createProgressTextNode = ({ width, color, name, progress, index }) => { + const staggerDelay = (index + 3) * 150; const paddingRight = 95; const progressTextX = width - paddingRight + 10; const progressWidth = width - paddingRight; return ` - ${name} - ${progress}% - ${createProgressNode({ - x: 0, - y: 25, - color, - width: progressWidth, - progress, - progressBarBackgroundColor: "#ddd", - })} + + ${name} + ${progress}% + ${createProgressNode({ + x: 0, + y: 25, + color, + width: progressWidth, + progress, + progressBarBackgroundColor: "#ddd", + delay: staggerDelay + 300, + })} + `; }; /** * Creates a text only node to display usage of a programming language in percentage. * - * @param {object[]} props Function properties. + * @param {object} props Function properties. * @param {Lang} props.lang Programming language object. * @param {number} props.totalSize Total size of all languages. + * @param {number} props.index Index of the programming language. * @returns {string} Compact layout programming language SVG node. */ -const createCompactLangNode = ({ lang, totalSize }) => { +const createCompactLangNode = ({ lang, totalSize, index }) => { const percentage = ((lang.size / totalSize) * 100).toFixed(2); + const staggerDelay = (index + 3) * 150; const color = lang.color || "#858585"; return ` - + ${lang.name} ${percentage}% @@ -104,7 +111,6 @@ const createLanguageTextNode = ({ langs, totalSize }) => { createCompactLangNode({ lang, totalSize, - // @ts-ignore index, }), ); @@ -134,12 +140,13 @@ const createLanguageTextNode = ({ langs, totalSize }) => { */ const renderNormalLayout = (langs, width, totalLanguageSize) => { return flexLayout({ - items: langs.map((lang) => { + items: langs.map((lang, index) => { return createProgressTextNode({ - width: width, + width, name: lang.name, color: lang.color || DEFAULT_LANG_COLOR, progress: ((lang.size / totalLanguageSize) * 100).toFixed(2), + index, }); }), gap: 40, @@ -187,7 +194,7 @@ const renderCompactLayout = (langs, width, totalLanguageSize) => { return ` - + ${compactProgressBar} @@ -276,6 +283,7 @@ const renderTopLanguages = (topLangs, options = {}) => { langs_count = DEFAULT_LANGS_COUNT, border_radius, border_color, + disable_animations, } = options; const i18n = new I18n({ @@ -324,11 +332,43 @@ const renderTopLanguages = (topLangs, options = {}) => { colors, }); - card.disableAnimations(); + if (disable_animations) card.disableAnimations(); + card.setHideBorder(hide_border); card.setHideTitle(hide_title); card.setCSS( - `.lang-name { font: 400 11px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${colors.textColor} }`, + ` + @keyframes slideInAnimation { + from { + width: 0; + } + to { + width: calc(100%-100px); + } + } + @keyframes growWidthAnimation { + from { + width: 0; + } + to { + width: 100%; + } + } + .lang-name { + font: 400 11px "Segoe UI", Ubuntu, Sans-Serif; + fill: ${colors.textColor}; + } + .stagger { + opacity: 0; + animation: fadeInAnimation 0.3s ease-in-out forwards; + } + #rect-mask rect{ + animation: slideInAnimation 1s ease-in-out forwards; + } + .lang-progress{ + animation: growWidthAnimation 0.6s ease-in-out forwards; + } + `, ); return card.render(` diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts index 502314c4..c5945d48 100644 --- a/src/cards/types.d.ts +++ b/src/cards/types.d.ts @@ -37,6 +37,7 @@ export type TopLangOptions = CommonOptions & { layout: "compact" | "normal"; custom_title: string; langs_count: number; + disable_animations: boolean; }; type WakaTimeOptions = CommonOptions & { diff --git a/src/common/createProgressNode.js b/src/common/createProgressNode.js index c36818b1..2825583c 100644 --- a/src/common/createProgressNode.js +++ b/src/common/createProgressNode.js @@ -10,6 +10,7 @@ import { clampValue } from "./utils.js"; * @param {string} createProgressNodeParams.color Progress color. * @param {string} createProgressNodeParams.progress Progress value. * @param {string} createProgressNodeParams.progressBarBackgroundColor Progress bar bg color. + * @param {number} createProgressNodeParams.delay Delay before animation starts. * @returns {string} Progress node. */ const createProgressNode = ({ @@ -19,20 +20,22 @@ const createProgressNode = ({ color, progress, progressBarBackgroundColor, + delay, }) => { const progressPercentage = clampValue(progress, 2, 100); return ` - - + + + `; }; From 5ae959b57c0831bc79d43425e07d0fe7c6a58011 Mon Sep 17 00:00:00 2001 From: Rick Staa Date: Tue, 10 Jan 2023 13:25:06 +0100 Subject: [PATCH 04/15] ci: fix theme readme generation action (#2271) --- scripts/push-theme-readme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/push-theme-readme.sh b/scripts/push-theme-readme.sh index 4a035db3..1ab5de47 100755 --- a/scripts/push-theme-readme.sh +++ b/scripts/push-theme-readme.sh @@ -9,6 +9,6 @@ git config --global user.name "GitHub Readme Stats Bot" git branch -d $BRANCH_NAME || true git checkout -b $BRANCH_NAME git add --all -git commit --message "docs(theme): Auto update theme readme" || exit 0 +git commit --no-verify --message "docs(theme): Auto update theme readme" git remote add origin-$BRANCH_NAME https://${PERSONAL_TOKEN}@github.com/${GH_REPO}.git git push --force --quiet --set-upstream origin-$BRANCH_NAME $BRANCH_NAME From 0850a9763058aa018b8538b34772f98bbf759aa2 Mon Sep 17 00:00:00 2001 From: Rick Staa Date: Thu, 12 Jan 2023 22:44:27 +0100 Subject: [PATCH 05/15] Revert "build(deps): bump json5 from 2.2.1 to 2.2.3 (#2373)" (#2393) This reverts commit 42fdff624fb7a3b389792f27352be594c2a45e07. --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 64d79cfb..048c316b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3929,9 +3929,9 @@ "dev": true }, "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", "dev": true, "bin": { "json5": "lib/cli.js" @@ -8656,9 +8656,9 @@ "dev": true }, "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", "dev": true }, "kleur": { From 70f0264905d9370efa635b6a611c8719b8958efa Mon Sep 17 00:00:00 2001 From: Rick Staa Date: Thu, 12 Jan 2023 22:48:28 +0100 Subject: [PATCH 06/15] Revert "ci: fix theme readme generation action (#2271)" (#2394) This reverts commit 5ae959b57c0831bc79d43425e07d0fe7c6a58011. --- scripts/push-theme-readme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/push-theme-readme.sh b/scripts/push-theme-readme.sh index 1ab5de47..4a035db3 100755 --- a/scripts/push-theme-readme.sh +++ b/scripts/push-theme-readme.sh @@ -9,6 +9,6 @@ git config --global user.name "GitHub Readme Stats Bot" git branch -d $BRANCH_NAME || true git checkout -b $BRANCH_NAME git add --all -git commit --no-verify --message "docs(theme): Auto update theme readme" +git commit --message "docs(theme): Auto update theme readme" || exit 0 git remote add origin-$BRANCH_NAME https://${PERSONAL_TOKEN}@github.com/${GH_REPO}.git git push --force --quiet --set-upstream origin-$BRANCH_NAME $BRANCH_NAME From 4b8198fa2198da394b71e43fe4c59862a7014287 Mon Sep 17 00:00:00 2001 From: Rick Staa Date: Thu, 12 Jan 2023 22:52:34 +0100 Subject: [PATCH 07/15] Revert "Add loading Animation to Most used Language card (#2197)" (#2396) This reverts commit 77dcdab42c306fd49e71e32a2335d6c06a90baf1. --- api/top-langs.js | 2 - readme.md | 1 - src/cards/top-languages-card.js | 82 ++++++++------------------------ src/cards/types.d.ts | 1 - src/common/createProgressNode.js | 19 ++++---- 5 files changed, 29 insertions(+), 76 deletions(-) diff --git a/api/top-langs.js b/api/top-langs.js index 19cccb89..d183d3b4 100644 --- a/api/top-langs.js +++ b/api/top-langs.js @@ -29,7 +29,6 @@ export default async (req, res) => { locale, border_radius, border_color, - disable_animations, } = req.query; res.setHeader("Content-Type", "image/svg+xml"); @@ -76,7 +75,6 @@ export default async (req, res) => { border_radius, border_color, locale: locale ? locale.toLowerCase() : null, - disable_animations: parseBoolean(disable_animations), }), ); } catch (err) { diff --git a/readme.md b/readme.md index 716bda22..bfe042fc 100644 --- a/readme.md +++ b/readme.md @@ -304,7 +304,6 @@ You can provide multiple comma-separated values in the bg_color option to render - `langs_count` - Show more languages on the card, between 1-10 _(number)_. Default `5`. - `exclude_repo` - Exclude specified repositories _(Comma-separated values)_. Default: `[] (blank array)`. - `custom_title` - Sets a custom title for the card _(string)_. Default `Most Used Languages`. -- `disable_animations` - Disables all animations in the card _(boolean)_. Default: `false`. > **Warning** > Language names should be URI-escaped, as specified in [Percent Encoding](https://en.wikipedia.org/wiki/Percent-encoding) diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js index 9396ff8e..602d1b81 100644 --- a/src/cards/top-languages-card.js +++ b/src/cards/top-languages-card.js @@ -39,53 +39,46 @@ const getLongestLang = (arr) => * Creates a node to display usage of a programming language in percentage * using text and a horizontal progress bar. * - * @param {object} props Function properties. + * @param {object[]} props Function properties. * @param {number} props.width The card width * @param {string} props.name Name of the programming language. * @param {string} props.color Color of the programming language. * @param {string} props.progress Usage of the programming language in percentage. - * @param {number} props.index Index of the programming language. * @returns {string} Programming language SVG node. */ -const createProgressTextNode = ({ width, color, name, progress, index }) => { - const staggerDelay = (index + 3) * 150; +const createProgressTextNode = ({ width, color, name, progress }) => { const paddingRight = 95; const progressTextX = width - paddingRight + 10; const progressWidth = width - paddingRight; return ` - - ${name} - ${progress}% - ${createProgressNode({ - x: 0, - y: 25, - color, - width: progressWidth, - progress, - progressBarBackgroundColor: "#ddd", - delay: staggerDelay + 300, - })} - + ${name} + ${progress}% + ${createProgressNode({ + x: 0, + y: 25, + color, + width: progressWidth, + progress, + progressBarBackgroundColor: "#ddd", + })} `; }; /** * Creates a text only node to display usage of a programming language in percentage. * - * @param {object} props Function properties. + * @param {object[]} props Function properties. * @param {Lang} props.lang Programming language object. * @param {number} props.totalSize Total size of all languages. - * @param {number} props.index Index of the programming language. * @returns {string} Compact layout programming language SVG node. */ -const createCompactLangNode = ({ lang, totalSize, index }) => { +const createCompactLangNode = ({ lang, totalSize }) => { const percentage = ((lang.size / totalSize) * 100).toFixed(2); - const staggerDelay = (index + 3) * 150; const color = lang.color || "#858585"; return ` - + ${lang.name} ${percentage}% @@ -111,6 +104,7 @@ const createLanguageTextNode = ({ langs, totalSize }) => { createCompactLangNode({ lang, totalSize, + // @ts-ignore index, }), ); @@ -140,13 +134,12 @@ const createLanguageTextNode = ({ langs, totalSize }) => { */ const renderNormalLayout = (langs, width, totalLanguageSize) => { return flexLayout({ - items: langs.map((lang, index) => { + items: langs.map((lang) => { return createProgressTextNode({ - width, + width: width, name: lang.name, color: lang.color || DEFAULT_LANG_COLOR, progress: ((lang.size / totalLanguageSize) * 100).toFixed(2), - index, }); }), gap: 40, @@ -194,7 +187,7 @@ const renderCompactLayout = (langs, width, totalLanguageSize) => { return ` - + ${compactProgressBar} @@ -283,7 +276,6 @@ const renderTopLanguages = (topLangs, options = {}) => { langs_count = DEFAULT_LANGS_COUNT, border_radius, border_color, - disable_animations, } = options; const i18n = new I18n({ @@ -332,43 +324,11 @@ const renderTopLanguages = (topLangs, options = {}) => { colors, }); - if (disable_animations) card.disableAnimations(); - + card.disableAnimations(); card.setHideBorder(hide_border); card.setHideTitle(hide_title); card.setCSS( - ` - @keyframes slideInAnimation { - from { - width: 0; - } - to { - width: calc(100%-100px); - } - } - @keyframes growWidthAnimation { - from { - width: 0; - } - to { - width: 100%; - } - } - .lang-name { - font: 400 11px "Segoe UI", Ubuntu, Sans-Serif; - fill: ${colors.textColor}; - } - .stagger { - opacity: 0; - animation: fadeInAnimation 0.3s ease-in-out forwards; - } - #rect-mask rect{ - animation: slideInAnimation 1s ease-in-out forwards; - } - .lang-progress{ - animation: growWidthAnimation 0.6s ease-in-out forwards; - } - `, + `.lang-name { font: 400 11px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${colors.textColor} }`, ); return card.render(` diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts index c5945d48..502314c4 100644 --- a/src/cards/types.d.ts +++ b/src/cards/types.d.ts @@ -37,7 +37,6 @@ export type TopLangOptions = CommonOptions & { layout: "compact" | "normal"; custom_title: string; langs_count: number; - disable_animations: boolean; }; type WakaTimeOptions = CommonOptions & { diff --git a/src/common/createProgressNode.js b/src/common/createProgressNode.js index 2825583c..c36818b1 100644 --- a/src/common/createProgressNode.js +++ b/src/common/createProgressNode.js @@ -10,7 +10,6 @@ import { clampValue } from "./utils.js"; * @param {string} createProgressNodeParams.color Progress color. * @param {string} createProgressNodeParams.progress Progress value. * @param {string} createProgressNodeParams.progressBarBackgroundColor Progress bar bg color. - * @param {number} createProgressNodeParams.delay Delay before animation starts. * @returns {string} Progress node. */ const createProgressNode = ({ @@ -20,22 +19,20 @@ const createProgressNode = ({ color, progress, progressBarBackgroundColor, - delay, }) => { const progressPercentage = clampValue(progress, 2, 100); return ` - - - + + `; }; From 0ff426d258387ecd0ebbb9206d91b96781e61cf0 Mon Sep 17 00:00:00 2001 From: Anurag Hazra Date: Fri, 13 Jan 2023 13:16:33 +0530 Subject: [PATCH 08/15] fix: retryer fixed (#2400) --- src/common/retryer.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/common/retryer.js b/src/common/retryer.js index e54eedbe..73833ef8 100644 --- a/src/common/retryer.js +++ b/src/common/retryer.js @@ -45,8 +45,9 @@ const retryer = async (fetcher, variables, retries = 0) => { // prettier-ignore // also checking for bad credentials if any tokens gets invalidated const isBadCredential = err.response.data && err.response.data.message === "Bad credentials"; + const isAccountSuspended = err.response.data && err.response.data.message === "Sorry. Your account was suspended."; - if (isBadCredential) { + if (isBadCredential || isAccountSuspended) { logger.log(`PAT_${retries + 1} Failed`); retries++; // directly return from the function From ab9c563ec51a0843ab8ad0877d5f9dd491d23e00 Mon Sep 17 00:00:00 2001 From: Rick Staa Date: Mon, 16 Jan 2023 12:21:13 +0100 Subject: [PATCH 09/15] Revert "Revert "ci: fix theme readme generation action (#2271)" (#2394)" (#2418) This reverts commit 70f0264905d9370efa635b6a611c8719b8958efa. --- scripts/push-theme-readme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/push-theme-readme.sh b/scripts/push-theme-readme.sh index 4a035db3..1ab5de47 100755 --- a/scripts/push-theme-readme.sh +++ b/scripts/push-theme-readme.sh @@ -9,6 +9,6 @@ git config --global user.name "GitHub Readme Stats Bot" git branch -d $BRANCH_NAME || true git checkout -b $BRANCH_NAME git add --all -git commit --message "docs(theme): Auto update theme readme" || exit 0 +git commit --no-verify --message "docs(theme): Auto update theme readme" git remote add origin-$BRANCH_NAME https://${PERSONAL_TOKEN}@github.com/${GH_REPO}.git git push --force --quiet --set-upstream origin-$BRANCH_NAME $BRANCH_NAME From ad9db67b4c551aba6e19cc5af9030d85ac1c4906 Mon Sep 17 00:00:00 2001 From: Rick Staa Date: Mon, 16 Jan 2023 12:28:31 +0100 Subject: [PATCH 10/15] refactor: update code formatting --- src/common/retryer.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/common/retryer.js b/src/common/retryer.js index 73833ef8..5351cbe8 100644 --- a/src/common/retryer.js +++ b/src/common/retryer.js @@ -45,7 +45,9 @@ const retryer = async (fetcher, variables, retries = 0) => { // prettier-ignore // also checking for bad credentials if any tokens gets invalidated const isBadCredential = err.response.data && err.response.data.message === "Bad credentials"; - const isAccountSuspended = err.response.data && err.response.data.message === "Sorry. Your account was suspended."; + const isAccountSuspended = + err.response.data && + err.response.data.message === "Sorry. Your account was suspended."; if (isBadCredential || isAccountSuspended) { logger.log(`PAT_${retries + 1} Failed`); From 06a2a78cfcb1cd29c3b8b46d3899ffac10ab14b8 Mon Sep 17 00:00:00 2001 From: Rick Staa Date: Mon, 16 Jan 2023 12:30:39 +0100 Subject: [PATCH 11/15] Revert "Revert "Add loading Animation to Most used Language card (#2197)" (#2396)" (#2419) This reverts commit 4b8198fa2198da394b71e43fe4c59862a7014287. --- api/top-langs.js | 2 + readme.md | 1 + src/cards/top-languages-card.js | 82 ++++++++++++++++++++++++-------- src/cards/types.d.ts | 1 + src/common/createProgressNode.js | 19 ++++---- 5 files changed, 76 insertions(+), 29 deletions(-) diff --git a/api/top-langs.js b/api/top-langs.js index d183d3b4..19cccb89 100644 --- a/api/top-langs.js +++ b/api/top-langs.js @@ -29,6 +29,7 @@ export default async (req, res) => { locale, border_radius, border_color, + disable_animations, } = req.query; res.setHeader("Content-Type", "image/svg+xml"); @@ -75,6 +76,7 @@ export default async (req, res) => { border_radius, border_color, locale: locale ? locale.toLowerCase() : null, + disable_animations: parseBoolean(disable_animations), }), ); } catch (err) { diff --git a/readme.md b/readme.md index bfe042fc..716bda22 100644 --- a/readme.md +++ b/readme.md @@ -304,6 +304,7 @@ You can provide multiple comma-separated values in the bg_color option to render - `langs_count` - Show more languages on the card, between 1-10 _(number)_. Default `5`. - `exclude_repo` - Exclude specified repositories _(Comma-separated values)_. Default: `[] (blank array)`. - `custom_title` - Sets a custom title for the card _(string)_. Default `Most Used Languages`. +- `disable_animations` - Disables all animations in the card _(boolean)_. Default: `false`. > **Warning** > Language names should be URI-escaped, as specified in [Percent Encoding](https://en.wikipedia.org/wiki/Percent-encoding) diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js index 602d1b81..9396ff8e 100644 --- a/src/cards/top-languages-card.js +++ b/src/cards/top-languages-card.js @@ -39,46 +39,53 @@ const getLongestLang = (arr) => * Creates a node to display usage of a programming language in percentage * using text and a horizontal progress bar. * - * @param {object[]} props Function properties. + * @param {object} props Function properties. * @param {number} props.width The card width * @param {string} props.name Name of the programming language. * @param {string} props.color Color of the programming language. * @param {string} props.progress Usage of the programming language in percentage. + * @param {number} props.index Index of the programming language. * @returns {string} Programming language SVG node. */ -const createProgressTextNode = ({ width, color, name, progress }) => { +const createProgressTextNode = ({ width, color, name, progress, index }) => { + const staggerDelay = (index + 3) * 150; const paddingRight = 95; const progressTextX = width - paddingRight + 10; const progressWidth = width - paddingRight; return ` - ${name} - ${progress}% - ${createProgressNode({ - x: 0, - y: 25, - color, - width: progressWidth, - progress, - progressBarBackgroundColor: "#ddd", - })} + + ${name} + ${progress}% + ${createProgressNode({ + x: 0, + y: 25, + color, + width: progressWidth, + progress, + progressBarBackgroundColor: "#ddd", + delay: staggerDelay + 300, + })} + `; }; /** * Creates a text only node to display usage of a programming language in percentage. * - * @param {object[]} props Function properties. + * @param {object} props Function properties. * @param {Lang} props.lang Programming language object. * @param {number} props.totalSize Total size of all languages. + * @param {number} props.index Index of the programming language. * @returns {string} Compact layout programming language SVG node. */ -const createCompactLangNode = ({ lang, totalSize }) => { +const createCompactLangNode = ({ lang, totalSize, index }) => { const percentage = ((lang.size / totalSize) * 100).toFixed(2); + const staggerDelay = (index + 3) * 150; const color = lang.color || "#858585"; return ` - + ${lang.name} ${percentage}% @@ -104,7 +111,6 @@ const createLanguageTextNode = ({ langs, totalSize }) => { createCompactLangNode({ lang, totalSize, - // @ts-ignore index, }), ); @@ -134,12 +140,13 @@ const createLanguageTextNode = ({ langs, totalSize }) => { */ const renderNormalLayout = (langs, width, totalLanguageSize) => { return flexLayout({ - items: langs.map((lang) => { + items: langs.map((lang, index) => { return createProgressTextNode({ - width: width, + width, name: lang.name, color: lang.color || DEFAULT_LANG_COLOR, progress: ((lang.size / totalLanguageSize) * 100).toFixed(2), + index, }); }), gap: 40, @@ -187,7 +194,7 @@ const renderCompactLayout = (langs, width, totalLanguageSize) => { return ` - + ${compactProgressBar} @@ -276,6 +283,7 @@ const renderTopLanguages = (topLangs, options = {}) => { langs_count = DEFAULT_LANGS_COUNT, border_radius, border_color, + disable_animations, } = options; const i18n = new I18n({ @@ -324,11 +332,43 @@ const renderTopLanguages = (topLangs, options = {}) => { colors, }); - card.disableAnimations(); + if (disable_animations) card.disableAnimations(); + card.setHideBorder(hide_border); card.setHideTitle(hide_title); card.setCSS( - `.lang-name { font: 400 11px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${colors.textColor} }`, + ` + @keyframes slideInAnimation { + from { + width: 0; + } + to { + width: calc(100%-100px); + } + } + @keyframes growWidthAnimation { + from { + width: 0; + } + to { + width: 100%; + } + } + .lang-name { + font: 400 11px "Segoe UI", Ubuntu, Sans-Serif; + fill: ${colors.textColor}; + } + .stagger { + opacity: 0; + animation: fadeInAnimation 0.3s ease-in-out forwards; + } + #rect-mask rect{ + animation: slideInAnimation 1s ease-in-out forwards; + } + .lang-progress{ + animation: growWidthAnimation 0.6s ease-in-out forwards; + } + `, ); return card.render(` diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts index 502314c4..c5945d48 100644 --- a/src/cards/types.d.ts +++ b/src/cards/types.d.ts @@ -37,6 +37,7 @@ export type TopLangOptions = CommonOptions & { layout: "compact" | "normal"; custom_title: string; langs_count: number; + disable_animations: boolean; }; type WakaTimeOptions = CommonOptions & { diff --git a/src/common/createProgressNode.js b/src/common/createProgressNode.js index c36818b1..2825583c 100644 --- a/src/common/createProgressNode.js +++ b/src/common/createProgressNode.js @@ -10,6 +10,7 @@ import { clampValue } from "./utils.js"; * @param {string} createProgressNodeParams.color Progress color. * @param {string} createProgressNodeParams.progress Progress value. * @param {string} createProgressNodeParams.progressBarBackgroundColor Progress bar bg color. + * @param {number} createProgressNodeParams.delay Delay before animation starts. * @returns {string} Progress node. */ const createProgressNode = ({ @@ -19,20 +20,22 @@ const createProgressNode = ({ color, progress, progressBarBackgroundColor, + delay, }) => { const progressPercentage = clampValue(progress, 2, 100); return ` - - + + + `; }; From 8bc69e761ff7c922f47e6561d7a2f4fd0cc153c7 Mon Sep 17 00:00:00 2001 From: Zohan Subhash Date: Thu, 19 Jan 2023 14:00:46 +0530 Subject: [PATCH 12/15] Update readme.md (#2442) --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 716bda22..281c4877 100644 --- a/readme.md +++ b/readme.md @@ -259,7 +259,7 @@ You can customize the appearance of your `Stats Card` or `Repo Card` however you - `bg_color` - Card's background color _(hex color)_ **or** a gradient in the form of _angle,start,end_. Default: `fffefe` - `hide_border` - Hides the card's border _(boolean)_. Default: `false` - `theme` - name of the theme, choose from [all available themes](./themes/README.md). Default: `default` theme. -- `cache_seconds` - set the cache header manually _(min: 7200, max: 86400)_. Default: `14400 seconds (4 hours)`. +- `cache_seconds` - set the cache header manually _(min: 14400, max: 86400)_. Default: `14400 seconds (4 hours)`. - `locale` - set the language in the card _(e.g. cn, de, es, etc.)_. Default: `en`. - `border_radius` - Corner rounding on the card. Default: `4.5`. From 4ff2c2a425dbeccde302e27042d3aa698bc8609c Mon Sep 17 00:00:00 2001 From: rickstaa Date: Sat, 21 Jan 2023 17:52:51 +0100 Subject: [PATCH 13/15] feat: fix e2e tests --- tests/e2e/e2e.test.js | 45 +++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/tests/e2e/e2e.test.js b/tests/e2e/e2e.test.js index 48bf16a0..4d00646d 100644 --- a/tests/e2e/e2e.test.js +++ b/tests/e2e/e2e.test.js @@ -11,27 +11,22 @@ import { renderStatsCard } from "../../src/cards/stats-card.js"; import { renderTopLanguages } from "../../src/cards/top-languages-card.js"; import { renderWakatimeCard } from "../../src/cards/wakatime-card.js"; -const REPO = "dummy-cra"; -const USER = "grsdummy"; +const REPO = "curly-fiesta"; +const USER = "catelinemnemosyne"; const STATS_DATA = { - name: "grsdummy", - totalPRs: 2, - totalCommits: 2, + name: "Cateline Mnemosyne", + totalPRs: 1, + totalCommits: 7, totalIssues: 1, totalStars: 1, - contributedTo: 2, + contributedTo: 1, rank: { level: "A+", - score: 50.900829325065935, + score: 50.893750297869225, }, }; const LANGS_DATA = { - TypeScript: { - color: "#3178c6", - name: "TypeScript", - size: 2049, - }, HTML: { color: "#e34c26", name: "HTML", @@ -42,19 +37,19 @@ const LANGS_DATA = { name: "CSS", size: 930, }, - Python: { - color: "#3572A5", - name: "Python", - size: 671, + JavaScript: { + color: "#f1e05a", + name: "JavaScript", + size: 1912, }, }; const WAKATIME_DATA = { human_readable_range: "last week", is_already_updating: false, - is_coding_activity_visible: false, + is_coding_activity_visible: true, is_including_today: false, - is_other_usage_visible: false, + is_other_usage_visible: true, is_stuck: false, is_up_to_date: false, is_up_to_date_pending_future: false, @@ -62,24 +57,24 @@ const WAKATIME_DATA = { range: "last_7_days", status: "pending_update", timeout: 15, - username: "grsdummy", + username: USER, writes_only: false, }; const REPOSITORY_DATA = { - name: "dummy-cra", - nameWithOwner: "grsdummy/dummy-cra", + name: "cra-test", + nameWithOwner: `${USER}/cra-test`, isPrivate: false, isArchived: false, isTemplate: false, stargazers: { totalCount: 1, }, - description: "Dummy create react app.", + description: "Simple cra test repo.", primaryLanguage: { - color: "#3178c6", - id: "MDg6TGFuZ3VhZ2UyODc=", - name: "TypeScript", + color: "#f1e05a", + id: "MDg6TGFuZ3VhZ2UxNDA=", + name: "JavaScript", }, forkCount: 0, starCount: 1, From c1dc7b850c3ff0a5db4a60564a4eaf8b9fbcdbda Mon Sep 17 00:00:00 2001 From: rickstaa Date: Sat, 21 Jan 2023 17:58:35 +0100 Subject: [PATCH 14/15] fix: fix e2e test data --- tests/e2e/e2e.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/e2e.test.js b/tests/e2e/e2e.test.js index 4d00646d..402e210f 100644 --- a/tests/e2e/e2e.test.js +++ b/tests/e2e/e2e.test.js @@ -62,7 +62,7 @@ const WAKATIME_DATA = { }; const REPOSITORY_DATA = { - name: "cra-test", + name: REPO, nameWithOwner: `${USER}/cra-test`, isPrivate: false, isArchived: false, From 60fae292a349cd3d92942dc56bf67778c213cb0d Mon Sep 17 00:00:00 2001 From: Rick Staa Date: Sat, 21 Jan 2023 18:32:37 +0100 Subject: [PATCH 15/15] feat: enable multi page star fetching for private vercel instances (#2159) * feat: enable multi-page stars' fetching for private vercel instances This commit enables multi-page stars' support from fetching on private Vercel instances. This feature can be disabled on the public Vercel instance by adding the `FETCH_SINGLE_PAGE_STARS=true` as an env variable in the public Vercel instance. This variable will not be present when people deploy their own Vercel instance, causing the code to fetch multiple star pages. * fix: improve stats multi-page fetching behavoir This commit makes sure that the GraphQL api is only called one time per 100 repositories. The old method added one unnecesairy GraphQL call. * docs: update documentation * style: improve code syntax Co-authored-by: Matteo Pierro * lol happy new year * docs: remove rate limit documentation for now Remove the `FETCH_SINGLE_PAGE_STARS` from documentation for now since it might confuse people. * fix: fix error in automatic merge * feat: make sure env variable is read Co-authored-by: Matteo Pierro Co-authored-by: Anurag --- readme.md | 8 +- src/fetchers/stats-fetcher.js | 207 +++++++++++++++++----------------- tests/api.test.js | 35 ++---- tests/fetchStats.test.js | 126 +++++++++++++++------ 4 files changed, 210 insertions(+), 166 deletions(-) diff --git a/readme.md b/readme.md index 281c4877..678c5c0b 100644 --- a/readme.md +++ b/readme.md @@ -93,7 +93,7 @@ Visit and make a small donation to hel - [Language Card Exclusive Options](#language-card-exclusive-options) - [Wakatime Card Exclusive Option](#wakatime-card-exclusive-options) - [Deploy Yourself](#deploy-on-your-own-vercel-instance) - - [Keep your fork up to date](#keep-your-fork-up-to-date) + - [Keep your fork up to date](#keep-your-fork-up-to-date) # GitHub Stats Card @@ -264,7 +264,7 @@ You can customize the appearance of your `Stats Card` or `Repo Card` however you - `border_radius` - Corner rounding on the card. Default: `4.5`. > **Warning** -> We use caching to decrease the load on our servers (see https://github.com/anuraghazra/github-readme-stats/issues/1471#issuecomment-1271551425). Our cards have a default cache of 4 hours (14400 seconds). Also, note that the cache is clamped to a minimum of 4 hours and a maximum of 24 hours. +> We use caching to decrease the load on our servers (see ). Our cards have a default cache of 4 hours (14400 seconds). Also, note that the cache is clamped to a minimum of 4 hours and a maximum of 24 hours. ##### Gradient in bg_color @@ -354,7 +354,7 @@ Use [show_owner](#customization) variable to include the repo's owner username The top languages card shows a GitHub user's most frequently used top language. > **Note** -> Top Languages does not indicate my skill level or anything like that; it's a GitHub metric to determine which languages have the most code on GitHub. It is a new feature of github-readme-stats._ +> Top Languages does not indicate my skill level or anything like that; it's a GitHub metric to determine which languages have the most code on GitHub. It is a new feature of github-readme-stats. ### Usage @@ -498,7 +498,7 @@ By default, GitHub does not lay out the cards side by side. To do that, you can ## Deploy on your own Vercel instance -#### [Check Out Step By Step Video Tutorial By @codeSTACKr](https://youtu.be/n6d4KHSKqGk?t=107) +#### :film_projector: [Check Out Step By Step Video Tutorial By @codeSTACKr](https://youtu.be/n6d4KHSKqGk?t=107) > **Warning** > If you are on the [hobby (i.e. free)](https://vercel.com/pricing) Vercel plan, please make sure you change the `maxDuration` parameter in the [vercel.json](https://github.com/anuraghazra/github-readme-stats/blob/master/vercel.json) file from `30` to `10` (see [#1416](https://github.com/anuraghazra/github-readme-stats/issues/1416#issuecomment-950275476) for more information). diff --git a/src/fetchers/stats-fetcher.js b/src/fetchers/stats-fetcher.js index 7f6cb9e5..a7df1e50 100644 --- a/src/fetchers/stats-fetcher.js +++ b/src/fetchers/stats-fetcher.js @@ -1,5 +1,6 @@ // @ts-check import axios from "axios"; +import * as dotenv from "dotenv"; import githubUsernameRegex from "github-username-regex"; import { calculateRank } from "../calculateRank.js"; import { retryer } from "../common/retryer.js"; @@ -11,46 +12,74 @@ import { wrapTextMultiline, } from "../common/utils.js"; +dotenv.config(); + +// GraphQL queries. +const GRAPHQL_REPOS_FIELD = ` + repositories(first: 100, ownerAffiliations: OWNER, orderBy: {direction: DESC, field: STARGAZERS}, after: $after) { + totalCount + nodes { + name + stargazers { + totalCount + } + } + pageInfo { + hasNextPage + endCursor + } + } +`; + +const GRAPHQL_REPOS_QUERY = ` + query userInfo($login: String!, $after: String) { + user(login: $login) { + ${GRAPHQL_REPOS_FIELD} + } + } +`; + +const GRAPHQL_STATS_QUERY = ` + query userInfo($login: String!, $after: String) { + user(login: $login) { + name + login + contributionsCollection { + totalCommitContributions + restrictedContributionsCount + } + repositoriesContributedTo(first: 1, contributionTypes: [COMMIT, ISSUE, PULL_REQUEST, REPOSITORY]) { + totalCount + } + pullRequests(first: 1) { + totalCount + } + openIssues: issues(states: OPEN) { + totalCount + } + closedIssues: issues(states: CLOSED) { + totalCount + } + followers { + totalCount + } + ${GRAPHQL_REPOS_FIELD} + } + } +`; + /** * Stats fetcher object. * * @param {import('axios').AxiosRequestHeaders} variables Fetcher variables. * @param {string} token GitHub token. - * @returns {Promise} Stats fetcher response. + * @returns {Promise} Stats fetcher response. */ const fetcher = (variables, token) => { + const query = !variables.after ? GRAPHQL_STATS_QUERY : GRAPHQL_REPOS_QUERY; return request( { - query: ` - query userInfo($login: String!) { - user(login: $login) { - name - login - contributionsCollection { - totalCommitContributions - restrictedContributionsCount - } - repositoriesContributedTo(contributionTypes: [COMMIT, ISSUE, PULL_REQUEST, REPOSITORY]) { - totalCount - } - pullRequests { - totalCount - } - openIssues: issues(states: OPEN) { - totalCount - } - closedIssues: issues(states: CLOSED) { - totalCount - } - followers { - totalCount - } - repositories(ownerAffiliations: OWNER) { - totalCount - } - } - } - `, + query, variables, }, { @@ -60,39 +89,42 @@ const fetcher = (variables, token) => { }; /** - * Fetch first 100 repositories for a given username. + * Fetch stats information for a given username. * - * @param {import('axios').AxiosRequestHeaders} variables Fetcher variables. - * @param {string} token GitHub token. - * @returns {Promise} Repositories fetcher response. + * @param {string} username Github username. + * @returns {Promise} GraphQL Stats object. + * + * @description This function supports multi-page fetching if the 'FETCH_MULTI_PAGE_STARS' environment variable is set to true. */ -const repositoriesFetcher = (variables, token) => { - return request( - { - query: ` - query userInfo($login: String!, $after: String) { - user(login: $login) { - repositories(first: 100, ownerAffiliations: OWNER, orderBy: {direction: DESC, field: STARGAZERS}, after: $after) { - nodes { - name - stargazers { - totalCount - } - } - pageInfo { - hasNextPage - endCursor - } - } - } - } - `, - variables, - }, - { - Authorization: `bearer ${token}`, - }, - ); +const statsFetcher = async (username) => { + let stats; + let hasNextPage = true; + let endCursor = null; + while (hasNextPage) { + const variables = { login: username, first: 100, after: endCursor }; + let res = await retryer(fetcher, variables); + if (res.data.errors) return res; + + // Store stats data. + const repoNodes = res.data.data.user.repositories.nodes; + if (!stats) { + stats = res; + } else { + stats.data.data.user.repositories.nodes.push(...repoNodes); + } + + // Disable multi page fetching on public Vercel instance due to rate limits. + const repoNodesWithStars = repoNodes.filter( + (node) => node.stargazers.totalCount !== 0, + ); + hasNextPage = + process.env.FETCH_MULTI_PAGE_STARS === "true" && + repoNodes.length === repoNodesWithStars.length && + res.data.data.user.repositories.pageInfo.hasNextPage; + endCursor = res.data.data.user.repositories.pageInfo.endCursor; + } + + return stats; }; /** @@ -137,46 +169,6 @@ const totalCommitsFetcher = async (username) => { return 0; }; -/** - * Fetch all the stars for all the repositories of a given username. - * - * @param {string} username GitHub username. - * @param {array} repoToHide Repositories to hide. - * @returns {Promise} Total stars. - */ -const totalStarsFetcher = async (username, repoToHide) => { - let nodes = []; - let hasNextPage = true; - let endCursor = null; - while (hasNextPage) { - const variables = { login: username, first: 100, after: endCursor }; - let res = await retryer(repositoriesFetcher, variables); - - if (res.data.errors) { - logger.error(res.data.errors); - throw new CustomError( - res.data.errors[0].message || "Could not fetch user", - CustomError.USER_NOT_FOUND, - ); - } - - const allNodes = res.data.data.user.repositories.nodes; - const nodesWithStars = allNodes.filter( - (node) => node.stargazers.totalCount !== 0, - ); - nodes.push(...nodesWithStars); - // hasNextPage = - // allNodes.length === nodesWithStars.length && - // res.data.data.user.repositories.pageInfo.hasNextPage; - hasNextPage = false; // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130. - endCursor = res.data.data.user.repositories.pageInfo.endCursor; - } - - return nodes - .filter((data) => !repoToHide[data.name]) - .reduce((prev, curr) => prev + curr.stargazers.totalCount, 0); -}; - /** * Fetch stats for a given username. * @@ -203,7 +195,7 @@ const fetchStats = async ( rank: { level: "C", score: 0 }, }; - let res = await retryer(fetcher, { login: username }); + let res = await statsFetcher(username); // Catch GraphQL errors. if (res.data.errors) { @@ -259,8 +251,15 @@ const fetchStats = async ( stats.contributedTo = user.repositoriesContributedTo.totalCount; // Retrieve stars while filtering out repositories to be hidden - stats.totalStars = await totalStarsFetcher(username, repoToHide); + stats.totalStars = user.repositories.nodes + .filter((data) => { + return !repoToHide[data.name]; + }) + .reduce((prev, curr) => { + return prev + curr.stargazers.totalCount; + }, 0); + // @ts-ignore // TODO: Fix this. stats.rank = calculateRank({ totalCommits: stats.totalCommits, totalRepos: user.repositories.totalCount, diff --git a/tests/api.test.js b/tests/api.test.js index 0037bcdb..461f3e18 100644 --- a/tests/api.test.js +++ b/tests/api.test.js @@ -25,7 +25,7 @@ stats.rank = calculateRank({ issues: stats.totalIssues, }); -const data = { +const data_stats = { data: { user: { name: stats.name, @@ -40,15 +40,6 @@ const data = { followers: { totalCount: 0 }, repositories: { totalCount: 1, - }, - }, - }, -}; - -const repositoriesData = { - data: { - user: { - repositories: { nodes: [{ stargazers: { totalCount: 100 } }], pageInfo: { hasNextPage: false, @@ -83,11 +74,7 @@ const faker = (query, data) => { setHeader: jest.fn(), send: jest.fn(), }; - mock - .onPost("https://api.github.com/graphql") - .replyOnce(200, data) - .onPost("https://api.github.com/graphql") - .replyOnce(200, repositoriesData); + mock.onPost("https://api.github.com/graphql").replyOnce(200, data); return { req, res }; }; @@ -98,7 +85,7 @@ afterEach(() => { describe("Test /api/", () => { it("should test the request", async () => { - const { req, res } = faker({}, data); + const { req, res } = faker({}, data_stats); await api(req, res); @@ -133,7 +120,7 @@ describe("Test /api/", () => { text_color: "fff", bg_color: "fff", }, - data, + data_stats, ); await api(req, res); @@ -154,7 +141,7 @@ describe("Test /api/", () => { }); it("should have proper cache", async () => { - const { req, res } = faker({}, data); + const { req, res } = faker({}, data_stats); await api(req, res); @@ -170,7 +157,7 @@ describe("Test /api/", () => { }); it("should set proper cache", async () => { - const { req, res } = faker({ cache_seconds: 15000 }, data); + const { req, res } = faker({ cache_seconds: 15000 }, data_stats); await api(req, res); expect(res.setHeader.mock.calls).toEqual([ @@ -196,7 +183,7 @@ describe("Test /api/", () => { it("should set proper cache with clamped values", async () => { { - let { req, res } = faker({ cache_seconds: 200000 }, data); + let { req, res } = faker({ cache_seconds: 200000 }, data_stats); await api(req, res); expect(res.setHeader.mock.calls).toEqual([ @@ -212,7 +199,7 @@ describe("Test /api/", () => { // note i'm using block scoped vars { - let { req, res } = faker({ cache_seconds: 0 }, data); + let { req, res } = faker({ cache_seconds: 0 }, data_stats); await api(req, res); expect(res.setHeader.mock.calls).toEqual([ @@ -227,7 +214,7 @@ describe("Test /api/", () => { } { - let { req, res } = faker({ cache_seconds: -10000 }, data); + let { req, res } = faker({ cache_seconds: -10000 }, data_stats); await api(req, res); expect(res.setHeader.mock.calls).toEqual([ @@ -248,7 +235,7 @@ describe("Test /api/", () => { username: "anuraghazra", count_private: true, }, - data, + data_stats, ); await api(req, res); @@ -288,7 +275,7 @@ describe("Test /api/", () => { text_color: "fff", bg_color: "fff", }, - data, + data_stats, ); await api(req, res); diff --git a/tests/fetchStats.test.js b/tests/fetchStats.test.js index 192146ea..04e943a7 100644 --- a/tests/fetchStats.test.js +++ b/tests/fetchStats.test.js @@ -4,7 +4,8 @@ import MockAdapter from "axios-mock-adapter"; import { calculateRank } from "../src/calculateRank.js"; import { fetchStats } from "../src/fetchers/stats-fetcher.js"; -const data = { +// Test parameters. +const data_stats = { data: { user: { name: "Anurag Hazra", @@ -19,15 +20,6 @@ const data = { followers: { totalCount: 100 }, repositories: { totalCount: 5, - }, - }, - }, -}; - -const firstRepositoriesData = { - data: { - user: { - repositories: { nodes: [ { name: "test-repo-1", stargazers: { totalCount: 100 } }, { name: "test-repo-2", stargazers: { totalCount: 100 } }, @@ -42,7 +34,7 @@ const firstRepositoriesData = { }, }; -const secondRepositoriesData = { +const data_repo = { data: { user: { repositories: { @@ -59,7 +51,7 @@ const secondRepositoriesData = { }, }; -const repositoriesWithZeroStarsData = { +const data_repo_zero_stars = { data: { user: { repositories: { @@ -93,13 +85,12 @@ const error = { const mock = new MockAdapter(axios); beforeEach(() => { + process.env.FETCH_MULTI_PAGE_STARS = "false"; // Set to `false` to fetch only one page of stars. mock .onPost("https://api.github.com/graphql") - .replyOnce(200, data) + .replyOnce(200, data_stats) .onPost("https://api.github.com/graphql") - .replyOnce(200, firstRepositoriesData); - // .onPost("https://api.github.com/graphql") // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130. - // .replyOnce(200, secondRepositoriesData); // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130. + .replyOnce(200, data_repo); }); afterEach(() => { @@ -114,8 +105,7 @@ describe("Test fetchStats", () => { totalRepos: 5, followers: 100, contributions: 61, - // stargazers: 400, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130. - stargazers: 300, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130. + stargazers: 300, prs: 300, issues: 200, }); @@ -126,8 +116,7 @@ describe("Test fetchStats", () => { totalCommits: 100, totalIssues: 200, totalPRs: 300, - // totalStars: 400, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130. - totalStars: 300, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130. + totalStars: 300, rank, }); }); @@ -136,9 +125,9 @@ describe("Test fetchStats", () => { mock.reset(); mock .onPost("https://api.github.com/graphql") - .replyOnce(200, data) + .replyOnce(200, data_stats) .onPost("https://api.github.com/graphql") - .replyOnce(200, repositoriesWithZeroStarsData); + .replyOnce(200, data_repo_zero_stars); let stats = await fetchStats("anuraghazra"); const rank = calculateRank({ @@ -178,8 +167,7 @@ describe("Test fetchStats", () => { totalRepos: 5, followers: 100, contributions: 61, - // stargazers: 400, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130. - stargazers: 300, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130. + stargazers: 300, prs: 300, issues: 200, }); @@ -190,8 +178,7 @@ describe("Test fetchStats", () => { totalCommits: 150, totalIssues: 200, totalPRs: 300, - // totalStars: 400, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130. - totalStars: 300, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130. + totalStars: 300, rank, }); }); @@ -207,8 +194,7 @@ describe("Test fetchStats", () => { totalRepos: 5, followers: 100, contributions: 61, - // stargazers: 400, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130. - stargazers: 300, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130. + stargazers: 300, prs: 300, issues: 200, }); @@ -219,8 +205,7 @@ describe("Test fetchStats", () => { totalCommits: 1050, totalIssues: 200, totalPRs: 300, - // totalStars: 400, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130. - totalStars: 300, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130. + totalStars: 300, rank, }); }); @@ -236,8 +221,7 @@ describe("Test fetchStats", () => { totalRepos: 5, followers: 100, contributions: 61, - // stargazers: 300, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130. - stargazers: 200, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130. + stargazers: 200, prs: 300, issues: 200, }); @@ -248,8 +232,82 @@ describe("Test fetchStats", () => { totalCommits: 1050, totalIssues: 200, totalPRs: 300, - // totalStars: 300, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130. - totalStars: 200, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130. + totalStars: 200, + rank, + }); + }); + + it("should fetch two pages of stars if 'FETCH_MULTI_PAGE_STARS' env variable is set to `true`", async () => { + process.env.FETCH_MULTI_PAGE_STARS = true; + + let stats = await fetchStats("anuraghazra"); + const rank = calculateRank({ + totalCommits: 100, + totalRepos: 5, + followers: 100, + contributions: 61, + stargazers: 400, + prs: 300, + issues: 200, + }); + + expect(stats).toStrictEqual({ + contributedTo: 61, + name: "Anurag Hazra", + totalCommits: 100, + totalIssues: 200, + totalPRs: 300, + totalStars: 400, + rank, + }); + }); + + it("should fetch one page of stars if 'FETCH_MULTI_PAGE_STARS' env variable is set to `false`", async () => { + process.env.FETCH_MULTI_PAGE_STARS = "false"; + + let stats = await fetchStats("anuraghazra"); + const rank = calculateRank({ + totalCommits: 100, + totalRepos: 5, + followers: 100, + contributions: 61, + stargazers: 300, + prs: 300, + issues: 200, + }); + + expect(stats).toStrictEqual({ + contributedTo: 61, + name: "Anurag Hazra", + totalCommits: 100, + totalIssues: 200, + totalPRs: 300, + totalStars: 300, + rank, + }); + }); + + it("should fetch one page of stars if 'FETCH_MULTI_PAGE_STARS' env variable is not set", async () => { + process.env.FETCH_MULTI_PAGE_STARS = undefined; + + let stats = await fetchStats("anuraghazra"); + const rank = calculateRank({ + totalCommits: 100, + totalRepos: 5, + followers: 100, + contributions: 61, + stargazers: 300, + prs: 300, + issues: 200, + }); + + expect(stats).toStrictEqual({ + contributedTo: 61, + name: "Anurag Hazra", + totalCommits: 100, + totalIssues: 200, + totalPRs: 300, + totalStars: 300, rank, }); });