diff --git a/x-pack/platform/plugins/shared/dataset_quality/common/api_types.ts b/x-pack/platform/plugins/shared/dataset_quality/common/api_types.ts index bd3937c3677ce..0fa0b16641594 100644 --- a/x-pack/platform/plugins/shared/dataset_quality/common/api_types.ts +++ b/x-pack/platform/plugins/shared/dataset_quality/common/api_types.ts @@ -10,6 +10,7 @@ import * as rt from 'io-ts'; const userPrivilegesRt = rt.type({ canMonitor: rt.boolean, canReadFailureStore: rt.boolean, + canManageFailureStore: rt.boolean, }); const datasetPrivilegeRt = rt.record( diff --git a/x-pack/platform/plugins/shared/dataset_quality/common/constants.ts b/x-pack/platform/plugins/shared/dataset_quality/common/constants.ts index dca855b426bda..9e0b79f5270ba 100644 --- a/x-pack/platform/plugins/shared/dataset_quality/common/constants.ts +++ b/x-pack/platform/plugins/shared/dataset_quality/common/constants.ts @@ -54,3 +54,4 @@ export const FAILURE_STORE_SELECTOR = '::failures'; export const DATA_SELECTOR = '::data'; export const FAILURE_STORE_PRIVILEGE = 'read_failure_store'; +export const MANAGE_FAILURE_STORE_PRIVILEGE = 'manage_failure_store'; diff --git a/x-pack/platform/plugins/shared/dataset_quality/common/translations.ts b/x-pack/platform/plugins/shared/dataset_quality/common/translations.ts index 704f7d81ee3a3..6c91d6e8a243d 100644 --- a/x-pack/platform/plugins/shared/dataset_quality/common/translations.ts +++ b/x-pack/platform/plugins/shared/dataset_quality/common/translations.ts @@ -771,6 +771,10 @@ export const createAlertText = i18n.translate('xpack.datasetQuality.createAlert' defaultMessage: 'Create rule', }); +export const editFailureStoreText = i18n.translate('xpack.datasetQuality.editFailureStore', { + defaultMessage: 'Edit failure store', +}); + export const issueTypeFilterSearchPlaceholder = i18n.translate( 'xpack.datasetQuality.details.qualityIssuesTable.issueTypeFilterSearchPlaceholder', { diff --git a/x-pack/platform/plugins/shared/dataset_quality/public/components/dataset_quality_details/overview/document_trends/index.tsx b/x-pack/platform/plugins/shared/dataset_quality/public/components/dataset_quality_details/overview/document_trends/index.tsx index 1863833a4f118..e895b148276f7 100644 --- a/x-pack/platform/plugins/shared/dataset_quality/public/components/dataset_quality_details/overview/document_trends/index.tsx +++ b/x-pack/platform/plugins/shared/dataset_quality/public/components/dataset_quality_details/overview/document_trends/index.tsx @@ -20,8 +20,13 @@ import { discoverAriaText, openInDiscoverText, createAlertText, + editFailureStoreText, } from '../../../../../common/translations'; -import { useDatasetQualityDetailsState, useQualityIssuesDocsChart } from '../../../../hooks'; +import { + useDatasetQualityDetailsState, + useFailureStoreModal, + useQualityIssuesDocsChart, +} from '../../../../hooks'; import { TrendDocsChart } from './trend_docs_chart'; import { useKibanaContextForPlugin } from '../../../../utils/use_kibana'; import { getAlertingCapabilities } from '../../../../alerts/get_alerting_capabilities'; @@ -30,12 +35,15 @@ import { getAlertingCapabilities } from '../../../../alerts/get_alerting_capabil // eslint-disable-next-line import/no-default-export export default function DocumentTrends({ lastReloadTime, - displayCreateRuleButton, openAlertFlyout, + displayActions: { displayCreateRuleButton, displayEditFailureStore }, }: { lastReloadTime: number; - displayCreateRuleButton: boolean; openAlertFlyout: () => void; + displayActions: { + displayCreateRuleButton: boolean; + displayEditFailureStore: boolean; + }; }) { const { timeRange, updateTimeRange } = useDatasetQualityDetailsState(); const { @@ -59,6 +67,12 @@ export default function DocumentTrends({ [updateTimeRange, timeRange.refresh] ); + const { + openModal: openFailureStoreModal, + canUserManageFailureStore, + renderModal: renderFailureStoreModal, + } = useFailureStoreModal(); + return ( <> @@ -90,7 +104,7 @@ export default function DocumentTrends({ /> {displayCreateRuleButton && isAlertingAvailable && ( - + )} + {displayEditFailureStore && canUserManageFailureStore && ( + + + + )} @@ -111,6 +137,7 @@ export default function DocumentTrends({ lastReloadTime={lastReloadTime} onTimeRangeChange={onTimeRangeChange} /> + {renderFailureStoreModal()} ); } diff --git a/x-pack/platform/plugins/shared/dataset_quality/public/components/dataset_quality_details/overview/index.tsx b/x-pack/platform/plugins/shared/dataset_quality/public/components/dataset_quality_details/overview/index.tsx index 9127076c6535d..9524624ed5008 100644 --- a/x-pack/platform/plugins/shared/dataset_quality/public/components/dataset_quality_details/overview/index.tsx +++ b/x-pack/platform/plugins/shared/dataset_quality/public/components/dataset_quality_details/overview/index.tsx @@ -73,8 +73,11 @@ export function Overview({ openAlertFlyout }: { openAlertFlyout: () => void }) { diff --git a/x-pack/platform/plugins/shared/dataset_quality/public/components/dataset_quality_details/overview/quality_summary_cards/index.tsx b/x-pack/platform/plugins/shared/dataset_quality/public/components/dataset_quality_details/overview/quality_summary_cards/index.tsx index bdac8336e9551..e314a2751ae6f 100644 --- a/x-pack/platform/plugins/shared/dataset_quality/public/components/dataset_quality_details/overview/quality_summary_cards/index.tsx +++ b/x-pack/platform/plugins/shared/dataset_quality/public/components/dataset_quality_details/overview/quality_summary_cards/index.tsx @@ -6,10 +6,9 @@ */ import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiCode } from '@elastic/eui'; -import React, { useState } from 'react'; +import React from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { FailureStoreModal } from '@kbn/failure-store-modal'; import { overviewPanelDatasetQualityIndicatorDegradedDocs, overviewPanelDatasetQualityIndicatorFailedDocs, @@ -18,6 +17,7 @@ import { import { useOverviewSummaryPanel } from '../../../../hooks/use_overview_summary_panel'; import { useQualityIssuesDocsChart } from '../../../../hooks/use_quality_issues_docs_chart'; import { useDatasetQualityDetailsState } from '../../../../hooks/use_dataset_quality_details_state'; +import { useFailureStoreModal } from '../../../../hooks/use_failure_store_modal'; import { DatasetQualityIndicator, QualityPercentageIndicator } from '../../../quality_indicator'; import { Card } from './card'; @@ -60,35 +60,16 @@ export default function QualitySummaryCards({ } = useOverviewSummaryPanel(); const { handleDocsTrendChartChange } = useQualityIssuesDocsChart(); const { - canUserReadFailureStore, - hasFailureStore, loadingState: { dataStreamSettingsLoading }, - defaultRetentionPeriod, - customRetentionPeriod, - updateFailureStore, } = useDatasetQualityDetailsState(); - const [isFailureStoreModalOpen, setIsFailureStoreModalOpen] = useState(false); - - const closeModal = () => { - setIsFailureStoreModalOpen(false); - }; - - const handleSaveModal = async (data: { - failureStoreEnabled: boolean; - customRetentionPeriod?: string; - }) => { - updateFailureStore({ - failureStoreEnabled: data.failureStoreEnabled, - customRetentionPeriod: data.customRetentionPeriod, - }); - closeModal(); - }; - - const onClick = () => { - setIsFailureStoreModalOpen(true); - }; - + const { + openModal, + canUserReadFailureStore, + canUserManageFailureStore, + hasFailureStore, + renderModal: renderFailureStoreModal, + } = useFailureStoreModal(); return ( @@ -139,9 +120,9 @@ export default function QualitySummaryCards({ defaultMessage: 'No failure store', })} footer={ - canUserReadFailureStore && ( + canUserManageFailureStore && ( {i18n.translate('xpack.datasetQuality.enableFailureStore', { @@ -151,17 +132,7 @@ export default function QualitySummaryCards({ ) } /> - {canUserReadFailureStore && isFailureStoreModalOpen && defaultRetentionPeriod && ( - - )} + {renderFailureStoreModal()} ) : ( { dataStreamSettings?.datasetUserPrivileges?.datasetsPrivilages?.[dataStream]?.canReadFailureStore ); + const canUserManageFailureStore = Boolean( + dataStreamSettings?.datasetUserPrivileges?.datasetsPrivilages?.[dataStream] + ?.canManageFailureStore + ); + const dataStreamDetails = useSelector(service, (state) => state.matches('initializing.dataStreamDetails.done') ? state.context.dataStreamDetails @@ -214,5 +219,6 @@ export const useDatasetQualityDetailsState = () => { isQualityIssueFlyoutOpen, defaultRetentionPeriod, customRetentionPeriod, + canUserManageFailureStore, }; }; diff --git a/x-pack/platform/plugins/shared/dataset_quality/public/hooks/use_failure_store_modal.ts b/x-pack/platform/plugins/shared/dataset_quality/public/hooks/use_failure_store_modal.ts new file mode 100644 index 0000000000000..c53b5aa211201 --- /dev/null +++ b/x-pack/platform/plugins/shared/dataset_quality/public/hooks/use_failure_store_modal.ts @@ -0,0 +1,70 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useState } from 'react'; +import { FailureStoreModal } from '@kbn/failure-store-modal'; +import { useDatasetQualityDetailsState } from './use_dataset_quality_details_state'; + +export function useFailureStoreModal() { + const { + canUserReadFailureStore, + hasFailureStore, + defaultRetentionPeriod, + customRetentionPeriod, + updateFailureStore, + canUserManageFailureStore, + } = useDatasetQualityDetailsState(); + + const [isFailureStoreModalOpen, setIsFailureStoreModalOpen] = useState(false); + + const openModal = () => { + setIsFailureStoreModalOpen(true); + }; + + const closeModal = () => { + setIsFailureStoreModalOpen(false); + }; + + const handleSaveModal = async (data: { + failureStoreEnabled: boolean; + customRetentionPeriod?: string; + }) => { + updateFailureStore({ + failureStoreEnabled: data.failureStoreEnabled, + customRetentionPeriod: data.customRetentionPeriod, + }); + closeModal(); + }; + + const renderModal = (): React.ReactElement | null => { + if (canUserManageFailureStore && isFailureStoreModalOpen && defaultRetentionPeriod) { + return React.createElement(FailureStoreModal, { + onCloseModal: closeModal, + onSaveModal: handleSaveModal, + failureStoreProps: { + failureStoreEnabled: hasFailureStore, + defaultRetentionPeriod, + customRetentionPeriod, + }, + }); + } + return null; + }; + + return { + isFailureStoreModalOpen, + openModal, + closeModal, + handleSaveModal, + canUserReadFailureStore, + canUserManageFailureStore, + hasFailureStore, + defaultRetentionPeriod, + customRetentionPeriod, + renderModal, + }; +} diff --git a/x-pack/platform/plugins/shared/dataset_quality/public/state_machines/dataset_quality_details_controller/state_machine.ts b/x-pack/platform/plugins/shared/dataset_quality/public/state_machines/dataset_quality_details_controller/state_machine.ts index c763d259007d4..88f1a31e3b226 100644 --- a/x-pack/platform/plugins/shared/dataset_quality/public/state_machines/dataset_quality_details_controller/state_machine.ts +++ b/x-pack/platform/plugins/shared/dataset_quality/public/state_machines/dataset_quality_details_controller/state_machine.ts @@ -1008,7 +1008,7 @@ export const createDatasetQualityDetailsControllerStateMachine = ({ if ( 'dataStreamDetails' in context && context.dataStreamDetails && - context.dataStreamDetails.hasFailureStore + context.dataStreamDetails.hasFailureStore !== undefined ) { return dataStreamDetailsClient.updateFailureStore({ dataStream: context.dataStream, diff --git a/x-pack/platform/plugins/shared/dataset_quality/public/utils/generate_datasets.test.ts b/x-pack/platform/plugins/shared/dataset_quality/public/utils/generate_datasets.test.ts index 9322ea18fe414..ac4374828c6e9 100644 --- a/x-pack/platform/plugins/shared/dataset_quality/public/utils/generate_datasets.test.ts +++ b/x-pack/platform/plugins/shared/dataset_quality/public/utils/generate_datasets.test.ts @@ -46,6 +46,7 @@ describe('generateDatasets', () => { userPrivileges: { canMonitor: true, canReadFailureStore: true, + canManageFailureStore: true, }, }, { @@ -58,6 +59,7 @@ describe('generateDatasets', () => { userPrivileges: { canMonitor: true, canReadFailureStore: true, + canManageFailureStore: true, }, }, ]; @@ -114,6 +116,7 @@ describe('generateDatasets', () => { userPrivileges: { canMonitor: true, canReadFailureStore: true, + canManageFailureStore: true, }, docsInTimeRange: 102, quality: 'degraded', @@ -141,6 +144,7 @@ describe('generateDatasets', () => { userPrivileges: { canMonitor: true, canReadFailureStore: true, + canManageFailureStore: true, }, docsInTimeRange: 100, quality: 'poor', @@ -181,6 +185,7 @@ describe('generateDatasets', () => { userPrivileges: { canMonitor: true, canReadFailureStore: true, + canManageFailureStore: true, }, docsInTimeRange: 2, quality: 'poor', @@ -208,6 +213,7 @@ describe('generateDatasets', () => { userPrivileges: { canMonitor: true, canReadFailureStore: true, + canManageFailureStore: true, }, docsInTimeRange: 0, quality: 'good', @@ -379,6 +385,7 @@ describe('generateDatasets', () => { userPrivileges: { canMonitor: true, canReadFailureStore: true, + canManageFailureStore: true, }, quality: 'good', docsInTimeRange: 100, @@ -406,6 +413,7 @@ describe('generateDatasets', () => { userPrivileges: { canMonitor: true, canReadFailureStore: true, + canManageFailureStore: true, }, quality: 'good', docsInTimeRange: 100, @@ -434,6 +442,7 @@ describe('generateDatasets', () => { userPrivileges: { canMonitor: true, canReadFailureStore: true, + canManageFailureStore: true, }, }; @@ -453,6 +462,7 @@ describe('generateDatasets', () => { userPrivileges: { canMonitor: true, canReadFailureStore: true, + canManageFailureStore: true, }, quality: 'good', totalDocs: 100, diff --git a/x-pack/platform/plugins/shared/dataset_quality/server/routes/data_streams/get_data_stream_details/index.ts b/x-pack/platform/plugins/shared/dataset_quality/server/routes/data_streams/get_data_stream_details/index.ts index c94708a173aff..d838c2bf9a61f 100644 --- a/x-pack/platform/plugins/shared/dataset_quality/server/routes/data_streams/get_data_stream_details/index.ts +++ b/x-pack/platform/plugins/shared/dataset_quality/server/routes/data_streams/get_data_stream_details/index.ts @@ -8,7 +8,11 @@ import { badRequest } from '@hapi/boom'; import type { ElasticsearchClient, IScopedClusterClient } from '@kbn/core/server'; import type { DataStreamDetails } from '../../../../common/api_types'; -import { FAILURE_STORE_PRIVILEGE, MAX_HOSTS_METRIC_VALUE } from '../../../../common/constants'; +import { + FAILURE_STORE_PRIVILEGE, + MANAGE_FAILURE_STORE_PRIVILEGE, + MAX_HOSTS_METRIC_VALUE, +} from '../../../../common/constants'; import { _IGNORED } from '../../../../common/es_fields'; import { datasetQualityPrivileges } from '../../../services'; import { createDatasetQualityESClient } from '../../../utils'; @@ -40,7 +44,7 @@ export async function getDataStreamDetails({ await datasetQualityPrivileges.getHasIndexPrivileges( esClientAsCurrentUser, [dataStream], - ['monitor', FAILURE_STORE_PRIVILEGE] + ['monitor', FAILURE_STORE_PRIVILEGE, MANAGE_FAILURE_STORE_PRIVILEGE] ) )[dataStream]; @@ -91,6 +95,7 @@ export async function getDataStreamDetails({ userPrivileges: { canMonitor: dataStreamPrivileges.monitor, canReadFailureStore: dataStreamPrivileges[FAILURE_STORE_PRIVILEGE], + canManageFailureStore: dataStreamPrivileges[MANAGE_FAILURE_STORE_PRIVILEGE], }, customRetentionPeriod: esDataStream?.customRetentionPeriod, }; diff --git a/x-pack/platform/plugins/shared/dataset_quality/server/routes/data_streams/get_data_streams/index.ts b/x-pack/platform/plugins/shared/dataset_quality/server/routes/data_streams/get_data_streams/index.ts index fdba06727a2c4..7b0950f78ec43 100644 --- a/x-pack/platform/plugins/shared/dataset_quality/server/routes/data_streams/get_data_streams/index.ts +++ b/x-pack/platform/plugins/shared/dataset_quality/server/routes/data_streams/get_data_streams/index.ts @@ -6,7 +6,10 @@ */ import type { ElasticsearchClient } from '@kbn/core/server'; -import { FAILURE_STORE_PRIVILEGE } from '../../../../common/constants'; +import { + FAILURE_STORE_PRIVILEGE, + MANAGE_FAILURE_STORE_PRIVILEGE, +} from '../../../../common/constants'; import { streamPartsToIndexPattern } from '../../../../common/utils'; import type { DataStreamType } from '../../../../common/types'; import { dataStreamService, datasetQualityPrivileges } from '../../../services'; @@ -59,7 +62,7 @@ export async function getDataStreams(options: { ? await datasetQualityPrivileges.getHasIndexPrivileges( esClient, filteredDataStreams.map(({ name }) => name), - ['monitor', FAILURE_STORE_PRIVILEGE] + ['monitor', FAILURE_STORE_PRIVILEGE, MANAGE_FAILURE_STORE_PRIVILEGE] ) : {}; @@ -71,6 +74,7 @@ export async function getDataStreams(options: { userPrivileges: { canMonitor: dataStreamsPrivileges[dataStream.name].monitor, canReadFailureStore: dataStreamsPrivileges[dataStream.name][FAILURE_STORE_PRIVILEGE], + canManageFailureStore: dataStreamsPrivileges[dataStream.name][MANAGE_FAILURE_STORE_PRIVILEGE], }, hasFailureStore: dataStream.failure_store?.enabled, // @ts-expect-error diff --git a/x-pack/platform/plugins/shared/dataset_quality/server/services/privileges.ts b/x-pack/platform/plugins/shared/dataset_quality/server/services/privileges.ts index 9443b468cc0c6..82f34f83688c7 100644 --- a/x-pack/platform/plugins/shared/dataset_quality/server/services/privileges.ts +++ b/x-pack/platform/plugins/shared/dataset_quality/server/services/privileges.ts @@ -13,7 +13,11 @@ import type { import type { ElasticsearchClient } from '@kbn/core/server'; import { streamPartsToIndexPattern } from '../../common/utils'; -import { DEFAULT_DATASET_TYPE, FAILURE_STORE_PRIVILEGE } from '../../common/constants'; +import { + DEFAULT_DATASET_TYPE, + FAILURE_STORE_PRIVILEGE, + MANAGE_FAILURE_STORE_PRIVILEGE, +} from '../../common/constants'; class DatasetQualityPrivileges { public async getHasIndexPrivileges( @@ -55,7 +59,12 @@ class DatasetQualityPrivileges { ): Promise<{ datasetsPrivilages: Record< string, - { canRead: boolean; canMonitor: boolean; canReadFailureStore: boolean } + { + canRead: boolean; + canMonitor: boolean; + canReadFailureStore: boolean; + canManageFailureStore: boolean; + } >; canViewIntegrations: boolean; }> { @@ -64,6 +73,7 @@ class DatasetQualityPrivileges { 'monitor', 'view_index_metadata', FAILURE_STORE_PRIVILEGE, + MANAGE_FAILURE_STORE_PRIVILEGE, ]); const datasetsPrivilages = Object.fromEntries( @@ -73,6 +83,7 @@ class DatasetQualityPrivileges { canRead: privileges.read, canMonitor: privileges.view_index_metadata, canReadFailureStore: privileges[FAILURE_STORE_PRIVILEGE], + canManageFailureStore: privileges[MANAGE_FAILURE_STORE_PRIVILEGE], }, ]) ); diff --git a/x-pack/solutions/observability/test/api_integration_deployment_agnostic/apis/dataset_quality/data_stream_settings.ts b/x-pack/solutions/observability/test/api_integration_deployment_agnostic/apis/dataset_quality/data_stream_settings.ts index e5d78da2f281f..f7f636fbdf830 100644 --- a/x-pack/solutions/observability/test/api_integration_deployment_agnostic/apis/dataset_quality/data_stream_settings.ts +++ b/x-pack/solutions/observability/test/api_integration_deployment_agnostic/apis/dataset_quality/data_stream_settings.ts @@ -43,6 +43,7 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { canRead: true, canMonitor: true, canReadFailureStore: true, + canManageFailureStore: true, }, }, canViewIntegrations: true, diff --git a/x-pack/solutions/observability/test/dataset_quality_api_integration/tests/data_streams/stats.spec.ts b/x-pack/solutions/observability/test/dataset_quality_api_integration/tests/data_streams/stats.spec.ts index b394a192c0855..0d04499b0ebd1 100644 --- a/x-pack/solutions/observability/test/dataset_quality_api_integration/tests/data_streams/stats.spec.ts +++ b/x-pack/solutions/observability/test/dataset_quality_api_integration/tests/data_streams/stats.spec.ts @@ -86,6 +86,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { canRead: true, canMonitor: true, canReadFailureStore: true, + canManageFailureStore: true, }, }, canViewIntegrations: true, diff --git a/x-pack/solutions/observability/test/dataset_quality_api_integration/tests/data_streams/types_privileges.spec.ts b/x-pack/solutions/observability/test/dataset_quality_api_integration/tests/data_streams/types_privileges.spec.ts index fa040084358aa..f2f8e95abae11 100644 --- a/x-pack/solutions/observability/test/dataset_quality_api_integration/tests/data_streams/types_privileges.spec.ts +++ b/x-pack/solutions/observability/test/dataset_quality_api_integration/tests/data_streams/types_privileges.spec.ts @@ -39,12 +39,14 @@ export default function ApiTest({ getService }: FtrProviderContext) { canRead: false, canMonitor: false, canReadFailureStore: false, + canManageFailureStore: false, }; const fullPrivileges = { canRead: true, canMonitor: true, canReadFailureStore: true, + canManageFailureStore: true, }; it('returns no privileges for noAccessUser with single type', async () => { diff --git a/x-pack/solutions/observability/test/functional/apps/dataset_quality/dataset_quality_details_failure_store.ts b/x-pack/solutions/observability/test/functional/apps/dataset_quality/dataset_quality_details_failure_store.ts index 8fda4475addf7..1e2640af2b62c 100644 --- a/x-pack/solutions/observability/test/functional/apps/dataset_quality/dataset_quality_details_failure_store.ts +++ b/x-pack/solutions/observability/test/functional/apps/dataset_quality/dataset_quality_details_failure_store.ts @@ -223,6 +223,45 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid ); expect(failedDocsCard).to.not.contain('No failure store'); }); + + it('should edit failure store', async () => { + const { + datasetQualityDetailsSummaryCardFailedDocuments, + editFailureStoreIcon, + editFailureStoreModal, + failureStoreModalSaveButton, + enableFailureStoreToggle, + datasetQualityDetailsSummaryCardNoFailureStore, + } = PageObjects.datasetQuality.testSubjectSelectors; + + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: failureStoreDataStreamName, + }); + + await testSubjects.existOrFail(datasetQualityDetailsSummaryCardFailedDocuments); + await testSubjects.click(datasetQualityDetailsSummaryCardFailedDocuments); + + await testSubjects.existOrFail(editFailureStoreIcon); + await testSubjects.click(editFailureStoreIcon); + + await testSubjects.existOrFail(editFailureStoreModal); + + const saveModalButton = await testSubjects.find(failureStoreModalSaveButton); + await testSubjects.click(enableFailureStoreToggle); + + await retry.try(async () => { + expect(await saveModalButton.isEnabled()).to.be(true); + }); + + await testSubjects.click(failureStoreModalSaveButton); + + await testSubjects.missingOrFail(editFailureStoreModal); + await testSubjects.existOrFail(datasetQualityDetailsSummaryCardNoFailureStore); + const failedDocsCard = await testSubjects.getVisibleText( + datasetQualityDetailsSummaryCardNoFailureStore + ); + expect(failedDocsCard).to.contain('No failure store'); + }); }); }); } diff --git a/x-pack/solutions/observability/test/functional/page_objects/dataset_quality.ts b/x-pack/solutions/observability/test/functional/page_objects/dataset_quality.ts index d95ff4cb2ef70..87c4fec7c35e8 100644 --- a/x-pack/solutions/observability/test/functional/page_objects/dataset_quality.ts +++ b/x-pack/solutions/observability/test/functional/page_objects/dataset_quality.ts @@ -184,6 +184,7 @@ export function DatasetQualityPageObject({ getPageObjects, getService }: FtrProv editFailureStoreModal: 'editFailureStoreModal', enableFailureStoreToggle: 'enableFailureStoreToggle', failureStoreModalSaveButton: 'failureStoreModalSaveButton', + editFailureStoreIcon: 'datasetQualityDetailsEditFailureStore', }; return { diff --git a/x-pack/solutions/observability/test/serverless/functional/test_suites/dataset_quality/dataset_quality_details_failure_store.ts b/x-pack/solutions/observability/test/serverless/functional/test_suites/dataset_quality/dataset_quality_details_failure_store.ts index 1988715373e36..3907029fbb34a 100644 --- a/x-pack/solutions/observability/test/serverless/functional/test_suites/dataset_quality/dataset_quality_details_failure_store.ts +++ b/x-pack/solutions/observability/test/serverless/functional/test_suites/dataset_quality/dataset_quality_details_failure_store.ts @@ -183,6 +183,43 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ); expect(failedDocsCard).to.not.contain('No failure store'); }); + + it('should edit failure store', async () => { + const { + datasetQualityDetailsSummaryCardFailedDocuments, + editFailureStoreIcon, + editFailureStoreModal, + failureStoreModalSaveButton, + enableFailureStoreToggle, + datasetQualityDetailsSummaryCardNoFailureStore, + } = PageObjects.datasetQuality.testSubjectSelectors; + + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: failureStoreDataStreamName, + }); + + await testSubjects.existOrFail(datasetQualityDetailsSummaryCardFailedDocuments); + await testSubjects.click(datasetQualityDetailsSummaryCardFailedDocuments); + + await testSubjects.existOrFail(editFailureStoreIcon); + await testSubjects.click(editFailureStoreIcon); + + await testSubjects.existOrFail(editFailureStoreModal); + + const saveModalButton = await testSubjects.find(failureStoreModalSaveButton); + await testSubjects.click(enableFailureStoreToggle); + + expect(await saveModalButton.isEnabled()).to.be(true); + + await testSubjects.click(failureStoreModalSaveButton); + + await testSubjects.missingOrFail(editFailureStoreModal); + await testSubjects.existOrFail(datasetQualityDetailsSummaryCardNoFailureStore); + const failedDocsCard = await testSubjects.getVisibleText( + datasetQualityDetailsSummaryCardNoFailureStore + ); + expect(failedDocsCard).to.contain('No failure store'); + }); }); }); }