Skip to content

Commit 7be7428

Browse files
committed
test(query-devtools/Devtools): add tests for query list rendering, filtering, and status indicators
1 parent be4f84f commit 7be7428

1 file changed

Lines changed: 169 additions & 0 deletions

File tree

packages/query-devtools/src/__tests__/Devtools.test.tsx

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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(/Query key \["posts"\]/),
256+
).toBeInTheDocument()
257+
expect(
258+
rendered.getByLabelText(/Query key \["users","me"\]/),
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(/Query key \["new"\]/),
267+
).not.toBeInTheDocument()
268+
269+
queryClient.setQueryData(['new'], 'hello')
270+
271+
expect(rendered.getByLabelText(/Query key \["new"\]/)).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(/Query key \["posts"\]/),
285+
).toBeInTheDocument()
286+
expect(
287+
rendered.queryByLabelText(/Query key \["users"\]/),
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(/Query key \["posts"\]/),
300+
).not.toBeInTheDocument()
301+
expect(
302+
rendered.queryByLabelText(/Query key \["users"\]/),
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(/Mutation submitted at/),
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(/disabled/)).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(/Fresh: \d+/)).toBeInTheDocument()
376+
expect(rendered.getByLabelText(/Stale: \d+/)).toBeInTheDocument()
377+
expect(rendered.getByLabelText(/Fetching: \d+/)).toBeInTheDocument()
378+
expect(rendered.getByLabelText(/Paused: \d+/)).toBeInTheDocument()
379+
expect(rendered.getByLabelText(/Inactive: \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

Comments
 (0)