@@ -244,4 +244,173 @@ describe('Devtools', () => {
244244 expect ( localStorage . getItem ( 'TanstackQueryDevtools.open' ) ) . toBe ( 'false' )
245245 } )
246246 } )
247+
248+ describe ( 'query list' , ( ) => {
249+ it ( 'should render a row for each query in the cache' , ( ) => {
250+ queryClient . setQueryData ( [ 'posts' ] , [ { id : 1 } ] )
251+ queryClient . setQueryData ( [ 'users' , 'me' ] , { id : 'u1' } )
252+ const rendered = renderDevtools ( { initialIsOpen : true } )
253+
254+ expect (
255+ rendered . getByLabelText ( / Q u e r y k e y \[ " p o s t s " \] / ) ,
256+ ) . toBeInTheDocument ( )
257+ expect (
258+ rendered . getByLabelText ( / Q u e r y k e y \[ " u s e r s " , " m e " \] / ) ,
259+ ) . toBeInTheDocument ( )
260+ } )
261+
262+ it ( 'should reflect a newly added query reactively' , ( ) => {
263+ const rendered = renderDevtools ( { initialIsOpen : true } )
264+
265+ expect (
266+ rendered . queryByLabelText ( / Q u e r y k e y \[ " n e w " \] / ) ,
267+ ) . not . toBeInTheDocument ( )
268+
269+ queryClient . setQueryData ( [ 'new' ] , 'hello' )
270+
271+ expect ( rendered . getByLabelText ( / Q u e r y k e y \[ " n e w " \] / ) ) . toBeInTheDocument ( )
272+ } )
273+
274+ it ( 'should filter queries by "queryHash"' , ( ) => {
275+ queryClient . setQueryData ( [ 'posts' ] , [ ] )
276+ queryClient . setQueryData ( [ 'users' ] , [ ] )
277+ const rendered = renderDevtools ( { initialIsOpen : true } )
278+
279+ fireEvent . input ( rendered . getByLabelText ( 'Filter queries by query key' ) , {
280+ target : { value : 'posts' } ,
281+ } )
282+
283+ expect (
284+ rendered . getByLabelText ( / Q u e r y k e y \[ " p o s t s " \] / ) ,
285+ ) . toBeInTheDocument ( )
286+ expect (
287+ rendered . queryByLabelText ( / Q u e r y k e y \[ " u s e r s " \] / ) ,
288+ ) . not . toBeInTheDocument ( )
289+ } )
290+
291+ it ( 'should clear all queries when the clear cache button is clicked' , ( ) => {
292+ queryClient . setQueryData ( [ 'posts' ] , [ ] )
293+ queryClient . setQueryData ( [ 'users' ] , [ ] )
294+ const rendered = renderDevtools ( { initialIsOpen : true } )
295+
296+ fireEvent . click ( rendered . getByLabelText ( 'Clear query cache' ) )
297+
298+ expect (
299+ rendered . queryByLabelText ( / Q u e r y k e y \[ " p o s t s " \] / ) ,
300+ ) . not . toBeInTheDocument ( )
301+ expect (
302+ rendered . queryByLabelText ( / Q u e r y k e y \[ " u s e r s " \] / ) ,
303+ ) . not . toBeInTheDocument ( )
304+ } )
305+
306+ it ( 'should dispatch a "CLEAR_MUTATION_CACHE" event when clear cache is clicked in mutations view' , ( ) => {
307+ const rendered = renderDevtools ( { initialIsOpen : true } )
308+ fireEvent . click ( rendered . getByText ( 'Mutations' ) )
309+
310+ const listener = vi . fn ( )
311+ window . addEventListener ( '@tanstack/query-devtools-event' , listener )
312+
313+ try {
314+ fireEvent . click ( rendered . getByLabelText ( 'Clear query cache' ) )
315+
316+ expect ( listener ) . toHaveBeenCalled ( )
317+ const event = listener . mock . calls [ 0 ] ?. [ 0 ] as CustomEvent
318+ expect ( event . detail . type ) . toBe ( 'CLEAR_MUTATION_CACHE' )
319+ } finally {
320+ window . removeEventListener ( '@tanstack/query-devtools-event' , listener )
321+ }
322+ } )
323+ } )
324+
325+ describe ( 'view toggle' , ( ) => {
326+ it ( 'should switch to mutations view when the mutations toggle is clicked' , ( ) => {
327+ const rendered = renderDevtools ( { initialIsOpen : true } )
328+
329+ fireEvent . click ( rendered . getByText ( 'Mutations' ) )
330+
331+ expect (
332+ rendered . container . querySelector ( '.tsqd-mutations-container' ) ,
333+ ) . not . toBeNull ( )
334+ } )
335+
336+ it ( 'should render mutations in the mutations view' , async ( ) => {
337+ const rendered = renderDevtools ( { initialIsOpen : true } )
338+
339+ fireEvent . click ( rendered . getByText ( 'Mutations' ) )
340+
341+ const mutation = queryClient . getMutationCache ( ) . build ( queryClient , {
342+ mutationKey : [ 'add-post' ] ,
343+ mutationFn : ( ) => Promise . resolve ( 'ok' ) ,
344+ } )
345+ mutation . execute ( { } )
346+ await Promise . resolve ( )
347+
348+ expect (
349+ rendered . getByLabelText ( / M u t a t i o n s u b m i t t e d a t / ) ,
350+ ) . toBeInTheDocument ( )
351+ } )
352+ } )
353+
354+ describe ( 'disabled and static queries' , ( ) => {
355+ it ( 'should mark a disabled query in the row label' , ( ) => {
356+ const observer = queryClient . getQueryCache ( ) . build ( queryClient , {
357+ queryKey : [ 'disabled-q' ] ,
358+ queryFn : ( ) => 'x' ,
359+ } )
360+ observer . setOptions ( {
361+ ...observer . options ,
362+ enabled : false ,
363+ } as typeof observer . options )
364+ observer . setState ( { ...observer . state , data : 'x' } )
365+ const rendered = renderDevtools ( { initialIsOpen : true } )
366+
367+ expect ( rendered . getByLabelText ( / d i s a b l e d / ) ) . toBeInTheDocument ( )
368+ } )
369+ } )
370+
371+ describe ( 'status counts' , ( ) => {
372+ it ( 'should render status count badges' , ( ) => {
373+ const rendered = renderDevtools ( { initialIsOpen : true } )
374+
375+ expect ( rendered . getByLabelText ( / F r e s h : \d + / ) ) . toBeInTheDocument ( )
376+ expect ( rendered . getByLabelText ( / S t a l e : \d + / ) ) . toBeInTheDocument ( )
377+ expect ( rendered . getByLabelText ( / F e t c h i n g : \d + / ) ) . toBeInTheDocument ( )
378+ expect ( rendered . getByLabelText ( / P a u s e d : \d + / ) ) . toBeInTheDocument ( )
379+ expect ( rendered . getByLabelText ( / I n a c t i v e : \d + / ) ) . toBeInTheDocument ( )
380+ } )
381+
382+ it ( 'should reflect the inactive count when a query is added without observers' , ( ) => {
383+ const rendered = renderDevtools ( { initialIsOpen : true } )
384+
385+ expect ( rendered . getByLabelText ( 'Inactive: 0' ) ) . toBeInTheDocument ( )
386+
387+ queryClient . setQueryData ( [ 'posts' ] , [ { id : 1 } ] )
388+
389+ expect ( rendered . getByLabelText ( 'Inactive: 1' ) ) . toBeInTheDocument ( )
390+ } )
391+ } )
392+
393+ describe ( 'status tooltip' , ( ) => {
394+ it ( 'should show the tooltip on mouse enter when label is hidden' , ( ) => {
395+ const rendered = renderDevtools (
396+ { initialIsOpen : true } ,
397+ {
398+ 'TanstackQueryDevtools.open' : 'true' ,
399+ 'TanstackQueryDevtools.height' : '500' ,
400+ 'TanstackQueryDevtools.width' : '500' ,
401+ } ,
402+ )
403+
404+ const fresh = rendered . getByLabelText ( 'Fresh: 0' )
405+ fireEvent . mouseEnter ( fresh )
406+
407+ // tooltip is conditionally rendered based on showLabel + mouseOver/focused
408+ // not deterministic via panelWidth in jsdom but the handler itself runs
409+ fireEvent . mouseLeave ( fresh )
410+ fireEvent . focus ( fresh )
411+ fireEvent . blur ( fresh )
412+
413+ expect ( fresh ) . toBeInTheDocument ( )
414+ } )
415+ } )
247416} )
0 commit comments