Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: use button tag and native tabindex for clear button #63

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion assets/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@
}

&-clear-icon {
padding: 0;
font-size: 12px;
cursor: pointer;
background: none;
border: none;

&-hidden {
display: none;
Expand Down
6 changes: 2 additions & 4 deletions src/BaseInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ const BaseInput = React.forwardRef<HolderRef, BaseInputProps>((props, ref) => {
: '✖';

clearIcon = (
<span
<button
onClick={(event) => {
handleReset?.(event);
onClear?.();
Expand All @@ -92,11 +92,9 @@ const BaseInput = React.forwardRef<HolderRef, BaseInputProps>((props, ref) => {
[`${clearIconCls}-hidden`]: !needClear,
[`${clearIconCls}-has-suffix`]: !!suffix,
})}
role="button"
tabIndex={-1}
>
{iconNode}
</span>
</button>
);
}

Expand Down
63 changes: 48 additions & 15 deletions tests/BaseInput.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { fireEvent, render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import type { ChangeEvent, FC } from 'react';
import React, { useState } from 'react';
import BaseInput, { type HolderRef } from '../src/BaseInput';
Expand Down Expand Up @@ -45,11 +46,13 @@ describe('BaseInput', () => {
expect(container).toMatchSnapshot();
});

it('allowClear should work', () => {
describe('allowClear should work', () => {
const onChange = jest.fn();
const onBlur = jest.fn();
const onFocus = jest.fn();

const user = userEvent.setup();

const Demo: FC = () => {
const [value, setValue] = useState<string>('');

Expand All @@ -74,23 +77,53 @@ describe('BaseInput', () => {
);
};

const { container } = render(<Demo />);
it('By click', () => {
const { container } = render(<Demo />);

const inputEl = container.querySelector('input');
fireEvent.focus(inputEl!);
expect(onFocus).toHaveBeenCalledTimes(1);
const inputEl = container.querySelector('input');
fireEvent.focus(inputEl!);
expect(onFocus).toHaveBeenCalledTimes(1);

fireEvent.change(inputEl!, { target: { value: 'some text' } });
expect(onChange).toHaveBeenCalledTimes(1);
expect(inputEl!.value).toBe('some text');
fireEvent.change(inputEl!, { target: { value: 'some text' } });
expect(onChange).toHaveBeenCalledTimes(1);
expect(inputEl!.value).toBe('some text');

const clearIcon = container.querySelector('.rc-input-clear-icon');
fireEvent.mouseDown(clearIcon!);
fireEvent.click(clearIcon!);
fireEvent.mouseUp(clearIcon!);
expect(onBlur).not.toHaveBeenCalled();
expect(onChange).toHaveBeenCalledTimes(1);
expect(inputEl!.value).toBe('');
const clearIcon = container.querySelector('.rc-input-clear-icon');
fireEvent.mouseDown(clearIcon!);
fireEvent.click(clearIcon!);
fireEvent.mouseUp(clearIcon!);
expect(onBlur).not.toHaveBeenCalled();
expect(onChange).toHaveBeenCalledTimes(1);
expect(inputEl!.value).toBe('');
});

it('By focus and Space', async () => {
const { container } = render(<Demo />);

const inputEl = container.querySelector('input');
await user.click(inputEl!);

await user.type(inputEl!, 'some text');
expect(inputEl!.value).toBe('some text');

await user.tab();
await user.keyboard('[Space]');
expect(inputEl!.value).toBe('');
});

it('By focus and Enter', async () => {
const { container } = render(<Demo />);

const inputEl = container.querySelector('input');
await user.click(inputEl!);

await user.type(inputEl!, 'some text');
expect(inputEl!.value).toBe('some text');

await user.tab();
await user.keyboard('[Enter]');
expect(inputEl!.value).toBe('');
});
});

it('should display clearIcon correctly', () => {
Expand Down
36 changes: 12 additions & 24 deletions tests/__snapshots__/index.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,11 @@ exports[`Input allowClear should change type when click 1`] = `
<span
class="rc-input-suffix"
>
<span
<button
class="rc-input-clear-icon"
role="button"
tabindex="-1"
>
</span>
</button>
</span>
</span>
</div>
Expand All @@ -140,13 +138,11 @@ exports[`Input allowClear should change type when click 2`] = `
<span
class="rc-input-suffix"
>
<span
<button
class="rc-input-clear-icon rc-input-clear-icon-hidden"
role="button"
tabindex="-1"
>
</span>
</button>
</span>
</span>
</div>
Expand All @@ -165,13 +161,11 @@ exports[`Input allowClear should not show icon if defaultValue is undefined or e
<span
class="rc-input-suffix"
>
<span
<button
class="rc-input-clear-icon rc-input-clear-icon-hidden"
role="button"
tabindex="-1"
>
</span>
</button>
</span>
</span>
</div>
Expand All @@ -190,13 +184,11 @@ exports[`Input allowClear should not show icon if defaultValue is undefined or e
<span
class="rc-input-suffix"
>
<span
<button
class="rc-input-clear-icon rc-input-clear-icon-hidden"
role="button"
tabindex="-1"
>
</span>
</button>
</span>
</span>
</div>
Expand All @@ -215,13 +207,11 @@ exports[`Input allowClear should not show icon if value is undefined or empty st
<span
class="rc-input-suffix"
>
<span
<button
class="rc-input-clear-icon rc-input-clear-icon-hidden"
role="button"
tabindex="-1"
>
</span>
</button>
</span>
</span>
</div>
Expand All @@ -240,13 +230,11 @@ exports[`Input allowClear should not show icon if value is undefined or empty st
<span
class="rc-input-suffix"
>
<span
<button
class="rc-input-clear-icon rc-input-clear-icon-hidden"
role="button"
tabindex="-1"
>
</span>
</button>
</span>
</span>
</div>
Expand Down