返回 DeepSeek-Reasonix
update-star-history.test.mjs
根目录 / scripts / update-star-history.test.mjs
1 import assert from 'node:assert/strict';
2 import test from 'node:test';
3
4 import {
5 buildDailySeries,
6 fetchAllStargazers,
7 parseLinkHeader,
8 renderStarHistorySvg,
9 } from './update-star-history.mjs';
10
11 test('parseLinkHeader extracts pagination relationships', () => {
12 assert.deepEqual(
13 parseLinkHeader(
14 '<https://api.github.com/example?page=2>; rel="next", <https://api.github.com/example?page=4>; rel="last"',
15 ),
16 {
17 next: 'https://api.github.com/example?page=2',
18 last: 'https://api.github.com/example?page=4',
19 },
20 );
21 });
22
23 test('fetchAllStargazers follows every page and requests starred_at timestamps', async () => {
24 const requests = [];
25 const fakeFetch = async (url, options) => {
26 requests.push({ url: String(url), headers: options.headers });
27 const page = new URL(url).searchParams.get('page');
28 const body =
29 page === '1'
30 ? [{ starred_at: '2026-07-19T01:00:00Z' }]
31 : [{ starred_at: '2026-07-20T01:00:00Z' }];
32 return new Response(JSON.stringify(body), {
33 headers:
34 page === '1'
35 ? {
36 link: '<https://api.github.com/repos/example/repo/stargazers?per_page=100&page=2>; rel="next", <https://api.github.com/repos/example/repo/stargazers?per_page=100&page=2>; rel="last"',
37 }
38 : {},
39 status: 200,
40 });
41 };
42
43 assert.deepEqual(
44 await fetchAllStargazers({
45 repository: 'example/repo',
46 token: 'fake-token',
47 fetchImpl: fakeFetch,
48 }),
49 ['2026-07-19T01:00:00Z', '2026-07-20T01:00:00Z'],
50 );
51 assert.equal(requests.length, 2);
52 assert.equal(requests[0].headers.Accept, 'application/vnd.github.star+json');
53 assert.equal(requests[0].headers.Authorization, 'Bearer fake-token');
54 });
55
56 test('fetchAllStargazers does not retry permission failures', async () => {
57 let requests = 0;
58 const fakeFetch = async () => {
59 requests += 1;
60 return new Response('{"message":"Forbidden"}', { status: 403 });
61 };
62
63 await assert.rejects(
64 fetchAllStargazers({
65 repository: 'example/repo',
66 token: 'fake-token',
67 fetchImpl: fakeFetch,
68 }),
69 /GitHub API returned 403/,
70 );
71 assert.equal(requests, 1);
72 });
73
74 test('buildDailySeries aggregates days and extends the line to the current date', () => {
75 assert.deepEqual(
76 buildDailySeries(
77 [
78 '2026-07-19T01:00:00Z',
79 '2026-07-19T18:00:00Z',
80 '2026-07-20T01:00:00Z',
81 ],
82 new Date('2026-07-21T12:00:00Z'),
83 ),
84 [
85 { date: '2026-07-19', count: 2 },
86 { date: '2026-07-20', count: 3 },
87 { date: '2026-07-21', count: 3 },
88 ],
89 );
90 });
91
92 test('renderStarHistorySvg produces stable accessible light and dark charts', () => {
93 const series = [
94 { date: '2026-07-19', count: 1 },
95 { date: '2026-07-21', count: 3 },
96 ];
97 const light = renderStarHistorySvg(series, { repository: 'example/repo', theme: 'light' });
98 const dark = renderStarHistorySvg(series, { repository: 'example/repo', theme: 'dark' });
99
100 assert.match(light, /<title id="title">example\/repo Star History<\/title>/);
101 assert.match(light, /3 stars/);
102 assert.match(light, /#ffffff/);
103 assert.match(dark, /#0d1117/);
104 assert.doesNotMatch(light, /NaN|undefined/);
105 });
106
106 lines Plain Text