11import React from 'react' ;
2- import { render , screen , fireEvent } from '@testing-library/react' ;
2+
3+ import { fireEvent , render , screen } from '@testing-library/react' ;
34import '@testing-library/jest-dom' ;
4- import { describe , it , expect , vi } from 'vitest' ;
5- import { TableHeader } from '../../src/components/TableHeader' ;
65import type { HeaderGroup } from 'react-table' ;
7- import type { DataItem } from '../../src/types/types' ;
6+ import { describe , expect , it , vi } from 'vitest' ;
7+
8+ import { TableHeader } from '../../src/components/TableHeader' ;
89import type { ThemeProps } from '../../src/types/theme' ;
10+ import type { DataItem } from '../../src/types/types' ;
911
1012// Mock theme
1113const mockTheme : ThemeProps = {
@@ -28,7 +30,7 @@ const mockTheme: ThemeProps = {
2830// Mock header groups
2931const createMockHeaderGroup = (
3032 id : string ,
31- title : string ,
33+ title : string | React . ReactNode ,
3234 isSorted = false ,
3335 isSortedDesc = false ,
3436 hasFilter = false
@@ -42,21 +44,22 @@ const createMockHeaderGroup = (
4244 getSortByToggleProps : ( ) => ( {
4345 onClick : vi . fn ( ) ,
4446 } ) ,
45- render : ( type : string ) => ( type === 'Header' ? title : null ) ,
47+ render : ( type : string ) => ( type === 'Header' ? ( title || id ) : null ) ,
4648 isSorted,
4749 isSortedDesc,
4850 Filter : hasFilter
4951 ? ( { column } : { column : any } ) => (
50- < input
51- data-testid = { `filter-${ id } ` }
52- value = { column . filterValue || '' }
53- onChange = { ( e ) => column . setFilter ?.( e . target . value ) }
54- />
55- )
52+ < input
53+ data-testid = { `filter-${ id } ` }
54+ value = { column . filterValue || '' }
55+ onChange = { ( e ) => column . setFilter ?.( e . target . value ) }
56+ placeholder = { `Filter ${ column . title || column . id } ...` }
57+ />
58+ )
5659 : undefined ,
5760 setFilter : hasFilter ? vi . fn ( ) : undefined ,
5861 disableSortBy : false ,
59- title,
62+ title : title || id ,
6063 filterValue : '' ,
6164 } ;
6265
@@ -119,9 +122,11 @@ describe('TableHeader', () => {
119122
120123 it ( 'applies theme styles correctly' , ( ) => {
121124 const headerGroups = [ createMockHeaderGroup ( 'name' , 'Name' ) ] ;
125+
122126 renderTableHeader ( { headerGroups } ) ;
123127
124128 const headerCell = screen . getByRole ( 'columnheader' , { name : 'Name' } ) ;
129+
125130 expect ( headerCell ) . toHaveStyle ( {
126131 backgroundColor : mockTheme . table ?. header ?. background ,
127132 color : mockTheme . table ?. header ?. textColor ,
@@ -160,22 +165,27 @@ describe('TableHeader', () => {
160165
161166 it ( 'uses column id when title is not provided' , ( ) => {
162167 const headerGroups = [ createMockHeaderGroup ( 'name' , '' ) ] ;
168+
163169 renderTableHeader ( { headerGroups } ) ;
164170 expect ( screen . getByText ( 'name' ) ) . toBeInTheDocument ( ) ;
165171 } ) ;
166172
167173 it ( 'renders filter input when column has Filter component' , ( ) => {
168174 const headerGroups = [ createMockHeaderGroup ( 'name' , 'Name' , false , false , true ) ] ;
175+
169176 renderTableHeader ( { headerGroups } ) ;
170177 const filterInput = screen . getByPlaceholderText ( 'Filter Name...' ) ;
178+
171179 expect ( filterInput ) . toBeInTheDocument ( ) ;
172180 expect ( filterInput ) . toHaveClass ( 'filter-input' ) ;
173181 } ) ;
174182
175183 it ( 'applies filter theme styles correctly' , ( ) => {
176184 const headerGroups = [ createMockHeaderGroup ( 'name' , 'Name' , false , false , true ) ] ;
185+
177186 renderTableHeader ( { headerGroups } ) ;
178187 const filterInput = screen . getByPlaceholderText ( 'Filter Name...' ) ;
188+
179189 expect ( filterInput ) . toHaveStyle ( {
180190 color : mockTheme . table ?. filter ?. textColor ,
181191 borderColor : mockTheme . table ?. filter ?. borderColor ,
@@ -185,24 +195,43 @@ describe('TableHeader', () => {
185195
186196 it ( 'handles filter input change correctly' , ( ) => {
187197 const headerGroups = [ createMockHeaderGroup ( 'name' , 'Name' , false , false , true ) ] ;
198+
188199 renderTableHeader ( { headerGroups } ) ;
189200 const filterInput = screen . getByPlaceholderText ( 'Filter Name...' ) ;
201+
190202 fireEvent . change ( filterInput , { target : { value : 'test' } } ) ;
191203 const mockColumn = ( headerGroups [ 0 ] . headers [ 0 ] as any ) . column ;
204+
192205 expect ( mockColumn . setFilter ) . toHaveBeenCalledWith ( 'test' ) ;
193206 } ) ;
194207
195208 it ( 'renders filter input with column id when title is not provided' , ( ) => {
196209 const headerGroups = [ createMockHeaderGroup ( 'name' , '' , false , false , true ) ] ;
210+
197211 renderTableHeader ( { headerGroups } ) ;
198212 const filterInput = screen . getByPlaceholderText ( 'Filter name...' ) ;
213+
199214 expect ( filterInput ) . toBeInTheDocument ( ) ;
200215 } ) ;
201216
202217 it ( 'does not render filter input when column has no Filter component' , ( ) => {
203218 const headerGroups = [ createMockHeaderGroup ( 'name' , 'Name' , false , false , false ) ] ;
219+
204220 renderTableHeader ( { headerGroups } ) ;
205221 const filterInput = screen . queryByPlaceholderText ( 'Filter Name...' ) ;
222+
206223 expect ( filterInput ) . not . toBeInTheDocument ( ) ;
207224 } ) ;
225+
226+ it ( 'renders a React node as column header' , ( ) => {
227+ const customHeader = < span data-testid = "custom-header" > Custom</ span > ;
228+ const headerGroups = [
229+ createMockHeaderGroup ( 'custom' , customHeader as any ) ,
230+ ] ;
231+
232+ // Patch the render function to return the React node for 'Header'
233+ ( headerGroups [ 0 ] . headers [ 0 ] as any ) . render = ( type : string ) => type === 'Header' ? customHeader : null ;
234+ renderTableHeader ( { headerGroups } ) ;
235+ expect ( screen . getByTestId ( 'custom-header' ) ) . toBeInTheDocument ( ) ;
236+ } ) ;
208237} ) ;
0 commit comments