Repository: anuraghazra/github-readme-stats
Pull request #2657 (2023-04-28 11:42:20)

test: fix mistaken pageInfo.endCursor keys
```
The previous mock logic was too simplistic and has been fixed in the
commit. If the mock logic had been properly implemented, then the
mistaken pageInfo.endCursor keys should have made the test case "should
fetch two pages of stars if 'FETCH_MULTI_PAGE_STARS' env variable is set
to `true`" stuck.
```

See also https://github.com/anuraghazra/github-readme-stats/pull/1691#issuecomment-1527401508

vercel[bot]: @Rongronggg9 is attempting to deploy a commit to the **github readme stats** Team on [Vercel](https://vercel.com).

A member of the Team first needs to [authorize it](https://vercel.com/git/authorize?team=github%20readme%20stats&type=github&job=%7B%22headInfo%22%3A%7B%22sha%22%3A%22654dc32152cbdb62593eac0d742c418f5dce1995%22%7D%2C%22id%22%3A%22Qmdy6UQ3JQ8dTTk9ntggrba8udSWxqRQHvwdNbTz8LdwnP%22%2C%22org%22%3A%22anuraghazra%22%2C%22prId%22%3A2657%2C%22repo%22%3A%22github-readme-stats%22%7D).



Patch:
diff --git a/.github/workflows/prs-cache-clean.yml b/.github/workflows/prs-cache-clean.yml
new file mode 100644
index 0000000..8ee4670
--- /dev/null
+++ b/.github/workflows/prs-cache-clean.yml
@@ -0,0 +1,33 @@
+name: prs cache clean
+on:
+  pull_request:
+    types:
+      - closed
+
+jobs:
+  cleanup:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v3
+
+      - name: Cleanup
+        run: |
+          gh extension install actions/gh-actions-cache
+
+          REPO=${{ github.repository }}
+          BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge"
+
+          echo "Fetching list of cache key"
+          cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH | cut -f 1 )
+
+          ## Setting this to not fail the workflow while deleting cache keys. 
+          set +e
+          echo "Deleting caches..."
+          for cacheKey in $cacheKeysForPR
+          do
+              gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
+          done
+          echo "Done"
+        env:
+          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/package-lock.json b/package-lock.json
index ebc7570..a378d89 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5581,9 +5581,9 @@
       "dev": true
     },
     "node_modules/yaml": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.3.tgz",
-      "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==",
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz",
+      "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==",
       "dev": true,
       "engines": {
         "node": ">= 14"
@@ -9855,9 +9855,9 @@
       "dev": true
     },
     "yaml": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.3.tgz",
