diff --git a/webapp/channels/src/components/admin_console/__snapshots__/bleve_settings.test.tsx.snap b/webapp/channels/src/components/admin_console/__snapshots__/bleve_settings.test.tsx.snap
index d2ac779815..9e7b8a87f9 100644
--- a/webapp/channels/src/components/admin_console/__snapshots__/bleve_settings.test.tsx.snap
+++ b/webapp/channels/src/components/admin_console/__snapshots__/bleve_settings.test.tsx.snap
@@ -76,7 +76,6 @@ exports[`components/BleveSettings should match snapshot, disabled 1`] = `
}
onChange={[Function]}
setByEnv={false}
- type="input"
value=""
/>
{
onChange={this.handleSettingChanged}
setByEnv={this.isSetByEnv('BleveSettings.IndexDir')}
disabled={this.props.isDisabled}
- type='input'
/>
@@ -2797,7 +2790,6 @@ exports[`components/PluginManagement should match snapshot, text entered into th
}
onChange={[Function]}
setByEnv={false}
- type="input"
value="marketplace.example.com"
/>
{
/>
{
onChange={this.handleChange}
disabled={this.props.isDisabled || this.state.pushNotificationServerType !== PUSH_NOTIFICATIONS_CUSTOM}
setByEnv={this.isSetByEnv('EmailSettings.PushNotificationServer')}
- type='input'
/>
{
test('render component with required props', () => {
- const onChange = jest.fn();
renderWithIntl(
,
);
screen.getByText('some label', {exact: false});
- expect(screen.getByTestId('string.idinput')).toHaveProperty('id', 'string.id');
- expect(screen.getByTestId('string.idinput')).toHaveValue('some value');
+ expect(screen.getByTestId('some.idinput')).toHaveProperty('id', 'some.id');
+ expect(screen.getByTestId('some.idinput')).toHaveValue('some value');
});
});
diff --git a/webapp/channels/src/components/admin_console/text_setting.tsx b/webapp/channels/src/components/admin_console/text_setting.tsx
index e1b1a8ee02..f83c85aece 100644
--- a/webapp/channels/src/components/admin_console/text_setting.tsx
+++ b/webapp/channels/src/components/admin_console/text_setting.tsx
@@ -3,7 +3,7 @@
import React from 'react';
-import TextSetting, {WidgetTextSettingProps} from 'components/widgets/settings/text_setting';
+import TextSetting, {Props as WidgetTextSettingProps} from 'components/widgets/settings/text_setting';
import SetByEnv from './set_by_env';
diff --git a/webapp/channels/src/components/apps_form/apps_form_field/apps_form_field.test.tsx b/webapp/channels/src/components/apps_form/apps_form_field/apps_form_field.test.tsx
index 9e806be6bc..8bb10fb750 100644
--- a/webapp/channels/src/components/apps_form/apps_form_field/apps_form_field.test.tsx
+++ b/webapp/channels/src/components/apps_form/apps_form_field/apps_form_field.test.tsx
@@ -8,8 +8,6 @@ import {AppField} from '@mattermost/types/apps';
import TextSetting from 'components/widgets/settings/text_setting';
-import Markdown from 'components/markdown';
-
import AppsFormField, {Props} from './apps_form_field';
import AppsFormSelectField from './apps_form_select_field';
@@ -37,23 +35,6 @@ describe('components/apps_form/apps_form_field/AppsFormField', () => {
performLookup: jest.fn(),
};
- const baseTextSettingProps = {
- inputClassName: '',
- label: (
-
- {textField.modal_label}
- {false}
-
- ),
- maxLength: 100,
- placeholder: 'The hint',
- resizable: false,
- type: 'input',
- value: '',
- id: baseDialogTextProps.name,
- helpText: ( ),
- };
-
it('subtype blank - optional field', () => {
const wrapper = shallow(
{
}}
/>,
);
- expect(wrapper.matchesElement(
-
- {textField.modal_label}
- {{' (optional)'} }
-
- )}
- type='input'
- />,
- )).toEqual(true);
+
+ expect(wrapper.find(TextSetting).props().type).toEqual('text');
});
it('subtype blank', () => {
@@ -86,12 +57,7 @@ describe('components/apps_form/apps_form_field/AppsFormField', () => {
/>,
);
- expect(wrapper.matchesElement(
- ,
- )).toEqual(true);
+ expect(wrapper.find(TextSetting).props().type).toEqual('text');
});
it('subtype email', () => {
@@ -104,30 +70,8 @@ describe('components/apps_form/apps_form_field/AppsFormField', () => {
}}
/>,
);
- expect(wrapper.matchesElement(
- ,
- )).toEqual(true);
- });
- it('subtype invalid', () => {
- const wrapper = shallow(
- ,
- );
- expect(wrapper.matchesElement(
- ,
- )).toEqual(true);
+ expect(wrapper.find(TextSetting).props().type).toEqual('email');
});
it('subtype password', () => {
@@ -140,12 +84,8 @@ describe('components/apps_form/apps_form_field/AppsFormField', () => {
}}
/>,
);
- expect(wrapper.matchesElement(
- ,
- )).toEqual(true);
+
+ expect(wrapper.find(TextSetting).props().type).toEqual('password');
});
});
diff --git a/webapp/channels/src/components/apps_form/apps_form_field/apps_form_field.tsx b/webapp/channels/src/components/apps_form/apps_form_field/apps_form_field.tsx
index 5f6f399861..f55c098707 100644
--- a/webapp/channels/src/components/apps_form/apps_form_field/apps_form_field.tsx
+++ b/webapp/channels/src/components/apps_form/apps_form_field/apps_form_field.tsx
@@ -108,18 +108,13 @@ export default class AppsFormField extends React.PureComponent {
}
}
- let textType: InputTypes = 'input';
- if (subtype && TextSetting.validTypes.includes(subtype)) {
- textType = subtype as InputTypes;
- }
-
const textValue = value as string;
return (
{
},
onChange: jest.fn(),
};
- const baseTextSettingProps = {
- id: baseDialogProps.name,
- maxLength: 100,
- resizable: false,
- value: '',
- label: (
-
- {baseDialogProps.displayName}
- {' *'}
-
- ),
- };
+
it('subtype blank', () => {
const wrapper = shallow(
{
subtype=''
/>,
);
- expect(wrapper.matchesElement(
- ,
- )).toEqual(true);
+
+ expect(wrapper.find(TextSetting).props().type).toEqual('text');
});
it('subtype email', () => {
@@ -55,27 +40,7 @@ describe('components/interactive_dialog/DialogElement', () => {
subtype='email'
/>,
);
- expect(wrapper.matchesElement(
- ,
- )).toEqual(true);
- });
-
- it('subtype invalid', () => {
- const wrapper = shallow(
- ,
- );
- expect(wrapper.matchesElement(
- ,
- )).toEqual(true);
+ expect(wrapper.find(TextSetting).props().type).toEqual('email');
});
it('subtype password', () => {
@@ -85,12 +50,7 @@ describe('components/interactive_dialog/DialogElement', () => {
subtype='password'
/>,
);
- expect(wrapper.matchesElement(
- ,
- )).toEqual(true);
+ expect(wrapper.find(TextSetting).props().type).toEqual('password');
});
describe('radioSetting', () => {
diff --git a/webapp/channels/src/components/interactive_dialog/dialog_element/dialog_element.tsx b/webapp/channels/src/components/interactive_dialog/dialog_element/dialog_element.tsx
index 8e67144eb0..30ecd7b2f6 100644
--- a/webapp/channels/src/components/interactive_dialog/dialog_element/dialog_element.tsx
+++ b/webapp/channels/src/components/interactive_dialog/dialog_element/dialog_element.tsx
@@ -116,10 +116,10 @@ export default class DialogElement extends React.PureComponent {
errorText,
optional,
options,
+ type,
+ maxLength,
} = this.props;
- let {type, maxLength} = this.props;
-
let displayNameContent: React.ReactNode = displayName;
if (optional) {
displayNameContent = (
@@ -155,16 +155,11 @@ export default class DialogElement extends React.PureComponent {
}
if (type === 'text' || type === 'textarea') {
+ let textSettingMaxLength;
if (type === 'text') {
- maxLength = maxLength || TEXT_DEFAULT_MAX_LENGTH;
-
- if (subtype && TextSetting.validTypes.includes(subtype)) {
- type = subtype;
- } else {
- type = 'input';
- }
+ textSettingMaxLength = maxLength || TEXT_DEFAULT_MAX_LENGTH;
} else {
- maxLength = maxLength || TEXTAREA_DEFAULT_MAX_LENGTH;
+ textSettingMaxLength = maxLength || TEXTAREA_DEFAULT_MAX_LENGTH;
}
const textValue = value as string;
@@ -172,9 +167,9 @@ export default class DialogElement extends React.PureComponent {
+
+
+`;
+
+exports[`components/widgets/settings/TextSetting render with textarea type 1`] = `
+
+
+
+`;
diff --git a/webapp/channels/src/components/widgets/settings/text_setting.test.tsx b/webapp/channels/src/components/widgets/settings/text_setting.test.tsx
index cb757fc577..8605d7558c 100644
--- a/webapp/channels/src/components/widgets/settings/text_setting.test.tsx
+++ b/webapp/channels/src/components/widgets/settings/text_setting.test.tsx
@@ -17,24 +17,8 @@ describe('components/widgets/settings/TextSetting', () => {
onChange={onChange}
/>,
);
- expect(wrapper).toMatchInlineSnapshot(`
-
-
-
- `);
+
+ expect(wrapper).toMatchSnapshot();
});
test('render with textarea type', () => {
@@ -48,26 +32,8 @@ describe('components/widgets/settings/TextSetting', () => {
onChange={onChange}
/>,
);
- expect(wrapper).toMatchInlineSnapshot(`
-
-
-
- `);
+
+ expect(wrapper).toMatchSnapshot();
});
test('onChange', () => {
diff --git a/webapp/channels/src/components/widgets/settings/text_setting.tsx b/webapp/channels/src/components/widgets/settings/text_setting.tsx
index 0310e9c3f3..b963fe5a11 100644
--- a/webapp/channels/src/components/widgets/settings/text_setting.tsx
+++ b/webapp/channels/src/components/widgets/settings/text_setting.tsx
@@ -1,108 +1,95 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
-import React from 'react';
+import React, {ChangeEvent, ReactNode} from 'react';
import Setting from './setting';
-export type InputTypes = 'input' | 'textarea' | 'number' | 'email' | 'tel' | 'url' | 'password'
+const INPUT_TYPES = ['text', 'textarea', 'number', 'email', 'tel', 'url', 'password'] as const;
+export type InputTypes = typeof INPUT_TYPES[number];
-export type WidgetTextSettingProps = {
+export type Props = {
id: string;
- label: React.ReactNode;
+ label: ReactNode;
labelClassName?: string;
placeholder?: string;
- helpText?: React.ReactNode;
- footer?: React.ReactNode;
+ helpText?: ReactNode;
+ footer?: ReactNode;
value: string | number;
inputClassName?: string;
maxLength?: number;
resizable?: boolean;
- onChange(name: string, value: any): void;
+ onChange(id: string, value: any): void;
disabled?: boolean;
- type: InputTypes;
+
+ // This is a custom prop that is not part of the HTML input element type
+ type?: InputTypes;
autoFocus?: boolean;
}
-// Since handle change is read from input and textarea element
-type HandleChangeTypes = React.ChangeEventHandler
+function TextSetting(props: Props) {
+ const {labelClassName = '', inputClassName = '', maxLength = -1, resizable = true, type = 'text'} = props;
-export default class TextSetting extends React.PureComponent {
- public static validTypes: string[] = ['input', 'textarea', 'number', 'email', 'tel', 'url', 'password'];
-
- public static defaultProps: Partial = {
- labelClassName: '',
- inputClassName: '',
- type: 'input',
- maxLength: -1, // A negative number allows for values of any length
- resizable: true,
- };
-
- private handleChange: HandleChangeTypes = (e) => {
- if (this.props.type === 'number') {
- this.props.onChange(this.props.id, parseInt(e.target.value, 10));
+ function handleChange(event: ChangeEvent) {
+ if (props.type === 'number') {
+ props.onChange(props.id, parseInt(event.target.value, 10));
} else {
- this.props.onChange(this.props.id, e.target.value);
+ props.onChange(props.id, event.target.value);
}
- };
+ }
- public render(): JSX.Element {
- const {resizable} = this.props;
- let {type} = this.props;
- let input = null;
+ let input = null;
+ if (type === 'textarea') {
+ input = (
+
+ );
+ } else {
+ const inputType = INPUT_TYPES.includes(type) ? type : 'text';
- if (type === 'textarea') {
- let style = {};
- if (!resizable) {
- style = Object.assign({}, {resize: 'none'});
- }
+ // a lot of our e2e test rely on 'input' being in the test id if it's a text/textarea input
+ const testId = inputType === 'text' ? `${props.id}input` : `${props.id}${inputType}`;
- input = (
-
- );
- } else {
- type = ['input', 'email', 'tel', 'number', 'url', 'password'].includes(type) ? type : 'input';
-
- input = (
-
- );
- }
-
- return (
-
- {input}
-
+ input = (
+
);
}
+
+ return (
+
+ {input}
+
+ );
}
+
+export default TextSetting;