Skip to content

Commit 31da0f6

Browse files
Merge pull request #111 from nicolaslopezj/codex/añadir-más-tests-sin-modificar-código
Add more tests
2 parents 30196f9 + 56d7ab6 commit 31da0f6

6 files changed

Lines changed: 235 additions & 1 deletion

File tree

src/Array/additional.test.tsx

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import {render, screen} from '@testing-library/react'
2+
import Field from '../Field'
3+
import Form from '../Form'
4+
import ArrayField from './index'
5+
import {FieldProps} from '../types'
6+
import '@testing-library/jest-dom'
7+
8+
jest.useFakeTimers()
9+
10+
function DummyInput(props: FieldProps) {
11+
return (
12+
<input
13+
value={props.value || ''}
14+
onChange={e => props.onChange(e.target.value)}
15+
/>
16+
)
17+
}
18+
19+
test('autoAddItem renders an empty item when value is empty', () => {
20+
const {container} = render(
21+
<Form>
22+
<Field fieldName="items" type={ArrayField} autoAddItem>
23+
<Field fieldName="name" type={DummyInput} />
24+
</Field>
25+
</Form>,
26+
)
27+
expect(container.querySelectorAll('input')).toHaveLength(1)
28+
})
29+
30+
test('renderProps provides the current index', () => {
31+
render(
32+
<Form state={{items: [{}]}}>
33+
<Field fieldName="items" type={ArrayField} renderProps>
34+
{index => <div data-testid={`item-${index}`}>Item {index}</div>}
35+
</Field>
36+
</Form>,
37+
)
38+
expect(screen.getByTestId('item-0')).toBeInTheDocument()
39+
})
40+
41+
test('renderItem customizes each item element', () => {
42+
render(
43+
<Form state={{items: [{name: 'A'}]}}>
44+
<Field
45+
fieldName="items"
46+
type={ArrayField}
47+
renderItem={(item, i) => <div data-testid={`custom-${i}`}>{item.name}</div>}
48+
/>
49+
</Form>,
50+
)
51+
expect(screen.getByTestId('custom-0')).toHaveTextContent('A')
52+
})
53+
54+
test('honors showAddButton and custom addLabel', () => {
55+
const {container} = render(
56+
<Form>
57+
<Field fieldName="items" type={ArrayField} showAddButton={false} addLabel="Plus">
58+
<Field fieldName="name" type={DummyInput} />
59+
</Field>
60+
</Form>,
61+
)
62+
expect(screen.queryByText('Plus')).not.toBeInTheDocument()
63+
expect(container.querySelector('.srf_addButton')).not.toBeInTheDocument()
64+
})
65+
66+
test('honors showRemoveButton and custom removeLabel', () => {
67+
const {container} = render(
68+
<Form state={{items: [{}]}}>
69+
<Field
70+
fieldName="items"
71+
type={ArrayField}
72+
showRemoveButton={false}
73+
removeLabel="Del"
74+
>
75+
<Field fieldName="name" type={DummyInput} />
76+
</Field>
77+
</Form>,
78+
)
79+
expect(screen.queryByText('Del')).not.toBeInTheDocument()
80+
expect(container.querySelector('.srf_removeButton')).not.toBeInTheDocument()
81+
})
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import getNewValue from './getNewValue'
2+
3+
test('supports updater functions', () => {
4+
const original = {counter: 1}
5+
const result = getNewValue(original, 'counter', n => (n || 0) + 1)
6+
expect(result).toEqual({counter: 2})
7+
expect(original).toEqual({counter: 1})
8+
})
9+
10+
test('creates nested objects when missing', () => {
11+
const result = getNewValue({}, 'person.name.first', 'John')
12+
expect(result).toEqual({person: {name: {first: 'John'}}})
13+
})
14+
15+
test('throws if path expects object but finds primitive', () => {
16+
expect(() => getNewValue({person: 5}, 'person.name', 'John')).toThrow('Expected plain object for key person')
17+
})

src/Form/index.test.tsx

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,38 @@ test('should allow to reset state', () => {
163163

164164
expect(form.getValue()).toEqual({name: 'Nico'})
165165
})
166+
167+
test('does not render form tag in React Native environment', () => {
168+
const original: any = (global as any).navigator
169+
Object.defineProperty(global, 'navigator', {
170+
value: {product: 'ReactNative'},
171+
configurable: true,
172+
enumerable: true,
173+
writable: true,
174+
})
175+
176+
const {container} = render(
177+
<Form>
178+
<Field fieldName="name" type={DummyInput} />
179+
</Form>,
180+
)
181+
182+
expect(container.querySelector('form')).not.toBeInTheDocument()
183+
184+
Object.defineProperty(global, 'navigator', {
185+
value: original,
186+
configurable: true,
187+
enumerable: true,
188+
writable: true,
189+
})
190+
})
191+
192+
test('passes dom props to the form element', () => {
193+
const {container} = render(
194+
<Form target="/submit-here">
195+
<Field fieldName="name" type={DummyInput} />
196+
</Form>,
197+
)
198+
199+
expect(container.querySelector('form').getAttribute('target')).toBe('/submit-here')
200+
})

