Skip to content

Commit 0e9b7a6

Browse files
test(customize): add ControlsPanel component tests (JhaSourav07#1924)
* test(customize): add ControlsPanel component tests * fix(customize): use valid default font * chore: sync package-lock.json * test(customize): update tests for font query parameter
1 parent 09caff5 commit 0e9b7a6

4 files changed

Lines changed: 80 additions & 28 deletions

File tree

Lines changed: 71 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
1-
import { fireEvent, render, screen } from '@testing-library/react';
2-
import type { ComponentProps } from 'react';
3-
import { describe, expect, it, vi } from 'vitest';
1+
import '@testing-library/jest-dom';
2+
import type { Scale, BadgeSize, Font, ViewMode, DeltaFormat, Language, Timezone } from '../types';
3+
import { describe, it, expect, vi, beforeEach } from 'vitest';
4+
import { render, screen, fireEvent } from '@testing-library/react';
45
import { ControlsPanel } from './ControlsPanel';
5-
import type { BadgeSize, DeltaFormat, Font, Language, Scale, Timezone, ViewMode } from '../types';
66

77
const defaultProps = {
8-
username: 'octocat',
9-
theme: 'dark',
8+
username: '',
9+
theme: 'github-dark',
1010
bgHex: '',
1111
accentHex: '',
1212
textHex: '',
1313
scale: 'linear' as Scale,
1414
speed: '8s',
1515
font: '' as Font,
16-
year: '',
16+
year: '2025',
1717
radius: 8,
1818
size: 'medium' as BadgeSize,
19+
1920
onUsernameChange: vi.fn(),
2021
onThemeChange: vi.fn(),
2122
onBgHexChange: vi.fn(),
@@ -28,43 +29,94 @@ const defaultProps = {
2829
onSizeChange: vi.fn(),
2930
onClearOverrides: vi.fn(),
3031
onRadiusChange: vi.fn(),
32+
3133
hideTitle: false,
3234
hideBackground: false,
3335
hideStats: false,
36+
3437
viewMode: 'default' as ViewMode,
3538
deltaFormat: 'percent' as DeltaFormat,
36-
badgeWidth: '' as const,
37-
badgeHeight: '' as const,
39+
40+
badgeWidth: 0,
41+
badgeHeight: 0,
42+
3843
grace: 1,
44+
3945
language: 'en' as Language,
4046
timezone: 'UTC' as Timezone,
47+
4148
onHideTitleChange: vi.fn(),
4249
onHideBackgroundChange: vi.fn(),
4350
onHideStatsChange: vi.fn(),
51+
4452
onViewModeChange: vi.fn(),
4553
onDeltaFormatChange: vi.fn(),
54+
4655
onBadgeWidthChange: vi.fn(),
4756
onBadgeHeightChange: vi.fn(),
57+
4858
onGraceChange: vi.fn(),
59+
4960
onLanguageChange: vi.fn(),
5061
onTimezoneChange: vi.fn(),
51-
} satisfies ComponentProps<typeof ControlsPanel>;
62+
};
63+
describe('ControlsPanel Component', () => {
64+
beforeEach(() => {
65+
vi.clearAllMocks();
66+
});
5267

53-
describe('ControlsPanel timezone control', () => {
54-
it('renders UTC as the default timezone option', () => {
68+
it('renders the GitHub Username label', () => {
5569
render(<ControlsPanel {...defaultProps} />);
5670

57-
expect((screen.getByLabelText('Timezone') as HTMLSelectElement).value).toBe('UTC');
71+
expect(screen.getByText(/GitHub Username/i)).toBeTruthy();
5872
});
5973

60-
it('calls onTimezoneChange with the selected IANA timezone', () => {
61-
const onTimezoneChange = vi.fn();
62-
render(<ControlsPanel {...defaultProps} onTimezoneChange={onTimezoneChange} />);
74+
it('renders username input with correct id', () => {
75+
render(<ControlsPanel {...defaultProps} />);
76+
const input = document.getElementById('username-input');
77+
78+
expect(input).toHaveAttribute('id', 'username-input');
79+
});
80+
81+
it('calls onUsernameChange when typing', () => {
82+
render(<ControlsPanel {...defaultProps} />);
83+
84+
const input = document.getElementById('username-input');
6385

64-
fireEvent.change(screen.getByLabelText('Timezone'), {
65-
target: { value: 'Asia/Kolkata' },
86+
fireEvent.change(input!, {
87+
target: { value: 'shikhar' },
6688
});
6789

68-
expect(onTimezoneChange).toHaveBeenCalledWith('Asia/Kolkata');
90+
expect(defaultProps.onUsernameChange).toHaveBeenCalled();
91+
});
92+
93+
it('renders Linear and Logarithmic buttons', () => {
94+
render(<ControlsPanel {...defaultProps} />);
95+
96+
expect(screen.getByRole('button', { name: /Linear/i })).toBeTruthy();
97+
98+
expect(screen.getByRole('button', { name: /Logarithmic/i })).toBeTruthy();
99+
});
100+
101+
it('calls onScaleChange with log', () => {
102+
render(<ControlsPanel {...defaultProps} />);
103+
104+
const logButton = screen.getByText(/Logarithmic/i);
105+
106+
fireEvent.click(logButton);
107+
108+
expect(defaultProps.onScaleChange).toHaveBeenCalledWith('log');
109+
});
110+
111+
it('hides Clear overrides button initially', () => {
112+
render(<ControlsPanel {...defaultProps} />);
113+
114+
expect(screen.queryByText(/Clear overrides/i)).toBeNull();
115+
});
116+
117+
it('shows Clear overrides button when bgHex is provided', () => {
118+
render(<ControlsPanel {...defaultProps} bgHex="#000000" />);
119+
120+
expect(screen.getByText(/Clear overrides/i)).toBeTruthy();
69121
});
70122
});

app/customize/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export default function CustomizePage(): ReactElement {
2929
const [textHex, setTextHex] = useState('');
3030
const [scale, setScale] = useState<Scale>('linear');
3131
const [speed, setSpeed] = useState('8s');
32-
const [font, setFont] = useState<Font>('');
32+
const [font, setFont] = useState<Font>('Inter');
3333
const [year, setYear] = useState('');
3434
const [radius, setRadius] = useState(8);
3535
const [size, setSize] = useState<BadgeSize>('medium');

app/customize/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export const SIZES = [
2828
] as const;
2929

3030
export const FONTS = [
31-
{ value: '', label: 'Default' },
31+
{ value: 'Inter', label: 'Default' },
3232
{ value: 'jetbrains', label: 'JetBrains Mono' },
3333
{ value: 'fira', label: 'Fira Code' },
3434
{ value: 'roboto', label: 'Roboto' },

app/customize/utils.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ describe('Export Snippet utilities', () => {
111111
textHex: '',
112112
scale: 'linear',
113113
speed: '8s',
114-
font: '',
114+
font: 'Inter',
115115
year: '',
116116
radius: 8,
117117
size: 'medium',
@@ -129,13 +129,13 @@ describe('Export Snippet utilities', () => {
129129

130130
it('returns minimal params with default values', () => {
131131
const result = buildQueryParams(defaultOptions);
132-
expect(result).toBe('user=testuser&theme=dark');
132+
expect(result).toBe('user=testuser&theme=dark&font=Inter');
133133
});
134134

135135
it('applies custom theme values', () => {
136136
const options = { ...defaultOptions, theme: 'light' };
137137
const result = buildQueryParams(options);
138-
expect(result).toBe('user=testuser&theme=light');
138+
expect(result).toBe('user=testuser&theme=light&font=Inter');
139139
});
140140

141141
it('applies custom color overrides and omits theme', () => {
@@ -147,7 +147,7 @@ describe('Export Snippet utilities', () => {
147147
textHex: '#000000',
148148
};
149149
const result = buildQueryParams(options);
150-
expect(result).toBe('user=testuser&bg=ffffff&accent=ff0000&text=000000');
150+
expect(result).toBe('user=testuser&bg=ffffff&accent=ff0000&text=000000&font=Inter');
151151
});
152152

153153
it('forces theme parameter and ignores custom colors for virtual themes (auto/random)', () => {
@@ -157,21 +157,21 @@ describe('Export Snippet utilities', () => {
157157
bgHex: 'ffffff',
158158
};
159159
const resultAuto = buildQueryParams(optionsAuto);
160-
expect(resultAuto).toBe('user=testuser&theme=auto');
160+
expect(resultAuto).toBe('user=testuser&theme=auto&font=Inter');
161161

162162
const optionsRandom = {
163163
...defaultOptions,
164164
theme: 'random',
165165
accentHex: 'ff0000',
166166
};
167167
const resultRandom = buildQueryParams(optionsRandom);
168-
expect(resultRandom).toBe('user=testuser&theme=random');
168+
expect(resultRandom).toBe('user=testuser&theme=random&font=Inter');
169169
});
170170

171171
it('handles empty username gracefully', () => {
172172
const options = { ...defaultOptions, username: ' ' };
173173
const result = buildQueryParams(options);
174-
expect(result).toBe('theme=dark');
174+
expect(result).toBe('theme=dark&font=Inter');
175175
});
176176

177177
it('includes all customized options', () => {

0 commit comments

Comments
 (0)