Skip to content

Commit 404be1a

Browse files
Merge branch 'main' into docs/cache-getorset-comments
2 parents ffc15ed + 85ea539 commit 404be1a

6 files changed

Lines changed: 357 additions & 1 deletion

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,3 +586,5 @@ Thanks to all contributors who have helped make CommitPulse better!
586586
</a>
587587

588588
<sub>View the [full contributor list →](https://github.com/JhaSourav07/commitpulse/graphs/contributors)</sub>
589+
590+
test commit for PR creation
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { render, screen } from '@testing-library/react';
2+
import { describe, expect, it, vi } from 'vitest';
3+
vi.mock('gsap', () => ({
4+
default: {
5+
registerPlugin: vi.fn(),
6+
context: vi.fn((cb) => {
7+
cb();
8+
return {
9+
revert: vi.fn(),
10+
};
11+
}),
12+
timeline: vi.fn(() => ({
13+
fromTo: vi.fn(),
14+
to: vi.fn(),
15+
kill: vi.fn(),
16+
})),
17+
set: vi.fn(),
18+
to: vi.fn(),
19+
},
20+
}));
21+
vi.mock('gsap/ScrollTrigger', () => ({
22+
ScrollTrigger: {},
23+
}));
24+
import { WallOfLove } from './WallOfLove';
25+
import '@testing-library/jest-dom/vitest';
26+
27+
describe('WallOfLove', () => {
28+
it('renders the Wall of Love heading', () => {
29+
render(<WallOfLove />);
30+
31+
expect(screen.getByText(/Wall of/i)).toBeInTheDocument();
32+
});
33+
it('renders the developer feedback text', () => {
34+
render(<WallOfLove />);
35+
36+
expect(
37+
screen.getByText(/See what developers are saying about CommitPulse/i)
38+
).toBeInTheDocument();
39+
});
40+
it('renders the statistics section', () => {
41+
render(<WallOfLove />);
42+
43+
expect(screen.getByText('Happy Developers')).toBeInTheDocument();
44+
expect(screen.getByText('Badges Generated')).toBeInTheDocument();
45+
expect(screen.getByText('Average Rating')).toBeInTheDocument();
46+
});
47+
48+
it('renders testimonial content', () => {
49+
render(<WallOfLove />);
50+
51+
expect(screen.getAllByText(/Alex Chen/i).length).toBeGreaterThan(0);
52+
});
53+
54+
it('renders the developer community badge', () => {
55+
render(<WallOfLove />);
56+
57+
expect(screen.getByText(/Loved by developers worldwide/i)).toBeInTheDocument();
58+
});
59+
});

components/dashboard/RadarChart.test.tsx

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,45 @@ describe('RadarChart', () => {
7878
expect(screen.getAllByText('Python')).toBeDefined();
7979
});
8080

81+
it('renders chart elements and layout structure visible across viewport sizes', () => {
82+
const mockLangsA = [
83+
{ name: 'TypeScript', percentage: 80, color: '#3178c6' },
84+
{ name: 'Python', percentage: 60, color: '#3572A5' },
85+
{ name: 'JavaScript', percentage: 40, color: '#f1e05a' },
86+
];
87+
88+
const mockLangsB = [
89+
{ name: 'TypeScript', percentage: 50, color: '#3178c6' },
90+
{ name: 'Python', percentage: 70, color: '#3572A5' },
91+
{ name: 'JavaScript', percentage: 30, color: '#f1e05a' },
92+
];
93+
94+
const { container } = render(
95+
<RadarChart languagesA={mockLangsA} languagesB={mockLangsB} labelA="User A" labelB="User B" />
96+
);
97+
98+
// Check that SVG element is rendered
99+
const svg = container.querySelector('svg');
100+
expect(svg).toBeDefined();
101+
102+
// Check that grid polygons are rendered (concentric levels)
103+
const polygons = container.querySelectorAll('polygon');
104+
expect(polygons.length).toBeGreaterThan(0);
105+
106+
// Check that axis lines are rendered
107+
const lines = container.querySelectorAll('line');
108+
expect(lines.length).toBeGreaterThan(0);
109+
110+
// Check that axis labels are rendered
111+
expect(screen.getAllByText('TypeScript')).toBeDefined();
112+
expect(screen.getAllByText('Python')).toBeDefined();
113+
expect(screen.getAllByText('JavaScript')).toBeDefined();
114+
115+
// Check that data points (circles) are rendered
116+
const circles = container.querySelectorAll('circle');
117+
expect(circles.length).toBeGreaterThan(0);
118+
});
119+
81120
it('deduplicates shared languages so TypeScript appears as a single axis label', () => {
82121
const langsA = [{ name: 'TypeScript', percentage: 70, color: '#3178c6' }];
83122
const langsB = [{ name: 'TypeScript', percentage: 50, color: '#3178c6' }];
@@ -110,7 +149,6 @@ describe('RadarChart', () => {
110149
labelB="Low Scorer"
111150
/>
112151
);
113-
114152
expect(screen.getAllByText('TypeScript')).toBeDefined();
115153
expect(screen.getAllByText('Python')).toBeDefined();
116154
expect(screen.getAllByText('JavaScript')).toBeDefined();
@@ -121,8 +159,52 @@ describe('RadarChart', () => {
121159
const svg = container.querySelector('svg');
122160
expect(svg).not.toBeNull();
123161

162+
// Check that data points (circles) are rendered
163+
const circles = container.querySelectorAll('circle');
164+
expect(circles.length).toBeGreaterThan(0);
165+
});
166+
167+
it('dynamically scales axis points based on dataset max score', () => {
168+
// Mock dataset with specific maximum score
169+
const mockLangsA = [
170+
{ name: 'TypeScript', percentage: 100, color: '#3178c6' }, // Max score
171+
{ name: 'Python', percentage: 75, color: '#3572A5' },
172+
{ name: 'JavaScript', percentage: 50, color: '#f1e05a' },
173+
];
174+
175+
const mockLangsB = [
176+
{ name: 'TypeScript', percentage: 90, color: '#3178c6' },
177+
{ name: 'Python', percentage: 60, color: '#3572A5' },
178+
{ name: 'JavaScript', percentage: 30, color: '#f1e05a' },
179+
];
180+
181+
const { container } = render(
182+
<RadarChart languagesA={mockLangsA} languagesB={mockLangsB} labelA="User A" labelB="User B" />
183+
);
184+
185+
// Verify that polygons are rendered with points attribute
186+
const polygons = container.querySelectorAll('polygon');
187+
expect(polygons.length).toBeGreaterThan(0);
188+
189+
// Check that the data polygons have points attribute (indicating scaling)
190+
const dataPolygons = Array.from(polygons).filter((p) =>
191+
p.getAttribute('points')?.includes(',')
192+
);
193+
expect(dataPolygons.length).toBeGreaterThan(0);
194+
195+
// Verify that circles (data points) are rendered at different positions
124196
const circles = container.querySelectorAll('circle');
125197
expect(circles.length).toBeGreaterThan(0);
198+
199+
// Get all circle positions to verify they're scaled differently
200+
const circlePositions = Array.from(circles).map((circle) => ({
201+
cx: circle.getAttribute('cx'),
202+
cy: circle.getAttribute('cy'),
203+
}));
204+
205+
// Verify that not all circles are at the same position (indicating dynamic scaling)
206+
const uniquePositions = new Set(circlePositions.map((pos) => `${pos.cx},${pos.cy}`));
207+
expect(uniquePositions.size).toBeGreaterThan(1);
126208
});
127209

128210
it('check generation of different polygon coordinates for different score magnitudes', () => {
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// lib/svg/constants.accessibility.test.ts
2+
3+
import { describe, expect, it } from 'vitest';
4+
import {
5+
SVG_WIDTH,
6+
SVG_HEIGHT,
7+
FONT_MAP,
8+
CONTRIBUTION_MILESTONES,
9+
STREAK_MILESTONES,
10+
} from './constants';
11+
12+
describe('SVG Constants Accessibility', () => {
13+
it('provides valid SVG dimensions for accessible rendering', () => {
14+
expect(SVG_WIDTH).toBeGreaterThan(0);
15+
expect(SVG_HEIGHT).toBeGreaterThan(0);
16+
});
17+
18+
it('exposes readable font mappings for SVG text content', () => {
19+
expect(FONT_MAP).toHaveProperty('jetbrains');
20+
expect(FONT_MAP).toHaveProperty('fira');
21+
expect(FONT_MAP).toHaveProperty('roboto');
22+
23+
Object.values(FONT_MAP).forEach((font) => {
24+
expect(typeof font).toBe('string');
25+
expect(font.length).toBeGreaterThan(0);
26+
});
27+
});
28+
29+
it('defines contribution milestone values suitable for accessible labels', () => {
30+
expect(CONTRIBUTION_MILESTONES.length).toBeGreaterThan(0);
31+
32+
CONTRIBUTION_MILESTONES.forEach((value) => {
33+
expect(value).toBeGreaterThan(0);
34+
});
35+
});
36+
37+
it('defines streak milestone values suitable for accessible labels', () => {
38+
expect(STREAK_MILESTONES.length).toBeGreaterThan(0);
39+
40+
STREAK_MILESTONES.forEach((value) => {
41+
expect(value).toBeGreaterThan(0);
42+
});
43+
});
44+
45+
it('maintains ascending milestone ordering for predictable narration', () => {
46+
expect(CONTRIBUTION_MILESTONES).toEqual([...CONTRIBUTION_MILESTONES].sort((a, b) => a - b));
47+
48+
expect(STREAK_MILESTONES).toEqual([...STREAK_MILESTONES].sort((a, b) => a - b));
49+
});
50+
});
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// lib/svg/constants.massive-scaling.test.ts
2+
3+
import { describe, expect, it } from 'vitest';
4+
import {
5+
SVG_WIDTH,
6+
SVG_HEIGHT,
7+
GHOST_HEIGHT_PX,
8+
LOG_SCALE_MULTIPLIER,
9+
LINEAR_SCALE_MULTIPLIER,
10+
MAX_LOG_HEIGHT,
11+
MAX_LINEAR_HEIGHT,
12+
CONTRIBUTION_MILESTONES,
13+
STREAK_MILESTONES,
14+
} from './constants';
15+
16+
describe('SVG Constants Massive Scaling', () => {
17+
it('supports large simulated contribution datasets', () => {
18+
const contributions = Array.from({ length: 10000 }, (_, i) => i + 1);
19+
20+
expect(contributions.length).toBe(10000);
21+
expect(Math.max(...contributions)).toBe(10000);
22+
});
23+
24+
it('maintains positive scaling configuration values', () => {
25+
expect(LOG_SCALE_MULTIPLIER).toBeGreaterThan(0);
26+
expect(LINEAR_SCALE_MULTIPLIER).toBeGreaterThan(0);
27+
expect(MAX_LOG_HEIGHT).toBeGreaterThan(0);
28+
expect(MAX_LINEAR_HEIGHT).toBeGreaterThan(0);
29+
});
30+
31+
it('provides valid SVG dimensions under high-volume scenarios', () => {
32+
expect(SVG_WIDTH).toBeGreaterThan(0);
33+
expect(SVG_HEIGHT).toBeGreaterThan(0);
34+
expect(GHOST_HEIGHT_PX).toBeGreaterThan(0);
35+
});
36+
37+
it('maintains milestone integrity with large data references', () => {
38+
expect(CONTRIBUTION_MILESTONES.every((v) => v > 0)).toBe(true);
39+
expect(STREAK_MILESTONES.every((v) => v > 0)).toBe(true);
40+
});
41+
42+
it('handles repeated access without configuration drift', () => {
43+
for (let i = 0; i < 10000; i++) {
44+
expect(SVG_WIDTH).toBe(600);
45+
expect(SVG_HEIGHT).toBe(420);
46+
}
47+
});
48+
});
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import { describe, it, expect, beforeEach, vi, Mock } from 'vitest';
2+
import { RefreshPolicy } from './refresh-policy';
3+
import { quotaMonitor } from './quota-monitor';
4+
5+
// Mock the quota monitor to control high-contrast "override" states
6+
vi.mock('./quota-monitor', () => ({
7+
quotaMonitor: {
8+
isQuotaLow: vi.fn(() => false),
9+
incrementRefreshCount: vi.fn(),
10+
},
11+
}));
12+
13+
describe('RefreshPolicy - Theme Contrast Equivalent (Mode Cohesion)', () => {
14+
let policy: RefreshPolicy;
15+
16+
beforeEach(() => {
17+
policy = RefreshPolicy.getInstance();
18+
policy.reset();
19+
vi.clearAllMocks();
20+
});
21+
22+
it('Dual Environment Setup: seamlessly swaps between standard (light) and aggressive (dark) modes', () => {
23+
// Light Mode (Standard Cooldown)
24+
policy.setCooldown(300000);
25+
expect(policy.getRemainingCooldown('new_user')).toBe(0);
26+
27+
// Dark Mode (Aggressive Cooldown)
28+
policy.setCooldown(600000);
29+
expect(policy.getRemainingCooldown('new_user')).toBe(0);
30+
31+
// Swap back
32+
policy.setCooldown(300000);
33+
expect(policy.getRemainingCooldown('new_user')).toBe(0);
34+
});
35+
36+
it('Behavior Adaptation Cohesion: dynamically adapts allow/deny status based on active mode', () => {
37+
// Record user in Standard Mode (300000ms)
38+
policy.setCooldown(300000);
39+
policy.recordRefresh('mode_user');
40+
41+
// Simulate exactly 400000ms passing by manipulating Date.now
42+
const originalDateNow = Date.now;
43+
const futureTime = originalDateNow() + 400000;
44+
vi.spyOn(Date, 'now').mockReturnValue(futureTime);
45+
46+
// In Standard Mode, 400000 > 300000, so refresh is allowed
47+
expect(policy.isRefreshAllowed('mode_user')).toBe(true);
48+
49+
// Swap to Aggressive Mode (600000ms)
50+
policy.setCooldown(600000);
51+
52+
// In Aggressive Mode, 400000 < 600000, so refresh is now denied!
53+
expect(policy.isRefreshAllowed('mode_user')).toBe(false);
54+
55+
// Restore
56+
vi.restoreAllMocks();
57+
});
58+
59+
it('Contrast Verification (Overrides): quota lockouts uniformly block across all configuration modes', () => {
60+
// Activate high-contrast global override
61+
(quotaMonitor.isQuotaLow as Mock).mockReturnValue(true);
62+
63+
policy.setCooldown(100);
64+
expect(policy.isRefreshAllowed('user_1')).toBe(false);
65+
66+
policy.setCooldown(9999999);
67+
expect(policy.isRefreshAllowed('user_1')).toBe(false);
68+
69+
policy.setCooldown(0);
70+
expect(policy.isRefreshAllowed('user_1')).toBe(false);
71+
72+
// Deactivate override
73+
(quotaMonitor.isQuotaLow as Mock).mockReturnValue(false);
74+
});
75+
76+
it('Configuration Preservation: swapping modes preserves internal caching data integrity', () => {
77+
// Record in mode A
78+
policy.setCooldown(300000);
79+
policy.recordRefresh('state_user');
80+
81+
// Check remaining cooldown (should be roughly 300000)
82+
const remainingA = policy.getRemainingCooldown('state_user');
83+
84+
// Swap to mode B
85+
policy.setCooldown(600000);
86+
87+
// The timestamp state is still intact, just the boundary shifted
88+
const remainingB = policy.getRemainingCooldown('state_user');
89+
90+
expect(remainingB).toBeGreaterThan(remainingA);
91+
// Delta should be exactly 300000
92+
expect(Math.abs(remainingB - remainingA - 300000)).toBeLessThan(50);
93+
});
94+
95+
it('Foreground/Background Cohesion: getRemainingCooldown calculates foreground values flawlessly against active background mode', () => {
96+
policy.recordRefresh('fg_bg_user');
97+
98+
// Background Mode 1
99+
policy.setCooldown(1000);
100+
const bg1 = policy.getRemainingCooldown('fg_bg_user');
101+
expect(bg1).toBeGreaterThan(0);
102+
expect(bg1).toBeLessThanOrEqual(1000);
103+
104+
// Background Mode 2
105+
policy.setCooldown(5000);
106+
const bg2 = policy.getRemainingCooldown('fg_bg_user');
107+
expect(bg2).toBeGreaterThan(1000);
108+
expect(bg2).toBeLessThanOrEqual(5000);
109+
110+
// Background Mode 3 (Disabled)
111+
policy.setCooldown(0);
112+
const bg3 = policy.getRemainingCooldown('fg_bg_user');
113+
expect(bg3).toBe(0);
114+
});
115+
});

0 commit comments

Comments
 (0)