| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- // @ts-nocheck
- import type { HotkeyRegistrationView, SequenceRegistrationView } from '@tanstack/react-hotkeys'
- import { screen } from '@testing-library/react'
- import userEvent from '@testing-library/user-event'
- import { beforeEach, describe, expect, it, vi } from 'vitest'
- import { ShortcutsReferenceSheet } from './ShortcutsReferenceSheet'
- import { SHORTCUT_DEFINITIONS, SHORTCUT_IDS, type ShortcutId } from '@/state/shortcuts/registry'
- import type { ShortcutHotkeyMeta } from '@/state/shortcuts/useShortcut'
- import { customRender } from '@/tests/lib/custom-render'
- const { mockUseHotkeyRegistrations } = vi.hoisted(() => ({
- mockUseHotkeyRegistrations:
- vi.fn<() => { hotkeys: HotkeyRegistrationView[]; sequences: SequenceRegistrationView[] }>(),
- }))
- vi.mock('@tanstack/react-hotkeys', async () => {
- const actual =
- await vi.importActual<typeof import('@tanstack/react-hotkeys')>('@tanstack/react-hotkeys')
- return {
- ...actual,
- useHotkeyRegistrations: mockUseHotkeyRegistrations,
- }
- })
- const ACTIVE_SHORTCUT_IDS = [
- SHORTCUT_IDS.COMMAND_MENU_OPEN,
- SHORTCUT_IDS.NAV_HOME,
- ] satisfies ShortcutId[]
- const ACTIVE_DATABASE_SHORTCUT_IDS = [
- ...ACTIVE_SHORTCUT_IDS,
- SHORTCUT_IDS.NAV_DATABASE_TABLES,
- ] satisfies ShortcutId[]
- const ACTIVE_AUTH_SHORTCUT_IDS = [
- ...ACTIVE_SHORTCUT_IDS,
- SHORTCUT_IDS.NAV_AUTH_USERS,
- ] satisfies ShortcutId[]
- const ACTIVE_FUNCTION_DETAIL_NAV_SHORTCUT_IDS = [
- ...ACTIVE_SHORTCUT_IDS,
- SHORTCUT_IDS.NAV_FUNCTION_DETAIL_OVERVIEW,
- ] satisfies ShortcutId[]
- const ACTIVE_REALTIME_NAV_SHORTCUT_IDS = [
- ...ACTIVE_SHORTCUT_IDS,
- SHORTCUT_IDS.NAV_REALTIME_INSPECTOR,
- ] satisfies ShortcutId[]
- const ACTIVE_REALTIME_INSPECTOR_SHORTCUT_IDS = [
- ...ACTIVE_SHORTCUT_IDS,
- SHORTCUT_IDS.INSPECTOR_JOIN_CHANNEL,
- SHORTCUT_IDS.INSPECTOR_TOGGLE_LISTENING,
- SHORTCUT_IDS.INSPECTOR_BROADCAST,
- SHORTCUT_IDS.INSPECTOR_COPY_MESSAGE,
- ] satisfies ShortcutId[]
- const ACTIVE_SURFACE_SHORTCUT_IDS = [
- ...ACTIVE_SHORTCUT_IDS,
- SHORTCUT_IDS.AUTH_USERS_REFRESH,
- SHORTCUT_IDS.FUNCTION_DETAIL_OPEN_TEST,
- SHORTCUT_IDS.FUNCTION_OVERVIEW_INTERVAL_15MIN,
- SHORTCUT_IDS.FUNCTIONS_LIST_REFRESH,
- SHORTCUT_IDS.LOGS_PREVIEW_REFRESH,
- SHORTCUT_IDS.SQL_EDITOR_FORMAT,
- SHORTCUT_IDS.STORAGE_BUCKETS_REFRESH,
- SHORTCUT_IDS.STORAGE_EXPLORER_REFRESH,
- ] satisfies ShortcutId[]
- let sequenceIdCounter = 0
- const buildSequenceRegistration = (id: ShortcutId): SequenceRegistrationView => {
- const definition = SHORTCUT_DEFINITIONS[id]
- const meta: ShortcutHotkeyMeta = {
- id: definition.id,
- name: definition.label,
- referenceGroup: definition.referenceGroup,
- }
- return {
- id: `sequence_${++sequenceIdCounter}`,
- sequence: definition.sequence,
- options: {
- enabled: true,
- meta,
- },
- target: document,
- triggerCount: 0,
- hasFired: false,
- matchedStepCount: 0,
- partialMatchLastKeyTime: 0,
- }
- }
- const seedRegistrations = (ids: ShortcutId[]) => {
- mockUseHotkeyRegistrations.mockReturnValue({
- hotkeys: [],
- sequences: ids.map(buildSequenceRegistration),
- })
- }
- const renderShortcutsReferenceSheet = (ids: ShortcutId[] = ACTIVE_SHORTCUT_IDS) => {
- seedRegistrations(ids)
- const onOpenChange = vi.fn()
- customRender(<ShortcutsReferenceSheet open onOpenChange={onOpenChange} />)
- return { onOpenChange }
- }
- describe('ShortcutsReferenceSheet', () => {
- beforeEach(() => {
- sequenceIdCounter = 0
- mockUseHotkeyRegistrations.mockReset()
- mockUseHotkeyRegistrations.mockReturnValue({ hotkeys: [], sequences: [] })
- })
- it('renders the grouped shortcut list by default', async () => {
- renderShortcutsReferenceSheet()
- expect(await screen.findByText('Keyboard shortcuts')).toBeInTheDocument()
- expect(screen.getByLabelText('Search shortcuts')).toBeInTheDocument()
- expect(screen.getByText('Command Menu')).toBeInTheDocument()
- expect(screen.getByText('Navigation')).toBeInTheDocument()
- expect(screen.queryByText('Global Navigation')).not.toBeInTheDocument()
- expect(screen.queryByText('Database Navigation')).not.toBeInTheDocument()
- expect(screen.getByText('Open command menu')).toBeInTheDocument()
- expect(screen.getByText('Go to Project Overview')).toBeInTheDocument()
- })
- it('shows only active shortcuts in a group when the group label matches the search', async () => {
- const user = userEvent.setup()
- renderShortcutsReferenceSheet()
- await user.type(screen.getByLabelText('Search shortcuts'), 'navigation')
- expect(screen.getByText('Navigation')).toBeInTheDocument()
- expect(screen.getByText('Go to Project Overview')).toBeInTheDocument()
- expect(screen.queryByText('Command Menu')).not.toBeInTheDocument()
- expect(screen.queryByText('Go to Database')).not.toBeInTheDocument()
- })
- it('keeps the parent group header when only an item label matches', async () => {
- const user = userEvent.setup()
- renderShortcutsReferenceSheet()
- await user.type(screen.getByLabelText('Search shortcuts'), 'Go to Project Overview')
- expect(screen.getByText('Navigation')).toBeInTheDocument()
- expect(screen.getByText('Go to Project Overview')).toBeInTheDocument()
- expect(screen.queryByText('Open command menu')).not.toBeInTheDocument()
- expect(screen.queryByText('Command Menu')).not.toBeInTheDocument()
- })
- it('shows the database navigation section when database shortcuts are active', async () => {
- renderShortcutsReferenceSheet(ACTIVE_DATABASE_SHORTCUT_IDS)
- expect(await screen.findByText('Global Navigation')).toBeInTheDocument()
- expect(screen.getByText('Database Navigation')).toBeInTheDocument()
- expect(screen.queryByText(/^Navigation$/)).not.toBeInTheDocument()
- expect(screen.getByText('Go to Tables')).toBeInTheDocument()
- })
- it('shows the auth navigation section when auth shortcuts are active', async () => {
- renderShortcutsReferenceSheet(ACTIVE_AUTH_SHORTCUT_IDS)
- expect(await screen.findByText('Global Navigation')).toBeInTheDocument()
- expect(screen.getByText('Auth Navigation')).toBeInTheDocument()
- expect(screen.queryByText(/^Navigation$/)).not.toBeInTheDocument()
- expect(screen.getByText('Go to Users')).toBeInTheDocument()
- })
- it('shows the edge function tabs section when function tab shortcuts are active', async () => {
- renderShortcutsReferenceSheet(ACTIVE_FUNCTION_DETAIL_NAV_SHORTCUT_IDS)
- expect(await screen.findByText('Global Navigation')).toBeInTheDocument()
- expect(screen.getByText('Edge Function Tabs')).toBeInTheDocument()
- expect(screen.queryByText('Edge Function Page Navigation')).not.toBeInTheDocument()
- expect(screen.getByText('Go to Overview')).toBeInTheDocument()
- })
- it('shows the realtime navigation section when realtime shortcuts are active', async () => {
- renderShortcutsReferenceSheet(ACTIVE_REALTIME_NAV_SHORTCUT_IDS)
- expect(await screen.findByText('Global Navigation')).toBeInTheDocument()
- expect(screen.getByText('Realtime Navigation')).toBeInTheDocument()
- expect(screen.getByText('Go to Inspector')).toBeInTheDocument()
- })
- it('uses human labels for realtime inspector shortcut groups', async () => {
- renderShortcutsReferenceSheet(ACTIVE_REALTIME_INSPECTOR_SHORTCUT_IDS)
- expect(await screen.findByText('Realtime Inspector')).toBeInTheDocument()
- expect(screen.getByText('Join a channel')).toBeInTheDocument()
- expect(screen.getByText('Start/Stop listening')).toBeInTheDocument()
- expect(screen.getByText('Broadcast a message')).toBeInTheDocument()
- expect(screen.getByText('Copy selected message')).toBeInTheDocument()
- expect(screen.queryByText('realtime-inspector')).not.toBeInTheDocument()
- })
- it('uses human labels for active surface shortcut groups', async () => {
- renderShortcutsReferenceSheet(ACTIVE_SURFACE_SHORTCUT_IDS)
- expect(await screen.findByText('Auth Users')).toBeInTheDocument()
- expect(screen.getByText('Edge Function Actions')).toBeInTheDocument()
- expect(screen.getByText('Edge Function Overview')).toBeInTheDocument()
- expect(screen.getByText('Edge Functions')).toBeInTheDocument()
- expect(screen.getByText('Logs Explorer')).toBeInTheDocument()
- expect(screen.getByText('SQL Editor')).toBeInTheDocument()
- expect(screen.getByText('Storage Buckets')).toBeInTheDocument()
- expect(screen.getByText('Storage File Explorer')).toBeInTheDocument()
- expect(screen.queryByText('auth-users')).not.toBeInTheDocument()
- expect(screen.queryByText('functions-detail')).not.toBeInTheDocument()
- expect(screen.queryByText('functions-list')).not.toBeInTheDocument()
- expect(screen.queryByText('functions-overview')).not.toBeInTheDocument()
- expect(screen.queryByText('logs-preview')).not.toBeInTheDocument()
- expect(screen.queryByText('sql-editor')).not.toBeInTheDocument()
- expect(screen.queryByText('storage-buckets')).not.toBeInTheDocument()
- expect(screen.queryByText('storage-explorer')).not.toBeInTheDocument()
- })
- it('does not show inactive database shortcuts in search results', async () => {
- const user = userEvent.setup()
- renderShortcutsReferenceSheet()
- await user.type(screen.getByLabelText('Search shortcuts'), 'Go to Tables')
- expect(screen.getByText('No matching shortcuts found')).toBeInTheDocument()
- expect(screen.queryByText('Database Navigation')).not.toBeInTheDocument()
- })
- it('hides shortcuts whose registration is soft-disabled', async () => {
- sequenceIdCounter = 0
- const enabled = buildSequenceRegistration(SHORTCUT_IDS.COMMAND_MENU_OPEN)
- const disabled = buildSequenceRegistration(SHORTCUT_IDS.NAV_HOME)
- disabled.options = { ...disabled.options, enabled: false }
- mockUseHotkeyRegistrations.mockReturnValue({
- hotkeys: [],
- sequences: [enabled, disabled],
- })
- customRender(<ShortcutsReferenceSheet open onOpenChange={vi.fn()} />)
- expect(await screen.findByText('Open command menu')).toBeInTheDocument()
- expect(screen.queryByText('Go to Project Overview')).not.toBeInTheDocument()
- })
- it('shows a clear button when searching and resets the list when clicked', async () => {
- const user = userEvent.setup()
- renderShortcutsReferenceSheet()
- await user.type(screen.getByLabelText('Search shortcuts'), 'navigation')
- expect(screen.getByRole('button', { name: 'Clear search' })).toBeInTheDocument()
- await user.click(screen.getByRole('button', { name: 'Clear search' }))
- expect(screen.getByLabelText('Search shortcuts')).toHaveValue('')
- expect(screen.getByText('Command Menu')).toBeInTheDocument()
- expect(screen.getByText('Navigation')).toBeInTheDocument()
- })
- it.each(['⌘Esc', 'Mod+/'])('does not search shortcut values like %s', async (query) => {
- const user = userEvent.setup()
- renderShortcutsReferenceSheet()
- await user.type(screen.getByLabelText('Search shortcuts'), query)
- expect(screen.getByText('No matching shortcuts found')).toBeInTheDocument()
- expect(screen.queryByText('Navigation')).not.toBeInTheDocument()
- })
- it('shows an empty state when nothing matches', async () => {
- const user = userEvent.setup()
- renderShortcutsReferenceSheet()
- await user.type(screen.getByLabelText('Search shortcuts'), 'totally missing')
- expect(screen.getByText('No matching shortcuts found')).toBeInTheDocument()
- })
- })
|