1- import { describe , it , expect , beforeEach , vi } from 'vitest'
2- import { render , screen } from '@testing-library/react'
1+ import { describe , it , expect , beforeEach , afterEach , vi } from 'vitest'
2+ import { render , screen , waitFor } from '@testing-library/react'
33import App from './App'
44import { useStore } from './store'
55
66describe ( 'App' , ( ) => {
7+ const originalLocation = window . location
8+
79 beforeEach ( ( ) => {
810 // Reset store state before each test
911 useStore . setState ( {
@@ -12,11 +14,40 @@ describe('App', () => {
1214 bugs : [ ] ,
1315 isLoading : false ,
1416 error : '' ,
15- filters : { whiteboardTag : '' , component : '' } ,
17+ filters : { whiteboardTag : '' , component : '' , excludeMetaBugs : false , sortOrder : 'priority' } ,
1618 changes : new Map ( ) ,
1719 isApplying : false ,
1820 applyError : '' ,
1921 } )
22+
23+ // Reset URL to base
24+ const mockLocation = {
25+ search : '' ,
26+ pathname : '/' ,
27+ href : 'http://localhost:3000/' ,
28+ origin : 'http://localhost:3000' ,
29+ host : 'localhost:3000' ,
30+ hostname : 'localhost' ,
31+ port : '3000' ,
32+ protocol : 'http:' ,
33+ hash : '' ,
34+ assign : vi . fn ( ) ,
35+ reload : vi . fn ( ) ,
36+ replace : vi . fn ( ) ,
37+ toString : ( ) => 'http://localhost:3000/' ,
38+ }
39+ Object . defineProperty ( window , 'location' , {
40+ value : mockLocation ,
41+ writable : true ,
42+ } )
43+ } )
44+
45+ afterEach ( ( ) => {
46+ vi . restoreAllMocks ( )
47+ Object . defineProperty ( window , 'location' , {
48+ value : originalLocation ,
49+ writable : true ,
50+ } )
2051 } )
2152
2253 describe ( 'without API key' , ( ) => {
@@ -143,4 +174,91 @@ describe('App', () => {
143174 const appContainer = container . querySelector ( '.min-h-screen' )
144175 expect ( appContainer ) . toHaveClass ( 'bg-bg-primary' )
145176 } )
177+
178+ describe ( 'auto-fetch with URL filters' , ( ) => {
179+ it ( 'should auto-fetch bugs when URL has filters and API key is loaded' , async ( ) => {
180+ // Setup: URL has filters
181+ window . location . search = '?whiteboard=%5Bkanban%5D'
182+
183+ const fetchBugs = vi . fn ( ) . mockResolvedValue ( [ ] )
184+
185+ // Simulate async API key loading - resolves after a short delay
186+ const loadApiKey = vi . fn ( ) . mockImplementation ( async ( ) => {
187+ await new Promise ( ( resolve ) => {
188+ setTimeout ( resolve , 10 )
189+ } )
190+ useStore . setState ( { apiKey : 'test-api-key' , isValid : true } )
191+ } )
192+
193+ useStore . setState ( {
194+ loadApiKey,
195+ fetchBugs,
196+ apiKey : '' , // No API key initially
197+ } )
198+
199+ render ( < App /> )
200+
201+ // Wait for loadApiKey to complete and fetchBugs to be called
202+ await waitFor ( ( ) => {
203+ expect ( fetchBugs ) . toHaveBeenCalledWith ( 'test-api-key' )
204+ } )
205+ } )
206+
207+ it ( 'should not auto-fetch when URL has no filters even with API key' , async ( ) => {
208+ // Setup: URL has no filters (search is empty)
209+ window . location . search = ''
210+
211+ const fetchBugs = vi . fn ( ) . mockResolvedValue ( [ ] )
212+ const loadApiKey = vi . fn ( ) . mockImplementation ( ( ) => {
213+ useStore . setState ( { apiKey : 'test-api-key' , isValid : true } )
214+ return Promise . resolve ( )
215+ } )
216+
217+ useStore . setState ( {
218+ loadApiKey,
219+ fetchBugs,
220+ apiKey : '' ,
221+ } )
222+
223+ render ( < App /> )
224+
225+ // Wait a bit to ensure no auto-fetch happens
226+ await new Promise ( ( resolve ) => {
227+ setTimeout ( resolve , 50 )
228+ } )
229+
230+ expect ( fetchBugs ) . not . toHaveBeenCalled ( )
231+ } )
232+
233+ it ( 'should apply filters from URL to store before fetching' , async ( ) => {
234+ window . location . search = '?whiteboard=%5Bkanban%5D&component=Core'
235+
236+ const fetchBugs = vi . fn ( ) . mockResolvedValue ( [ ] )
237+ const setFilters = vi . fn ( )
238+ const loadApiKey = vi . fn ( ) . mockImplementation ( async ( ) => {
239+ await new Promise ( ( resolve ) => {
240+ setTimeout ( resolve , 10 )
241+ } )
242+ useStore . setState ( { apiKey : 'test-api-key' , isValid : true } )
243+ } )
244+
245+ useStore . setState ( {
246+ loadApiKey,
247+ fetchBugs,
248+ setFilters,
249+ apiKey : '' ,
250+ } )
251+
252+ render ( < App /> )
253+
254+ await waitFor ( ( ) => {
255+ expect ( setFilters ) . toHaveBeenCalledWith (
256+ expect . objectContaining ( {
257+ whiteboardTag : '[kanban]' ,
258+ component : 'Core' ,
259+ } ) ,
260+ )
261+ } )
262+ } )
263+ } )
146264} )
0 commit comments