src/WithValue/index.test.tsx

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {render, screen} from '@testing-library/react'
1+
import {render, screen, fireEvent, act} from '@testing-library/react'
22
import React from 'react'
33
import Field from '../Field'
44
import Form from '../Form'
@@ -7,6 +7,8 @@ import {FieldProps} from '../types'
77
import WithValue from './index'
88
import '@testing-library/jest-dom'
99

10+
jest.useFakeTimers()
11+
1012
class DummyInput extends React.Component<FieldProps> {
1113
render() {
1214
return (
@@ -59,3 +61,27 @@ it('should pass the value of the form on sub object data', () => {
5961
const content = screen.getByText('Nicolás')
6062
expect(content.innerHTML).toBe('Nicolás')
6163
})
64+
65+
test('updates the render prop when the form value changes', () => {
66+
function Test() {
67+
const [state, setState] = React.useState({name: ''})
68+
return (
69+
<Form state={state} onChange={setState}>
70+
<WithValue>{value => <div data-testid="val">{value.name}</div>}</WithValue>
71+
<Field fieldName="name" type={DummyInput} />
72+
</Form>
73+
)
74+
}
75+
76+
const {container} = render(<Test />)
77+
78+
expect(screen.getByTestId('val')).toHaveTextContent('')
79+
80+
fireEvent.change(container.querySelector('input'), {target: {value: 'John'}})
81+
82+
act(() => {
83+
jest.advanceTimersByTime(0)
84+
})
85+
86+
expect(screen.getByTestId('val')).toHaveTextContent('John')
87+
})

src/useValue.test.tsx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import {render, screen, fireEvent} from '@testing-library/react'
2+
import React from 'react'
3+
import {ValueContext} from './Contexts'
4+
import useValue from './useValue'
5+
import '@testing-library/jest-dom'
6+
7+
function DisplayValue() {
8+
const value = useValue()
9+
return <div data-testid="value">{String(value)}</div>
10+
}
11+
12+
test('useValue returns the current context value', () => {
13+
render(
14+
<ValueContext.Provider value="context-value">
15+
<DisplayValue />
16+
</ValueContext.Provider>,
17+
)
18+
expect(screen.getByTestId('value')).toHaveTextContent('context-value')
19+
})
20+
21+
test('useValue updates when the context value changes', () => {
22+
function Wrapper() {
23+
const [val, setVal] = React.useState('first')
24+
return (
25+
<ValueContext.Provider value={val}>
26+
<button onClick={() => setVal('second')}>change</button>
27+
<DisplayValue />
28+
</ValueContext.Provider>
29+
)
30+
}
31+
32+
render(<Wrapper />)
33+
expect(screen.getByTestId('value')).toHaveTextContent('first')
34+
fireEvent.click(screen.getByText('change'))
35+
expect(screen.getByTestId('value')).toHaveTextContent('second')
36+
})

src/utility/isReactNative.test.tsx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import isReactNative from './isReactNative'
2+
3+
test('returns false in default browser environment', () => {
4+
expect(isReactNative()).toBe(false)
5+
})
6+
7+
test('detects React Native when navigator.product is ReactNative', () => {
8+
const original: any = (global as any).navigator
9+
Object.defineProperty(global, 'navigator', {
10+
value: {product: 'ReactNative'},
11+
configurable: true,
12+
enumerable: true,
13+
writable: true,
14+
})
15+
expect(isReactNative()).toBe(true)
16+
Object.defineProperty(global, 'navigator', {
17+
value: original,
18+
configurable: true,
19+
enumerable: true,
20+
writable: true,
21+
})
22+
})
23+
24+
test('returns false when navigator is undefined', () => {
25+
const original: any = (global as any).navigator
26+
Object.defineProperty(global, 'navigator', {
27+
value: undefined,
28+
configurable: true,
29+
enumerable: true,
30+
writable: true,
31+
})
32+
expect(isReactNative()).toBe(false)
33+
Object.defineProperty(global, 'navigator', {
34+
value: original,
35+
configurable: true,
36+
enumerable: true,
37+
writable: true,
38+
})
39+
})

0 commit comments

Comments
 (0)