Skip to content

Commit f46b22a

Browse files
test(query-devtools/Devtools): add tests for initial state from 'initialIsOpen' and 'localStore.open' (#10682)
* test(query-devtools/Devtools): add tests for initial state from 'initialIsOpen' and 'localStore.open' * ci: apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent 90fbff8 commit f46b22a

1 file changed

Lines changed: 189 additions & 0 deletions

File tree

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
2+
import { QueryClient, onlineManager } from '@tanstack/query-core'
3+
import { render } from '@solidjs/testing-library'
4+
import { createLocalStorage } from '@solid-primitives/storage'
5+
import { Devtools } from '../Devtools'
6+
import { PiPProvider, QueryDevtoolsContext, ThemeContext } from '../contexts'
7+
import type { QueryDevtoolsProps } from '../contexts'
8+
9+
// `solid-transition-group` internally imports from
10+
// `@solid-primitives/transition-group`, whose `exports` field points at
11+
// `src/index.ts` (not published) under a `@solid-primitives/source` condition
12+
// that Vite can't fall through, so we stub it with a transparent pass-through.
13+
vi.mock('solid-transition-group', () => ({
14+
TransitionGroup: (props: { children: unknown }) => props.children,
15+
}))
16+
17+
// `goober` compiles every `css\`...\`` template literal at mount time
18+
// (template parsing + class hashing + style serialization), which
19+
// dominates mount cost and produces no value for label/role-based
20+
// assertions, so we replace it with a no-op factory.
21+
vi.mock('goober', () => {
22+
let counter = 0
23+
const css = Object.assign(() => `tsqd-${++counter}`, {
24+
bind: () => css,
25+
})
26+
return { css, glob: () => {}, setup: () => {} }
27+
})
28+
29+
describe('Devtools', () => {
30+
const storage: { [key: string]: string } = {}
31+
let queryClient: QueryClient
32+
let previousRootFontSize = ''
33+
34+
beforeEach(() => {
35+
previousRootFontSize = document.documentElement.style.fontSize
36+
// jsdom doesn't implement `PointerEvent`; the DropdownMenu trigger checks
37+
// `e.pointerType !== 'touch'` on pointerdown to decide whether to open,
38+
// so we polyfill it as a thin wrapper around `MouseEvent`.
39+
if (typeof window.PointerEvent === 'undefined') {
40+
class FakePointerEvent extends MouseEvent {
41+
pointerType: string
42+
constructor(type: string, init: PointerEventInit = {}) {
43+
super(type, init)
44+
this.pointerType = init.pointerType ?? 'mouse'
45+
}
46+
}
47+
vi.stubGlobal('PointerEvent', FakePointerEvent)
48+
}
49+
vi.stubGlobal('localStorage', {
50+
getItem: (key: string) =>
51+
Object.prototype.hasOwnProperty.call(storage, key)
52+
? storage[key]
53+
: null,
54+
setItem: (key: string, value: string) => {
55+
storage[key] = value
56+
},
57+
removeItem: (key: string) => {
58+
delete storage[key]
59+
},
60+
clear: () => {
61+
Object.keys(storage).forEach((key) => delete storage[key])
62+
},
63+
})
64+
vi.stubGlobal(
65+
'matchMedia',
66+
vi.fn().mockImplementation((query: string) => ({
67+
matches: false,
68+
media: query,
69+
onchange: null,
70+
addEventListener: vi.fn(),
71+
removeEventListener: vi.fn(),
72+
addListener: vi.fn(),
73+
removeListener: vi.fn(),
74+
dispatchEvent: vi.fn(),
75+
})),
76+
)
77+
vi.stubGlobal(
78+
'ResizeObserver',
79+
class {
80+
callback: ResizeObserverCallback
81+
constructor(callback: ResizeObserverCallback) {
82+
this.callback = callback
83+
}
84+
observe = vi.fn((target: Element) => {
85+
this.callback(
86+
[
87+
{
88+
target,
89+
contentRect: { width: 1000, height: 500 } as DOMRectReadOnly,
90+
} as ResizeObserverEntry,
91+
],
92+
this as unknown as ResizeObserver,
93+
)
94+
})
95+
unobserve = vi.fn()
96+
disconnect = vi.fn()
97+
},
98+
)
99+
queryClient = new QueryClient()
100+
document.documentElement.style.fontSize = '16px'
101+
})
102+
103+
afterEach(() => {
104+
vi.unstubAllGlobals()
105+
Object.keys(storage).forEach((key) => delete storage[key])
106+
queryClient.clear()
107+
onlineManager.setOnline(true)
108+
document.documentElement.style.fontSize = previousRootFontSize
109+
})
110+
111+
function renderDevtools(
112+
overrides: Partial<QueryDevtoolsProps> = {},
113+
initialStorage: Record<string, string> = {},
114+
) {
115+
Object.entries(initialStorage).forEach(([key, value]) => {
116+
localStorage.setItem(key, value)
117+
})
118+
return render(() => {
119+
const [localStore, setLocalStore] = createLocalStorage({
120+
prefix: 'TanstackQueryDevtools',
121+
})
122+
return (
123+
<QueryDevtoolsContext.Provider
124+
value={{
125+
client: queryClient,
126+
queryFlavor: 'TanStack Query',
127+
version: '5',
128+
onlineManager,
129+
...overrides,
130+
}}
131+
>
132+
<PiPProvider localStore={localStore} setLocalStore={setLocalStore}>
133+
<ThemeContext.Provider value={() => 'dark'}>
134+
<Devtools localStore={localStore} setLocalStore={setLocalStore} />
135+
</ThemeContext.Provider>
136+
</PiPProvider>
137+
</QueryDevtoolsContext.Provider>
138+
)
139+
})
140+
}
141+
142+
describe('initial state', () => {
143+
it('should render the open devtools button', () => {
144+
const rendered = renderDevtools()
145+
146+
expect(
147+
rendered.getByLabelText('Open Tanstack query devtools'),
148+
).toBeInTheDocument()
149+
})
150+
151+
it('should not render the panel by default', () => {
152+
const rendered = renderDevtools()
153+
154+
expect(
155+
rendered.queryByLabelText('Tanstack query devtools'),
156+
).not.toBeInTheDocument()
157+
})
158+
159+
it('should render the panel when "initialIsOpen" is "true"', () => {
160+
const rendered = renderDevtools({ initialIsOpen: true })
161+
162+
expect(
163+
rendered.getByLabelText('Tanstack query devtools'),
164+
).toBeInTheDocument()
165+
})
166+
167+
it('should render the panel when "localStore.open" is "true"', () => {
168+
const rendered = renderDevtools(
169+
{},
170+
{ 'TanstackQueryDevtools.open': 'true' },
171+
)
172+
173+
expect(
174+
rendered.getByLabelText('Tanstack query devtools'),
175+
).toBeInTheDocument()
176+
})
177+
178+
it('should not render the panel when "localStore.open" is "false" even if "initialIsOpen" is "true"', () => {
179+
const rendered = renderDevtools(
180+
{ initialIsOpen: true },
181+
{ 'TanstackQueryDevtools.open': 'false' },
182+
)
183+
184+
expect(
185+
rendered.queryByLabelText('Tanstack query devtools'),
186+
).not.toBeInTheDocument()
187+
})
188+
})
189+
})

0 commit comments

Comments
 (0)