import React from 'react'
import { render } from '../utils/test-utils'
import type { GridEditorInputNumericProps } from './input-numeric'
import { GridEditorInputNumeric } from './input-numeric'
import userEvent from '@testing-library/user-event'

const baseProps = {
    rowId: '1',
    mode: 'editing' as GridEditorInputNumericProps<any>['mode'],
    tabIndex: 0,
    label: '',
    value: '123',
    columnId: 'name',
}

describe('GridEditorInputNumeric', () => {
    let onConfirm: jest.Mock
    let onCancel: jest.Mock

    beforeEach(() => {
        onConfirm = jest.fn()
        onCancel = jest.fn()
    })

    function renderInput(
        props: Partial<GridEditorInputNumericProps<any>> = {}
    ) {
        return render(
            <GridEditorInputNumeric
                {...baseProps}
                onCancel={onCancel}
                onConfirm={onConfirm}
                {...props}
            />
        )
    }

    it('should render', () => {
        const { queryByRole } = renderInput()
        expect(queryByRole('textbox')).toBeInTheDocument()
    })

    it('should support editing (commit with Tab)', async () => {
        renderInput()

        await userEvent.keyboard('{Tab}234{Tab}')

        expect(onConfirm).toHaveBeenCalledWith('234', {
            continueEditing: 'next',
        })
    })

    it('should support editing (commit with Shift+Tab)', async () => {
        renderInput()

        await userEvent.keyboard('{Tab}234{Shift>}{Tab}{/Shift}')

        expect(onConfirm).toHaveBeenCalledWith('234', {
            continueEditing: 'previous',
        })
    })

    it('should support editing (commit with Enter)', async () => {
        renderInput()

        await userEvent.keyboard('{Tab}234{Enter}')

        expect(onConfirm).toHaveBeenCalledWith('234')
    })

    it('should support cancelling an edit with Esc', async () => {
        renderInput()

        await userEvent.keyboard('{Tab}234{Escape}')

        expect(onConfirm).not.toHaveBeenCalled()
        expect(onCancel).toHaveBeenCalled()
    })

    it('should support controlled rendering', async () => {
        const Wrapper = () => {
            const [value, setValue] = React.useState('')

            return (
                <GridEditorInputNumeric
                    {...baseProps}
                    value={value}
                    controlled
                    onChange={(val) =>
                        setValue(val.substring(0, 1).toLowerCase())
                    }
                    onCancel={onCancel}
                    onConfirm={onConfirm}
                />
            )
        }

        render(<Wrapper />)

        await userEvent.keyboard('{Tab}234{Tab}')

        expect(onConfirm).toHaveBeenCalledWith('2', {
            continueEditing: 'next',
        })
    })
})