-      "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==",
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz",
+      "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==",
       "dev": true
     },
     "yargs": {
diff --git a/readme.md b/readme.md
index 538b4e8..a95022b 100644
--- a/readme.md
+++ b/readme.md
@@ -363,6 +363,16 @@ The top languages card shows a GitHub user's most frequently used top language.
 > **Note**
 > Top Languages does not indicate the user's 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
+
+Copy-paste this code into your readme and change the links.
+
+Endpoint: `api/top-langs?username=anuraghazra`
+
+```md
+[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra)](https://github.com/anuraghazra/github-readme-stats)
+```
+
 ### Language stats algorithm
 
 We use the following algorithm to calculate the languages percentages on the language card:
@@ -381,16 +391,6 @@ By default, only the byte count is used for determining the languages percentage
 [![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&size_weight=0.5&count_weight=0.5)](https://github.com/anuraghazra/github-readme-stats)
 ```
 
-### Usage
-
-Copy-paste this code into your readme and change the links.
-
-Endpoint: `api/top-langs?username=anuraghazra`
-
-```md
-[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra)](https://github.com/anuraghazra/github-readme-stats)
-```
-
 ### Exclude individual repositories
 
 You can use the `&exclude_repo=repo1,repo2` parameter to exclude individual repositories.
@@ -456,13 +456,13 @@ Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
 
 ### Demo
 
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
 
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
 
 -   Compact layout
 
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
 
 * * *
 
@@ -520,7 +520,7 @@ Choose from any of the [default themes](#themes)
 
 -   WakaTime card
 
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
 
 * * *
 
diff --git a/src/calculateRank.js b/src/calculateRank.js
index 24845bc..215c24d 100644
--- a/src/calculateRank.js
+++ b/src/calculateRank.js
@@ -29,13 +29,14 @@ const normalcdf = (mean, sigma, to) => {
 /**
  * Calculates the users rank.
  *
- * @param {number} totalRepos Total number of repos.
- * @param {number} totalCommits Total number of commits.
- * @param {number} contributions The number of contributions.
- * @param {number} followers The number of followers.
- * @param {number} prs The number of pull requests.
- * @param {number} issues The number of issues.
- * @param {number} stargazers The number of stars.
+ * @param {object} params Parameters on which the user's rank depends.
+ * @param {number} params.totalRepos Total number of repos.
+ * @param {number} params.totalCommits Total number of commits.
+ * @param {number} params.contributions The number of contributions.
+ * @param {number} params.followers The number of followers.
+ * @param {number} params.prs The number of pull requests.
+ * @param {number} params.issues The number of issues.
+ * @param {number} params.stargazers The number of stars.
  * @returns {{level: string, score: number}}} The users rank.
  */
 const calculateRank = ({
diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js
index 92701d8..4761d02 100644
--- a/src/cards/stats-card.js
+++ b/src/cards/stats-card.js
@@ -20,14 +20,16 @@ const RANK_CARD_DEFAULT_WIDTH = 450;
 /**
  * Create a stats card text item.
  *
- * @param {object[]} createTextNodeParams Object that contains the createTextNode parameters.
+ * @param {object} createTextNodeParams Object that contains the createTextNode parameters.
+ * @param {string} createTextNodeParams.icon The icon to display.
  * @param {string} createTextNodeParams.label The label to display.
- * @param {string} createTextNodeParams.value The value to display.
+ * @param {number} createTextNodeParams.value The value to display.
  * @param {string} createTextNodeParams.id The id of the stat.
  * @param {number} createTextNodeParams.index The index of the stat.
  * @param {boolean} createTextNodeParams.showIcons Whether to show icons.
  * @param {number} createTextNodeParams.shiftValuePos Number of pixels the value has to be shifted to the right.
  * @param {boolean} createTextNodeParams.bold Whether to bold the label.
+ * @param {string} createTextNodeParams.number_format The format of numbers on card.
  * @returns
  */
 const createTextNode = ({
diff --git a/src/cards/wakatime-card.js b/src/cards/wakatime-card.js
index 2c32955..0b23667 100644
--- a/src/cards/wakatime-card.js
+++ b/src/cards/wakatime-card.js
@@ -36,11 +36,11 @@ const noCodingActivityNode = ({ color, text }) => {
 /**
  * Create compact WakaTime layout.
  *
- * @param {Object[]} args The function arguments.
- * @param {import("../fetchers/types").WakaTimeLang[]} languages The languages array.
- * @param {number} totalSize The total size of the languages.
- * @param {number} x The x position of the language node.
- * @param {number} y The y position of the language node.
+ * @param {Object} args The function arguments.
+ * @param {import("../fetchers/types").WakaTimeLang} args.lang The languages array.
+ * @param {number} args.totalSize The total size of the languages.
+ * @param {number} args.x The x position of the language node.
+ * @param {number} args.y The y position of the language node.
  */
 const createCompactLangNode = ({ lang, totalSize, x, y }) => {
   const color = languageColors[lang.name] || "#858585";
@@ -58,11 +58,11 @@ const createCompactLangNode = ({ lang, totalSize, x, y }) => {
 /**
  * Create WakaTime language text node item.
  *
- * @param {Object[]} args The function arguments.
- * @param {import("../fetchers/types").WakaTimeLang} lang The language object.
- * @param {number} totalSize The total size of the languages.
- * @param {number} x The x position of the language node.
- * @param {number} y The y position of the language node.
+ * @param {Object} args The function arguments.
+ * @param {import("../fetchers/types").WakaTimeLang[]} args.langs The language objects.
+ * @param {number} args.totalSize The total size of the languages.
+ * @param {number} args.x The x position of the language node.
+ * @param {number} args.y The y position of the language node.
  */
 const createLanguageTextNode = ({ langs, totalSize, x, y }) => {
   return langs.map((lang, index) => {
@@ -86,14 +86,15 @@ const createLanguageTextNode = ({ langs, totalSize, x, y }) => {
 /**
  * Create WakaTime text item.
  *
- * @param {Object[]} args The function arguments.
- * @param {string} id The id of the text node item.
- * @param {string} label The label of the text node item.
- * @param {string} value The value of the text node item.
- * @param {number} index The index of the text node item.
- * @param {percent} percent Percentage of the text node item.
- * @param {boolean} hideProgress Whether to hide the progress bar.
- * @param {string} progressBarBackgroundColor The color of the progress bar background.
+ * @param {Object} args The function arguments.
+ * @param {string} args.id The id of the text node item.
+ * @param {string} args.label The label of the text node item.
+ * @param {string} args.value The value of the text node item.
+ * @param {number} args.index The index of the text node item.
+ * @param {string} args.percent Percentage of the text node item.
+ * @param {boolean} args.hideProgress Whether to hide the progress bar.
+ * @param {string} args.progressBarColor The color of the progress bar.
+ * @param {string} args.progressBarBackgroundColor The color of the progress bar background.
  */
 const createTextNode = ({
   id,
@@ -267,12 +268,20 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
       <rect x="25" y="0" width="${width - 50}" height="8" fill="white" rx="5" />
       </mask>
       ${compactProgressBar}
-      ${createLanguageTextNode({
-        x: 0,
-        y: 25,
-        langs: filteredLanguages,
-        totalSize: 100,
-      }).join("")}
+      ${
+        filteredLanguages.length
+          ? createLanguageTextNode({
+              x: 0,
+              y: 25,
+              langs: filteredLanguages,
+              totalSize: 100,
+            }).join("")
+          : noCodingActivityNode({
+              // @ts-ignore
+              color: textColor,
+              text: i18n.t("wakatimecard.nocodingactivity"),
+            })
+      }
     `;
   } else {
     finalLayout = flexLayout({
diff --git a/src/common/Card.js b/src/common/Card.js
index 2f1d9c2..c61b17d 100644
--- a/src/common/Card.js
+++ b/src/common/Card.js
@@ -12,6 +12,12 @@ class Card {
    * @param {string?=} args.customTitle Card custom title.
    * @param {string?=} args.defaultTitle Card default title.
    * @param {string?=} args.titlePrefixIcon Card title prefix icon.
+   * @param {object?=} args.colors Card colors arguments.
+   * @param {string} args.colors.titleColor Card title color.
+   * @param {string} args.colors.textColor Card text color.
+   * @param {string} args.colors.iconColor Card icon color.
+   * @param {string|Array} args.colors.bgColor Card background color.
+   * @param {string} args.colors.borderColor Card border color.
    * @returns {Card} Card instance.
    */
   constructor({
diff --git a/src/common/utils.js b/src/common/utils.js
index f825446..47e1061 100644
--- a/src/common/utils.js
+++ b/src/common/utils.js
@@ -194,15 +194,15 @@ const flexLayout = ({ items, gap, direction, sizes = [] }) => {
 /**
  * Returns theme based colors with proper overrides and defaults.
  *
- * @param {Object[]} args Function arguments.
+ * @param {Object} args Function arguments.
  * @param {string} args.title_color Card title color.
  * @param {string} args.text_color Card text color.
  * @param {string} args.icon_color Card icon color.
  * @param {string} args.bg_color Card background color.
  * @param {string} args.border_color Card border color.
+ * @param {string} args.ring_color Card ring color.
  * @param {string} args.theme Card theme.
  * @param {string} args.fallbackTheme Fallback theme.
- *
  */
 const getCardColors = ({
   title_color,
diff --git a/src/fetchers/stats-fetcher.js b/src/fetchers/stats-fetcher.js
index fc06fce..8603e38 100644
--- a/src/fetchers/stats-fetcher.js
+++ b/src/fetchers/stats-fetcher.js
@@ -259,7 +259,6 @@ const fetchStats = async (
       return prev + curr.stargazers.totalCount;
     }, 0);
 
-  // @ts-ignore // TODO: Fix this.
   stats.rank = calculateRank({
     totalCommits: stats.totalCommits,
     totalRepos: user.repositories.totalCount,
diff --git a/src/fetchers/wakatime-fetcher.js b/src/fetchers/wakatime-fetcher.js
index fa1f3d8..2af8fa9 100644
--- a/src/fetchers/wakatime-fetcher.js
+++ b/src/fetchers/wakatime-fetcher.js
@@ -14,7 +14,9 @@ const fetchWakatimeStats = async ({ username, api_domain, range }) => {
     const { data } = await axios.get(
       `https://${
         api_domain ? api_domain.replace(/\/$/gi, "") : "wakatime.com"
-      }/api/v1/users/${username}/stats/${range || ""}?is_including_today=true`,
+      }/api/v1/users/${username}/stats/${
+        range || "all_time"
+      }?is_including_today=true`,
     );
 
     return data.data;


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index fe34668..e8fc84a 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -34,4 +34,4 @@ jobs:
           npm run format:check
 
       - name: Code Coverage
-        uses: codecov/codecov-action@v1
+        uses: codecov/codecov-action@v3
diff --git a/tests/api.test.js b/tests/api.test.js
index 461f3e1..f11832e 100644
--- a/tests/api.test.js
+++ b/tests/api.test.js
@@ -43,7 +43,7 @@ const data_stats = {
         nodes: [{ stargazers: { totalCount: 100 } }],
         pageInfo: {
           hasNextPage: false,
-          cursor: "cursor",
+          endCursor: "cursor",
         },
       },
     },
diff --git a/tests/fetchStats.test.js b/tests/fetchStats.test.js
index 04e943a..08523f3 100644
--- a/tests/fetchStats.test.js
+++ b/tests/fetchStats.test.js
@@ -27,7 +27,7 @@ const data_stats = {
         ],
         pageInfo: {
           hasNextPage: true,
-          cursor: "cursor",
+          endCursor: "cursor",
         },
       },
     },
@@ -44,7 +44,7 @@ const data_repo = {
         ],
         pageInfo: {
           hasNextPage: false,
-          cursor: "cursor",
+          endCursor: "cursor",
         },
       },
     },
@@ -64,7 +64,7 @@ const data_repo_zero_stars = {
         ],
         pageInfo: {
           hasNextPage: true,
-          cursor: "cursor",
+          endCursor: "cursor",
         },
       },
     },
@@ -86,11 +86,12 @@ 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_stats)
-    .onPost("https://api.github.com/graphql")
-    .replyOnce(200, data_repo);
+  mock.onPost("https://api.github.com/graphql").reply((cfg) => {
+    return [
+      200,
+      cfg.data.includes("contributionsCollection") ? data_stats : data_repo,
+    ];
+  });
 });
 
 afterEach(() => {
diff --git a/tests/fetchWakatime.test.js b/tests/fetchWakatime.test.js
index 47ca25b..04c01ba 100644
--- a/tests/fetchWakatime.test.js
+++ b/tests/fetchWakatime.test.js
@@ -105,7 +105,7 @@ describe("Wakatime fetcher", () => {
     const username = "anuraghazra";
     mock
       .onGet(
-        `https://wakatime.com/api/v1/users/${username}/stats/?is_including_today=true`,
+        `https://wakatime.com/api/v1/users/${username}/stats/all_time?is_including_today=true`,
       )
       .reply(200, wakaTimeData);
 
diff --git a/tests/renderWakatimeCard.test.js b/tests/renderWakatimeCard.test.js
index 25e7ab4..630f259 100644
--- a/tests/renderWakatimeCard.test.js
+++ b/tests/renderWakatimeCard.test.js
@@ -67,4 +67,19 @@ describe("Test Render Wakatime Card", () => {
       "No coding activity this week",
     );
   });
+
+  it('should show "no coding activity this week" message when using compact layout and there has not been activity', () => {
+    document.body.innerHTML = renderWakatimeCard(
+      {
+        ...wakaTimeData.data,
+        languages: undefined,
+      },
+      {
+        layout: "compact",
+      },
+    );
+    expect(document.querySelector(".stat").textContent).toBe(
+      "No coding activity this week",
+    );
+  });
 });