Skip to content
Open
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
43 changes: 43 additions & 0 deletions semcore/input-number/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,49 @@ describe('InputNumber', () => {
expect(spy).toBeCalledWith('40', expect.anything());
});

test.sequential('Verify typed value keeps decimal count equal to step precision', async () => {
const spy = vi.fn();
const { getByTestId } = render(
<InputNumber>
<InputNumber.Value data-testid='input-step-typed' value='' onChange={spy} step={0.01} />
</InputNumber>,
);

const input = getByTestId('input-step-typed') as HTMLInputElement;
await focusInput(input);
await userEvent.keyboard('0.10');

expect(spy).lastCalledWith('0.10', expect.anything());
expect(input.value).toBe('0.10');
});

test.sequential(
'Verify increment/decrement keeps decimal count equal to step precision',
async () => {
const spy = vi.fn();
const { getByTestId } = render(
<InputNumber>
<InputNumber.Value
data-testid='input-step-controls'
defaultValue='0.09'
onChange={spy}
step={0.01}
/>
<InputNumber.Controls data-testid='controls-step' />
</InputNumber>,
);
const controls = getByTestId('controls-step');

const arrowUp = controls.querySelectorAll('button')[0];
await userEvent.click(arrowUp);
expect(spy).lastCalledWith('0.10', expect.anything());

const arrowDown = controls.querySelectorAll('button')[1];
await userEvent.click(arrowDown);
expect(spy).lastCalledWith('0.09', expect.anything());
},
);

test.sequential('Verify not accept letters', async () => {
const spy = vi.fn();
const { getByTestId } = render(
Expand Down
18 changes: 17 additions & 1 deletion semcore/input-number/__tests__/input-number.browser-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ test.describe(`${TAG.FUNCTIONAL} `, () => {
}, async ({ page }) => {
await loadPage(page, 'stories/components/input-number/tests/examples/basic_example.tsx', 'en', item);

const [_, decimals] = item.step?.toString().split('.') ?? [];
const stepPrecision = decimals?.length ?? 0;

const controls = page.locator('[data-ui-name="InputNumber.Controls"]');

const minAttr = await locators.input(page).getAttribute('min');
Expand Down Expand Up @@ -194,8 +197,13 @@ test.describe(`${TAG.FUNCTIONAL} `, () => {
} else {
expectedValue = numericValue;
}

if (stepPrecision) {
expectedValue = expectedValue.toFixed(stepPrecision);
}

await page.locator('label').click();
await expect(locators.input(page)).toHaveValue((expectedValue).toLocaleString());
await expect(locators.input(page)).toHaveValue(expectedValue.toLocaleString());
await expect(locators.input(page)).toBeFocused();
});

Expand All @@ -218,6 +226,10 @@ test.describe(`${TAG.FUNCTIONAL} `, () => {
expectedValue = 0 - decrement;
}

if (stepPrecision) {
expectedValue = expectedValue.toFixed(stepPrecision);
}

await expect(locators.input(page)).toHaveValue(String(expectedValue));
await expect(locators.input(page)).toBeFocused();
});
Expand All @@ -236,6 +248,10 @@ test.describe(`${TAG.FUNCTIONAL} `, () => {
expectedValue = numericValue;
}

if (stepPrecision) {
expectedValue = expectedValue.toFixed(stepPrecision);
}

await page.locator('label').click();
await expect(locators.input(page)).toHaveValue(expectedValue.toLocaleString());
await expect(locators.input(page)).toBeFocused();
Expand Down
40 changes: 25 additions & 15 deletions semcore/input-number/src/InputNumber.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,17 +143,28 @@ class Value extends Component {
};
};

get stepPrecision() {
const { step } = this.asProps;
const [_, decimals] = step.toString().split('.');

return decimals?.length ?? 0;
}

getDisplayValue(value) {
return value === 0 ? value : value.toFixed(this.stepPrecision);
}

round(value, step) {
const countDecimals = Math.floor(step) === step ? 0 : step.toString().split('.')[1].length || 0;
return countDecimals === 0
? Number.parseFloat(value)
: Number.parseFloat(value).toPrecision(countDecimals);
const { stepPrecision } = this;

return stepPrecision === 0
? value
: Number.parseFloat(value).toPrecision(stepPrecision);
}

handleValidation = (event) => {
const { value, displayValue, min, max, step } = this.asProps;
const { parsedValue } = this.valueParser(event.currentTarget.value, value, displayValue);
const roundCoefficient = step < 1 ? step.toString().split('.')[1].length : 1;

if (Number.isNaN(value) || Number.isNaN(Number.parseFloat(parsedValue))) {
event.currentTarget.value = '';
Expand All @@ -168,9 +179,8 @@ class Value extends Component {
numberValue -= rounded;
}
}
const numberValueRounded = Number(numberValue.toFixed(roundCoefficient));

this.handlers.value(String(numberValueRounded), event);
this.handlers.value(this.getDisplayValue(numberValue), event);
}
};

Expand Down Expand Up @@ -423,11 +433,11 @@ class Value extends Component {
numberValue = Number.parseFloat(value);
}

if (!Number.isNaN(numberValue)) {
const newValue = numberValue + step <= max ? numberValue + step : max;
if (Number.isNaN(numberValue)) return;

this.handlers.value(newValue.toString(), event);
}
const nextValue = Math.min(numberValue + step, max);

this.handlers.value(this.getDisplayValue(nextValue), event);
};

stepDown = (event) => {
Expand All @@ -441,11 +451,11 @@ class Value extends Component {
numberValue = Number.parseFloat(value);
}

if (!Number.isNaN(numberValue)) {
const newValue = numberValue - step >= min ? numberValue - step : min;
if (Number.isNaN(numberValue)) return;

this.handlers.value(newValue.toString(), event);
}
const nextValue = Math.max(numberValue - step, min);

this.handlers.value(this.getDisplayValue(nextValue), event);
};

render() {
Expand Down
Loading