diff --git a/app/screens/apps_form/__snapshots__/apps_form_component.test.tsx.snap b/app/screens/apps_form/__snapshots__/apps_form_component.test.tsx.snap
new file mode 100644
index 000000000..74a3b9b9c
--- /dev/null
+++ b/app/screens/apps_form/__snapshots__/apps_form_component.test.tsx.snap
@@ -0,0 +1,349 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AppsForm should set match snapshot 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/app/screens/apps_form/apps_form_component.test.tsx b/app/screens/apps_form/apps_form_component.test.tsx
new file mode 100644
index 000000000..b6b6f7d98
--- /dev/null
+++ b/app/screens/apps_form/apps_form_component.test.tsx
@@ -0,0 +1,137 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import {ShallowWrapper} from 'enzyme';
+import React from 'react';
+import {shallowWithIntl} from 'test/intl-test-helper';
+
+import Preferences from '@mm-redux/constants/preferences';
+
+import AppsFormComponent, {Props, State} from './apps_form_component';
+
+describe('AppsForm', () => {
+ const baseProps: Props = {
+ actions: {
+ performLookupCall: jest.fn(),
+ refreshOnSelect: jest.fn(),
+ submit: jest.fn(),
+ },
+ call: {
+ context: {
+ app_id: 'app1',
+ },
+ path: '/create',
+ },
+ componentId: '',
+ form: {
+ title: 'Title',
+ footer: 'Footer',
+ header: 'Header',
+ icon: 'Icon',
+ submit_buttons: 'submit_buttons1',
+ fields: [
+ {
+ name: 'bool1',
+ type: 'bool',
+ },
+ {
+ name: 'bool2',
+ type: 'bool',
+ value: false,
+ },
+ {
+ name: 'bool3',
+ type: 'bool',
+ value: true,
+ },
+ {
+ name: 'text1',
+ type: 'text',
+ value: 'initial text',
+ },
+ {
+ name: 'select1',
+ type: 'static_select',
+ options: [
+ {label: 'Label1', value: 'Value1'},
+ {label: 'Label2', value: 'Value2'},
+ ],
+ value: {label: 'Label1', value: 'Value1'},
+ },
+ {
+ name: 'submit_buttons1',
+ type: 'static_select',
+ options: [
+ {label: 'Label3', value: 'Value3'},
+ {label: 'Label4', value: 'Value4'},
+ ],
+ value: null,
+ },
+
+ ],
+ },
+ theme: Preferences.THEMES.default,
+ };
+
+ test('should set match snapshot', () => {
+ const wrapper: ShallowWrapper = shallowWithIntl(
+ ,
+ ) as unknown as ShallowWrapper;
+
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ test('should set initial form values', () => {
+ const wrapper: ShallowWrapper = shallowWithIntl(
+ ,
+ ) as unknown as ShallowWrapper;
+
+ expect(wrapper.state().values).toEqual({
+ bool1: false,
+ bool2: false,
+ bool3: true,
+ text1: 'initial text',
+ select1: {label: 'Label1', value: 'Value1'},
+ submit_buttons1: null,
+ });
+ });
+
+ test('it should submit and close the modal', async () => {
+ const submit = jest.fn().mockResolvedValue({data: {type: 'ok'}});
+
+ const props: Props = {
+ ...baseProps,
+ actions: {
+ ...baseProps.actions,
+ submit,
+ },
+ };
+
+ const wrapper: ShallowWrapper = shallowWithIntl(
+ ,
+ ) as unknown as ShallowWrapper;
+
+ const hide = jest.fn();
+ wrapper.instance().handleHide = hide;
+
+ await wrapper.instance().doSubmit();
+
+ expect(submit).toHaveBeenCalledWith({
+ values: {
+ bool1: false,
+ bool2: false,
+ bool3: true,
+ text1: 'initial text',
+ select1: {label: 'Label1', value: 'Value1'},
+ submit_buttons1: null,
+ },
+ });
+ expect(hide).toHaveBeenCalled();
+ });
+});
diff --git a/app/screens/apps_form/apps_form_component.tsx b/app/screens/apps_form/apps_form_component.tsx
index 3edde4fa7..419248f19 100644
--- a/app/screens/apps_form/apps_form_component.tsx
+++ b/app/screens/apps_form/apps_form_component.tsx
@@ -7,16 +7,16 @@ import {ScrollView, Text, View} from 'react-native';
import Button from 'react-native-button';
import {EventSubscription, Navigation} from 'react-native-navigation';
import {SafeAreaView} from 'react-native-safe-area-context';
+import {DoAppCallResult} from 'types/actions/apps';
import {dismissModal} from '@actions/navigation';
import Markdown from '@components/markdown';
import StatusBar from '@components/status_bar';
-import {AppCallResponseTypes} from '@mm-redux/constants/apps';
+import {AppCallResponseTypes, AppFieldTypes} from '@mm-redux/constants/apps';
import {AppCallRequest, AppField, AppForm, AppFormValue, AppFormValues, AppLookupResponse, AppSelectOption, FormResponseData} from '@mm-redux/types/apps';
import {DialogElement} from '@mm-redux/types/integrations';
import {Theme} from '@mm-redux/types/preferences';
import {checkDialogElementForError, checkIfErrorsMatchElements} from '@mm-redux/utils/integration_utils';
-import {DoAppCallResult} from '@mm-types/actions/apps';
import {getMarkdownBlockStyles, getMarkdownTextStyles} from '@utils/markdown';
import {preventDoubleTap} from '@utils/tap';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
@@ -31,9 +31,7 @@ export type Props = {
form: AppForm;
actions: {
submit: (submission: {
- values: {
- [name: string]: string;
- };
+ values: AppFormValues;
}) => Promise>;
performLookupCall: (field: AppField, values: AppFormValues, userInput: string) => Promise>;
refreshOnSelect: (field: AppField, values: AppFormValues, value: AppFormValue) => Promise>;
@@ -42,18 +40,23 @@ export type Props = {
componentId: string;
}
-type State = {
- values: {[name: string]: string};
+export type State = {
+ values: AppFormValues;
formError: string | null;
fieldErrors: {[name: string]: string};
form: AppForm;
}
-const initFormValues = (form: AppForm): {[name: string]: string} => {
- const values: {[name: string]: any} = {};
+const initFormValues = (form: AppForm): AppFormValues => {
+ const values: AppFormValues = {};
if (form && form.fields) {
form.fields.forEach((f) => {
- values[f.name] = f.value || null;
+ let defaultValue: AppFormValue = null;
+ if (f.type === AppFieldTypes.BOOL) {
+ defaultValue = false;
+ }
+
+ values[f.name] = f.value || defaultValue;
});
}