mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
fix(ui): verification-code iteration fix (#2917)
This commit is contained in:
parent
d6aeaf9b0e
commit
4130291359
4 changed files with 95 additions and 50 deletions
|
@ -30,6 +30,7 @@ const Toast = ({ message, duration = 3000, callback }: Props) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReactModal
|
<ReactModal
|
||||||
|
shouldFocusAfterRender={false}
|
||||||
// For styling use
|
// For styling use
|
||||||
// eslint-disable-next-line jsx-a11y/aria-role
|
// eslint-disable-next-line jsx-a11y/aria-role
|
||||||
role="toast"
|
role="toast"
|
||||||
|
|
|
@ -6,7 +6,7 @@ describe('VerificationCode Component', () => {
|
||||||
const onChange = jest.fn();
|
const onChange = jest.fn();
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
onChange.mockClear();
|
jest.clearAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('render with value', () => {
|
it('render with value', () => {
|
||||||
|
@ -80,9 +80,11 @@ describe('VerificationCode Component', () => {
|
||||||
const inputElements = container.querySelectorAll('input');
|
const inputElements = container.querySelectorAll('input');
|
||||||
|
|
||||||
if (inputElements[2]) {
|
if (inputElements[2]) {
|
||||||
fireEvent.input(inputElements[2], { target: { value: 'a' } });
|
for (const value of ['a', 'e', '+', '-', '.']) {
|
||||||
|
fireEvent.input(inputElements[2], { target: { value } });
|
||||||
expect(onChange).not.toBeCalled();
|
expect(onChange).not.toBeCalled();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('replace old value with new input char', () => {
|
it('replace old value with new input char', () => {
|
||||||
|
@ -124,14 +126,14 @@ describe('VerificationCode Component', () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('onPasteHandler', () => {
|
describe('onPasteHandler', () => {
|
||||||
|
it('full update', () => {
|
||||||
const input = ['1', '2', '3', '4', '5', '6'];
|
const input = ['1', '2', '3', '4', '5', '6'];
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
<VerificationCode name="passcode" value={input} onChange={onChange} />
|
<VerificationCode name="passcode" value={input} onChange={onChange} />
|
||||||
);
|
);
|
||||||
const inputElements = container.querySelectorAll('input');
|
const inputElements = container.querySelectorAll('input');
|
||||||
|
|
||||||
// Full update
|
|
||||||
if (inputElements[0]) {
|
if (inputElements[0]) {
|
||||||
fireEvent.paste(inputElements[0], {
|
fireEvent.paste(inputElements[0], {
|
||||||
clipboardData: {
|
clipboardData: {
|
||||||
|
@ -140,8 +142,15 @@ describe('VerificationCode Component', () => {
|
||||||
});
|
});
|
||||||
expect(onChange).toBeCalledWith(['7', '8', '9', '0', '1', '2']);
|
expect(onChange).toBeCalledWith(['7', '8', '9', '0', '1', '2']);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('partial update', () => {
|
||||||
|
const input = ['1', '2', '3', '4', '5', '6'];
|
||||||
|
const { container } = render(
|
||||||
|
<VerificationCode name="passcode" value={input} onChange={onChange} />
|
||||||
|
);
|
||||||
|
const inputElements = container.querySelectorAll('input');
|
||||||
|
|
||||||
// Partial update
|
|
||||||
if (inputElements[2]) {
|
if (inputElements[2]) {
|
||||||
fireEvent.paste(inputElements[2], {
|
fireEvent.paste(inputElements[2], {
|
||||||
clipboardData: {
|
clipboardData: {
|
||||||
|
@ -150,8 +159,15 @@ describe('VerificationCode Component', () => {
|
||||||
});
|
});
|
||||||
expect(onChange).toBeCalledWith(['1', '2', '7', '8', '9', '6']);
|
expect(onChange).toBeCalledWith(['1', '2', '7', '8', '9', '6']);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('overLength partial update', () => {
|
||||||
|
const input = ['1', '2', '3', '4', '5', '6'];
|
||||||
|
const { container } = render(
|
||||||
|
<VerificationCode name="passcode" value={input} onChange={onChange} />
|
||||||
|
);
|
||||||
|
const inputElements = container.querySelectorAll('input');
|
||||||
|
|
||||||
// OverLength update
|
|
||||||
if (inputElements[4]) {
|
if (inputElements[4]) {
|
||||||
fireEvent.paste(inputElements[4], {
|
fireEvent.paste(inputElements[4], {
|
||||||
clipboardData: {
|
clipboardData: {
|
||||||
|
@ -160,10 +176,32 @@ describe('VerificationCode Component', () => {
|
||||||
});
|
});
|
||||||
expect(onChange).toBeCalledWith(['1', '2', '3', '4', '7', '8']);
|
expect(onChange).toBeCalledWith(['1', '2', '3', '4', '7', '8']);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
onChange.mockClear();
|
it('filter numeric past data', () => {
|
||||||
|
const input = ['1', '2', '3', '4', '5', '6'];
|
||||||
|
const { container } = render(
|
||||||
|
<VerificationCode name="passcode" value={input} onChange={onChange} />
|
||||||
|
);
|
||||||
|
const inputElements = container.querySelectorAll('input');
|
||||||
|
|
||||||
|
if (inputElements[0]) {
|
||||||
|
fireEvent.paste(inputElements[0], {
|
||||||
|
clipboardData: {
|
||||||
|
getData: () => 'test input 124 343',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(onChange).toBeCalledWith(['1', '2', '4', '3', '4', '3']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Non-numeric past data', () => {
|
||||||
|
const input = ['1', '2', '3', '4', '5', '6'];
|
||||||
|
const { container } = render(
|
||||||
|
<VerificationCode name="passcode" value={input} onChange={onChange} />
|
||||||
|
);
|
||||||
|
const inputElements = container.querySelectorAll('input');
|
||||||
|
|
||||||
// Non-numeric past data
|
|
||||||
if (inputElements[0]) {
|
if (inputElements[0]) {
|
||||||
fireEvent.paste(inputElements[0], {
|
fireEvent.paste(inputElements[0], {
|
||||||
clipboardData: {
|
clipboardData: {
|
||||||
|
@ -173,4 +211,5 @@ describe('VerificationCode Component', () => {
|
||||||
expect(onChange).not.toBeCalled();
|
expect(onChange).not.toBeCalled();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -105,7 +105,7 @@ const VerificationCode = ({
|
||||||
clipboardData,
|
clipboardData,
|
||||||
} = event;
|
} = event;
|
||||||
|
|
||||||
const data = clipboardData.getData('text');
|
const data = clipboardData.getData('text').match(/\d/g)?.join('') ?? '';
|
||||||
|
|
||||||
// Unrecognized target input field
|
// Unrecognized target input field
|
||||||
if (!dataset.id) {
|
if (!dataset.id) {
|
||||||
|
@ -160,6 +160,10 @@ const VerificationCode = ({
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
nextTarget?.focus();
|
nextTarget?.focus();
|
||||||
break;
|
break;
|
||||||
|
case '+':
|
||||||
|
case '-':
|
||||||
|
case 'e':
|
||||||
|
case '.':
|
||||||
case 'ArrowUp':
|
case 'ArrowUp':
|
||||||
case 'ArrowDown':
|
case 'ArrowDown':
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
@ -175,7 +179,7 @@ const VerificationCode = ({
|
||||||
if (value.length === 0) {
|
if (value.length === 0) {
|
||||||
inputReferences.current[0]?.focus();
|
inputReferences.current[0]?.focus();
|
||||||
}
|
}
|
||||||
}, [value, onChange]);
|
}, [value]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
|
|
|
@ -71,9 +71,10 @@ const VerificationCode = ({ type, method, className, hasPasswordButton, target }
|
||||||
<TextLink
|
<TextLink
|
||||||
className={styles.link}
|
className={styles.link}
|
||||||
text="description.resend_passcode"
|
text="description.resend_passcode"
|
||||||
onClick={() => {
|
onClick={async () => {
|
||||||
clearErrorMessage();
|
clearErrorMessage();
|
||||||
void onResendVerificationCode();
|
await onResendVerificationCode();
|
||||||
|
setCode([]);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
Loading…
Reference in a new issue