Skip to content

Commit 263a2f4

Browse files
authored
test(components/dashboard): add aiinsights rendering tests with 5 tes… (JhaSourav07#856)
…t cases ## Description Fixes JhaSourav07#667 ## Pillar - [] 🎨 Pillar 1 — New Theme Design - [] 📐 Pillar 2 — Geometric SVG Improvement - [] 🕐 Pillar 3 — Timezone Logic Optimization - [x] 🛠️ Other (Bug fix, refactoring, docs) ## Visual Preview ## 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): ...`). - [] 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. - [] 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 7c7f92e + 8d5d7c2 commit 263a2f4

1 file changed

Lines changed: 93 additions & 0 deletions

File tree

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
2+
import { describe, it, expect, vi, beforeEach } from 'vitest';
3+
import { render, screen } from '@testing-library/react';
4+
import AIInsights from './AIInsights';
5+
import type { AIInsight } from '@/types/dashboard';
6+
7+
// Mock framer-motion
8+
vi.mock('framer-motion', () => ({
9+
motion: {
10+
div: ({ children, ...props }: any) => (
11+
<div {...props} data-testid="motion-div">
12+
{children}
13+
</div>
14+
),
15+
},
16+
}));
17+
18+
// Mock lucide-react
19+
vi.mock('lucide-react', () => ({
20+
Sparkles: (props: any) => <div data-testid="icon-sparkles" {...props} />,
21+
Moon: (props: any) => <div data-testid="icon-moon" {...props} />,
22+
Sun: (props: any) => <div data-testid="icon-sun" {...props} />,
23+
Zap: (props: any) => <div data-testid="icon-zap" {...props} />,
24+
Calendar: (props: any) => <div data-testid="icon-calendar" {...props} />,
25+
Flame: (props: any) => <div data-testid="icon-flame" {...props} />,
26+
Code: (props: any) => <div data-testid="icon-code" {...props} />,
27+
Star: (props: any) => <div data-testid="icon-star" {...props} />,
28+
LucideIcon: () => null,
29+
}));
30+
31+
describe('AIInsights', () => {
32+
beforeEach(() => {
33+
vi.clearAllMocks();
34+
});
35+
36+
// Test 1: renders the 'AI Insights' heading
37+
it('should render the AI Insights heading', () => {
38+
const insights: AIInsight[] = [];
39+
render(<AIInsights insights={insights} />);
40+
41+
expect(screen.getByText('AI Insights')).toBeDefined();
42+
});
43+
44+
// Test 2: renders the correct number of insight items when given an array
45+
it('should render the correct number of insight items', () => {
46+
const insights: AIInsight[] = [
47+
{ id: '1', icon: 'Moon', text: 'Night owl detected' },
48+
{ id: '2', icon: 'Sun', text: 'Morning committer' },
49+
{ id: '3', icon: 'Zap', text: 'High activity spike' },
50+
];
51+
render(<AIInsights insights={insights} />);
52+
53+
expect(screen.getByText('Night owl detected')).toBeDefined();
54+
expect(screen.getByText('Morning committer')).toBeDefined();
55+
expect(screen.getByText('High activity spike')).toBeDefined();
56+
});
57+
58+
// Test 3: renders insight text correctly
59+
it('should render insight text correctly', () => {
60+
const insights: AIInsight[] = [
61+
{ id: '1', icon: 'Flame', text: 'You are on fire this week!' },
62+
{ id: '2', icon: 'Code', text: 'TypeScript is your main language' },
63+
];
64+
render(<AIInsights insights={insights} />);
65+
66+
expect(screen.getByText('You are on fire this week!')).toBeDefined();
67+
expect(screen.getByText('TypeScript is your main language')).toBeDefined();
68+
});
69+
70+
// Test 4: renders empty state (empty insights array) without crashing
71+
it('should render empty state with no insights without crashing', () => {
72+
const insights: AIInsight[] = [];
73+
const { container } = render(<AIInsights insights={insights} />);
74+
75+
// Should still render the heading
76+
expect(screen.getByText('AI Insights')).toBeDefined();
77+
// Should not crash and container should exist
78+
expect(container).toBeDefined();
79+
});
80+
81+
// Test 5: unknown icon key falls back to Sparkles without throwing
82+
it('should fall back to Sparkles icon for unknown icon names', () => {
83+
const insights: AIInsight[] = [
84+
{ id: '1', icon: 'UnknownIcon', text: 'This has an unknown icon' },
85+
];
86+
render(<AIInsights insights={insights} />);
87+
88+
expect(screen.getByText('This has an unknown icon')).toBeDefined();
89+
// getAllByTestId because Sparkles is used both in header and as fallback icon
90+
const sparklesIcons = screen.getAllByTestId('icon-sparkles');
91+
expect(sparklesIcons.length).toBeGreaterThanOrEqual(2);
92+
});
93+
});

0 commit comments

Comments
 (0)