Files
supabase/apps/studio/tests/lib/custom-render.tsx
T
Charis 4d793a708e test(sql-editor): shared renderHook harness with in-memory editor port (#48209)
## Summary

- Add `renderSqlEditorHook()` test harness that eliminates mocking
Monaco by injecting a real, deterministic in-memory editor port
(EditorController/DiffController backed by plain JS state)
- Include `createInMemoryEditor()`, `resetSqlEditorStores()`, and
`setupSqlEditorMocks()` utilities to provide isolation and mock-free
network testing via MSW handlers
- Export `CustomWrapper` from custom-render and add optional
`editor`/`diff` injection points to SQLEditorProvider (production
unaffected via null-coalesce fallback)

This is **Step 3** of an in-progress SQL editor testability refactor
(Step 2 finished EditorController/DiffController port; this harness has
no consumers yet — hook tests land in a follow-up step).

## Test plan

- [x] `pnpm --filter studio typecheck` passes (already verified)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Tests**
* Added reusable SQL Editor test utilities for in-memory editing,
selections, error highlighting, snippets, and diff content.
* Added helpers for resetting editor state, configuring API mocks, and
rendering SQL Editor hooks in a complete test environment.
* Enabled SQL Editor providers to accept optional controller overrides
for isolated testing.
  * Exported the shared test wrapper for reuse across test suites.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-22 13:32:55 -04:00

81 lines
2.1 KiB
TypeScript

import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { render, renderHook, type RenderOptions } from '@testing-library/react'
import { NuqsTestingAdapter } from 'nuqs/adapters/testing'
import { TooltipProvider } from 'ui'
import { CommandProvider } from 'ui-patterns/CommandMenu'
// End of third-party imports
import { ProfileContext, type ProfileContextType } from '@/lib/profile'
type AdapterProps = Partial<Parameters<typeof NuqsTestingAdapter>[0]>
export const CustomWrapper = ({
children,
queryClient,
nuqs,
profileContext,
}: {
children: React.ReactNode
queryClient?: QueryClient
nuqs?: AdapterProps
profileContext?: ProfileContextType
}) => {
const _queryClient =
queryClient ??
new QueryClient({
defaultOptions: {
queries: { retry: false },
mutations: { retry: false },
},
})
const content = (
<QueryClientProvider client={_queryClient}>
<NuqsTestingAdapter {...nuqs}>
<TooltipProvider>
<CommandProvider openKey="">{children}</CommandProvider>
</TooltipProvider>
</NuqsTestingAdapter>
</QueryClientProvider>
)
return profileContext ? (
<ProfileContext.Provider value={profileContext}>{content}</ProfileContext.Provider>
) : (
content
)
}
type CustomRenderOpts = RenderOptions & {
queryClient?: QueryClient
nuqs?: AdapterProps
profileContext?: ProfileContextType
}
export const customRender = (component: React.ReactElement, renderOptions?: CustomRenderOpts) => {
return render(component, {
wrapper: ({ children }) =>
CustomWrapper({
queryClient: renderOptions?.queryClient,
nuqs: renderOptions?.nuqs,
profileContext: renderOptions?.profileContext,
children,
}),
...renderOptions,
})
}
export const customRenderHook = (hook: () => any, renderOptions?: CustomRenderOpts) => {
return renderHook(hook, {
wrapper: ({ children }) =>
CustomWrapper({
children,
queryClient: renderOptions?.queryClient,
nuqs: renderOptions?.nuqs,
profileContext: renderOptions?.profileContext,
}),
...renderOptions,
})
}