1+ import { render , screen } from '@testing-library/react' ;
2+ import { BlogPreviewSection } from '@/components/sections/blog-preview-section' ;
3+ import { BlogPost } from '@/types' ;
4+
5+ // Mock blog posts data
6+ const mockPosts : BlogPost [ ] = [
7+ {
8+ title : 'Building Offline-First Apps' ,
9+ slug : 'building-offline-first-apps' ,
10+ date : new Date ( '2025-01-15' ) ,
11+ excerpt : 'Real-time synchronization strategies for mobile applications' ,
12+ tags : [ 'React Native' , 'Offline' , 'Sync' ] ,
13+ category : 'Mobile Development' ,
14+ content : '' ,
15+ readingTime : 8 ,
16+ published : true
17+ } ,
18+ {
19+ title : 'Microservices Architecture Patterns' ,
20+ slug : 'microservices-architecture-patterns' ,
21+ date : new Date ( '2025-01-10' ) ,
22+ excerpt : 'Best practices for designing scalable microservices' ,
23+ tags : [ 'Microservices' , 'Architecture' , 'Scalability' ] ,
24+ category : 'Backend Development' ,
25+ content : '' ,
26+ readingTime : 12 ,
27+ published : true
28+ } ,
29+ {
30+ title : 'Modern CSS Techniques' ,
31+ slug : 'modern-css-techniques' ,
32+ date : new Date ( '2025-01-05' ) ,
33+ excerpt : 'Advanced CSS features for modern web development' ,
34+ tags : [ 'CSS' , 'Frontend' , 'Web Development' ] ,
35+ category : 'Frontend Development' ,
36+ content : '' ,
37+ readingTime : 6 ,
38+ published : true
39+ }
40+ ] ;
41+
42+ describe ( 'BlogPreviewSection' , ( ) => {
43+ it ( 'renders section header "Latest Blog Posts"' , ( ) => {
44+ render ( < BlogPreviewSection posts = { mockPosts } /> ) ;
45+
46+ expect ( screen . getByText ( 'Latest Blog Posts' ) ) . toBeInTheDocument ( ) ;
47+ } ) ;
48+
49+ it ( 'renders 3 latest blog posts' , ( ) => {
50+ render ( < BlogPreviewSection posts = { mockPosts } /> ) ;
51+
52+ expect ( screen . getByText ( 'Building Offline-First Apps' ) ) . toBeInTheDocument ( ) ;
53+ expect ( screen . getByText ( 'Microservices Architecture Patterns' ) ) . toBeInTheDocument ( ) ;
54+ expect ( screen . getByText ( 'Modern CSS Techniques' ) ) . toBeInTheDocument ( ) ;
55+ } ) ;
56+
57+ it ( 'renders "View All Posts" link' , ( ) => {
58+ render ( < BlogPreviewSection posts = { mockPosts } /> ) ;
59+
60+ const viewAllLink = screen . getByRole ( 'link' , { name : / v i e w a l l p o s t s / i } ) ;
61+ expect ( viewAllLink ) . toBeInTheDocument ( ) ;
62+ expect ( viewAllLink ) . toHaveAttribute ( 'href' , '/blog' ) ;
63+ } ) ;
64+
65+ it ( 'renders blog post cards with correct structure' , ( ) => {
66+ render ( < BlogPreviewSection posts = { mockPosts } /> ) ;
67+
68+ const blogCards = screen . getAllByTestId ( 'blog-post-card' ) ;
69+ expect ( blogCards ) . toHaveLength ( 3 ) ;
70+ } ) ;
71+
72+ it ( 'displays blog post excerpts' , ( ) => {
73+ render ( < BlogPreviewSection posts = { mockPosts } /> ) ;
74+
75+ expect ( screen . getByText ( 'Real-time synchronization strategies for mobile applications' ) ) . toBeInTheDocument ( ) ;
76+ expect ( screen . getByText ( 'Best practices for designing scalable microservices' ) ) . toBeInTheDocument ( ) ;
77+ expect ( screen . getByText ( 'Advanced CSS features for modern web development' ) ) . toBeInTheDocument ( ) ;
78+ } ) ;
79+
80+ it ( 'displays blog post categories' , ( ) => {
81+ render ( < BlogPreviewSection posts = { mockPosts } /> ) ;
82+
83+ expect ( screen . getByText ( 'Mobile Development' ) ) . toBeInTheDocument ( ) ;
84+ expect ( screen . getByText ( 'Backend Development' ) ) . toBeInTheDocument ( ) ;
85+ expect ( screen . getByText ( 'Frontend Development' ) ) . toBeInTheDocument ( ) ;
86+ } ) ;
87+
88+ it ( 'displays reading time for each post' , ( ) => {
89+ render ( < BlogPreviewSection posts = { mockPosts } /> ) ;
90+
91+ expect ( screen . getByText ( '8 min read' ) ) . toBeInTheDocument ( ) ;
92+ expect ( screen . getByText ( '12 min read' ) ) . toBeInTheDocument ( ) ;
93+ expect ( screen . getByText ( '6 min read' ) ) . toBeInTheDocument ( ) ;
94+ } ) ;
95+
96+ it ( 'has responsive grid layout' , ( ) => {
97+ render ( < BlogPreviewSection posts = { mockPosts } /> ) ;
98+
99+ const container = screen . getByTestId ( 'blog-preview-grid' ) ;
100+ expect ( container ) . toHaveClass ( 'grid' , 'grid-cols-1' , 'md:grid-cols-2' , 'lg:grid-cols-3' ) ;
101+ } ) ;
102+
103+ it ( 'follows homepage section styling patterns' , ( ) => {
104+ render ( < BlogPreviewSection posts = { mockPosts } /> ) ;
105+
106+ const section = screen . getByTestId ( 'blog-preview-section' ) ;
107+ expect ( section ) . toHaveClass ( 'py-20' , 'bg-[#ffffff]' , 'dark:bg-[#0d1117]' ) ;
108+ } ) ;
109+
110+ it ( 'has proper section container with max width' , ( ) => {
111+ render ( < BlogPreviewSection posts = { mockPosts } /> ) ;
112+
113+ const container = screen . getByTestId ( 'blog-preview-container' ) ;
114+ expect ( container ) . toHaveClass ( 'max-w-6xl' , 'mx-auto' , 'px-4' ) ;
115+ } ) ;
116+
117+ it ( 'uses correct typography for section header' , ( ) => {
118+ render ( < BlogPreviewSection posts = { mockPosts } /> ) ;
119+
120+ const header = screen . getByText ( 'Latest Blog Posts' ) ;
121+ expect ( header ) . toHaveClass ( 'font-mono' , 'text-[2rem]' , 'md:text-[2.5rem]' , 'font-semibold' ) ;
122+ } ) ;
123+
124+ it ( 'handles empty posts array gracefully' , ( ) => {
125+ render ( < BlogPreviewSection posts = { [ ] } /> ) ;
126+
127+ expect ( screen . getByText ( 'Latest Blog Posts' ) ) . toBeInTheDocument ( ) ;
128+ expect ( screen . getByText ( 'View All Posts' ) ) . toBeInTheDocument ( ) ;
129+ expect ( screen . queryByTestId ( 'blog-post-card' ) ) . not . toBeInTheDocument ( ) ;
130+ } ) ;
131+ } ) ;
0 commit comments