diff --git a/packages/examples/src/1645.ts b/packages/examples/src/1645.ts new file mode 100644 index 000000000..b127a61c7 --- /dev/null +++ b/packages/examples/src/1645.ts @@ -0,0 +1,66 @@ +/* + The MIT License + + Copyright (c) 2021 EclipseSource Munich + https://github.com/eclipsesource/jsonforms + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ +import { registerExamples } from './register'; +import { UISchemaElement } from '@jsonforms/core'; + +export const schema = { + type: 'object', + properties: { + propText0: {type: 'string'}, + propText1: {type: 'string'}, + propText2: {type: 'string'}, + propText3: {type: 'string'}, + propText4: {type: 'string'}, + propText5: {type: 'string'}, + propText6: {type: 'string'}, + propText7: {type: 'string'}, + propText8: {type: 'string'}, + propText9: {type: 'string'}, + propNumber0: {type: 'number'}, + propNumber1: {type: 'number'}, + propNumber2: {type: 'number'}, + propNumber3: {type: 'number'}, + propNumber4: {type: 'number'}, + propNumber5: {type: 'number'}, + propNumber6: {type: 'number'}, + propNumber7: {type: 'number'}, + propNumber8: {type: 'number'}, + propNumber9: {type: 'number'}, + } +}; + +export const uischema: UISchemaElement = undefined; + +export const data = {}; + +registerExamples([ + { + name: '1645', + label: 'Issue 1645', + data, + schema, + uischema + } +]); diff --git a/packages/examples/src/index.ts b/packages/examples/src/index.ts index 875a5bc10..61b1011ad 100644 --- a/packages/examples/src/index.ts +++ b/packages/examples/src/index.ts @@ -75,6 +75,7 @@ import * as multiEnum from './multi-enum'; import * as enumInArray from './enumInArray'; import * as readonly from './readonly'; import * as bug_1779 from './1779'; +import * as bug_1645 from './1645'; export * from './register'; export * from './example'; @@ -134,5 +135,6 @@ export { multiEnum, enumInArray, readonly, - bug_1779 + bug_1779, + bug_1645 }; diff --git a/packages/material/src/controls/MaterialAnyOfStringOrEnumControl.tsx b/packages/material/src/controls/MaterialAnyOfStringOrEnumControl.tsx index 11796ad8b..dcc20abd6 100644 --- a/packages/material/src/controls/MaterialAnyOfStringOrEnumControl.tsx +++ b/packages/material/src/controls/MaterialAnyOfStringOrEnumControl.tsx @@ -38,7 +38,8 @@ import { Control, withJsonFormsControlProps } from '@jsonforms/react'; import { Input } from '@material-ui/core'; import { InputBaseComponentProps } from '@material-ui/core/InputBase'; import merge from 'lodash/merge'; -import React from 'react'; +import React, { useMemo } from 'react'; +import { useDebouncedChange } from '../util'; import { MaterialInputControl } from './MaterialInputControl'; const findEnumSchema = (schemas: JsonSchema[]) => @@ -64,17 +65,20 @@ const MuiAutocompleteInputText = (props: EnumCellProps & WithClassname) => { const enumSchema = findEnumSchema(schema.anyOf); const stringSchema = findTextSchema(schema.anyOf); const maxLength = stringSchema.maxLength; - const appliedUiSchemaOptions = merge({}, config, uischema.options); - let inputProps: InputBaseComponentProps = {}; - if (appliedUiSchemaOptions.restrict) { - inputProps = { maxLength: maxLength }; - } - if (appliedUiSchemaOptions.trim && maxLength !== undefined) { - inputProps.size = maxLength; - } - const onChange = (ev: any) => handleChange(path, ev.target.value); + const appliedUiSchemaOptions = useMemo(() => merge({}, config, uischema.options),[config, uischema.options]); + const inputProps: InputBaseComponentProps = useMemo(() => { + let propMemo: InputBaseComponentProps = {}; + if (appliedUiSchemaOptions.restrict) { + propMemo = { maxLength: maxLength }; + } + if (appliedUiSchemaOptions.trim && maxLength !== undefined) { + propMemo.size = maxLength; + } + propMemo.list = props.id + 'datalist'; + return propMemo; + },[appliedUiSchemaOptions,props.id]); + const [inputText, onChange] = useDebouncedChange(handleChange, '', data, path); - inputProps.list = props.id + 'datalist'; const dataList = ( {enumSchema.enum.map(optionValue => ( @@ -85,7 +89,7 @@ const MuiAutocompleteInputText = (props: EnumCellProps & WithClassname) => { return ( + value === '' ? undefined : parseInt(value, 10); +const eventToValue = (ev:any) => toNumber(ev.target.value); export const MuiInputInteger = React.memo( (props: CellProps & WithClassname) => { @@ -41,15 +46,16 @@ export const MuiInputInteger = React.memo( config } = props; const inputProps = { step: '1' }; - const toNumber = (value: string) => - value === '' ? undefined : parseInt(value, 10); + const appliedUiSchemaOptions = merge({}, config, uischema.options); + const [inputValue, onChange] = useDebouncedChange(handleChange, '', data, path, eventToValue); + return ( handleChange(path, toNumber(ev.target.value))} + value={inputValue} + onChange={onChange} className={className} id={id} disabled={!enabled} diff --git a/packages/material/src/mui-controls/MuiInputNumber.tsx b/packages/material/src/mui-controls/MuiInputNumber.tsx index d20a4a17c..6a5e4e738 100644 --- a/packages/material/src/mui-controls/MuiInputNumber.tsx +++ b/packages/material/src/mui-controls/MuiInputNumber.tsx @@ -27,7 +27,11 @@ import { CellProps, WithClassname } from '@jsonforms/core'; import Input from '@material-ui/core/Input'; import { areEqual } from '@jsonforms/react'; import merge from 'lodash/merge'; +import {useDebouncedChange} from '../util'; +const toNumber = (value: string) => + value === '' ? undefined : parseFloat(value); +const eventToValue = (ev:any) => toNumber(ev.target.value); export const MuiInputNumber = React.memo((props: CellProps & WithClassname) => { const { data, @@ -40,15 +44,15 @@ export const MuiInputNumber = React.memo((props: CellProps & WithClassname) => { config } = props; const inputProps = { step: '0.1' }; - const toNumber = (value: string) => - value === '' ? undefined : parseFloat(value); + const appliedUiSchemaOptions = merge({}, config, uischema.options); + const [inputValue, onChange] = useDebouncedChange(handleChange, '', data, path, eventToValue); return ( handleChange(path, toNumber(ev.target.value))} + value={inputValue} + onChange={onChange} className={className} id={id} disabled={!enabled} diff --git a/packages/material/src/mui-controls/MuiInputNumberFormat.tsx b/packages/material/src/mui-controls/MuiInputNumberFormat.tsx index 077e33529..c4fba2201 100644 --- a/packages/material/src/mui-controls/MuiInputNumberFormat.tsx +++ b/packages/material/src/mui-controls/MuiInputNumberFormat.tsx @@ -22,11 +22,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import React from 'react'; +import React, {useCallback} from 'react'; import { CellProps, Formatted, WithClassname } from '@jsonforms/core'; import Input from '@material-ui/core/Input'; import { areEqual } from '@jsonforms/react'; import merge from 'lodash/merge'; +import { useDebouncedChange } from '../util'; export const MuiInputNumberFormat = React.memo( (props: CellProps & WithClassname & Formatted) => { @@ -51,15 +52,14 @@ export const MuiInputNumberFormat = React.memo( } const formattedNumber = props.toFormatted(props.data); - const onChange = (ev: any) => { - const validStringNumber = props.fromFormatted(ev.currentTarget.value); - handleChange(path, validStringNumber); - }; + const validStringNumber = useCallback((ev:any) => props.fromFormatted(ev.currentTarget.value),[props.fromFormatted]); + const [inputValue, onChange] = useDebouncedChange(handleChange, '', formattedNumber, path, validStringNumber); + return ( { +export const MuiInputText = React.memo((props: CellProps & WithClassname & MuiTextInputProps) => { const [showAdornment, setShowAdornment] = useState(false); const { data, @@ -63,23 +62,27 @@ export const MuiInputText = React.memo((props: CellProps & WithClassname & MuiTe } else { inputProps = {}; } - + inputProps = merge(inputProps, muiInputProps); - + if (appliedUiSchemaOptions.trim && maxLength !== undefined) { inputProps.size = maxLength; - } - const onChange = (ev: any) => handleChange(path, ev.target.value); + }; + + const [inputText, onChange, onClear] = useDebouncedChange(handleChange, '', data, path); + const onPointerEnter = () => setShowAdornment(true); + const onPointerLeave = () => setShowAdornment(false); const theme: JsonFormsTheme = useTheme(); - const inputDeleteBackgroundColor = theme.jsonforms?.input?.delete?.background || theme.palette.background.default; + + const closeStyle = {background: theme.jsonforms?.input?.delete?.background || theme.palette.background.default, borderRadius: '50%'}; return ( setShowAdornment(true) } - onPointerLeave={() => setShowAdornment(false) } + onPointerEnter={onPointerEnter} + onPointerLeave={onPointerLeave} endAdornment={ handleChange(path, undefined)} + onClick={onClear} > - + } diff --git a/packages/material/src/mui-controls/MuiInputTime.tsx b/packages/material/src/mui-controls/MuiInputTime.tsx index 622e005a6..9c82b3f1a 100644 --- a/packages/material/src/mui-controls/MuiInputTime.tsx +++ b/packages/material/src/mui-controls/MuiInputTime.tsx @@ -27,6 +27,7 @@ import { CellProps, WithClassname } from '@jsonforms/core'; import Input from '@material-ui/core/Input'; import { areEqual } from '@jsonforms/react'; import merge from 'lodash/merge'; +import { useDebouncedChange } from '../util'; export const MuiInputTime = React.memo((props: CellProps & WithClassname) => { const { @@ -40,11 +41,13 @@ export const MuiInputTime = React.memo((props: CellProps & WithClassname) => { config } = props; const appliedUiSchemaOptions = merge({}, config, uischema.options); + const [inputValue, onChange] = useDebouncedChange(handleChange, '', data, path); + return ( handleChange(path, ev.target.value)} + value={inputValue} + onChange={onChange} className={className} id={id} disabled={!enabled} diff --git a/packages/material/src/util/debounce.ts b/packages/material/src/util/debounce.ts new file mode 100644 index 000000000..c5b299171 --- /dev/null +++ b/packages/material/src/util/debounce.ts @@ -0,0 +1,19 @@ +import { debounce } from 'lodash'; +import { useState, useCallback, useEffect } from 'react' + + +const eventToValue = (ev: any) => ev.target.value; +export const useDebouncedChange = (handleChange: (path: string, value: any) => void, defaultValue: any, data: any, path: string, eventToValueFunction: (ev: any) => any = eventToValue, timeout = 300): [any, React.ChangeEventHandler, () => void] => { + const [input, setInput] = useState(data ?? defaultValue); + useEffect(() => { + setInput(data ?? defaultValue); + }, [data]); + const debouncedUpdate = useCallback(debounce((newValue: string) => handleChange(path, newValue), timeout), [handleChange, path, timeout]); + const onChange = useCallback((ev: any) => { + const newValue = eventToValueFunction(ev); + setInput(newValue ?? defaultValue); + debouncedUpdate(newValue); + }, [debouncedUpdate, eventToValueFunction]); + const onClear = useCallback(() => { setInput(defaultValue); handleChange(path, undefined) }, [defaultValue, handleChange, path]); + return [input, onChange, onClear]; +}; \ No newline at end of file diff --git a/packages/material/src/util/index.ts b/packages/material/src/util/index.ts index cdf369598..0999bc9e2 100644 --- a/packages/material/src/util/index.ts +++ b/packages/material/src/util/index.ts @@ -25,3 +25,4 @@ export * from './datejs'; export * from './layout'; export * from './theme'; +export * from './debounce'; diff --git a/packages/material/test/renderers/MaterialAnyOfRenderer.test.tsx b/packages/material/test/renderers/MaterialAnyOfRenderer.test.tsx index a161ee2a3..e541de043 100644 --- a/packages/material/test/renderers/MaterialAnyOfRenderer.test.tsx +++ b/packages/material/test/renderers/MaterialAnyOfRenderer.test.tsx @@ -62,7 +62,7 @@ describe('Material anyOf renderer', () => { afterEach(() => wrapper.unmount()); - it('should add an item at correct path', () => { + it('should add an item at correct path', (done) => { const schema = { type: 'object', properties: { @@ -103,9 +103,12 @@ describe('Material anyOf renderer', () => { const input = wrapper.find('input').first(); input.simulate('change', { target: { value: 'test' } }); wrapper.update(); - expect(onChangeData.data).toEqual({ - value: 'test' - }); + setTimeout(() => { + expect(onChangeData.data).toEqual({ + value: 'test' + }); + done(); + }, 1000); }); it('should add a "mything"', async () => { @@ -179,7 +182,7 @@ describe('Material anyOf renderer', () => { expect(nrOfRowsAfterAdd.length).toBe(4); }); - it('should switch to "yourThing" edit, then switch back, then edit', async () => { + it('should switch to "yourThing" edit, then switch back, then edit', async (done) => { const schema = { type: 'object', properties: { @@ -260,9 +263,12 @@ describe('Material anyOf renderer', () => { input.simulate('change', { target: { value: 'test' } }); wrapper.update(); - expect(onChangeData.data).toEqual({ - myThingsAndOrYourThings: [{ age: 5, name: 'test' }] - }); + setTimeout(() => { + expect(onChangeData.data).toEqual({ + myThingsAndOrYourThings: [{ age: 5, name: 'test' }] + }); + done(); + }, 1000); }); it('should be hideable', () => { diff --git a/packages/material/test/renderers/MaterialIntegerCell.test.tsx b/packages/material/test/renderers/MaterialIntegerCell.test.tsx index ae037b7db..3bc7871c3 100644 --- a/packages/material/test/renderers/MaterialIntegerCell.test.tsx +++ b/packages/material/test/renderers/MaterialIntegerCell.test.tsx @@ -175,7 +175,7 @@ describe('Material integer cells', () => { expect(input.props().value).toBe(0); }); - it('should update via input event', () => { + it('should update via input event', (done) => { const core = initCore(schema, uischema, data); const onChangeData: any = { data: undefined @@ -193,10 +193,13 @@ describe('Material integer cells', () => { const input = wrapper.find('input'); input.simulate('change', { target: { value: 13 } }); - expect(onChangeData.data.foo).toBe(13); + setTimeout(() => { + expect(onChangeData.data.foo).toBe(13); + done(); + }, 1000) }); - it('should update via action', () => { + it('should update via action', (done) => { const core = initCore(schema, uischema, { foo: 13 }); wrapper = mount( @@ -206,11 +209,14 @@ describe('Material integer cells', () => { core.data = { ...core.data, foo: 42 }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input').first(); - expect(input.props().value).toBe(42); + setTimeout(() => { + const input = wrapper.find('input').first(); + expect(input.props().value).toBe(42); + done(); + }, 1000); }); - it('should not update with undefined value', () => { + it('should not update with undefined value', (done) => { const core = initCore(schema, uischema, data); wrapper = mount( @@ -220,11 +226,14 @@ describe('Material integer cells', () => { core.data = { ...core.data, foo: undefined }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input'); - expect(input.props().value).toBe(''); + setTimeout(() => { + const input = wrapper.find('input'); + expect(input.props().value).toBe(''); + done(); + }, 1000); }); - it('should not update with null value', () => { + it('should not update with null value', (done) => { const core = initCore(schema, uischema, data); wrapper = mount( @@ -234,11 +243,14 @@ describe('Material integer cells', () => { core.data = { ...core.data, foo: null }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input').first(); - expect(input.props().value).toBe(''); + setTimeout(() => { + const input = wrapper.find('input').first(); + expect(input.props().value).toBe(''); + done(); + }, 1000); }); - it('should not update with wrong ref', () => { + it('should not update with wrong ref', (done) => { const core = initCore(schema, uischema, data); wrapper = mount( @@ -248,11 +260,14 @@ describe('Material integer cells', () => { core.data = { ...core.data, bar: 11 }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input'); - expect(input.props().value).toBe(42); + setTimeout(() => { + const input = wrapper.find('input'); + expect(input.props().value).toBe(42); + done(); + }, 1000); }); - it('should not update with null ref', () => { + it('should not update with null ref', (done) => { const core = initCore(schema, uischema, data); wrapper = mount( @@ -262,11 +277,14 @@ describe('Material integer cells', () => { core.data = { ...core.data, null: 13 }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input').first(); - expect(input.props().value).toBe(42); + setTimeout(() => { + const input = wrapper.find('input'); + expect(input.props().value).toBe(42); + done(); + }, 1000); }); - it('should not update with undefined ref', () => { + it('should not update with undefined ref', (done) => { const core = initCore(schema, uischema, data); wrapper = mount( @@ -276,8 +294,11 @@ describe('Material integer cells', () => { core.data = { ...core.data, undefined: 13 }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input').first(); - expect(input.props().value).toBe(42); + setTimeout(() => { + const input = wrapper.find('input'); + expect(input.props().value).toBe(42); + done(); + }, 1000); }); it('can be disabled', () => { diff --git a/packages/material/test/renderers/MaterialNumberCell.test.tsx b/packages/material/test/renderers/MaterialNumberCell.test.tsx index 4e6f72b09..254686d6e 100644 --- a/packages/material/test/renderers/MaterialNumberCell.test.tsx +++ b/packages/material/test/renderers/MaterialNumberCell.test.tsx @@ -217,7 +217,7 @@ describe('Material number cells', () => { expect(input.props().value).toBe(0); }); - it('should update via input event', () => { + it('should update via input event', (done) => { const core = initCore(schema, uischema, data); const onChangeData: any = { data: undefined @@ -234,10 +234,13 @@ describe('Material number cells', () => { ); const input = wrapper.find('input'); input.simulate('change', { target: { value: 2.72 } }); - expect(onChangeData.data.foo).toBe(2.72); + setTimeout(() => { + expect(onChangeData.data.foo).toBe(2.72); + done(); + }, 1000); }); - it('should update via action', () => { + it('should update via action', (done) => { const core = initCore(schema, uischema, { foo: 2.72 }); wrapper = mount( @@ -251,15 +254,18 @@ describe('Material number cells', () => { wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - expect( - wrapper - .find('input') - .first() - .props().value - ).toBe(3.14); + setTimeout(() => { + expect( + wrapper + .find('input') + .first() + .props().value + ).toBe(3.14); + done(); + }, 1000); }); - it('should update with undefined value', () => { + it('should update with undefined value', (done) => { const core = initCore(schema, uischema, data); wrapper = mount( @@ -269,11 +275,14 @@ describe('Material number cells', () => { core.data = { ...core.data, foo: undefined }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input').first(); - expect(input.props().value).toBe(''); + setTimeout(() => { + const input = wrapper.find('input').first(); + expect(input.props().value).toBe(''); + done(); + }, 1000); }); - it('should not update with null value', () => { + it('should not update with null value', (done) => { const core = initCore(schema, uischema, data); wrapper = mount( @@ -283,11 +292,14 @@ describe('Material number cells', () => { core.data = { ...core.data, foo: null }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input').first(); - expect(input.props().value).toBe(''); + setTimeout(() => { + const input = wrapper.find('input').first(); + expect(input.props().value).toBe(''); + done(); + }, 1000); }); - it('should not update with wrong ref', () => { + it('should not update with wrong ref', (done) => { const core = initCore(schema, uischema, data); wrapper = mount( @@ -297,11 +309,14 @@ describe('Material number cells', () => { core.data = { ...core.data, bar: 11 }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input').first(); - expect(input.props().value).toBe(3.14); + setTimeout(() => { + const input = wrapper.find('input').first(); + expect(input.props().value).toBe(3.14); + done(); + }, 1000); }); - it('should not update with null ref', () => { + it('should not update with null ref', (done) => { const core = initCore(schema, uischema, data); wrapper = mount( @@ -311,11 +326,14 @@ describe('Material number cells', () => { core.data = { ...core.data, null: 2.72 }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input').first(); - expect(input.props().value).toBe(3.14); + setTimeout(() => { + const input = wrapper.find('input').first(); + expect(input.props().value).toBe(3.14); + done(); + }, 1000); }); - it('should not update with undefined ref', () => { + it('should not update with undefined ref', (done) => { const core = initCore(schema, uischema, data); wrapper = mount( @@ -325,8 +343,11 @@ describe('Material number cells', () => { core.data = { ...core.data, undefined: 13 }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input').first(); - expect(input.props().value).toBe(3.14); + setTimeout(() => { + const input = wrapper.find('input').first(); + expect(input.props().value).toBe(3.14); + done(); + }, 1000); }); it('can be disabled', () => { diff --git a/packages/material/test/renderers/MaterialOneOfRenderer.test.tsx b/packages/material/test/renderers/MaterialOneOfRenderer.test.tsx index 7344539ed..80d01ba59 100644 --- a/packages/material/test/renderers/MaterialOneOfRenderer.test.tsx +++ b/packages/material/test/renderers/MaterialOneOfRenderer.test.tsx @@ -256,7 +256,7 @@ describe('Material oneOf renderer', () => { expect(secondTab.props().selected).toBeTruthy(); }); - it('should add an item at correct path', () => { + it('should add an item at correct path', (done) => { const schema = { type: 'object', properties: { @@ -298,9 +298,12 @@ describe('Material oneOf renderer', () => { const input = wrapper.find('input').first(); input.simulate('change', { target: { value: 'test' } }); wrapper.update(); - expect(onChangeData.data).toEqual({ - value: 'test' - }); + setTimeout(() => { + expect(onChangeData.data).toEqual({ + value: 'test' + }); + done(); + }, 1000); }); it.skip('should add an item within an array', async () => { diff --git a/packages/material/test/renderers/MaterialTextCell.test.tsx b/packages/material/test/renderers/MaterialTextCell.test.tsx index 234a35052..4c4176a88 100644 --- a/packages/material/test/renderers/MaterialTextCell.test.tsx +++ b/packages/material/test/renderers/MaterialTextCell.test.tsx @@ -196,7 +196,7 @@ describe('Material text cell', () => { expect(input.props().value).toBe('Foo'); }); - it('should update via input event', () => { + it('should update via input event', (done) => { const core = initCore(minLengthSchema, uischema, data); const onChangeData: any = { data: undefined @@ -214,10 +214,13 @@ describe('Material text cell', () => { const input = wrapper.find('input').first(); input.simulate('change', { target: { value: 'Bar' } }); - expect(onChangeData.data.name).toBe('Bar'); + setTimeout(() => { + expect(onChangeData.data.name).toBe('Bar'); + done(); + }, 1000); }); - it('should update via action', () => { + it('should update via action', (done) => { const core = initCore(minLengthSchema, uischema, data); wrapper = mount( @@ -227,11 +230,14 @@ describe('Material text cell', () => { core.data = { ...core.data, name: 'Bar' }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input').first(); - expect(input.props().value).toBe('Bar'); + setTimeout(() => { + const input = wrapper.find('input').first(); + expect(input.props().value).toBe('Bar'); + done(); + }, 1000); }); - it('should update with undefined value', () => { + it('should update with undefined value', (done) => { const core = initCore(minLengthSchema, uischema, data); wrapper = mount( @@ -241,11 +247,14 @@ describe('Material text cell', () => { core.data = { ...core.data, name: undefined }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input').first(); - expect(input.props().value).toBe(''); + setTimeout(() => { + const input = wrapper.find('input').first(); + expect(input.props().value).toBe(''); + done(); + }, 1000); }); - it('should update with null value', () => { + it('should update with null value', (done) => { const core = initCore(minLengthSchema, uischema, data); wrapper = mount( @@ -255,11 +264,14 @@ describe('Material text cell', () => { core.data = { ...core.data, name: null }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input').first(); - expect(input.props().value).toBe(''); + setTimeout(() => { + const input = wrapper.find('input').first(); + expect(input.props().value).toBe(''); + done(); + }, 1000); }); - it('should not update if wrong ref', () => { + it('should not update if wrong ref', (done) => { const core = initCore(minLengthSchema, uischema, data); wrapper = mount( @@ -269,11 +281,14 @@ describe('Material text cell', () => { core.data = { ...core.data, firstname: 'Bar' }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input').first(); - expect(input.props().value).toBe('Foo'); + setTimeout(() => { + const input = wrapper.find('input').first(); + expect(input.props().value).toBe('Foo'); + done(); + }, 1000); }); - it('should not update if null ref', () => { + it('should not update if null ref', (done) => { const core = initCore(minLengthSchema, uischema, data); wrapper = mount( @@ -283,11 +298,14 @@ describe('Material text cell', () => { core.data = { ...core.data, null: 'Bar' }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input').first(); - expect(input.props().value).toBe('Foo'); + setTimeout(() => { + const input = wrapper.find('input').first(); + expect(input.props().value).toBe('Foo'); + done(); + }, 1000); }); - it('should not update if undefined ref', () => { + it('should not update if undefined ref', (done) => { const core = initCore(minLengthSchema, uischema, data); wrapper = mount( @@ -297,8 +315,11 @@ describe('Material text cell', () => { core.data = { ...core.data, undefined: 'Bar' }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input').first(); - expect(input.props().value).toBe('Foo'); + setTimeout(() => { + const input = wrapper.find('input').first(); + expect(input.props().value).toBe('Foo'); + done(); + }, 1000); }); it('can be disabled', () => { diff --git a/packages/material/test/renderers/MaterialTimeCell.test.tsx b/packages/material/test/renderers/MaterialTimeCell.test.tsx index d5bf92836..cf0b8aa52 100644 --- a/packages/material/test/renderers/MaterialTimeCell.test.tsx +++ b/packages/material/test/renderers/MaterialTimeCell.test.tsx @@ -174,7 +174,7 @@ describe('Material time cell', () => { expect(input.props().value).toBe('13:37'); }); - it('should update via event', () => { + it('should update via event', (done) => { const core = initCore(schema, uischema, data); const onChangeData: any = { data: undefined @@ -191,10 +191,13 @@ describe('Material time cell', () => { ); const input = wrapper.find('input').first(); input.simulate('change', { target: { value: '20:15' } }); - expect(onChangeData.data.foo).toBe('20:15'); + setTimeout(() => { + expect(onChangeData.data.foo).toBe('20:15'); + done(); + }, 1000); }); - it('should update via action', () => { + it('should update via action', (done) => { const core = initCore(schema, uischema, data); wrapper = mount( @@ -204,11 +207,14 @@ describe('Material time cell', () => { core.data = { ...core.data, foo: '20:15' }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input').first(); - expect(input.props().value).toBe('20:15'); + setTimeout(() => { + const input = wrapper.find('input').first(); + expect(input.props().value).toBe('20:15'); + done(); + }, 1000); }); - it('should update with null value', () => { + it('should update with null value', (done) => { const core = initCore(schema, uischema, data); wrapper = mount( @@ -218,11 +224,14 @@ describe('Material time cell', () => { core.data = { ...core.data, foo: null }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input').first(); - expect(input.props().value).toBe(''); + setTimeout(() => { + const input = wrapper.find('input').first(); + expect(input.props().value).toBe(''); + done(); + }, 1000); }); - it('update with undefined value', () => { + it('update with undefined value', (done) => { const core = initCore(schema, uischema, data); wrapper = mount( @@ -232,11 +241,14 @@ describe('Material time cell', () => { core.data = { ...core.data, foo: undefined }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input').first(); - expect(input.props().value).toBe(''); + setTimeout(() => { + const input = wrapper.find('input').first(); + expect(input.props().value).toBe(''); + done(); + }, 1000); }); - it('should update with wrong ref', () => { + it('should update with wrong ref', (done) => { const core = initCore(schema, uischema, data); wrapper = mount( @@ -246,11 +258,14 @@ describe('Material time cell', () => { core.data = { ...core.data, bar: 'Bar' }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input').first(); - expect(input.props().value).toBe('13:37'); + setTimeout(() => { + const input = wrapper.find('input').first(); + expect(input.props().value).toBe('13:37'); + done(); + }, 1000); }); - it('should update with null ref', () => { + it('should update with null ref', (done) => { const core = initCore(schema, uischema, data); wrapper = mount( @@ -260,11 +275,14 @@ describe('Material time cell', () => { core.data = { ...core.data, null: '20:15' }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input').first(); - expect(input.props().value).toBe('13:37'); + setTimeout(() => { + const input = wrapper.find('input').first(); + expect(input.props().value).toBe('13:37'); + done(); + }, 1000); }); - it('should update with undefined ref', () => { + it('should update with undefined ref', (done) => { const core = initCore(schema, uischema, data); wrapper = mount( @@ -274,8 +292,11 @@ describe('Material time cell', () => { core.data = { ...core.data, undefined: '20:15' }; wrapper.setProps({ initState: { renderers: materialRenderers, core }} ); wrapper.update(); - const input = wrapper.find('input').first(); - expect(input.props().value).toBe('13:37'); + setTimeout(() => { + const input = wrapper.find('input').first(); + expect(input.props().value).toBe('13:37'); + done(); + }, 1000); }); it('can be disabled', () => {