{tabs.map((tab) => (
setSelectedTabId(tab.id)}
key={tab.id}
@@ -146,6 +147,6 @@ export const DecisionPathPopover: FC = ({
{selectedTabId === DECISION_PATH_TABS.JSON && (
)}
- >
+
);
};
diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/total_feature_importance_summary/feature_importance_summary.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/total_feature_importance_summary/feature_importance_summary.tsx
index 64835e7ca4c6d..0fab1cf75259e 100644
--- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/total_feature_importance_summary/feature_importance_summary.tsx
+++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/total_feature_importance_summary/feature_importance_summary.tsx
@@ -210,6 +210,7 @@ export const FeatureImportanceSummaryPanel: FC
-
+
)
}
/>
diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/page.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/page.tsx
index 44085384f7536..c31a3b08aa756 100644
--- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/page.tsx
+++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/page.tsx
@@ -59,16 +59,13 @@ export const Page: FC = () => {
/>
diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart.js b/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart.js
index 8df186c5c3c6e..b2d054becbb1a 100644
--- a/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart.js
+++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart.js
@@ -51,6 +51,7 @@ import {
unhighlightFocusChartAnnotation,
ANNOTATION_MIN_WIDTH,
} from './timeseries_chart_annotations';
+import { distinctUntilChanged } from 'rxjs/operators';
const focusZoomPanelHeight = 25;
const focusChartHeight = 310;
@@ -570,6 +571,7 @@ class TimeseriesChartIntl extends Component {
}
renderFocusChart() {
+ console.log('renderFocusChart');
const {
focusAggregationInterval,
focusAnnotationData: focusAnnotationDataOriginalPropValue,
@@ -1798,7 +1800,15 @@ class TimeseriesChartIntl extends Component {
}
export const TimeseriesChart = (props) => {
- const annotationProp = useObservable(annotation$);
+ const annotationProp = useObservable(
+ annotation$.pipe(
+ distinctUntilChanged((prev, curr) => {
+ // prevent re-rendering
+ return prev !== null && curr !== null;
+ })
+ )
+ );
+
if (annotationProp === undefined) {
return null;
}
diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js
index e3b6e38f47bab..f14f11e5d6149 100644
--- a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js
+++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js
@@ -1014,6 +1014,7 @@ export class TimeSeriesExplorer extends React.Component {
this.previousShowForecast = showForecast;
this.previousShowModelBounds = showModelBounds;
+ console.log('Timeseriesexplorer rerendered');
return (
{fieldNamesWithEmptyValues.length > 0 && (
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index ba6ac32f2e3d0..1d4cf7435aeeb 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -11284,24 +11284,9 @@
"xpack.maps.layerWizardSelect.solutionsCategoryLabel": "ソリューション",
"xpack.maps.loadMap.errorAttemptingToLoadSavedMap": "マップを読み込めません",
"xpack.maps.map.initializeErrorTitle": "マップを初期化できません",
- "xpack.maps.mapListing.advancedSettingsLinkText": "高度な設定",
- "xpack.maps.mapListing.cancelTitle": "キャンセル",
- "xpack.maps.mapListing.createMapButtonLabel": "マップを作成",
- "xpack.maps.mapListing.deleteSelectedButtonLabel": "選択項目を削除",
- "xpack.maps.mapListing.deleteSelectedItemsTitle": "選択項目を削除しますか?",
- "xpack.maps.mapListing.deleteTitle": "削除",
- "xpack.maps.mapListing.deleteWarning": "削除されたアイテムは復元できません。",
"xpack.maps.mapListing.descriptionFieldTitle": "説明",
"xpack.maps.mapListing.errorAttemptingToLoadSavedMaps": "マップを読み込めません",
- "xpack.maps.mapListing.limitExceededTitle": "リスティング制限超過",
- "xpack.maps.mapListing.limitHelpDescription": "{totalItems} 個のアイテムがありますが、listingLimit の設定により {listingLimit} 個までしか下の表に表示できません。この設定は次の場所で変更できます ",
- "xpack.maps.mapListing.listingTableTitle": "マップ",
- "xpack.maps.mapListing.noItemsDescription": "マップがないようです。作成ボタンをクリックして作成してください。",
- "xpack.maps.mapListing.noMatchDescription": "検索に一致するアイテムがありません。",
- "xpack.maps.mapListing.searchAriaLabel": "フィルターアイテム",
- "xpack.maps.mapListing.searchPlaceholder": "検索…",
"xpack.maps.mapListing.titleFieldTitle": "タイトル",
- "xpack.maps.mapListing.unableToDeleteToastTitle": "マップを削除できません",
"xpack.maps.maps.choropleth.rightSourcePlaceholder": "インデックスパターンを選択",
"xpack.maps.mapSavedObjectLabel": "マップ",
"xpack.maps.mapSettingsPanel.autoFitToBoundsLocationLabel": "自動的にマップをデータ境界に合わせる",
@@ -12191,8 +12176,6 @@
"xpack.ml.dataframe.analyticsList.expandedRow.tabs.jobSettings.state": "ステータス",
"xpack.ml.dataframe.analyticsList.expandedRow.tabs.jobSettings.stats": "統計",
"xpack.ml.dataframe.analyticsList.expandedRow.tabs.jobSettingsLabel": "ジョブの詳細",
- "xpack.ml.dataframe.analyticsList.experimentalBadgeLabel": "実験的",
- "xpack.ml.dataframe.analyticsList.experimentalBadgeTooltipContent": "データフレーム分析は実験段階の機能です。フィードバックをお待ちしています。",
"xpack.ml.dataframe.analyticsList.fetchSourceIndexPatternForCloneErrorMessage": "インデックスパターン{indexPattern}が存在するかどうかを確認するときにエラーが発生しました。{error}",
"xpack.ml.dataframe.analyticsList.forceStopModalBody": "{analyticsId}は失敗状態です。ジョブを停止して、エラーを修正する必要があります。",
"xpack.ml.dataframe.analyticsList.forceStopModalCancelButton": "キャンセル",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index 822ccf5cc8409..fb2c5341ac952 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -11297,24 +11297,9 @@
"xpack.maps.layerWizardSelect.solutionsCategoryLabel": "解决方案",
"xpack.maps.loadMap.errorAttemptingToLoadSavedMap": "无法加载地图",
"xpack.maps.map.initializeErrorTitle": "无法初始化地图",
- "xpack.maps.mapListing.advancedSettingsLinkText": "高级设置",
- "xpack.maps.mapListing.cancelTitle": "取消",
- "xpack.maps.mapListing.createMapButtonLabel": "创建地图",
- "xpack.maps.mapListing.deleteSelectedButtonLabel": "删除选定",
- "xpack.maps.mapListing.deleteSelectedItemsTitle": "删除选定项?",
- "xpack.maps.mapListing.deleteTitle": "删除",
- "xpack.maps.mapListing.deleteWarning": "您无法恢复已删除项。",
"xpack.maps.mapListing.descriptionFieldTitle": "描述",
"xpack.maps.mapListing.errorAttemptingToLoadSavedMaps": "无法加载地图",
- "xpack.maps.mapListing.limitExceededTitle": "已超过列表限制",
- "xpack.maps.mapListing.limitHelpDescription": "您有 {totalItems} 项,但您的 listingLimit 设置阻止下表显示 {listingLimit} 项以上。此设置可在以下选项下更改: ",
- "xpack.maps.mapListing.listingTableTitle": "Maps",
- "xpack.maps.mapListing.noItemsDescription": "似乎您没有任何地图。单击创建按钮来创建。",
- "xpack.maps.mapListing.noMatchDescription": "没有任何项匹配您的搜索。",
- "xpack.maps.mapListing.searchAriaLabel": "筛选项",
- "xpack.maps.mapListing.searchPlaceholder": "搜索......",
"xpack.maps.mapListing.titleFieldTitle": "标题",
- "xpack.maps.mapListing.unableToDeleteToastTitle": "无法删除地图",
"xpack.maps.maps.choropleth.rightSourcePlaceholder": "选择索引模式",
"xpack.maps.mapSavedObjectLabel": "地图",
"xpack.maps.mapSettingsPanel.autoFitToBoundsLocationLabel": "使地图自适应数据边界",
@@ -12205,8 +12190,6 @@
"xpack.ml.dataframe.analyticsList.expandedRow.tabs.jobSettings.state": "状态",
"xpack.ml.dataframe.analyticsList.expandedRow.tabs.jobSettings.stats": "统计",
"xpack.ml.dataframe.analyticsList.expandedRow.tabs.jobSettingsLabel": "作业详情",
- "xpack.ml.dataframe.analyticsList.experimentalBadgeLabel": "实验性",
- "xpack.ml.dataframe.analyticsList.experimentalBadgeTooltipContent": "数据帧分析为实验功能。我们很乐意听取您的反馈意见。",
"xpack.ml.dataframe.analyticsList.fetchSourceIndexPatternForCloneErrorMessage": "检查索引模式 {indexPattern} 是否存在时发生错误:{error}",
"xpack.ml.dataframe.analyticsList.forceStopModalBody": "{analyticsId} 处于失败状态。您必须停止该作业并修复失败问题。",
"xpack.ml.dataframe.analyticsList.forceStopModalCancelButton": "取消",
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_message_variables.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_message_variables.tsx
index e60785f70bffe..f5095101d96b5 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_message_variables.tsx
+++ b/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_message_variables.tsx
@@ -63,7 +63,7 @@ export const TextAreaWithMessageVariables: React.FunctionComponent = ({
fullWidth
isInvalid={errors && errors.length > 0 && inputTargetValue !== undefined}
name={paramsProperty}
- value={inputTargetValue}
+ value={inputTargetValue || ''}
data-test-subj={`${paramsProperty}TextArea`}
onChange={(e: React.ChangeEvent) => onChangeWithMessageVariable(e)}
onFocus={(e: React.FocusEvent) => {
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/text_field_with_message_variables.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/text_field_with_message_variables.tsx
index fc05b237ccf5e..946bf064eb9ce 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/components/text_field_with_message_variables.tsx
+++ b/x-pack/plugins/triggers_actions_ui/public/application/components/text_field_with_message_variables.tsx
@@ -50,7 +50,7 @@ export const TextFieldWithMessageVariables: React.FunctionComponent = ({
id={`${paramsProperty}Id`}
isInvalid={errors && errors.length > 0 && inputTargetValue !== undefined}
data-test-subj={`${paramsProperty}Input`}
- value={inputTargetValue}
+ value={inputTargetValue || ''}
onChange={(e: React.ChangeEvent) => onChangeWithMessageVariable(e)}
onFocus={(e: React.FocusEvent) => {
setCurrentTextElement(e.target);
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.tsx
index 00ff6fc132cdc..b53d0816ea068 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.tsx
+++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.tsx
@@ -72,10 +72,8 @@ export const ConnectorAddFlyout = ({
const [isSaving, setIsSaving] = useState(false);
const closeFlyout = useCallback(() => {
- setActionType(undefined);
- setConnector(initialConnector);
onClose();
- }, [onClose, initialConnector]);
+ }, [onClose]);
const canSave = hasSaveActionsCapability(capabilities);
diff --git a/x-pack/plugins/ui_actions_enhanced/server/dynamic_action_enhancement.ts b/x-pack/plugins/ui_actions_enhanced/server/dynamic_action_enhancement.ts
index ade78c31211ab..4cea7ddf4854a 100644
--- a/x-pack/plugins/ui_actions_enhanced/server/dynamic_action_enhancement.ts
+++ b/x-pack/plugins/ui_actions_enhanced/server/dynamic_action_enhancement.ts
@@ -6,23 +6,19 @@
import { EnhancementRegistryDefinition } from '../../../../src/plugins/embeddable/server';
import { SavedObjectReference } from '../../../../src/core/types';
-import { DynamicActionsState, SerializedEvent } from './types';
-import { AdvancedUiActionsServerPlugin } from './plugin';
+import { ActionFactory, DynamicActionsState, SerializedEvent } from './types';
import { SerializableState } from '../../../../src/plugins/kibana_utils/common';
export const dynamicActionEnhancement = (
- uiActionsEnhanced: AdvancedUiActionsServerPlugin
+ getActionFactory: (id: string) => undefined | ActionFactory
): EnhancementRegistryDefinition => {
return {
id: 'dynamicActions',
telemetry: (state: SerializableState, telemetry: Record) => {
let telemetryData = telemetry;
(state as DynamicActionsState).events.forEach((event: SerializedEvent) => {
- if (uiActionsEnhanced.getActionFactory(event.action.factoryId)) {
- telemetryData = uiActionsEnhanced
- .getActionFactory(event.action.factoryId)!
- .telemetry(event, telemetryData);
- }
+ const factory = getActionFactory(event.action.factoryId);
+ if (factory) telemetryData = factory.telemetry(event, telemetryData);
});
return telemetryData;
},
@@ -30,8 +26,9 @@ export const dynamicActionEnhancement = (
const references: SavedObjectReference[] = [];
const newState: DynamicActionsState = {
events: (state as DynamicActionsState).events.map((event: SerializedEvent) => {
- const result = uiActionsEnhanced.getActionFactory(event.action.factoryId)
- ? uiActionsEnhanced.getActionFactory(event.action.factoryId)!.extract(event)
+ const factory = getActionFactory(event.action.factoryId);
+ const result = factory
+ ? factory.extract(event)
: {
state: event,
references: [],
@@ -45,9 +42,8 @@ export const dynamicActionEnhancement = (
inject: (state: SerializableState, references: SavedObjectReference[]) => {
return {
events: (state as DynamicActionsState).events.map((event: SerializedEvent) => {
- return uiActionsEnhanced.getActionFactory(event.action.factoryId)
- ? uiActionsEnhanced.getActionFactory(event.action.factoryId)!.inject(event, references)
- : event;
+ const factory = getActionFactory(event.action.factoryId);
+ return factory ? factory.inject(event, references) : event;
}),
} as DynamicActionsState;
},
diff --git a/x-pack/plugins/ui_actions_enhanced/server/plugin.ts b/x-pack/plugins/ui_actions_enhanced/server/plugin.ts
index 718304018730d..e6362418efc66 100644
--- a/x-pack/plugins/ui_actions_enhanced/server/plugin.ts
+++ b/x-pack/plugins/ui_actions_enhanced/server/plugin.ts
@@ -5,15 +5,10 @@
*/
import { identity } from 'lodash';
-import { CoreSetup, Plugin, SavedObjectReference } from '../../../../src/core/server';
+import { CoreSetup, Plugin } from '../../../../src/core/server';
import { EmbeddableSetup } from '../../../../src/plugins/embeddable/server';
import { dynamicActionEnhancement } from './dynamic_action_enhancement';
-import {
- ActionFactoryRegistry,
- SerializedEvent,
- ActionFactoryDefinition,
- DynamicActionsState,
-} from './types';
+import { ActionFactoryRegistry, SerializedEvent, ActionFactoryDefinition } from './types';
export interface SetupContract {
registerActionFactory: (definition: ActionFactoryDefinition) => void;
@@ -32,7 +27,9 @@ export class AdvancedUiActionsServerPlugin
constructor() {}
public setup(core: CoreSetup, { embeddable }: SetupDependencies) {
- embeddable.registerEnhancement(dynamicActionEnhancement(this));
+ const getActionFactory = (actionFactoryId: string) => this.actionFactories.get(actionFactoryId);
+
+ embeddable.registerEnhancement(dynamicActionEnhancement(getActionFactory));
return {
registerActionFactory: this.registerActionFactory,
@@ -64,45 +61,4 @@ export class AdvancedUiActionsServerPlugin
migrations: definition.migrations || {},
});
};
-
- public readonly getActionFactory = (actionFactoryId: string) => {
- const actionFactory = this.actionFactories.get(actionFactoryId);
- return actionFactory;
- };
-
- public readonly telemetry = (state: DynamicActionsState, telemetry: Record = {}) => {
- state.events.forEach((event: SerializedEvent) => {
- if (this.actionFactories.has(event.action.factoryId)) {
- this.actionFactories.get(event.action.factoryId)!.telemetry(event, telemetry);
- }
- });
- return telemetry;
- };
-
- public readonly extract = (state: DynamicActionsState) => {
- const references: SavedObjectReference[] = [];
- const newState = {
- events: state.events.map((event: SerializedEvent) => {
- const result = this.actionFactories.has(event.action.factoryId)
- ? this.actionFactories.get(event.action.factoryId)!.extract(event)
- : {
- state: event,
- references: [],
- };
- result.references.forEach((r) => references.push(r));
- return result.state;
- }),
- };
- return { state: newState, references };
- };
-
- public readonly inject = (state: DynamicActionsState, references: SavedObjectReference[]) => {
- return {
- events: state.events.map((event: SerializedEvent) => {
- return this.actionFactories.has(event.action.factoryId)
- ? this.actionFactories.get(event.action.factoryId)!.inject(event, references)
- : event;
- }),
- };
- };
}
diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_ping_histogram.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_ping_histogram.test.ts
index 86e5f2876ca28..427061b6c16d4 100644
--- a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_ping_histogram.test.ts
+++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_ping_histogram.test.ts
@@ -7,8 +7,13 @@
import { getPingHistogram } from '../get_ping_histogram';
import { DYNAMIC_SETTINGS_DEFAULTS } from '../../../../common/constants';
import { elasticsearchServiceMock } from '../../../../../../../src/core/server/mocks';
+import * as intervalHelper from '../../helper/get_histogram_interval';
describe('getPingHistogram', () => {
+ beforeEach(() => {
+ jest.spyOn(intervalHelper, 'getHistogramInterval').mockReturnValue(36000);
+ });
+
const standardMockResponse: any = {
aggregations: {
timeseries: {
@@ -36,7 +41,7 @@ describe('getPingHistogram', () => {
},
};
- it.skip('returns a single bucket if array has 1', async () => {
+ it('returns a single bucket if array has 1', async () => {
expect.assertions(2);
const mockEsClient = elasticsearchServiceMock.createElasticsearchClient();
diff --git a/x-pack/plugins/uptime/server/lib/requests/get_monitor_states.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor_states.ts
index 020fcf5331188..2ff1043d79e84 100644
--- a/x-pack/plugins/uptime/server/lib/requests/get_monitor_states.ts
+++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor_states.ts
@@ -151,7 +151,7 @@ export const getHistogramForMonitors = async (
},
},
};
- const result = await queryContext.search(params);
+ const { body: result } = await queryContext.search(params);
const histoBuckets: any[] = result.aggregations?.histogram.buckets ?? [];
const simplified = histoBuckets.map((histoBucket: any): { timestamp: number; byId: any } => {
diff --git a/x-pack/test/alerting_api_integration/common/config.ts b/x-pack/test/alerting_api_integration/common/config.ts
index f9fdfaed1c79b..cb78e76bdd697 100644
--- a/x-pack/test/alerting_api_integration/common/config.ts
+++ b/x-pack/test/alerting_api_integration/common/config.ts
@@ -92,6 +92,7 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions)
...xPackApiIntegrationTestsConfig.get('kbnTestServer.serverArgs'),
`--xpack.actions.allowedHosts=${JSON.stringify(['localhost', 'some.non.existent.com'])}`,
'--xpack.encryptedSavedObjects.encryptionKey="wuGNaIhoMpk5sO4UBxgr3NyW1sFcLgIf"',
+ '--xpack.alerts.invalidateApiKeysTask.interval="15s"',
`--xpack.actions.enabledActionTypes=${JSON.stringify(enabledActionTypes)}`,
...actionsProxyUrl,
diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts
index 7ed864afac4cc..998ec6ab2ed0e 100644
--- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts
+++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts
@@ -437,6 +437,21 @@ export function defineAlertTypes(
throw new Error('this alert is intended to fail');
},
};
+ const longRunningAlertType: AlertType = {
+ id: 'test.longRunning',
+ name: 'Test: Long Running',
+ actionGroups: [
+ {
+ id: 'default',
+ name: 'Default',
+ },
+ ],
+ producer: 'alertsFixture',
+ defaultActionGroupId: 'default',
+ async executor() {
+ await new Promise((resolve) => setTimeout(resolve, 5000));
+ },
+ };
alerts.registerType(getAlwaysFiringAlertType());
alerts.registerType(getCumulativeFiringAlertType());
@@ -449,4 +464,5 @@ export function defineAlertTypes(
alerts.registerType(onlyStateVariablesAlertType);
alerts.registerType(getPatternFiringAlertType());
alerts.registerType(throwAlertType);
+ alerts.registerType(longRunningAlertType);
}
diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/plugin.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/plugin.ts
index fbf3b798500d3..d832902fe066d 100644
--- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/plugin.ts
+++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/plugin.ts
@@ -50,6 +50,7 @@ export class FixturePlugin implements Plugin,
+ res: KibanaResponseFactory
+ ): Promise> => {
+ try {
+ const [{ savedObjects }] = await core.getStartServices();
+ const savedObjectsWithTasksAndAlerts = await savedObjects.getScopedClient(req, {
+ includedHiddenTypes: ['api_key_pending_invalidation'],
+ });
+ const findResult = await savedObjectsWithTasksAndAlerts.find({
+ type: 'api_key_pending_invalidation',
+ });
+ return res.ok({
+ body: { apiKeysToInvalidate: findResult.saved_objects },
+ });
+ } catch (err) {
+ return res.badRequest({ body: err });
+ }
+ }
+ );
}
diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/update.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/update.ts
index 8836bc2e4db2f..9c3d2801c0886 100644
--- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/update.ts
+++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/update.ts
@@ -836,6 +836,80 @@ export default function createUpdateTests({ getService }: FtrProviderContext) {
}
});
+ it('should handle updates for a long running alert type without failing the underlying tasks due to invalidated ApiKey', async () => {
+ const { body: createdAlert } = await supertest
+ .post(`${getUrlPrefix(space.id)}/api/alerts/alert`)
+ .set('kbn-xsrf', 'foo')
+ .send({
+ enabled: true,
+ name: 'abc',
+ tags: ['foo'],
+ alertTypeId: 'test.longRunning',
+ consumer: 'alertsFixture',
+ schedule: { interval: '1s' },
+ throttle: '1m',
+ actions: [],
+ params: {},
+ })
+ .expect(200);
+ objectRemover.add(space.id, createdAlert.id, 'alert', 'alerts');
+ const updatedData = {
+ name: 'bcd',
+ tags: ['bar'],
+ params: {
+ foo: true,
+ },
+ schedule: { interval: '1m' },
+ actions: [],
+ throttle: '1m',
+ };
+ const response = await supertestWithoutAuth
+ .put(`${getUrlPrefix(space.id)}/api/alerts/alert/${createdAlert.id}`)
+ .set('kbn-xsrf', 'foo')
+ .auth(user.username, user.password)
+ .send(updatedData);
+
+ const statusUpdates: string[] = [];
+ await retry.try(async () => {
+ const alertTask = (await getAlertingTaskById(createdAlert.scheduledTaskId)).docs[0];
+ statusUpdates.push(alertTask.status);
+ expect(alertTask.status).to.eql('idle');
+ });
+
+ expect(statusUpdates.find((status) => status === 'failed')).to.be(undefined);
+
+ switch (scenario.id) {
+ case 'no_kibana_privileges at space1':
+ case 'space_1_all at space2':
+ case 'global_read at space1':
+ expect(response.statusCode).to.eql(403);
+ expect(response.body).to.eql({
+ error: 'Forbidden',
+ message: getConsumerUnauthorizedErrorMessage(
+ 'update',
+ 'test.longRunning',
+ 'alertsFixture'
+ ),
+ statusCode: 403,
+ });
+ break;
+ case 'superuser at space1':
+ case 'space_1_all at space1':
+ case 'space_1_all_alerts_none_actions at space1':
+ case 'space_1_all_with_restricted_fixture at space1':
+ expect(response.statusCode).to.eql(200);
+ await retry.try(async () => {
+ const alertTask = (await getAlertingTaskById(createdAlert.scheduledTaskId)).docs[0];
+ expect(alertTask.status).to.eql('idle');
+ // ensure the alert is rescheduled to a minute from now
+ ensureDatetimeIsWithinRange(Date.parse(alertTask.runAt), 60 * 1000);
+ });
+ break;
+ default:
+ throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`);
+ }
+ });
+
it('should handle updates to an alert schedule by setting the new schedule for the underlying task', async () => {
const { body: createdAlert } = await supertest
.post(`${getUrlPrefix(space.id)}/api/alerts/alert`)
diff --git a/x-pack/test/api_integration/apis/uptime/rest/__snapshots__/monitor_states_real_data.snap b/x-pack/test/api_integration/apis/uptime/rest/__snapshots__/monitor_states_real_data.snap
new file mode 100644
index 0000000000000..50625683b605d
--- /dev/null
+++ b/x-pack/test/api_integration/apis/uptime/rest/__snapshots__/monitor_states_real_data.snap
@@ -0,0 +1,369 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`monitor states endpoint will fetch monitor state data for the given down filters 1`] = `
+Object {
+ "nextPagePagination": "{\\"cursorDirection\\":\\"AFTER\\",\\"sortOrder\\":\\"ASC\\",\\"cursorKey\\":{\\"monitor_id\\":\\"0020-down\\"}}",
+ "prevPagePagination": null,
+ "summaries": Array [
+ Object {
+ "histogram": Object {
+ "points": Array [
+ Object {
+ "down": 1,
+ "timestamp": 1568172624744,
+ },
+ Object {
+ "down": 2,
+ "timestamp": 1568172677247,
+ },
+ Object {
+ "down": 1,
+ "timestamp": 1568172729750,
+ },
+ Object {
+ "down": 2,
+ "timestamp": 1568172782253,
+ },
+ Object {
+ "down": 2,
+ "timestamp": 1568172834756,
+ },
+ Object {
+ "down": 2,
+ "timestamp": 1568172887259,
+ },
+ Object {
+ "down": 1,
+ "timestamp": 1568172939762,
+ },
+ Object {
+ "down": 2,
+ "timestamp": 1568172992265,
+ },
+ Object {
+ "down": 2,
+ "timestamp": 1568173044768,
+ },
+ Object {
+ "down": 2,
+ "timestamp": 1568173097271,
+ },
+ Object {
+ "down": 1,
+ "timestamp": 1568173149774,
+ },
+ Object {
+ "down": 2,
+ "timestamp": 1568173202277,
+ },
+ ],
+ },
+ "minInterval": 52503,
+ "monitor_id": "0010-down",
+ "state": Object {
+ "monitor": Object {
+ "name": "",
+ },
+ "observer": Object {
+ "geo": Object {
+ "name": Array [
+ "mpls",
+ ],
+ },
+ },
+ "summary": Object {
+ "down": 1,
+ "status": "down",
+ "up": 0,
+ },
+ "summaryPings": Array [
+ Object {
+ "@timestamp": "2019-09-11T03:40:34.371Z",
+ "agent": Object {
+ "ephemeral_id": "412a92a8-2142-4b1a-a7a2-1afd32e12f85",
+ "hostname": "avc-x1x",
+ "id": "04e1d082-65bc-4929-8d65-d0768a2621c4",
+ "type": "heartbeat",
+ "version": "8.0.0",
+ },
+ "docId": "rZtoHm0B0I9WX_CznN_V",
+ "ecs": Object {
+ "version": "1.1.0",
+ },
+ "error": Object {
+ "message": "400 Bad Request",
+ "type": "validate",
+ },
+ "event": Object {
+ "dataset": "uptime",
+ },
+ "host": Object {
+ "name": "avc-x1x",
+ },
+ "http": Object {
+ "response": Object {
+ "body": Object {
+ "bytes": 3,
+ "content": "400",
+ "hash": "26d228663f13a88592a12d16cf9587caab0388b262d6d9f126ed62f9333aca94",
+ },
+ "status_code": 400,
+ },
+ "rtt": Object {
+ "content": Object {
+ "us": 41,
+ },
+ "response_header": Object {
+ "us": 36777,
+ },
+ "total": Object {
+ "us": 37821,
+ },
+ "validate": Object {
+ "us": 36818,
+ },
+ "write_request": Object {
+ "us": 53,
+ },
+ },
+ },
+ "monitor": Object {
+ "check_group": "d76f07d1-d445-11e9-88e3-3e80641b9c71",
+ "duration": Object {
+ "us": 37926,
+ },
+ "id": "0010-down",
+ "ip": "127.0.0.1",
+ "name": "",
+ "status": "down",
+ "type": "http",
+ },
+ "observer": Object {
+ "geo": Object {
+ "location": "37.926868, -78.024902",
+ "name": "mpls",
+ },
+ "hostname": "avc-x1x",
+ },
+ "resolve": Object {
+ "ip": "127.0.0.1",
+ "rtt": Object {
+ "us": 56,
+ },
+ },
+ "summary": Object {
+ "down": 1,
+ "up": 0,
+ },
+ "tcp": Object {
+ "rtt": Object {
+ "connect": Object {
+ "us": 890,
+ },
+ },
+ },
+ "timestamp": "2019-09-11T03:40:34.371Z",
+ "url": Object {
+ "domain": "localhost",
+ "full": "http://localhost:5678/pattern?r=400x1",
+ "path": "/pattern",
+ "port": 5678,
+ "query": "r=400x1",
+ "scheme": "http",
+ },
+ },
+ ],
+ "timestamp": "2019-09-11T03:40:34.371Z",
+ "url": Object {
+ "domain": "localhost",
+ "full": "http://localhost:5678/pattern?r=400x1",
+ "path": "/pattern",
+ "port": 5678,
+ "query": "r=400x1",
+ "scheme": "http",
+ },
+ },
+ },
+ Object {
+ "histogram": Object {
+ "points": Array [
+ Object {
+ "down": 1,
+ "timestamp": 1568172624744,
+ },
+ Object {
+ "down": 2,
+ "timestamp": 1568172677247,
+ },
+ Object {
+ "down": 1,
+ "timestamp": 1568172729750,
+ },
+ Object {
+ "down": 2,
+ "timestamp": 1568172782253,
+ },
+ Object {
+ "down": 2,
+ "timestamp": 1568172834756,
+ },
+ Object {
+ "down": 2,
+ "timestamp": 1568172887259,
+ },
+ Object {
+ "down": 1,
+ "timestamp": 1568172939762,
+ },
+ Object {
+ "down": 2,
+ "timestamp": 1568172992265,
+ },
+ Object {
+ "down": 2,
+ "timestamp": 1568173044768,
+ },
+ Object {
+ "down": 2,
+ "timestamp": 1568173097271,
+ },
+ Object {
+ "down": 1,
+ "timestamp": 1568173149774,
+ },
+ Object {
+ "down": 2,
+ "timestamp": 1568173202277,
+ },
+ ],
+ },
+ "minInterval": 52503,
+ "monitor_id": "0020-down",
+ "state": Object {
+ "monitor": Object {
+ "name": "",
+ },
+ "observer": Object {
+ "geo": Object {
+ "name": Array [
+ "mpls",
+ ],
+ },
+ },
+ "summary": Object {
+ "down": 1,
+ "status": "down",
+ "up": 0,
+ },
+ "summaryPings": Array [
+ Object {
+ "@timestamp": "2019-09-11T03:40:34.372Z",
+ "agent": Object {
+ "ephemeral_id": "412a92a8-2142-4b1a-a7a2-1afd32e12f85",
+ "hostname": "avc-x1x",
+ "id": "04e1d082-65bc-4929-8d65-d0768a2621c4",
+ "type": "heartbeat",
+ "version": "8.0.0",
+ },
+ "docId": "X5toHm0B0I9WX_CznN-6",
+ "ecs": Object {
+ "version": "1.1.0",
+ },
+ "error": Object {
+ "message": "400 Bad Request",
+ "type": "validate",
+ },
+ "event": Object {
+ "dataset": "uptime",
+ },
+ "host": Object {
+ "name": "avc-x1x",
+ },
+ "http": Object {
+ "response": Object {
+ "body": Object {
+ "bytes": 3,
+ "content": "400",
+ "hash": "26d228663f13a88592a12d16cf9587caab0388b262d6d9f126ed62f9333aca94",
+ },
+ "status_code": 400,
+ },
+ "rtt": Object {
+ "content": Object {
+ "us": 54,
+ },
+ "response_header": Object {
+ "us": 180,
+ },
+ "total": Object {
+ "us": 555,
+ },
+ "validate": Object {
+ "us": 234,
+ },
+ "write_request": Object {
+ "us": 63,
+ },
+ },
+ },
+ "monitor": Object {
+ "check_group": "d7712ecb-d445-11e9-88e3-3e80641b9c71",
+ "duration": Object {
+ "us": 14900,
+ },
+ "id": "0020-down",
+ "ip": "127.0.0.1",
+ "name": "",
+ "status": "down",
+ "type": "http",
+ },
+ "observer": Object {
+ "geo": Object {
+ "location": "37.926868, -78.024902",
+ "name": "mpls",
+ },
+ "hostname": "avc-x1x",
+ },
+ "resolve": Object {
+ "ip": "127.0.0.1",
+ "rtt": Object {
+ "us": 14294,
+ },
+ },
+ "summary": Object {
+ "down": 1,
+ "up": 0,
+ },
+ "tcp": Object {
+ "rtt": Object {
+ "connect": Object {
+ "us": 105,
+ },
+ },
+ },
+ "timestamp": "2019-09-11T03:40:34.372Z",
+ "url": Object {
+ "domain": "localhost",
+ "full": "http://localhost:5678/pattern?r=400x1",
+ "path": "/pattern",
+ "port": 5678,
+ "query": "r=400x1",
+ "scheme": "http",
+ },
+ },
+ ],
+ "timestamp": "2019-09-11T03:40:34.372Z",
+ "url": Object {
+ "domain": "localhost",
+ "full": "http://localhost:5678/pattern?r=400x1",
+ "path": "/pattern",
+ "port": 5678,
+ "query": "r=400x1",
+ "scheme": "http",
+ },
+ },
+ },
+ ],
+ "totalSummaryCount": 2000,
+}
+`;
diff --git a/x-pack/test/api_integration/apis/uptime/rest/index.ts b/x-pack/test/api_integration/apis/uptime/rest/index.ts
index f59b79a6b7bfc..6f410add0fa4d 100644
--- a/x-pack/test/api_integration/apis/uptime/rest/index.ts
+++ b/x-pack/test/api_integration/apis/uptime/rest/index.ts
@@ -9,12 +9,15 @@ import {
settingsObjectId,
settingsObjectType,
} from '../../../../../plugins/uptime/server/lib/saved_objects';
+import { registerMochaHooksForSnapshots } from '../../../../apm_api_integration/common/match_snapshot';
export default function ({ getService, loadTestFile }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const server = getService('kibanaServer');
describe('uptime REST endpoints', () => {
+ registerMochaHooksForSnapshots();
+
beforeEach('clear settings', async () => {
try {
await server.savedObjects.delete({
diff --git a/x-pack/test/api_integration/apis/uptime/rest/monitor_states_real_data.ts b/x-pack/test/api_integration/apis/uptime/rest/monitor_states_real_data.ts
index d3c49bb49ff52..08a339ed59326 100644
--- a/x-pack/test/api_integration/apis/uptime/rest/monitor_states_real_data.ts
+++ b/x-pack/test/api_integration/apis/uptime/rest/monitor_states_real_data.ts
@@ -9,6 +9,7 @@ import { isRight } from 'fp-ts/lib/Either';
import { FtrProviderContext } from '../../../ftr_provider_context';
import { MonitorSummariesResultType } from '../../../../../plugins/uptime/common/runtime_types';
import { API_URLS } from '../../../../../plugins/uptime/common/constants';
+import { expectSnapshot } from '../../../../apm_api_integration/common/match_snapshot';
interface ExpectedMonitorStatesPage {
response: any;
@@ -90,6 +91,16 @@ export default function ({ getService }: FtrProviderContext) {
});
});
+ it('will fetch monitor state data for the given down filters', async () => {
+ const statusFilter = 'down';
+ const size = 2;
+ const { body } = await supertest.get(
+ `${API_URLS.MONITOR_LIST}?dateRangeStart=${from}&dateRangeEnd=${to}&statusFilter=${statusFilter}&pageSize=${size}`
+ );
+
+ expectSnapshot(body).toMatch();
+ });
+
it('can navigate forward and backward using pagination', async () => {
const expectedResultsCount = 100;
const size = 10;
diff --git a/x-pack/test/functional/apps/maps/mvt_super_fine.js b/x-pack/test/functional/apps/maps/mvt_super_fine.js
index b5a7935a81eb5..6d86b93c3ec44 100644
--- a/x-pack/test/functional/apps/maps/mvt_super_fine.js
+++ b/x-pack/test/functional/apps/maps/mvt_super_fine.js
@@ -19,7 +19,7 @@ export default function ({ getPageObjects, getService }) {
['global_maps_all', 'test_logstash_reader', 'geoshape_data_reader'],
false
);
- await PageObjects.maps.loadSavedMap('geo grid vector grid example (SUPER_FINE resolution)');
+ await PageObjects.maps.loadSavedMap('geo grid vector grid example SUPER_FINE resolution');
});
after(async () => {
diff --git a/x-pack/test/functional/apps/maps/saved_object_management.js b/x-pack/test/functional/apps/maps/saved_object_management.js
index 277a8a5651453..8c62136472921 100644
--- a/x-pack/test/functional/apps/maps/saved_object_management.js
+++ b/x-pack/test/functional/apps/maps/saved_object_management.js
@@ -139,8 +139,8 @@ export default function ({ getPageObjects, getService }) {
await PageObjects.maps.openNewMap();
await PageObjects.maps.saveMap(MAP1_NAME);
- const count = await PageObjects.maps.getMapCountWithName(MAP1_NAME);
- expect(count).to.equal(1);
+
+ await PageObjects.maps.searchAndExpectItemsCount(MAP1_NAME, 1);
});
it('should allow saving map that crosses dateline', async () => {
@@ -148,8 +148,8 @@ export default function ({ getPageObjects, getService }) {
await PageObjects.maps.setView('64', '179', '5');
await PageObjects.maps.saveMap(MAP2_NAME);
- const count = await PageObjects.maps.getMapCountWithName(MAP2_NAME);
- expect(count).to.equal(1);
+
+ await PageObjects.maps.searchAndExpectItemsCount(MAP2_NAME, 1);
});
});
@@ -157,11 +157,9 @@ export default function ({ getPageObjects, getService }) {
it('should delete selected saved objects', async () => {
await PageObjects.maps.deleteSavedMaps(MAP_NAME_PREFIX);
- const map1Count = await PageObjects.maps.getMapCountWithName(MAP1_NAME);
- expect(map1Count).to.equal(0);
+ await PageObjects.maps.searchAndExpectItemsCount(MAP1_NAME, 0);
- const map2Count = await PageObjects.maps.getMapCountWithName(MAP2_NAME);
- expect(map2Count).to.equal(0);
+ await PageObjects.maps.searchAndExpectItemsCount(MAP2_NAME, 0);
});
});
});
diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/feature_importance.ts b/x-pack/test/functional/apps/ml/data_frame_analytics/feature_importance.ts
new file mode 100644
index 0000000000000..ff2bbd077fa8f
--- /dev/null
+++ b/x-pack/test/functional/apps/ml/data_frame_analytics/feature_importance.ts
@@ -0,0 +1,211 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import { DeepPartial } from '../../../../../plugins/ml/common/types/common';
+import { DataFrameAnalyticsConfig } from '../../../../../plugins/ml/public/application/data_frame_analytics/common';
+
+import { FtrProviderContext } from '../../../ftr_provider_context';
+
+export default function ({ getService }: FtrProviderContext) {
+ const esArchiver = getService('esArchiver');
+ const ml = getService('ml');
+
+ describe('total feature importance panel and decision path popover', function () {
+ const testDataList: Array<{
+ suiteTitle: string;
+ archive: string;
+ indexPattern: { name: string; timeField: string };
+ job: DeepPartial;
+ }> = (() => {
+ const timestamp = Date.now();
+
+ return [
+ {
+ suiteTitle: 'binary classification job',
+ archive: 'ml/ihp_outlier',
+ indexPattern: { name: 'ft_ihp_outlier', timeField: '@timestamp' },
+ job: {
+ id: `ihp_fi_binary_${timestamp}`,
+ description:
+ "Classification job based on 'ft_bank_marketing' dataset with dependentVariable 'y' and trainingPercent '35'",
+ source: {
+ index: ['ft_ihp_outlier'],
+ query: {
+ match_all: {},
+ },
+ },
+ dest: {
+ get index(): string {
+ return `user-ihp_fi_binary_${timestamp}`;
+ },
+ results_field: 'ml_central_air',
+ },
+ analyzed_fields: {
+ includes: [
+ 'CentralAir',
+ 'GarageArea',
+ 'GarageCars',
+ 'YearBuilt',
+ 'Electrical',
+ 'Neighborhood',
+ 'Heating',
+ '1stFlrSF',
+ ],
+ },
+ analysis: {
+ classification: {
+ dependent_variable: 'CentralAir',
+ num_top_feature_importance_values: 5,
+ training_percent: 35,
+ prediction_field_name: 'CentralAir_prediction',
+ num_top_classes: -1,
+ },
+ },
+ model_memory_limit: '60mb',
+ allow_lazy_start: false,
+ },
+ },
+ {
+ suiteTitle: 'multi class classification job',
+ archive: 'ml/ihp_outlier',
+ indexPattern: { name: 'ft_ihp_outlier', timeField: '@timestamp' },
+ job: {
+ id: `ihp_fi_multi_${timestamp}`,
+ description:
+ "Classification job based on 'ft_bank_marketing' dataset with dependentVariable 'y' and trainingPercent '35'",
+ source: {
+ index: ['ft_ihp_outlier'],
+ query: {
+ match_all: {},
+ },
+ },
+ dest: {
+ get index(): string {
+ return `user-ihp_fi_multi_${timestamp}`;
+ },
+ results_field: 'ml_heating_qc',
+ },
+ analyzed_fields: {
+ includes: [
+ 'CentralAir',
+ 'GarageArea',
+ 'GarageCars',
+ 'Electrical',
+ 'Neighborhood',
+ 'Heating',
+ '1stFlrSF',
+ 'HeatingQC',
+ ],
+ },
+ analysis: {
+ classification: {
+ dependent_variable: 'HeatingQC',
+ num_top_feature_importance_values: 5,
+ training_percent: 35,
+ prediction_field_name: 'heatingqc',
+ num_top_classes: -1,
+ },
+ },
+ model_memory_limit: '60mb',
+ allow_lazy_start: false,
+ },
+ },
+ {
+ suiteTitle: 'regression job',
+ archive: 'ml/egs_regression',
+ indexPattern: { name: 'ft_egs_regression', timeField: '@timestamp' },
+ job: {
+ id: `egs_fi_reg_${timestamp}`,
+ description: 'This is the job description',
+ source: {
+ index: ['ft_egs_regression'],
+ query: {
+ match_all: {},
+ },
+ },
+ dest: {
+ get index(): string {
+ return `user-egs_fi_reg_${timestamp}`;
+ },
+ results_field: 'ml',
+ },
+ analysis: {
+ regression: {
+ prediction_field_name: 'test',
+ dependent_variable: 'stab',
+ num_top_feature_importance_values: 5,
+ training_percent: 35,
+ },
+ },
+ analyzed_fields: {
+ includes: [
+ 'g1',
+ 'g2',
+ 'g3',
+ 'g4',
+ 'p1',
+ 'p2',
+ 'p3',
+ 'p4',
+ 'stab',
+ 'tau1',
+ 'tau2',
+ 'tau3',
+ 'tau4',
+ ],
+ excludes: [],
+ },
+ model_memory_limit: '20mb',
+ },
+ },
+ ];
+ })();
+
+ before(async () => {
+ await ml.testResources.setKibanaTimeZoneToUTC();
+ await ml.securityUI.loginAsMlPowerUser();
+ for (const testData of testDataList) {
+ await esArchiver.loadIfNeeded(testData.archive);
+ await ml.testResources.createIndexPatternIfNeeded(
+ testData.indexPattern.name,
+ testData.indexPattern.timeField
+ );
+ await ml.api.createAndRunDFAJob(testData.job as DataFrameAnalyticsConfig);
+ }
+ });
+
+ after(async () => {
+ await ml.api.cleanMlIndices();
+ });
+
+ for (const testData of testDataList) {
+ describe(`${testData.suiteTitle}`, function () {
+ before(async () => {
+ await ml.navigation.navigateToMl();
+ await ml.navigation.navigateToDataFrameAnalytics();
+ await ml.dataFrameAnalyticsTable.waitForAnalyticsToLoad();
+ await ml.dataFrameAnalyticsTable.openResultsView(testData.job.id as string);
+ });
+
+ after(async () => {
+ await ml.api.deleteIndices(testData.job.dest!.index as string);
+ await ml.testResources.deleteIndexPatternByTitle(testData.job.dest!.index as string);
+ });
+
+ it('should display the total feature importance in the results view', async () => {
+ await ml.dataFrameAnalyticsResults.assertTotalFeatureImportanceEvaluatePanelExists();
+ });
+
+ it('should display the feature importance decision path in the data grid', async () => {
+ await ml.dataFrameAnalyticsResults.assertResultsTableExists();
+ await ml.dataFrameAnalyticsResults.assertResultsTableNotEmpty();
+ await ml.dataFrameAnalyticsResults.openFeatureImportanceDecisionPathPopover();
+ await ml.dataFrameAnalyticsResults.assertFeatureImportanceDecisionPathElementsExists();
+ await ml.dataFrameAnalyticsResults.assertFeatureImportanceDecisionPathChartElementsExists();
+ });
+ });
+ }
+ });
+}
diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/index.ts b/x-pack/test/functional/apps/ml/data_frame_analytics/index.ts
index 0202c8431ce34..a57d26b536b4f 100644
--- a/x-pack/test/functional/apps/ml/data_frame_analytics/index.ts
+++ b/x-pack/test/functional/apps/ml/data_frame_analytics/index.ts
@@ -13,5 +13,6 @@ export default function ({ loadTestFile }: FtrProviderContext) {
loadTestFile(require.resolve('./regression_creation'));
loadTestFile(require.resolve('./classification_creation'));
loadTestFile(require.resolve('./cloning'));
+ loadTestFile(require.resolve('./feature_importance'));
});
}
diff --git a/x-pack/test/functional/es_archives/discover/default/mappings.json b/x-pack/test/functional/es_archives/discover/default/mappings.json
index 82002c095bcc5..53bbe8a5baa5b 100644
--- a/x-pack/test/functional/es_archives/discover/default/mappings.json
+++ b/x-pack/test/functional/es_archives/discover/default/mappings.json
@@ -93,6 +93,9 @@
},
"title": {
"type": "text"
+ },
+ "fieldAttrs": {
+ "type": "text"
}
}
},
diff --git a/x-pack/test/functional/es_archives/maps/kibana/data.json b/x-pack/test/functional/es_archives/maps/kibana/data.json
index e3a8743e60897..79e8c14cc3982 100644
--- a/x-pack/test/functional/es_archives/maps/kibana/data.json
+++ b/x-pack/test/functional/es_archives/maps/kibana/data.json
@@ -638,7 +638,7 @@
"description": "",
"layerListJSON": "[{\"id\":\"g1xkv\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"resolution\": \"SUPER_FINE\",\"type\":\"ES_GEO_GRID\",\"id\":\"9305f6ea-4518-4c06-95b9-33321aa38d6a\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\",\"geoField\":\"geo.coordinates\",\"requestType\":\"grid\",\"metrics\":[{\"type\":\"count\"},{\"type\":\"max\",\"field\":\"bytes\"}]},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"max of bytes\",\"name\":\"max_of_bytes\",\"origin\":\"source\"},\"color\":\"Blues\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#cccccc\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"Count\",\"name\":\"doc_count\",\"origin\":\"source\"},\"minSize\":4,\"maxSize\":32}}},\"temporary\":true,\"previousStyle\":null},\"type\":\"TILED_VECTOR\"}]",
"mapStateJSON": "{\"zoom\":3.59,\"center\":{\"lon\":-98.05765,\"lat\":38.32288},\"timeFilters\":{\"from\":\"2015-09-20T00:00:00.000Z\",\"to\":\"2015-09-20T01:00:00.000Z\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":1000}}",
- "title": "geo grid vector grid example (SUPER_FINE resolution)",
+ "title": "geo grid vector grid example SUPER_FINE resolution",
"uiStateJSON": "{\"isDarkMode\":false}"
},
"type": "map"
diff --git a/x-pack/test/functional/page_objects/gis_page.ts b/x-pack/test/functional/page_objects/gis_page.ts
index c4f1bd7dc2a6b..7e22acf785d36 100644
--- a/x-pack/test/functional/page_objects/gis_page.ts
+++ b/x-pack/test/functional/page_objects/gis_page.ts
@@ -21,6 +21,7 @@ export function GisPageProvider({ getService, getPageObjects }: FtrProviderConte
const renderable = getService('renderable');
const browser = getService('browser');
const MenuToggle = getService('MenuToggle');
+ const listingTable = getService('listingTable');
const setViewPopoverToggle = new MenuToggle({
name: 'SetView Popover',
@@ -120,13 +121,10 @@ export function GisPageProvider({ getService, getPageObjects }: FtrProviderConte
await retry.try(async () => {
await this.searchForMapWithName(name);
- await this.selectMap(name);
+ await listingTable.clickItemLink('map', name);
await PageObjects.header.waitUntilLoadingHasFinished();
-
- const onMapListingPage = await this.onMapListingPage();
- if (onMapListingPage) {
- throw new Error(`Failed to open map ${name}`);
- }
+ // check Map landing page is not present
+ await testSubjects.missingOrFail('mapLandingPage', { timeout: 10000 });
});
await this.waitForLayersToLoad();
@@ -134,8 +132,8 @@ export function GisPageProvider({ getService, getPageObjects }: FtrProviderConte
async deleteSavedMaps(search: string) {
await this.searchForMapWithName(search);
- await testSubjects.click('checkboxSelectAll');
- await testSubjects.click('deleteSelectedItems');
+ await listingTable.checkListingSelectAllCheckbox();
+ await listingTable.clickDeleteSelected();
await PageObjects.common.clickConfirmOnModal();
await PageObjects.header.waitUntilLoadingHasFinished();
@@ -150,7 +148,7 @@ export function GisPageProvider({ getService, getPageObjects }: FtrProviderConte
await renderable.waitForRender();
}
- async saveMap(name: string, uncheckReturnToOriginModeSwitch = false) {
+ async saveMap(name: string, uncheckReturnToOriginModeSwitch = false, tags?: string[]) {
await testSubjects.click('mapSaveButton');
await testSubjects.setValue('savedObjectTitle', name);
if (uncheckReturnToOriginModeSwitch) {
@@ -162,6 +160,13 @@ export function GisPageProvider({ getService, getPageObjects }: FtrProviderConte
}
await testSubjects.setEuiSwitch('returnToOriginModeSwitch', 'uncheck');
}
+ if (tags) {
+ await testSubjects.click('savedObjectTagSelector');
+ for (const tagName of tags) {
+ await testSubjects.click(`tagSelectorOption-${tagName.replace(' ', '_')}`);
+ }
+ await testSubjects.click('savedObjectTitle');
+ }
await testSubjects.clickWhenNotDisabled('confirmSaveSavedObjectButton');
}
@@ -174,7 +179,7 @@ export function GisPageProvider({ getService, getPageObjects }: FtrProviderConte
}
async expectMissingCreateNewButton() {
- await testSubjects.missingOrFail('newMapLink');
+ await testSubjects.missingOrFail('newItemButton');
}
async expectMissingAddLayerButton() {
@@ -187,8 +192,7 @@ export function GisPageProvider({ getService, getPageObjects }: FtrProviderConte
async onMapListingPage() {
log.debug(`onMapListingPage`);
- const exists = await testSubjects.exists('mapsListingPage', { timeout: 3500 });
- return exists;
+ return await listingTable.onListingPage('map');
}
async searchForMapWithName(name: string) {
@@ -196,21 +200,11 @@ export function GisPageProvider({ getService, getPageObjects }: FtrProviderConte
await this.gotoMapListingPage();
- await retry.try(async () => {
- const searchFilter = await testSubjects.find('searchFilter');
- await searchFilter.clearValue();
- await searchFilter.click();
- await searchFilter.type(name);
- await PageObjects.common.pressEnterKey();
- });
+ await listingTable.searchForItemWithName(name);
await PageObjects.header.waitUntilLoadingHasFinished();
}
- async selectMap(name: string) {
- await testSubjects.click(`mapListingTitleLink-${name.split(' ').join('-')}`);
- }
-
async getHits() {
await inspector.open();
await inspector.openInspectorRequestsView();
@@ -232,13 +226,11 @@ export function GisPageProvider({ getService, getPageObjects }: FtrProviderConte
}
}
- async getMapCountWithName(name: string) {
+ async searchAndExpectItemsCount(name: string, count: number) {
await this.gotoMapListingPage();
- log.debug(`getMapCountWithName: ${name}`);
- await this.searchForMapWithName(name);
- const buttons = await find.allByButtonText(name);
- return buttons.length;
+ log.debug(`searchAndExpectItemsCount: ${name}`);
+ await listingTable.searchAndExpectItemsCount('map', name, count);
}
async setView(lat: number, lon: number, zoom: number) {
diff --git a/x-pack/test/functional/services/ml/data_frame_analytics_results.ts b/x-pack/test/functional/services/ml/data_frame_analytics_results.ts
index 8781a2cd216f2..1ac11a0149897 100644
--- a/x-pack/test/functional/services/ml/data_frame_analytics_results.ts
+++ b/x-pack/test/functional/services/ml/data_frame_analytics_results.ts
@@ -5,12 +5,14 @@
*/
import expect from '@kbn/expect';
+import { WebElementWrapper } from 'test/functional/services/lib/web_element_wrapper';
import { FtrProviderContext } from '../../ftr_provider_context';
export function MachineLearningDataFrameAnalyticsResultsProvider({
getService,
}: FtrProviderContext) {
+ const retry = getService('retry');
const testSubjects = getService('testSubjects');
return {
@@ -60,5 +62,59 @@ export function MachineLearningDataFrameAnalyticsResultsProvider({
`DFA results table should have at least one row (got '${resultTableRows.length}')`
);
},
+
+ async assertTotalFeatureImportanceEvaluatePanelExists() {
+ await testSubjects.existOrFail('mlDFExpandableSection-FeatureImportanceSummary');
+ await testSubjects.existOrFail('mlTotalFeatureImportanceChart', { timeout: 5000 });
+ },
+
+ async assertFeatureImportanceDecisionPathElementsExists() {
+ await testSubjects.existOrFail('mlDFADecisionPathPopoverTab-decision_path_chart', {
+ timeout: 5000,
+ });
+ await testSubjects.existOrFail('mlDFADecisionPathPopoverTab-decision_path_json', {
+ timeout: 5000,
+ });
+ },
+
+ async assertFeatureImportanceDecisionPathChartElementsExists() {
+ await testSubjects.existOrFail('mlDFADecisionPathChart', {
+ timeout: 5000,
+ });
+ },
+
+ async openFeatureImportanceDecisionPathPopover() {
+ this.assertResultsTableNotEmpty();
+
+ const featureImportanceCell = await this.getFirstFeatureImportanceCell();
+ const interactionButton = await featureImportanceCell.findByTagName('button');
+
+ // simulate hover and wait for button to appear
+ await featureImportanceCell.moveMouseTo();
+ await this.waitForInteractionButtonToDisplay(interactionButton);
+
+ // open popover
+ await interactionButton.click();
+ await testSubjects.existOrFail('mlDFADecisionPathPopover');
+ },
+
+ async getFirstFeatureImportanceCell(): Promise {
+ // get first row of the data grid
+ const firstDataGridRow = await testSubjects.find(
+ 'mlExplorationDataGrid loaded > dataGridRow'
+ );
+ // find the feature importance cell in that row
+ const featureImportanceCell = await firstDataGridRow.findByCssSelector(
+ '[data-test-subj="dataGridRowCell"][class*="featureImportance"]'
+ );
+ return featureImportanceCell;
+ },
+
+ async waitForInteractionButtonToDisplay(interactionButton: WebElementWrapper) {
+ await retry.tryForTime(5000, async () => {
+ const buttonVisible = await interactionButton.isDisplayed();
+ expect(buttonVisible).to.equal(true, 'Expected data grid cell button to be visible');
+ });
+ },
};
}
diff --git a/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/_find.ts b/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/_find.ts
index 4f08134365e95..8734b7cf5bb68 100644
--- a/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/_find.ts
+++ b/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/_find.ts
@@ -60,6 +60,7 @@ export default function ({ getService }: FtrProviderContext) {
USERS.DEFAULT_SPACE_SO_TAGGING_WRITE_USER,
USERS.DEFAULT_SPACE_DASHBOARD_READ_USER,
USERS.DEFAULT_SPACE_VISUALIZE_READ_USER,
+ USERS.DEFAULT_SPACE_MAPS_READ_USER,
],
unauthorized: [USERS.NOT_A_KIBANA_USER, USERS.DEFAULT_SPACE_ADVANCED_SETTINGS_READ_USER],
};
diff --git a/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/create.ts b/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/create.ts
index 70884ba6c968b..8ca92ac472c6e 100644
--- a/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/create.ts
+++ b/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/create.ts
@@ -60,6 +60,7 @@ export default function ({ getService }: FtrProviderContext) {
USERS.DEFAULT_SPACE_DASHBOARD_READ_USER,
USERS.DEFAULT_SPACE_VISUALIZE_READ_USER,
USERS.DEFAULT_SPACE_ADVANCED_SETTINGS_READ_USER,
+ USERS.DEFAULT_SPACE_MAPS_READ_USER,
USERS.NOT_A_KIBANA_USER,
],
};
diff --git a/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/delete.ts b/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/delete.ts
index 64f120fd75629..a2e3630622d67 100644
--- a/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/delete.ts
+++ b/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/delete.ts
@@ -53,6 +53,7 @@ export default function ({ getService }: FtrProviderContext) {
USERS.DEFAULT_SPACE_DASHBOARD_READ_USER,
USERS.DEFAULT_SPACE_VISUALIZE_READ_USER,
USERS.DEFAULT_SPACE_ADVANCED_SETTINGS_READ_USER,
+ USERS.DEFAULT_SPACE_MAPS_READ_USER,
USERS.NOT_A_KIBANA_USER,
],
};
diff --git a/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/get.ts b/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/get.ts
index 1a354bbbcb660..9cde766b4f514 100644
--- a/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/get.ts
+++ b/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/get.ts
@@ -57,6 +57,7 @@ export default function ({ getService }: FtrProviderContext) {
USERS.DEFAULT_SPACE_SO_TAGGING_WRITE_USER,
USERS.DEFAULT_SPACE_DASHBOARD_READ_USER,
USERS.DEFAULT_SPACE_VISUALIZE_READ_USER,
+ USERS.DEFAULT_SPACE_MAPS_READ_USER,
],
unauthorized: [USERS.NOT_A_KIBANA_USER, USERS.DEFAULT_SPACE_ADVANCED_SETTINGS_READ_USER],
};
diff --git a/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/get_all.ts b/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/get_all.ts
index 61b859cf81992..677bdee56ed8b 100644
--- a/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/get_all.ts
+++ b/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/get_all.ts
@@ -63,6 +63,7 @@ export default function ({ getService }: FtrProviderContext) {
USERS.DEFAULT_SPACE_SO_TAGGING_WRITE_USER,
USERS.DEFAULT_SPACE_DASHBOARD_READ_USER,
USERS.DEFAULT_SPACE_VISUALIZE_READ_USER,
+ USERS.DEFAULT_SPACE_MAPS_READ_USER,
],
unauthorized: [USERS.NOT_A_KIBANA_USER, USERS.DEFAULT_SPACE_ADVANCED_SETTINGS_READ_USER],
};
diff --git a/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/update.ts b/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/update.ts
index 77bf9d7ca3287..3347eca9920d6 100644
--- a/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/update.ts
+++ b/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/update.ts
@@ -60,6 +60,7 @@ export default function ({ getService }: FtrProviderContext) {
USERS.DEFAULT_SPACE_DASHBOARD_READ_USER,
USERS.DEFAULT_SPACE_VISUALIZE_READ_USER,
USERS.DEFAULT_SPACE_ADVANCED_SETTINGS_READ_USER,
+ USERS.DEFAULT_SPACE_MAPS_READ_USER,
USERS.NOT_A_KIBANA_USER,
],
};
diff --git a/x-pack/test/saved_object_tagging/common/fixtures/es_archiver/maps/data.json b/x-pack/test/saved_object_tagging/common/fixtures/es_archiver/maps/data.json
new file mode 100644
index 0000000000000..cdaf4fe171ec0
--- /dev/null
+++ b/x-pack/test/saved_object_tagging/common/fixtures/es_archiver/maps/data.json
@@ -0,0 +1,210 @@
+{
+ "type": "doc",
+ "value": {
+ "id": "space:default",
+ "index": ".kibana",
+ "source": {
+ "space": {
+ "_reserved": true,
+ "description": "This is the default space",
+ "name": "Default Space"
+ },
+ "type": "space",
+ "updated_at": "2017-09-21T18:49:16.270Z"
+ },
+ "type": "doc"
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "id": "tag:tag-1",
+ "index": ".kibana",
+ "source": {
+ "tag": {
+ "name": "tag-1",
+ "description": "My first tag!",
+ "color": "#FF00FF"
+ },
+ "type": "tag",
+ "updated_at": "2017-09-21T18:49:16.270Z"
+ },
+ "type": "doc"
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "id": "tag:tag-2",
+ "index": ".kibana",
+ "source": {
+ "tag": {
+ "name": "tag-2",
+ "description": "Another awesome tag",
+ "color": "#11FF22"
+ },
+ "type": "tag",
+ "updated_at": "2017-09-21T18:49:16.270Z"
+ },
+ "type": "doc"
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "id": "tag:tag-3",
+ "index": ".kibana",
+ "source": {
+ "tag": {
+ "name": "tag-3",
+ "description": "Last but not least",
+ "color": "#AA0077"
+ },
+ "type": "tag",
+ "updated_at": "2017-09-21T18:49:16.270Z"
+ },
+ "type": "doc"
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "id": "config:6.3.0",
+ "index": ".kibana",
+ "source": {
+ "config": {
+ "buildNum": 8467,
+ "defaultIndex": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c"
+ },
+ "references": [
+ ],
+ "type": "config",
+ "updated_at": "2018-04-11T20:43:55.434Z"
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "id": "map:63af0ed0-2515-11eb-8f44-eda8d4b698b3",
+ "index": ".kibana",
+ "source": {
+ "map": {
+ "title" : "map 3 (tag-1 and tag-3)",
+ "description" : "",
+ "layerListJSON" : "[{\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"isAutoSelect\":true},\"id\":\"d897b506-e719-42b8-9927-351eedd7d357\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"style\":{\"type\":\"TILE\"},\"type\":\"VECTOR_TILE\"}]",
+ "mapStateJSON" : "{\"zoom\":0.97,\"center\":{\"lon\":0,\"lat\":19.94277},\"timeFilters\":{\"from\":\"now-15m\",\"to\":\"now\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":0},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"settings\":{\"autoFitToDataBounds\":false,\"initialLocation\":\"LAST_SAVED_LOCATION\",\"fixedLocation\":{\"lat\":0,\"lon\":0,\"zoom\":2},\"browserLocation\":{\"zoom\":2},\"maxZoom\":24,\"minZoom\":0,\"showSpatialFilters\":true,\"spatialFiltersAlpa\":0.3,\"spatialFiltersFillColor\":\"#DA8B45\",\"spatialFiltersLineColor\":\"#DA8B45\"}}",
+ "uiStateJSON" : "{\"isLayerTOCOpen\":true,\"openTOCDetails\":[]}"
+ },
+ "type" : "map",
+ "references" : [
+ {
+ "type" : "tag",
+ "id" : "tag-1",
+ "name" : "tag-ref-tag-1"
+ },
+ {
+ "type" : "tag",
+ "id" : "tag-3",
+ "name" : "tag-ref-tag-3"
+ }
+ ],
+ "migrationVersion" : {
+ "map" : "7.10.0"
+ },
+ "updated_at" : "2020-11-12T18:32:16.189Z"
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "id": "map:4afc6d10-2515-11eb-8f44-eda8d4b698b3",
+ "index": ".kibana",
+ "source": {
+ "map" : {
+ "title" : "map 1 (tag-2)",
+ "description" : "",
+ "layerListJSON" : "[{\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"isAutoSelect\":true},\"id\":\"6a91fb66-465c-4193-8c59-9b3f5f262756\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"style\":{\"type\":\"TILE\"},\"type\":\"VECTOR_TILE\"}]",
+ "mapStateJSON" : "{\"zoom\":0.97,\"center\":{\"lon\":0,\"lat\":16.22097},\"timeFilters\":{\"from\":\"now-15m\",\"to\":\"now\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":0},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"settings\":{\"autoFitToDataBounds\":false,\"initialLocation\":\"LAST_SAVED_LOCATION\",\"fixedLocation\":{\"lat\":0,\"lon\":0,\"zoom\":2},\"browserLocation\":{\"zoom\":2},\"maxZoom\":24,\"minZoom\":0,\"showSpatialFilters\":true,\"spatialFiltersAlpa\":0.3,\"spatialFiltersFillColor\":\"#DA8B45\",\"spatialFiltersLineColor\":\"#DA8B45\"}}",
+ "uiStateJSON" : "{\"isLayerTOCOpen\":true,\"openTOCDetails\":[]}"
+ },
+ "type" : "map",
+ "references" : [
+ {
+ "type" : "tag",
+ "id" : "tag-2",
+ "name" : "tag-ref-tag-2"
+ }
+ ],
+ "migrationVersion" : {
+ "map" : "7.10.0"
+ },
+ "updated_at" : "2020-11-12T18:31:34.753Z"
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "id": "map:562cce50-2515-11eb-8f44-eda8d4b698b3",
+ "index": ".kibana",
+ "source": {
+ "map" : {
+ "title" : "map 2 (tag-3)",
+ "description" : "",
+ "layerListJSON" : "[{\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"isAutoSelect\":true},\"id\":\"285d5190-aaf1-4dfc-912b-9c7d9e0104a8\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"style\":{\"type\":\"TILE\"},\"type\":\"VECTOR_TILE\"}]",
+ "mapStateJSON" : "{\"zoom\":0.97,\"center\":{\"lon\":0,\"lat\":19.94277},\"timeFilters\":{\"from\":\"now-15m\",\"to\":\"now\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":0},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"settings\":{\"autoFitToDataBounds\":false,\"initialLocation\":\"LAST_SAVED_LOCATION\",\"fixedLocation\":{\"lat\":0,\"lon\":0,\"zoom\":2},\"browserLocation\":{\"zoom\":2},\"maxZoom\":24,\"minZoom\":0,\"showSpatialFilters\":true,\"spatialFiltersAlpa\":0.3,\"spatialFiltersFillColor\":\"#DA8B45\",\"spatialFiltersLineColor\":\"#DA8B45\"}}",
+ "uiStateJSON" : "{\"isLayerTOCOpen\":true,\"openTOCDetails\":[]}"
+ },
+ "type" : "map",
+ "references" : [
+ {
+ "type" : "tag",
+ "id" : "tag-3",
+ "name" : "tag-ref-tag-3"
+ }
+ ],
+ "migrationVersion" : {
+ "map" : "7.10.0"
+ },
+ "updated_at" : "2020-11-12T18:31:53.525Z"
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "id": "map:6f021340-2515-11eb-8f44-eda8d4b698b3",
+ "index": ".kibana",
+ "source": {
+ "map" : {
+ "title" : "map 4 (tag-1)",
+ "description" : "",
+ "layerListJSON" : "[{\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"isAutoSelect\":true},\"id\":\"3deeb666-33cf-4e9a-ab78-e453ed9d721d\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"style\":{\"type\":\"TILE\"},\"type\":\"VECTOR_TILE\"}]",
+ "mapStateJSON" : "{\"zoom\":0.97,\"center\":{\"lon\":0,\"lat\":19.94277},\"timeFilters\":{\"from\":\"now-15m\",\"to\":\"now\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":0},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"settings\":{\"autoFitToDataBounds\":false,\"initialLocation\":\"LAST_SAVED_LOCATION\",\"fixedLocation\":{\"lat\":0,\"lon\":0,\"zoom\":2},\"browserLocation\":{\"zoom\":2},\"maxZoom\":24,\"minZoom\":0,\"showSpatialFilters\":true,\"spatialFiltersAlpa\":0.3,\"spatialFiltersFillColor\":\"#DA8B45\",\"spatialFiltersLineColor\":\"#DA8B45\"}}",
+ "uiStateJSON" : "{\"isLayerTOCOpen\":true,\"openTOCDetails\":[]}"
+ },
+ "type" : "map",
+ "references" : [
+ {
+ "type" : "tag",
+ "id" : "tag-1",
+ "name" : "tag-ref-tag-1"
+ }
+ ],
+ "migrationVersion" : {
+ "map" : "7.10.0"
+ },
+ "updated_at" : "2020-11-12T18:32:35.188Z"
+ }
+ }
+}
diff --git a/x-pack/test/saved_object_tagging/common/lib/authentication.ts b/x-pack/test/saved_object_tagging/common/lib/authentication.ts
index c318755bedcdd..8917057ad685e 100644
--- a/x-pack/test/saved_object_tagging/common/lib/authentication.ts
+++ b/x-pack/test/saved_object_tagging/common/lib/authentication.ts
@@ -118,6 +118,19 @@ export const ROLES = {
],
},
},
+ KIBANA_RBAC_DEFAULT_SPACE_MAPS_READ_USER: {
+ name: 'kibana_rbac_default_space_maps_read_user',
+ privileges: {
+ kibana: [
+ {
+ feature: {
+ maps: ['read'],
+ },
+ spaces: ['default'],
+ },
+ ],
+ },
+ },
};
export const USERS = {
@@ -185,4 +198,9 @@ export const USERS = {
password: 'password',
roles: [ROLES.KIBANA_RBAC_DEFAULT_SPACE_ADVANCED_SETTINGS_READ_USER.name],
},
+ DEFAULT_SPACE_MAPS_READ_USER: {
+ username: 'a_kibana_rbac_default_space_maps_read_user',
+ password: 'password',
+ roles: [ROLES.KIBANA_RBAC_DEFAULT_SPACE_MAPS_READ_USER.name],
+ },
};
diff --git a/x-pack/test/saved_object_tagging/functional/tests/index.ts b/x-pack/test/saved_object_tagging/functional/tests/index.ts
index 43673487ba74f..0ddfa64d682a8 100644
--- a/x-pack/test/saved_object_tagging/functional/tests/index.ts
+++ b/x-pack/test/saved_object_tagging/functional/tests/index.ts
@@ -23,5 +23,6 @@ export default function ({ loadTestFile, getService }: FtrProviderContext) {
loadTestFile(require.resolve('./visualize_integration'));
loadTestFile(require.resolve('./dashboard_integration'));
loadTestFile(require.resolve('./feature_control'));
+ loadTestFile(require.resolve('./maps_integration'));
});
}
diff --git a/x-pack/test/saved_object_tagging/functional/tests/maps_integration.ts b/x-pack/test/saved_object_tagging/functional/tests/maps_integration.ts
new file mode 100644
index 0000000000000..4e44659b4fc67
--- /dev/null
+++ b/x-pack/test/saved_object_tagging/functional/tests/maps_integration.ts
@@ -0,0 +1,139 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import expect from '@kbn/expect';
+import { FtrProviderContext } from '../ftr_provider_context';
+
+// eslint-disable-next-line import/no-default-export
+export default function ({ getPageObjects, getService }: FtrProviderContext) {
+ const esArchiver = getService('esArchiver');
+ const listingTable = getService('listingTable');
+ const testSubjects = getService('testSubjects');
+ const find = getService('find');
+ const PageObjects = getPageObjects(['maps', 'tagManagement', 'common']);
+
+ /**
+ * Select tags in the searchbar's tag filter.
+ */
+ const selectFilterTags = async (...tagNames: string[]) => {
+ // open the filter dropdown
+ const filterButton = await find.byCssSelector('.euiFilterGroup .euiFilterButton');
+ await filterButton.click();
+ // select the tags
+ for (const tagName of tagNames) {
+ await testSubjects.click(
+ `tag-searchbar-option-${PageObjects.tagManagement.testSubjFriendly(tagName)}`
+ );
+ }
+ // click elsewhere to close the filter dropdown
+ const searchFilter = await find.byCssSelector('main .euiFieldSearch');
+ await searchFilter.click();
+ };
+
+ describe('maps integration', () => {
+ before(async () => {
+ await esArchiver.load('maps');
+ });
+ after(async () => {
+ await esArchiver.unload('maps');
+ });
+
+ describe('listing', () => {
+ beforeEach(async () => {
+ await PageObjects.common.navigateToUrlWithBrowserHistory('maps', '/');
+ await PageObjects.maps.gotoMapListingPage();
+ });
+
+ it('allows to manually type tag filter query', async () => {
+ await listingTable.searchForItemWithName('tag:(tag-1)', { escape: false });
+
+ await listingTable.expectItemsCount('map', 2);
+ const itemNames = await listingTable.getAllItemsNames();
+ expect(itemNames).to.eql(['map 3 (tag-1 and tag-3)', 'map 4 (tag-1)']);
+ });
+
+ it('allows to filter by selecting a tag in the filter menu', async () => {
+ await selectFilterTags('tag-3');
+
+ await listingTable.expectItemsCount('map', 2);
+ const itemNames = await listingTable.getAllItemsNames();
+ expect(itemNames).to.eql(['map 3 (tag-1 and tag-3)', 'map 2 (tag-3)']);
+ });
+
+ it('allows to filter by multiple tags', async () => {
+ await selectFilterTags('tag-2', 'tag-3');
+
+ await listingTable.expectItemsCount('map', 3);
+ const itemNames = await listingTable.getAllItemsNames();
+ expect(itemNames).to.eql(['map 3 (tag-1 and tag-3)', 'map 1 (tag-2)', 'map 2 (tag-3)']);
+ });
+ });
+
+ describe('creating', () => {
+ beforeEach(async () => {
+ await PageObjects.maps.openNewMap();
+ });
+
+ it('allows to select tags for a new map', async () => {
+ await PageObjects.maps.saveMap('my-new-map', false, ['tag-1', 'tag-3']);
+
+ await PageObjects.maps.gotoMapListingPage();
+ await selectFilterTags('tag-1');
+ const itemNames = await listingTable.getAllItemsNames();
+ expect(itemNames).to.contain('my-new-map');
+ });
+
+ it('allows to create a tag from the tag selector', async () => {
+ const { tagModal } = PageObjects.tagManagement;
+
+ await testSubjects.click('mapSaveButton');
+ await testSubjects.setValue('savedObjectTitle', 'map-with-new-tag');
+
+ await testSubjects.click('savedObjectTagSelector');
+ await testSubjects.click(`tagSelectorOption-action__create`);
+
+ expect(await tagModal.isOpened()).to.be(true);
+
+ await tagModal.fillForm(
+ {
+ name: 'my-new-tag',
+ color: '#FFCC33',
+ description: '',
+ },
+ {
+ submit: true,
+ }
+ );
+
+ expect(await tagModal.isOpened()).to.be(false);
+
+ await testSubjects.click('confirmSaveSavedObjectButton');
+
+ await PageObjects.maps.gotoMapListingPage();
+ await selectFilterTags('my-new-tag');
+ const itemNames = await listingTable.getAllItemsNames();
+ expect(itemNames).to.contain('map-with-new-tag');
+ });
+ });
+
+ describe('editing', () => {
+ beforeEach(async () => {
+ await PageObjects.common.navigateToUrlWithBrowserHistory('maps', '/');
+ });
+
+ it('allows to select tags for an existing map', async () => {
+ await listingTable.clickItemLink('map', 'map 4 (tag-1)');
+
+ await PageObjects.maps.saveMap('map 4 (tag-1)', false, ['tag-3']);
+
+ await PageObjects.maps.gotoMapListingPage();
+ await selectFilterTags('tag-3');
+ const itemNames = await listingTable.getAllItemsNames();
+ expect(itemNames).to.contain('map 4 (tag-1)');
+ });
+ });
+ });
+}
diff --git a/yarn.lock b/yarn.lock
index 3497fdf83d7dd..91ae4b236adf3 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5277,10 +5277,10 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.4.tgz#cdfbb62e26c7435ed9aab9c941393cc3598e9b46"
integrity sha512-o3oj1bETk8kBwzz1WlO6JWL/AfAA3Vm6J1B3C9CsdxHYp7XgPiH7OEXPUbZTndHlRaIElrANkQfe6ZmfJb3H2w==
-"@types/nodemailer@^6.2.1":
- version "6.2.1"
- resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.2.1.tgz#8f089bf0ef826f04b9d8dd8750233b04978cb675"
- integrity sha512-6f46rxxaFwyOW39psPoQiM7jHjL7apDRNT5WPHIuv+TZFv+7sBGSI9J7blIC3/NWff4O9/VSzgoQtO6aPLUdvQ==
+"@types/nodemailer@^6.4.0":
+ version "6.4.0"
+ resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.0.tgz#d8c039be3ed685c4719a026455555be82c124b74"
+ integrity sha512-KY7bFWB0MahRZvVW4CuW83qcCDny59pJJ0MQ5ifvfcjNwPlIT0vW4uARO4u1gtkYnWdhSvURegecY/tzcukJcA==
dependencies:
"@types/node" "*"
@@ -20791,10 +20791,10 @@ node-status-codes@^1.0.0:
resolved "https://registry.yarnpkg.com/node-status-codes/-/node-status-codes-1.0.0.tgz#5ae5541d024645d32a58fcddc9ceecea7ae3ac2f"
integrity sha1-WuVUHQJGRdMqWPzdyc7s6nrjrC8=
-nodemailer@^4.7.0:
- version "4.7.0"
- resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-4.7.0.tgz#4420e06abfffd77d0618f184ea49047db84f4ad8"
- integrity sha512-IludxDypFpYw4xpzKdMAozBSkzKHmNBvGanUREjJItgJ2NYcK/s8+PggVhj7c2yGFQykKsnnmv1+Aqo0ZfjHmw==
+nodemailer@^6.4.16:
+ version "6.4.16"
+ resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.4.16.tgz#5cb6391b1d79ab7eff32d6f9f48366b5a7117293"
+ integrity sha512-68K0LgZ6hmZ7PVmwL78gzNdjpj5viqBdFqKrTtr9bZbJYj6BRj5W6WGkxXrEnUl3Co3CBXi3CZBUlpV/foGnOQ==
nodemon@^2.0.4:
version "2.0.6"