@@ -3,81 +3,110 @@ import { render, screen, fireEvent } from '@testing-library/react';
3
3
import TaskList from '../TaskList' ;
4
4
import useTodoStore from '../../stores/todoStore' ;
5
5
6
- // Tell Vitest to mock the entire todoStore module
7
- // This replaces the real implementation with a mock function
8
6
vi . mock ( '../../stores/todoStore' ) ;
9
7
10
8
describe ( 'TaskList' , ( ) => {
11
- // Mock data that represents what our store would normally return
12
9
const mockTodos = [
13
- { id : 1 , name : 'Test Todo' , priority : 'high' , completed_at : null } ,
14
- { id : 2 , name : 'Completed Todo' , priority : 'low' , completed_at : '2024-03-19' }
10
+ {
11
+ id : 1 ,
12
+ name : 'Test Todo' ,
13
+ priority : 'high' ,
14
+ completed_at : null ,
15
+ due_date : '2024-03-25'
16
+ } ,
17
+ {
18
+ id : 2 ,
19
+ name : 'Completed Todo' ,
20
+ priority : 'low' ,
21
+ completed_at : '2024-03-19' ,
22
+ due_date : '2024-03-20'
23
+ }
15
24
] ;
16
25
17
- // Create a mock store object that matches the shape of our real store
18
- // but with vi.fn() mock functions for actions
19
26
const mockStore = {
20
27
todos : mockTodos ,
21
28
isLoading : false ,
22
29
error : null ,
23
- fetchTodos : vi . fn ( ) , // Mock function for fetching todos
24
- completeTodo : vi . fn ( ) , // Mock function for completing todos
25
- deleteTodo : vi . fn ( ) , // Mock function for deleting todos
26
- incompleteTodo : vi . fn ( ) // Mock function for marking todos as incomplete
30
+ fetchTodos : vi . fn ( ) ,
31
+ completeTodo : vi . fn ( ) ,
32
+ deleteTodo : vi . fn ( ) ,
33
+ incompleteTodo : vi . fn ( )
27
34
} ;
28
35
29
- // Before each test, reset the mock implementation
30
- // This ensures each test starts with a fresh mock
31
36
beforeEach ( ( ) => {
32
- // When useTodoStore is called, return our mockStore
37
+ vi . clearAllMocks ( ) ;
33
38
useTodoStore . mockReturnValue ( mockStore ) ;
34
39
} ) ;
35
40
36
- // Test cases...
37
- // Each test renders the component and asserts expected behavior
38
- it ( 'renders todos list' , ( ) => {
41
+ it ( 'renders table with correct headers' , ( ) => {
39
42
render ( < TaskList /> ) ;
40
- expect ( screen . getByText ( 'Test Todo' ) ) . toBeInTheDocument ( ) ;
41
- expect ( screen . getByText ( 'Completed Todo' ) ) . toBeInTheDocument ( ) ;
43
+ expect ( screen . getByText ( 'Due Date' ) ) . toBeInTheDocument ( ) ;
44
+ expect ( screen . getByText ( 'Title' ) ) . toBeInTheDocument ( ) ;
45
+ expect ( screen . getByText ( 'Priority' ) ) . toBeInTheDocument ( ) ;
46
+ expect ( screen . getByText ( 'Action' ) ) . toBeInTheDocument ( ) ;
42
47
} ) ;
43
48
44
- // Test interaction with complete button
45
- // Verifies that clicking calls the mock function with correct ID
46
- it ( 'handles complete todo action' , ( ) => {
49
+ it ( 'renders todo items with due dates' , ( ) => {
47
50
render ( < TaskList /> ) ;
51
+ // Use a regex to match the date format
52
+ expect ( screen . getByText ( / 3 \/ 2 5 \/ 2 0 2 4 | 3 \/ 2 4 \/ 2 0 2 4 / ) ) . toBeInTheDocument ( ) ;
53
+ expect ( screen . getByText ( / 3 \/ 2 0 \/ 2 0 2 4 | 3 \/ 1 9 \/ 2 0 2 4 / ) ) . toBeInTheDocument ( ) ;
54
+ } ) ;
55
+
56
+ it ( 'applies correct styling for completed todos' , ( ) => {
57
+ render ( < TaskList /> ) ;
58
+ const completedRow = screen . getByText ( 'Completed Todo' ) . closest ( 'tr' ) ;
59
+ expect ( completedRow ) . toHaveClass ( 'table-success' ) ;
60
+ } ) ;
61
+
62
+ it ( 'applies correct styling for different priority levels' , ( ) => {
63
+ render ( < TaskList /> ) ;
64
+ const highPriorityTask = screen . getByText ( 'Test Todo' ) ;
65
+ expect ( highPriorityTask ) . toHaveClass ( 'text-danger' ) ;
66
+ expect ( highPriorityTask ) . toHaveStyle ( { textShadow : '1px 1px 2px red' } ) ;
67
+ } ) ;
68
+
69
+ it ( 'toggles todo completion status' , ( ) => {
70
+ render ( < TaskList /> ) ;
71
+
72
+ // Complete an incomplete todo
48
73
const completeButton = screen . getByLabelText ( 'Mark complete' ) ;
49
74
fireEvent . click ( completeButton ) ;
50
75
expect ( mockStore . completeTodo ) . toHaveBeenCalledWith ( 1 ) ;
76
+
77
+ // Incomplete a completed todo
78
+ const incompleteButton = screen . getByLabelText ( 'Mark incomplete' ) ;
79
+ fireEvent . click ( incompleteButton ) ;
80
+ expect ( mockStore . incompleteTodo ) . toHaveBeenCalledWith ( 2 ) ;
81
+ } ) ;
82
+
83
+ it ( 'shows correct completion icons' , ( ) => {
84
+ render ( < TaskList /> ) ;
85
+ expect ( screen . getByLabelText ( 'Mark complete' ) ) . toBeInTheDocument ( ) ;
86
+ expect ( screen . getByLabelText ( 'Mark incomplete' ) ) . toBeInTheDocument ( ) ;
51
87
} ) ;
52
88
53
- // Test interaction with delete button
54
- // Verifies that clicking calls the mock function with correct ID
55
- it ( 'handles delete todo action' , ( ) => {
89
+ it ( 'handles delete action' , ( ) => {
56
90
render ( < TaskList /> ) ;
57
- const deleteButton = screen . getAllByRole ( 'button' , { name : / D e l e t e / i } ) [ 0 ] ;
58
- fireEvent . click ( deleteButton ) ;
91
+ const deleteButtons = screen . getAllByText ( ' Delete' ) ;
92
+ fireEvent . click ( deleteButtons [ 0 ] ) ;
59
93
expect ( mockStore . deleteTodo ) . toHaveBeenCalledWith ( 1 ) ;
60
94
} ) ;
61
95
62
- // Test loading state by modifying mock store return value
63
- it ( 'shows loading state' , ( ) => {
64
- useTodoStore . mockReturnValue ( { ...mockStore , isLoading : true } ) ;
96
+ it ( 'fetches todos on mount' , ( ) => {
65
97
render ( < TaskList /> ) ;
66
- expect ( screen . getByRole ( 'status' ) ) . toBeInTheDocument ( ) ;
98
+ expect ( mockStore . fetchTodos ) . toHaveBeenCalledTimes ( 1 ) ;
67
99
} ) ;
68
100
69
- // Test error state by modifying mock store return value
70
- it ( 'shows error state' , ( ) => {
71
- useTodoStore . mockReturnValue ( { ...mockStore , error : 'Test error' } ) ;
101
+ it ( 'shows loading spinner when loading' , ( ) => {
102
+ useTodoStore . mockReturnValue ( { ...mockStore , isLoading : true } ) ;
72
103
render ( < TaskList /> ) ;
73
- expect ( screen . getByText ( 'Error: Test error ') ) . toBeInTheDocument ( ) ;
104
+ expect ( screen . getByRole ( 'status ') ) . toBeInTheDocument ( ) ;
74
105
} ) ;
75
106
76
- // Test incomplete todo action
77
- it ( 'handles incomplete todo action' , ( ) => {
107
+ it ( 'shows error message when there is an error' , ( ) => {
108
+ useTodoStore . mockReturnValue ( { ... mockStore , error : 'Failed to load todos' } ) ;
78
109
render ( < TaskList /> ) ;
79
- const incompleteButton = screen . getByLabelText ( 'Mark incomplete' ) ;
80
- fireEvent . click ( incompleteButton ) ;
81
- expect ( mockStore . incompleteTodo ) . toHaveBeenCalledWith ( 2 ) ;
110
+ expect ( screen . getByText ( 'Error: Failed to load todos' ) ) . toBeInTheDocument ( ) ;
82
111
} ) ;
83
112
} ) ;
0 commit comments