diff --git a/x-pack/plugins/cases/public/components/custom_fields/index.test.tsx b/x-pack/plugins/cases/public/components/custom_fields/index.test.tsx index 06c5219141a8f..d81e31ba69d6d 100644 --- a/x-pack/plugins/cases/public/components/custom_fields/index.test.tsx +++ b/x-pack/plugins/cases/public/components/custom_fields/index.test.tsx @@ -89,27 +89,17 @@ describe('CustomFields', () => { }); it('shows error when custom fields reaches the limit', async () => { - const customFields = [ - ...customFieldsConfigurationMock, - { - key: 'third_field_key', - label: 'My third custom label', + const generatedMockCustomFields = []; + + for (let i = 0; i < 8; i++) { + generatedMockCustomFields.push({ + key: `field_key_${i + 1}`, + label: `My custom label ${i + 1}`, type: CustomFieldTypes.TEXT, required: false, - }, - { - key: 'fourth_field_key', - label: 'My fourth custom label', - type: CustomFieldTypes.TOGGLE, - required: true, - }, - { - key: 'fifth_field_key', - label: 'My fifth custom label', - type: CustomFieldTypes.TEXT, - required: true, - }, - ]; + }); + } + const customFields = [...customFieldsConfigurationMock, ...generatedMockCustomFields]; appMockRender.render(); diff --git a/x-pack/plugins/cases/server/client/cases/create.test.ts b/x-pack/plugins/cases/server/client/cases/create.test.ts index 2734d257d9408..ae31b77058e1e 100644 --- a/x-pack/plugins/cases/server/client/cases/create.test.ts +++ b/x-pack/plugins/cases/server/client/cases/create.test.ts @@ -496,6 +496,25 @@ describe('create', () => { }); it('should not throw an error and fill out missing customFields when they are undefined', async () => { + casesClient.configure.get = jest.fn().mockResolvedValue([ + { + owner: theCase.owner, + customFields: [ + { + key: 'first_key', + type: CustomFieldTypes.TEXT, + label: 'foo', + required: false, + }, + { + key: 'second_key', + type: CustomFieldTypes.TOGGLE, + label: 'foo', + required: false, + }, + ], + }, + ]); await expect(create({ ...theCase }, clientArgs, casesClient)).resolves.not.toThrow(); expect(clientArgs.services.caseService.postNewCase).toHaveBeenCalledWith( @@ -523,6 +542,34 @@ describe('create', () => { ); }); + it('should throw an error when required customFields are undefined', async () => { + casesClient.configure.get = jest.fn().mockResolvedValue([ + { + owner: theCase.owner, + customFields: [ + { + key: 'first_key', + type: CustomFieldTypes.TEXT, + label: 'foo', + required: true, + }, + { + key: 'second_key', + type: CustomFieldTypes.TOGGLE, + label: 'foo', + required: false, + }, + ], + }, + ]); + + await expect( + create({ ...theCase }, clientArgs, casesClient) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Failed to create case: Error: Missing required custom fields: first_key"` + ); + }); + it('throws error when the customFields array is too long', async () => { await expect( create( @@ -534,7 +581,7 @@ describe('create', () => { casesClient ) ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Failed to create case: Error: The length of the field customFields is too long. Array must be of length <= 5."` + `"Failed to create case: Error: The length of the field customFields is too long. Array must be of length <= 10."` ); }); diff --git a/x-pack/plugins/cases/server/client/cases/update.test.ts b/x-pack/plugins/cases/server/client/cases/update.test.ts index 7589e5c9d09b5..a1427284c3c9a 100644 --- a/x-pack/plugins/cases/server/client/cases/update.test.ts +++ b/x-pack/plugins/cases/server/client/cases/update.test.ts @@ -1068,7 +1068,7 @@ describe('update', () => { casesClient ) ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Failed to update case, ids: [{\\"id\\":\\"mock-id-1\\",\\"version\\":\\"WzAsMV0=\\"}]: Error: The length of the field customFields is too long. Array must be of length <= 5."` + `"Failed to update case, ids: [{\\"id\\":\\"mock-id-1\\",\\"version\\":\\"WzAsMV0=\\"}]: Error: The length of the field customFields is too long. Array must be of length <= 10."` ); }); diff --git a/x-pack/plugins/cases/server/client/cases/validators.ts b/x-pack/plugins/cases/server/client/cases/validators.ts index d52f98b92d0b0..d8afe75ce625c 100644 --- a/x-pack/plugins/cases/server/client/cases/validators.ts +++ b/x-pack/plugins/cases/server/client/cases/validators.ts @@ -95,12 +95,12 @@ export const validateRequiredCustomFields = ({ requestCustomFields, customFieldsConfiguration, }: CustomFieldValidationParams) => { - if (!Array.isArray(requestCustomFields) || !requestCustomFields.length) { - return; - } - if (customFieldsConfiguration === undefined) { - throw Boom.badRequest('No custom fields configured.'); + if (!Array.isArray(requestCustomFields) || !requestCustomFields.length) { + return; + } else { + throw Boom.badRequest('No custom fields configured.'); + } } const requiredCustomFields = customFieldsConfiguration.filter( @@ -109,7 +109,7 @@ export const validateRequiredCustomFields = ({ const invalidCustomFieldKeys = differenceWith( requiredCustomFields, - requestCustomFields, + requestCustomFields ?? [], (requiredVal, requestedVal) => requiredVal.key === requestedVal.key ).map((e) => e.key); diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/import_export.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/import_export.ts index 3f5d757124e4e..060b6463c0451 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/import_export.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/import_export.ts @@ -79,7 +79,7 @@ export default ({ getService }: FtrProviderContext): void => { expect(objects).to.have.length(4); - const expectedCaseRequest = { ...caseRequest, category: null }; // added default value + const expectedCaseRequest = { ...caseRequest, category: null, customFields: [] }; // added default value expectExportToHaveCaseSavedObject(objects, expectedCaseRequest); expectExportToHaveUserActions(objects, expectedCaseRequest); diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/patch_cases.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/patch_cases.ts index 068456d2bbee4..bce8ee853d46f 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/patch_cases.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/patch_cases.ts @@ -109,6 +109,13 @@ export default ({ getService }: FtrProviderContext): void => { const data = removeServerGeneratedPropertiesFromCase(patchedCases[0]); expect(data).to.eql({ ...postCaseResp(), + customFields: [ + { + key: 'test_custom_field', + type: CustomFieldTypes.TEXT, + value: null, + }, + ], title: 'new title', updated_by: defaultUser, }); @@ -329,7 +336,16 @@ export default ({ getService }: FtrProviderContext): void => { }) ); - const postedCase = await createCase(supertest, postCaseReq); + const postedCase = await createCase(supertest, { + ...postCaseReq, + customFields: [ + { + key: 'test_custom_field_2', + type: CustomFieldTypes.TOGGLE, + value: true, + }, + ], + }); const patchedCases = await updateCase({ supertest, params: { @@ -368,7 +384,7 @@ export default ({ getService }: FtrProviderContext): void => { ]); }); - it('should fill out missing custom fields', async () => { + it('should fill out missing optional custom fields', async () => { await createConfiguration( supertest, getConfigurationRequest({ @@ -391,7 +407,17 @@ export default ({ getService }: FtrProviderContext): void => { }) ); - const postedCase = await createCase(supertest, postCaseReq); + const postedCase = await createCase(supertest, { + ...postCaseReq, + customFields: [ + { + key: 'test_custom_field_2', + type: CustomFieldTypes.TOGGLE, + value: true, + }, + ], + }); + const patchedCases = await updateCase({ supertest, params: { @@ -1016,7 +1042,7 @@ export default ({ getService }: FtrProviderContext): void => { }); }); - it('400s when trying to create case with a missing required custom field', async () => { + it('400s when trying to patch a case with a missing required custom field', async () => { await createConfiguration( supertest, getConfigurationRequest({ @@ -1032,7 +1058,16 @@ export default ({ getService }: FtrProviderContext): void => { }, }) ); - const postedCase = await createCase(supertest, postCaseReq); + const postedCase = await createCase(supertest, { + ...postCaseReq, + customFields: [ + { + key: 'test_custom_field', + type: CustomFieldTypes.TEXT, + value: ['hello'], + }, + ], + }); await updateCase({ supertest, @@ -1049,7 +1084,7 @@ export default ({ getService }: FtrProviderContext): void => { }); }); - it('400s when trying to create case with a custom field with the wrong type', async () => { + it('400s when trying to patch a case with a custom field with the wrong type', async () => { await createConfiguration( supertest, getConfigurationRequest({ @@ -1059,7 +1094,7 @@ export default ({ getService }: FtrProviderContext): void => { key: 'test_custom_field', label: 'text', type: CustomFieldTypes.TEXT, - required: true, + required: false, }, ], }, @@ -1078,7 +1113,7 @@ export default ({ getService }: FtrProviderContext): void => { { key: 'test_custom_field', type: CustomFieldTypes.TOGGLE, - value: true, + value: false, }, ], }, diff --git a/x-pack/test/functional/services/cases/common.ts b/x-pack/test/functional/services/cases/common.ts index ef7964935ae41..7a969b310f56f 100644 --- a/x-pack/test/functional/services/cases/common.ts +++ b/x-pack/test/functional/services/cases/common.ts @@ -63,6 +63,7 @@ export function CasesCommonServiceProvider({ getService, getPageObject }: FtrPro const radioGroup = await testSubjects.find(testSubject); const label = await radioGroup.findByCssSelector(`label[for="${value}"]`); await label.click(); + await header.waitUntilLoadingHasFinished(); await this.assertRadioGroupValue(testSubject, value); }, diff --git a/x-pack/test/functional_with_es_ssl/apps/cases/group2/configure.ts b/x-pack/test/functional_with_es_ssl/apps/cases/group2/configure.ts index b812bbaeb019b..098297551347d 100644 --- a/x-pack/test/functional_with_es_ssl/apps/cases/group2/configure.ts +++ b/x-pack/test/functional_with_es_ssl/apps/cases/group2/configure.ts @@ -13,6 +13,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { const testSubjects = getService('testSubjects'); const cases = getService('cases'); const toasts = getService('toasts'); + const header = getPageObject('header'); describe('Configure', function () { before(async () => { @@ -24,6 +25,9 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { }); describe('Closure options', function () { + this.beforeEach(async () => { + await header.waitUntilLoadingHasFinished(); + }); it('defaults the closure option correctly', async () => { await cases.common.assertRadioGroupValue('closure-options-radio-group', 'close-by-user'); }); @@ -33,6 +37,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { const toast = await toasts.getToastElement(1); expect(await toast.getVisibleText()).to.be('Saved external connection settings'); await toasts.dismissAllToasts(); + await cases.common.assertRadioGroupValue('closure-options-radio-group', 'close-by-pushing'); }); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/explore/cases/connectors.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/explore/cases/connectors.cy.ts index d61b24d67c223..05efe03c56bc0 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/explore/cases/connectors.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/explore/cases/connectors.cy.ts @@ -35,6 +35,7 @@ describe('Cases connectors', { tags: ['@ess', '@serverless'] }, () => { error: null, updated_at: null, updated_by: null, + customFields: [], mappings: [ { source: 'title', target: 'short_description', action_type: 'overwrite' }, { source: 'description', target: 'description', action_type: 'overwrite' }, diff --git a/x-pack/test/security_solution_cypress/cypress/objects/case.ts b/x-pack/test/security_solution_cypress/cypress/objects/case.ts index 2abdce5fb068c..f30f24fb6ff06 100644 --- a/x-pack/test/security_solution_cypress/cypress/objects/case.ts +++ b/x-pack/test/security_solution_cypress/cypress/objects/case.ts @@ -74,6 +74,7 @@ export const getCaseResponse = (): Case => ({ status: CaseStatuses.open, severity: CaseSeverity.HIGH, assignees: [], + customFields: [], settings: { syncAlerts: false, }, diff --git a/x-pack/test_serverless/api_integration/services/svl_cases/api.ts b/x-pack/test_serverless/api_integration/services/svl_cases/api.ts index 4163fc70291db..a504b71240dd5 100644 --- a/x-pack/test_serverless/api_integration/services/svl_cases/api.ts +++ b/x-pack/test_serverless/api_integration/services/svl_cases/api.ts @@ -133,6 +133,7 @@ export function SvlCasesApiServiceProvider({ getService }: FtrProviderContext) { status: CaseStatuses.open, updated_by: null, category: null, + customFields: [], }; },