From 428edf37fba479f245a996f6a2d417d03af74317 Mon Sep 17 00:00:00 2001 From: forgejo-backport-action Date: Wed, 13 Aug 2025 23:06:30 +0200 Subject: [PATCH] [v12.0/forgejo] fix: compare week as numbers and not as strings (#8887) **Backport:** https://codeberg.org/forgejo/forgejo/pulls/8882 The repository contributors graph received the stats for each author for each week, these weeks are stored as unix milis values, `Object.entries` converted these values to strings and `sort()` would thus sort them as strings - this worked without a problem for most repository. If a repository has commits from before 'Sun Sep 9 03:46:40 AM CEST 2001', it meant that the weeks when those commits were made would be sorted towards the end because "1000000000" > "999999999" (when compared as strings) and would thus be silently cut from the data. This edge-case was seen by the curl repository (https://mastodon.social/@bagder/115018271785548165) Sort them as numbers to avoid this problem, it being stored as strings is otherwise not a problem. Co-authored-by: Gusted Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8887 Reviewed-by: Gusted Reviewed-by: Beowulf Co-authored-by: forgejo-backport-action Co-committed-by: forgejo-backport-action --- .../js/components/RepoContributors.test.js | 76 +++++++++++++++++++ web_src/js/components/RepoContributors.vue | 2 +- web_src/js/vitest.setup.js | 4 + 3 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 web_src/js/components/RepoContributors.test.js diff --git a/web_src/js/components/RepoContributors.test.js b/web_src/js/components/RepoContributors.test.js new file mode 100644 index 0000000000..d97a862d2d --- /dev/null +++ b/web_src/js/components/RepoContributors.test.js @@ -0,0 +1,76 @@ +import {flushPromises, mount} from '@vue/test-utils'; +import RepoContributors from './RepoContributors.vue'; + +test('has commits from before 2001', async () => { + vi.spyOn(global, 'fetch').mockResolvedValue({ + json: vi.fn().mockResolvedValue({ + 'daniel@haxx.se': { + name: 'Daniel Stenberg', + total_commits: 13, + weeks: { + 1754179200000: { + week: 1754179200000, + additions: 4330, + deletions: 47, + commits: 10, + }, + 946166400000: { + week: 946166400000, + additions: 37273, + deletions: 0, + commits: 1, + }, + }, + }, + total: { + name: 'Total', + total_commits: 11, + weeks: { + 1754179200000: { + week: 1754179200000, + additions: 4330, + deletions: 47, + commits: 10, + }, + 946166400000: { + week: 946166400000, + additions: 37273, + deletions: 0, + commits: 1, + }, + }, + }, + }), + ok: true, + }); + + const repoContributorsGraph = mount(RepoContributors, { + global: { + stubs: { + 'relative-time': { + template: 'relative time', + }, + }, + }, + props: { + repoLink: '', + repoDefaultBranchName: '', + locale: { + filterLabel: '', + contributionType: { + commits: '', + additions: '', + deletions: '', + }, + + loadingTitle: '', + loadingTitleFailed: '', + loadingInfo: '', + }, + }, + }); + await flushPromises(); + + expect(repoContributorsGraph.componentVM.xAxisStart).toBe(946166400000); + expect(repoContributorsGraph.componentVM.contributorsStats['daniel@haxx.se'].weeks[0].week).toBe(946166400000); +}); diff --git a/web_src/js/components/RepoContributors.vue b/web_src/js/components/RepoContributors.vue index 5e03019ef1..4b15c3714b 100644 --- a/web_src/js/components/RepoContributors.vue +++ b/web_src/js/components/RepoContributors.vue @@ -125,7 +125,7 @@ export default { const data = await response.json(); const {total, ...rest} = data; // below line might be deleted if we are sure go produces map always sorted by keys - total.weeks = Object.fromEntries(Object.entries(total.weeks).sort()); + total.weeks = Object.fromEntries(Object.entries(total.weeks).map((x) => [parseInt(x[0]), x[1]]).sort((a, b) => a[0] - b[0])); const weekValues = Object.values(total.weeks); this.xAxisStart = weekValues[0].week; diff --git a/web_src/js/vitest.setup.js b/web_src/js/vitest.setup.js index 5366958fb5..a99b852097 100644 --- a/web_src/js/vitest.setup.js +++ b/web_src/js/vitest.setup.js @@ -1,3 +1,7 @@ +import $ from 'jquery'; + +$.fn.dropdown = () => undefined; + window.__webpack_public_path__ = ''; window.config = {