1
- import React from 'react' ;
2
- import { render , screen , fireEvent , waitFor } from '@testing-library/react' ;
3
- import { PullRequestItem } from './pull-request' ;
4
- import { vi , describe , it , expect , beforeEach } from 'vitest' ;
5
- import { PullRequest } from './types' ;
6
- import useSWR from 'swr' ;
7
-
8
- vi . mock ( '@/lib/github' , async ( ) => {
9
- const actual = await vi . importActual ( '@/lib/github' ) ;
1
+ import React from "react" ;
2
+ import { render , screen , fireEvent , waitFor } from "@testing-library/react" ;
3
+ import { PullRequestItem } from "./pull-request" ;
4
+ import { vi , describe , it , expect , beforeEach } from "vitest" ;
5
+ import { PullRequest } from "./types" ;
6
+ import useSWR from "swr" ;
7
+ import { fetchBuildStatus } from "@/lib/github" ;
8
+ import { experimental_useObject as useObject } from "ai/react" ;
9
+ import { act } from "react" ;
10
+
11
+ vi . mock ( "@/lib/github" , async ( ) => {
12
+ const actual = await vi . importActual ( "@/lib/github" ) ;
10
13
return {
11
14
...( actual as object ) ,
12
15
getPullRequestInfo : vi . fn ( ) ,
@@ -17,44 +20,56 @@ vi.mock('@/lib/github', async () => {
17
20
} ;
18
21
} ) ;
19
22
20
- vi . mock ( ' @/hooks/use-toast' , ( ) => ( {
23
+ vi . mock ( " @/hooks/use-toast" , ( ) => ( {
21
24
useToast : vi . fn ( ( ) => ( {
22
25
toast : vi . fn ( ) ,
23
26
} ) ) ,
24
27
} ) ) ;
25
28
26
- vi . mock ( 'next/link' , ( ) => ( {
27
- default : ( { children, href } : { children : React . ReactNode ; href : string } ) => (
28
- < a href = { href } > { children } </ a >
29
- ) ,
29
+ vi . mock ( "next/link" , ( ) => ( {
30
+ default : ( {
31
+ children,
32
+ href,
33
+ } : {
34
+ children : React . ReactNode ;
35
+ href : string ;
36
+ } ) => < a href = { href } > { children } </ a > ,
30
37
} ) ) ;
31
38
32
- vi . mock ( ' react-diff-viewer' , ( ) => ( {
39
+ vi . mock ( " react-diff-viewer" , ( ) => ( {
33
40
default : ( ) => < div data-testid = "react-diff-viewer" > Mocked Diff Viewer</ div > ,
34
41
} ) ) ;
35
42
36
- vi . mock ( ' swr' , ( ) => ( {
43
+ vi . mock ( " swr" , ( ) => ( {
37
44
default : vi . fn ( ) ,
38
45
} ) ) ;
39
46
40
- vi . mock ( ' ./log-view' , ( ) => ( {
47
+ vi . mock ( " ./log-view" , ( ) => ( {
41
48
LogView : ( ) => < div data-testid = "log-view" > Mocked Log View</ div > ,
42
49
} ) ) ;
43
50
44
- describe ( 'PullRequestItem' , ( ) => {
51
+ vi . mock ( "./log-view" , ( ) => ( {
52
+ LogView : ( ) => < div data-testid = "log-view" > Mocked Log View</ div > ,
53
+ } ) ) ;
54
+
55
+ vi . mock ( "ai/react" , ( ) => ( {
56
+ experimental_useObject : vi . fn ( ) ,
57
+ } ) ) ;
58
+
59
+ describe ( "PullRequestItem" , ( ) => {
45
60
const mockPullRequest : PullRequest = {
46
61
id : 1 ,
47
- title : ' Test PR' ,
62
+ title : " Test PR" ,
48
63
number : 123 ,
49
- buildStatus : ' success' ,
64
+ buildStatus : " success" ,
50
65
isDraft : false ,
51
- branchName : ' feature-branch' ,
66
+ branchName : " feature-branch" ,
52
67
repository : {
53
68
id : 1 ,
54
- name : ' test-repo' ,
55
- full_name : ' owner/test-repo' ,
69
+ name : " test-repo" ,
70
+ full_name : " owner/test-repo" ,
56
71
owner : {
57
- login : ' owner' ,
72
+ login : " owner" ,
58
73
} ,
59
74
} ,
60
75
} ;
@@ -69,17 +84,22 @@ describe('PullRequestItem', () => {
69
84
isValidating : false ,
70
85
isLoading : false ,
71
86
} ) ;
87
+ vi . mocked ( useObject ) . mockReturnValue ( {
88
+ object : null ,
89
+ submit : vi . fn ( ) ,
90
+ isLoading : false ,
91
+ } ) ;
72
92
} ) ;
73
93
74
- it ( ' renders the pull request information correctly' , ( ) => {
94
+ it ( " renders the pull request information correctly" , ( ) => {
75
95
render ( < PullRequestItem pullRequest = { mockPullRequest } /> ) ;
76
- expect ( screen . getByText ( ' Test PR' ) ) . toBeInTheDocument ( ) ;
77
- expect ( screen . getByText ( ' #123' ) ) . toBeInTheDocument ( ) ;
78
- expect ( screen . getByText ( ' Build: success' ) ) . toBeInTheDocument ( ) ;
96
+ expect ( screen . getByText ( " Test PR" ) ) . toBeInTheDocument ( ) ;
97
+ expect ( screen . getByText ( " #123" ) ) . toBeInTheDocument ( ) ;
98
+ expect ( screen . getByText ( " Build: success" ) ) . toBeInTheDocument ( ) ;
79
99
} ) ;
80
100
81
- it ( ' displays running build status' , ( ) => {
82
- const runningPR = { ...mockPullRequest , buildStatus : ' running' } ;
101
+ it ( " displays running build status" , ( ) => {
102
+ const runningPR = { ...mockPullRequest , buildStatus : " running" } ;
83
103
vi . mocked ( useSWR ) . mockReturnValue ( {
84
104
data : runningPR ,
85
105
mutate : vi . fn ( ) ,
@@ -88,12 +108,12 @@ describe('PullRequestItem', () => {
88
108
isLoading : false ,
89
109
} ) ;
90
110
render ( < PullRequestItem pullRequest = { runningPR } /> ) ;
91
- expect ( screen . getByText ( ' Build: Running' ) ) . toBeInTheDocument ( ) ;
92
- expect ( screen . getByText ( ' Running...' ) ) . toBeInTheDocument ( ) ;
111
+ expect ( screen . getByText ( " Build: Running" ) ) . toBeInTheDocument ( ) ;
112
+ expect ( screen . getByText ( " Running..." ) ) . toBeInTheDocument ( ) ;
93
113
} ) ;
94
114
95
- it ( ' disables buttons when build is running' , ( ) => {
96
- const runningPR = { ...mockPullRequest , buildStatus : ' running' } ;
115
+ it ( " disables buttons when build is running" , ( ) => {
116
+ const runningPR = { ...mockPullRequest , buildStatus : " running" } ;
97
117
vi . mocked ( useSWR ) . mockReturnValue ( {
98
118
data : runningPR ,
99
119
mutate : vi . fn ( ) ,
@@ -102,14 +122,16 @@ describe('PullRequestItem', () => {
102
122
isLoading : false ,
103
123
} ) ;
104
124
render ( < PullRequestItem pullRequest = { runningPR } /> ) ;
105
- expect ( screen . getByText ( ' Running...' ) ) . toBeDisabled ( ) ;
125
+ expect ( screen . getByText ( " Running..." ) ) . toBeDisabled ( ) ;
106
126
} ) ;
107
127
108
- it ( ' updates build status periodically' , async ( ) => {
128
+ it ( " updates build status periodically" , async ( ) => {
109
129
const mutate = vi . fn ( ) ;
110
130
const fetchBuildStatusMock = vi . fn ( ) . mockResolvedValue ( mockPullRequest ) ;
131
+ vi . mocked ( fetchBuildStatus ) . mockImplementation ( fetchBuildStatusMock ) ;
132
+
111
133
vi . mocked ( useSWR ) . mockImplementation ( ( key , fetcher , options ) => {
112
- if ( typeof fetcher === ' function' ) {
134
+ if ( typeof fetcher === " function" ) {
113
135
fetcher ( ) ;
114
136
}
115
137
return {
@@ -122,7 +144,7 @@ describe('PullRequestItem', () => {
122
144
} ) ;
123
145
124
146
render ( < PullRequestItem pullRequest = { mockPullRequest } /> ) ;
125
-
147
+
126
148
await waitFor ( ( ) => {
127
149
expect ( useSWR ) . toHaveBeenCalledWith (
128
150
`pullRequest-${ mockPullRequest . id } ` ,
@@ -134,20 +156,37 @@ describe('PullRequestItem', () => {
134
156
} )
135
157
) ;
136
158
} ) ;
159
+
160
+ // Verify that fetchBuildStatus is called with the correct parameters
161
+
162
+ expect ( fetchBuildStatusMock ) . toHaveBeenCalledWith (
163
+ mockPullRequest . repository . owner . login ,
164
+ mockPullRequest . repository . name ,
165
+ mockPullRequest . number
166
+ ) ;
137
167
} ) ;
138
168
139
- it ( 'triggers revalidation after committing changes' , async ( ) => {
140
- const { getPullRequestInfo, commitChangesToPullRequest } = await import ( '@/lib/github' ) ;
169
+ it ( "triggers revalidation after committing changes" , async ( ) => {
170
+ const { getPullRequestInfo, commitChangesToPullRequest } = await import (
171
+ "@/lib/github"
172
+ ) ;
141
173
vi . mocked ( getPullRequestInfo ) . mockResolvedValue ( {
142
- diff : ' mock diff' ,
143
- testFiles : [ { name : ' existing_test.ts' , content : ' existing content' } ] ,
174
+ diff : " mock diff" ,
175
+ testFiles : [ { name : " existing_test.ts" , content : " existing content" } ] ,
144
176
} ) ;
145
- vi . mocked ( commitChangesToPullRequest ) . mockResolvedValue ( 'https://github.com/commit/123' ) ;
177
+ vi . mocked ( commitChangesToPullRequest ) . mockResolvedValue (
178
+ "https://github.com/commit/123"
179
+ ) ;
146
180
147
- vi . mocked ( global . fetch ) . mockResolvedValue ( {
148
- ok : true ,
149
- json : ( ) => Promise . resolve ( [ { name : 'generated_test.ts' , content : 'generated content' } ] ) ,
150
- } as Response ) ;
181
+ const mockSubmit = vi . fn ( ) ;
182
+ vi . mocked ( useObject ) . mockReturnValue ( {
183
+ object : null ,
184
+ submit : mockSubmit ,
185
+ isLoading : false ,
186
+ setInput : vi . fn ( ) ,
187
+ error : null ,
188
+ stop : vi . fn ( ) ,
189
+ } ) ;
151
190
152
191
const mutate = vi . fn ( ) ;
153
192
vi . mocked ( useSWR ) . mockReturnValue ( {
@@ -159,14 +198,28 @@ describe('PullRequestItem', () => {
159
198
} ) ;
160
199
161
200
render ( < PullRequestItem pullRequest = { mockPullRequest } /> ) ;
162
- const writeTestsButton = screen . getByText ( 'Write new tests' ) ;
201
+
202
+ const writeTestsButton = screen . getByText ( "Write new tests" ) ;
163
203
fireEvent . click ( writeTestsButton ) ;
164
204
165
205
await waitFor ( ( ) => {
166
- expect ( screen . getByText ( 'generated_test.ts' ) ) . toBeInTheDocument ( ) ;
206
+ expect ( screen . getByText ( "Analyzing PR diff..." ) ) . toBeInTheDocument ( ) ;
207
+ } ) ;
208
+
209
+ await act ( async ( ) => {
210
+ const { onFinish } = vi . mocked ( useObject ) . mock . calls [ 0 ] [ 0 ] ;
211
+ await onFinish ( {
212
+ object : {
213
+ tests : [ { name : "generated_test.ts" , content : "generated content" } ] ,
214
+ } ,
215
+ } ) ;
216
+ } ) ;
217
+
218
+ await waitFor ( ( ) => {
219
+ expect ( screen . getByText ( "generated_test.ts" ) ) . toBeInTheDocument ( ) ;
167
220
} ) ;
168
221
169
- const commitButton = screen . getByText ( ' Commit changes' ) ;
222
+ const commitButton = screen . getByText ( " Commit changes" ) ;
170
223
fireEvent . click ( commitButton ) ;
171
224
172
225
await waitFor ( ( ) => {
@@ -175,36 +228,36 @@ describe('PullRequestItem', () => {
175
228
} ) ;
176
229
} ) ;
177
230
178
- it ( ' shows and hides logs when toggle is clicked' , async ( ) => {
231
+ it ( " shows and hides logs when toggle is clicked" , async ( ) => {
179
232
vi . mocked ( useSWR ) . mockReturnValue ( {
180
- data : { ...mockPullRequest , buildStatus : ' success' } ,
233
+ data : { ...mockPullRequest , buildStatus : " success" } ,
181
234
mutate : vi . fn ( ) ,
182
235
error : undefined ,
183
236
isValidating : false ,
184
237
isLoading : false ,
185
238
} ) ;
186
239
187
- const { getLatestRunId } = await import ( ' @/lib/github' ) ;
188
- vi . mocked ( getLatestRunId ) . mockResolvedValue ( ' 123' ) ;
240
+ const { getLatestRunId } = await import ( " @/lib/github" ) ;
241
+ vi . mocked ( getLatestRunId ) . mockResolvedValue ( " 123" ) ;
189
242
190
243
render ( < PullRequestItem pullRequest = { mockPullRequest } /> ) ;
191
244
192
245
await waitFor ( ( ) => {
193
- expect ( screen . getByText ( ' Show Logs' ) ) . toBeInTheDocument ( ) ;
246
+ expect ( screen . getByText ( " Show Logs" ) ) . toBeInTheDocument ( ) ;
194
247
} ) ;
195
248
196
- fireEvent . click ( screen . getByText ( ' Show Logs' ) ) ;
249
+ fireEvent . click ( screen . getByText ( " Show Logs" ) ) ;
197
250
198
251
await waitFor ( ( ) => {
199
- expect ( screen . getByTestId ( ' log-view' ) ) . toBeInTheDocument ( ) ;
200
- expect ( screen . getByText ( ' Hide Logs' ) ) . toBeInTheDocument ( ) ;
252
+ expect ( screen . getByTestId ( " log-view" ) ) . toBeInTheDocument ( ) ;
253
+ expect ( screen . getByText ( " Hide Logs" ) ) . toBeInTheDocument ( ) ;
201
254
} ) ;
202
255
203
- fireEvent . click ( screen . getByText ( ' Hide Logs' ) ) ;
256
+ fireEvent . click ( screen . getByText ( " Hide Logs" ) ) ;
204
257
205
258
await waitFor ( ( ) => {
206
- expect ( screen . queryByTestId ( ' log-view' ) ) . not . toBeInTheDocument ( ) ;
207
- expect ( screen . getByText ( ' Show Logs' ) ) . toBeInTheDocument ( ) ;
259
+ expect ( screen . queryByTestId ( " log-view" ) ) . not . toBeInTheDocument ( ) ;
260
+ expect ( screen . getByText ( " Show Logs" ) ) . toBeInTheDocument ( ) ;
208
261
} ) ;
209
262
} ) ;
210
263
} ) ;
0 commit comments