diff --git a/ui/src/components/BaseFormView/BaseFormConfigMock.ts b/ui/src/components/BaseFormView/BaseFormConfigMock.ts index 7571fbdbb..f5fd0f352 100644 --- a/ui/src/components/BaseFormView/BaseFormConfigMock.ts +++ b/ui/src/components/BaseFormView/BaseFormConfigMock.ts @@ -176,6 +176,115 @@ export function getGlobalConfigMockCustomControl() { return GlobalConfigSchema.parse(globalConfigMockCustomControl); } +const getGlobalConfigMockGroups = ({ + entitiesConfig, + entityGroupsConfig, + entitiesInputs, + entityGroupsInputs, +}: { + entitiesConfig?: z.input[]; + entityGroupsConfig?: typeof GROUPS_FOR_EXAMPLE_ENTITIES; + entitiesInputs?: z.input[]; + entityGroupsInputs?: typeof GROUPS_FOR_EXAMPLE_ENTITIES; +}) => + ({ + pages: { + configuration: { + tabs: [ + { + name: 'account', + table: { + actions: ['edit', 'delete', 'clone'], + header: [ + { + label: 'Name', + field: 'name', + }, + ], + }, + entity: [ + { + type: 'text', + label: 'Name', + validators: [ + { + type: 'regex', + errorMsg: + 'Account Name must begin with a letter and consist exclusively of alphanumeric characters and underscores.', + pattern: '^[a-zA-Z]\\w*$', + }, + ], + field: 'name', + help: 'A unique name for the account.', + required: true, + }, + ...(entitiesConfig || []), + ], + groups: entityGroupsConfig, + title: 'Accounts', + }, + ], + title: 'Configuration', + description: 'Set up your add-on', + }, + inputs: { + services: [ + { + name: 'demo_input', + entity: [ + { + type: 'text', + label: 'Name', + validators: [ + { + type: 'regex', + errorMsg: + 'Input Name must begin with a letter and consist exclusively of alphanumeric characters and underscores.', + pattern: '^[a-zA-Z]\\w*$', + }, + { + type: 'string', + errorMsg: + 'Length of input name should be between 1 and 100', + minLength: 1, + maxLength: 100, + }, + ], + field: 'name', + help: 'A unique name for the data input.', + required: true, + encrypted: false, + }, + ...(entitiesInputs || []), + ], + groups: entityGroupsInputs, + title: 'demo_input', + }, + ], + title: 'Inputs', + description: 'Manage your data inputs', + table: { + actions: ['edit', 'delete', 'clone'], + header: [ + { + label: 'Name', + field: 'name', + }, + ], + }, + }, + }, + meta: { + name: 'demo_addon_for_splunk', + restRoot: 'demo_addon_for_splunk', + version: '5.31.1R85f0e18e', + displayName: 'Demo Add-on for Splunk', + schemaVersion: '0.0.3', + checkForUpdates: false, + searchViewDefault: false, + }, + } satisfies z.input); + const EXAMPLE_GROUPS_ENTITIES = [ { type: 'text', @@ -238,171 +347,105 @@ const GROUPS_FOR_EXAMPLE_ENTITIES = [ }, ]; -const globalConfigMockGroupsForConfigPage = { - pages: { - configuration: { - tabs: [ - { - name: 'account', - table: { - actions: ['edit', 'delete', 'clone'], - header: [ - { - label: 'Name', - field: 'name', - }, - ], - }, - entity: [ - { - type: 'text', - label: 'Name', - validators: [ - { - type: 'regex', - errorMsg: - 'Account Name must begin with a letter and consist exclusively of alphanumeric characters and underscores.', - pattern: '^[a-zA-Z]\\w*$', - }, - ], - field: 'name', - help: 'A unique name for the account.', - required: true, - }, - ...EXAMPLE_GROUPS_ENTITIES, - ], - groups: GROUPS_FOR_EXAMPLE_ENTITIES, - title: 'Accounts', - }, - ], - title: 'Configuration', - description: 'Set up your add-on', - }, - inputs: { - services: [], - title: 'Inputs', - description: 'Manage your data inputs', - table: { - actions: ['edit', 'delete', 'clone'], - header: [ - { - label: 'Name', - field: 'name', - }, - ], - }, - }, - }, - meta: { - name: 'demo_addon_for_splunk', - restRoot: 'demo_addon_for_splunk', - version: '5.31.1R85f0e18e', - displayName: 'Demo Add-on for Splunk', - schemaVersion: '0.0.3', - checkForUpdates: false, - searchViewDefault: false, - }, -} satisfies z.input; - export function getGlobalConfigMockGroupsForConfigPage(): GlobalConfig { - return GlobalConfigSchema.parse(globalConfigMockGroupsForConfigPage); + return GlobalConfigSchema.parse( + getGlobalConfigMockGroups({ + entitiesConfig: EXAMPLE_GROUPS_ENTITIES, + entityGroupsConfig: GROUPS_FOR_EXAMPLE_ENTITIES, + }) + ); } -const globalConfigMockGroupsForInputPage = { - pages: { - configuration: { - tabs: [ - { - name: 'account', - table: { - actions: ['edit', 'delete', 'clone'], - header: [ - { - label: 'Name', - field: 'name', - }, - ], - }, - entity: [ - { - type: 'text', - label: 'Name', - validators: [ - { - type: 'regex', - errorMsg: - 'Account Name must begin with a letter and consist exclusively of alphanumeric characters and underscores.', - pattern: '^[a-zA-Z]\\w*$', - }, - ], - field: 'name', - help: 'A unique name for the account.', - required: true, +export function getGlobalConfigMockGroupsForInputPage(): GlobalConfig { + return GlobalConfigSchema.parse( + getGlobalConfigMockGroups({ + entitiesInputs: EXAMPLE_GROUPS_ENTITIES, + entityGroupsInputs: GROUPS_FOR_EXAMPLE_ENTITIES, + }) + ); +} + +const GROUP_ENTITIES_MODIFICATIONS = [ + { + type: 'text', + label: 'Text 1 Group 2', + field: 'text_field_1_group_2', + required: false, + modifyFieldsOnValue: [ + { + fieldValue: '[[any_other_value]]', + fieldsToModify: [ + { + fieldId: 'text_field_2_group_2', + disabled: false, + required: false, + help: 'help after mods 2-2', + label: 'label after mods 2-2', + markdownMessage: { + text: 'markdown message after mods 2-2', }, - ], - title: 'Accounts', - }, - ], - title: 'Configuration', - description: 'Set up your add-on', - }, - inputs: { - services: [ - { - name: 'demo_input', - entity: [ - { - type: 'text', - label: 'Name', - validators: [ - { - type: 'regex', - errorMsg: - 'Input Name must begin with a letter and consist exclusively of alphanumeric characters and underscores.', - pattern: '^[a-zA-Z]\\w*$', - }, - { - type: 'string', - errorMsg: 'Length of input name should be between 1 and 100', - minLength: 1, - maxLength: 100, - }, - ], - field: 'name', - help: 'A unique name for the data input.', - required: true, - encrypted: false, + }, + { + fieldId: 'text_field_2_group_1', + disabled: false, + required: true, + help: 'help after mods 2-1', + label: 'label after mods 2-1', + markdownMessage: { + text: 'markdown message after mods 2-1', }, - ...EXAMPLE_GROUPS_ENTITIES, - ], - groups: GROUPS_FOR_EXAMPLE_ENTITIES, - title: 'demo_input', - }, - ], - title: 'Inputs', - description: 'Manage your data inputs', - table: { - actions: ['edit', 'delete', 'clone'], - header: [ + }, { - label: 'Name', - field: 'name', + fieldId: 'text_field_1_group_1', + disabled: true, }, ], }, + ], + }, + { + type: 'text', + label: 'Text 2 Group 2', + field: 'text_field_2_group_2', + required: false, + }, + { + type: 'text', + label: 'Text 1 Group 1', + field: 'text_field_1_group_1', + required: false, + }, + { + type: 'text', + label: 'Text 2 Group 1', + field: 'text_field_2_group_1', + required: false, + options: { + enable: false, }, }, - meta: { - name: 'demo_addon_for_splunk', - restRoot: 'demo_addon_for_splunk', - version: '5.31.1R85f0e18e', - displayName: 'Demo Add-on for Splunk', - schemaVersion: '0.0.3', - checkForUpdates: false, - searchViewDefault: false, + { + type: 'text', + label: 'Text 1 Group 3', + field: 'text_field_1_group_3', + required: false, + options: { + enable: false, + }, }, -} satisfies z.input; + { + type: 'text', + label: 'Text 2 Group 3', + field: 'text_field_2_group_3', + required: false, + }, +] satisfies z.input[]; -export function getGlobalConfigMockGroupsFoInputPage(): GlobalConfig { - return GlobalConfigSchema.parse(globalConfigMockGroupsForInputPage); +export function getGlobalConfigMockModificationToGroupsConfig(): GlobalConfig { + return GlobalConfigSchema.parse( + getGlobalConfigMockGroups({ + entitiesConfig: GROUP_ENTITIES_MODIFICATIONS, + entityGroupsConfig: GROUPS_FOR_EXAMPLE_ENTITIES, + }) + ); } diff --git a/ui/src/components/BaseFormView/BaseFormView.test.tsx b/ui/src/components/BaseFormView/BaseFormView.test.tsx index ac05b2ec3..533c388aa 100644 --- a/ui/src/components/BaseFormView/BaseFormView.test.tsx +++ b/ui/src/components/BaseFormView/BaseFormView.test.tsx @@ -9,7 +9,7 @@ import { getBuildDirPath } from '../../util/script'; import mockCustomControlMockForTest from '../CustomControl/CustomControlMockForTest'; import { getGlobalConfigMockCustomControl, - getGlobalConfigMockGroupsFoInputPage, + getGlobalConfigMockGroupsForInputPage, getGlobalConfigMockGroupsForConfigPage, } from './BaseFormConfigMock'; @@ -97,7 +97,7 @@ it.each([ }, { page: 'inputs' as const, - config: getGlobalConfigMockGroupsFoInputPage(), + config: getGlobalConfigMockGroupsForInputPage(), service: 'demo_input', }, ])('entities grouping for page works properly %s', async ({ config, page, service }) => { diff --git a/ui/src/components/BaseFormView/BaseFormView.tsx b/ui/src/components/BaseFormView/BaseFormView.tsx index b5189c01e..d74fd788e 100644 --- a/ui/src/components/BaseFormView/BaseFormView.tsx +++ b/ui/src/components/BaseFormView/BaseFormView.tsx @@ -1259,6 +1259,7 @@ class BaseFormView extends PureComponent { this.entities?.map((e) => { if (e.field === fieldName) { const temState = this.state?.data?.[e.field]; + return ( { markdownMessage={temState?.markdownMessage} dependencyValues={temState?.dependencyValues || null} page={this.props.page} + fileNameToDisplay={temState.fileNameToDisplay} + modifiedEntitiesData={temState.modifiedEntitiesData} /> ); } diff --git a/ui/src/components/BaseFormView/BaseFormViewGrups.test.tsx b/ui/src/components/BaseFormView/BaseFormViewGrups.test.tsx new file mode 100644 index 000000000..bd7d0bea6 --- /dev/null +++ b/ui/src/components/BaseFormView/BaseFormViewGrups.test.tsx @@ -0,0 +1,66 @@ +import { render, screen, within } from '@testing-library/react'; +import React from 'react'; + +import { setUnifiedConfig } from '../../util/util'; +import BaseFormView from './BaseFormView'; +import { getGlobalConfigMockModificationToGroupsConfig } from './BaseFormConfigMock'; + +const handleFormSubmit = jest.fn(); + +const PAGE_CONF = 'configuration'; +const SERVICE_NAME = 'account'; +const STANZA_NAME = 'stanzaName'; + +it('should modify correctly all properties of field in groups', async () => { + const mockConfig = getGlobalConfigMockModificationToGroupsConfig(); + setUnifiedConfig(mockConfig); + render( + + ); + await screen.findByText('Text 1 Group 2'); + + const getAndValidateGroupFieldLabels = ( + fieldId: string, + label: string, + help: string, + markdownMsg: string + ) => { + const modifiedFieldSameGroup = document.querySelector( + `[data-name="${fieldId}"]` + ) as HTMLElement; + + expect(modifiedFieldSameGroup).toBeInTheDocument(); + + expect(within(modifiedFieldSameGroup).getByTestId('help')).toHaveTextContent(label); + expect(within(modifiedFieldSameGroup).getByTestId('label')).toHaveTextContent(help); + expect(within(modifiedFieldSameGroup).getByTestId('msg-markdown')).toHaveTextContent( + markdownMsg + ); + return modifiedFieldSameGroup; + }; + + const modifiedFieldSameGroup = getAndValidateGroupFieldLabels( + 'text_field_2_group_1', + 'help after mods 2-1', + 'label after mods 2-1', + 'markdown message after mods 2-1' + ); + + expect(within(modifiedFieldSameGroup).queryByText('*')).toBeInTheDocument(); + + const modifiedFieldDiffGroup = getAndValidateGroupFieldLabels( + 'text_field_2_group_2', + 'help after mods 2-2', + 'label after mods 2-2', + 'markdown message after mods 2-2' + ); + + expect(within(modifiedFieldDiffGroup).queryByText('*')).not.toBeInTheDocument(); +}); diff --git a/ui/src/components/BaseFormView/stories/BaseFormView.stories.tsx b/ui/src/components/BaseFormView/stories/BaseFormView.stories.tsx index 5fdb655cb..43b7d1c5e 100644 --- a/ui/src/components/BaseFormView/stories/BaseFormView.stories.tsx +++ b/ui/src/components/BaseFormView/stories/BaseFormView.stories.tsx @@ -13,8 +13,9 @@ import { Mode } from '../../../constants/modes'; import { BaseFormProps } from '../../../types/components/BaseFormTypes'; import { Platforms } from '../../../types/globalConfig/pages'; import { - getGlobalConfigMockGroupsFoInputPage, + getGlobalConfigMockGroupsForInputPage, getGlobalConfigMockGroupsForConfigPage, + getGlobalConfigMockModificationToGroupsConfig, } from '../BaseFormConfigMock'; interface BaseFormStoriesProps extends BaseFormProps { @@ -125,7 +126,20 @@ export const InputPageGroups: Story = { page: 'inputs', stanzaName: 'unknownStanza', handleFormSubmit: fn(), - config: getGlobalConfigMockGroupsFoInputPage(), + config: getGlobalConfigMockGroupsForInputPage(), + platform: 'cloud', + }, +}; + +export const GroupModificationsConfig: Story = { + args: { + currentServiceState: {}, + serviceName: 'account', + mode: 'create' as Mode, + page: 'configuration', + stanzaName: 'unknownStanza', + handleFormSubmit: fn(), + config: getGlobalConfigMockModificationToGroupsConfig(), platform: 'cloud', }, }; diff --git a/ui/src/components/BaseFormView/stories/__images__/BaseFormView-group-modifications-config-chromium.png b/ui/src/components/BaseFormView/stories/__images__/BaseFormView-group-modifications-config-chromium.png new file mode 100644 index 000000000..caeca1a1a --- /dev/null +++ b/ui/src/components/BaseFormView/stories/__images__/BaseFormView-group-modifications-config-chromium.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ba49279f39361f1c139fa1d0f041317a23bda3fb2199ba343d61c3f0393267c1 +size 29733