Skip to content

Commit b9202b0

Browse files
authored
test(Icons-responsive-breakpoints): verify Responsive Multi-device Columns & Mobile Viewport Layouts (JhaSourav07#3224)
## Description Creates app/components/Icons.responsive-breakpoints.test.tsx with 5 test cases verifying that all Icons components use bounded, numeric SVG dimensions that cannot cause horizontal overflow or layout instability on narrow mobile viewports. **Tests**: 1. All icon widths are bounded within a 375 px mobile viewport. No icon can cause horizontal scroll 2. All icons use explicit numeric width/height attributes. No auto or % values that cause layout instability 3. CopyIcon and CheckIcon use compact 20 px sizing appropriate for inline/mobile use 4. CloseIcon uses an 18 px footprint suitable for dismissal controls on narrow viewports 5. ZapIcon and BoxIcon use 24 px sizing within standard mobile touch-target bounds (≤ 48 px) Fixes JhaSourav07#2819 ## Pillar - [ ] 🎨 Pillar 1 — New Theme Design - [ ] 📐 Pillar 2 — Geometric SVG Improvement - [ ] 🕐 Pillar 3 — Timezone Logic Optimization - [x] 🛠️ Other (Bug fix, refactoring, docs) ## Visual Preview N/A ## Checklist before requesting a review: - [x] I have read the `CONTRIBUTING.md` file. - [x] I have tested these changes locally (`localhost:3000/api/streak?user=YOUR_USERNAME`). - [x] I have run `npm run format` and `npm run lint` locally and resolved all errors (CI will fail otherwise). - [x] My commits follow the Conventional Commits format (e.g., `feat(themes): ...`, `fix(calculate): ...`). - [x] I have updated `README.md` if I added a new theme or URL parameter. - [x] I have started the repo. - [x] I have made sure that i have only one commit to merge in this PR. - [x] The SVG output matches the CommitPulse "premium quality" aesthetic standard (no raw elements, smooth animations, correct fonts). - [x] (Recommended) I joined the CommitPulse Discord community for contributor discussions, mentorship, and faster PR support.
2 parents d5ed2e8 + e463aef commit b9202b0

1 file changed

Lines changed: 80 additions & 0 deletions

File tree

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { render } from '@testing-library/react';
2+
import { afterEach, describe, expect, it, vi } from 'vitest';
3+
import { BoxIcon, CheckIcon, CloseIcon, CopyIcon, ZapIcon } from './Icons';
4+
5+
afterEach(() => {
6+
vi.unstubAllGlobals();
7+
});
8+
9+
describe('Icons — responsive breakpoints', () => {
10+
it('icon dimensions are bounded values that will not cause horizontal overflow on a 375 px mobile viewport', () => {
11+
const { container: c1 } = render(<CopyIcon />);
12+
const { container: c2 } = render(<ZapIcon />);
13+
const { container: c3 } = render(<BoxIcon />);
14+
const { container: c4 } = render(<CheckIcon />);
15+
const { container: c5 } = render(<CloseIcon />);
16+
17+
const MOBILE_WIDTH = 375;
18+
for (const container of [c1, c2, c3, c4, c5]) {
19+
const svg = container.querySelector('svg');
20+
expect(svg).not.toBeNull();
21+
const widthAttr = svg!.getAttribute('width');
22+
expect(widthAttr).not.toBeNull();
23+
const width = Number(widthAttr);
24+
expect(Number.isFinite(width)).toBe(true);
25+
expect(width).toBeGreaterThan(0);
26+
expect(width).toBeLessThanOrEqual(MOBILE_WIDTH);
27+
}
28+
});
29+
30+
it('all icons use explicit numeric width and height attributes — no percentage or auto values that could cause layout instability', () => {
31+
const icons = [
32+
render(<CopyIcon />),
33+
render(<ZapIcon />),
34+
render(<BoxIcon />),
35+
render(<CheckIcon />),
36+
render(<CloseIcon />),
37+
];
38+
39+
for (const { container } of icons) {
40+
const svg = container.querySelector('svg');
41+
const width = svg?.getAttribute('width');
42+
const height = svg?.getAttribute('height');
43+
expect(Number(width)).toBeGreaterThan(0);
44+
expect(Number(height)).toBeGreaterThan(0);
45+
}
46+
});
47+
48+
it('CopyIcon and CheckIcon use compact 20 px sizing appropriate for inline/mobile use', () => {
49+
const { container: copyContainer } = render(<CopyIcon />);
50+
const { container: checkContainer } = render(<CheckIcon />);
51+
52+
expect(Number(copyContainer.querySelector('svg')?.getAttribute('width'))).toBe(20);
53+
expect(Number(copyContainer.querySelector('svg')?.getAttribute('height'))).toBe(20);
54+
expect(Number(checkContainer.querySelector('svg')?.getAttribute('width'))).toBe(20);
55+
expect(Number(checkContainer.querySelector('svg')?.getAttribute('height'))).toBe(20);
56+
});
57+
58+
it('CloseIcon uses a smaller 18 px footprint suitable for dismissal controls on narrow viewports', () => {
59+
const { container } = render(<CloseIcon />);
60+
const svg = container.querySelector('svg');
61+
62+
expect(Number(svg?.getAttribute('width'))).toBe(18);
63+
expect(Number(svg?.getAttribute('height'))).toBe(18);
64+
});
65+
66+
it('ZapIcon and BoxIcon use 24 px sizing that stays within standard mobile touch-target bounds', () => {
67+
const { container: zapContainer } = render(<ZapIcon />);
68+
const { container: boxContainer } = render(<BoxIcon />);
69+
70+
const TOUCH_TARGET = 48;
71+
for (const container of [zapContainer, boxContainer]) {
72+
const width = Number(container.querySelector('svg')?.getAttribute('width'));
73+
const height = Number(container.querySelector('svg')?.getAttribute('height'));
74+
expect(width).toBe(24);
75+
expect(height).toBe(24);
76+
expect(width).toBeLessThanOrEqual(TOUCH_TARGET);
77+
expect(height).toBeLessThanOrEqual(TOUCH_TARGET);
78+
}
79+
});
80+
});

0 commit comments

Comments
 (0)