diff --git a/packages/preact-query-devtools/package.json b/packages/preact-query-devtools/package.json
index cbcbe3f949..f9a03c29de 100644
--- a/packages/preact-query-devtools/package.json
+++ b/packages/preact-query-devtools/package.json
@@ -27,6 +27,8 @@
"test:types:ts59": "node ../../node_modules/typescript59/lib/tsc.js --build tsconfig.legacy.json",
"test:types:tscurrent": "tsc --build",
"test:types:ts60": "node ../../node_modules/typescript60/lib/tsc.js --build tsconfig.legacy.json",
+ "test:lib": "vitest",
+ "test:lib:dev": "pnpm run test:lib --watch",
"test:build": "publint --strict && attw --pack",
"build": "tsup --tsconfig tsconfig.prod.json",
"build:dev": "tsup --watch"
diff --git a/packages/preact-query-devtools/src/__tests__/PreactQueryDevtools.test.tsx b/packages/preact-query-devtools/src/__tests__/PreactQueryDevtools.test.tsx
new file mode 100644
index 0000000000..25fd5c4169
--- /dev/null
+++ b/packages/preact-query-devtools/src/__tests__/PreactQueryDevtools.test.tsx
@@ -0,0 +1,77 @@
+import { beforeEach, describe, expect, it, vi } from 'vitest'
+import { render } from '@testing-library/preact'
+import { QueryClient, QueryClientProvider } from '@tanstack/preact-query'
+import type { TanstackQueryDevtools } from '@tanstack/query-devtools'
+
+const mountMock = vi.fn()
+const unmountMock = vi.fn()
+const setClientMock = vi.fn()
+const setButtonPositionMock = vi.fn()
+const setPositionMock = vi.fn()
+const setInitialIsOpenMock = vi.fn()
+const setErrorTypesMock = vi.fn()
+const setThemeMock = vi.fn()
+
+vi.mock('@tanstack/query-devtools', () => ({
+ TanstackQueryDevtools: vi.fn(function (this: TanstackQueryDevtools) {
+ this.mount = mountMock
+ this.unmount = unmountMock
+ this.setClient = setClientMock
+ this.setButtonPosition = setButtonPositionMock
+ this.setPosition = setPositionMock
+ this.setInitialIsOpen = setInitialIsOpenMock
+ this.setErrorTypes = setErrorTypesMock
+ this.setTheme = setThemeMock
+ }),
+}))
+
+describe('PreactQueryDevtools', () => {
+ beforeEach(() => {
+ vi.clearAllMocks()
+ })
+
+ it('should throw an error if no query client has been set', async () => {
+ const { PreactQueryDevtools } = await import('../PreactQueryDevtools')
+
+ expect(() => render()).toThrow(
+ 'No QueryClient set, use QueryClientProvider to set one',
+ )
+ })
+
+ it('should not throw an error if query client is provided via context', async () => {
+ const { PreactQueryDevtools } = await import('../PreactQueryDevtools')
+ const queryClient = new QueryClient()
+
+ expect(() =>
+ render(
+
+
+ ,
+ ),
+ ).not.toThrow()
+ expect(mountMock).toHaveBeenCalled()
+ })
+
+ it('should not throw an error if query client is provided via props', async () => {
+ const { PreactQueryDevtools } = await import('../PreactQueryDevtools')
+ const queryClient = new QueryClient()
+
+ expect(() =>
+ render(),
+ ).not.toThrow()
+ expect(mountMock).toHaveBeenCalled()
+ })
+
+ it('should return null in non-development environments', async () => {
+ vi.stubEnv('NODE_ENV', 'production')
+ vi.resetModules()
+
+ try {
+ const { PreactQueryDevtools } = await import('..')
+ expect(PreactQueryDevtools({})).toBeNull()
+ } finally {
+ vi.unstubAllEnvs()
+ vi.resetModules()
+ }
+ })
+})
diff --git a/packages/preact-query-devtools/src/__tests__/PreactQueryDevtoolsPanel.test.tsx b/packages/preact-query-devtools/src/__tests__/PreactQueryDevtoolsPanel.test.tsx
new file mode 100644
index 0000000000..cc03560a36
--- /dev/null
+++ b/packages/preact-query-devtools/src/__tests__/PreactQueryDevtoolsPanel.test.tsx
@@ -0,0 +1,78 @@
+import { beforeEach, describe, expect, it, vi } from 'vitest'
+import { render } from '@testing-library/preact'
+import { QueryClient, QueryClientProvider } from '@tanstack/preact-query'
+import type { TanstackQueryDevtoolsPanel } from '@tanstack/query-devtools'
+
+const mountMock = vi.fn()
+const unmountMock = vi.fn()
+const setClientMock = vi.fn()
+const setOnCloseMock = vi.fn()
+const setErrorTypesMock = vi.fn()
+const setThemeMock = vi.fn()
+
+vi.mock('@tanstack/query-devtools', () => ({
+ TanstackQueryDevtoolsPanel: vi.fn(function (
+ this: TanstackQueryDevtoolsPanel,
+ ) {
+ this.mount = mountMock
+ this.unmount = unmountMock
+ this.setClient = setClientMock
+ this.setOnClose = setOnCloseMock
+ this.setErrorTypes = setErrorTypesMock
+ this.setTheme = setThemeMock
+ }),
+}))
+
+describe('PreactQueryDevtoolsPanel', () => {
+ beforeEach(() => {
+ vi.clearAllMocks()
+ })
+
+ it('should throw an error if no query client has been set', async () => {
+ const { PreactQueryDevtoolsPanel } =
+ await import('../PreactQueryDevtoolsPanel')
+
+ expect(() => render()).toThrow(
+ 'No QueryClient set, use QueryClientProvider to set one',
+ )
+ })
+
+ it('should not throw an error if query client is provided via context', async () => {
+ const { PreactQueryDevtoolsPanel } =
+ await import('../PreactQueryDevtoolsPanel')
+ const queryClient = new QueryClient()
+
+ expect(() =>
+ render(
+
+
+ ,
+ ),
+ ).not.toThrow()
+ expect(mountMock).toHaveBeenCalled()
+ })
+
+ it('should not throw an error if query client is provided via props', async () => {
+ const { PreactQueryDevtoolsPanel } =
+ await import('../PreactQueryDevtoolsPanel')
+ const queryClient = new QueryClient()
+
+ expect(() =>
+ render(),
+ ).not.toThrow()
+ expect(mountMock).toHaveBeenCalled()
+ })
+
+ it('should return null in non-development environments', async () => {
+ vi.stubEnv('NODE_ENV', 'production')
+ vi.resetModules()
+
+ try {
+ const { PreactQueryDevtoolsPanel } = await import('..')
+ expect(PreactQueryDevtoolsPanel({})).toBeNull()
+ } finally {
+ vi.unstubAllEnvs()
+ vi.resetModules()
+ }
+ })
+})
diff --git a/packages/react-query-devtools/src/__tests__/ReactQueryDevtools.test.tsx b/packages/react-query-devtools/src/__tests__/ReactQueryDevtools.test.tsx
new file mode 100644
index 0000000000..0d48c3d173
--- /dev/null
+++ b/packages/react-query-devtools/src/__tests__/ReactQueryDevtools.test.tsx
@@ -0,0 +1,77 @@
+import { beforeEach, describe, expect, it, vi } from 'vitest'
+import { render } from '@testing-library/react'
+import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
+import type { TanstackQueryDevtools } from '@tanstack/query-devtools'
+
+const mountMock = vi.fn()
+const unmountMock = vi.fn()
+const setClientMock = vi.fn()
+const setButtonPositionMock = vi.fn()
+const setPositionMock = vi.fn()
+const setInitialIsOpenMock = vi.fn()
+const setErrorTypesMock = vi.fn()
+const setThemeMock = vi.fn()
+
+vi.mock('@tanstack/query-devtools', () => ({
+ TanstackQueryDevtools: vi.fn(function (this: TanstackQueryDevtools) {
+ this.mount = mountMock
+ this.unmount = unmountMock
+ this.setClient = setClientMock
+ this.setButtonPosition = setButtonPositionMock
+ this.setPosition = setPositionMock
+ this.setInitialIsOpen = setInitialIsOpenMock
+ this.setErrorTypes = setErrorTypesMock
+ this.setTheme = setThemeMock
+ }),
+}))
+
+describe('ReactQueryDevtools', () => {
+ beforeEach(() => {
+ vi.clearAllMocks()
+ })
+
+ it('should throw an error if no query client has been set', async () => {
+ const { ReactQueryDevtools } = await import('../ReactQueryDevtools')
+
+ expect(() => render()).toThrow(
+ 'No QueryClient set, use QueryClientProvider to set one',
+ )
+ })
+
+ it('should not throw an error if query client is provided via context', async () => {
+ const { ReactQueryDevtools } = await import('../ReactQueryDevtools')
+ const queryClient = new QueryClient()
+
+ expect(() =>
+ render(
+
+
+ ,
+ ),
+ ).not.toThrow()
+ expect(mountMock).toHaveBeenCalled()
+ })
+
+ it('should not throw an error if query client is provided via props', async () => {
+ const { ReactQueryDevtools } = await import('../ReactQueryDevtools')
+ const queryClient = new QueryClient()
+
+ expect(() =>
+ render(),
+ ).not.toThrow()
+ expect(mountMock).toHaveBeenCalled()
+ })
+
+ it('should return null in non-development environments', async () => {
+ vi.stubEnv('NODE_ENV', 'production')
+ vi.resetModules()
+
+ try {
+ const { ReactQueryDevtools } = await import('..')
+ expect(ReactQueryDevtools({})).toBeNull()
+ } finally {
+ vi.unstubAllEnvs()
+ vi.resetModules()
+ }
+ })
+})
diff --git a/packages/react-query-devtools/src/__tests__/ReactQueryDevtoolsPanel.test.tsx b/packages/react-query-devtools/src/__tests__/ReactQueryDevtoolsPanel.test.tsx
new file mode 100644
index 0000000000..4beb7d99c0
--- /dev/null
+++ b/packages/react-query-devtools/src/__tests__/ReactQueryDevtoolsPanel.test.tsx
@@ -0,0 +1,78 @@
+import { beforeEach, describe, expect, it, vi } from 'vitest'
+import { render } from '@testing-library/react'
+import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
+import type { TanstackQueryDevtoolsPanel } from '@tanstack/query-devtools'
+
+const mountMock = vi.fn()
+const unmountMock = vi.fn()
+const setClientMock = vi.fn()
+const setOnCloseMock = vi.fn()
+const setErrorTypesMock = vi.fn()
+const setThemeMock = vi.fn()
+
+vi.mock('@tanstack/query-devtools', () => ({
+ TanstackQueryDevtoolsPanel: vi.fn(function (
+ this: TanstackQueryDevtoolsPanel,
+ ) {
+ this.mount = mountMock
+ this.unmount = unmountMock
+ this.setClient = setClientMock
+ this.setOnClose = setOnCloseMock
+ this.setErrorTypes = setErrorTypesMock
+ this.setTheme = setThemeMock
+ }),
+}))
+
+describe('ReactQueryDevtoolsPanel', () => {
+ beforeEach(() => {
+ vi.clearAllMocks()
+ })
+
+ it('should throw an error if no query client has been set', async () => {
+ const { ReactQueryDevtoolsPanel } =
+ await import('../ReactQueryDevtoolsPanel')
+
+ expect(() => render()).toThrow(
+ 'No QueryClient set, use QueryClientProvider to set one',
+ )
+ })
+
+ it('should not throw an error if query client is provided via context', async () => {
+ const { ReactQueryDevtoolsPanel } =
+ await import('../ReactQueryDevtoolsPanel')
+ const queryClient = new QueryClient()
+
+ expect(() =>
+ render(
+
+
+ ,
+ ),
+ ).not.toThrow()
+ expect(mountMock).toHaveBeenCalled()
+ })
+
+ it('should not throw an error if query client is provided via props', async () => {
+ const { ReactQueryDevtoolsPanel } =
+ await import('../ReactQueryDevtoolsPanel')
+ const queryClient = new QueryClient()
+
+ expect(() =>
+ render(),
+ ).not.toThrow()
+ expect(mountMock).toHaveBeenCalled()
+ })
+
+ it('should return null in non-development environments', async () => {
+ vi.stubEnv('NODE_ENV', 'production')
+ vi.resetModules()
+
+ try {
+ const { ReactQueryDevtoolsPanel } = await import('..')
+ expect(ReactQueryDevtoolsPanel({})).toBeNull()
+ } finally {
+ vi.unstubAllEnvs()
+ vi.resetModules()
+ }
+ })
+})
diff --git a/packages/react-query-devtools/src/__tests__/devtools.test.tsx b/packages/react-query-devtools/src/__tests__/devtools.test.tsx
deleted file mode 100644
index 0e44d74db6..0000000000
--- a/packages/react-query-devtools/src/__tests__/devtools.test.tsx
+++ /dev/null
@@ -1,7 +0,0 @@
-import { describe, expect, it } from 'vitest'
-
-describe('ReactQueryDevtools', () => {
- it('should be able to open and close devtools', () => {
- expect(1).toBe(1)
- })
-})
diff --git a/packages/react-query-devtools/src/__tests__/not-development.test.tsx b/packages/react-query-devtools/src/__tests__/not-development.test.tsx
deleted file mode 100644
index 6353147ed4..0000000000
--- a/packages/react-query-devtools/src/__tests__/not-development.test.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import { describe, expect, it } from 'vitest'
-import { ReactQueryDevtools } from '..'
-
-describe('ReactQueryDevtools not in process.env.NODE_ENV=development', () => {
- it('should return null', () => {
- expect(process.env.NODE_ENV).not.toBe('development')
- expect(ReactQueryDevtools({})).toBeNull()
- })
-})
diff --git a/packages/svelte-query-devtools/tests/Devtools.svelte.test.ts b/packages/svelte-query-devtools/tests/Devtools.svelte.test.ts
index 6808633dad..dc773f5430 100644
--- a/packages/svelte-query-devtools/tests/Devtools.svelte.test.ts
+++ b/packages/svelte-query-devtools/tests/Devtools.svelte.test.ts
@@ -2,6 +2,7 @@ import { describe, expect, it } from 'vitest'
import { render } from '@testing-library/svelte'
import { QueryClient } from '@tanstack/svelte-query'
import SvelteQueryDevtools from '../src/Devtools.svelte'
+import Wrapper from './Wrapper.svelte'
describe('SvelteQueryDevtools', () => {
it('should render the parent container without throwing in non-development environments', () => {
@@ -15,4 +16,24 @@ describe('SvelteQueryDevtools', () => {
container.querySelector('.tsqd-parent-container'),
).toBeInTheDocument()
})
+
+ it('should throw an error if no query client has been set', () => {
+ expect(() => render(SvelteQueryDevtools)).toThrow(
+ 'No QueryClient was found in Svelte context. Did you forget to wrap your component with QueryClientProvider?',
+ )
+ })
+
+ it('should not throw an error if query client is provided via context', () => {
+ const queryClient = new QueryClient()
+
+ expect(() => render(Wrapper, { props: { queryClient } })).not.toThrow()
+ })
+
+ it('should not throw an error if query client is provided via props', () => {
+ const queryClient = new QueryClient()
+
+ expect(() =>
+ render(SvelteQueryDevtools, { props: { client: queryClient } }),
+ ).not.toThrow()
+ })
})
diff --git a/packages/svelte-query-devtools/tests/Wrapper.svelte b/packages/svelte-query-devtools/tests/Wrapper.svelte
new file mode 100644
index 0000000000..35c5cf1517
--- /dev/null
+++ b/packages/svelte-query-devtools/tests/Wrapper.svelte
@@ -0,0 +1,15 @@
+
+
+
+
+