Browse Source

Update maskedtextinput tests

Ensure component has 100% test coverage.
master
TheoryOfNekomata 1 year ago
parent
commit
8f85959659
2 changed files with 117 additions and 15 deletions
  1. +100
    -3
      categories/web/freeform/react/src/components/MaskedTextInput/MaskedTextInput.test.tsx
  2. +17
    -12
      categories/web/freeform/react/src/components/MaskedTextInput/index.tsx

+ 100
- 3
categories/web/freeform/react/src/components/MaskedTextInput/MaskedTextInput.test.tsx View File

@@ -1,8 +1,9 @@
import * as React from 'react';
import {
cleanup,
render,
screen,
cleanup, fireEvent,
render,
screen,
act, waitFor,
} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { TextControl } from '@tesseract-design/web-base';
@@ -91,6 +92,102 @@ describe('MaskedTextInput', () => {
expect(indicator).toBeInTheDocument();
});

it('renders the indicator changing when switching visibility state', async () => {
render(
<MaskedTextInput
enhanced
/>,
);

const indicator = screen.getByTestId('indicator');

await userEvent.click(indicator);
expect(indicator).toHaveTextContent('Hide');

await userEvent.click(indicator);
expect(indicator).toHaveTextContent('Show');
});

it('renders the indicator changing when switching visibility state using function ref', async () => {
render(
<MaskedTextInput
enhanced
ref={vi.fn()}
/>,
);

const indicator = screen.getByTestId('indicator');

await userEvent.click(indicator);
expect(indicator).toHaveTextContent('Hide');

await userEvent.click(indicator);
expect(indicator).toHaveTextContent('Show');
});

it('highlights the indicator when visibility is toggled via keyboard', async () => {
render(
<MaskedTextInput
enhanced
/>,
);

const input = screen.getByTestId('input');
const indicator = screen.getByTestId('indicator');

input.focus();
fireEvent.keyDown(input, { code: 'Space', ctrlKey: true });
expect(indicator).toHaveClass('text-tertiary');

fireEvent.keyUp(input, { code: 'Space', ctrlKey: true });
expect(indicator).toHaveClass('text-primary');
});

it('handles keydown events', async () => {
const onKeyDown = vi.fn();
render(
<MaskedTextInput
enhanced
onKeyDown={onKeyDown}
/>,
);

const input = screen.getByTestId('input');

input.focus();
fireEvent.keyDown(input, { code: 'Space', ctrlKey: true });
expect(onKeyDown).toBeCalled();
});

it('handles keyup events', async () => {
const onKeyUp = vi.fn();
render(
<MaskedTextInput
enhanced
onKeyUp={onKeyUp}
/>,
);

const input = screen.getByTestId('input');

input.focus();
fireEvent.keyUp(input, { code: 'Space', ctrlKey: true });
expect(onKeyUp).toBeCalled();
});

it('accepts a function ref', () => {
const ref = vi.fn();

render(
<MaskedTextInput
enhanced
ref={ref}
/>,
);

expect(ref).toBeCalled();
});

describe.each`
size | inputClassName | hintClassName | indicatorClassName
${'small'} | ${'h-10'} | ${'pr-10'} | ${'w-10'}


+ 17
- 12
categories/web/freeform/react/src/components/MaskedTextInput/index.tsx View File

@@ -12,6 +12,10 @@ export type MaskedTextInputDerivedElement = HTMLElementTagNameMap[
typeof MaskedTextInputDerivedElementComponent
];

type SelectionDirection = 'none' | 'forward' | 'backward';

const AVAILABLE_AUTO_COMPLETE_VALUES = ['current-password', 'new-password'] as const;

/**
* Props of the {@link MaskedTextInput} component.
*/
@@ -55,7 +59,7 @@ export interface MaskedTextInputProps extends Omit<React.HTMLProps<MaskedTextInp
/**
* Autocomplete value type of the component.
*/
autoComplete?: 'current-password' | 'new-password',
autoComplete?: typeof AVAILABLE_AUTO_COMPLETE_VALUES[number],
}

/**
@@ -114,19 +118,16 @@ export const MaskedTextInput = React.forwardRef<
}, [onKeyUp]);

const handleToggleVisible = React.useCallback(() => {
const { current } = typeof ref === 'object' ? ref : defaultRef;
let selectionStart = 0;
let selectionEnd = 0;
let selectionDirection: 'none' | 'forward' | 'backward' | undefined = 'none' as const;
if (current) {
selectionStart = current.selectionStart ?? 0;
selectionEnd = current.selectionEnd ?? 0;
selectionDirection = current.selectionDirection ?? 'none' as const;
}
const effectiveRef = typeof ref === 'object' ? ref : defaultRef;
const current = effectiveRef.current as MaskedTextInputDerivedElement;
const selectionStart = current.selectionStart as number;
const selectionEnd = current.selectionEnd as number;
const selectionDirection = current.selectionDirection as SelectionDirection;

setVisible((prev) => !prev);
setTimeout(() => {
current?.focus();
current?.setSelectionRange(selectionStart, selectionEnd, selectionDirection);
current.focus();
current.setSelectionRange(selectionStart, selectionEnd, selectionDirection);
});
}, [ref, defaultRef]);

@@ -288,7 +289,11 @@ export const MaskedTextInput = React.forwardRef<
},
)}
onClick={handleToggleVisible}
title={visible ? 'Hide' : 'Show'}
>
<span className="sr-only">
{visible ? 'Hide' : 'Show'}
</span>
<svg
className="w-6 h-6 fill-none stroke-current stroke-2 linejoin-round linecap-round"
viewBox="0 0 24 24"


Loading…
Cancel
Save