import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { Command } from 'cmdk'
import type { PropsWithChildren } from 'react'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { CommandPaletteSearchInput } from './CommandPaletteSearchInput'
const mockSetMode = vi.fn()
const wrapper = (props: PropsWithChildren) => (
{props.children}
)
afterEach(() => {
vi.clearAllMocks()
})
describe('in case input mode is "default"', () => {
describe('when the user pressed > key', () => {
it('should switch to "command" mode when value is empty', async () => {
const user = userEvent.setup()
render(
,
{ wrapper },
)
await user.keyboard('>')
expect(mockSetMode).toHaveBeenCalledWith({ type: 'command' })
})
it('should not switch input mode when value is not empty', async () => {
const user = userEvent.setup()
render(
,
{ wrapper },
)
// make the input not empty
await user.keyboard('hello')
await user.keyboard('>')
expect(mockSetMode).not.toHaveBeenCalled()
})
})
describe('when the user pressed Tab key', () => {
it('should switch to "table" mode and make the input empty when a table is suggested', async () => {
const user = userEvent.setup()
render(
,
{ wrapper },
)
const input = screen.getByRole('combobox')
// make the input not empty
await user.keyboard('user')
await user.keyboard('{Tab}')
expect(mockSetMode).toHaveBeenCalledWith({
type: 'table',
tableName: 'users',
})
expect(input).toHaveValue('')
})
it('should complete input value with suggested text but should not switch the input mode when suggestion is other than "table" option', async () => {
const user = userEvent.setup()
render(
,
{ wrapper },
)
const input = screen.getByRole('combobox')
await user.keyboard('{Tab}')
expect(mockSetMode).not.toHaveBeenCalled()
expect(input).toHaveValue('Copy Link')
})
})
})
describe('in case input mode is "command"', () => {
describe('when the user pressed Backspace key', () => {
it('should switch to "default" mode when value is empty', async () => {
const user = userEvent.setup()
render(
,
{ wrapper },
)
await user.keyboard('{backspace}')
expect(mockSetMode).toHaveBeenCalledWith({ type: 'default' })
})
it('should not switch input mode when value is not empty', async () => {
const user = userEvent.setup()
render(
,
{ wrapper },
)
// make the input not empty
await user.keyboard('hello')
await user.keyboard('{backspace}')
expect(mockSetMode).not.toHaveBeenCalled()
})
})
describe('when the user pressed Tab key', () => {
it('should complete input value with suggested text', async () => {
const user = userEvent.setup()
render(
,
{ wrapper },
)
const input = screen.getByRole('combobox')
await user.keyboard('{Tab}')
expect(mockSetMode).not.toHaveBeenCalled()
expect(input).toHaveValue('Copy Link')
})
})
})
describe('in case input mode is "table"', () => {
describe('when the user pressed Backspace key', () => {
it('should switch to "default" mode when value is empty', async () => {
const user = userEvent.setup()
render(
,
{ wrapper },
)
await user.keyboard('{backspace}')
expect(mockSetMode).toHaveBeenCalledWith({ type: 'default' })
})
it('should not switch input mode when value is not empty', async () => {
const user = userEvent.setup()
render(
,
{ wrapper },
)
// make the input not empty
await user.keyboard('hello')
await user.keyboard('{backspace}')
expect(mockSetMode).not.toHaveBeenCalled()
})
})
describe('when the user pressed Tab key', () => {
it('should complete input value with suggested text', async () => {
const user = userEvent.setup()
render(
,
{ wrapper },
)
const input = screen.getByRole('combobox')
await user.keyboard('{Tab}')
expect(mockSetMode).not.toHaveBeenCalled()
expect(input).toHaveValue('created_at')
})
it('should not complete input value when a table is suggested', async () => {
const user = userEvent.setup()
render(
,
{ wrapper },
)
const input = screen.getByRole('combobox')
await user.keyboard('{Tab}')
expect(mockSetMode).not.toHaveBeenCalled()
expect(input).toHaveValue('')
})
})
})
describe('displays a suggestion to complete the input', () => {
it('displays the remaining text when the input matches the beginning of a suggestion', async () => {
const user = userEvent.setup()
render(
,
{ wrapper },
)
await user.type(screen.getByRole('combobox'), 'user-s')
expect(
screen.getByTestId('command-palette-search-input-suggestion-suffix'),
).toHaveTextContent(/^ettings$/)
})
it('display the whole text when the input does not match the beginning of a suggestion', async () => {
const user = userEvent.setup()
render(
,
{ wrapper },
)
await user.type(screen.getByRole('combobox'), 'setting')
expect(
screen.getByTestId('command-palette-search-input-suggestion-suffix'),
).toHaveTextContent(/^- user-settings$/)
})
})