Skip to content
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
8 changes: 4 additions & 4 deletions assets/build/example.min.js

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions assets/build/index.min.js

Large diffs are not rendered by default.

18 changes: 11 additions & 7 deletions assets/src/components/field/number/Number.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
import {
useRef,
useMemo,
useState,
useEffect
} from 'react'
Expand All @@ -22,7 +23,10 @@ const NumberComponent = props => {

const { locale } = useLocale()
const [value, setValue] = useState(props.value ?? '')
const state = useNumberFieldState({ ...props, locale })

const defaultFormatOptions = useMemo(() => ({ maximumFractionDigits: 10, useGrouping: false }), [])
const formatOptions = props.formatOptions ?? defaultFormatOptions
const state = useNumberFieldState({ ...props, formatOptions, locale })
const inputRef = useRef()

const {
Expand All @@ -32,7 +36,7 @@ const NumberComponent = props => {
inputProps,
incrementButtonProps,
decrementButtonProps
} = useNumberField(props, state, inputRef)
} = useNumberField({ ...props, formatOptions }, state, inputRef)

useEffect(() => props.onChange && props.onChange(value), [value])

Expand All @@ -53,10 +57,10 @@ const NumberComponent = props => {
ref={ inputRef }
inputProps={ inputProps }
>
<input
{ ...inputProps}
value={ Number.isInteger(state.numberValue) ? state.numberValue : 0 }
ref={ inputRef }
<input
{ ...inputProps}
step={ props.step ?? 1 }
ref={ inputRef }
name={ props.name ?? '' }
disabled={ isDisabled }
/>
Expand Down
136 changes: 129 additions & 7 deletions tests/jest/cases/components/controls/Number.test.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import * as fields from '../../../../../assets/src/index.tsx'
import {
render,
within
import {
render,
within
} from '@testing-library/react'
import {
import userEvent from '@testing-library/user-event'
import {
rendersWithMinimal,
rendersWithoutLabelThrowWarning,
rendersLabelAndDescription,
Expand Down Expand Up @@ -37,10 +38,10 @@ describe('Number component', () => {
{ props: { readOnly : false }, result: false }
])('supports readOnly (%p)', async args => {

const { container } = render(
const { container } = render(
fields.render({
name : 'field-name',
type : 'number',
name : 'field-name',
type : 'number',
label : 'Label',
...args.props
})
Expand All @@ -53,4 +54,125 @@ describe('Number component', () => {
expect( within(container).getByText('-').hasAttribute('disabled') ).toBe(args.result)
})

test.each([
{ value: 3.14, expected: '3.14' },
{ value: '3.14', expected: '3.14' },
])('accepts a decimal value as initial prop ($value)', ({ value, expected }) => {

const { container } = render(
fields.render({
name : 'field-name',
type : 'number',
label : 'Label',
value : value
})
)

const input = container.querySelector('.tf-number input')
expect( input.value ).toBe(expected)
})

test.each([
{ value: 0.5, expected: '0.5' },
{ value: '0.5', expected: '0.5' },
])('does not collapse decimal values to 0 ($value)', ({ value, expected }) => {

const { container } = render(
fields.render({
name : 'field-name',
type : 'number',
label : 'Label',
value : value
})
)

const input = container.querySelector('.tf-number input')
expect( input.value ).toBe(expected)
})

it('accepts a decimal input typed by the user', async () => {

const user = userEvent.setup()

const { container } = render(
fields.render({
name : 'field-name',
type : 'number',
label : 'Label',
})
)

const input = container.querySelector('.tf-number input')

await user.clear(input)
await user.type(input, '2.75')

expect( input.value ).toBe('2.75')
})

it('increments by step value when clicking +', async () => {

const user = userEvent.setup()

const { container } = render(
fields.render({
name : 'field-name',
type : 'number',
label : 'Label',
value : 1,
step : 0.5
})
)

const input = container.querySelector('.tf-number input')
const incrementButton = within(container).getByText('+')

expect( input.value ).toBe('1')

await user.click(incrementButton)
expect( input.value ).toBe('1.5')

await user.click(incrementButton)
expect( input.value ).toBe('2')
})

it('increments by 1 when step is not specified', async () => {

const user = userEvent.setup()

const { container } = render(
fields.render({
name : 'field-name',
type : 'number',
label : 'Label',
value : 3,
})
)

const input = container.querySelector('.tf-number input')
const incrementButton = within(container).getByText('+')

await user.click(incrementButton)
expect( input.value ).toBe('4')
})

test.each([
{ value: 3.14159, expected: '3.14' },
{ value: '3.14159', expected: '3.14' },
])('truncates decimals when formatOptions limits fraction digits ($value)', ({ value, expected }) => {

const { container } = render(
fields.render({
name : 'field-name',
type : 'number',
label : 'Label',
value : value,
formatOptions : { maximumFractionDigits: 2, useGrouping: false }
})
)

const input = container.querySelector('.tf-number input')
expect( input.value ).toBe(expected)
})

})
Loading