Skip to content

Commit

Permalink
Fix propper Wizard and defaultValue support
Browse files Browse the repository at this point in the history
  • Loading branch information
tujoworker committed Sep 25, 2024
1 parent 8b24e74 commit 89ea339
Show file tree
Hide file tree
Showing 6 changed files with 294 additions and 62 deletions.
14 changes: 2 additions & 12 deletions packages/dnb-eufemia/src/extensions/forms/Iterate/Array/Array.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import IterateItemContext, {
import SummaryListContext from '../../Value/SummaryList/SummaryListContext'
import ValueBlockContext from '../../ValueBlock/ValueBlockContext'
import FieldBoundaryProvider from '../../DataContext/FieldBoundary/FieldBoundaryProvider'
import DataContext from '../../DataContext/Context'
import useDataValue from '../../hooks/useDataValue'
import { useArrayLimit, useSwitchContainerMode } from '../hooks'
import { getMessage } from '../../FieldBlock'
Expand Down Expand Up @@ -75,22 +74,22 @@ function ArrayComponent(props: Props) {
}

return {
isIterateArray: true,
required: false,
...props,
value: newValue,
}
}
}

return { required: false, ...props }
return { isIterateArray: true, required: false, ...props }
}, [getValueByPath, props])

const {
path,
value: arrayValue,
limit,
error,
defaultValue,
withoutFlex,
emptyValue,
placeholder,
Expand Down Expand Up @@ -129,15 +128,6 @@ function ArrayComponent(props: Props) {

const omitFlex = withoutFlex ?? (summaryListContext || valueBlockContext)

// To support React.StrictMode, we inject the defaultValue into the data context this way.
// The routine inside useFieldProps where updateDataValueDataContext is called, does not support React.StrictMode
const { handlePathChange } = useContext(DataContext) || {}
useMountEffect(() => {
if (defaultValue) {
handlePathChange?.(path, defaultValue)
}
})

useEffect(() => {
// Update inside the useEffect, to support React.StrictMode
valueCountRef.current = arrayValue || []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -562,31 +562,110 @@ describe('Iterate.Array', () => {
expect(onChangeIterate).toHaveBeenLastCalledWith(['foo'])
})

it('should handle "defaultValue" with React.StrictMode', () => {
const onSubmit = jest.fn()
describe('defaultValue', () => {
it('should handle "defaultValue" (empty string) in React.StrictMode', () => {
const onSubmit = jest.fn()

render(
<React.StrictMode>
<Form.Handler onSubmit={onSubmit}>
<Iterate.Array path="/myList" defaultValue={['']}>
<Field.String itemPath="/" />
</Iterate.Array>
</Form.Handler>
</React.StrictMode>
)
render(
<React.StrictMode>
<Form.Handler onSubmit={onSubmit}>
<Iterate.Array path="/myList" defaultValue={['']}>
<Field.String itemPath="/" />
</Iterate.Array>
</Form.Handler>
</React.StrictMode>
)

const form = document.querySelector('form')
const input = document.querySelector('input')
const form = document.querySelector('form')
const input = document.querySelector('input')

expect(input).toHaveValue('')
expect(input).toHaveValue('')

fireEvent.submit(form)
fireEvent.submit(form)

expect(onSubmit).toHaveBeenCalledTimes(1)
expect(onSubmit).toHaveBeenLastCalledWith(
{ myList: [''] },
expect.anything()
)
expect(onSubmit).toHaveBeenCalledTimes(1)
expect(onSubmit).toHaveBeenLastCalledWith(
{ myList: [''] },
expect.anything()
)
})

it('should handle "defaultValue" (with value) in React.StrictMode', () => {
const onSubmit = jest.fn()

render(
<React.StrictMode>
<Form.Handler onSubmit={onSubmit}>
<Iterate.Array path="/myList" defaultValue={['foo']}>
<Field.String itemPath="/" />
</Iterate.Array>
</Form.Handler>
</React.StrictMode>
)

const form = document.querySelector('form')
const input = document.querySelector('input')

expect(input).toHaveValue('foo')

fireEvent.submit(form)

expect(onSubmit).toHaveBeenCalledTimes(1)
expect(onSubmit).toHaveBeenLastCalledWith(
{ myList: ['foo'] },
expect.anything()
)
})

it('should handle "defaultValue" (with null) in React.StrictMode', () => {
const onSubmit = jest.fn()

render(
<React.StrictMode>
<Form.Handler onSubmit={onSubmit}>
<Iterate.Array path="/myList" defaultValue={[null]}>
<Field.String itemPath="/" defaultValue="foo" />
</Iterate.Array>
</Form.Handler>
</React.StrictMode>
)

const form = document.querySelector('form')
const input = document.querySelector('input')

expect(input).toHaveValue('foo')

fireEvent.submit(form)

expect(onSubmit).toHaveBeenCalledTimes(1)
expect(onSubmit).toHaveBeenLastCalledWith(
{ myList: ['foo'] },
expect.anything()
)
})

it('should set empty array in the data context', () => {
const onSubmit = jest.fn()

render(
<React.StrictMode>
<Form.Handler onSubmit={onSubmit}>
<Iterate.Array path="/myList" defaultValue={[]}>
content
</Iterate.Array>
</Form.Handler>
</React.StrictMode>
)

const form = document.querySelector('form')
fireEvent.submit(form)

expect(onSubmit).toHaveBeenCalledTimes(1)
expect(onSubmit).toHaveBeenLastCalledWith(
{ myList: [] },
expect.anything()
)
})
})

describe('with primitive elements', () => {
Expand Down Expand Up @@ -1294,7 +1373,7 @@ describe('Iterate.Array', () => {
<Form.Handler
onSubmit={onSubmit}
data={{
myList: ['', undefined, null, 'something'],
myList: [undefined, null, 'something'],
}}
>
<Iterate.Array path="/myList">
Expand All @@ -1311,26 +1390,20 @@ describe('Iterate.Array', () => {
)

const form = document.querySelector('form')
const [first, second, third, forth] = Array.from(
const [first, second, third] = Array.from(
document.querySelectorAll('input')
)

expect(first).toHaveValue('default value 1')
expect(second).toHaveValue('default value 2')
expect(third).toHaveValue('default value 3')
expect(forth).toHaveValue('default value 4')
expect(third).toHaveValue('something')

fireEvent.submit(form)

expect(onSubmit).toHaveBeenCalledTimes(1)
expect(onSubmit).toHaveBeenLastCalledWith(
{
myList: [
'default value 1',
'default value 2',
'default value 3',
'default value 4',
],
myList: ['default value 1', 'default value 2', 'something'],
},
expect.anything()
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useCallback } from 'react'
import { Field, Form, Iterate, Value } from '../..'
import { Field, Form, Iterate, Tools, Value, Wizard } from '../..'
import { Card, Flex, Section } from '../../../../components'

export default {
Expand Down Expand Up @@ -256,3 +256,42 @@ export const WithArrayValidator = () => {
</Form.Handler>
)
}

export function InWizard() {
return (
<React.StrictMode>
<Form.Handler>
<Wizard.Container>
<Wizard.Step>
<Field.String
label="Regular"
path="/regular"
defaultValue="123"
/>
<Iterate.Array path="/items" defaultValue={[{}]}>
<Field.String
label="In Iterate"
itemPath="/x"
defaultValue="123"
/>
</Iterate.Array>

<Wizard.Buttons />
</Wizard.Step>

<Wizard.Step>
<Wizard.Buttons />
</Wizard.Step>
</Wizard.Container>

<Tools.Log />
</Form.Handler>

<Form.Handler>
<Iterate.Array path="/myList" defaultValue={[null]}>
<Field.String itemPath="/" defaultValue="bar" />
</Iterate.Array>
</Form.Handler>
</React.StrictMode>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react'
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { wait } from '../../../../../core/jest/jestSetup'
import { Field, Form, OnSubmit, Wizard } from '../../..'
import { Field, Form, Iterate, OnSubmit, Wizard } from '../../..'

import nbNO from '../../../constants/locales/nb-NO'
const nb = nbNO['nb-NO']
Expand Down Expand Up @@ -1964,4 +1964,107 @@ describe('Wizard.Container', () => {
expect(iframe.parentElement).toBeNull()
})
})

describe('defaultValue', () => {
it('should set defaultValue of a Field.* only once between step changes', async () => {
const onChange = jest.fn()
const onStepChange = jest.fn()

render(
<Form.Handler onChange={onChange}>
<Wizard.Container onStepChange={onStepChange}>
<Wizard.Step>
<Field.String path="/foo" defaultValue="123" />
<Wizard.Buttons />
</Wizard.Step>

<Wizard.Step>
<Wizard.Buttons />
</Wizard.Step>
</Wizard.Container>
</Form.Handler>
)

expect(document.querySelector('input')).toHaveValue('123')

await userEvent.type(document.querySelector('input'), '4')

expect(document.querySelector('input')).toHaveValue('1234')

await userEvent.click(nextButton())

expect(onStepChange).toHaveBeenLastCalledWith(
1,
'next',
expect.anything()
)

await userEvent.click(previousButton())

expect(onStepChange).toHaveBeenLastCalledWith(
0,
'previous',
expect.anything()
)

expect(document.querySelector('input')).toHaveValue('1234')
})

it('should set defaultValue of Iterate.Array only once between step changes', async () => {
const onChange = jest.fn()
const onStepChange = jest.fn()

render(
<Form.Handler onChange={onChange}>
<Wizard.Container onStepChange={onStepChange}>
<Wizard.Step>
<Iterate.Array path="/items" defaultValue={[null]}>
<Field.String itemPath="/" defaultValue="123" />
</Iterate.Array>

<Iterate.PushButton pushValue={null} path="/items" />

<Wizard.Buttons />
</Wizard.Step>

<Wizard.Step>
<Wizard.Buttons />
</Wizard.Step>
</Wizard.Container>
</Form.Handler>
)

expect(document.querySelectorAll('input')).toHaveLength(1)
expect(document.querySelector('input')).toHaveValue('123')

await userEvent.type(document.querySelector('input'), '4')

expect(document.querySelector('input')).toHaveValue('1234')

const pushButton = document.querySelector(
'.dnb-forms-iterate-push-button'
)
await userEvent.click(pushButton)

expect(document.querySelectorAll('input')).toHaveLength(2)

await userEvent.click(nextButton())

expect(onStepChange).toHaveBeenLastCalledWith(
1,
'next',
expect.anything()
)

await userEvent.click(previousButton())

expect(document.querySelectorAll('input')).toHaveLength(2)
expect(onStepChange).toHaveBeenLastCalledWith(
0,
'previous',
expect.anything()
)
expect(document.querySelector('input')).toHaveValue('1234')
})
})
})
Loading

0 comments on commit 89ea339

Please sign in to comment.