Files
supabase/apps/studio/components/interfaces/Explorer/ExplorerQuerySourceMenu.test.tsx
T
Joshen Lim d61477085e Joshenlim/fe 4175 add row limit in explorerquerysourcemenu (#49098)
## Context

Related to Explorer/Notebook - builds on the ExplorerQuerySourceMenu by
adding an option for row limit in both Notebook Query cell + Query Tab

## Side note RE persistence of the selected row limit value
Note that for QueryTab - its intentional that for now that the row limit
isn't scoped to the query draft atm as I wanna avoid making changes to
`explorer-query` atm as there's a couple of PRs in flux that touches
that file. So will handle that separately

^ This means that switching between query tabs will not change nor
persist the row limit

<img width="931" height="335" alt="image"
src="https://github.com/user-attachments/assets/d1d52ee7-7c1d-42aa-a6ae-1d7d99ab95c9"
/>

<img width="1381" height="486" alt="image"
src="https://github.com/user-attachments/assets/689368c9-c0fc-4000-a09e-f59bfa7afa97"
/>

## To test
- [ ] Verify that row limit behaviour works in notebooks
- [ ] Verify that row limit behaviour works in explorer query tab
2026-08-17 13:36:31 +08:00

125 lines
3.9 KiB
TypeScript

import { screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { FeatureFlagContext } from 'common'
import { mockAnimationsApi } from 'jsdom-testing-mocks'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { ExplorerQuerySourceMenu } from './ExplorerQuerySourceMenu'
import { customRender } from '@/tests/lib/custom-render'
import { addAPIMock } from '@/tests/lib/msw'
mockAnimationsApi()
beforeEach(() => {
addAPIMock({
method: 'get',
path: '/platform/projects/:ref',
response: {
id: 1,
ref: 'default',
organization_id: 1,
name: 'Test Project',
status: 'ACTIVE_HEALTHY',
cloud_provider: 'AWS',
region: 'us-east-1',
db_host: 'db.default.supabase.co',
restUrl: 'https://default.supabase.co/rest/v1/',
inserted_at: '2024-01-01T00:00:00Z',
updated_at: '2024-01-01T00:00:00Z',
subscription_id: 'sub_123',
is_branch_enabled: false,
is_physical_backups_enabled: false,
high_availability: false,
integration_source: null,
connectionString: 'postgresql://postgres@localhost:5432/postgres',
is_hibernating: false,
},
})
})
describe('ExplorerQuerySourceMenu', () => {
const renderWithFlags = (
source: Parameters<typeof ExplorerQuerySourceMenu>[0]['source'],
flags: Record<string, boolean>
) =>
customRender(
<FeatureFlagContext.Provider value={{ configcat: flags, posthog: {}, hasLoaded: true }}>
<ExplorerQuerySourceMenu
rowLimit={100}
onRowLimitChange={vi.fn()}
source={source}
onSourceChange={vi.fn()}
/>
</FeatureFlagContext.Provider>
)
it('emits a complete default binding when the query changes source', async () => {
const onSourceChange = vi.fn()
customRender(
<ExplorerQuerySourceMenu
rowLimit={100}
onRowLimitChange={vi.fn()}
source={{
_tag: 'logs',
time_range: { _tag: 'relative_time_range', amount: 1, unit: 'hour' },
}}
onSourceChange={onSourceChange}
/>
)
await userEvent.click(screen.getByRole('button', { name: 'Query source: Logs' }))
await userEvent.click(screen.getByText('Database'))
expect(onSourceChange).toHaveBeenCalledWith({ _tag: 'database' })
})
it('emits the selected log time range as source parameters', async () => {
const onSourceChange = vi.fn()
customRender(
<ExplorerQuerySourceMenu
rowLimit={100}
onRowLimitChange={vi.fn()}
source={{
_tag: 'logs',
time_range: { _tag: 'relative_time_range', amount: 1, unit: 'hour' },
}}
onSourceChange={onSourceChange}
/>
)
await userEvent.click(screen.getByRole('button', { name: 'Query source: Logs' }))
await userEvent.hover(screen.getByText('Time range'))
await userEvent.click(await screen.findByText('Last 3 hours'))
expect(onSourceChange).toHaveBeenCalledWith({
_tag: 'logs',
time_range: { _tag: 'relative_time_range', amount: 3, unit: 'hour' },
})
})
it('does not offer logs when source flags are disabled for a database query', async () => {
renderWithFlags({ _tag: 'database' }, { sqlEditorLogsSource: false, otelLegacyLogs: false })
await userEvent.click(screen.getByRole('button', { name: 'Query source: Database' }))
expect(screen.queryByText('Logs')).not.toBeInTheDocument()
})
it('keeps logs available when an existing query already uses it', async () => {
renderWithFlags(
{
_tag: 'logs',
time_range: { _tag: 'relative_time_range', amount: 1, unit: 'hour' },
},
{ sqlEditorLogsSource: false, otelLegacyLogs: false }
)
await userEvent.click(screen.getByRole('button', { name: 'Query source: Logs' }))
expect(screen.getAllByText('Logs')).toHaveLength(2)
expect(screen.getByText('Database')).toBeInTheDocument()
})
})