Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions lib/rss.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { describe, it, expect, vi } from 'vitest';
import { fetchLatestArticles } from './rss';

// Mock rss-parser so it doesn't make real network requests during tests
vi.mock('rss-parser', () => {
return {
default: class MockParser {
parseURL = vi.fn().mockResolvedValue({
items: [
{
title: 'Test Post',
link: 'https://dev.to/test',
pubDate: '2026-06-15T00:00:00Z',
},
],
});
},
};
});

describe('rss / fetchLatestArticles', () => {
it('[Bug fix] formats pubDate deterministically regardless of Node process locale', async () => {
// Because rss-parser is mocked above, this will reliably return the mock item
const articles = await fetchLatestArticles('devto', 'testuser');

expect(articles).toHaveLength(1);
// This verifies the 'en-US' Date locale change correctly generates "Jun 15, 2026"
expect(articles[0].pubDate).toBe('Jun 15, 2026');
});
});
6 changes: 5 additions & 1 deletion lib/rss.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,12 @@ export async function fetchLatestArticles(
const articles = feed.items.slice(0, 3).map((item) => ({
title: item.title || 'Untitled',
link: item.link || '',
// Explicit 'en-US' locale, matching the pattern already used in
// lib/github.ts's joinedDate formatting β€” this string is baked
// server-side into the generated SVG, so it must be deterministic
// regardless of the server's ambient runtime locale/ICU build.
pubDate: item.pubDate
? new Date(item.pubDate).toLocaleDateString(undefined, {
? new Date(item.pubDate).toLocaleDateString('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric',
Expand Down
32 changes: 32 additions & 0 deletions lib/svg/repoSpotlight.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { describe, it, expect } from 'vitest';
import { generateRepoSpotlightSVG } from './repoSpotlight';
import { GitHubRepo } from '@/lib/github';
import { BadgeParams } from '@/types';

describe('generateRepoSpotlightSVG', () => {
it('[Bug fix] formats pushed_at with a fixed, explicit locale', () => {
// Construct a minimal mocked repository to satisfy the function requirements
const mockRepo = {
name: 'test-repo',
description: 'A test repository',
language: 'TypeScript',
stargazers_count: 100,
forks_count: 50,
pushed_at: '2026-06-15T00:00:00Z',
participation: [0, 5, 10, 5, 0],
} as GitHubRepo;

// Provide default mockup formatting arguments
const mockParams = {
bg: 'ffffff',
text: '000000',
accent: 'ff0000',
radius: 4,
} as BadgeParams;

const svg = generateRepoSpotlightSVG(mockRepo, mockParams);

// Check that our forced date outputs perfectly in the generated SVG
expect(svg).toContain('Updated Jun 15, 2026');
});
});
3 changes: 2 additions & 1 deletion lib/svg/repoSpotlight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ export function generateRepoSpotlightSVG(repo: GitHubRepo, params: BadgeParams):

// Parse dates if available
const dateStr = repo.pushed_at
? new Date(repo.pushed_at).toLocaleDateString(undefined, {
? // Explicit 'en-US' locale β€” see lib/rss.ts for the same fix and rationale.
new Date(repo.pushed_at).toLocaleDateString('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric',
Expand Down
19 changes: 7 additions & 12 deletions utils/dateHelpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { getAuthorLocalHour, getViewerLocalHour, processCommitTimestamps } from

describe('dateHelpers', () => {
describe('getAuthorLocalHour', () => {
// ... keeping existing tests identical ...
it('extracts hour from a standard ISO timestamp with positive offset', () => {
expect(getAuthorLocalHour('2024-03-10T15:30:00+02:00')).toBe(15);
});
Expand Down Expand Up @@ -70,48 +71,42 @@ describe('dateHelpers', () => {
expect(result).toEqual({ morning: 0, afternoon: 0, evening: 0, night: 0 });
});

// NOTE: Removed 'Z' from timestamp strings below to parse as local time
// and prevent timezone shifting during test execution.

it('counts valid morning commits correctly', () => {
const result = processCommitTimestamps(['2024-03-10T09:00:00', '2024-03-10T11:30:00']);
const result = processCommitTimestamps(['2024-03-10T09:00:00Z', '2024-03-10T11:30:00Z']);
expect(result.morning).toBe(2);
expect(result.afternoon).toBe(0);
expect(result.evening).toBe(0);
expect(result.night).toBe(0);
});

it('counts valid afternoon commits correctly', () => {
const result = processCommitTimestamps(['2024-03-10T12:00:00', '2024-03-10T17:59:00']);
const result = processCommitTimestamps(['2024-03-10T12:00:00Z', '2024-03-10T17:59:00Z']);
expect(result.morning).toBe(0);
expect(result.afternoon).toBe(2);
});

it('counts valid evening commits correctly', () => {
const result = processCommitTimestamps(['2024-03-10T18:00:00', '2024-03-10T23:59:00']);
const result = processCommitTimestamps(['2024-03-10T18:00:00Z', '2024-03-10T23:59:00Z']);
expect(result.evening).toBe(2);
});

it('counts valid night commits correctly', () => {
const result = processCommitTimestamps(['2024-03-10T00:00:00', '2024-03-10T05:59:00']);
const result = processCommitTimestamps(['2024-03-10T00:00:00Z', '2024-03-10T05:59:00Z']);
expect(result.night).toBe(2);
});

it('ignores invalid dates while counting valid ones', () => {
// Removed Z from strings
const result = processCommitTimestamps([
'2024-03-10T09:00:00',
'2024-03-10T09:00:00Z',
'invalid-date',
'2024-03-10T14:00:00',
'2024-03-10T14:00:00Z',
]);
expect(result.morning).toBe(1);
expect(result.afternoon).toBe(1);
expect(result.night).toBe(0);
expect(result.evening).toBe(0);
});

// Regression test: verifies timezone-agnostic behavior.
// This test would fail with getHours() in IST but passes with getUTCHours().
it('produces consistent results regardless of system timezone', () => {
const timestamps = [
'2024-03-10T09:00:00Z', // 09:00 UTC = morning
Expand Down
Loading