Files
supabase/apps/studio/tests/helpers.tsx
Gildas GarciaandAlaister Young 737b8595f2 Update API types (#50234)
## Problem

platform, v1 and v2 have been already completely migrated and introduced
some changes.

Some types have been renamed, some outputs and inputs updated.

## Solution

- Update the API types
- Fix the TS errors

## Update

Taking this over to unblock #50134, which needs the new scoped token
permission ids from the regenerated types.

- Merged `master`.
- Regenerated `api-v2.d.ts` from the production spec. The previous files
came from a local API that exposed a webhook events endpoint production
doesn't have yet. Production has since added standardized 400 error
responses on the v2 organization endpoints. `api-v1.d.ts` and
`platform.d.ts` already matched production.
- Fixed `verify-production-types`. It formatted the regenerated files in
a temp directory outside the repository, so Prettier fell back to its
defaults and the comparison could never match the committed files. It
now passes the repository config explicitly. `pnpm api:verify-types`
passes on this branch.
- Verified locally: `pnpm typecheck`, `pnpm api:verify-types`, Studio
unit tests.

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

* **Bug Fixes**
* Preserved descriptions when saving, sharing, moving, or unsharing
notebooks, reports, SQL snippets, and saved queries.
* Improved handling of empty or null values across notebook
descriptions, billing usage, pooler settings, and infrastructure fields.
* Improved read-replica connection handling, including read-only
connection strings.
* Updated storage configuration and capability handling to match current
settings.

* **API and Compatibility**
* Updated organization, project, storage, OAuth, billing, and
infrastructure data handling to match current API responses.
  * OAuth app creation and updates now require scopes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-09-11 12:17:49 +08:00

162 lines
4.6 KiB
TypeScript

import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { fireEvent, getByText, render as originalRender, screen } from '@testing-library/react'
import { platformComponents as components } from 'api-types'
import type React from 'react'
import { useState } from 'react'
import { TooltipProvider } from 'ui'
import { CommandProvider } from 'ui-patterns/CommandMenu'
import { ProjectInfoInfinite } from '@/data/projects/projects-infinite-query'
import type { Organization } from '@/types'
type OrganizationResponse = components['schemas']['OrganizationResponse_Output']
interface SelectorOptions {
container?: HTMLElement
}
/**
* Returns the toggle button given a text matcher
*
* Defaults to screen if container option is not provided
*/
export const getToggleByText = (
text: string | RegExp,
options: SelectorOptions = {}
): HTMLElement | null => {
const container = options?.container
let textNode
if (container) {
textNode = getByText(container as HTMLElement, text)
} else {
textNode = screen.getByText(text)
}
if (textNode && textNode.parentElement) {
return textNode.parentElement.querySelector('button')
} else {
return textNode
}
}
export const clickDropdown = (elem: HTMLElement) => {
fireEvent.pointerDown(
elem,
new window.PointerEvent('pointerdown', {
ctrlKey: false,
button: 0,
})
)
}
export const createMockOrganization = (details: Partial<Organization>): Organization => {
const base: Organization = {
id: 1,
name: 'Organization 1',
slug: 'abcdefghijklmnopqrst',
plan: { id: 'free', name: 'Free' },
managed_by: 'supabase',
is_owner: true,
billing_email: 'billing@example.com',
billing_partner: null,
integration_source: null,
usage_billing_enabled: false,
stripe_customer_id: 'stripe-1',
subscription_id: 'subscription-1',
organization_requires_mfa: false,
opt_in_tags: [],
restriction_status: null,
requires_indirect_tax_declaration: false,
restriction_data: null,
organization_missing_address: false,
organization_missing_tax_id: false,
}
return Object.assign(base, details)
}
/**
* Returns the raw OpenAPI `OrganizationResponse` shape — without the
* frontend-derived fields (`managed_by`, `partner_id`) that
* `castOrganizationResponseToOrganization` attaches in the query layer.
*
* Use this for MSW mocks at the network boundary (e.g. `/platform/organizations`).
* Use `createMockOrganization` for in-app fixtures that need the cast shape.
*/
export const createMockOrganizationResponse = (
details: Partial<OrganizationResponse> = {}
): OrganizationResponse => {
const base: OrganizationResponse = {
id: 1,
name: 'Organization 1',
slug: 'abcdefghijklmnopqrst',
plan: { id: 'free', name: 'Free' },
is_owner: true,
billing_email: 'billing@example.com',
billing_partner: null,
integration_source: null,
usage_billing_enabled: false,
stripe_customer_id: 'stripe-1',
subscription_id: 'subscription-1',
organization_requires_mfa: false,
opt_in_tags: [],
restriction_status: null,
requires_indirect_tax_declaration: false,
restriction_data: null,
organization_missing_address: false,
organization_missing_tax_id: false,
}
return Object.assign(base, details)
}
export const createMockProject = (details: Partial<ProjectInfoInfinite>): ProjectInfoInfinite => {
const base: ProjectInfoInfinite = {
id: 1,
ref: 'abcdefghijklmnopqrst',
name: 'Project 1',
status: 'ACTIVE_HEALTHY',
organization_id: 1,
cloud_provider: 'AWS',
region: 'us-east-1',
inserted_at: new Date().toISOString(),
subscription_id: 'subscription-1',
is_branch_enabled: false,
is_physical_backups_enabled: false,
organization_slug: 'slug',
preview_branch_refs: [],
}
return Object.assign(base, details)
}
/**
* A custom render function for react testing library
* https://testing-library.com/docs/react-testing-library/setup/#custom-render
*/
const ReactQueryTestConfig: React.FC<React.PropsWithChildren> = ({ children }) => {
const [queryClient] = useState(
() =>
new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
})
)
return (
<TooltipProvider>
<QueryClientProvider client={queryClient}>
<CommandProvider openKey="">{children}</CommandProvider>
</QueryClientProvider>
</TooltipProvider>
)
}
type renderParams = Parameters<typeof originalRender>
export const render = ((ui: renderParams[0], options: renderParams[1]) =>
originalRender(ui, {
wrapper: ReactQueryTestConfig,
...options,
})) as typeof originalRender