Skip to content

Commit

Permalink
fix: onValueChange not called for values with 3 or less characters
Browse files Browse the repository at this point in the history
  • Loading branch information
rfviolato committed May 17, 2024
1 parent 5edf305 commit c866092
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 27 deletions.
7 changes: 2 additions & 5 deletions src/number_format_base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -191,17 +191,14 @@ export default function NumberFormatBase<BaseType = InputAttributes>(

/**
* if the formatted value is not synced to parent, or if the formatted value is different from last synced value sync it
* we also don't need to sync to the parent if no formatting is applied
* if the formatting props is removed, in which case last formatted value will be different from the numeric string value
* in such case we need to inform the parent.
*/
useEffect(() => {
const { formattedValue: lastFormattedValue, numAsString: lastNumAsString } =
lastUpdatedValue.current;
if (
formattedValue !== lastFormattedValue &&
(formattedValue !== numAsString || lastFormattedValue !== lastNumAsString)
) {

if (formattedValue !== lastFormattedValue || numAsString !== lastNumAsString) {
_onValueChange(getValueObject(formattedValue, numAsString), {
event: undefined,
source: SourceType.props,
Expand Down
88 changes: 66 additions & 22 deletions test/library/input.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -439,27 +439,6 @@ describe('NumberFormat as input', () => {
});
});

it('should not call onValueChange if no formatting is applied', async () => {
const mockOnValueChange = vi.fn();

const { rerender } = await render(<NumericFormat value="" onValueChange={mockOnValueChange} />);

expect(mockOnValueChange).not.toHaveBeenCalled();

rerender(<NumericFormat value={NaN} onValueChange={mockOnValueChange} />);
expect(mockOnValueChange).not.toHaveBeenCalled();

rerender(<NumericFormat value={1234} onValueChange={mockOnValueChange} />);
expect(mockOnValueChange).not.toHaveBeenCalled();

rerender(<NumericFormat value={1234} onValueChange={mockOnValueChange} thousandSeparator />);
expect(mockOnValueChange.mock.lastCall[0]).toEqual({
formattedValue: '1,234',
value: '1234',
floatValue: 1234,
});
});

it('should always call setState when input is not on focus and value formatting is changed from outside', async () => {
const { input, user, rerender } = await render(
<NumericFormat value="1.1" valueIsNumericString />,
Expand Down Expand Up @@ -526,7 +505,7 @@ describe('NumberFormat as input', () => {
expect(source).toEqual('event');
});

it('should call onValueChange when value changes', async () => {
it('should call onValueChange when value changes via user input', async () => {
const mockOnValueChange = vi.fn();

const { input, user, rerender } = await render(
Expand All @@ -545,8 +524,73 @@ describe('NumberFormat as input', () => {
);
expect(mockOnValueChange).toHaveBeenCalled();

mockOnValueChange.mockReset();

await simulateKeyInput(user, input, '5', 0);
expect(input).toHaveValue('51,234');
expect(mockOnValueChange).toHaveBeenCalled();

await simulateKeyInput(user, input, '{Backspace}', 6);
expect(input).toHaveValue('5,123');
expect(mockOnValueChange).toHaveBeenCalled();

mockOnValueChange.mockReset();

await simulateKeyInput(user, input, '{Backspace}', 5);
expect(input).toHaveValue('512');
expect(mockOnValueChange).toHaveBeenCalled();

mockOnValueChange.mockReset();

await simulateKeyInput(user, input, '{Backspace}', 4);
expect(input).toHaveValue('51');
expect(mockOnValueChange).toHaveBeenCalled();
});

it('should call onValueChange when value changes via props', async () => {
const mockOnValueChange = vi.fn();

const { input, rerender } = await render(
<NumericFormat value="1234" valueIsNumericString={true} onValueChange={mockOnValueChange} />,
);

expect(input).toHaveValue('1234');

rerender(
<NumericFormat
onValueChange={mockOnValueChange}
thousandSeparator
value="1234"
valueIsNumericString={true}
/>,
);
expect(mockOnValueChange).toHaveBeenCalled();

mockOnValueChange.mockReset();

rerender(
<NumericFormat
onValueChange={mockOnValueChange}
thousandSeparator
value="123"
valueIsNumericString={true}
/>,
);
expect(mockOnValueChange).toHaveBeenCalled();

mockOnValueChange.mockReset();

rerender(
<NumericFormat
onValueChange={mockOnValueChange}
thousandSeparator
value="12"
valueIsNumericString={true}
/>,
);
expect(mockOnValueChange).toHaveBeenCalled();

console.log({ input });
});

it('should treat Infinity value as empty string', async () => {
Expand Down

0 comments on commit c866092

Please sign in to comment.