diff --git a/.buildkite/ftr_oblt_stateful_configs.yml b/.buildkite/ftr_oblt_stateful_configs.yml index 134721b65a9d8..fa85778994182 100644 --- a/.buildkite/ftr_oblt_stateful_configs.yml +++ b/.buildkite/ftr_oblt_stateful_configs.yml @@ -11,6 +11,7 @@ disabled: - x-pack/solutions/observability/plugins/uptime/e2e/config.ts - x-pack/solutions/observability/test/api_integration/config.ts - x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.ai_assistant_local.stateful.config.ts + - x-pack/solutions/observability/test/functional/config.base.ts # Elastic Synthetics configs - x-pack/solutions/observability/plugins/uptime/e2e/uptime/synthetics_run.ts @@ -36,15 +37,18 @@ enabled: - x-pack/test/functional/apps/dataset_quality/config.ts - x-pack/test/functional/apps/slo/embeddables/config.ts - x-pack/test/functional/apps/uptime/config.ts - - x-pack/test/observability_api_integration/basic/config.ts - - x-pack/test/observability_api_integration/trial/config.ts - - x-pack/test/observability_functional/with_rac_write.config.ts - - x-pack/test/observability_onboarding_api_integration/basic/config.ts - - x-pack/test/observability_onboarding_api_integration/cloud/config.ts - - x-pack/test/observability_ai_assistant_functional/enterprise/config.ts + - x-pack/solutions/observability/test/observability_api_integration/basic/config.ts + - x-pack/solutions/observability/test/observability_api_integration/trial/config.ts + - x-pack/solutions/observability/test/observability_functional/with_rac_write.config.ts + - x-pack/solutions/observability/test/observability_onboarding_api_integration/basic/config.ts + - x-pack/solutions/observability/test/observability_onboarding_api_integration/cloud/config.ts + - x-pack/solutions/observability/test/observability_ai_assistant_functional/enterprise/config.ts - x-pack/solutions/observability/test/api_integration/profiling/cloud/config.ts - x-pack/test/functional/apps/apm/config.ts - - x-pack/test/functional_with_es_ssl/apps/config.ts + - x-pack/solutions/observability/test/functional_with_es_ssl/config.ts + - x-pack/solutions/observability/test/accessibility/config.ts + - x-pack/solutions/observability/test/functional/apps/infra/config.ts + - x-pack/solutions/observability/test/functional/config.firefox.ts # stateful configs that run deployment-agnostic tests - x-pack/solutions/observability/test/api_integration_deployment_agnostic/configs/stateful/oblt.stateful.config.ts - x-pack/solutions/observability/test/api_integration_deployment_agnostic/configs/stateful/oblt.apm.stateful.config.ts diff --git a/.buildkite/ftr_platform_stateful_configs.yml b/.buildkite/ftr_platform_stateful_configs.yml index b8530de174b31..a89dd286930d6 100644 --- a/.buildkite/ftr_platform_stateful_configs.yml +++ b/.buildkite/ftr_platform_stateful_configs.yml @@ -217,7 +217,7 @@ enabled: - x-pack/test/functional/apps/home/config.ts - x-pack/test/functional/apps/index_lifecycle_management/config.ts - x-pack/test/functional/apps/index_management/config.ts - - x-pack/test/functional/apps/infra/config.ts + - x-pack/solutions/observability/test/functional/apps/infra/config.ts - x-pack/test/functional/apps/ingest_pipelines/config.ts - x-pack/test/functional/apps/lens/group1/config.ts - x-pack/test/functional/apps/lens/group2/config.ts diff --git a/.eslintrc.js b/.eslintrc.js index 81fe23f09d8b3..749a6e05db190 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -779,9 +779,11 @@ module.exports = { 'x-pack/platform/test/*/{tests,test_suites,apis,apps}/**/*', 'x-pack/platform/test/*api_integration*/**/*', 'x-pack/platform/test/*/*config.*ts', - 'x-pack/solutions/*/test/**/{tests,test_suites,apis,apps,fixtures}/**/*', - 'x-pack/solutions/*/test/*api_integration*/**/*', - 'x-pack/solutions/*/test/**/*config.*ts', + 'x-pack/solutions/*/test/**/{tests,test_suites,apis,apps,fixtures,index.ts}/**/*', + 'x-pack/solutions/*/test/**/*config*.ts', + 'x-pack/solutions/*/test/**/tests/**/*', + 'x-pack/solutions/*/test/api_integration_deployment_agnostic/*configs/**/*', + 'x-pack/solutions/*/test/alerting_api_integration/**/*', 'x-pack/test/*/{tests,test_suites,apis,apps}/**/*', 'x-pack/test/*/*config.*ts', 'x-pack/platform/test/saved_object_api_integration/*/apis/**/*', diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 8047250968438..c33f56bfac86c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1354,7 +1354,7 @@ x-pack/solutions/observability/plugins/observability/server/lib/esql_extensions /x-pack/test_serverless/api_integration/test_suites/common/data_usage @elastic/kibana-management /x-pack/test_serverless/functional/test_suites/common/data_usage @elastic/kibana-management /x-pack/test_serverless/functional/page_objects/svl_data_usage.ts @elastic/kibana-management -/x-pack/test/observability_ai_assistant_functional @elastic/obs-ai-assistant +/x-pack/solutions/observability/test/observability_ai_assistant_functional @elastic/obs-ai-assistant /x-pack/test/functional/es_archives/observability/ai_assistant @elastic/obs-ai-assistant /x-pack/solutions/observability/test/api_integration_deployment_agnostic/apis/ai_assistant @elastic/obs-ai-assistant /x-pack/solutions/observability/test/api_integration_deployment_agnostic/configs/serverless/oblt.ai_assistant.index.ts @elastic/obs-ai-assistant @@ -1383,8 +1383,10 @@ x-pack/solutions/observability/plugins/observability/server/lib/esql_extensions /x-pack/solutions/observability/test/api_integration_deployment_agnostic/configs/serverless/oblt.serverless.config.ts @elastic/obs-ux-infra_services-team /x-pack/solutions/observability/test/api_integration_deployment_agnostic/configs/stateful/oblt.index.ts @elastic/obs-ux-infra_services-team /x-pack/solutions/observability/test/api_integration_deployment_agnostic/configs/stateful/oblt.stateful.config.ts @elastic/obs-ux-infra_services-team -/x-pack/test/functional/page_objects/asset_details.ts @elastic/obs-ux-infra_services-team # Assigned per https://github.com/elastic/kibana/pull/200157/files/c83fae62151fe634342c498aca69b686b739fe45#r1842202022 +/x-pack/solutions/observability/test/functional/page_objects/asset_details.ts @elastic/obs-ux-infra_services-team # Assigned per https://github.com/elastic/kibana/pull/200157/files/c83fae62151fe634342c498aca69b686b739fe45#r1842202022 +/x-pack/test/functional/page_objects/asset_details.ts @elastic/obs-ux-infra_services-team /x-pack/test/functional/page_objects/infra_* @elastic/obs-ux-infra_services-team +/x-pack/solutions/observability/test/functional/page_objects/infra_* @elastic/obs-ux-infra_services-team /x-pack/test/functional/es_archives/infra @elastic/obs-ux-infra_services-team /x-pack/test_serverless/**/test_suites/observability/infra/ @elastic/obs-ux-infra_services-team /src/platform/test/common/plugins/otel_metrics @elastic/obs-ux-infra_services-team @@ -1453,8 +1455,8 @@ x-pack/solutions/observability/plugins/observability/server/lib/esql_extensions /x-pack/test/common/services/infra_synthtrace_kibana_client.ts @elastic/obs-ux-infra_services-team /x-pack/test/common/services/infra_log_views.ts @elastic/obs-ux-infra_services-team # Assigned per https://github.com/elastic/kibana/pull/188204 /x-pack/test/api_integration/apis/infra @elastic/obs-ux-infra_services-team -/x-pack/test/functional/apps/infra @elastic/obs-ux-infra_services-team -/x-pack/test/functional/apps/infra/logs @elastic/obs-ux-logs-team +/x-pack/solutions/observability/test/functional/apps/infra @elastic/obs-ux-infra_services-team +/x-pack/solutions/observability/test/functional/apps/infra/logs @elastic/obs-ux-logs-team /x-pack/solutions/observability/test/api_integration/services/index.ts @elastic/obs-ux-infra_services-team /x-pack/solutions/observability/test/api_integration/services/infra_log_views.ts @elastic/obs-ux-infra_services-team @@ -1463,13 +1465,15 @@ x-pack/solutions/observability/plugins/observability/server/lib/esql_extensions /x-pack/test/api_integration/services/slo.ts @elastic/obs-ux-management-team /x-pack/test/functional/services/slo @elastic/obs-ux-management-team /x-pack/test/functional/apps/slo @elastic/obs-ux-management-team -/x-pack/test/observability_api_integration @elastic/obs-ux-management-team # Assigned per https://github.com/elastic/kibana/pull/182243 +/x-pack/solutions/observability/test/observability_api_integration @elastic/obs-ux-management-team # Assigned per https://github.com/elastic/kibana/pull/182243 /x-pack/test/functional/services/observability @elastic/obs-ux-management-team +/x-pack/solutions/observability/test/functional/services/observability @elastic/obs-ux-management-team /x-pack/test/api_integration/apis/slos @elastic/obs-ux-management-team /x-pack/test/accessibility/apps/group1/uptime.ts @elastic/obs-ux-management-team -/x-pack/test/accessibility/apps/group3/observability.ts @elastic/obs-ux-management-team +/x-pack/solutions/observability/test/accessibility/apps/observability.ts @elastic/obs-ux-management-team +/x-pack/solutions/observability/test/functional/services/slo @elastic/obs-ux-management-team /x-pack/packages/observability/alert_details @elastic/obs-ux-management-team -/x-pack/test/observability_functional @elastic/obs-ux-management-team +/x-pack/solutions/observability/test/observability_functional @elastic/obs-ux-management-team /x-pack/solutions/observability/plugins/infra/public/alerting @elastic/obs-ux-management-team /x-pack/solutions/observability/plugins/infra/server/lib/alerting @elastic/obs-ux-management-team /x-pack/test_serverless/**/test_suites/observability/custom_threshold_rule/ @elastic/obs-ux-management-team @@ -1490,7 +1494,7 @@ x-pack/solutions/observability/plugins/observability/server/lib/esql_extensions /x-pack/solutions/observability/test/api_integration_deployment_agnostic/services/synthetics_private_location @elastic/obs-ux-management-team /x-pack/solutions/observability/test/api_integration_deployment_agnostic/apis/incident_management/ @elastic/obs-ux-management-team /x-pack/solutions/observability/test/api_integration_deployment_agnostic/services @elastic/obs-ux-management-team -/x-pack/test/functional/page_objects/alert_controls.ts @elastic/obs-ux-management-team +/x-pack/solutions/observability/test/functional/page_objects/alert_controls.ts @elastic/obs-ux-management-team # Elastic Stack Monitoring /x-pack/platform/test/monitoring_api_integration @elastic/stack-monitoring @@ -1536,12 +1540,15 @@ x-pack/solutions/observability/plugins/observability/server/lib/esql_extensions # Uptime /x-pack/test/functional/page_objects/uptime_page.ts @elastic/obs-ux-management-team -/x-pack/test/functional_with_es_ssl/apps/uptime/ @elastic/obs-ux-management-team -/x-pack/test/functional_with_es_ssl/apps/config.ts @elastic/obs-ux-management-team -/x-pack/test/functional_with_es_ssl/ftr_provider_context.ts @elastic/obs-ux-management-team -/x-pack/test/functional/apps/uptime @elastic/obs-ux-management-team +/x-pack/solutions/observability/test/functional/page_objects/uptime_page.ts @elastic/obs-ux-management-team +/x-pack/solutions/observability/test/accessibility/apps/uptime.ts @elastic/obs-ux-management-team +/x-pack/solutions/observability/test/functional_with_es_ssl/apps/uptime/ @elastic/obs-ux-management-team +/x-pack/solutions/observability/test/functional_with_es_ssl/config.ts @elastic/obs-ux-management-team +/x-pack/solutions/observability/test/functional_with_es_ssl/ftr_provider_context.ts @elastic/obs-ux-management-team +/x-pack/solutions/observability/test/functional/apps/uptime @elastic/obs-ux-management-team /x-pack/test/functional/es_archives/uptime @elastic/obs-ux-management-team /x-pack/test/functional/services/uptime @elastic/obs-ux-management-team +/x-pack/solutions/observability/test/functional/services/uptime @elastic/obs-ux-management-team /x-pack/solutions/observability/test/api_integration/apis/uptime @elastic/obs-ux-management-team /x-pack/solutions/observability/test/api_integration/apis/synthetics @elastic/obs-ux-management-team /x-pack/solutions/observability/test/alerting_api_integration/observability/synthetics_rule.ts @elastic/obs-ux-management-team @@ -1562,10 +1569,11 @@ x-pack/solutions/observability/plugins/observability/server/lib/esql_extensions /x-pack/test_serverless/functional/test_suites/observability/index* @elastic/obs-ux-logs-team /x-pack/test_serverless/functional/test_suites/observability/cypress @elastic/obs-ux-logs-team /x-pack/test/functional/services/infra_source_configuration_form.ts @elastic/obs-ux-infra_services-team -/x-pack/test/functional/services/logs_ui @elastic/obs-ux-logs-team +/x-pack/solutions/observability/test/functional/services/infra_source_configuration_form.ts @elastic/obs-ux-infra_services-team +/x-pack/solutions/observability/test/functional/services/logs_ui @elastic/obs-ux-logs-team /x-pack/test/functional/page_objects/observability_logs_explorer.ts @elastic/obs-ux-logs-team /src/platform/test/functional/services/selectable.ts @elastic/obs-ux-logs-team -/x-pack/test/observability_onboarding_api_integration @elastic/obs-ux-logs-team +/x-pack/solutions/observability/test/observability_onboarding_api_integration @elastic/obs-ux-logs-team /x-pack/test_serverless/api_integration/test_suites/observability/index.feature_flags.ts @elastic/obs-ux-logs-team /x-pack/solutions/observability/test/api_integration/apis/logs_ui @elastic/obs-ux-logs-team /x-pack/test/dataset_quality_api_integration @elastic/obs-ux-logs-team @@ -1579,16 +1587,17 @@ x-pack/solutions/observability/plugins/observability/server/lib/esql_extensions /x-pack/solutions/observability/test/api_integration/apis/logs_shared @elastic/obs-ux-logs-team /src/platform/test/functional/apps/discover/observability/embeddable @elastic/obs-ux-logs-team /src/platform/test/functional/apps/discover/observability/logs @elastic/obs-ux-logs-team +/x-pack/solutions/observability/test/functional/config.firefox.ts @elastic/obs-ux-logs-team # Observability-ui /x-pack/test_serverless/api_integration/test_suites/observability/index.ts @elastic/observability-ui /x-pack/test/functional_solution_sidenav/tests/observability_sidenav.ts @elastic/observability-ui -/x-pack/test/functional/page_objects/observability_page.ts @elastic/observability-ui +/x-pack/solutions/observability/test/functional/page_objects/observability_page.ts @elastic/observability-ui /x-pack/test_serverless/**/test_suites/observability/config.ts @elastic/observability-ui # Observability onboarding tour /x-pack/solutions/observability/plugins/observability_shared/public/components/tour @elastic/appex-sharedux -/x-pack/test/functional/apps/infra/tour.ts @elastic/appex-sharedux +/x-pack/solutions/observability/test/functional/apps/infra/tour.ts @elastic/appex-sharedux # Observability settings /x-pack/plugins/observability_solution/observability/server/ui_settings.ts @elastic/obs-docs @@ -1779,6 +1788,7 @@ x-pack/platform/plugins/shared/ml/server/models/data_recognizer/modules/security /x-pack/platform/test/upgrade/ftr_provider_context.d.ts @elastic/appex-qa /x-pack/platform/test/upgrade/config.ts @elastic/appex-qa /x-pack/platform/test/functional_basic/ftr_provider_context.d.ts @elastic/appex-qa +x-pack/test/functional/services/index.ts @elastic/appex-qa /x-pack/test/functional/services/remote_es/remote_es.ts @elastic/appex-qa /x-pack/test/functional/services/random.js @elastic/appex-qa /x-pack/test/functional/services/index.ts @elastic/appex-qa @@ -1910,8 +1920,6 @@ x-pack/platform/plugins/shared/ml/server/models/data_recognizer/modules/security /x-pack/solutions/security/test/api_integration/services/index.ts @elastic/appex-qa /x-pack/solutions/security/test/alerting_api_integration/ftr_provider_context.d.ts @elastic/appex-qa /x-pack/test/apm_api_integration @elastic/appex-qa # temporarily due to SKA tests relocation -/x-pack/test/common/utils/observability @elastic/appex-qa # temporarily due to SKA tests relocation -/x-pack/test/common/utils/uptime @elastic/appex-qa # temporarily due to SKA tests relocation /x-pack/solutions/observability/test/api_integration_deployment_agnostic/feature_flag_configs/serverless/oblt.index.ts @elastic/appex-qa # temporarily due to SKA tests relocation /x-pack/solutions/observability/test/api_integration_deployment_agnostic/feature_flag_configs/serverless/oblt.serverless.config.ts @elastic/appex-qa # temporarily due to SKA tests relocation /x-pack/solutions/observability/test/api_integration_deployment_agnostic/feature_flag_configs/stateful/oblt.index.ts @elastic/appex-qa # temporarily due to SKA tests relocation @@ -1920,6 +1928,17 @@ x-pack/platform/plugins/shared/ml/server/models/data_recognizer/modules/security /x-pack/test/api_integration/deployment_agnostic @elastic/appex-qa /x-pack/platform/test/functional/services/ml/api.ts @elastic/appex-qa # temporarily due to SKA tests relocation /x-pack/test/api_integration/deployment_agnostic/apis/ @elastic/appex-qa # temporarily due to SKA tests relocation +/x-pack/solutions/observability/test/functional/config.base.ts @elastic/appex-qa +/x-pack/solutions/observability/test/functional/ftr_provider_context.d.ts @elastic/appex-qa +/x-pack/solutions/observability/test/functional/page_objects/index.ts @elastic/appex-qa +/x-pack/solutions/observability/test/functional/services/index.ts @elastic/appex-qa +/x-pack/solutions/observability/test/accessibility/config.ts @elastic/appex-qa +/x-pack/solutions/observability/test/accessibility/ftr_provider_context.d.ts @elastic/appex-qa +/x-pack/solutions/observability/test/accessibility/index.ts @elastic/appex-qa +/x-pack/solutions/observability/test/accessibility/page_objects.ts @elastic/appex-qa +/x-pack/solutions/observability/test/accessibility/services.ts @elastic/appex-qa +/x-pack/solutions/observability/test/accessibility/apps/index.ts @elastic/appex-qa +/x-pack/solutions/observability/test/functional_with_es_ssl/apps/index.ts @elastic/appex-qa /x-pack/platform/test/.gitignore @elastic/appex-qa /x-pack/solutions/**/test/.gitignore @elastic/appex-qa @@ -1936,12 +1955,11 @@ x-pack/platform/plugins/shared/ml/server/models/data_recognizer/modules/security /src/platform/test/interpreter_functional @elastic/kibana-core # Assigned per https://github.com/elastic/kibana/blob/main/test/interpreter_functional/plugins/kbn_tp_run_pipeline/kibana.jsonc#L4 /src/platform/test/api_integration/apis/general/*.js @elastic/kibana-core # Assigned per https://github.com/elastic/kibana/pull/199795/files/894a8ede3f9d0398c5af56bf5a82654a9bc0610b#r1846691639 /x-pack/platform/test/plugin_api_integration/plugins/feature_usage_test @elastic/kibana-core -/x-pack/test/functional/page_objects/navigational_search.ts @elastic/kibana-core +/x-pack/platform/test/functional/page_objects/navigational_search.ts @elastic/kibana-core /x-pack/test/stack_functional_integration/apps/savedobjects_upgrade_testing @elastic/kibana-core /x-pack/test/functional/page_objects/status_page.ts @elastic/kibana-core /x-pack/test/functional/page_objects/share_saved_objects_to_space_page.ts @elastic/kibana-core /x-pack/platform/test/functional/page_objects/banners_page.ts @elastic/kibana-core -/x-pack/test/common/lib/test_data_loader.ts @elastic/kibana-core /x-pack/test/api_integration/services/usage_api.ts @elastic/kibana-core /x-pack/platform/test/api_integration/apis/kibana @elastic/kibana-core /src/platform/test/api_integration/fixtures/import.ndjson @elastic/kibana-core diff --git a/.github/paths-labeller.yml b/.github/paths-labeller.yml index 5e3ae02e073f8..ae69ba388364c 100644 --- a/.github/paths-labeller.yml +++ b/.github/paths-labeller.yml @@ -26,7 +26,7 @@ - 'Team:Obs AI Assistant': - 'x-pack/platform/plugins/shared/observability_ai_assistant/**/*.*' - 'x-pack/plugins/observability_solution/observability_ai_assistant_*/**/*.*' - - 'x-pack/test/observability_ai_assistant_functional/**/*.*' + - 'x-pack/solutions/observability/test/observability_ai_assistant_functional/**/*.*' - 'ci:project-deploy-observability': - 'packages/kbn-apm-*/**/*.*' - 'src/platform/plugins/shared/ai_assistant_management/**/*.*' diff --git a/packages/kbn-failed-test-reporter-cli/failed_tests_reporter/__fixtures__/ftr_report.xml b/packages/kbn-failed-test-reporter-cli/failed_tests_reporter/__fixtures__/ftr_report.xml index 77c0d7691d22d..704e8ad99967a 100644 --- a/packages/kbn-failed-test-reporter-cli/failed_tests_reporter/__fixtures__/ftr_report.xml +++ b/packages/kbn-failed-test-reporter-cli/failed_tests_reporter/__fixtures__/ftr_report.xml @@ -32,7 +32,7 @@ Wait timed out after 10055ms at process._tickCallback (internal/process/next_tick.js:68:7) name: 'NoSuchSessionError', remoteStacktrace: '' }]]> - + { + at process._tickCallback (internal/process/next_tick.js:68:7) name: 'NoSuchSessionError', remoteStacktrace: '' } ‹/failure› ‹/testcase› - ‹testcase name="InfraOps app feature controls infrastructure security global infrastructure all privileges shows infrastructure navlink" classname="Chrome X-Pack UI Functional Tests.x-pack/test/functional/apps/infra/feature_controls/infrastructure_security·ts" owners="elastic/kibana-presentation"› + ‹testcase name="InfraOps app feature controls infrastructure security global infrastructure all privileges shows infrastructure navlink" classname="Chrome X-Pack UI Functional Tests.x-pack/solutions/observability/test/functional/apps/infra/feature_controls/infrastructure_security·ts" owners="elastic/kibana-presentation"› ‹system-out› - ‹![CDATA[[00:00:00] │ + [00:00:00] │ diff --git a/x-pack/platform/test/functional/page_objects/index.ts b/x-pack/platform/test/functional/page_objects/index.ts index ccfbbb6b3bb27..620ed6685d565 100644 --- a/x-pack/platform/test/functional/page_objects/index.ts +++ b/x-pack/platform/test/functional/page_objects/index.ts @@ -25,6 +25,7 @@ import { SearchSessionsPageProvider } from './search_sessions_management_page'; import { GraphPageObject } from './graph_page'; import { MaintenanceWindowsPageProvider } from './maintenance_windows_page'; import { BannersPageObject } from './banners_page'; +import { NavigationalSearchPageObject } from './navigational_search'; // just like services, PageObjects are defined as a map of // names to Providers. Merge in Kibana's or pick specific ones @@ -49,4 +50,5 @@ export const pageObjects = { userProfiles: UserProfilePageProvider, maintenanceWindows: MaintenanceWindowsPageProvider, banners: BannersPageObject, + navigationalSearch: NavigationalSearchPageObject, }; diff --git a/x-pack/test/functional/page_objects/navigational_search.ts b/x-pack/platform/test/functional/page_objects/navigational_search.ts similarity index 100% rename from x-pack/test/functional/page_objects/navigational_search.ts rename to x-pack/platform/test/functional/page_objects/navigational_search.ts diff --git a/x-pack/solutions/observability/plugins/observability/README.md b/x-pack/solutions/observability/plugins/observability/README.md index 95792d04545f9..1f52fb4ca8f90 100644 --- a/x-pack/solutions/observability/plugins/observability/README.md +++ b/x-pack/solutions/observability/plugins/observability/README.md @@ -13,12 +13,12 @@ xpack.ruleRegistry.write.enabled: true When this is set to `true`, your alerts should show on the alerts page. - ## Shared navigation The Observability plugin maintains a navigation registry for Observability solutions, and exposes a shared page template component. Please refer to the docs in [the component directory](public/components/shared/page_template) for more information on registering your solution's navigation structure, and rendering the navigation via the shared component. ## Exploratory view component + A shared component for visualizing observability data types via lens embeddable. [For further details.](./public/components/shared/exploratory_view/README.md) ## Unit testing @@ -58,25 +58,25 @@ This requires separate test servers and test runners. ``` # Start server -node scripts/functional_tests_server --config x-pack/test/observability_api_integration/basic/config.ts +node scripts/functional_tests_server --config x-pack/solutions/observability/test/observability_api_integration/basic/config.ts # Run tests -node scripts/functional_test_runner --config x-pack/test/observability_api_integration/basic/config.ts +node scripts/functional_test_runner --config x-pack/solutions/observability/test/observability_api_integration/basic/config.ts ``` -The API tests for "basic" are located in `x-pack/test/observability_api_integration/basic/tests`. +The API tests for "basic" are located in `x-pack/solutions/observability/test/observability_api_integration/basic/tests`. ### Trial ``` # Start server -node scripts/functional_tests_server --config x-pack/test/observability_api_integration/trial/config.ts +node scripts/functional_tests_server --config x-pack/solutions/observability/test/observability_api_integration/trial/config.ts # Run tests -node scripts/functional_test_runner --config x-pack/test/observability_api_integration/trial/config.ts +node scripts/functional_test_runner --config x-pack/solutions/observability/test/observability_api_integration/trial/config.ts ``` -The API tests for "trial" are located in `x-pack/test/observability_api_integration/trial/tests`. +The API tests for "trial" are located in `x-pack/solutions/observability/test/observability_api_integration/trial/tests`. ### API test tips diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/README.md b/x-pack/solutions/observability/plugins/observability_onboarding/README.md index ce58ff9e1f548..b35be2256835c 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/README.md +++ b/x-pack/solutions/observability/plugins/observability_onboarding/README.md @@ -56,20 +56,20 @@ node scripts/functional_test_runner --config x-pack/solutions/observability/test ```sh # start server -yarn test:ftr:server --config ./x-pack/test/observability_onboarding_api_integration/basic/config.ts +yarn test:ftr:server --config ./x-pack/solutions/observability/test/observability_onboarding_api_integration/basic/config.ts # run tests -yarn test:ftr:runner --config ./x-pack/test/observability_onboarding_api_integration/basic/config.ts --include ./x-pack/test/observability_onboarding_api_integration/tests/index.ts +yarn test:ftr:runner --config ./x-pack/solutions/observability/test/observability_onboarding_api_integration/basic/config.ts --include ./x-pack/solutions/observability/test/observability_onboarding_api_integration/tests/index.ts ``` #### Cloud config ```sh # start server -yarn test:ftr:server --config ./x-pack/test/observability_onboarding_api_integration/cloud/config.ts +yarn test:ftr:server --config ./x-pack/solutions/observability/test/observability_onboarding_api_integration/cloud/config.ts # run tests -yarn test:ftr:runner --config ./x-pack/test/observability_onboarding_api_integration/cloud/config.ts --include ./x-pack/test/observability_onboarding_api_integration/tests/index.ts +yarn test:ftr:runner --config ./x-pack/solutions/observability/test/observability_onboarding_api_integration/cloud/config.ts --include ./x-pack/solutions/observability/test/observability_onboarding_api_integration/tests/index.ts ``` ### Functional Tests diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/scripts/test/api.js b/x-pack/solutions/observability/plugins/observability_onboarding/scripts/test/api.js index e8574fd42ad51..b384466eb35d2 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/scripts/test/api.js +++ b/x-pack/solutions/observability/plugins/observability_onboarding/scripts/test/api.js @@ -83,7 +83,7 @@ const cmd = [ `${REPO_ROOT}/scripts/${ftrScript}`, ...(grep ? [`--grep "${grep}"`] : []), ...(updateSnapshots ? [`--updateSnapshots`] : []), - `--config ${REPO_ROOT}/x-pack/test/observability_onboarding_api_integration/${license}/config.ts`, + `--config ${REPO_ROOT}/x-pack/solutions/observability/test/observability_onboarding_api_integration/${license}/config.ts`, ].join(' '); console.log(`Running: "${cmd}"`); diff --git a/x-pack/solutions/observability/test/accessibility/apps/index.ts b/x-pack/solutions/observability/test/accessibility/apps/index.ts new file mode 100644 index 0000000000000..de6f1dc368c7d --- /dev/null +++ b/x-pack/solutions/observability/test/accessibility/apps/index.ts @@ -0,0 +1,15 @@ +/* + * 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 { FtrProviderContext } from '../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('X-Pack Observability Accessibility Tests', function () { + loadTestFile(require.resolve('./uptime')); + loadTestFile(require.resolve('./observability')); + }); +} diff --git a/x-pack/test/accessibility/apps/group3/observability.ts b/x-pack/solutions/observability/test/accessibility/apps/observability.ts similarity index 95% rename from x-pack/test/accessibility/apps/group3/observability.ts rename to x-pack/solutions/observability/test/accessibility/apps/observability.ts index 6c7ed0e98aca4..2e2fadd959aaf 100644 --- a/x-pack/test/accessibility/apps/group3/observability.ts +++ b/x-pack/solutions/observability/test/accessibility/apps/observability.ts @@ -6,7 +6,7 @@ */ // a11y tests for spaces, space selection and space creation and feature controls -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'infraHome']); diff --git a/x-pack/test/accessibility/apps/group1/uptime.ts b/x-pack/solutions/observability/test/accessibility/apps/uptime.ts similarity index 93% rename from x-pack/test/accessibility/apps/group1/uptime.ts rename to x-pack/solutions/observability/test/accessibility/apps/uptime.ts index b366808d860f8..1b4dafa9e97d0 100644 --- a/x-pack/test/accessibility/apps/group1/uptime.ts +++ b/x-pack/solutions/observability/test/accessibility/apps/uptime.ts @@ -6,8 +6,8 @@ */ import moment from 'moment'; -import { makeChecks } from '@kbn/test-suites-xpack-observability/api_integration/apis/uptime/rest/helper/make_checks'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { makeChecks } from '../../api_integration/apis/uptime/rest/helper/make_checks'; +import { FtrProviderContext } from '../ftr_provider_context'; const A11Y_TEST_MONITOR_ID = 'a11yTestMonitor'; diff --git a/x-pack/solutions/observability/test/accessibility/config.ts b/x-pack/solutions/observability/test/accessibility/config.ts new file mode 100644 index 0000000000000..7edb4e7597146 --- /dev/null +++ b/x-pack/solutions/observability/test/accessibility/config.ts @@ -0,0 +1,27 @@ +/* + * 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 { FtrConfigProviderContext } from '@kbn/test'; +import { services } from './services'; +import { pageObjects } from './page_objects'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../functional/config.base.ts')); + + return { + ...functionalConfig.getAll(), + + testFiles: [require.resolve('./apps')], + + pageObjects, + services, + + junit: { + reportName: 'X-Pack Observability Accessibility Tests', + }, + }; +} diff --git a/x-pack/solutions/observability/test/accessibility/ftr_provider_context.d.ts b/x-pack/solutions/observability/test/accessibility/ftr_provider_context.d.ts new file mode 100644 index 0000000000000..24f5087ef7fe2 --- /dev/null +++ b/x-pack/solutions/observability/test/accessibility/ftr_provider_context.d.ts @@ -0,0 +1,13 @@ +/* + * 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 { GenericFtrProviderContext } from '@kbn/test'; + +import { pageObjects } from './page_objects'; +import { services } from './services'; + +export type FtrProviderContext = GenericFtrProviderContext; diff --git a/x-pack/solutions/observability/test/accessibility/page_objects.ts b/x-pack/solutions/observability/test/accessibility/page_objects.ts new file mode 100644 index 0000000000000..d97010fb1bac9 --- /dev/null +++ b/x-pack/solutions/observability/test/accessibility/page_objects.ts @@ -0,0 +1,8 @@ +/* + * 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. + */ + +export { pageObjects } from '../functional/page_objects'; diff --git a/x-pack/solutions/observability/test/accessibility/services.ts b/x-pack/solutions/observability/test/accessibility/services.ts new file mode 100644 index 0000000000000..d7f56d3be6dd8 --- /dev/null +++ b/x-pack/solutions/observability/test/accessibility/services.ts @@ -0,0 +1,14 @@ +/* + * 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 { services as kibanaA11yServices } from '@kbn/test-suites-src/accessibility/services'; +import { services as functionalServices } from '../functional/services'; + +export const services = { + ...kibanaA11yServices, + ...functionalServices, +}; diff --git a/x-pack/test/functional/apps/infra/config.ts b/x-pack/solutions/observability/test/functional/apps/infra/config.ts similarity index 96% rename from x-pack/test/functional/apps/infra/config.ts rename to x-pack/solutions/observability/test/functional/apps/infra/config.ts index 79c902c94d5c5..d1872fa0dba4c 100644 --- a/x-pack/test/functional/apps/infra/config.ts +++ b/x-pack/solutions/observability/test/functional/apps/infra/config.ts @@ -8,7 +8,7 @@ import { FtrConfigProviderContext } from '@kbn/test'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + const functionalConfig = await readConfigFile(require.resolve('../../config.base.ts')); return { ...functionalConfig.getAll(), diff --git a/x-pack/test/functional/apps/infra/constants.ts b/x-pack/solutions/observability/test/functional/apps/infra/constants.ts similarity index 100% rename from x-pack/test/functional/apps/infra/constants.ts rename to x-pack/solutions/observability/test/functional/apps/infra/constants.ts diff --git a/x-pack/test/functional/apps/infra/feature_controls/index.ts b/x-pack/solutions/observability/test/functional/apps/infra/feature_controls/index.ts similarity index 100% rename from x-pack/test/functional/apps/infra/feature_controls/index.ts rename to x-pack/solutions/observability/test/functional/apps/infra/feature_controls/index.ts diff --git a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts b/x-pack/solutions/observability/test/functional/apps/infra/feature_controls/infrastructure_security.ts similarity index 100% rename from x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts rename to x-pack/solutions/observability/test/functional/apps/infra/feature_controls/infrastructure_security.ts diff --git a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_spaces.ts b/x-pack/solutions/observability/test/functional/apps/infra/feature_controls/infrastructure_spaces.ts similarity index 100% rename from x-pack/test/functional/apps/infra/feature_controls/infrastructure_spaces.ts rename to x-pack/solutions/observability/test/functional/apps/infra/feature_controls/infrastructure_spaces.ts diff --git a/x-pack/test/functional/apps/infra/feature_controls/logs_security.ts b/x-pack/solutions/observability/test/functional/apps/infra/feature_controls/logs_security.ts similarity index 100% rename from x-pack/test/functional/apps/infra/feature_controls/logs_security.ts rename to x-pack/solutions/observability/test/functional/apps/infra/feature_controls/logs_security.ts diff --git a/x-pack/test/functional/apps/infra/feature_controls/logs_spaces.ts b/x-pack/solutions/observability/test/functional/apps/infra/feature_controls/logs_spaces.ts similarity index 100% rename from x-pack/test/functional/apps/infra/feature_controls/logs_spaces.ts rename to x-pack/solutions/observability/test/functional/apps/infra/feature_controls/logs_spaces.ts diff --git a/x-pack/test/functional/apps/infra/helpers.ts b/x-pack/solutions/observability/test/functional/apps/infra/helpers.ts similarity index 100% rename from x-pack/test/functional/apps/infra/helpers.ts rename to x-pack/solutions/observability/test/functional/apps/infra/helpers.ts diff --git a/x-pack/test/functional/apps/infra/home_page.ts b/x-pack/solutions/observability/test/functional/apps/infra/home_page.ts similarity index 100% rename from x-pack/test/functional/apps/infra/home_page.ts rename to x-pack/solutions/observability/test/functional/apps/infra/home_page.ts diff --git a/x-pack/test/functional/apps/infra/hosts_view.ts b/x-pack/solutions/observability/test/functional/apps/infra/hosts_view.ts similarity index 100% rename from x-pack/test/functional/apps/infra/hosts_view.ts rename to x-pack/solutions/observability/test/functional/apps/infra/hosts_view.ts diff --git a/x-pack/test/functional/apps/infra/index.ts b/x-pack/solutions/observability/test/functional/apps/infra/index.ts similarity index 100% rename from x-pack/test/functional/apps/infra/index.ts rename to x-pack/solutions/observability/test/functional/apps/infra/index.ts diff --git a/x-pack/test/functional/apps/infra/logs/link_to.ts b/x-pack/solutions/observability/test/functional/apps/infra/logs/link_to.ts similarity index 100% rename from x-pack/test/functional/apps/infra/logs/link_to.ts rename to x-pack/solutions/observability/test/functional/apps/infra/logs/link_to.ts diff --git a/x-pack/test/functional/apps/infra/logs/log_entry_categories_tab.ts b/x-pack/solutions/observability/test/functional/apps/infra/logs/log_entry_categories_tab.ts similarity index 100% rename from x-pack/test/functional/apps/infra/logs/log_entry_categories_tab.ts rename to x-pack/solutions/observability/test/functional/apps/infra/logs/log_entry_categories_tab.ts diff --git a/x-pack/test/functional/apps/infra/logs/log_entry_rate_tab.ts b/x-pack/solutions/observability/test/functional/apps/infra/logs/log_entry_rate_tab.ts similarity index 100% rename from x-pack/test/functional/apps/infra/logs/log_entry_rate_tab.ts rename to x-pack/solutions/observability/test/functional/apps/infra/logs/log_entry_rate_tab.ts diff --git a/x-pack/test/functional/apps/infra/logs/ml_job_id_formats/assert_id_formats.ts b/x-pack/solutions/observability/test/functional/apps/infra/logs/ml_job_id_formats/assert_id_formats.ts similarity index 100% rename from x-pack/test/functional/apps/infra/logs/ml_job_id_formats/assert_id_formats.ts rename to x-pack/solutions/observability/test/functional/apps/infra/logs/ml_job_id_formats/assert_id_formats.ts diff --git a/x-pack/test/functional/apps/infra/logs/ml_job_id_formats/ml_job_configs.ts b/x-pack/solutions/observability/test/functional/apps/infra/logs/ml_job_id_formats/ml_job_configs.ts similarity index 100% rename from x-pack/test/functional/apps/infra/logs/ml_job_id_formats/ml_job_configs.ts rename to x-pack/solutions/observability/test/functional/apps/infra/logs/ml_job_id_formats/ml_job_configs.ts diff --git a/x-pack/test/functional/apps/infra/logs/ml_job_id_formats/ml_job_helper.ts b/x-pack/solutions/observability/test/functional/apps/infra/logs/ml_job_id_formats/ml_job_helper.ts similarity index 100% rename from x-pack/test/functional/apps/infra/logs/ml_job_id_formats/ml_job_helper.ts rename to x-pack/solutions/observability/test/functional/apps/infra/logs/ml_job_id_formats/ml_job_helper.ts diff --git a/x-pack/test/functional/apps/infra/logs/ml_job_id_formats/request_tracker.ts b/x-pack/solutions/observability/test/functional/apps/infra/logs/ml_job_id_formats/request_tracker.ts similarity index 100% rename from x-pack/test/functional/apps/infra/logs/ml_job_id_formats/request_tracker.ts rename to x-pack/solutions/observability/test/functional/apps/infra/logs/ml_job_id_formats/request_tracker.ts diff --git a/x-pack/test/functional/apps/infra/logs/ml_job_id_formats/tests.ts b/x-pack/solutions/observability/test/functional/apps/infra/logs/ml_job_id_formats/tests.ts similarity index 100% rename from x-pack/test/functional/apps/infra/logs/ml_job_id_formats/tests.ts rename to x-pack/solutions/observability/test/functional/apps/infra/logs/ml_job_id_formats/tests.ts diff --git a/x-pack/test/functional/apps/infra/metrics_anomalies.ts b/x-pack/solutions/observability/test/functional/apps/infra/metrics_anomalies.ts similarity index 100% rename from x-pack/test/functional/apps/infra/metrics_anomalies.ts rename to x-pack/solutions/observability/test/functional/apps/infra/metrics_anomalies.ts diff --git a/x-pack/test/functional/apps/infra/metrics_explorer.ts b/x-pack/solutions/observability/test/functional/apps/infra/metrics_explorer.ts similarity index 100% rename from x-pack/test/functional/apps/infra/metrics_explorer.ts rename to x-pack/solutions/observability/test/functional/apps/infra/metrics_explorer.ts diff --git a/x-pack/test/functional/apps/infra/metrics_source_configuration.ts b/x-pack/solutions/observability/test/functional/apps/infra/metrics_source_configuration.ts similarity index 97% rename from x-pack/test/functional/apps/infra/metrics_source_configuration.ts rename to x-pack/solutions/observability/test/functional/apps/infra/metrics_source_configuration.ts index a8b2bd8c69df2..39c6b33d2f3e2 100644 --- a/x-pack/test/functional/apps/infra/metrics_source_configuration.ts +++ b/x-pack/solutions/observability/test/functional/apps/infra/metrics_source_configuration.ts @@ -11,11 +11,11 @@ import { Aggregators, MetricThresholdParams } from '@kbn/infra-plugin/common/ale import { COMPARATORS } from '@kbn/alerting-comparators'; import { InfraRuleType } from '@kbn/rule-data-utils'; -import { createRule } from '@kbn/test-suites-xpack-observability/alerting_api_integration/observability/helpers/alerting_api_helper'; +import { createRule } from '../../../alerting_api_integration/observability/helpers/alerting_api_helper'; import { waitForDocumentInIndex, waitForRuleStatus, -} from '@kbn/test-suites-xpack-observability/alerting_api_integration/observability/helpers/alerting_wait_for_helpers'; +} from '../../../alerting_api_integration/observability/helpers/alerting_wait_for_helpers'; import { FtrProviderContext } from '../../ftr_provider_context'; import { DATES } from './constants'; diff --git a/x-pack/test/functional/apps/infra/node_details.ts b/x-pack/solutions/observability/test/functional/apps/infra/node_details.ts similarity index 100% rename from x-pack/test/functional/apps/infra/node_details.ts rename to x-pack/solutions/observability/test/functional/apps/infra/node_details.ts diff --git a/x-pack/test/functional/apps/infra/page_not_found.ts b/x-pack/solutions/observability/test/functional/apps/infra/page_not_found.ts similarity index 100% rename from x-pack/test/functional/apps/infra/page_not_found.ts rename to x-pack/solutions/observability/test/functional/apps/infra/page_not_found.ts diff --git a/x-pack/test/functional/apps/infra/tour.ts b/x-pack/solutions/observability/test/functional/apps/infra/tour.ts similarity index 100% rename from x-pack/test/functional/apps/infra/tour.ts rename to x-pack/solutions/observability/test/functional/apps/infra/tour.ts diff --git a/x-pack/test/functional/apps/uptime/certificates.ts b/x-pack/solutions/observability/test/functional/apps/uptime/certificates.ts similarity index 93% rename from x-pack/test/functional/apps/uptime/certificates.ts rename to x-pack/solutions/observability/test/functional/apps/uptime/certificates.ts index a256c2f9e32d8..2fbd72e841def 100644 --- a/x-pack/test/functional/apps/uptime/certificates.ts +++ b/x-pack/solutions/observability/test/functional/apps/uptime/certificates.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { makeCheck } from '@kbn/test-suites-xpack-observability/api_integration/apis/uptime/rest/helper/make_checks'; -import { getSha256 } from '@kbn/test-suites-xpack-observability/api_integration/apis/uptime/rest/helper/make_tls'; +import { makeCheck } from '../../../api_integration/apis/uptime/rest/helper/make_checks'; +import { getSha256 } from '../../../api_integration/apis/uptime/rest/helper/make_tls'; import { FtrProviderContext } from '../../ftr_provider_context'; import { UPTIME_HEARTBEAT_DATA } from './overview'; diff --git a/x-pack/test/functional/apps/uptime/config.ts b/x-pack/solutions/observability/test/functional/apps/uptime/config.ts similarity index 95% rename from x-pack/test/functional/apps/uptime/config.ts rename to x-pack/solutions/observability/test/functional/apps/uptime/config.ts index 5635351a4790e..32459260455ed 100644 --- a/x-pack/test/functional/apps/uptime/config.ts +++ b/x-pack/solutions/observability/test/functional/apps/uptime/config.ts @@ -8,7 +8,7 @@ import { FtrConfigProviderContext } from '@kbn/test'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.base.js')); + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.base.ts')); return { ...baseIntegrationTestsConfig.getAll(), diff --git a/x-pack/test/functional/apps/uptime/feature_controls/index.ts b/x-pack/solutions/observability/test/functional/apps/uptime/feature_controls/index.ts similarity index 100% rename from x-pack/test/functional/apps/uptime/feature_controls/index.ts rename to x-pack/solutions/observability/test/functional/apps/uptime/feature_controls/index.ts diff --git a/x-pack/test/functional/apps/uptime/feature_controls/uptime_security.ts b/x-pack/solutions/observability/test/functional/apps/uptime/feature_controls/uptime_security.ts similarity index 100% rename from x-pack/test/functional/apps/uptime/feature_controls/uptime_security.ts rename to x-pack/solutions/observability/test/functional/apps/uptime/feature_controls/uptime_security.ts diff --git a/x-pack/test/functional/apps/uptime/feature_controls/uptime_spaces.ts b/x-pack/solutions/observability/test/functional/apps/uptime/feature_controls/uptime_spaces.ts similarity index 100% rename from x-pack/test/functional/apps/uptime/feature_controls/uptime_spaces.ts rename to x-pack/solutions/observability/test/functional/apps/uptime/feature_controls/uptime_spaces.ts diff --git a/x-pack/test/functional/apps/uptime/index.ts b/x-pack/solutions/observability/test/functional/apps/uptime/index.ts similarity index 100% rename from x-pack/test/functional/apps/uptime/index.ts rename to x-pack/solutions/observability/test/functional/apps/uptime/index.ts diff --git a/x-pack/test/functional/apps/uptime/missing_mappings.ts b/x-pack/solutions/observability/test/functional/apps/uptime/missing_mappings.ts similarity index 87% rename from x-pack/test/functional/apps/uptime/missing_mappings.ts rename to x-pack/solutions/observability/test/functional/apps/uptime/missing_mappings.ts index 483e4619937d7..60a3822f8bb70 100644 --- a/x-pack/test/functional/apps/uptime/missing_mappings.ts +++ b/x-pack/solutions/observability/test/functional/apps/uptime/missing_mappings.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { makeCheck } from '@kbn/test-suites-xpack-observability/api_integration/apis/uptime/rest/helper/make_checks'; +import { makeCheck } from '../../../api_integration/apis/uptime/rest/helper/make_checks'; import { FtrProviderContext } from '../../ftr_provider_context'; export default ({ getPageObjects, getService }: FtrProviderContext) => { diff --git a/x-pack/test/functional/apps/uptime/ml_anomaly.ts b/x-pack/solutions/observability/test/functional/apps/uptime/ml_anomaly.ts similarity index 100% rename from x-pack/test/functional/apps/uptime/ml_anomaly.ts rename to x-pack/solutions/observability/test/functional/apps/uptime/ml_anomaly.ts diff --git a/x-pack/test/functional/apps/uptime/overview.ts b/x-pack/solutions/observability/test/functional/apps/uptime/overview.ts similarity index 100% rename from x-pack/test/functional/apps/uptime/overview.ts rename to x-pack/solutions/observability/test/functional/apps/uptime/overview.ts diff --git a/x-pack/test/functional/apps/uptime/settings.ts b/x-pack/solutions/observability/test/functional/apps/uptime/settings.ts similarity index 97% rename from x-pack/test/functional/apps/uptime/settings.ts rename to x-pack/solutions/observability/test/functional/apps/uptime/settings.ts index baf27dbae550a..685f4651f7bab 100644 --- a/x-pack/test/functional/apps/uptime/settings.ts +++ b/x-pack/solutions/observability/test/functional/apps/uptime/settings.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import { DynamicSettings } from '@kbn/uptime-plugin/common/runtime_types'; import { DYNAMIC_SETTINGS_DEFAULTS } from '@kbn/uptime-plugin/common/constants'; -import { makeChecks } from '@kbn/test-suites-xpack-observability/api_integration/apis/uptime/rest/helper/make_checks'; +import { makeChecks } from '../../../api_integration/apis/uptime/rest/helper/make_checks'; import { FtrProviderContext } from '../../ftr_provider_context'; export default ({ getPageObjects, getService }: FtrProviderContext) => { diff --git a/x-pack/solutions/observability/test/functional/config.base.ts b/x-pack/solutions/observability/test/functional/config.base.ts new file mode 100644 index 0000000000000..a88c575678915 --- /dev/null +++ b/x-pack/solutions/observability/test/functional/config.base.ts @@ -0,0 +1,39 @@ +/* + * 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 { ScoutTestRunConfigCategory } from '@kbn/scout-info'; +import { FtrConfigProviderContext } from '@kbn/test'; +import { services } from './services'; +import { pageObjects } from './page_objects'; + +export async function getFunctionalConfig({ readConfigFile }: FtrConfigProviderContext) { + const xPackPlatformFunctionalTestsConfig = await readConfigFile( + require.resolve('@kbn/test-suites-xpack-platform/functional/config.base') + ); + + return { + ...xPackPlatformFunctionalTestsConfig.getAll(), + services, + pageObjects, + testConfigCategory: ScoutTestRunConfigCategory.UI_TEST, + servers: xPackPlatformFunctionalTestsConfig.get('servers'), + security: xPackPlatformFunctionalTestsConfig.get('security'), + junit: { + reportName: 'X-Pack Observability Functional UI Tests', + }, + kbnTestServer: { + ...xPackPlatformFunctionalTestsConfig.get('kbnTestServer'), + serverArgs: [...xPackPlatformFunctionalTestsConfig.get('kbnTestServer.serverArgs')], + }, + esTestCluster: { + ...xPackPlatformFunctionalTestsConfig.get('esTestCluster'), + serverArgs: [...xPackPlatformFunctionalTestsConfig.get('esTestCluster.serverArgs')], + }, + }; +} + +export default getFunctionalConfig; diff --git a/x-pack/test/functional/config.firefox.js b/x-pack/solutions/observability/test/functional/config.firefox.ts similarity index 72% rename from x-pack/test/functional/config.firefox.js rename to x-pack/solutions/observability/test/functional/config.firefox.ts index a9a39042ff664..f7ee6727c1f09 100644 --- a/x-pack/test/functional/config.firefox.js +++ b/x-pack/solutions/observability/test/functional/config.firefox.ts @@ -5,8 +5,10 @@ * 2.0. */ -export default async function ({ readConfigFile }) { - const chromeConfig = await readConfigFile(require.resolve('./config.base.js')); +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const chromeConfig = await readConfigFile(require.resolve('./config.base.ts')); return { ...chromeConfig.getAll(), @@ -23,7 +25,7 @@ export default async function ({ readConfigFile }) { }, junit: { - reportName: 'Firefox XPack UI Functional Tests', + reportName: 'Firefox XPack Observability UI Functional Tests', }, }; } diff --git a/x-pack/solutions/observability/test/functional/ftr_provider_context.d.ts b/x-pack/solutions/observability/test/functional/ftr_provider_context.d.ts new file mode 100644 index 0000000000000..0b0bb482c700b --- /dev/null +++ b/x-pack/solutions/observability/test/functional/ftr_provider_context.d.ts @@ -0,0 +1,14 @@ +/* + * 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 { GenericFtrProviderContext } from '@kbn/test'; + +import { services } from './services'; +import { pageObjects } from './page_objects'; + +export type FtrProviderContext = GenericFtrProviderContext; +export class FtrService extends GenericFtrService {} diff --git a/x-pack/test/functional/page_objects/alert_controls.ts b/x-pack/solutions/observability/test/functional/page_objects/alert_controls.ts similarity index 100% rename from x-pack/test/functional/page_objects/alert_controls.ts rename to x-pack/solutions/observability/test/functional/page_objects/alert_controls.ts diff --git a/x-pack/solutions/observability/test/functional/page_objects/asset_details.ts b/x-pack/solutions/observability/test/functional/page_objects/asset_details.ts new file mode 100644 index 0000000000000..50a7b5a9b0e08 --- /dev/null +++ b/x-pack/solutions/observability/test/functional/page_objects/asset_details.ts @@ -0,0 +1,385 @@ +/* + * 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 { stringHash } from '@kbn/ml-string-hash'; +import { AlertStatus } from '@kbn/rule-data-utils'; +import { FtrProviderContext } from '../ftr_provider_context'; + +export function AssetDetailsProvider({ getService }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + + return { + async clickApmServicesLink() { + return testSubjects.click('infraAssetDetailsViewAPMServicesButton'); + }, + + async clickOpenAsPageLink() { + return testSubjects.click('infraAssetDetailsOpenAsPageButton'); + }, + + async hostMetricsChartsGroupExists(metric: string) { + return testSubjects.existOrFail(`infraAssetDetailsHostChartsSection${metric}`); + }, + + // Add metrics callout + async addMetricsCalloutExists() { + return testSubjects.existOrFail('infraAddMetricsCallout'); + }, + + // Overview + async clickOverviewTab() { + return testSubjects.click('infraAssetDetailsOverviewTab'); + }, + + async getOverviewTab() { + return testSubjects.find('infraAssetDetailsOverviewTab'); + }, + + async assetDetailsKPITileMissing(type: string) { + return testSubjects.missingOrFail(`infraAssetDetailsKPI${type}`); + }, + + async getAssetDetailsKPITileValue(type: string) { + const element = await testSubjects.find(`infraAssetDetailsKPI${type}`); + const div = await element.findByClassName('echMetricText__value'); + return div.getAttribute('title'); + }, + + async getAssetDetailsKPIMissingFieldMessageExists(type: string) { + const element = await testSubjects.find(`infraAssetDetailsKPI${type}`); + const badge = await element.findByTestSubject('lens-message-list-trigger'); + + await badge.click(); + + await testSubjects.existOrFail('lens-message-list-warning'); + await testSubjects.existOrFail('infraLensCustomErrorHanlderText'); + + await badge.click(); + }, + + async overviewAlertsTitleExists() { + return testSubjects.existOrFail('infraAssetDetailsAlertsTitle'); + }, + + async getAssetDetailsServicesWithIconsAndNames() { + await testSubjects.existOrFail('infraAssetDetailsServicesContainer'); + const container = await testSubjects.find('infraAssetDetailsServicesContainer'); + const serviceLinks = await container.findAllByCssSelector('[data-test-subj="serviceLink"]'); + + const servicesWithIconsAndNames = await Promise.all( + serviceLinks.map(async (link, index) => { + const icon = await link.findByTagName('img'); + const iconSrc = await icon.getAttribute('src'); + await testSubjects.existOrFail(`serviceNameText-service-${index}`); + const serviceElement = await link.findByCssSelector( + `[data-test-subj="serviceNameText-service-${index}"]` + ); + const serviceName = await serviceElement.getVisibleText(); + const serviceUrl = await link.getAttribute('href'); + + return { + serviceName, + serviceUrl, + iconSrc, + }; + }) + ); + + return servicesWithIconsAndNames; + }, + + async overviewLinkToAlertsExist() { + return testSubjects.existOrFail('infraAssetDetailsAlertsTabAlertsShowAllButton'); + }, + + async overviewOpenAlertsFlyoutExist() { + return testSubjects.existOrFail('infraAssetDetailsAlertsTabCreateAlertsRuleButton'); + }, + + async clickShowAllMetadataOverviewTab() { + return testSubjects.click('infraAssetDetailsMetadataShowAllButton'); + }, + + async cpuProfilingPromptExists() { + return testSubjects.existOrFail('infraAssetDetailsCPUProfilingPrompt'); + }, + + async profilingTabExists() { + return testSubjects.existOrFail('infraAssetDetailsProfilingTab'); + }, + + async getOverviewTabHostMetricCharts(metric: string) { + const container = await testSubjects.find('infraAssetDetailsOverviewTabContent'); + await testSubjects.existOrFail(`infraAssetDetailsHostChartsSection${metric}`); + const section = await container.findByTestSubject( + `infraAssetDetailsHostChartsSection${metric}` + ); + return section.findAllByCssSelector('[data-test-subj*="infraAssetDetailsMetricChart"]'); + }, + + async getOverviewTabDockerMetricCharts(metric: string) { + const container = await testSubjects.find('infraAssetDetailsOverviewTabContent'); + await testSubjects.existOrFail(`infraAssetDetailsDockerChartsSection${metric}`); + const section = await container.findByTestSubject( + `infraAssetDetailsDockerChartsSection${metric}` + ); + + return section.findAllByCssSelector('[data-test-subj*="infraAssetDetailsMetricChart"]'); + }, + + async getOverviewTabKubernetesMetricCharts() { + const container = await testSubjects.find('infraAssetDetailsOverviewTabContent'); + const section = await container.findByTestSubject(`infraAssetDetailsKubernetesChartsSection`); + return section.findAllByCssSelector('[data-test-subj*="infraAssetDetailsMetricChart"]'); + }, + + // Collapsable sections + async metadataSectionCollapsibleExist() { + return testSubjects.existOrFail('infraAssetDetailsMetadataCollapsible'); + }, + async alertsSectionCollapsibleExist() { + return testSubjects.existOrFail('infraAssetDetailsAlertsCollapsible'); + }, + async servicesSectionCollapsibleExist() { + return testSubjects.existOrFail('infraAssetDetailsServicesCollapsible'); + }, + async metricsSectionCollapsibleExist() { + return testSubjects.existOrFail('infraAssetDetailsMetricsCollapsible'); + }, + + async alertsSectionCollapsibleClick() { + return testSubjects.click('infraAssetDetailsAlertsCollapsible'); + }, + + async alertsSectionClosedContentExist() { + return testSubjects.existOrFail('infraAssetDetailsAlertsClosedContentWithAlerts'); + }, + async alertsSectionClosedContentMissing() { + return testSubjects.missingOrFail('infraAssetDetailsAlertsClosedContentWithAlerts'); + }, + + async alertsSectionClosedContentNoAlertsExist() { + return testSubjects.existOrFail('infraAssetDetailsAlertsClosedContentNoAlerts'); + }, + async alertsSectionClosedContentNoAlertsMissing() { + return testSubjects.missingOrFail('infraAssetDetailsAlertsClosedContentNoAlerts'); + }, + + // Metadata + async getMetadataTab() { + return testSubjects.find('infraAssetDetailsMetadataTab'); + }, + + async clickMetadataTab() { + return testSubjects.click('infraAssetDetailsMetadataTab'); + }, + + async clickAddMetadataPin() { + return testSubjects.click('infraAssetDetailsMetadataAddPin'); + }, + + async clickRemoveMetadataPin() { + return testSubjects.click('infraAssetDetailsMetadataRemovePin'); + }, + + async clickAddMetadataFilter() { + // Make this selector tied to the field to avoid flakiness + // https://github.com/elastic/kibana/issues/191565 + return testSubjects.click('infraAssetDetailsMetadataField.host.name'); + }, + + async clickRemoveMetadataFilter() { + return testSubjects.click('infraAssetDetailsMetadataRemoveFilterButton'); + }, + + async metadataTableExists() { + return testSubjects.existOrFail('infraAssetDetailsMetadataTable'); + }, + + async metadataTableMissing() { + return testSubjects.missingOrFail('infraAssetDetailsMetadataTable'); + }, + + async metadataRemovePinExists() { + return testSubjects.exists('infraAssetDetailsMetadataRemovePin'); + }, + + async getMetadataAppliedFilter() { + const filter = await testSubjects.find( + `filter-badge-${stringHash( + 'host.name: host-1' + )} filter filter-enabled filter-key-host.name filter-value-host-1 filter-unpinned filter-id-0` + ); + return filter.getVisibleText(); + }, + + async metadataRemoveFilterExists() { + return testSubjects.exists('infraAssetDetailsMetadataRemoveFilterButton'); + }, + + async getMetadataSearchField() { + return testSubjects.find('infraAssetDetailsMetadataSearchBarInput'); + }, + + // Metrics + async clickMetricsTab() { + return testSubjects.click('infraAssetDetailsMetricsTab'); + }, + + async isMetricChartsLoaded() { + return !(await testSubjects.exists( + '[data-test-subj*="infraAssetDetailsMetricChart"] .echChartStatus[data-ech-render-complete=true]' + )); + }, + + async metricsChartsContentExists() { + return testSubjects.click('infraAssetDetailsMetricChartsContent'); + }, + + async getMetricsTabHostCharts(metric: string) { + const container = await testSubjects.find('infraAssetDetailsMetricsTabContent'); + await testSubjects.existOrFail(`infraAssetDetailsHostChartsSection${metric}`); + const section = await container.findByTestSubject( + `infraAssetDetailsHostChartsSection${metric}` + ); + return section.findAllByCssSelector('[data-test-subj*="infraAssetDetailsMetricChart"]'); + }, + + async getMetricsTabKubernetesCharts() { + const container = await testSubjects.find('infraAssetDetailsMetricsTabContent'); + const section = await container.findByTestSubject(`infraAssetDetailsKubernetesChartsSection`); + return section.findAllByCssSelector('[data-test-subj*="infraAssetDetailsMetricChart"]'); + }, + + async getMetricsTabDockerCharts(metric: string) { + const container = await testSubjects.find('infraAssetDetailsMetricsTabContent'); + const section = await container.findByTestSubject( + `infraAssetDetailsDockerChartsSection${metric}` + ); + return section.findAllByCssSelector('[data-test-subj*="infraAssetDetailsMetricChart"]'); + }, + + async quickAccessItemExists(metric: string) { + return testSubjects.click(`infraMetricsQuickAccessItem${metric}`); + }, + + // Processes + async clickProcessesTab() { + return testSubjects.click('infraAssetDetailsProcessesTab'); + }, + + async getProcessesTabContentTitle(index: number) { + const processesListElements = await testSubjects.findAll( + 'infraAssetDetailsProcessesSummaryTableItem' + ); + return processesListElements[index].findByCssSelector('dt'); + }, + + async processesContentExist() { + return testSubjects.existOrFail('infraAssetDetailsProcessesTabContent'); + }, + + async getProcessesTabContentTotalValue() { + const processesListElements = await testSubjects.findAll( + 'infraAssetDetailsProcessesSummaryTableItem' + ); + return processesListElements[0].findByCssSelector('dd'); + }, + + async processesTableExists() { + return testSubjects.existOrFail('infraAssetDetailsProcessesTable'); + }, + + async getProcessesTableBody() { + const processesTable = await testSubjects.find('infraAssetDetailsProcessesTable'); + return processesTable.findByCssSelector('tbody'); + }, + + async clickProcessesTableExpandButton() { + return testSubjects.click('infraProcessRowButton'); + }, + + async getProcessesSearchField() { + return testSubjects.find('infraAssetDetailsProcessesSearchBarInput'); + }, + + async processesSearchInputErrorMissing() { + return testSubjects.missingOrFail('infraAssetDetailsProcessesSearchInputError'); + }, + + async processesSearchInputErrorExists() { + return testSubjects.existOrFail('infraAssetDetailsProcessesSearchInputError'); + }, + + // Logs + async clickLogsTab() { + return testSubjects.click('infraAssetDetailsLogsTab'); + }, + + async logsExists() { + return testSubjects.existOrFail('infraAssetDetailsLogsTabContent'); + }, + + async getLogsSearchField() { + return testSubjects.find('infraAssetDetailsLogsTabFieldSearch'); + }, + + // Anomalies + async clickAnomaliesTab() { + return testSubjects.click('infraAssetDetailsAnomaliesTab'); + }, + + // Osquery + async clickOsqueryTab() { + return testSubjects.click('infraAssetDetailsOsqueryTab'); + }, + + // Dashboards + async clickDashboardsTab() { + return testSubjects.click('infraAssetDetailsDashboardsTab'); + }, + + async dashboardsTabExists() { + return testSubjects.exists('infraAssetDetailsDashboardsTab'); + }, + + async dashboardsTabExistsOrFail() { + return testSubjects.existOrFail('infraAssetDetailsDashboardsTab'); + }, + + async addDashboardExists() { + await testSubjects.existOrFail('infraAddDashboard'); + }, + + async getAddDashboardButton() { + return testSubjects.find('infraAddDashboard'); + }, + + // APM Tab link + async clickApmTabLink() { + return testSubjects.click('infraAssetDetailsApmServicesLinkTab'); + }, + + setAlertStatusFilter(alertStatus?: AlertStatus) { + const buttons: Record = { + active: 'hostsView-alert-status-filter-active-button', + recovered: 'hostsView-alert-status-filter-recovered-button', + untracked: 'hostsView-alert-status-filter-untracked-button', + all: 'hostsView-alert-status-filter-show-all-button', + }; + + const buttonSubject = alertStatus ? buttons[alertStatus] : buttons.all; + + return testSubjects.click(buttonSubject); + }, + + // Callouts + async legacyMetricAlertCalloutExists() { + return testSubjects.exists('infraAssetDetailsLegacyMetricAlertCallout'); + }, + }; +} diff --git a/x-pack/solutions/observability/test/functional/page_objects/index.ts b/x-pack/solutions/observability/test/functional/page_objects/index.ts new file mode 100644 index 0000000000000..5b699d8efa6a6 --- /dev/null +++ b/x-pack/solutions/observability/test/functional/page_objects/index.ts @@ -0,0 +1,30 @@ +/* + * 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 { pageObjects as platformPageObjects } from '@kbn/test-suites-xpack-platform/functional/page_objects'; +import { InfraHomePageProvider } from './infra_home_page'; +import { InfraHostsViewProvider } from './infra_hosts_view'; +import { InfraLogsPageProvider } from './infra_logs_page'; +import { InfraMetricsExplorerProvider } from './infra_metrics_explorer'; +import { InfraSavedViewsProvider } from './infra_saved_views'; +import { UptimePageObject } from './uptime_page'; +import { AssetDetailsProvider } from './asset_details'; +import { ObservabilityPageProvider } from './observability_page'; +import { AlertControlsProvider } from './alert_controls'; + +export const pageObjects = { + ...platformPageObjects, + alertControls: AlertControlsProvider, + assetDetails: AssetDetailsProvider, + infraHome: InfraHomePageProvider, + infraHostsView: InfraHostsViewProvider, + infraLogs: InfraLogsPageProvider, + infraMetricsExplorer: InfraMetricsExplorerProvider, + infraSavedViews: InfraSavedViewsProvider, + observability: ObservabilityPageProvider, + uptime: UptimePageObject, +}; diff --git a/x-pack/solutions/observability/test/functional/page_objects/infra_home_page.ts b/x-pack/solutions/observability/test/functional/page_objects/infra_home_page.ts new file mode 100644 index 0000000000000..b2cec24f61bb8 --- /dev/null +++ b/x-pack/solutions/observability/test/functional/page_objects/infra_home_page.ts @@ -0,0 +1,532 @@ +/* + * 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 expect from '@kbn/expect'; +import { subj as testSubjSelector } from '@kbn/test-subj-selector'; + +import { FtrProviderContext } from '../ftr_provider_context'; + +export function InfraHomePageProvider({ getService, getPageObjects }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + const retry = getService('retry'); + const find = getService('find'); + const browser = getService('browser'); + const pageObjects = getPageObjects(['common']); + const comboBox = getService('comboBox'); + + return { + async goToTime(time: string) { + const datePickerInput = await find.byCssSelector( + `${testSubjSelector('waffleDatePicker')} .euiDatePicker.euiFieldText` + ); + + // explicitly focus to trigger tooltip + await datePickerInput.focus(); + + await datePickerInput.clearValueWithKeyboard(); + await datePickerInput.type(time); + + // dismiss the tooltip, which won't be hidden because blur doesn't happen reliably + await this.dismissDatePickerTooltip(); + + await datePickerInput.pressKeys(browser.keys.ESCAPE); + + await this.waitForLoading(); + }, + + async getWaffleMap() { + await retry.tryForTime(5000, async () => { + const element = await testSubjects.find('waffleMap'); + if (!element) { + throw new Error(); + } + }); + return testSubjects.find('waffleMap'); + }, + + async getWaffleMapTooltips() { + const node = await testSubjects.findAll('nodeContainer'); + await node[0].moveMouseTo(); + const tooltip = await testSubjects.find('conditionalTooltipContent-demo-stack-redis-01'); + const metrics = await tooltip.findAllByTestSubject('conditionalTooltipContent-metric'); + const values = await tooltip.findAllByTestSubject('conditionalTooltipContent-value'); + expect(await metrics[0].getVisibleText()).to.be('CPU usage'); + expect(await values[0].getVisibleText()).to.be('1%'); + expect(await metrics[1].getVisibleText()).to.be('Memory usage'); + expect(await values[1].getVisibleText()).to.be('15.9%'); + expect(await metrics[2].getVisibleText()).to.be('Outbound traffic'); + expect(await values[2].getVisibleText()).to.be('71.9kbit/s'); + expect(await metrics[3].getVisibleText()).to.be('Inbound traffic'); + expect(await values[3].getVisibleText()).to.be('25.6kbit/s'); + await node[1].moveMouseTo(); + const tooltip2 = await testSubjects.find('conditionalTooltipContent-demo-stack-nginx-01'); + const metrics2 = await tooltip2.findAllByTestSubject('conditionalTooltipContent-metric'); + const values2 = await tooltip2.findAllByTestSubject('conditionalTooltipContent-value'); + expect(await metrics2[0].getVisibleText()).to.be('CPU usage'); + expect(await values2[0].getVisibleText()).to.be('1.1%'); + expect(await metrics2[1].getVisibleText()).to.be('Memory usage'); + expect(await values2[1].getVisibleText()).to.be('18%'); + expect(await metrics2[2].getVisibleText()).to.be('Outbound traffic'); + expect(await values2[2].getVisibleText()).to.be('256.3kbit/s'); + expect(await metrics2[3].getVisibleText()).to.be('Inbound traffic'); + expect(await values2[3].getVisibleText()).to.be('255.1kbit/s'); + }, + + async getNodesWithValues() { + const nodes = await testSubjects.findAll('nodeContainer'); + const promises = nodes.map(async (node) => { + const nodeName = await node.findByTestSubject('nodeName'); + const name = await nodeName.getVisibleText(); + const nodeValue = await node.findByTestSubject('nodeValue'); + const value = await nodeValue.getVisibleText(); + const color = await nodeValue.getAttribute('color'); + return { name, value: parseFloat(value), color }; + }); + return Promise.all(promises); + }, + + async getFirstNode() { + const nodes = await testSubjects.findAll('nodeContainer'); + return nodes[0]; + }, + + async clickOnFirstNode() { + const firstNode = await this.getFirstNode(); + return firstNode.click(); + }, + + async clickOnGoToNodeDetails() { + await retry.tryForTime(5000, async () => { + await testSubjects.click('viewAssetDetailsContextMenuItem'); + }); + }, + + async clickOnNodeDetailsFlyoutOpenAsPage() { + await retry.tryForTime(5000, async () => { + await testSubjects.click('infraAssetDetailsOpenAsPageButton'); + }); + }, + + async sortNodesBy(sort: string) { + await testSubjects.click('waffleSortByDropdown'); + if (sort === 'value') { + await testSubjects.find('waffleSortByValue'); + await testSubjects.click('waffleSortByValue'); + } else { + await testSubjects.find('waffleSortByName'); + await testSubjects.click('waffleSortByName'); + } + }, + + async groupByCustomField(field: string) { + await testSubjects.click('waffleGroupByDropdown'); + const contextMenu = await testSubjects.find('groupByContextMenu'); + const menuItems = await contextMenu.findAllByCssSelector('button.euiContextMenuItem'); + await menuItems[0].click(); + const groupByCustomField = await testSubjects.find('groupByCustomField'); + await comboBox.setElement(groupByCustomField, field); + await testSubjects.click('groupByCustomFieldAddButton'); + await this.waitForLoading(); + const groupNameButtons = await testSubjects.findAll('groupNameButton'); + return Promise.all(groupNameButtons.map((link) => link.getVisibleText())); + }, + + async enterSearchTerm(query: string) { + const input = await this.clearSearchTerm(); + await input.type(query); + + // wait for input value to echo the input before submitting + // this ensures the React state has caught up with the events + await retry.tryForTime(5000, async () => { + const value = await input.getAttribute('value'); + expect(value).to.eql(query); + }); + + await input.type(browser.keys.RETURN); + await this.waitForLoading(); + }, + + async clearSearchTerm() { + const input = await testSubjects.find('infraSearchField'); + await input.clearValueWithKeyboard(); + return input; + }, + + async openLegendControls() { + await testSubjects.click('openLegendControlsButton'); + await testSubjects.find('legendControls'); + }, + + async changePalette(paletteId: string) { + const paletteSelector = await testSubjects.find('legendControlsPalette'); + await paletteSelector.click(); + const paletteSelectorEntry = await paletteSelector.findByCssSelector( + `option[value=${paletteId}]` + ); + await paletteSelectorEntry.click(); + }, + + async applyLegendControls() { + await testSubjects.click('applyLegendControlsButton'); + }, + + async toggleReverseSort() { + await testSubjects.click('waffleSortByDropdown'); + await testSubjects.find('waffleSortByDirection'); + await testSubjects.click('waffleSortByDirection'); + }, + + async openTimeline() { + await testSubjects.click('toggleTimelineButton'); + await testSubjects.existOrFail('timelineContainerOpen'); + }, + + async closeTimeline() { + await testSubjects.click('toggleTimelineButton'); + const timelineSelectorsVisible = await Promise.all([ + testSubjects.exists('timelineContainerClosed'), + testSubjects.exists('timelineContainerOpen'), + ]); + + return timelineSelectorsVisible.every((visible) => !visible); + }, + + async toggleInventorySwitcher() { + await testSubjects.click('openInventorySwitcher'); + await testSubjects.find('goToHost'); + await testSubjects.click('openInventorySwitcher'); + await testSubjects.missingOrFail('goToHost', { timeout: 10 * 1000 }); + }, + + async goToHost() { + await browser.pressKeys(browser.keys.ESCAPE); + await testSubjects.click('openInventorySwitcher'); + await testSubjects.find('goToHost'); + return testSubjects.click('goToHost'); + }, + + async goToPods() { + await browser.pressKeys(browser.keys.ESCAPE); + await testSubjects.click('openInventorySwitcher'); + await testSubjects.find('goToHost'); + + return testSubjects.click('goToPods'); + }, + + async goToContainer() { + await browser.pressKeys(browser.keys.ESCAPE); + await testSubjects.click('openInventorySwitcher'); + await testSubjects.find('goToHost'); + return testSubjects.click('goToContainer'); + }, + + async goToSettings() { + await pageObjects.common.navigateToUrlWithBrowserHistory( + 'infraOps', + `/settings`, + undefined, + { ensureCurrentUrl: false } // Test runner struggles with `rison-node` escaped values + ); + }, + + async goToInventory() { + await pageObjects.common.navigateToUrlWithBrowserHistory( + 'infraOps', + `/inventory`, + undefined, + { ensureCurrentUrl: false } // Test runner struggles with `rison-node` escaped values + ); + }, + + async goToMetricExplorer() { + await pageObjects.common.navigateToUrlWithBrowserHistory( + 'infraOps', + `/explorer`, + undefined, + { ensureCurrentUrl: false } // Test runner struggles with `rison-node` escaped values + ); + }, + + async goToHostsView() { + await pageObjects.common.navigateToUrlWithBrowserHistory( + 'infraOps', + `/hosts`, + undefined, + { ensureCurrentUrl: false } // Test runner struggles with `rison-node` escaped values + ); + }, + + async getSaveViewButton() { + return testSubjects.find('openSaveViewModal'); + }, + + async getLoadViewsButton() { + return testSubjects.find('loadViews'); + }, + + async openSaveViewsFlyout() { + return testSubjects.click('loadViews'); + }, + + async closeSavedViewFlyout() { + return testSubjects.click('cancelSavedViewModal'); + }, + + async openCreateSaveViewModal() { + return testSubjects.click('openSaveViewModal'); + }, + + async openEnterViewNameAndSave() { + await testSubjects.setValue('savedViewName', 'View1'); + await testSubjects.click('createSavedViewButton'); + }, + + async noDataPromptExists() { + return testSubjects.existOrFail('noDataPage'); + }, + + async noDataPromptAddDataClick() { + return testSubjects.click('noDataDefaultFooterAction'); + }, + + async getNoMetricsDataPrompt() { + return testSubjects.find('noMetricsDataPrompt'); + }, + + async getNoRemoteClusterPrompt() { + return testSubjects.find('infraHostsNoRemoteCluster'); + }, + + async getInfraMissingMetricsIndicesCallout() { + return testSubjects.find('infraIndicesPanelSettingsWarningCallout'); + }, + async getInfraIndicesPanelSettingsWarningCalloutUsedByRules() { + return testSubjects.find('infraIndicesPanelSettingsWarningCalloutUsedByRules'); + }, + + async getInfraMissingRemoteClusterIndicesCallout() { + return testSubjects.find('infraIndicesPanelSettingsWarningCallout'); + }, + + async openSourceConfigurationFlyout() { + await testSubjects.click('configureSourceButton'); + await testSubjects.exists('sourceConfigurationFlyout'); + }, + + async waitForLoading() { + await testSubjects.missingOrFail('loadingMessage', { timeout: 20000 }); + }, + + async openAnomalyFlyout() { + await testSubjects.click('openAnomalyFlyoutButton'); + await testSubjects.exists('loadMLFlyout'); + }, + async closeFlyout() { + await testSubjects.click('euiFlyoutCloseButton'); + }, + async goToAnomaliesTab() { + await testSubjects.click('anomalyFlyoutAnomaliesTab'); + }, + async getNoAnomaliesMsg() { + await testSubjects.find('noAnomaliesFoundMsg'); + }, + async clickHostsAnomaliesDropdown() { + await testSubjects.click('anomaliesComboBoxType'); + await testSubjects.click('anomaliesHostComboBoxItem'); + }, + async clickK8sAnomaliesDropdown() { + await testSubjects.click('anomaliesComboBoxType'); + await testSubjects.click('anomaliesK8sComboBoxItem'); + }, + async findAnomalies() { + return testSubjects.findAll('anomalyRow'); + }, + async setAnomaliesDate(date: string) { + await testSubjects.click('superDatePickerShowDatesButton'); + await testSubjects.click('superDatePickerAbsoluteTab'); + const datePickerInput = await testSubjects.find('superDatePickerAbsoluteDateInput'); + await datePickerInput.clearValueWithKeyboard(); + await datePickerInput.type([date, browser.keys.RETURN]); + }, + async setAnomaliesThreshold(threshold: string) { + const thresholdInput = await find.byCssSelector( + `.euiFieldNumber.euiRangeInput.euiRangeInput--max` + ); + await thresholdInput.clearValueWithKeyboard({ charByChar: true }); + await thresholdInput.type([threshold]); + }, + + async ensureAlertsAndRulesDropdownIsMissing() { + await testSubjects.missingOrFail('infrastructure-alerts-and-rules'); + }, + + async clickAlertsAndRules() { + await testSubjects.click('infrastructure-alerts-and-rules'); + }, + + async ensurePopoverOpened() { + await testSubjects.existOrFail('metrics-alert-menu'); + }, + + async ensurePopoverClosed() { + await testSubjects.missingOrFail('metrics-alert-menu'); + }, + + async ensureCustomThresholdAlertMenuItemIsVisible() { + await testSubjects.existOrFail('custom-threshold-alerts-menu-option'); + }, + + async ensureCustomThresholdAlertMenuItemIsMissing() { + await testSubjects.missingOrFail('custom-threshold-alerts-menu-option'); + }, + + async dismissDatePickerTooltip() { + const isTooltipOpen = await testSubjects.exists(`waffleDatePickerIntervalTooltip`, { + timeout: 3000, + }); + + if (isTooltipOpen) { + await testSubjects.click(`waffleDatePickerIntervalTooltip`); + } + }, + + async openInventoryAlertFlyout() { + await this.dismissDatePickerTooltip(); + await testSubjects.click('infrastructure-alerts-and-rules'); + await testSubjects.click('inventory-alerts-menu-option'); + + // forces date picker tooltip to close in case it pops up after Alerts and rules opens + await testSubjects.moveMouseTo('contextMenuPanelTitleButton'); + + await retry.tryForTime(1000, () => testSubjects.click('inventory-alerts-create-rule')); + await testSubjects.missingOrFail('inventory-alerts-create-rule', { timeout: 30000 }); + }, + + async openMetricsThresholdAlertFlyout() { + await this.dismissDatePickerTooltip(); + await testSubjects.click('infrastructure-alerts-and-rules'); + await testSubjects.click('metrics-threshold-alerts-menu-option'); + + // forces date picker tooltip to close in case it pops up after Alerts and rules opens + await testSubjects.moveMouseTo('contextMenuPanelTitleButton'); + + await retry.tryForTime(1000, () => + testSubjects.click('metrics-threshold-alerts-create-rule') + ); + await testSubjects.missingOrFail('metrics-threshold-alerts-create-rule', { timeout: 30000 }); + }, + + async closeAlertFlyout() { + await testSubjects.click('euiFlyoutCloseButton'); + }, + + async waitForTourStep(tourStep: string) { + await retry.waitForWithTimeout(`tour step ${tourStep}`, 10000, () => + testSubjects.exists(tourStep) + ); + }, + + async ensureTourStepIsClosed(tourStep: string) { + await testSubjects.missingOrFail(tourStep); + }, + + async clickTourNextButton() { + await testSubjects.click('onboarding--observTourNextStepButton'); + }, + + async clickTourEndButton() { + await testSubjects.click('onboarding--observTourEndButton'); + }, + + async clickTourSkipButton() { + await testSubjects.click('onboarding--observTourSkipButton'); + }, + + async clickGuidedSetupButton() { + await testSubjects.click('guidedSetupButton'); + }, + + async clickQueryBar() { + await testSubjects.click('infraSearchField'); + }, + + async inputQueryData() { + const queryBar = await testSubjects.find('infraSearchField'); + await queryBar.type('h'); + }, + + async inputAddHostNameFilter(hostName: string) { + await this.enterSearchTerm(`host.name:"${hostName}"`); + }, + + async clickOnNode() { + return testSubjects.click('nodeContainer'); + }, + + async ensureSuggestionsPanelVisible() { + await testSubjects.find('infraSuggestionsPanel'); + }, + + async ensureInventoryFeedbackLinkIsVisible() { + await testSubjects.existOrFail('infraInventoryFeedbackLink'); + }, + + async ensureKubernetesTourIsVisible() { + const container = await testSubjects.find('infra-kubernetesTour-text'); + const containerText = await container.getVisibleText(); + return containerText; + }, + + async ensureKubernetesTourIsClosed() { + await testSubjects.missingOrFail('infra-kubernetesTour-text'); + }, + + async clickDismissKubernetesTourButton() { + return testSubjects.click('infra-kubernetesTour-dismiss'); + }, + + async clickCloseFlyoutButton() { + return testSubjects.click('euiFlyoutCloseButton'); + }, + + async clickCustomMetricDropdown() { + await testSubjects.click('infraInventoryMetricDropdown'); + }, + + async addCustomMetric(field: string) { + await testSubjects.click('infraModeSwitcherAddMetricButton'); + const groupByCustomField = await testSubjects.find('infraCustomMetricFieldSelect'); + await comboBox.setElement(groupByCustomField, field); + await testSubjects.click('infraCustomMetricFormSaveButton'); + }, + + async getMetricsContextMenuItemsCount() { + const contextMenu = await testSubjects.find('infraInventoryMetricsContextMenu'); + const menuItems = await contextMenu.findAllByCssSelector('button.euiContextMenuItem'); + return menuItems.length; + }, + + async ensureCustomMetricAddButtonIsDisabled() { + const button = await testSubjects.find('infraModeSwitcherAddMetricButton'); + expect(await button.getAttribute('disabled')).to.be('true'); + }, + + async clickAnomalyActionMenuButton() { + await testSubjects.click('infraAnomalyActionMenuButton'); + }, + + async clickShowAffectedHostsButton() { + await this.clickAnomalyActionMenuButton(); + await testSubjects.click('infraAnomalyFlyoutShowAffectedHosts'); + }, + + async getAnomalyHostName() { + const element = await testSubjects.find('nodeNameRow'); + return await element.getVisibleText(); + }, + }; +} diff --git a/x-pack/solutions/observability/test/functional/page_objects/infra_hosts_view.ts b/x-pack/solutions/observability/test/functional/page_objects/infra_hosts_view.ts new file mode 100644 index 0000000000000..268640b67e876 --- /dev/null +++ b/x-pack/solutions/observability/test/functional/page_objects/infra_hosts_view.ts @@ -0,0 +1,280 @@ +/* + * 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 { AlertStatus } from '@kbn/rule-data-utils'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; +import { FtrProviderContext } from '../ftr_provider_context'; + +export function InfraHostsViewProvider({ getService }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + + return { + async clickTableOpenFlyoutButton() { + return testSubjects.click('hostsView-flyout-button'); + }, + + async clickHostCheckbox(id: string, os: string) { + return testSubjects.click(`checkboxSelectRow-${id}-${os}`); + }, + + async clickSelectedHostsButton() { + return testSubjects.click('hostsViewTableSelectHostsFilterButton'); + }, + + async clickSelectedHostsAddFilterButton() { + return testSubjects.click('hostsViewTableAddFilterButton'); + }, + + // Table + + async getHostsTable() { + return testSubjects.find('hostsView-table-loaded'); + }, + + async isHostTableLoaded() { + return !(await testSubjects.exists('hostsView-table-loading')); + }, + + async getHostsTableData() { + const table = await this.getHostsTable(); + return table.findAllByTestSubject('hostsView-tableRow'); + }, + + async getHostsRowDataWithAlerts(row: WebElementWrapper) { + // Find all the row cells + const cells = await row.findAllByCssSelector('[data-test-subj*="hostsView-tableRow-"]'); + + // Retrieve content for each cell + const [ + alertsCount, + title, + cpuUsage, + normalizedLoad, + memoryUsage, + memoryFree, + diskSpaceUsage, + rx, + tx, + ] = await Promise.all(cells.map((cell) => this.getHostsCellContent(cell))); + + return { + alertsCount, + title, + cpuUsage, + normalizedLoad, + memoryUsage, + memoryFree, + diskSpaceUsage, + rx, + tx, + }; + }, + + async getHostsRowData(row: WebElementWrapper) { + // Find all the row cells + const cells = await row.findAllByCssSelector('[data-test-subj*="hostsView-tableRow-"]'); + + // Retrieve content for each cell + const [title, cpuUsage, normalizedLoad, memoryUsage, memoryFree, diskSpaceUsage, rx, tx] = + await Promise.all(cells.map((cell) => this.getHostsCellContent(cell))); + + return { + title, + cpuUsage, + normalizedLoad, + memoryUsage, + memoryFree, + diskSpaceUsage, + rx, + tx, + }; + }, + + async getHostsCellContent(cell: WebElementWrapper) { + const cellContent = await cell.findByClassName('euiTableCellContent'); + return cellContent.getVisibleText(); + }, + + async selectedHostsButtonExist() { + return testSubjects.exists('hostsViewTableSelectHostsFilterButton'); + }, + + async getMetricsTrendContainer() { + return testSubjects.find('hostsViewKPIGrid'); + }, + + async getChartsContainer() { + return testSubjects.find('hostsView-metricChart'); + }, + + async getAllHostDetailLinks() { + return testSubjects.findAll('hostsViewTableEntryTitleLink'); + }, + + // Metrics Tab + async getMetricsTab() { + return testSubjects.find('hostsView-tabs-metrics'); + }, + + async visitMetricsTab() { + const metricsTab = await this.getMetricsTab(); + return metricsTab.click(); + }, + + async getAllMetricsCharts() { + const container = await this.getChartsContainer(); + return container.findAllByCssSelector('[data-test-subj*="hostsView-metricChart-"]'); + }, + + async clickAndValidateMetricChartActionOptions() { + const element = await testSubjects.find('hostsView-metricChart-tx'); + await element.moveMouseTo(); + + const button = await element.findByTestSubject('embeddablePanelToggleMenuIcon'); + await button.click(); + const menuElement = await testSubjects.find('presentationPanelContextMenuItems'); + await menuElement.moveMouseTo(); + return testSubjects.existOrFail('embeddablePanelAction-openInLens'); + }, + + // KPIs + async isKPIChartsLoaded() { + return !(await testSubjects.exists( + '[data-test-subj=hostsView-metricsTrend] .echChartStatus[data-ech-render-complete=true]' + )); + }, + + async getAllKPITiles() { + const container = await this.getMetricsTrendContainer(); + return container.findAllByCssSelector('[data-test-subj*="hostsViewKPI-"]'); + }, + + async getKPITileValue(type: string) { + const container = await this.getMetricsTrendContainer(); + const element = await container.findByTestSubject(`hostsViewKPI-${type}`); + const div = await element.findByClassName('echMetricText__value'); + return div.getAttribute('title'); + }, + + // Logs Tab + getLogsTab() { + return testSubjects.find('hostsView-tabs-logs'); + }, + + async visitLogsTab() { + const logsTab = await this.getLogsTab(); + await logsTab.click(); + }, + + async getLogEntries() { + const container = await testSubjects.find('hostsView-logs'); + + return container.findAllByCssSelector('[data-test-subj*=streamEntry]'); + }, + + async getLogsTableColumnHeaders() { + const columnHeaderElements: WebElementWrapper[] = await testSubjects.findAll( + '~logColumnHeader' + ); + return await Promise.all(columnHeaderElements.map((element) => element.getVisibleText())); + }, + + // Alerts Tab + getAlertsTab() { + return testSubjects.find('hostsView-tabs-alerts'); + }, + + getAlertsTabCountBadge() { + return testSubjects.find('hostsView-tabs-alerts-count'); + }, + + async getAlertsCount() { + const alertsCountBadge = await this.getAlertsTabCountBadge(); + return alertsCountBadge.getVisibleText(); + }, + + async visitAlertTab() { + const alertsTab = await this.getAlertsTab(); + await alertsTab.click(); + }, + + setAlertStatusFilter(alertStatus?: AlertStatus) { + const buttons: Record = { + active: 'hostsView-alert-status-filter-active-button', + recovered: 'hostsView-alert-status-filter-recovered-button', + untracked: 'hostsView-alert-status-filter-untracked-button', + all: 'hostsView-alert-status-filter-show-all-button', + }; + + const buttonSubject = alertStatus ? buttons[alertStatus] : buttons.all; + + return testSubjects.click(buttonSubject); + }, + + // Query Bar + getQueryBar() { + return testSubjects.find('queryInput'); + }, + + async typeInQueryBar(query: string) { + const queryBar = await this.getQueryBar(); + await queryBar.clearValueWithKeyboard(); + return queryBar.type(query); + }, + + async submitQuery(query: string) { + await this.typeInQueryBar(query); + await testSubjects.click('querySubmitButton'); + }, + + // Pagination + getPageNumberButton(pageNumber: number) { + return testSubjects.find(`pagination-button-${pageNumber - 1}`); + }, + + getPageSizeSelector() { + return testSubjects.find('tablePaginationPopoverButton'); + }, + + getPageSizeOption(pageSize: number) { + return testSubjects.find(`tablePagination-${pageSize}-rows`); + }, + + async changePageSize(pageSize: number) { + const pageSizeSelector = await this.getPageSizeSelector(); + await pageSizeSelector.click(); + const pageSizeOption = await this.getPageSizeOption(pageSize); + await pageSizeOption.click(); + }, + + async paginateTo(pageNumber: number) { + const paginationButton = await this.getPageNumberButton(pageNumber); + await paginationButton.click(); + }, + + // Sorting + getCpuHeader() { + return testSubjects.find('tableHeaderCell_cpuV2_2'); + }, + + getTitleHeader() { + return testSubjects.find('tableHeaderCell_title_1'); + }, + + async sortByCpuUsage() { + const cpu = await this.getCpuHeader(); + const button = await testSubjects.findDescendant('tableHeaderSortButton', cpu); + await button.click(); + }, + + async sortByTitle() { + const titleHeader = await this.getTitleHeader(); + const button = await testSubjects.findDescendant('tableHeaderSortButton', titleHeader); + await button.click(); + }, + }; +} diff --git a/x-pack/solutions/observability/test/functional/page_objects/infra_logs_page.ts b/x-pack/solutions/observability/test/functional/page_objects/infra_logs_page.ts new file mode 100644 index 0000000000000..21d54b844a050 --- /dev/null +++ b/x-pack/solutions/observability/test/functional/page_objects/infra_logs_page.ts @@ -0,0 +1,34 @@ +/* + * 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 { FtrProviderContext } from '../ftr_provider_context'; + +export function InfraLogsPageProvider({ getPageObjects, getService }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + const pageObjects = getPageObjects(['common']); + + return { + async navigateTo() { + await pageObjects.common.navigateToApp('infraLogs'); + }, + + async navigateToTab(logsUiTab: T) { + await pageObjects.common.navigateToUrlWithBrowserHistory( + 'infraLogs', + `/${logsUiTab}`, + '', + { ensureCurrentUrl: false } // Test runner struggles with `rison-node` escaped values + ); + }, + + async getLogStream() { + return await testSubjects.find('logStream'); + }, + }; +} + +type LogsUiTab = 'log-categories' | 'log-rate'; diff --git a/x-pack/test/functional/page_objects/infra_metrics_explorer.ts b/x-pack/solutions/observability/test/functional/page_objects/infra_metrics_explorer.ts similarity index 100% rename from x-pack/test/functional/page_objects/infra_metrics_explorer.ts rename to x-pack/solutions/observability/test/functional/page_objects/infra_metrics_explorer.ts diff --git a/x-pack/test/functional/page_objects/infra_saved_views.ts b/x-pack/solutions/observability/test/functional/page_objects/infra_saved_views.ts similarity index 100% rename from x-pack/test/functional/page_objects/infra_saved_views.ts rename to x-pack/solutions/observability/test/functional/page_objects/infra_saved_views.ts diff --git a/x-pack/test/functional/page_objects/observability_page.ts b/x-pack/solutions/observability/test/functional/page_objects/observability_page.ts similarity index 100% rename from x-pack/test/functional/page_objects/observability_page.ts rename to x-pack/solutions/observability/test/functional/page_objects/observability_page.ts diff --git a/x-pack/solutions/observability/test/functional/page_objects/uptime_page.ts b/x-pack/solutions/observability/test/functional/page_objects/uptime_page.ts new file mode 100644 index 0000000000000..07c7e25edd975 --- /dev/null +++ b/x-pack/solutions/observability/test/functional/page_objects/uptime_page.ts @@ -0,0 +1,126 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrService } from '../ftr_provider_context'; + +export class UptimePageObject extends FtrService { + private readonly timePicker = this.ctx.getPageObject('timePicker'); + private readonly header = this.ctx.getPageObject('header'); + + private readonly commonService = this.ctx.getService('uptime').common; + private readonly monitor = this.ctx.getService('uptime').monitor; + private readonly navigation = this.ctx.getService('uptime').navigation; + private readonly retry = this.ctx.getService('retry'); + + public async goToRoot(refresh?: boolean) { + await this.navigation.goToUptime(); + if (refresh) { + await this.navigation.refreshApp(); + } + } + + public async setDateRange(start: string, end: string) { + const { start: prevStart, end: prevEnd } = await this.timePicker.getTimeConfig(); + if (start !== prevStart || prevEnd !== end) { + await this.timePicker.setAbsoluteRange(start, end); + } else { + await this.navigation.refreshApp(); + } + } + + public async goToUptimeOverviewAndLoadData( + dateStart: string, + dateEnd: string, + monitorIdToCheck?: string + ) { + await this.navigation.goToUptime(); + await this.setDateRange(dateStart, dateEnd); + if (monitorIdToCheck) { + await this.commonService.monitorIdExists(monitorIdToCheck); + } + await this.header.waitUntilLoadingHasFinished(); + } + + public async loadDataAndGoToMonitorPage(dateStart: string, dateEnd: string, monitorId: string) { + await this.header.waitUntilLoadingHasFinished(); + await this.setDateRange(dateStart, dateEnd); + await this.navigation.goToMonitor(monitorId); + } + + public async inputFilterQuery(filterQuery: string) { + await this.commonService.setFilterText(filterQuery); + } + + public async pageHasDataMissing() { + return await this.commonService.pageHasDataMissing(); + } + + public async pageHasExpectedIds(monitorIdsToCheck: string[]): Promise { + return this.retry.tryForTime(15000, async () => { + await Promise.all( + monitorIdsToCheck.map((id) => this.commonService.monitorPageLinkExists(id)) + ); + }); + } + + public async pageUrlContains(value: string, expected: boolean = true): Promise { + return this.retry.tryForTime(12000, async () => { + expect(await this.commonService.urlContains(value)).to.eql(expected); + }); + } + + public async changePage(direction: 'next' | 'prev') { + if (direction === 'next') { + await this.commonService.goToNextPage(); + } else if (direction === 'prev') { + await this.commonService.goToPreviousPage(); + } + } + + public async setStatusFilter(value: 'up' | 'down') { + if (value === 'up') { + await this.commonService.setStatusFilterUp(); + } else if (value === 'down') { + await this.commonService.setStatusFilterDown(); + } + } + + public async selectFilterItems(filters: Record) { + for (const key in filters) { + if (Object.hasOwn(filters, key)) { + const values = filters[key]; + for (let i = 0; i < values.length; i++) { + await this.commonService.selectFilterItem(key, values[i]); + } + } + } + } + + public async getSnapshotCount() { + return await this.commonService.getSnapshotCount(); + } + + public async setAlertKueryBarText(filters: string) { + const { setKueryBarText } = this.commonService; + await setKueryBarText('xpack.synthetics.alerts.monitorStatus.filterBar', filters); + } + + public async setMonitorListPageSize(size: number): Promise { + await this.commonService.openPageSizeSelectPopover(); + return this.commonService.clickPageSizeSelectPopoverItem(size); + } + + public async checkPingListInteractions(timestamps: string[]): Promise { + return this.monitor.checkForPingListTimestamps(timestamps); + } + + public async resetFilters() { + await this.inputFilterQuery(''); + await this.commonService.resetStatusFilter(); + } +} diff --git a/x-pack/solutions/observability/test/functional/services/index.ts b/x-pack/solutions/observability/test/functional/services/index.ts new file mode 100644 index 0000000000000..dc5f22c836be2 --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/index.ts @@ -0,0 +1,24 @@ +/* + * 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 { services as platformServices } from '@kbn/test-suites-xpack-platform/functional/services'; +import { services as obltApiServices } from '../../api_integration/services'; +import { SloUiServiceProvider } from './slo'; +import { UptimeProvider } from './uptime'; +import { InfraSourceConfigurationFormProvider } from './infra_source_configuration_form'; +import { LogsUiProvider } from './logs_ui'; +import { ObservabilityProvider } from './observability'; + +export const services = { + ...platformServices, + ...obltApiServices, + infraSourceConfigurationForm: InfraSourceConfigurationFormProvider, + logsUi: LogsUiProvider, + observability: ObservabilityProvider, + sloUi: SloUiServiceProvider, + uptime: UptimeProvider, +}; diff --git a/x-pack/solutions/observability/test/functional/services/infra_source_configuration_form.ts b/x-pack/solutions/observability/test/functional/services/infra_source_configuration_form.ts new file mode 100644 index 0000000000000..9589debf5d289 --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/infra_source_configuration_form.ts @@ -0,0 +1,72 @@ +/* + * 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 { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; +import { FtrProviderContext } from '../ftr_provider_context'; + +export function InfraSourceConfigurationFormProvider({ + getService, + getPageObject, +}: FtrProviderContext) { + const retry = getService('retry'); + const testSubjects = getService('testSubjects'); + + return { + /** + * Indices and fields + */ + async getNameInput(): Promise { + return await testSubjects.findDescendant('~nameInput', await this.getForm()); + }, + async getMetricIndicesInput(): Promise { + return await testSubjects.findDescendant('~metricIndicesInput', await this.getForm()); + }, + async selectIndicesPanel(): Promise { + return await testSubjects.click('logIndicesCheckableCard'); + }, + + /** + * Infra Metrics bottom actions bar + */ + async getSaveButton(): Promise { + return await testSubjects.find('infraBottomBarActionsButton'); + }, + + async saveInfraSettings() { + await (await this.getSaveButton()).click(); + + await retry.try(async () => { + const element = await this.getSaveButton(); + return !(await element.isDisplayed()); + }); + }, + + async discardInfraSettingsChanges() { + await (await testSubjects.find('infraBottomBarActionsDiscardChangesButton')).click(); + }, + + /** + * Form + */ + async getForm(): Promise { + return await testSubjects.find('~sourceConfigurationContent'); + }, + async saveConfiguration() { + await ( + await testSubjects.findDescendant('~applySettingsButton', await this.getForm()) + ).click(); + + await retry.try(async () => { + const element = await testSubjects.findDescendant( + '~applySettingsButton', + await this.getForm() + ); + return !(await element.isEnabled()); + }); + }, + }; +} diff --git a/x-pack/test/functional/services/logs_ui/index.ts b/x-pack/solutions/observability/test/functional/services/logs_ui/index.ts similarity index 100% rename from x-pack/test/functional/services/logs_ui/index.ts rename to x-pack/solutions/observability/test/functional/services/logs_ui/index.ts diff --git a/x-pack/test/functional/services/logs_ui/log_entry_categories.ts b/x-pack/solutions/observability/test/functional/services/logs_ui/log_entry_categories.ts similarity index 100% rename from x-pack/test/functional/services/logs_ui/log_entry_categories.ts rename to x-pack/solutions/observability/test/functional/services/logs_ui/log_entry_categories.ts diff --git a/x-pack/test/functional/services/logs_ui/log_entry_rate.ts b/x-pack/solutions/observability/test/functional/services/logs_ui/log_entry_rate.ts similarity index 100% rename from x-pack/test/functional/services/logs_ui/log_entry_rate.ts rename to x-pack/solutions/observability/test/functional/services/logs_ui/log_entry_rate.ts diff --git a/x-pack/solutions/observability/test/functional/services/observability/alerts/add_to_case.ts b/x-pack/solutions/observability/test/functional/services/observability/alerts/add_to_case.ts new file mode 100644 index 0000000000000..6197273243432 --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/observability/alerts/add_to_case.ts @@ -0,0 +1,76 @@ +/* + * 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 { FtrProviderContext } from '../../../ftr_provider_context'; + +const ADD_TO_EXISTING_CASE_SELECTOR = 'add-to-existing-case-action'; +const ADD_TO_NEW_CASE_SELECTOR = 'add-to-new-case-action'; +const CREATE_CASE_FLYOUT = 'create-case-flyout'; +const SELECT_CASE_MODAL = 'all-cases-modal'; + +export function ObservabilityAlertsAddToCaseProvider({ getService }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + + const getAddToExistingCaseSelector = async () => { + return await testSubjects.find(ADD_TO_EXISTING_CASE_SELECTOR); + }; + + const getAddToExistingCaseSelectorOrFail = async () => { + return await testSubjects.existOrFail(ADD_TO_EXISTING_CASE_SELECTOR); + }; + + const missingAddToExistingCaseSelectorOrFail = async () => { + return await testSubjects.missingOrFail(ADD_TO_EXISTING_CASE_SELECTOR); + }; + + const getAddToNewCaseSelector = async () => { + return await testSubjects.find(ADD_TO_NEW_CASE_SELECTOR); + }; + + const getAddToNewCaseSelectorOrFail = async () => { + return await testSubjects.existOrFail(ADD_TO_NEW_CASE_SELECTOR); + }; + + const missingAddToNewCaseSelectorOrFail = async () => { + return await testSubjects.missingOrFail(ADD_TO_NEW_CASE_SELECTOR); + }; + + const addToNewCaseButtonClick = async () => { + return await (await getAddToNewCaseSelector()).click(); + }; + + const addToExistingCaseButtonClick = async () => { + return await (await getAddToExistingCaseSelector()).click(); + }; + + const getCreateCaseFlyoutOrFail = async () => { + return await testSubjects.existOrFail(CREATE_CASE_FLYOUT); + }; + + const closeFlyout = async () => { + await testSubjects.click('euiFlyoutCloseButton'); // click close button + await testSubjects.missingOrFail('euiFlyoutCloseButton'); // wait for flyout to be closed + }; + + const getAddToExistingCaseModalOrFail = async () => { + return await testSubjects.existOrFail(SELECT_CASE_MODAL); + }; + + return { + getAddToExistingCaseSelector, + getAddToExistingCaseSelectorOrFail, + missingAddToExistingCaseSelectorOrFail, + getAddToNewCaseSelector, + getAddToNewCaseSelectorOrFail, + missingAddToNewCaseSelectorOrFail, + getCreateCaseFlyoutOrFail, + closeFlyout, + addToNewCaseButtonClick, + addToExistingCaseButtonClick, + getAddToExistingCaseModalOrFail, + }; +} diff --git a/x-pack/solutions/observability/test/functional/services/observability/alerts/common.ts b/x-pack/solutions/observability/test/functional/services/observability/alerts/common.ts new file mode 100644 index 0000000000000..81a19364316a5 --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/observability/alerts/common.ts @@ -0,0 +1,463 @@ +/* + * 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 expect from '@kbn/expect'; +import { ToolingLog } from '@kbn/tooling-log'; +import { chunk } from 'lodash'; +import { ALERT_STATUS_ACTIVE, ALERT_STATUS_RECOVERED, AlertStatus } from '@kbn/rule-data-utils'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; +import { Agent as SuperTestAgent } from 'supertest'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +// Based on the x-pack/test/functional/es_archives/observability/alerts archive. +const DATE_WITH_DATA = { + rangeFrom: '2021-10-18T13:36:22.109Z', + rangeTo: '2021-10-20T13:36:22.109Z', +}; + +const ALERTS_FLYOUT_SELECTOR = 'alertsFlyout'; +const FILTER_FOR_VALUE_BUTTON_SELECTOR = 'filterForValue'; +const ALERTS_TABLE_WITH_DATA_SELECTOR = 'alertsTableIsLoaded'; +const ALERTS_TABLE_NO_DATA_SELECTOR = 'alertsTableEmptyState'; +const ALERTS_TABLE_ERROR_PROMPT_SELECTOR = 'alertsTableErrorPrompt'; +const ALERTS_TABLE_ACTIONS_MENU_SELECTOR = 'alertsTableActionsMenu'; +const VIEW_RULE_DETAILS_SELECTOR = 'viewRuleDetails'; +const VIEW_RULE_DETAILS_FLYOUT_SELECTOR = 'viewRuleDetailsFlyout'; +const ALERTS_TABLE_LOADING_SELECTOR = 'internalAlertsPageLoading'; + +type WorkflowStatus = 'open' | 'acknowledged' | 'closed'; + +export function ObservabilityAlertsCommonProvider({ + getPageObjects, + getService, +}: FtrProviderContext) { + const find = getService('find'); + const testSubjects = getService('testSubjects'); + const flyoutService = getService('flyout'); + const retry = getService('retry'); + const toasts = getService('toasts'); + const kibanaServer = getService('kibanaServer'); + const retryOnStale = getService('retryOnStale'); + const pageObjects = getPageObjects(['common', 'header']); + + const navigateToTimeWithData = async () => { + await pageObjects.common.navigateToUrlWithBrowserHistory( + 'observability', + '/alerts', + `?_a=(rangeFrom:'${DATE_WITH_DATA.rangeFrom}',rangeTo:'${DATE_WITH_DATA.rangeTo}')`, + { ensureCurrentUrl: false } + ); + await pageObjects.header.waitUntilLoadingHasFinished(); + }; + + const navigateToRulesPage = async () => { + return await pageObjects.common.navigateToUrlWithBrowserHistory( + 'observability', + '/alerts/rules', + '', + { ensureCurrentUrl: false } + ); + }; + + const navigateToRulesLogsPage = async () => { + return await pageObjects.common.navigateToUrlWithBrowserHistory( + 'observability', + '/alerts/rules/logs', + '', + { ensureCurrentUrl: false } + ); + }; + + const navigateToAlertDetails = async (alertId: string) => { + return await pageObjects.common.navigateToUrlWithBrowserHistory( + 'observability', + `/alerts/${alertId}`, + '', + { ensureCurrentUrl: false } + ); + }; + + const navigateToRuleDetailsByRuleId = async (ruleId: string) => { + return await pageObjects.common.navigateToUrlWithBrowserHistory( + 'observability', + `/alerts/rules/${ruleId}`, + '?', + { ensureCurrentUrl: false } + ); + }; + + const navigateWithoutFilter = async () => { + return await pageObjects.common.navigateToUrlWithBrowserHistory( + 'observability', + '/alerts', + `?`, + { ensureCurrentUrl: false } + ); + }; + + const setKibanaTimeZoneToUTC = async () => { + await kibanaServer.uiSettings.update({ + 'dateFormat:tz': 'UTC', + }); + }; + + // Alert table + const waitForAlertsTableLoadingToDisappear = async () => { + await testSubjects.missingOrFail(ALERTS_TABLE_LOADING_SELECTOR, { timeout: 30_000 }); + }; + + const waitForAlertTableToLoad = async () => { + await waitForAlertsTableLoadingToDisappear(); + await retry.waitFor('alerts table to appear', async () => { + return ( + (await testSubjects.exists(ALERTS_TABLE_NO_DATA_SELECTOR)) || + (await testSubjects.exists(ALERTS_TABLE_WITH_DATA_SELECTOR)) + ); + }); + }; + + const getTableColumnHeaders = async () => { + const table = await testSubjects.find(ALERTS_TABLE_WITH_DATA_SELECTOR); + const tableHeaderRow = await testSubjects.findDescendant('dataGridHeader', table); + const columnHeaders = await tableHeaderRow.findAllByXpath('./div'); + return columnHeaders; + }; + + const getTableCells = async () => { + // NOTE: This isn't ideal, but EuiDataGrid doesn't really have the concept of "rows" + return await testSubjects.findAll('dataGridRowCell'); + }; + + const getAllDisabledCheckBoxInTable = async () => { + return await find.allByCssSelector('.euiDataGridRowCell input[type="checkbox"]:disabled'); + }; + + const getAllEnabledCheckBoxInTable = async () => { + return await find.allByCssSelector('.euiDataGridRowCell input[type="checkbox"]:enabled'); + }; + + const getTableCellsInRows = retryOnStale.wrap(async () => { + const columnHeaders = await getTableColumnHeaders(); + if (columnHeaders.length <= 0) { + return []; + } + const cells = await getTableCells(); + return chunk(cells, columnHeaders.length); + }); + + const getTableOrFail = async () => { + return await testSubjects.existOrFail(ALERTS_TABLE_WITH_DATA_SELECTOR); + }; + + const ensureNoTableErrorPrompt = async () => { + return await testSubjects.missingOrFail(ALERTS_TABLE_ERROR_PROMPT_SELECTOR); + }; + + const getNoDataPageOrFail = async () => { + return await testSubjects.existOrFail('noDataPage'); + }; + + const getNoDataStateOrFail = async () => { + return await testSubjects.existOrFail('alertsTableEmptyState'); + }; + + // Query Bar + const getQueryBar = async () => { + await retry.try(async () => { + await testSubjects.existOrFail('queryInput'); + }); + return await testSubjects.find('queryInput'); + }; + + const clearQueryBar = retryOnStale.wrap(async () => { + return await (await getQueryBar()).clearValueWithKeyboard(); + }); + + const typeInQueryBar = retryOnStale.wrap(async (query: string) => { + return await (await getQueryBar()).type(query); + }); + + const clickOnQueryBar = retryOnStale.wrap(async () => { + return await (await getQueryBar()).click(); + }); + + const submitQuery = async (query: string) => { + await typeInQueryBar(query); + await testSubjects.click('querySubmitButton'); + }; + + // Flyout + const getReasonMessageLinkByIndex = async (index: number) => { + const reasonMessageLinks = await find.allByCssSelector( + '[data-test-subj="o11yGetRenderCellValueLink"]' + ); + return reasonMessageLinks[index] || null; + }; + + const openAlertsFlyout = retryOnStale.wrap(async (index: number = 0) => { + const reasonMessageLink = await getReasonMessageLinkByIndex(index); + await reasonMessageLink.click(); + await retry.waitFor( + 'flyout open', + async () => await testSubjects.exists(ALERTS_FLYOUT_SELECTOR, { timeout: 2500 }) + ); + }); + + const getAlertsFlyout = async () => { + return await testSubjects.find(ALERTS_FLYOUT_SELECTOR); + }; + + const getAlertsFlyoutOrFail = async () => { + return await testSubjects.existOrFail(ALERTS_FLYOUT_SELECTOR); + }; + + const getAlertsFlyoutTitle = async () => { + return await testSubjects.find('alertsFlyoutTitle'); + }; + + const closeAlertsFlyout = async () => { + return await flyoutService.close(ALERTS_FLYOUT_SELECTOR); + }; + + const getAlertsFlyoutViewInAppButtonOrFail = async () => { + return await testSubjects.existOrFail('alertsFlyoutViewInAppButton'); + }; + + const getAlertsFlyoutViewRuleDetailsLinkOrFail = async () => { + return await testSubjects.existOrFail('viewRuleDetailsFlyout'); + }; + + const getAlertsFlyoutDescriptionListTitles = retryOnStale.wrap( + async (): Promise => { + const flyout = await getAlertsFlyout(); + return await testSubjects.findAllDescendant('alertsFlyoutDescriptionListTitle', flyout); + } + ); + + const getAlertsFlyoutDescriptionListDescriptions = retryOnStale.wrap( + async (): Promise => { + const flyout = await getAlertsFlyout(); + return await testSubjects.findAllDescendant('alertsFlyoutDescriptionListDescription', flyout); + } + ); + + // Cell actions + + const filterForValueButtonExists = async () => { + return await testSubjects.exists(FILTER_FOR_VALUE_BUTTON_SELECTOR); + }; + + const getFilterForValueButton = async () => { + return await testSubjects.find(FILTER_FOR_VALUE_BUTTON_SELECTOR); + }; + + const openActionsMenuForRow = retryOnStale.wrap(async (rowIndex: number) => { + const actionsOverflowButton = await getActionsButtonByIndex(rowIndex); + await actionsOverflowButton.click(); + await testSubjects.existOrFail(ALERTS_TABLE_ACTIONS_MENU_SELECTOR); + }); + + const viewRuleDetailsButtonClick = async () => { + await testSubjects.click(VIEW_RULE_DETAILS_SELECTOR); + }; + + const viewRuleDetailsLinkClick = async () => { + await testSubjects.click(VIEW_RULE_DETAILS_FLYOUT_SELECTOR); + }; + + // Workflow status + const setWorkflowStatusForRow = async (rowIndex: number, workflowStatus: WorkflowStatus) => { + await openActionsMenuForRow(rowIndex); + + if (workflowStatus === 'closed') { + await testSubjects.click('close-alert-status'); + } else { + await testSubjects.click(`${workflowStatus}-alert-status`); + } + + // wait for a confirmation toast (the css index is 1-based) + await toasts.getElementByIndex(1); + await toasts.dismissAll(); + }; + + const setWorkflowStatusFilter = retryOnStale.wrap(async (workflowStatus: WorkflowStatus) => { + await testSubjects.click(`workflowStatusFilterButton-${workflowStatus}`); + }); + + const getWorkflowStatusFilterValue = retryOnStale.wrap(async () => { + const selectedWorkflowStatusButton = await find.byClassName('euiButtonGroupButton-isSelected'); + return await selectedWorkflowStatusButton.getVisibleText(); + }); + + // Alert status + const setAlertStatusFilter = async (alertStatus?: AlertStatus) => { + let buttonSubject = 'alert-status-filter-show-all-button'; + if (alertStatus === ALERT_STATUS_ACTIVE) { + buttonSubject = 'alert-status-filter-active-button'; + } + if (alertStatus === ALERT_STATUS_RECOVERED) { + buttonSubject = 'alert-status-filter-recovered-button'; + } + + await testSubjects.click(buttonSubject); + }; + + const selectAlertStatusFilter = async (alertStatus: AlertStatus) => { + await testSubjects.click('optionsList-control-0'); + await testSubjects.click(`optionsList-control-selection-${alertStatus}`); + await testSubjects.click('optionsList-control-0'); + }; + + const alertDataHasLoaded = async () => { + await retry.waitFor( + 'Alert Table is loaded', + async () => await testSubjects.exists('alertsTableIsLoaded', { timeout: 2500 }) + ); + }; + + // Date picker + const getTimeRange = async () => { + const isAbsoluteRange = await testSubjects.exists('superDatePickerstartDatePopoverButton'); + + if (isAbsoluteRange) { + const startText = await testSubjects.getVisibleText('superDatePickerstartDatePopoverButton'); + const endText = await testSubjects.getVisibleText('superDatePickerendDatePopoverButton'); + return `${startText} - ${endText}`; + } + + return await testSubjects.getVisibleText('superDatePickerShowDatesButton'); + }; + + const getActionsButtonByIndex = async (index: number) => { + const actionsOverflowButtons = await find.allByCssSelector( + '[data-test-subj="alertsTableRowActionMore"]' + ); + return actionsOverflowButtons[index] || null; + }; + + const getRuleStatValue = retryOnStale.wrap(async (testSubj: string) => { + const stat = await testSubjects.find(testSubj); + const title = await stat.findByCssSelector('.euiStat__title'); + const count = await title.getVisibleText(); + const value = Number.parseInt(count, 10); + expect(Number.isNaN(value)).to.be(false); + return value; + }); + + // Data view + const createDataView = async ({ + supertest, + id, + name, + title, + logger, + }: { + supertest: SuperTestAgent; + id: string; + name: string; + title: string; + logger: ToolingLog; + }) => { + const { body } = await supertest + .post(`/api/content_management/rpc/create`) + .set('kbn-xsrf', 'foo') + .send({ + contentTypeId: 'index-pattern', + data: { + fieldAttrs: '{}', + title, + timeFieldName: '@timestamp', + sourceFilters: '[]', + fields: '[]', + fieldFormatMap: '{}', + typeMeta: '{}', + runtimeFieldMap: '{}', + name, + }, + options: { id }, + version: 1, + }) + .expect(200); + + logger.debug(`Created data view: ${JSON.stringify(body)}`); + return body; + }; + + const deleteDataView = async ({ + supertest, + id, + logger, + }: { + supertest: SuperTestAgent; + id: string; + logger: ToolingLog; + }) => { + const { body } = await supertest + .post(`/api/content_management/rpc/delete`) + .set('kbn-xsrf', 'foo') + .send({ + contentTypeId: 'index-pattern', + id, + options: { force: true }, + version: 1, + }) + .expect(200); + + logger.debug(`Deleted data view id: ${id}`); + return body; + }; + + return { + getQueryBar, + clearQueryBar, + clickOnQueryBar, + closeAlertsFlyout, + filterForValueButtonExists, + getAlertsFlyout, + getAlertsFlyoutDescriptionListDescriptions, + getAlertsFlyoutDescriptionListTitles, + getAlertsFlyoutOrFail, + getAlertsFlyoutTitle, + getAlertsFlyoutViewInAppButtonOrFail, + getAllDisabledCheckBoxInTable, + getAllEnabledCheckBoxInTable, + getFilterForValueButton, + getNoDataPageOrFail, + getNoDataStateOrFail, + getTableCells, + getTableCellsInRows, + getTableColumnHeaders, + getTableOrFail, + waitForAlertTableToLoad, + ensureNoTableErrorPrompt, + navigateToTimeWithData, + setKibanaTimeZoneToUTC, + openAlertsFlyout, + setWorkflowStatusForRow, + setWorkflowStatusFilter, + getWorkflowStatusFilterValue, + setAlertStatusFilter, + alertDataHasLoaded, + submitQuery, + typeInQueryBar, + openActionsMenuForRow, + getTimeRange, + navigateWithoutFilter, + getActionsButtonByIndex, + viewRuleDetailsButtonClick, + viewRuleDetailsLinkClick, + getAlertsFlyoutViewRuleDetailsLinkOrFail, + getRuleStatValue, + navigateToRulesPage, + navigateToRulesLogsPage, + navigateToRuleDetailsByRuleId, + navigateToAlertDetails, + createDataView, + deleteDataView, + selectAlertStatusFilter, + }; +} diff --git a/x-pack/solutions/observability/test/functional/services/observability/alerts/index.ts b/x-pack/solutions/observability/test/functional/services/observability/alerts/index.ts new file mode 100644 index 0000000000000..a617fdab808a6 --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/observability/alerts/index.ts @@ -0,0 +1,27 @@ +/* + * 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 { ObservabilityAlertsPaginationProvider } from './pagination'; +import { ObservabilityAlertsCommonProvider } from './common'; +import { ObservabilityAlertsAddToCaseProvider } from './add_to_case'; +import { ObservabilityAlertsRulesProvider } from './rules_page'; + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export function ObservabilityAlertsProvider(context: FtrProviderContext) { + const common = ObservabilityAlertsCommonProvider(context); + const pagination = ObservabilityAlertsPaginationProvider(context); + const addToCase = ObservabilityAlertsAddToCaseProvider(context); + const rulesPage = ObservabilityAlertsRulesProvider(context); + + return { + common, + pagination, + addToCase, + rulesPage, + }; +} diff --git a/x-pack/solutions/observability/test/functional/services/observability/alerts/pagination.ts b/x-pack/solutions/observability/test/functional/services/observability/alerts/pagination.ts new file mode 100644 index 0000000000000..91959e95d75af --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/observability/alerts/pagination.ts @@ -0,0 +1,115 @@ +/* + * 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 { FtrProviderContext } from '../../../ftr_provider_context'; + +const ROWS_PER_PAGE_SELECTOR = 'tablePaginationPopoverButton'; +const PREV_BUTTON_SELECTOR = 'pagination-button-previous'; +const NEXT_BUTTON_SELECTOR = 'pagination-button-next'; +const TEN_ROWS_SELECTOR = 'tablePagination-10-rows'; +const TWENTY_ROWS_SELECTOR = 'tablePagination-20-rows'; +const FIFTY_ROWS_SELECTOR = 'tablePagination-50-rows'; +const BUTTON_ONE_SELECTOR = 'pagination-button-0'; +const BUTTON_TWO_SELECTOR = 'pagination-button-1'; + +export function ObservabilityAlertsPaginationProvider({ getService }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + + const getPageSizeSelector = async () => { + return await testSubjects.find(ROWS_PER_PAGE_SELECTOR); + }; + + const getPageSizeSelectorOrFail = async () => { + return await testSubjects.existOrFail(ROWS_PER_PAGE_SELECTOR); + }; + + const missingPageSizeSelectorOrFail = async () => { + return await testSubjects.missingOrFail(ROWS_PER_PAGE_SELECTOR); + }; + + const getTenRowsPageSelector = async () => { + return await testSubjects.find(TEN_ROWS_SELECTOR); + }; + + const getTwentyRowsPageSelector = async () => { + return await testSubjects.find(TWENTY_ROWS_SELECTOR); + }; + + const getFiftyRowsPageSelector = async () => { + return await testSubjects.find(FIFTY_ROWS_SELECTOR); + }; + + const getPrevPageButton = async () => { + return await testSubjects.find(PREV_BUTTON_SELECTOR); + }; + + const getPrevPageButtonOrFail = async () => { + return await testSubjects.existOrFail(PREV_BUTTON_SELECTOR); + }; + + const missingPrevPageButtonOrFail = async () => { + return await testSubjects.missingOrFail(PREV_BUTTON_SELECTOR); + }; + + const getNextPageButton = async () => { + return await testSubjects.find(NEXT_BUTTON_SELECTOR); + }; + + const getNextPageButtonOrFail = async () => { + return await testSubjects.existOrFail(NEXT_BUTTON_SELECTOR); + }; + + const getPaginationButtonOne = async () => { + return await testSubjects.find(BUTTON_ONE_SELECTOR); + }; + + const getPaginationButtonTwo = async () => { + return await testSubjects.find(BUTTON_TWO_SELECTOR); + }; + + const goToNextPage = async () => { + return await (await getNextPageButton()).click(); + }; + + const goToPrevPage = async () => { + return await (await getPrevPageButton()).click(); + }; + + const goToFirstPage = async () => { + await (await getPaginationButtonOne()).click(); + }; + + const goToNthPage = async (page: number) => { + const pageButton = await testSubjects.find(`pagination-button-${page - 1}`); + await pageButton.click(); + }; + + const getPrevButtonDisabledValue = async () => { + return await (await getPrevPageButton()).getAttribute('disabled'); + }; + + return { + getPageSizeSelector, + getPageSizeSelectorOrFail, + missingPageSizeSelectorOrFail, + getTenRowsPageSelector, + getTwentyRowsPageSelector, + getFiftyRowsPageSelector, + getPrevPageButton, + getPrevPageButtonOrFail, + missingPrevPageButtonOrFail, + getNextPageButton, + getNextPageButtonOrFail, + getPaginationButtonOne, + getPaginationButtonTwo, + goToNextPage, + goToPrevPage, + goToFirstPage, + getPrevButtonDisabledValue, + goToNthPage, + }; +} diff --git a/x-pack/solutions/observability/test/functional/services/observability/alerts/rules_page.ts b/x-pack/solutions/observability/test/functional/services/observability/alerts/rules_page.ts new file mode 100644 index 0000000000000..588e64fca0bfb --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/observability/alerts/rules_page.ts @@ -0,0 +1,75 @@ +/* + * 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 { FtrProviderContext } from '../../../ftr_provider_context'; + +const METRIC_THRESHOLD_RULE_TYPE_SELECTOR = 'metrics.alert.threshold-SelectOption'; +const CUSTOM_THRESHOLD_RULE_TYPE_SELECTOR = 'observability.rules.custom_threshold-SelectOption'; + +export function ObservabilityAlertsRulesProvider({ getService }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + const find = getService('find'); + const log = getService('log'); + + const getManageRulesPageHref = async () => { + const manageRulesPageButton = await testSubjects.find('manageRulesPageButton'); + return manageRulesPageButton.getAttribute('href'); + }; + + const clickCreateRuleButton = async () => { + await testSubjects.existOrFail('createRuleButton'); + const createRuleButton = await testSubjects.find('createRuleButton'); + log.debug(`clicking on ${await createRuleButton.getAttribute('innerText')}`); + return await createRuleButton.click(); + }; + + const clickRuleStatusDropDownMenu = async () => testSubjects.click('statusDropdown'); + + const clickDisableFromDropDownMenu = async () => testSubjects.click('statusDropdownDisabledItem'); + + const clickLogsTab = async () => testSubjects.click('ruleLogsTab'); + + const clickOnRuleInEventLogs = async () => { + await find.clickByButtonText('metric-threshold'); + }; + + const clickOnInfrastructureCategory = async () => { + await testSubjects.existOrFail('ruleTypeModal'); + const categories = await testSubjects.find('ruleTypeModal'); + const category = await categories.findByCssSelector(`.euiFacetButton[title="Infrastructure"]`); + await category.click(); + }; + + const clickOnMetricThresholdRule = async () => { + await testSubjects.existOrFail(METRIC_THRESHOLD_RULE_TYPE_SELECTOR); + await testSubjects.click(METRIC_THRESHOLD_RULE_TYPE_SELECTOR); + }; + + const clickOnObservabilityCategory = async () => { + await testSubjects.existOrFail('ruleTypeModal'); + const categories = await testSubjects.find('ruleTypeModal'); + const category = await categories.findByCssSelector(`.euiFacetButton[title="Observability"]`); + await category.click(); + }; + + const clickOnCustomThresholdRule = async () => { + await testSubjects.existOrFail(CUSTOM_THRESHOLD_RULE_TYPE_SELECTOR); + await testSubjects.click(CUSTOM_THRESHOLD_RULE_TYPE_SELECTOR); + }; + + return { + getManageRulesPageHref, + clickCreateRuleButton, + clickRuleStatusDropDownMenu, + clickDisableFromDropDownMenu, + clickLogsTab, + clickOnRuleInEventLogs, + clickOnInfrastructureCategory, + clickOnMetricThresholdRule, + clickOnObservabilityCategory, + clickOnCustomThresholdRule, + }; +} diff --git a/x-pack/solutions/observability/test/functional/services/observability/components/alert_search_bar.ts b/x-pack/solutions/observability/test/functional/services/observability/components/alert_search_bar.ts new file mode 100644 index 0000000000000..12781afb67b4f --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/observability/components/alert_search_bar.ts @@ -0,0 +1,38 @@ +/* + * 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 dateMath from '@kbn/datemath'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +const FROM_SELECTOR = 'superDatePickerstartDatePopoverButton'; +const TO_SELECTOR = 'superDatePickerendDatePopoverButton'; + +export function ObservabilityAlertSearchBarProvider({ getService }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + + const getAbsoluteTimeRange = async () => { + // Since FTR uses UTC, with this format, we remove local browser timezone + const format = 'YYYY-MM-DDTHH:mm:ss.SSS'; + + const fromMoment = dateMath.parse( + await (await testSubjects.find(FROM_SELECTOR)).getVisibleText() + ); + const from = fromMoment!.format(format); + + const toMoment = dateMath.parse(await (await testSubjects.find(TO_SELECTOR)).getVisibleText()); + const to = toMoment!.format(format); + + return { + from, + to, + }; + }; + + return { + getAbsoluteTimeRange, + }; +} diff --git a/x-pack/solutions/observability/test/functional/services/observability/components/alert_summary_widget.ts b/x-pack/solutions/observability/test/functional/services/observability/components/alert_summary_widget.ts new file mode 100644 index 0000000000000..f689f973d57aa --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/observability/components/alert_summary_widget.ts @@ -0,0 +1,63 @@ +/* + * 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 { FtrProviderContext } from '../../../ftr_provider_context'; + +const COMPACT_COMPONENT_SELECTOR = 'alertSummaryWidgetCompact'; +const COMPACT_TIME_RANGE_TITLE_SELECTOR = 'timeRangeTitle'; + +const FULL_SIZE_COMPONENT_SELECTOR = 'alertSummaryWidgetFullSize'; + +const ACTIVE_ALERT_SELECTOR = 'activeAlertCount'; +const TOTAL_ALERT_SELECTOR = 'totalAlertCount'; + +export function ObservabilityAlertSummaryWidgetProvider({ getService }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + + const getCompactComponentSelectorOrFail = async () => { + return await testSubjects.existOrFail(COMPACT_COMPONENT_SELECTOR); + }; + + const getFullSizeComponentSelectorOrFail = async () => { + return await testSubjects.existOrFail(FULL_SIZE_COMPONENT_SELECTOR); + }; + + const getCompactTimeRangeTitle = async () => { + return (await testSubjects.find(COMPACT_TIME_RANGE_TITLE_SELECTOR)).getVisibleText(); + }; + + const getCompactWidgetSelector = async () => { + return await testSubjects.find(COMPACT_COMPONENT_SELECTOR); + }; + + const getActiveAlertSelector = async () => { + return await testSubjects.find(ACTIVE_ALERT_SELECTOR); + }; + + const getTotalAlertSelector = async () => { + return await testSubjects.find(TOTAL_ALERT_SELECTOR); + }; + + const getActiveAlertCount = async () => { + return (await getActiveAlertSelector()).getVisibleText(); + }; + + const getTotalAlertCount = async () => { + return (await getTotalAlertSelector()).getVisibleText(); + }; + + return { + getCompactComponentSelectorOrFail, + getCompactWidgetSelector, + getCompactTimeRangeTitle, + getFullSizeComponentSelectorOrFail, + getTotalAlertSelector, + getActiveAlertSelector, + getTotalAlertCount, + getActiveAlertCount, + }; +} diff --git a/x-pack/solutions/observability/test/functional/services/observability/components/index.ts b/x-pack/solutions/observability/test/functional/services/observability/components/index.ts new file mode 100644 index 0000000000000..0a11968a0cb56 --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/observability/components/index.ts @@ -0,0 +1,21 @@ +/* + * 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 { ObservabilityAlertSearchBarProvider } from './alert_search_bar'; +import { ObservabilityAlertSummaryWidgetProvider } from './alert_summary_widget'; + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export function ObservabilityComponentsProvider(context: FtrProviderContext) { + const alertSearchBar = ObservabilityAlertSearchBarProvider(context); + const alertSummaryWidget = ObservabilityAlertSummaryWidgetProvider(context); + + return { + alertSearchBar, + alertSummaryWidget, + }; +} diff --git a/x-pack/solutions/observability/test/functional/services/observability/index.ts b/x-pack/solutions/observability/test/functional/services/observability/index.ts new file mode 100644 index 0000000000000..db262cef8bf63 --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/observability/index.ts @@ -0,0 +1,26 @@ +/* + * 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 { FtrProviderContext } from '../../ftr_provider_context'; +import { ObservabilityUsersProvider } from './users'; +import { ObservabilityAlertsProvider } from './alerts'; +import { ObservabilityOverviewProvider } from './overview'; +import { ObservabilityComponentsProvider } from './components'; + +export function ObservabilityProvider(context: FtrProviderContext) { + const alerts = ObservabilityAlertsProvider(context); + const components = ObservabilityComponentsProvider(context); + const users = ObservabilityUsersProvider(context); + const overview = ObservabilityOverviewProvider(context); + + return { + alerts, + components, + users, + overview, + }; +} diff --git a/x-pack/solutions/observability/test/functional/services/observability/overview/common.ts b/x-pack/solutions/observability/test/functional/services/observability/overview/common.ts new file mode 100644 index 0000000000000..0d4585e18af82 --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/observability/overview/common.ts @@ -0,0 +1,102 @@ +/* + * 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 { FtrProviderContext } from '../../../ftr_provider_context'; + +// Based on the x-pack/test/functional/es_archives/observability/alerts archive. +const DATE_WITH_DATA = { + rangeFrom: '2021-10-18T13:36:22.109Z', + rangeTo: '2021-10-20T13:36:22.109Z', +}; + +const DATE_WITHOUT_DATA = { + rangeFrom: '2021-09-18T13:36:22.109Z', + rangeTo: '2021-09-20T13:36:22.109Z', +}; + +const ALERTS_TITLE = 'Alerts'; +const ALERTS_ACCORDION_SELECTOR = `accordion-${ALERTS_TITLE}`; +const ALERTS_SECTION_BUTTON_CSS_SELECTOR = `[data-test-subj=${ALERTS_ACCORDION_SELECTOR}] button.euiAccordion__button`; +const ALERTS_TABLE_NO_DATA_SELECTOR = 'alertsTableEmptyState'; +const ALERTS_TABLE_WITH_DATA_SELECTOR = 'alertsTableIsLoaded'; +const ALERTS_TABLE_LOADING_SELECTOR = 'internalAlertsPageLoading'; + +export function ObservabilityOverviewCommonProvider({ + getPageObjects, + getService, +}: FtrProviderContext) { + const find = getService('find'); + const pageObjects = getPageObjects(['common', 'header']); + const testSubjects = getService('testSubjects'); + const retry = getService('retry'); + + const navigateToOverviewPageWithAlerts = async () => { + return await pageObjects.common.navigateToUrlWithBrowserHistory( + 'observability', + '/overview', + `?rangeFrom=${DATE_WITH_DATA.rangeFrom}&rangeTo=${DATE_WITH_DATA.rangeTo}`, + { ensureCurrentUrl: false } + ); + }; + + const navigateToOverviewPageWithoutAlerts = async () => { + return await pageObjects.common.navigateToUrlWithBrowserHistory( + 'observability', + '/overview', + `?rangeFrom=${DATE_WITHOUT_DATA.rangeFrom}&rangeTo=${DATE_WITHOUT_DATA.rangeTo}`, + { ensureCurrentUrl: false } + ); + }; + + const navigateToOverviewPage = async () => { + await pageObjects.common.navigateToUrlWithBrowserHistory( + 'observability', + '/overview', + undefined, + { ensureCurrentUrl: false } + ); + await pageObjects.header.waitUntilLoadingHasFinished(); + }; + + const waitForAlertsAccordionToAppear = async () => { + await retry.waitFor('alert accordion to appear', async () => { + return await testSubjects.exists(ALERTS_ACCORDION_SELECTOR); + }); + }; + + const waitForAlertsTableLoadingToDisappear = async () => { + await testSubjects.missingOrFail(ALERTS_TABLE_LOADING_SELECTOR, { timeout: 30_000 }); + }; + + const openAlertsSection = async () => { + await waitForAlertsAccordionToAppear(); + await find.clickByCssSelector(ALERTS_SECTION_BUTTON_CSS_SELECTOR); + }; + + const openAlertsSectionAndWaitToAppear = async () => { + await openAlertsSection(); + await waitForAlertsTableLoadingToDisappear(); + await retry.waitFor('alerts table to appear', async () => { + return ( + (await testSubjects.exists(ALERTS_TABLE_NO_DATA_SELECTOR)) || + (await testSubjects.exists(ALERTS_TABLE_WITH_DATA_SELECTOR)) + ); + }); + }; + + const getAlertsTableNoDataOrFail = async () => { + return await testSubjects.existOrFail(ALERTS_TABLE_NO_DATA_SELECTOR); + }; + + return { + getAlertsTableNoDataOrFail, + navigateToOverviewPageWithAlerts, + navigateToOverviewPageWithoutAlerts, + navigateToOverviewPage, + openAlertsSectionAndWaitToAppear, + }; +} diff --git a/x-pack/solutions/observability/test/functional/services/observability/overview/index.ts b/x-pack/solutions/observability/test/functional/services/observability/overview/index.ts new file mode 100644 index 0000000000000..5c34d4afce99e --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/observability/overview/index.ts @@ -0,0 +1,18 @@ +/* + * 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 { ObservabilityOverviewCommonProvider } from './common'; + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export function ObservabilityOverviewProvider(context: FtrProviderContext) { + const common = ObservabilityOverviewCommonProvider(context); + + return { + common, + }; +} diff --git a/x-pack/solutions/observability/test/functional/services/observability/users.ts b/x-pack/solutions/observability/test/functional/services/observability/users.ts new file mode 100644 index 0000000000000..68de5f2ad03fb --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/observability/users.ts @@ -0,0 +1,107 @@ +/* + * 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 { Role } from '@kbn/security-plugin/common'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +type CreateRolePayload = Pick; + +const OBSERVABILITY_TEST_ROLE_NAME = 'observability-functional-test-role'; +const HOME_PAGE_SELECTOR = 'homeApp'; + +export function ObservabilityUsersProvider({ getPageObject, getService }: FtrProviderContext) { + const security = getService('security'); + const testSubjects = getService('testSubjects'); + const commonPageObject = getPageObject('common'); + + /** + * Creates a test role and set it as the test user's role. Performs a page + * reload to apply the role change, but doesn't require a re-login. + * + * @arg roleDefinition - the privileges of the test role + */ + const setTestUserRole = async (roleDefinition: CreateRolePayload) => { + // return to neutral grounds to avoid running into permission problems on reload + await commonPageObject.navigateToActualUrl('home'); + await testSubjects.existOrFail(HOME_PAGE_SELECTOR); + + await security.role.create(OBSERVABILITY_TEST_ROLE_NAME, roleDefinition); + + await security.testUser.setRoles([OBSERVABILITY_TEST_ROLE_NAME]); // performs a page reload + }; + + /** + * Deletes the test role and restores thedefault test user role. Performs a + * page reload to apply the role change, but doesn't require a re-login. + */ + const restoreDefaultTestUserRole = async () => { + await Promise.all([ + security.role.delete(OBSERVABILITY_TEST_ROLE_NAME), + security.testUser.restoreDefaults(), + ]); + }; + + return { + defineBasicObservabilityRole, + restoreDefaultTestUserRole, + setTestUserRole, + }; +} + +/** + * Generates a combination of Elasticsearch and Kibana privileges for given + * observability features. + */ +const defineBasicObservabilityRole = ( + features: Partial<{ + observabilityCasesV3: string[]; + apm: string[]; + logs: string[]; + infrastructure: string[]; + uptime: string[]; + }> +): CreateRolePayload => { + return { + elasticsearch: { + cluster: ['all'], + indices: [ + ...((features.logs?.length ?? 0) > 0 + ? [{ names: ['filebeat-*', 'logs-*'], privileges: ['all'] }] + : []), + ...((features.infrastructure?.length ?? 0) > 0 + ? [{ names: ['metricbeat-*', 'metrics-*'], privileges: ['all'] }] + : []), + ...((features.apm?.length ?? 0) > 0 + ? [ + { + names: [ + 'apm-*', + 'logs-apm*', + 'metrics-apm*', + 'traces-apm*', + 'observability-annotations', + ], + privileges: ['read', 'view_index_metadata'], + }, + ] + : []), + ...((features.uptime?.length ?? 0) > 0 + ? [{ names: ['heartbeat-*,synthetics-*'], privileges: ['all'] }] + : []), + ], + run_as: [], + }, + kibana: [ + { + spaces: ['*'], + base: [], + // undefined props yet + feature: features, + }, + ], + }; +}; diff --git a/x-pack/solutions/observability/test/functional/services/slo/common.ts b/x-pack/solutions/observability/test/functional/services/slo/common.ts new file mode 100644 index 0000000000000..a4986581c0df4 --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/slo/common.ts @@ -0,0 +1,140 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; +import { sloData } from './fixtures/create_slo'; + +const OVERVIEW_MODE_SELECTOR = 'sloOverviewModeSelector'; +const SLO_CONFIRM_BUTTON = 'sloConfirmButton'; +const SINGLE_SLO_SELECTOR = 'singleSloSelector'; +const SLO_SINGLE_OVERVIEW_CONFIGURATION = 'sloSingleOverviewConfiguration'; +const SLO_GROUP_OVERVIEW_CONFIGURATION = 'sloGroupOverviewConfiguration'; +const SLO_GROUP_OVERVIEW_CONFIGURATION_GROUP_BY = 'sloGroupOverviewConfigurationGroupBy'; +const SLO_GROUP_OVERVIEW_CONFIGURATION_GROUP = 'sloGroupOverviewConfigurationGroup'; +const SLO_GROUP_OVERVIEW_CONFIGURATION_KQLBAR = 'sloGroupOverviewConfigurationKqlBar'; +const SLO_SINGLE_OVERVIEW_PANEL = 'sloSingleOverviewPanel'; +const SLO_GROUP_OVERVIEW_PANEL = 'sloGroupOverviewPanel'; + +export function SloUiCommonServiceProvider({ getService }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + const comboBox = getService('comboBox'); + const find = getService('find'); + const toasts = getService('toasts'); + const retry = getService('retry'); + + return { + async assertSloOverviewConfigurationExists() { + await retry.tryForTime(60 * 1000, async () => { + await testSubjects.existOrFail(SLO_SINGLE_OVERVIEW_CONFIGURATION); + }); + }, + async assertOverviewSloSelectorExists() { + await retry.tryForTime(60 * 1000, async () => { + await testSubjects.existOrFail(SINGLE_SLO_SELECTOR); + }); + }, + async setComboBoxSloSelection() { + await retry.tryForTime(60 * 1000, async () => { + await testSubjects.click('sloSelector'); + await comboBox.set('sloSelector > comboBoxInput', sloData.name); + }); + }, + async assertOverviewConfigurationSaveButtonIsEnabled(subj: string) { + await retry.tryForTime(60 * 1000, async () => { + await testSubjects.existOrFail(subj); + await testSubjects.isEnabled(subj); + }); + }, + async clickOverviewCofigurationSaveButton() { + await retry.tryForTime(60 * 1000, async () => { + await this.assertOverviewConfigurationSaveButtonIsEnabled(SLO_CONFIRM_BUTTON); + await testSubjects.clickWhenNotDisabledWithoutRetry(SLO_CONFIRM_BUTTON); + }); + }, + + async assertOverviewModeSelectorExists() { + await retry.tryForTime(60 * 1000, async () => { + await testSubjects.existOrFail(OVERVIEW_MODE_SELECTOR); + }); + }, + + async clickOverviewMode() { + await retry.tryForTime(60 * 1000, async () => { + await this.assertOverviewModeSelectorExists(); + const wrapper = await testSubjects.find(OVERVIEW_MODE_SELECTOR); + const button = await testSubjects.findDescendant('groups', wrapper); + await button.click(); + }); + }, + + async assertSloConfigurationGroupOverviewModeIsSelected() { + await retry.tryForTime(60 * 1000, async () => { + await testSubjects.existOrFail(SLO_GROUP_OVERVIEW_CONFIGURATION); + }); + }, + + async assertGroupOverviewConfigurationGroupByExists() { + await retry.tryForTime(60 * 1000, async () => { + await testSubjects.existOrFail(SLO_GROUP_OVERVIEW_CONFIGURATION_GROUP_BY); + }); + }, + + async assertGroupOverviewConfigurationGroupExists() { + await retry.tryForTime(60 * 1000, async () => { + await testSubjects.existOrFail(SLO_GROUP_OVERVIEW_CONFIGURATION_GROUP); + }); + }, + + async assertGroupOverviewConfigurationKqlBarExists() { + await retry.tryForTime(60 * 1000, async () => { + await testSubjects.existOrFail(SLO_GROUP_OVERVIEW_CONFIGURATION_KQLBAR); + }); + }, + + async dismissAllToasts() { + await retry.tryForTime(60 * 1000, async () => { + await toasts.dismissAll(); + }); + }, + + async assertSingleOverviewPanelExists() { + await retry.tryForTime(60 * 1000, async () => { + await testSubjects.existOrFail(SLO_SINGLE_OVERVIEW_PANEL); + }); + }, + + async getSloCardTitle() { + const container = await testSubjects.find(SLO_SINGLE_OVERVIEW_PANEL); + return await (await container.findByClassName('echMetricText__title')).getVisibleText(); + }, + + async assertSingleOverviewPanelContentExists() { + await retry.tryForTime(2000, async () => { + expect( + await find.existsByCssSelector( + `[data-test-subj="${SLO_SINGLE_OVERVIEW_PANEL}"] .echChart` + ) + ).to.eql(true); + + expect( + await find.existsByCssSelector( + `[data-test-subj="${SLO_SINGLE_OVERVIEW_PANEL}"] .echMetricText__title` + ) + ).to.eql(true); + + expect(await this.getSloCardTitle()).to.eql(sloData.name); + }); + }, + + async assertGroupOverviewPanelExists() { + await retry.tryForTime(60 * 1000, async () => { + await testSubjects.existOrFail(SLO_GROUP_OVERVIEW_PANEL); + }); + }, + }; +} diff --git a/x-pack/test/api_integration/apis/slos/fixtures/create_slo.ts b/x-pack/solutions/observability/test/functional/services/slo/fixtures/create_slo.ts similarity index 100% rename from x-pack/test/api_integration/apis/slos/fixtures/create_slo.ts rename to x-pack/solutions/observability/test/functional/services/slo/fixtures/create_slo.ts diff --git a/x-pack/test/api_integration/apis/slos/helper/load_test_data.ts b/x-pack/solutions/observability/test/functional/services/slo/helper/load_test_data.ts similarity index 100% rename from x-pack/test/api_integration/apis/slos/helper/load_test_data.ts rename to x-pack/solutions/observability/test/functional/services/slo/helper/load_test_data.ts diff --git a/x-pack/test/api_integration/apis/slos/helper/wait_for_index_state.ts b/x-pack/solutions/observability/test/functional/services/slo/helper/wait_for_index_state.ts similarity index 100% rename from x-pack/test/api_integration/apis/slos/helper/wait_for_index_state.ts rename to x-pack/solutions/observability/test/functional/services/slo/helper/wait_for_index_state.ts diff --git a/x-pack/solutions/observability/test/functional/services/slo/index.ts b/x-pack/solutions/observability/test/functional/services/slo/index.ts new file mode 100644 index 0000000000000..75339f41dfe3a --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/slo/index.ts @@ -0,0 +1,15 @@ +/* + * 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 { FtrProviderContext } from '../../ftr_provider_context'; +import { SloUiCommonServiceProvider } from './common'; + +export function SloUiServiceProvider(context: FtrProviderContext) { + return { + common: SloUiCommonServiceProvider(context), + }; +} diff --git a/x-pack/solutions/observability/test/functional/services/uptime/alerts.ts b/x-pack/solutions/observability/test/functional/services/uptime/alerts.ts new file mode 100644 index 0000000000000..35fed9796d250 --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/uptime/alerts.ts @@ -0,0 +1,123 @@ +/* + * 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 { FtrProviderContext } from '../../ftr_provider_context'; + +export function UptimeAlertsProvider({ getService }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + const browser = getService('browser'); + + return { + async openFlyout(alertType: 'monitorStatus' | 'tls') { + await testSubjects.click('xpack.synthetics.alertsPopover.toggleButton'); + await testSubjects.click('xpack.synthetics.openAlertContextPanel'); + if (alertType === 'monitorStatus') { + await testSubjects.click('xpack.synthetics.toggleAlertFlyout'); + } else if (alertType === 'tls') { + await testSubjects.click('xpack.synthetics.toggleTlsAlertFlyout'); + } + // ensure the flyout has opened + await testSubjects.exists('ruleFlyoutTitle'); + }, + async openMonitorStatusAlertType(alertType: string) { + await testSubjects.click(`xpack.synthetics.alerts.${alertType}-SelectOption`); + }, + async setAlertTags(tags: string[]) { + await testSubjects.click('ruleFormStep-details'); + for (let i = 0; i < tags.length; i += 1) { + await testSubjects.click('comboBoxSearchInput'); + await testSubjects.setValue('comboBoxInput', tags[i]); + await browser.pressKeys(browser.keys.ENTER); + } + }, + async setAlertName(name: string) { + await testSubjects.click('ruleFormStep-details'); + await testSubjects.setValue('ruleDetailsNameInput', name); + }, + async setAlertInterval(value: string) { + await testSubjects.click('ruleFormStep-definition'); + await testSubjects.setValue('ruleScheduleNumberInput', value); + }, + async setAlertThrottleInterval(value: string) { + await testSubjects.click('notifyWhenSelect'); + await testSubjects.click('onThrottleInterval'); + await testSubjects.setValue('throttleInput', value); + }, + async setAlertExpressionValue( + expressionAttribute: string, + fieldAttribute: string, + value: string + ) { + await testSubjects.click(expressionAttribute); + await testSubjects.setValue(fieldAttribute, value); + await testSubjects.click(expressionAttribute); + }, + async setAlertStatusNumTimes(value: string) { + await this.setAlertExpressionValue( + 'xpack.synthetics.alerts.monitorStatus.numTimesExpression', + 'xpack.synthetics.alerts.monitorStatus.numTimesField', + value + ); + }, + async setAlertTimerangeSelection(value: string) { + await this.setAlertExpressionValue( + 'xpack.synthetics.alerts.monitorStatus.timerangeValueExpression', + 'xpack.synthetics.alerts.monitorStatus.timerangeValueField', + value + ); + }, + async setAlertExpressionSelectable( + expressionAttribute: string, + selectableAttribute: string, + optionAttributes: string[] + ) { + await testSubjects.click(expressionAttribute); + await testSubjects.click(selectableAttribute); + for (let i = 0; i < optionAttributes.length; i += 1) { + await testSubjects.click(optionAttributes[i]); + } + await testSubjects.click(expressionAttribute); + }, + async setMonitorStatusSelectableToHours() { + await this.setAlertExpressionSelectable( + 'xpack.synthetics.alerts.monitorStatus.timerangeUnitExpression', + 'xpack.synthetics.alerts.monitorStatus.timerangeUnitSelectable', + ['xpack.synthetics.alerts.monitorStatus.timerangeUnitSelectable.hoursOption'] + ); + }, + async clickAddFilter() { + await testSubjects.click('uptimeCreateAlertAddFilter'); + }, + async clickAddFilterLocation() { + await this.clickAddFilter(); + await testSubjects.click('uptimeAlertAddFilter.observer.geo.name'); + await testSubjects.click('uptimeCreateStatusAlert.filter_location'); + }, + async clickAddFilterPort() { + await this.clickAddFilter(); + await testSubjects.click('uptimeAlertAddFilter.url.port'); + await testSubjects.click('uptimeCreateStatusAlert.filter_port'); + }, + async clickAddFilterType() { + await this.clickAddFilter(); + await testSubjects.click('uptimeAlertAddFilter.monitor.type'); + await testSubjects.click('uptimeCreateStatusAlert.filter_scheme'); + }, + async clickSaveRuleButton(name: string) { + /* The most common cause of flakiness in this test is the absence of value for the name field, + * While this field is set in previous step, it is possible that component rerendering could be + * clearing out the value after it's filled in. To prevent this particular issue with flakiness, + * we should attempt to set the name again before saving the alert */ + await testSubjects.click('ruleFormStep-details'); + await testSubjects.setValue('ruleDetailsNameInput', name); + await testSubjects.click('ruleFlyoutFooterSaveButton'); + }, + async clickSaveAlertsConfirmButton() { + await testSubjects.click('confirmModalConfirmButton', 20000); + }, + }; +} diff --git a/x-pack/solutions/observability/test/functional/services/uptime/certificates.ts b/x-pack/solutions/observability/test/functional/services/uptime/certificates.ts new file mode 100644 index 0000000000000..830423109509b --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/uptime/certificates.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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export function UptimeCertProvider({ getService, getPageObjects }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + const retry = getService('retry'); + const find = getService('find'); + + const PageObjects = getPageObjects(['common', 'timePicker', 'header']); + + const changeSearchField = async (text: string) => { + const input = await testSubjects.find('uptimeCertSearch'); + await input.clearValueWithKeyboard(); + await input.type(text); + }; + + const refreshApp = async () => { + await testSubjects.click('superDatePickerApplyTimeButton', 10000); + }; + + return { + async hasViewCertButton() { + return retry.tryForTime(15000, async () => { + await find.existsByCssSelector('[href="/app/uptime/certificates"]'); + }); + }, + async certificateExists(cert: { certId: string; monitorId: string }) { + return retry.tryForTime(60 * 1000, async () => { + if (!(await testSubjects.exists(cert.certId))) { + await refreshApp(); + } + await testSubjects.existOrFail(cert.certId); + await testSubjects.existOrFail('monitor-page-link-' + cert.monitorId); + }); + }, + async hasCertificates(expectedTotal?: number) { + return retry.tryForTime(60 * 1000, async () => { + const totalCerts = await testSubjects.getVisibleText('uptimeCertTotal'); + if (expectedTotal) { + expect(Number(totalCerts)).to.eql(expectedTotal); + } else { + if (Number(totalCerts) < 1) { + await refreshApp(); + } + expect(Number(totalCerts) > 0).to.eql(true); + } + }); + }, + async searchIsWorking(monId: string) { + const self = this; + return retry.tryForTime(60 * 1000, async () => { + await changeSearchField(monId); + await PageObjects.header.waitUntilLoadingHasFinished(); + await self.hasCertificates(1); + }); + }, + async displaysEmptyMessage() { + await testSubjects.existOrFail('uptimeCertsEmptyMessage'); + const emptyText = await testSubjects.getVisibleText('uptimeCertsEmptyMessage'); + expect(emptyText).to.eql('No Certificates found.'); + }, + }; +} diff --git a/x-pack/solutions/observability/test/functional/services/uptime/common.ts b/x-pack/solutions/observability/test/functional/services/uptime/common.ts new file mode 100644 index 0000000000000..d78aea22f8167 --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/uptime/common.ts @@ -0,0 +1,122 @@ +/* + * 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 { FtrProviderContext } from '../../ftr_provider_context'; + +export function UptimeCommonProvider({ getService, getPageObjects }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + const browser = getService('browser'); + const retry = getService('retry'); + const find = getService('find'); + + const { header } = getPageObjects(['header']); + + return { + async assertExists(key: string) { + if (!(await testSubjects.exists(key))) { + throw new Error(`Couldn't find expected element with key "${key}".`); + } + }, + async monitorIdExists(key: string) { + await retry.tryForTime(10000, async () => { + await testSubjects.existOrFail(key); + }); + }, + async monitorPageLinkExists(monitorId: string) { + await testSubjects.existOrFail(`monitor-page-link-${monitorId}`); + }, + async urlContains(expected: string) { + const url = await browser.getCurrentUrl(); + return url.indexOf(expected) >= 0; + }, + async pageHasDataMissing() { + return await testSubjects.find('data-missing', 5000); + }, + async setKueryBarText(attribute: string, value: string) { + await testSubjects.click(attribute); + await testSubjects.setValue(attribute, value); + await browser.pressKeys(browser.keys.ENTER); + }, + async setFilterText(filterQuery: string) { + await this.setKueryBarText('queryInput', filterQuery); + }, + async goToNextPage() { + await testSubjects.click('xpack.uptime.monitorList.nextButton', 5000); + }, + async goToPreviousPage() { + await testSubjects.click('xpack.synthetics.monitorList.prevButton', 5000); + }, + async setStatusFilterUp() { + await testSubjects.click('xpack.synthetics.filterBar.filterStatusUp'); + }, + async setStatusFilterDown() { + await testSubjects.click('xpack.synthetics.filterBar.filterStatusDown'); + }, + async resetStatusFilter() { + const upFilter = await find.byCssSelector( + '[data-test-subj="xpack.synthetics.filterBar.filterStatusUp"]' + ); + if (await upFilter.elementHasClass('euiFilterButton-hasActiveFilters')) { + await this.setStatusFilterUp(); + } + const downFilter = await find.byCssSelector( + '[data-test-subj="xpack.synthetics.filterBar.filterStatusDown"]' + ); + if (await downFilter.elementHasClass('euiFilterButton-hasActiveFilters')) { + await this.setStatusFilterDown(); + } + }, + async selectFilterItem(filterType: string, itemArg: string | string[]) { + const itemList = Array.isArray(itemArg) ? itemArg : [itemArg]; + const filterPopoverButton = await find.byCssSelector( + `[aria-label="expands filter group for ${filterType} filter"]` + ); + await filterPopoverButton.click(); + await this.clickFilterItems(itemList); + return this.applyFilterItems(filterType); + }, + async clickFilterItems(itemList: string[]) { + for (const title of itemList) { + await find.clickByCssSelector(`li[title="${title}"]`); + } + }, + async applyFilterItems(filterType: string) { + const applyButton = await find.byCssSelector( + `[aria-label="Apply the selected filters for ${filterType}"]` + ); + await applyButton.click(); + }, + async getSnapshotCount() { + return { + up: await testSubjects.getVisibleText('xpack.synthetics.snapshot.donutChart.up'), + down: await testSubjects.getVisibleText('xpack.synthetics.snapshot.donutChart.down'), + }; + }, + async openPageSizeSelectPopover(): Promise { + return testSubjects.click('xpack.uptime.monitorList.pageSizeSelect.popoverOpen', 5000); + }, + async clickPageSizeSelectPopoverItem(size: number = 10): Promise { + return testSubjects.click( + `xpack.uptime.monitorList.pageSizeSelect.sizeSelectItem${size.toString()}`, + 5000 + ); + }, + async waitUntilDataIsLoaded() { + await header.waitUntilLoadingHasFinished(); + return retry.tryForTime(60 * 1000, async () => { + if (await testSubjects.exists('data-missing')) { + await browser.refresh(); + await header.waitUntilLoadingHasFinished(); + } + await testSubjects.missingOrFail('data-missing'); + }); + }, + async hasMappingsError() { + return testSubjects.exists('xpack.synthetics.mappingsErrorPage'); + }, + }; +} diff --git a/x-pack/solutions/observability/test/functional/services/uptime/index.ts b/x-pack/solutions/observability/test/functional/services/uptime/index.ts new file mode 100644 index 0000000000000..649408c03284d --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/uptime/index.ts @@ -0,0 +1,8 @@ +/* + * 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. + */ + +export { UptimeProvider } from './uptime'; diff --git a/x-pack/solutions/observability/test/functional/services/uptime/ml_anomaly.ts b/x-pack/solutions/observability/test/functional/services/uptime/ml_anomaly.ts new file mode 100644 index 0000000000000..9825245591c9e --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/uptime/ml_anomaly.ts @@ -0,0 +1,82 @@ +/* + * 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 { FtrProviderContext } from '../../ftr_provider_context'; + +export function UptimeMLAnomalyProvider({ getService }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + const retry = getService('retry'); + const log = getService('log'); + + return { + async openMLFlyout() { + return retry.tryForTime(15000, async () => { + await testSubjects.click('uptimeEnableAnomalyBtn'); + await testSubjects.existOrFail('uptimeMLFlyout'); + }); + }, + + async openMLManageMenu() { + await this.cancelAlertFlyout(); + return retry.tryForTime(30000, async () => { + await testSubjects.click('uptimeManageMLJobBtn'); + await testSubjects.existOrFail('uptimeManageMLContextMenu'); + }); + }, + + async cancelAlertFlyout() { + if (await testSubjects.exists('euiFlyoutCloseButton')) + await testSubjects.click('euiFlyoutCloseButton', 60 * 1000); + if (await testSubjects.exists('ruleFlyoutConfirmCancelConfirmButton')) + await testSubjects.click('ruleFlyoutConfirmCancelConfirmButton', 60 * 1000); + }, + + async alreadyHasJob() { + return await testSubjects.exists('uptimeManageMLJobBtn'); + }, + + async createMLJob() { + await testSubjects.click('uptimeMLCreateJobBtn'); + return retry.tryForTime(30000, async () => { + await testSubjects.existOrFail('uptimeMLJobSuccessfullyCreated'); + log.info('Job successfully created'); + }); + }, + + async deleteMLJob() { + await testSubjects.click('uptimeDeleteMLJobBtn'); + return retry.tryForTime(10000, async () => { + await testSubjects.click('uptimeMLJobDeleteConfirmModel > confirmModalConfirmButton'); + await testSubjects.existOrFail('uptimeMLJobSuccessfullyDeleted'); + log.info('Job successfully deleted'); + }); + }, + + async canCreateJob() { + const createJobBtn = await testSubjects.find('uptimeMLCreateJobBtn'); + return !!(await createJobBtn.getAttribute('disabled')); + }, + + async hasNoLicenseInfo() { + return await testSubjects.missingOrFail('uptimeMLLicenseInfo', { timeout: 1000 }); + }, + + async openAlertFlyout() { + return await testSubjects.click('uptimeEnableAnomalyAlertBtn'); + }, + + async manageAnomalyAlertIsVisible() { + return await testSubjects.exists('uptimeManageAnomalyAlertBtn'); + }, + + async changeAlertThreshold(level: string) { + await testSubjects.click('uptimeAnomalySeverity'); + await testSubjects.click('anomalySeveritySelect'); + await testSubjects.click(`alertAnomaly${level}`); + }, + }; +} diff --git a/x-pack/solutions/observability/test/functional/services/uptime/monitor.ts b/x-pack/solutions/observability/test/functional/services/uptime/monitor.ts new file mode 100644 index 0000000000000..529cbf6eac2da --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/uptime/monitor.ts @@ -0,0 +1,68 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export function UptimeMonitorProvider({ getService, getPageObjects }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + const retry = getService('retry'); + + const PageObjects = getPageObjects(['header']); + + return { + async displayOverallAvailability(availabilityVal: string) { + return retry.tryForTime(60 * 1000, async () => { + await testSubjects.existOrFail('uptimeOverallAvailability'); + const availability = await testSubjects.getVisibleText('uptimeOverallAvailability'); + expect(availability).to.be(availabilityVal); + }); + }, + async setPingListLocation(location: string) { + await testSubjects.click('xpack.synthetics.pingList.locationSelect', 5000); + return testSubjects.click(`xpack.synthetics.pingList.locationOptions.${location}`, 5000); + }, + async setPingListStatus(status: string) { + await testSubjects.click('xpack.synthetics.pingList.statusSelect', 5000); + return testSubjects.click(`xpack.synthetics.pingList.statusOptions.${status}`, 5000); + }, + async checkForPingListTimestamps(timestamps: string[]): Promise { + return retry.tryForTime(10000, async () => { + await Promise.all( + timestamps.map( + async (timestamp) => + await testSubjects.existOrFail(`xpack.synthetics.pingList.ping-${timestamp}`) + ) + ); + }); + }, + async hasRedirectInfo() { + return retry.tryForTime(30000, async () => { + await testSubjects.existOrFail('uptimeMonitorRedirectInfo'); + }); + }, + async expandPingRow() { + return retry.tryForTime( + 60 * 3000, + async () => { + await testSubjects.existOrFail('uptimePingListExpandBtn', { timeout: 5000 }); + await testSubjects.click('uptimePingListExpandBtn'); + }, + async () => { + await testSubjects.click('superDatePickerApplyTimeButton'); + await PageObjects.header.waitUntilLoadingHasFinished(); + } + ); + }, + async hasRedirectInfoInPingList() { + await this.expandPingRow(); + return retry.tryForTime(60 * 1000, async () => { + await testSubjects.existOrFail('uptimeMonitorPingListRedirectInfo'); + }); + }, + }; +} diff --git a/x-pack/solutions/observability/test/functional/services/uptime/navigation.ts b/x-pack/solutions/observability/test/functional/services/uptime/navigation.ts new file mode 100644 index 0000000000000..8a3898e813c6a --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/uptime/navigation.ts @@ -0,0 +1,97 @@ +/* + * 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 { FtrProviderContext } from '../../ftr_provider_context'; + +export function UptimeNavigationProvider({ getService, getPageObjects }: FtrProviderContext) { + const retry = getService('retry'); + const browser = getService('browser'); + const testSubjects = getService('testSubjects'); + const find = getService('find'); + const PageObjects = getPageObjects(['common', 'timePicker', 'header']); + + const goToUptimeRoot = async () => { + // Check if are already on overview uptime page, we don't need to repeat the step + await retry.tryForTime(60 * 1000, async () => { + if (await testSubjects.exists('uptimeSettingsToOverviewLink', { timeout: 0 })) { + await testSubjects.click('uptimeSettingsToOverviewLink'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await testSubjects.existOrFail('uptimeOverviewPage', { timeout: 2000 }); + } else { + await PageObjects.common.navigateToApp('uptime'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await testSubjects.existOrFail('uptimeOverviewPage', { timeout: 2000 }); + } + }); + }; + + return { + async refreshApp() { + await browser.refresh(); + await PageObjects.common.sleep(1000); + await PageObjects.header.waitUntilLoadingHasFinished(); + }, + + async goToUptime() { + await goToUptimeRoot(); + }, + + goToSettings: async () => { + await goToUptimeRoot(); + await testSubjects.click('settings-page-link', 5000); + await testSubjects.existOrFail('uptimeSettingsPage', { timeout: 10000 }); + }, + + checkIfOnMonitorPage: async (monitorId: string) => { + const monitorPage = await testSubjects.exists('uptimeMonitorPage', { timeout: 1000 }); + if (monitorId && monitorPage) { + const thisMonitorPage = + (await testSubjects.getVisibleText('monitor-page-title')) === monitorId; + return monitorPage && thisMonitorPage; + } else { + return monitorPage; + } + }, + + goToMonitor: async (monitorId: string) => { + // only go to monitor page if not already there + if (!(await testSubjects.exists('uptimeMonitorPage', { timeout: 0 }))) { + return retry.try(async () => { + await testSubjects.click(`monitor-page-link-${monitorId}`); + }); + await testSubjects.existOrFail('uptimeMonitorPage', { + timeout: 30000, + }); + } + }, + + goToCertificates: async () => { + if (!(await testSubjects.exists('uptimeCertificatesPage', { timeout: 0 }))) { + return retry.try(async () => { + if (await find.existsByCssSelector('[href="/app/uptime/certificates"]', 0)) { + await find.clickByCssSelector('[href="/app/uptime/certificates"]'); + } + await testSubjects.existOrFail('uptimeCertificatesPage'); + }); + } + return true; + }, + + async loadDataAndGoToMonitorPage(dateStart: string, dateEnd: string, monitorId: string) { + await PageObjects.timePicker.setAbsoluteRange(dateStart, dateEnd); + await this.goToMonitor(monitorId); + }, + + async isOnDetailsPage() { + return await testSubjects.exists('uptimeMonitorPage', { timeout: 0 }); + }, + + async goToHomeViaBreadCrumb() { + await testSubjects.click('breadcrumb first'); + }, + }; +} diff --git a/x-pack/solutions/observability/test/functional/services/uptime/overview.ts b/x-pack/solutions/observability/test/functional/services/uptime/overview.ts new file mode 100644 index 0000000000000..34b2531b76561 --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/uptime/overview.ts @@ -0,0 +1,45 @@ +/* + * 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 { FtrProviderContext } from '../../ftr_provider_context'; + +export function UptimeOverviewProvider({ getService }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + const retry = getService('retry'); + + return { + async expandMonitorDetail(id: string): Promise { + return testSubjects.click(`xpack.synthetics.monitorList.${id}.expandMonitorDetail`); + }, + async openIntegrationsPopoverForMonitor(id: string, plugin = 'synthetics'): Promise { + return testSubjects.click(`xpack.${plugin}.monitorList.actionsPopover.${id}`); + }, + async openAlertsPopover(): Promise { + return testSubjects.click('xpack.synthetics.alertsPopover.toggleButton'); + }, + /** + * If the popover is already open, click the nested button. + * Otherwise, open the popover, then click the nested button. + */ + async navigateToNestedPopover(): Promise { + if (await testSubjects.exists('xpack.synthetics.openAlertContextPanel')) { + return testSubjects.click('xpack.synthetics.openAlertContextPanel'); + } + await testSubjects.click('xpack.synthetics.alertsPopover.toggleButton'); + return testSubjects.click('xpack.synthetics.openAlertContextPanel'); + }, + + async clickDefineSettings() { + return retry.tryForTime(60 * 1000, async () => { + if (await testSubjects.exists('errorToastMessage', { timeout: 0 })) { + await testSubjects.click('toastCloseButton'); + } + await testSubjects.click('uptimeSettingsLink'); + }); + }, + }; +} diff --git a/x-pack/solutions/observability/test/functional/services/uptime/settings.ts b/x-pack/solutions/observability/test/functional/services/uptime/settings.ts new file mode 100644 index 0000000000000..46d8041b4028d --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/uptime/settings.ts @@ -0,0 +1,65 @@ +/* + * 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 { DynamicSettings } from '@kbn/uptime-plugin/common/runtime_types'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export function UptimeSettingsProvider({ getService }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + const retry = getService('retry'); + + const changeInputField = async (text: string, field: string) => { + const input = await testSubjects.find(field, 5000); + await input.clearValueWithKeyboard(); + await input.type(text); + }; + + return { + go: async () => { + await testSubjects.click('settings-page-link', 5000); + }, + + changeHeartbeatIndicesInput: async (text: string) => { + await changeInputField(text, 'heartbeat-indices-input-loaded'); + }, + changeErrorThresholdInput: async (text: string) => { + await changeInputField(text, 'expiration-threshold-input-loaded'); + }, + changeWarningThresholdInput: async (text: string) => { + await changeInputField(text, 'age-threshold-input-loaded'); + }, + loadFields: async (): Promise => { + const indInput = await testSubjects.find('heartbeat-indices-input-loaded', 5000); + const expirationInput = await testSubjects.find('expiration-threshold-input-loaded', 5000); + const ageInput = await testSubjects.find('age-threshold-input-loaded', 5000); + const heartbeatIndices = (await indInput.getAttribute('value')) ?? '0'; + const expiration = (await expirationInput.getAttribute('value')) ?? '0'; + const age = (await ageInput.getAttribute('value')) ?? '0'; + + return { + heartbeatIndices, + certAgeThreshold: parseInt(age, 10), + certExpirationThreshold: parseInt(expiration, 10), + defaultConnectors: [], + defaultEmail: { to: [], cc: [], bcc: [] }, + }; + }, + applyButtonIsDisabled: async () => { + return !!(await (await testSubjects.find('apply-settings-button')).getAttribute('disabled')); + }, + apply: async () => { + await (await testSubjects.find('apply-settings-button')).click(); + await retry.waitFor('submit to succeed', async () => { + // When the form submit is complete the form will no longer be disabled + const disabled = await ( + await testSubjects.find('heartbeat-indices-input-loaded', 5000) + ).getAttribute('disabled'); + return disabled === null; + }); + }, + }; +} diff --git a/x-pack/solutions/observability/test/functional/services/uptime/uptime.ts b/x-pack/solutions/observability/test/functional/services/uptime/uptime.ts new file mode 100644 index 0000000000000..b345be012968d --- /dev/null +++ b/x-pack/solutions/observability/test/functional/services/uptime/uptime.ts @@ -0,0 +1,39 @@ +/* + * 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 { FtrProviderContext } from '../../ftr_provider_context'; + +import { UptimeSettingsProvider } from './settings'; +import { UptimeCommonProvider } from './common'; +import { UptimeMonitorProvider } from './monitor'; +import { UptimeNavigationProvider } from './navigation'; +import { UptimeAlertsProvider } from './alerts'; +import { UptimeMLAnomalyProvider } from './ml_anomaly'; +import { UptimeCertProvider } from './certificates'; +import { UptimeOverviewProvider } from './overview'; + +export function UptimeProvider(context: FtrProviderContext) { + const common = UptimeCommonProvider(context); + const settings = UptimeSettingsProvider(context); + const monitor = UptimeMonitorProvider(context); + const navigation = UptimeNavigationProvider(context); + const alerts = UptimeAlertsProvider(context); + const ml = UptimeMLAnomalyProvider(context); + const cert = UptimeCertProvider(context); + const overview = UptimeOverviewProvider(context); + + return { + common, + settings, + monitor, + navigation, + alerts, + ml, + cert, + overview, + }; +} diff --git a/x-pack/solutions/observability/test/functional_with_es_ssl/apps/index.ts b/x-pack/solutions/observability/test/functional_with_es_ssl/apps/index.ts new file mode 100644 index 0000000000000..9ecb5bc054db5 --- /dev/null +++ b/x-pack/solutions/observability/test/functional_with_es_ssl/apps/index.ts @@ -0,0 +1,14 @@ +/* + * 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 { FtrProviderContext } from '../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('Chrome X-Pack Observability UI Functional Tests with ES SSL', function () { + loadTestFile(require.resolve('./uptime')); + }); +} diff --git a/x-pack/test/functional_with_es_ssl/apps/uptime/alert_flyout.ts b/x-pack/solutions/observability/test/functional_with_es_ssl/apps/uptime/alert_flyout.ts similarity index 100% rename from x-pack/test/functional_with_es_ssl/apps/uptime/alert_flyout.ts rename to x-pack/solutions/observability/test/functional_with_es_ssl/apps/uptime/alert_flyout.ts diff --git a/x-pack/test/functional_with_es_ssl/apps/uptime/index.ts b/x-pack/solutions/observability/test/functional_with_es_ssl/apps/uptime/index.ts similarity index 100% rename from x-pack/test/functional_with_es_ssl/apps/uptime/index.ts rename to x-pack/solutions/observability/test/functional_with_es_ssl/apps/uptime/index.ts diff --git a/x-pack/test/functional_with_es_ssl/apps/uptime/simple_down_alert.ts b/x-pack/solutions/observability/test/functional_with_es_ssl/apps/uptime/simple_down_alert.ts similarity index 100% rename from x-pack/test/functional_with_es_ssl/apps/uptime/simple_down_alert.ts rename to x-pack/solutions/observability/test/functional_with_es_ssl/apps/uptime/simple_down_alert.ts diff --git a/x-pack/test/functional_with_es_ssl/apps/config.ts b/x-pack/solutions/observability/test/functional_with_es_ssl/config.ts similarity index 82% rename from x-pack/test/functional_with_es_ssl/apps/config.ts rename to x-pack/solutions/observability/test/functional_with_es_ssl/config.ts index cfc7e119963e7..ae82efb582f86 100644 --- a/x-pack/test/functional_with_es_ssl/apps/config.ts +++ b/x-pack/solutions/observability/test/functional_with_es_ssl/config.ts @@ -7,7 +7,7 @@ import { FtrConfigProviderContext } from '@kbn/test'; import { resolve } from 'path'; -import { pageObjects, services } from '../ftr_provider_context'; +import { pageObjects, services } from './ftr_provider_context'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { const baseConfig = await readConfigFile( @@ -23,11 +23,11 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { '--uiSettings.overrides.observability:enableLegacyUptimeApp=true', ], }, - testFiles: [resolve(__dirname, './uptime')], + testFiles: [resolve(__dirname, './apps')], pageObjects, services, junit: { - reportName: 'Chrome X-Pack UI Functional Tests with ES SSL - Uptime', + reportName: 'Chrome X-Pack Observability UI Functional Tests with ES SSL', }, }; } diff --git a/x-pack/test/functional_with_es_ssl/ftr_provider_context.ts b/x-pack/solutions/observability/test/functional_with_es_ssl/ftr_provider_context.ts similarity index 63% rename from x-pack/test/functional_with_es_ssl/ftr_provider_context.ts rename to x-pack/solutions/observability/test/functional_with_es_ssl/ftr_provider_context.ts index 8185c6ff68c7d..c021f1c0e911a 100644 --- a/x-pack/test/functional_with_es_ssl/ftr_provider_context.ts +++ b/x-pack/solutions/observability/test/functional_with_es_ssl/ftr_provider_context.ts @@ -8,20 +8,16 @@ import { GenericFtrProviderContext, GenericFtrService } from '@kbn/test'; import { pageObjects as platformPageObjects } from '@kbn/test-suites-xpack-platform/functional_with_es_ssl/page_objects'; -import { services as platformServices } from '../functional/services'; -import { UptimePageObject } from '../functional/page_objects/uptime_page'; -import { InfraLogsPageProvider } from '../functional/page_objects/infra_logs_page'; -import { UptimeProvider } from '../functional/services/uptime'; +import { pageObjects as obltPageObjects } from '../functional/page_objects'; +import { services as obltFunctionalServices } from '../functional/services'; export const pageObjects = { ...platformPageObjects, - infraLogs: InfraLogsPageProvider, - uptime: UptimePageObject, + ...obltPageObjects, }; export const services = { - ...platformServices, - uptime: UptimeProvider, + ...obltFunctionalServices, }; export type FtrProviderContext = GenericFtrProviderContext; export class FtrService extends GenericFtrService {} diff --git a/x-pack/test/observability_ai_assistant_functional/common/config.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/common/config.ts similarity index 95% rename from x-pack/test/observability_ai_assistant_functional/common/config.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/common/config.ts index bee949cbeb19f..df8c15cb113a8 100644 --- a/x-pack/test/observability_ai_assistant_functional/common/config.ts +++ b/x-pack/solutions/observability/test/observability_ai_assistant_functional/common/config.ts @@ -13,7 +13,7 @@ import { } from '@kbn/test-suites-src/analytics/services/kibana_ebt'; import path from 'path'; import { secondaryEditor, editor, viewer } from './users/users'; -import { getScopedApiClient } from '../../api_integration/deployment_agnostic/apis/observability/ai_assistant/utils/observability_ai_assistant_api_client'; +import { getScopedApiClient } from '../../api_integration_deployment_agnostic/apis/ai_assistant/utils/observability_ai_assistant_api_client'; import { InheritedFtrProviderContext, InheritedServices } from '../ftr_provider_context'; import { ObservabilityAIAssistantUIProvider } from './ui'; import { getApmSynthtraceEsClient } from './create_synthtrace_client'; @@ -65,7 +65,7 @@ async function getTestConfig({ kibanaConfig: Record | undefined; readConfigFile: FtrConfigProviderContext['readConfigFile']; }) { - const testConfig = await readConfigFile(require.resolve('../../functional/config.base.js')); + const testConfig = await readConfigFile(require.resolve('../../functional/config.base.ts')); const getScopedApiClientForUsername = (username: string) => getScopedApiClient(kibanaServer, username); diff --git a/x-pack/test/observability_ai_assistant_functional/common/connectors.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/common/connectors.ts similarity index 90% rename from x-pack/test/observability_ai_assistant_functional/common/connectors.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/common/connectors.ts index eff4f0aca57dd..45f7d76a42bac 100644 --- a/x-pack/test/observability_ai_assistant_functional/common/connectors.ts +++ b/x-pack/solutions/observability/test/observability_ai_assistant_functional/common/connectors.ts @@ -6,7 +6,7 @@ */ import { Agent as SuperTestAgent } from 'supertest'; -import { LlmProxy } from '../../api_integration/deployment_agnostic/apis/observability/ai_assistant/utils/create_llm_proxy'; +import { LlmProxy } from '../../api_integration_deployment_agnostic/apis/ai_assistant/utils/create_llm_proxy'; export async function createConnector(proxy: LlmProxy, supertest: SuperTestAgent) { await supertest diff --git a/x-pack/test/observability_ai_assistant_functional/common/conversations.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/common/conversations.ts similarity index 100% rename from x-pack/test/observability_ai_assistant_functional/common/conversations.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/common/conversations.ts diff --git a/x-pack/test/observability_ai_assistant_functional/common/create_synthtrace_client.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/common/create_synthtrace_client.ts similarity index 100% rename from x-pack/test/observability_ai_assistant_functional/common/create_synthtrace_client.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/common/create_synthtrace_client.ts diff --git a/x-pack/test/observability_ai_assistant_functional/common/intercept_request.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/common/intercept_request.ts similarity index 100% rename from x-pack/test/observability_ai_assistant_functional/common/intercept_request.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/common/intercept_request.ts diff --git a/x-pack/test/observability_ai_assistant_functional/common/ui/index.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/common/ui/index.ts similarity index 100% rename from x-pack/test/observability_ai_assistant_functional/common/ui/index.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/common/ui/index.ts diff --git a/x-pack/test/observability_ai_assistant_functional/common/users/create_users_and_roles.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/common/users/create_users_and_roles.ts similarity index 100% rename from x-pack/test/observability_ai_assistant_functional/common/users/create_users_and_roles.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/common/users/create_users_and_roles.ts diff --git a/x-pack/test/observability_ai_assistant_functional/common/users/roles.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/common/users/roles.ts similarity index 100% rename from x-pack/test/observability_ai_assistant_functional/common/users/roles.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/common/users/roles.ts diff --git a/x-pack/test/observability_ai_assistant_functional/common/users/users.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/common/users/users.ts similarity index 100% rename from x-pack/test/observability_ai_assistant_functional/common/users/users.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/common/users/users.ts diff --git a/x-pack/test/observability_ai_assistant_functional/configs/index.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/configs/index.ts similarity index 100% rename from x-pack/test/observability_ai_assistant_functional/configs/index.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/configs/index.ts diff --git a/x-pack/test/observability_ai_assistant_functional/enterprise/config.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/enterprise/config.ts similarity index 86% rename from x-pack/test/observability_ai_assistant_functional/enterprise/config.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/enterprise/config.ts index 598ecae70efbb..2018bf87c4fee 100644 --- a/x-pack/test/observability_ai_assistant_functional/enterprise/config.ts +++ b/x-pack/solutions/observability/test/observability_ai_assistant_functional/enterprise/config.ts @@ -7,5 +7,4 @@ import { configs } from '../configs'; -// eslint-disable-next-line import/no-default-export export default configs.enterprise; diff --git a/x-pack/test/observability_ai_assistant_functional/ftr_provider_context.d.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/ftr_provider_context.d.ts similarity index 100% rename from x-pack/test/observability_ai_assistant_functional/ftr_provider_context.d.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/ftr_provider_context.d.ts diff --git a/x-pack/test/observability_ai_assistant_functional/tests/contextual_insights/index.spec.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/contextual_insights/index.spec.ts similarity index 97% rename from x-pack/test/observability_ai_assistant_functional/tests/contextual_insights/index.spec.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/contextual_insights/index.spec.ts index 7b59cab352742..478193af9fcd2 100644 --- a/x-pack/test/observability_ai_assistant_functional/tests/contextual_insights/index.spec.ts +++ b/x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/contextual_insights/index.spec.ts @@ -11,7 +11,7 @@ import moment from 'moment'; import { createLlmProxy, LlmProxy, -} from '../../../api_integration/deployment_agnostic/apis/observability/ai_assistant/utils/create_llm_proxy'; +} from '../../../api_integration_deployment_agnostic/apis/ai_assistant/utils/create_llm_proxy'; import { FtrProviderContext } from '../../ftr_provider_context'; import { deleteConnectors, createConnector } from '../../common/connectors'; diff --git a/x-pack/test/observability_ai_assistant_functional/tests/conversations/archiving.spec.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/conversations/archiving.spec.ts similarity index 97% rename from x-pack/test/observability_ai_assistant_functional/tests/conversations/archiving.spec.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/conversations/archiving.spec.ts index a18dc8074fd79..866f259743954 100644 --- a/x-pack/test/observability_ai_assistant_functional/tests/conversations/archiving.spec.ts +++ b/x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/conversations/archiving.spec.ts @@ -9,7 +9,7 @@ import expect from '@kbn/expect'; import { createLlmProxy, LlmProxy, -} from '../../../api_integration/deployment_agnostic/apis/observability/ai_assistant/utils/create_llm_proxy'; +} from '../../../api_integration_deployment_agnostic/apis/ai_assistant/utils/create_llm_proxy'; import { FtrProviderContext } from '../../ftr_provider_context'; import { createConnector, deleteConnectors } from '../../common/connectors'; import { deleteConversations } from '../../common/conversations'; diff --git a/x-pack/test/observability_ai_assistant_functional/tests/conversations/index.spec.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/conversations/index.spec.ts similarity index 98% rename from x-pack/test/observability_ai_assistant_functional/tests/conversations/index.spec.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/conversations/index.spec.ts index 3b652f18f7336..b280b8333be9f 100644 --- a/x-pack/test/observability_ai_assistant_functional/tests/conversations/index.spec.ts +++ b/x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/conversations/index.spec.ts @@ -11,11 +11,11 @@ import { ChatFeedback } from '@kbn/observability-ai-assistant-plugin/public/anal import { pick } from 'lodash'; import { parse as parseCookie } from 'tough-cookie'; import { kbnTestConfig } from '@kbn/test'; -import { systemMessageSorted } from '../../../api_integration/deployment_agnostic/apis/observability/ai_assistant/utils/conversation'; +import { systemMessageSorted } from '../../../api_integration_deployment_agnostic/apis/ai_assistant/utils/conversation'; import { createLlmProxy, LlmProxy, -} from '../../../api_integration/deployment_agnostic/apis/observability/ai_assistant/utils/create_llm_proxy'; +} from '../../../api_integration_deployment_agnostic/apis/ai_assistant/utils/create_llm_proxy'; import { FtrProviderContext } from '../../ftr_provider_context'; import { editor } from '../../common/users/users'; diff --git a/x-pack/test/observability_ai_assistant_functional/tests/conversations/sharing.spec.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/conversations/sharing.spec.ts similarity index 98% rename from x-pack/test/observability_ai_assistant_functional/tests/conversations/sharing.spec.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/conversations/sharing.spec.ts index 6c8abf525e0cb..76353ce6d38eb 100644 --- a/x-pack/test/observability_ai_assistant_functional/tests/conversations/sharing.spec.ts +++ b/x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/conversations/sharing.spec.ts @@ -9,7 +9,7 @@ import expect from '@kbn/expect'; import { createLlmProxy, LlmProxy, -} from '../../../api_integration/deployment_agnostic/apis/observability/ai_assistant/utils/create_llm_proxy'; +} from '../../../api_integration_deployment_agnostic/apis/ai_assistant/utils/create_llm_proxy'; import { FtrProviderContext } from '../../ftr_provider_context'; import { createConnector, deleteConnectors } from '../../common/connectors'; import { deleteConversations } from '../../common/conversations'; diff --git a/x-pack/test/observability_ai_assistant_functional/tests/feature_controls/assistant_security.spec.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/feature_controls/assistant_security.spec.ts similarity index 98% rename from x-pack/test/observability_ai_assistant_functional/tests/feature_controls/assistant_security.spec.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/feature_controls/assistant_security.spec.ts index 60c4c369879ba..3a6792b4dbca8 100644 --- a/x-pack/test/observability_ai_assistant_functional/tests/feature_controls/assistant_security.spec.ts +++ b/x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/feature_controls/assistant_security.spec.ts @@ -10,7 +10,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; import { createLlmProxy, LlmProxy, -} from '../../../api_integration/deployment_agnostic/apis/observability/ai_assistant/utils/create_llm_proxy'; +} from '../../../api_integration_deployment_agnostic/apis/ai_assistant/utils/create_llm_proxy'; import { createConnector, deleteConnectors } from '../../common/connectors'; import { createAndLoginUserWithCustomRole, deleteAndLogoutUser } from './helpers'; diff --git a/x-pack/test/observability_ai_assistant_functional/tests/feature_controls/helpers.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/feature_controls/helpers.ts similarity index 100% rename from x-pack/test/observability_ai_assistant_functional/tests/feature_controls/helpers.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/feature_controls/helpers.ts diff --git a/x-pack/test/observability_ai_assistant_functional/tests/feature_controls/settings_security.spec.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/feature_controls/settings_security.spec.ts similarity index 100% rename from x-pack/test/observability_ai_assistant_functional/tests/feature_controls/settings_security.spec.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/feature_controls/settings_security.spec.ts diff --git a/x-pack/test/observability_ai_assistant_functional/tests/index.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/index.ts similarity index 92% rename from x-pack/test/observability_ai_assistant_functional/tests/index.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/index.ts index 76f7a98a07aa2..b9ee4f7462fc5 100644 --- a/x-pack/test/observability_ai_assistant_functional/tests/index.ts +++ b/x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/index.ts @@ -8,7 +8,7 @@ import globby from 'globby'; import path from 'path'; import { createUsersAndRoles } from '../common/users/create_users_and_roles'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { FtrProviderContext } from '../../api_integration/ftr_provider_context'; const cwd = path.join(__dirname); diff --git a/x-pack/test/observability_ai_assistant_functional/tests/knowledge_base/index.spec.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/knowledge_base/index.spec.ts similarity index 90% rename from x-pack/test/observability_ai_assistant_functional/tests/knowledge_base/index.spec.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/knowledge_base/index.spec.ts index 4ec26fdcb46d2..b41d965dfa570 100644 --- a/x-pack/test/observability_ai_assistant_functional/tests/knowledge_base/index.spec.ts +++ b/x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/knowledge_base/index.spec.ts @@ -10,14 +10,14 @@ import { KnowledgeBaseState } from '@kbn/observability-ai-assistant-plugin/commo import { LlmProxy, createLlmProxy, -} from '../../../api_integration/deployment_agnostic/apis/observability/ai_assistant/utils/create_llm_proxy'; +} from '../../../api_integration_deployment_agnostic/apis/ai_assistant/utils/create_llm_proxy'; import { FtrProviderContext } from '../../ftr_provider_context'; import { deployTinyElserAndSetupKb, stopTinyElserModel, teardownTinyElserModelAndInferenceEndpoint, -} from '../../../api_integration/deployment_agnostic/apis/observability/ai_assistant/utils/model_and_inference'; -import { clearKnowledgeBase } from '../../../api_integration/deployment_agnostic/apis/observability/ai_assistant/utils/knowledge_base'; +} from '../../../api_integration_deployment_agnostic/apis/ai_assistant/utils/model_and_inference'; +import { clearKnowledgeBase } from '../../../api_integration_deployment_agnostic/apis/ai_assistant/utils/knowledge_base'; import { createConnector, deleteConnectors } from '../../common/connectors'; export default function ApiTest({ getService }: FtrProviderContext) { diff --git a/x-pack/test/observability_ai_assistant_functional/tests/knowledge_base_management/index.spec.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/knowledge_base_management/index.spec.ts similarity index 96% rename from x-pack/test/observability_ai_assistant_functional/tests/knowledge_base_management/index.spec.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/knowledge_base_management/index.spec.ts index 8e51217c4a3c8..ce231432aa48d 100644 --- a/x-pack/test/observability_ai_assistant_functional/tests/knowledge_base_management/index.spec.ts +++ b/x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/knowledge_base_management/index.spec.ts @@ -13,9 +13,9 @@ import path from 'path'; import { deployTinyElserAndSetupKb, teardownTinyElserModelAndInferenceEndpoint, -} from '../../../api_integration/deployment_agnostic/apis/observability/ai_assistant/utils/model_and_inference'; -import { clearKnowledgeBase } from '../../../api_integration/deployment_agnostic/apis/observability/ai_assistant/utils/knowledge_base'; -import { ObservabilityAIAssistantApiClient } from '../../../api_integration/deployment_agnostic/apis/observability/ai_assistant/utils/observability_ai_assistant_api_client'; +} from '../../../api_integration_deployment_agnostic/apis/ai_assistant/utils/model_and_inference'; +import { clearKnowledgeBase } from '../../../api_integration_deployment_agnostic/apis/ai_assistant/utils/knowledge_base'; +import { ObservabilityAIAssistantApiClient } from '../../../api_integration_deployment_agnostic/apis/ai_assistant/utils/observability_ai_assistant_api_client'; import { FtrProviderContext } from '../../ftr_provider_context'; export default function ApiTest({ getService, getPageObjects }: FtrProviderContext) { diff --git a/x-pack/test/observability_ai_assistant_functional/tests/settings/change_knowledge_base_model.spec.ts b/x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/settings/change_knowledge_base_model.spec.ts similarity index 95% rename from x-pack/test/observability_ai_assistant_functional/tests/settings/change_knowledge_base_model.spec.ts rename to x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/settings/change_knowledge_base_model.spec.ts index 12173f7c51727..94de8a525ebe9 100644 --- a/x-pack/test/observability_ai_assistant_functional/tests/settings/change_knowledge_base_model.spec.ts +++ b/x-pack/solutions/observability/test/observability_ai_assistant_functional/tests/settings/change_knowledge_base_model.spec.ts @@ -12,12 +12,12 @@ import { createConnector, deleteConnectors } from '../../common/connectors'; import { LlmProxy, createLlmProxy, -} from '../../../api_integration/deployment_agnostic/apis/observability/ai_assistant/utils/create_llm_proxy'; +} from '../../../api_integration_deployment_agnostic/apis/ai_assistant/utils/create_llm_proxy'; import { deployTinyElserAndSetupKb, stopTinyElserModel, teardownTinyElserModelAndInferenceEndpoint, -} from '../../../api_integration/deployment_agnostic/apis/observability/ai_assistant/utils/model_and_inference'; +} from '../../../api_integration_deployment_agnostic/apis/ai_assistant/utils/model_and_inference'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const log = getService('log'); diff --git a/x-pack/test/observability_api_integration/basic/config.ts b/x-pack/solutions/observability/test/observability_api_integration/basic/config.ts similarity index 89% rename from x-pack/test/observability_api_integration/basic/config.ts rename to x-pack/solutions/observability/test/observability_api_integration/basic/config.ts index f0fb37f79bcdd..20b6427826514 100644 --- a/x-pack/test/observability_api_integration/basic/config.ts +++ b/x-pack/solutions/observability/test/observability_api_integration/basic/config.ts @@ -7,7 +7,6 @@ import { createTestConfig } from '../common/config'; -// eslint-disable-next-line import/no-default-export export default createTestConfig({ license: 'basic', name: 'X-Pack Observability API integration tests (basic)', diff --git a/x-pack/test/observability_api_integration/basic/tests/annotations.ts b/x-pack/solutions/observability/test/observability_api_integration/basic/tests/annotations.ts similarity index 96% rename from x-pack/test/observability_api_integration/basic/tests/annotations.ts rename to x-pack/solutions/observability/test/observability_api_integration/basic/tests/annotations.ts index 6b1cdb43f5f54..5c7fc4a1c8540 100644 --- a/x-pack/test/observability_api_integration/basic/tests/annotations.ts +++ b/x-pack/solutions/observability/test/observability_api_integration/basic/tests/annotations.ts @@ -9,7 +9,6 @@ import expect from '@kbn/expect'; import { JsonObject } from '@kbn/utility-types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -// eslint-disable-next-line import/no-default-export export default function annotationApiTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); diff --git a/x-pack/test/observability_api_integration/basic/tests/index.ts b/x-pack/solutions/observability/test/observability_api_integration/basic/tests/index.ts similarity index 91% rename from x-pack/test/observability_api_integration/basic/tests/index.ts rename to x-pack/solutions/observability/test/observability_api_integration/basic/tests/index.ts index d22271c4cd2e0..c627bea149a48 100644 --- a/x-pack/test/observability_api_integration/basic/tests/index.ts +++ b/x-pack/solutions/observability/test/observability_api_integration/basic/tests/index.ts @@ -7,7 +7,6 @@ import { FtrProviderContext } from '../../common/ftr_provider_context'; -// eslint-disable-next-line import/no-default-export export default function observabilityApiIntegrationTests({ loadTestFile }: FtrProviderContext) { describe('Observability specs (basic)', function () { this.tags('skipFIPS'); diff --git a/x-pack/test/observability_api_integration/common/bootstrap_synthtrace.ts b/x-pack/solutions/observability/test/observability_api_integration/common/bootstrap_synthtrace.ts similarity index 100% rename from x-pack/test/observability_api_integration/common/bootstrap_synthtrace.ts rename to x-pack/solutions/observability/test/observability_api_integration/common/bootstrap_synthtrace.ts diff --git a/x-pack/test/observability_api_integration/common/config.ts b/x-pack/solutions/observability/test/observability_api_integration/common/config.ts similarity index 100% rename from x-pack/test/observability_api_integration/common/config.ts rename to x-pack/solutions/observability/test/observability_api_integration/common/config.ts diff --git a/x-pack/test/observability_api_integration/common/ftr_provider_context.ts b/x-pack/solutions/observability/test/observability_api_integration/common/ftr_provider_context.ts similarity index 100% rename from x-pack/test/observability_api_integration/common/ftr_provider_context.ts rename to x-pack/solutions/observability/test/observability_api_integration/common/ftr_provider_context.ts diff --git a/x-pack/test/observability_api_integration/common/obs_api_supertest.ts b/x-pack/solutions/observability/test/observability_api_integration/common/obs_api_supertest.ts similarity index 100% rename from x-pack/test/observability_api_integration/common/obs_api_supertest.ts rename to x-pack/solutions/observability/test/observability_api_integration/common/obs_api_supertest.ts diff --git a/x-pack/test/observability_api_integration/fixtures/kbn_archiver/saved_objects/slo.json b/x-pack/solutions/observability/test/observability_api_integration/fixtures/kbn_archiver/saved_objects/slo.json similarity index 100% rename from x-pack/test/observability_api_integration/fixtures/kbn_archiver/saved_objects/slo.json rename to x-pack/solutions/observability/test/observability_api_integration/fixtures/kbn_archiver/saved_objects/slo.json diff --git a/x-pack/test/observability_api_integration/trial/config.ts b/x-pack/solutions/observability/test/observability_api_integration/trial/config.ts similarity index 89% rename from x-pack/test/observability_api_integration/trial/config.ts rename to x-pack/solutions/observability/test/observability_api_integration/trial/config.ts index 0df73c190d8ba..a8fbc757909d1 100644 --- a/x-pack/test/observability_api_integration/trial/config.ts +++ b/x-pack/solutions/observability/test/observability_api_integration/trial/config.ts @@ -7,7 +7,6 @@ import { createTestConfig } from '../common/config'; -// eslint-disable-next-line import/no-default-export export default createTestConfig({ license: 'trial', name: 'X-Pack Observability API integration tests (trial)', diff --git a/x-pack/test/observability_api_integration/trial/tests/annotations.ts b/x-pack/solutions/observability/test/observability_api_integration/trial/tests/annotations.ts similarity index 99% rename from x-pack/test/observability_api_integration/trial/tests/annotations.ts rename to x-pack/solutions/observability/test/observability_api_integration/trial/tests/annotations.ts index 0b6bba88c0f79..beb3e3668bc58 100644 --- a/x-pack/test/observability_api_integration/trial/tests/annotations.ts +++ b/x-pack/solutions/observability/test/observability_api_integration/trial/tests/annotations.ts @@ -12,7 +12,6 @@ import { FtrProviderContext } from '../../common/ftr_provider_context'; const DEFAULT_INDEX_NAME = 'observability-annotations'; -// eslint-disable-next-line import/no-default-export export default function annotationApiTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const es = getService('es'); diff --git a/x-pack/test/observability_api_integration/trial/tests/find_annotations.ts b/x-pack/solutions/observability/test/observability_api_integration/trial/tests/find_annotations.ts similarity index 98% rename from x-pack/test/observability_api_integration/trial/tests/find_annotations.ts rename to x-pack/solutions/observability/test/observability_api_integration/trial/tests/find_annotations.ts index 73b5266b8206b..7a1a163c550ec 100644 --- a/x-pack/test/observability_api_integration/trial/tests/find_annotations.ts +++ b/x-pack/solutions/observability/test/observability_api_integration/trial/tests/find_annotations.ts @@ -13,7 +13,6 @@ import { FtrProviderContext } from '../../common/ftr_provider_context'; const DEFAULT_INDEX_NAME = 'observability-annotations'; -// eslint-disable-next-line import/no-default-export export default function annotationApiTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const es = getService('es'); diff --git a/x-pack/test/observability_api_integration/trial/tests/index.ts b/x-pack/solutions/observability/test/observability_api_integration/trial/tests/index.ts similarity index 92% rename from x-pack/test/observability_api_integration/trial/tests/index.ts rename to x-pack/solutions/observability/test/observability_api_integration/trial/tests/index.ts index 59536dee4ccc9..3dee2124727a0 100644 --- a/x-pack/test/observability_api_integration/trial/tests/index.ts +++ b/x-pack/solutions/observability/test/observability_api_integration/trial/tests/index.ts @@ -7,7 +7,6 @@ import { FtrProviderContext } from '../../common/ftr_provider_context'; -// eslint-disable-next-line import/no-default-export export default function apmApiIntegrationTests({ loadTestFile }: FtrProviderContext) { describe('Observability specs (trial)', function () { loadTestFile(require.resolve('./annotations')); diff --git a/x-pack/test/observability_api_integration/trial/tests/obs_alert_details_context.ts b/x-pack/solutions/observability/test/observability_api_integration/trial/tests/obs_alert_details_context.ts similarity index 99% rename from x-pack/test/observability_api_integration/trial/tests/obs_alert_details_context.ts rename to x-pack/solutions/observability/test/observability_api_integration/trial/tests/obs_alert_details_context.ts index 31f2bb5e3466e..99bdd0808a4e7 100644 --- a/x-pack/test/observability_api_integration/trial/tests/obs_alert_details_context.ts +++ b/x-pack/solutions/observability/test/observability_api_integration/trial/tests/obs_alert_details_context.ts @@ -12,7 +12,6 @@ import { LogCategory } from '@kbn/apm-plugin/server/routes/assistant_functions/g import { SupertestReturnType } from '../../common/obs_api_supertest'; import { ObsFtrProviderContext } from '../../common/ftr_provider_context'; -// eslint-disable-next-line import/no-default-export export default function ApiTest({ getService }: ObsFtrProviderContext) { const obsApiClient = getService('obsApiClient'); const apmSynthtraceClient = getService('apmSynthtraceEsClient'); diff --git a/x-pack/test/observability_functional/apps/observability/exploratory_view.ts b/x-pack/solutions/observability/test/observability_functional/apps/observability/exploratory_view.ts similarity index 100% rename from x-pack/test/observability_functional/apps/observability/exploratory_view.ts rename to x-pack/solutions/observability/test/observability_functional/apps/observability/exploratory_view.ts diff --git a/x-pack/test/observability_functional/apps/observability/feature_controls/index.ts b/x-pack/solutions/observability/test/observability_functional/apps/observability/feature_controls/index.ts similarity index 100% rename from x-pack/test/observability_functional/apps/observability/feature_controls/index.ts rename to x-pack/solutions/observability/test/observability_functional/apps/observability/feature_controls/index.ts diff --git a/x-pack/test/observability_functional/apps/observability/feature_controls/observability_security.ts b/x-pack/solutions/observability/test/observability_functional/apps/observability/feature_controls/observability_security.ts similarity index 100% rename from x-pack/test/observability_functional/apps/observability/feature_controls/observability_security.ts rename to x-pack/solutions/observability/test/observability_functional/apps/observability/feature_controls/observability_security.ts diff --git a/x-pack/test/observability_functional/apps/observability/helpers.ts b/x-pack/solutions/observability/test/observability_functional/apps/observability/helpers.ts similarity index 100% rename from x-pack/test/observability_functional/apps/observability/helpers.ts rename to x-pack/solutions/observability/test/observability_functional/apps/observability/helpers.ts diff --git a/x-pack/test/observability_functional/apps/observability/index.ts b/x-pack/solutions/observability/test/observability_functional/apps/observability/index.ts similarity index 100% rename from x-pack/test/observability_functional/apps/observability/index.ts rename to x-pack/solutions/observability/test/observability_functional/apps/observability/index.ts diff --git a/x-pack/test/observability_functional/apps/observability/pages/alert_details_page.ts b/x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alert_details_page.ts similarity index 100% rename from x-pack/test/observability_functional/apps/observability/pages/alert_details_page.ts rename to x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alert_details_page.ts diff --git a/x-pack/test/observability_functional/apps/observability/pages/alerts/add_to_case.ts b/x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alerts/add_to_case.ts similarity index 100% rename from x-pack/test/observability_functional/apps/observability/pages/alerts/add_to_case.ts rename to x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alerts/add_to_case.ts diff --git a/x-pack/test/observability_functional/apps/observability/pages/alerts/alert_controls.ts b/x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alerts/alert_controls.ts similarity index 100% rename from x-pack/test/observability_functional/apps/observability/pages/alerts/alert_controls.ts rename to x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alerts/alert_controls.ts diff --git a/x-pack/test/observability_functional/apps/observability/pages/alerts/alert_summary_widget.ts b/x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alerts/alert_summary_widget.ts similarity index 100% rename from x-pack/test/observability_functional/apps/observability/pages/alerts/alert_summary_widget.ts rename to x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alerts/alert_summary_widget.ts diff --git a/x-pack/test/observability_functional/apps/observability/pages/alerts/custom_threshold.ts b/x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alerts/custom_threshold.ts similarity index 100% rename from x-pack/test/observability_functional/apps/observability/pages/alerts/custom_threshold.ts rename to x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alerts/custom_threshold.ts diff --git a/x-pack/test/observability_functional/apps/observability/pages/alerts/custom_threshold_preview_chart.ts b/x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alerts/custom_threshold_preview_chart.ts similarity index 100% rename from x-pack/test/observability_functional/apps/observability/pages/alerts/custom_threshold_preview_chart.ts rename to x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alerts/custom_threshold_preview_chart.ts diff --git a/x-pack/test/observability_functional/apps/observability/pages/alerts/index.ts b/x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alerts/index.ts similarity index 100% rename from x-pack/test/observability_functional/apps/observability/pages/alerts/index.ts rename to x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alerts/index.ts diff --git a/x-pack/test/observability_functional/apps/observability/pages/alerts/metric_threshold.ts b/x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alerts/metric_threshold.ts similarity index 100% rename from x-pack/test/observability_functional/apps/observability/pages/alerts/metric_threshold.ts rename to x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alerts/metric_threshold.ts diff --git a/x-pack/test/observability_functional/apps/observability/pages/alerts/pagination.ts b/x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alerts/pagination.ts similarity index 100% rename from x-pack/test/observability_functional/apps/observability/pages/alerts/pagination.ts rename to x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alerts/pagination.ts diff --git a/x-pack/test/observability_functional/apps/observability/pages/alerts/rule_stats.ts b/x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alerts/rule_stats.ts similarity index 100% rename from x-pack/test/observability_functional/apps/observability/pages/alerts/rule_stats.ts rename to x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alerts/rule_stats.ts diff --git a/x-pack/test/observability_functional/apps/observability/pages/alerts/state_synchronization.ts b/x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alerts/state_synchronization.ts similarity index 100% rename from x-pack/test/observability_functional/apps/observability/pages/alerts/state_synchronization.ts rename to x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alerts/state_synchronization.ts diff --git a/x-pack/test/observability_functional/apps/observability/pages/alerts/table_configuration.ts b/x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alerts/table_configuration.ts similarity index 100% rename from x-pack/test/observability_functional/apps/observability/pages/alerts/table_configuration.ts rename to x-pack/solutions/observability/test/observability_functional/apps/observability/pages/alerts/table_configuration.ts diff --git a/x-pack/test/observability_functional/apps/observability/pages/cases/case_details.ts b/x-pack/solutions/observability/test/observability_functional/apps/observability/pages/cases/case_details.ts similarity index 100% rename from x-pack/test/observability_functional/apps/observability/pages/cases/case_details.ts rename to x-pack/solutions/observability/test/observability_functional/apps/observability/pages/cases/case_details.ts diff --git a/x-pack/test/observability_functional/apps/observability/pages/overview/alert_table.ts b/x-pack/solutions/observability/test/observability_functional/apps/observability/pages/overview/alert_table.ts similarity index 100% rename from x-pack/test/observability_functional/apps/observability/pages/overview/alert_table.ts rename to x-pack/solutions/observability/test/observability_functional/apps/observability/pages/overview/alert_table.ts diff --git a/x-pack/test/observability_functional/apps/observability/pages/rule_details_page.ts b/x-pack/solutions/observability/test/observability_functional/apps/observability/pages/rule_details_page.ts similarity index 100% rename from x-pack/test/observability_functional/apps/observability/pages/rule_details_page.ts rename to x-pack/solutions/observability/test/observability_functional/apps/observability/pages/rule_details_page.ts diff --git a/x-pack/test/observability_functional/apps/observability/pages/rules_page.ts b/x-pack/solutions/observability/test/observability_functional/apps/observability/pages/rules_page.ts similarity index 100% rename from x-pack/test/observability_functional/apps/observability/pages/rules_page.ts rename to x-pack/solutions/observability/test/observability_functional/apps/observability/pages/rules_page.ts diff --git a/x-pack/test/observability_functional/apps/observability/sidenav/sidenav.ts b/x-pack/solutions/observability/test/observability_functional/apps/observability/sidenav/sidenav.ts similarity index 100% rename from x-pack/test/observability_functional/apps/observability/sidenav/sidenav.ts rename to x-pack/solutions/observability/test/observability_functional/apps/observability/sidenav/sidenav.ts diff --git a/x-pack/test/observability_functional/ftr_provider_context.d.ts b/x-pack/solutions/observability/test/observability_functional/ftr_provider_context.d.ts similarity index 100% rename from x-pack/test/observability_functional/ftr_provider_context.d.ts rename to x-pack/solutions/observability/test/observability_functional/ftr_provider_context.d.ts diff --git a/x-pack/test/observability_functional/with_rac_write.config.ts b/x-pack/solutions/observability/test/observability_functional/with_rac_write.config.ts similarity index 98% rename from x-pack/test/observability_functional/with_rac_write.config.ts rename to x-pack/solutions/observability/test/observability_functional/with_rac_write.config.ts index b739b9b6ae048..625b4be938edd 100644 --- a/x-pack/test/observability_functional/with_rac_write.config.ts +++ b/x-pack/solutions/observability/test/observability_functional/with_rac_write.config.ts @@ -28,7 +28,7 @@ const enabledActionTypes = [ export default async function ({ readConfigFile }: FtrConfigProviderContext) { const xpackFunctionalConfig = await readConfigFile( - require.resolve('../functional/config.base.js') + require.resolve('../functional/config.base.ts') ); const servers = { diff --git a/x-pack/test/observability_onboarding_api_integration/basic/config.ts b/x-pack/solutions/observability/test/observability_onboarding_api_integration/basic/config.ts similarity index 85% rename from x-pack/test/observability_onboarding_api_integration/basic/config.ts rename to x-pack/solutions/observability/test/observability_onboarding_api_integration/basic/config.ts index 614f052c9c774..2611fe4a21dfa 100644 --- a/x-pack/test/observability_onboarding_api_integration/basic/config.ts +++ b/x-pack/solutions/observability/test/observability_onboarding_api_integration/basic/config.ts @@ -7,5 +7,4 @@ import { configs } from '../configs'; -// eslint-disable-next-line import/no-default-export export default configs.basic; diff --git a/x-pack/test/observability_onboarding_api_integration/cloud/config.ts b/x-pack/solutions/observability/test/observability_onboarding_api_integration/cloud/config.ts similarity index 85% rename from x-pack/test/observability_onboarding_api_integration/cloud/config.ts rename to x-pack/solutions/observability/test/observability_onboarding_api_integration/cloud/config.ts index 9f3ac78179c28..06421969888b5 100644 --- a/x-pack/test/observability_onboarding_api_integration/cloud/config.ts +++ b/x-pack/solutions/observability/test/observability_onboarding_api_integration/cloud/config.ts @@ -7,5 +7,4 @@ import { configs } from '../configs'; -// eslint-disable-next-line import/no-default-export export default configs.cloud; diff --git a/x-pack/test/observability_onboarding_api_integration/common/config.ts b/x-pack/solutions/observability/test/observability_onboarding_api_integration/common/config.ts similarity index 100% rename from x-pack/test/observability_onboarding_api_integration/common/config.ts rename to x-pack/solutions/observability/test/observability_onboarding_api_integration/common/config.ts diff --git a/x-pack/test/observability_onboarding_api_integration/common/ftr_provider_context.ts b/x-pack/solutions/observability/test/observability_onboarding_api_integration/common/ftr_provider_context.ts similarity index 100% rename from x-pack/test/observability_onboarding_api_integration/common/ftr_provider_context.ts rename to x-pack/solutions/observability/test/observability_onboarding_api_integration/common/ftr_provider_context.ts diff --git a/x-pack/test/observability_onboarding_api_integration/common/observability_onboarding_api_supertest.ts b/x-pack/solutions/observability/test/observability_onboarding_api_integration/common/observability_onboarding_api_supertest.ts similarity index 100% rename from x-pack/test/observability_onboarding_api_integration/common/observability_onboarding_api_supertest.ts rename to x-pack/solutions/observability/test/observability_onboarding_api_integration/common/observability_onboarding_api_supertest.ts diff --git a/x-pack/test/observability_onboarding_api_integration/common/registry.ts b/x-pack/solutions/observability/test/observability_onboarding_api_integration/common/registry.ts similarity index 100% rename from x-pack/test/observability_onboarding_api_integration/common/registry.ts rename to x-pack/solutions/observability/test/observability_onboarding_api_integration/common/registry.ts diff --git a/x-pack/test/observability_onboarding_api_integration/common/utils/expect_to_reject.ts b/x-pack/solutions/observability/test/observability_onboarding_api_integration/common/utils/expect_to_reject.ts similarity index 100% rename from x-pack/test/observability_onboarding_api_integration/common/utils/expect_to_reject.ts rename to x-pack/solutions/observability/test/observability_onboarding_api_integration/common/utils/expect_to_reject.ts diff --git a/x-pack/test/observability_onboarding_api_integration/common/utils/join_by_key.ts b/x-pack/solutions/observability/test/observability_onboarding_api_integration/common/utils/join_by_key.ts similarity index 100% rename from x-pack/test/observability_onboarding_api_integration/common/utils/join_by_key.ts rename to x-pack/solutions/observability/test/observability_onboarding_api_integration/common/utils/join_by_key.ts diff --git a/x-pack/test/observability_onboarding_api_integration/common/utils/maybe.ts b/x-pack/solutions/observability/test/observability_onboarding_api_integration/common/utils/maybe.ts similarity index 100% rename from x-pack/test/observability_onboarding_api_integration/common/utils/maybe.ts rename to x-pack/solutions/observability/test/observability_onboarding_api_integration/common/utils/maybe.ts diff --git a/x-pack/test/observability_onboarding_api_integration/configs/index.ts b/x-pack/solutions/observability/test/observability_onboarding_api_integration/configs/index.ts similarity index 100% rename from x-pack/test/observability_onboarding_api_integration/configs/index.ts rename to x-pack/solutions/observability/test/observability_onboarding_api_integration/configs/index.ts diff --git a/x-pack/test/observability_onboarding_api_integration/tests/flow/progress/progress.spec.ts b/x-pack/solutions/observability/test/observability_onboarding_api_integration/tests/flow/progress/progress.spec.ts similarity index 100% rename from x-pack/test/observability_onboarding_api_integration/tests/flow/progress/progress.spec.ts rename to x-pack/solutions/observability/test/observability_onboarding_api_integration/tests/flow/progress/progress.spec.ts diff --git a/x-pack/test/observability_onboarding_api_integration/tests/index.ts b/x-pack/solutions/observability/test/observability_onboarding_api_integration/tests/index.ts similarity index 100% rename from x-pack/test/observability_onboarding_api_integration/tests/index.ts rename to x-pack/solutions/observability/test/observability_onboarding_api_integration/tests/index.ts diff --git a/x-pack/solutions/observability/test/tsconfig.json b/x-pack/solutions/observability/test/tsconfig.json index c2acabb2a060a..fa000f06a70da 100644 --- a/x-pack/solutions/observability/test/tsconfig.json +++ b/x-pack/solutions/observability/test/tsconfig.json @@ -79,5 +79,17 @@ "@kbn/es-errors", "@kbn/content-packs-schema", "@kbn/server-route-repository-utils", + "@kbn/test-suites-src", + "@kbn/ftr-common-functional-ui-services", + "@kbn/config-schema", + "@kbn/guided-onboarding-plugin", + "@kbn/ml-string-hash", + "@kbn/test-subj-selector", + "@kbn/datemath", + "@kbn/infra-forge", + "@kbn/typed-react-router-config", + "@kbn/observability-ai-assistant-app-plugin", + "@kbn/cases-plugin", + "@kbn/dev-utils", ] } diff --git a/x-pack/test/accessibility/apps/group1/index.ts b/x-pack/test/accessibility/apps/group1/index.ts index 7b6a6d615d300..ffb6c2a9edbd8 100644 --- a/x-pack/test/accessibility/apps/group1/index.ts +++ b/x-pack/test/accessibility/apps/group1/index.ts @@ -16,7 +16,6 @@ export default ({ loadTestFile }: FtrProviderContext): void => { loadTestFile(require.resolve('./grok_debugger')); loadTestFile(require.resolve('./search_profiler')); loadTestFile(require.resolve('./painless_lab')); - loadTestFile(require.resolve('./uptime')); loadTestFile(require.resolve('./spaces')); loadTestFile(require.resolve('./advanced_settings')); loadTestFile(require.resolve('./dashboard_controls')); diff --git a/x-pack/test/accessibility/apps/group3/index.ts b/x-pack/test/accessibility/apps/group3/index.ts index d295c2a17a4f0..5acd3cc1c3029 100644 --- a/x-pack/test/accessibility/apps/group3/index.ts +++ b/x-pack/test/accessibility/apps/group3/index.ts @@ -30,6 +30,5 @@ export default ({ loadTestFile }: FtrProviderContext): void => { // loadTestFile(require.resolve('./stack_monitoring')); // loadTestFile(require.resolve('./watcher')); // loadTestFile(require.resolve('./rollup_jobs')); - // loadTestFile(require.resolve('./observability')); }); }; diff --git a/x-pack/test/api_integration/apis/slos/helper/es.ts b/x-pack/test/api_integration/apis/slos/helper/es.ts deleted file mode 100644 index 190f9b08bd9af..0000000000000 --- a/x-pack/test/api_integration/apis/slos/helper/es.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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 { Client } from '@elastic/elasticsearch'; -import { - SLI_DESTINATION_INDEX_PATTERN, - SUMMARY_DESTINATION_INDEX_PATTERN, -} from '@kbn/slo-plugin/common/constants'; - -export class SloEsClient { - constructor(private esClient: Client) {} - - public async getSLOSummaryDataById(id: string) { - return await this.esClient.search({ - index: SUMMARY_DESTINATION_INDEX_PATTERN, - query: { - bool: { - filter: [ - { - term: { 'slo.id': id }, - }, - { - term: { isTempDoc: false }, - }, - ], - }, - }, - }); - } - - public async getSLORollupDataById(id: string) { - return await this.esClient.search({ - index: SLI_DESTINATION_INDEX_PATTERN, - query: { - bool: { - filter: [ - { - term: { 'slo.id': id }, - }, - ], - }, - }, - }); - } - - public async deleteTestSourceData() { - try { - await this.esClient.deleteByQuery({ - index: 'kbn-data-forge-fake_hosts*', - query: { term: { 'system.network.name': 'eth1' } }, - }); - } catch (e) { - // eslint-disable-next-line no-console - console.warn('SLO api integration test data not found'); - } - } -} diff --git a/x-pack/test/common/lib/test_data_loader.ts b/x-pack/test/common/lib/test_data_loader.ts deleted file mode 100644 index 20796fcd8e582..0000000000000 --- a/x-pack/test/common/lib/test_data_loader.ts +++ /dev/null @@ -1,200 +0,0 @@ -/* - * 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 { LegacyUrlAlias } from '@kbn/core-saved-objects-base-server-internal'; -import { ALL_SAVED_OBJECT_INDICES } from '@kbn/core-saved-objects-server'; -import Fs from 'fs/promises'; -import { FtrProviderContext } from '../ftr_provider_context'; - -export const SPACE_1 = { - id: 'space_1', - name: 'Space 1', - description: 'This is the first test space', - disabledFeatures: [], -}; - -export const SPACE_2 = { - id: 'space_2', - name: 'Space 2', - description: 'This is the second test space', - disabledFeatures: [], -}; - -async function parseLegacyUrlAliases(path: string): Promise { - return (await Fs.readFile(path, 'utf-8')) - .split(/\r?\n\r?\n/) - .filter((line) => !!line) - .map((line) => JSON.parse(line)); -} - -// Objects can only be imported in one space at a time. To have test saved objects -// that are shared in multiple spaces we should import all objects in the "original" -// spaces first and then share them to other spaces as a subsequent operation. -const OBJECTS_TO_SHARE: Array<{ - spacesToAdd?: string[]; - spacesToRemove?: string[]; - objects: Array<{ type: string; id: string }>; -}> = [ - { - spacesToAdd: ['*'], - spacesToRemove: ['default'], - objects: [ - { type: 'sharedtype', id: 'all_spaces' }, - { type: 'sharedtype', id: 'space_2_only_matching_origin' }, - { type: 'sharedtype', id: 'alias_delete_exclusive' }, - ], - }, - { - spacesToRemove: ['default'], - spacesToAdd: [SPACE_1.id, SPACE_2.id], - objects: [{ type: 'sharedtype', id: 'space_1_and_space_2' }], - }, - { - spacesToAdd: [SPACE_1.id, SPACE_2.id], - objects: [ - { type: 'sharedtype', id: 'each_space' }, - { type: 'sharedtype', id: 'conflict_2_all' }, - { type: 'sharedtype', id: 'alias_delete_inclusive' }, - ], - }, - { - spacesToAdd: [SPACE_1.id], - objects: [ - { type: 'sharedtype', id: 'conflict_1c_default_and_space_1' }, - { type: 'sharedtype', id: 'default_and_space_1' }, - ], - }, - { - spacesToAdd: [SPACE_2.id], - objects: [{ type: 'sharedtype', id: 'default_and_space_2' }], - }, - { - spacesToAdd: [SPACE_1.id, SPACE_2.id], - objects: [{ type: 'resolvetype', id: 'conflict-newid' }], - }, -]; - -export function getTestDataLoader({ getService }: Pick) { - const spacesService = getService('spaces'); - const kbnServer = getService('kibanaServer'); - const supertest = getService('supertest'); - const log = getService('log'); - const es = getService('es'); - - return { - createFtrSpaces: async () => { - await Promise.all([await spacesService.create(SPACE_1), await spacesService.create(SPACE_2)]); - }, - - deleteFtrSpaces: async () => { - await Promise.all([spacesService.delete(SPACE_1.id), spacesService.delete(SPACE_2.id)]); - }, - - createFtrSavedObjectsData: async ( - spaceData: Array<{ spaceName: string | null; dataUrl: string }> - ) => { - log.debug('Loading test data for the following spaces: default, space_1 and space_2'); - - await Promise.all( - spaceData.map((spaceDataObj) => { - if (spaceDataObj.spaceName) { - return kbnServer.importExport.load(spaceDataObj.dataUrl, { - space: spaceDataObj.spaceName, - }); - } else { - return kbnServer.importExport.load(spaceDataObj.dataUrl); - } - }) - ); - - // Adjust spaces for the imported saved objects. - for (const { objects, spacesToAdd = [], spacesToRemove = [] } of OBJECTS_TO_SHARE) { - log.debug( - `Updating spaces for the following objects (add: [${spacesToAdd.join( - ', ' - )}], remove: [${spacesToRemove.join(', ')}]): ${objects - .map(({ type, id }) => `${type}:${id}`) - .join(', ')}` - ); - await supertest - .post('/api/spaces/_update_objects_spaces') - .send({ objects, spacesToAdd, spacesToRemove }) - .expect(200); - } - }, - - createLegacyUrlAliases: async ( - spaceData: Array<{ spaceName: string | null; dataUrl: string; disabled?: boolean }> - ) => { - await Promise.all( - spaceData.map(async (data) => { - const spaceString = data.spaceName ?? 'default'; - - const aliases = await parseLegacyUrlAliases(data.dataUrl); - log.info('creating', aliases.length, 'legacy URL aliases', { - space: spaceString, - }); - - await Promise.all( - aliases.map(async (alias) => { - await es.create({ - id: `legacy-url-alias:${spaceString}:${alias.targetType}:${alias.sourceId}`, - index: '.kibana', - refresh: 'wait_for', - document: { - type: 'legacy-url-alias', - updated_at: '2017-09-21T18:51:23.794Z', - 'legacy-url-alias': { - ...alias, - targetNamespace: spaceString, - ...(data.disabled && { disabled: data.disabled }), - }, - }, - }); - }) - ); - }) - ); - }, - - deleteFtrSavedObjectsData: async () => { - const allSpacesIds = [ - ...(await spacesService.getAll()).map((space: { id: string }) => space.id), - 'non_existent_space', - ]; - log.debug(`Removing data from the following spaces: ${allSpacesIds.join(', ')}`); - await Promise.all( - allSpacesIds.flatMap((spaceId) => [ - kbnServer.savedObjects.cleanStandardList({ space: spaceId }), - kbnServer.savedObjects.clean({ space: spaceId, types: ['sharedtype', 'isolatedtype'] }), - ]) - ); - }, - - deleteAllSavedObjectsFromKibanaIndex: async () => { - await es.deleteByQuery({ - index: ALL_SAVED_OBJECT_INDICES, - ignore_unavailable: true, - wait_for_completion: true, - conflicts: 'proceed', - query: { - bool: { - must_not: [ - { - term: { - type: { - value: 'space', - }, - }, - }, - ], - }, - }, - }); - }, - }; -} diff --git a/x-pack/test/common/utils/server_route_repository/create_admin_service_from_repository.ts b/x-pack/test/common/utils/server_route_repository/create_admin_service_from_repository.ts deleted file mode 100644 index ad2f8137f3291..0000000000000 --- a/x-pack/test/common/utils/server_route_repository/create_admin_service_from_repository.ts +++ /dev/null @@ -1,237 +0,0 @@ -/* - * 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 { - formatRequest, - ServerRouteRepository, - EndpointOf, - ReturnOf, - ClientRequestParamsOf, -} from '@kbn/server-route-repository'; -import { Subtract, RequiredKeys } from 'utility-types'; -import { format } from 'url'; -import supertest from 'supertest'; -import { - RoleScopedSupertestProvider, - SupertestWithRoleScope, -} from '@kbn/test-suites-xpack-platform/api_integration_deployment_agnostic/services/role_scoped_supertest'; -import { CustomRoleScopedSupertestProvider } from '@kbn/test-suites-xpack-platform/api_integration_deployment_agnostic/services/custom_role_scoped_supertest'; - -type MaybeOptional> = RequiredKeys extends never - ? [TArgs] | [] - : [TArgs]; - -export interface RepositorySupertestClient { - fetch: >( - endpoint: TEndpoint, - ...options: MaybeOptional< - { - type?: 'form-data'; - } & ClientRequestParamsOf - > - ) => RepositorySupertestReturnOf; - - sendFile: >( - endpoint: TEndpoint, - options: ClientRequestParamsOf & { - file: { key: string; filename: string }; - } - ) => RepositorySupertestReturnOf; -} - -type RepositorySupertestReturnOf< - TServerRouteRepository extends ServerRouteRepository, - TEndpoint extends EndpointOf -> = OverwriteThisMethods< - WithoutPromise, - Promise<{ - text: string; - status: number; - body: ReturnOf; - }> ->; - -async function getApiClient( - supertestWithRoleScoped: SupertestWithRoleScope -): Promise> { - return { - fetch: (endpoint, ...rest) => { - const options = rest.length ? rest[0] : { type: undefined }; - - const { type } = options; - - const params = 'params' in options ? (options.params as Record) : {}; - - const { method, pathname, version } = formatRequest(endpoint, params.path); - const url = format({ pathname, query: params?.query }); - - const headers: Record = { - 'kbn-xsrf': 'foo', - 'x-elastic-internal-origin': 'kibana', - }; - - if (version) { - headers['Elastic-Api-Version'] = version; - } - - let res: unknown; - if (type === 'form-data') { - const fields: Array<[string, any]> = Object.entries(params.body); - const formDataRequest = supertestWithRoleScoped[method](url) - .set(headers) - .set('Content-type', 'multipart/form-data'); - - for (const field of fields) { - void formDataRequest.field(field[0], field[1]); - } - - res = formDataRequest; - } else if (params.body) { - res = supertestWithRoleScoped[method](url).send(params.body).set(headers); - } else { - res = supertestWithRoleScoped[method](url).set(headers); - } - - return res as RepositorySupertestReturnOf< - TServerRouteRepository, - EndpointOf - >; - }, - - sendFile: (endpoint, options) => { - const params = 'params' in options ? (options.params as Record) : {}; - const { method, pathname, version } = formatRequest(endpoint, params.path); - const url = format({ pathname, query: params.query }); - - const headers: Record = { - 'kbn-xsrf': 'foo', - 'x-elastic-internal-origin': 'kibana', - }; - - if (version) { - headers['Elastic-Api-Version'] = version; - } - - const fields: Array<[string, any]> = Object.entries(params.body); - const formDataRequest = supertestWithRoleScoped[method](url) - .set(headers) - .set('Content-type', 'multipart/form-data') - .attach(options.file.key, params.body[options.file.key], { - filename: options.file.filename, - }); - - for (const field of fields.filter(([key]) => key !== options.file.key)) { - void formDataRequest.field(field[0], field[1]); - } - - return formDataRequest as RepositorySupertestReturnOf< - TServerRouteRepository, - EndpointOf - >; - }, - }; -} - -export async function getCustomRoleApiClient( - st: ReturnType -): Promise> { - const supertestWithCustomRoleScoped = await st.getSupertestWithCustomRoleScope({ - useCookieHeader: true, - withInternalHeaders: true, - }); - return await getApiClient(supertestWithCustomRoleScoped); -} - -export async function getAdminApiClient( - st: ReturnType -): Promise> { - const supertestWithRoleScoped = await st.getSupertestWithRoleScope('admin', { - useCookieHeader: true, - withInternalHeaders: true, - }); - return await getApiClient(supertestWithRoleScoped); -} - -type WithoutPromise> = Subtract>; - -// this is a little intense, but without it, method overrides are lost -// e.g., { -// end(one:string) -// end(one:string, two:string) -// } -// would lose the first signature. This keeps up to eight signatures. -type OverloadedParameters = T extends { - (...args: infer A1): any; - (...args: infer A2): any; - (...args: infer A3): any; - (...args: infer A4): any; - (...args: infer A5): any; - (...args: infer A6): any; - (...args: infer A7): any; - (...args: infer A8): any; -} - ? A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 - : T extends { - (...args: infer A1): any; - (...args: infer A2): any; - (...args: infer A3): any; - (...args: infer A4): any; - (...args: infer A5): any; - (...args: infer A6): any; - (...args: infer A7): any; - } - ? A1 | A2 | A3 | A4 | A5 | A6 | A7 - : T extends { - (...args: infer A1): any; - (...args: infer A2): any; - (...args: infer A3): any; - (...args: infer A4): any; - (...args: infer A5): any; - (...args: infer A6): any; - } - ? A1 | A2 | A3 | A4 | A5 | A6 - : T extends { - (...args: infer A1): any; - (...args: infer A2): any; - (...args: infer A3): any; - (...args: infer A4): any; - (...args: infer A5): any; - } - ? A1 | A2 | A3 | A4 | A5 - : T extends { - (...args: infer A1): any; - (...args: infer A2): any; - (...args: infer A3): any; - (...args: infer A4): any; - } - ? A1 | A2 | A3 | A4 - : T extends { - (...args: infer A1): any; - (...args: infer A2): any; - (...args: infer A3): any; - } - ? A1 | A2 | A3 - : T extends { - (...args: infer A1): any; - (...args: infer A2): any; - } - ? A1 | A2 - : T extends (...args: infer A) => any - ? A - : any; - -type OverrideReturnType any, TNextReturnType> = ( - ...args: OverloadedParameters -) => WithoutPromise> & TNextReturnType; - -type OverwriteThisMethods, TNextReturnType> = TNextReturnType & { - [key in keyof T]: T[key] extends (...args: infer TArgs) => infer TReturnType - ? TReturnType extends Promise - ? OverrideReturnType - : (...args: TArgs) => TReturnType - : T[key]; -}; diff --git a/x-pack/test/functional/config.edge.js b/x-pack/test/functional/config.edge.js deleted file mode 100644 index 58f35e844e283..0000000000000 --- a/x-pack/test/functional/config.edge.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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. - */ - -export default async function ({ readConfigFile }) { - const firefoxConfig = await readConfigFile(require.resolve('./config.firefox.js')); - - return { - ...firefoxConfig.getAll(), - - browser: { - type: 'msedge', - }, - - junit: { - reportName: 'MS Chromium Edge XPack UI Functional Tests', - }, - }; -} diff --git a/x-pack/test/functional/page_objects/index.ts b/x-pack/test/functional/page_objects/index.ts index b6f94822931df..967f284684e37 100644 --- a/x-pack/test/functional/page_objects/index.ts +++ b/x-pack/test/functional/page_objects/index.ts @@ -25,7 +25,7 @@ import { SearchSessionsPageProvider } from '@kbn/test-suites-xpack-platform/func import { GraphPageObject } from '@kbn/test-suites-xpack-platform/functional/page_objects/graph_page'; import { MaintenanceWindowsPageProvider } from '@kbn/test-suites-xpack-platform/functional/page_objects/maintenance_windows_page'; import { BannersPageObject } from '@kbn/test-suites-xpack-platform/functional/page_objects/banners_page'; -import { ApiKeysPageProvider } from './api_keys_page'; +import { NavigationalSearchPageObject } from '@kbn/test-suites-xpack-platform/functional/page_objects/navigational_search'; import { AssetDetailsProvider } from './asset_details'; import { CrossClusterReplicationPageProvider } from './cross_cluster_replication_page'; import { DetectionsPageObject } from '../../security_solution_ftr/page_objects/detections'; @@ -37,16 +37,11 @@ import { IndexManagementPageProvider } from './index_management_page'; import { InfraHomePageProvider } from './infra_home_page'; import { InfraHostsViewProvider } from './infra_hosts_view'; import { InfraLogsPageProvider } from './infra_logs_page'; -import { InfraMetricsExplorerProvider } from './infra_metrics_explorer'; -import { InfraSavedViewsProvider } from './infra_saved_views'; import { IngestPipelinesPageProvider } from './ingest_pipelines_page'; import { LicenseManagementPageProvider } from './license_management_page'; import { LogstashPageObject } from './logstash_page'; -import { NavigationalSearchPageObject } from './navigational_search'; import { ObservabilityLogsExplorerPageObject } from './observability_logs_explorer'; import { DatasetQualityPageObject } from './dataset_quality'; -import { ObservabilityPageProvider } from './observability_page'; -import { AlertControlsProvider } from './alert_controls'; import { RemoteClustersPageProvider } from './remote_clusters_page'; import { RollupPageObject } from './rollup_page'; import { ShareSavedObjectsToSpacePageProvider } from './share_saved_objects_to_space_page'; @@ -84,8 +79,6 @@ export const pageObjects = { infraHome: InfraHomePageProvider, infraHostsView: InfraHostsViewProvider, infraLogs: InfraLogsPageProvider, - infraMetricsExplorer: InfraMetricsExplorerProvider, - infraSavedViews: InfraSavedViewsProvider, ingestPipelines: IngestPipelinesPageProvider, lens: LensPageProvider, licenseManagement: LicenseManagementPageProvider, @@ -96,8 +89,6 @@ export const pageObjects = { navigationalSearch: NavigationalSearchPageObject, observabilityLogsExplorer: ObservabilityLogsExplorerPageObject, datasetQuality: DatasetQualityPageObject, - observability: ObservabilityPageProvider, - alertControls: AlertControlsProvider, remoteClusters: RemoteClustersPageProvider, reporting: ReportingPageObject, roleMappings: RoleMappingsPageProvider, diff --git a/x-pack/test/functional/services/index.ts b/x-pack/test/functional/services/index.ts index 6e7f8225d4edb..bee8eef631955 100644 --- a/x-pack/test/functional/services/index.ts +++ b/x-pack/test/functional/services/index.ts @@ -64,7 +64,6 @@ import { RandomProvider } from './random'; // @ts-ignore not ts yet import { UptimeProvider } from './uptime'; import { InfraSourceConfigurationFormProvider } from './infra_source_configuration_form'; -import { LogsUiProvider } from './logs_ui'; import { ObservabilityProvider } from './observability'; import { DataStreamProvider } from './data_stream'; import { SloUiServiceProvider } from './slo'; @@ -116,7 +115,6 @@ export const services = { userMenu: UserMenuProvider, uptime: UptimeProvider, infraSourceConfigurationForm: InfraSourceConfigurationFormProvider, - logsUi: LogsUiProvider, ml: MachineLearningProvider, transform: TransformProvider, reporting: ReportingFunctionalProvider, diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index 808a04689e932..fa50dbc544e4b 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -54,17 +54,14 @@ "@kbn/expect", "@kbn/std", "@kbn/apm-synthtrace", - "@kbn/core-saved-objects-base-server-internal", "@kbn/rule-data-utils", "@kbn/maps-plugin", "@kbn/test-subj-selector", "@kbn/rison", "@kbn/logging", - "@kbn/utility-types", "@kbn/data-views-plugin", "@kbn/datemath", "@kbn/es-archiver", - "@kbn/config-schema", "@kbn/es-query", "@kbn/session-view-plugin", "@kbn/ml-string-hash", @@ -76,27 +73,20 @@ "@kbn/security-api-integration-helpers", "@kbn/discover-plugin", "@kbn/shared-ux-file-types", - "@kbn/guided-onboarding-plugin", "@kbn/field-formats-plugin", - "@kbn/data-forge", - "@kbn/observability-shared-plugin", "@kbn/server-route-repository", "@kbn/core-http-common", "@kbn/logs-shared-plugin", - "@kbn/observability-onboarding-plugin", "@kbn/uptime-plugin", "@kbn/observability-ai-assistant-plugin", "@kbn/dataset-quality-plugin", "@kbn/io-ts-utils", "@kbn/security-plugin-types-common", "@kbn/slo-schema", - "@kbn/typed-react-router-config", "@kbn/ftr-common-functional-ui-services", "@kbn/infra-forge", "@kbn/slo-plugin", - "@kbn/observability-ai-assistant-app-plugin", "@kbn/search-types", - "@kbn/alerting-comparators", "@kbn/data-quality-plugin", "@kbn/openapi-common", "@kbn/securitysolution-lists-common", @@ -111,7 +101,6 @@ "@kbn/scout-info", "@kbn/inference-common", "@kbn/apm-sources-access-plugin", - "@kbn/test-suites-xpack-observability", "@kbn/test-suites-xpack-platform", "@kbn/core-chrome-browser", "@kbn/test-suites-xpack-platform", diff --git a/x-pack/test_serverless/functional/page_objects/svl_common_navigation.ts b/x-pack/test_serverless/functional/page_objects/svl_common_navigation.ts index 72c98a41b85f7..edb41dc72485b 100644 --- a/x-pack/test_serverless/functional/page_objects/svl_common_navigation.ts +++ b/x-pack/test_serverless/functional/page_objects/svl_common_navigation.ts @@ -7,7 +7,7 @@ import { SolutionNavigationProvider } from '@kbn/test-suites-src/functional/page_objects'; -import { NavigationalSearchPageObject } from '@kbn/test-suites-xpack/functional/page_objects/navigational_search'; +import { NavigationalSearchPageObject } from '@kbn/test-suites-xpack-platform/functional/page_objects/navigational_search'; import type { FtrProviderContext } from '../ftr_provider_context'; export function SvlCommonNavigationProvider(ctx: FtrProviderContext) {