diff --git a/.vscode/launch.json b/.vscode/launch.json index d35416cf4..73edb0dec 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -15,6 +15,20 @@ "disableOptimisticBPs": true, "cwd": "${workspaceFolder}/GDevelop.js" }, + { + "type": "node", + "request": "launch", + "name": "newIDE/app Jest tests (current file)", + "program": "${workspaceFolder}/newIDE/app/node_modules/.bin/react-scripts", + "args": [ + "test", "--env=node", + "${fileBasenameNoExtension}" + ], + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "disableOptimisticBPs": true, + "cwd": "${workspaceFolder}/newIDE/app" + }, { "type": "node", "request": "launch", diff --git a/newIDE/app/src/EventsSheet/ParameterFields/LeaderboardIdField.js b/newIDE/app/src/EventsSheet/ParameterFields/LeaderboardIdField.js index 0122142a7..676236c99 100644 --- a/newIDE/app/src/EventsSheet/ParameterFields/LeaderboardIdField.js +++ b/newIDE/app/src/EventsSheet/ParameterFields/LeaderboardIdField.js @@ -8,7 +8,7 @@ import { type ParameterFieldProps, type ParameterFieldInterface, } from './ParameterFieldCommons'; -import SelectField from '../../UI/SelectField'; +import SelectField, { type SelectFieldInterface } from '../../UI/SelectField'; import SelectOption from '../../UI/SelectOption'; import { TextFieldWithButtonLayout } from '../../UI/Layout'; import RaisedButtonWithSplitMenu from '../../UI/RaisedButtonWithSplitMenu'; @@ -57,9 +57,10 @@ export default React.forwardRef( const isOnline = useOnlineStatus(); const leaderboards = useFetchLeaderboards(); const [isAdminOpen, setIsAdminOpen] = React.useState(false); - const inputFieldRef = React.useRef( - null - ); + const inputFieldRef = React.useRef(null); React.useImperativeHandle(ref, () => ({ focus: () => { if (inputFieldRef.current) { diff --git a/newIDE/app/src/EventsSheet/ParameterFields/MouseField.js b/newIDE/app/src/EventsSheet/ParameterFields/MouseField.js index 74be1d150..6db3a5e1f 100644 --- a/newIDE/app/src/EventsSheet/ParameterFields/MouseField.js +++ b/newIDE/app/src/EventsSheet/ParameterFields/MouseField.js @@ -4,11 +4,11 @@ import { t } from '@lingui/macro'; import { type ParameterFieldProps } from './ParameterFieldCommons'; import { type ParameterInlineRendererProps } from './ParameterInlineRenderer.flow'; import React, { Component } from 'react'; -import SelectField from '../../UI/SelectField'; +import SelectField, { type SelectFieldInterface } from '../../UI/SelectField'; import SelectOption from '../../UI/SelectOption'; export default class MouseField extends Component { - _field: ?SelectField; + _field: ?SelectFieldInterface; focus() { if (this._field) this._field.focus(); diff --git a/newIDE/app/src/EventsSheet/ParameterFields/OperatorField.js b/newIDE/app/src/EventsSheet/ParameterFields/OperatorField.js index 4a75fc9b2..79cdc932b 100644 --- a/newIDE/app/src/EventsSheet/ParameterFields/OperatorField.js +++ b/newIDE/app/src/EventsSheet/ParameterFields/OperatorField.js @@ -4,7 +4,7 @@ import { t } from '@lingui/macro'; import React, { Component } from 'react'; import { type ParameterInlineRendererProps } from './ParameterInlineRenderer.flow'; import { type ParameterFieldProps } from './ParameterFieldCommons'; -import SelectField from '../../UI/SelectField'; +import SelectField, { type SelectFieldInterface } from '../../UI/SelectField'; import SelectOption from '../../UI/SelectOption'; const operatorLabels = { @@ -23,7 +23,7 @@ const mapTypeToOperators = { }; export default class OperatorField extends Component { - _field: ?SelectField; + _field: ?SelectFieldInterface; focus() { if (this._field && this._field.focus) this._field.focus(); } diff --git a/newIDE/app/src/EventsSheet/ParameterFields/RelationalOperatorField.js b/newIDE/app/src/EventsSheet/ParameterFields/RelationalOperatorField.js index 16721ca30..dfce89dd9 100644 --- a/newIDE/app/src/EventsSheet/ParameterFields/RelationalOperatorField.js +++ b/newIDE/app/src/EventsSheet/ParameterFields/RelationalOperatorField.js @@ -4,7 +4,7 @@ import { t } from '@lingui/macro'; import React, { Component } from 'react'; import { type ParameterInlineRendererProps } from './ParameterInlineRenderer.flow'; import { type ParameterFieldProps } from './ParameterFieldCommons'; -import SelectField from '../../UI/SelectField'; +import SelectField, { type SelectFieldInterface } from '../../UI/SelectField'; import SelectOption from '../../UI/SelectOption'; const operatorLabels = { @@ -25,7 +25,7 @@ const mapTypeToOperators: { [string]: Array } = { }; export default class RelationalOperatorField extends Component { - _field: ?SelectField; + _field: ?SelectFieldInterface; focus() { if (this._field && this._field.focus) this._field.focus(); } diff --git a/newIDE/app/src/UI/SelectField.js b/newIDE/app/src/UI/SelectField.js index 1fbd8f925..94c540995 100644 --- a/newIDE/app/src/UI/SelectField.js +++ b/newIDE/app/src/UI/SelectField.js @@ -41,6 +41,8 @@ type Props = {| hintText?: MessageDescriptor, |}; +export type SelectFieldInterface = {| focus: () => void |}; + const INVALID_VALUE = ''; const stopPropagation = event => event.stopPropagation(); @@ -48,15 +50,18 @@ const stopPropagation = event => event.stopPropagation(); * A select field based on Material-UI select field. * To be used with `SelectOption`. */ -export default class SelectField extends React.Component { - _input = React.createRef(); +const SelectField = React.forwardRef( + (props, ref) => { + const inputRef = React.useRef(null); - focus() { - if (this._input.current) this._input.current.focus(); - } + const focus = () => { + if (inputRef.current) inputRef.current.focus(); + }; + + React.useImperativeHandle(ref, () => ({ + focus, + })); - render() { - const { props } = this; const onChange = props.onChange || undefined; // Dig into children props to see if the current value is valid or not. @@ -108,7 +113,7 @@ export default class SelectField extends React.Component { native: true, }} style={props.style} - inputRef={this._input} + inputRef={inputRef} > {!hasValidValue ? (