From 9bd5789f887943e9606e39a6935c6b38abdc0b09 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 9 Oct 2024 03:50:36 +1100 Subject: [PATCH] [8.x] [Search][Onboarding] Default home to Global Empty State (#195142) (#195431) # Backport This will backport the following commits from `main` to `8.x`: - [[Search][Onboarding] Default home to Global Empty State (#195142)](https://github.com/elastic/kibana/pull/195142) ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) Co-authored-by: Rodney Norris --- packages/deeplinks/search/constants.ts | 2 + packages/deeplinks/search/deep_links.ts | 8 +- x-pack/plugins/search_indices/common/index.ts | 4 + .../public/components/start/create_index.tsx | 33 ++++---- .../components/start/elasticsearch_start.tsx | 2 - .../start/hooks/use_indices_redirect.tsx | 25 +++++- .../plugins/search_indices/public/plugin.ts | 18 +++-- .../plugins/search_indices/public/routes.ts | 3 + x-pack/plugins/search_indices/public/types.ts | 13 ++- x-pack/plugins/search_indices/tsconfig.json | 4 +- .../public/navigation_tree.ts | 33 +++++++- .../serverless_search/public/plugin.ts | 37 +++++++-- .../plugins/serverless_search/public/types.ts | 6 ++ .../plugins/serverless_search/tsconfig.json | 1 + .../test_serverless/functional/config.base.ts | 1 + .../services/svl_search_navigation.ts | 14 +++- .../search/config.feature_flags.ts | 11 +++ .../functional/test_suites/search/config.ts | 11 +++ .../test_suites/search/elasticsearch_start.ts | 79 ++++++++++--------- .../{landing_page.ts => getting_started.ts} | 8 +- .../test_suites/search/index.feature_flags.ts | 1 + .../functional/test_suites/search/index.ts | 2 +- .../test_suites/search/search_index_detail.ts | 3 +- x-pack/test_serverless/shared/types/index.ts | 1 + 24 files changed, 236 insertions(+), 84 deletions(-) rename x-pack/test_serverless/functional/test_suites/search/{landing_page.ts => getting_started.ts} (95%) diff --git a/packages/deeplinks/search/constants.ts b/packages/deeplinks/search/constants.ts index 76a9834d061e..c4a598145c87 100644 --- a/packages/deeplinks/search/constants.ts +++ b/packages/deeplinks/search/constants.ts @@ -19,3 +19,5 @@ export const SERVERLESS_ES_CONNECTORS_ID = 'serverlessConnectors'; export const SERVERLESS_ES_SEARCH_PLAYGROUND_ID = 'searchPlayground'; export const SERVERLESS_ES_SEARCH_INFERENCE_ENDPOINTS_ID = 'searchInferenceEndpoints'; export const SEARCH_HOMEPAGE = 'searchHomepage'; +export const SEARCH_INDICES_START = 'elasticsearchStart'; +export const SEARCH_INDICES = 'elasticsearchIndices'; diff --git a/packages/deeplinks/search/deep_links.ts b/packages/deeplinks/search/deep_links.ts index 6d42b5603f21..98703f18ac3f 100644 --- a/packages/deeplinks/search/deep_links.ts +++ b/packages/deeplinks/search/deep_links.ts @@ -20,6 +20,8 @@ import { SERVERLESS_ES_SEARCH_PLAYGROUND_ID, SERVERLESS_ES_SEARCH_INFERENCE_ENDPOINTS_ID, SEARCH_HOMEPAGE, + SEARCH_INDICES_START, + SEARCH_INDICES, } from './constants'; export type EnterpriseSearchApp = typeof ENTERPRISE_SEARCH_APP_ID; @@ -34,6 +36,8 @@ export type ConnectorsId = typeof SERVERLESS_ES_CONNECTORS_ID; export type SearchPlaygroundId = typeof SERVERLESS_ES_SEARCH_PLAYGROUND_ID; export type SearchInferenceEndpointsId = typeof SERVERLESS_ES_SEARCH_INFERENCE_ENDPOINTS_ID; export type SearchHomepage = typeof SEARCH_HOMEPAGE; +export type SearchStart = typeof SEARCH_INDICES_START; +export type SearchIndices = typeof SEARCH_INDICES; export type ContentLinkId = 'searchIndices' | 'connectors' | 'webCrawlers'; @@ -59,4 +63,6 @@ export type DeepLinkId = | `${EnterpriseSearchContentApp}:${ContentLinkId}` | `${EnterpriseSearchApplicationsApp}:${ApplicationsLinkId}` | `${EnterpriseSearchAppsearchApp}:${AppsearchLinkId}` - | `${EnterpriseSearchRelevanceApp}:${RelevanceLinkId}`; + | `${EnterpriseSearchRelevanceApp}:${RelevanceLinkId}` + | SearchStart + | SearchIndices; diff --git a/x-pack/plugins/search_indices/common/index.ts b/x-pack/plugins/search_indices/common/index.ts index f2b3e62577e4..e640397e3936 100644 --- a/x-pack/plugins/search_indices/common/index.ts +++ b/x-pack/plugins/search_indices/common/index.ts @@ -5,7 +5,11 @@ * 2.0. */ +import type { SearchIndices, SearchStart } from '@kbn/deeplinks-search/deep_links'; + export const PLUGIN_ID = 'searchIndices'; export const PLUGIN_NAME = 'searchIndices'; +export const START_APP_ID: SearchStart = 'elasticsearchStart'; +export const INDICES_APP_ID: SearchIndices = 'elasticsearchIndices'; export type { IndicesStatusResponse, UserStartPrivilegesResponse } from './types'; diff --git a/x-pack/plugins/search_indices/public/components/start/create_index.tsx b/x-pack/plugins/search_indices/public/components/start/create_index.tsx index bd80922d7968..f1392b3d3381 100644 --- a/x-pack/plugins/search_indices/public/components/start/create_index.tsx +++ b/x-pack/plugins/search_indices/public/components/start/create_index.tsx @@ -56,13 +56,17 @@ export const CreateIndexForm = ({ const [indexNameHasError, setIndexNameHasError] = useState(false); const usageTracker = useUsageTracker(); const { createIndex, isLoading } = useCreateIndex(); - const onCreateIndex = useCallback(() => { - if (!isValidIndexName(formState.indexName)) { - return; - } - usageTracker.click(AnalyticsEvents.startCreateIndexClick); - createIndex({ indexName: formState.indexName }); - }, [usageTracker, createIndex, formState.indexName]); + const onCreateIndex = useCallback( + (e: React.FormEvent) => { + e.preventDefault(); + if (!isValidIndexName(formState.indexName)) { + return; + } + usageTracker.click(AnalyticsEvents.startCreateIndexClick); + createIndex({ indexName: formState.indexName }); + }, + [usageTracker, createIndex, formState.indexName] + ); const onIndexNameChange = (e: React.ChangeEvent) => { const newIndexName = e.target.value; setFormState({ ...formState, indexName: e.target.value }); @@ -78,7 +82,12 @@ export const CreateIndexForm = ({ return ( <> - + {CREATE_INDEX_CONTENT} @@ -181,11 +188,7 @@ export const CreateIndexForm = ({ defaultMessage="Already have some data? {link}" values={{ link: ( - + {i18n.translate( 'xpack.searchIndices.startPage.createIndex.fileUpload.link', { diff --git a/x-pack/plugins/search_indices/public/components/start/elasticsearch_start.tsx b/x-pack/plugins/search_indices/public/components/start/elasticsearch_start.tsx index 00bc11674684..8bc8d5fcd7ea 100644 --- a/x-pack/plugins/search_indices/public/components/start/elasticsearch_start.tsx +++ b/x-pack/plugins/search_indices/public/components/start/elasticsearch_start.tsx @@ -221,7 +221,6 @@ export const ElasticsearchStart = ({ userPrivileges }: ElasticsearchStartProps) iconSide="right" iconType="popout" data-test-subj="analyzeLogsBtn" - data-telemetry-id="searchIndicesStartCollectLogsLink" href={docLinks.analyzeLogs} target="_blank" > @@ -249,7 +248,6 @@ export const ElasticsearchStart = ({ userPrivileges }: ElasticsearchStartProps) iconSide="right" iconType="popout" data-test-subj="startO11yTrialBtn" - data-telemetry-id="searchIndicesStartO11yTrialLink" href={o11yTrialLink} target="_blank" > diff --git a/x-pack/plugins/search_indices/public/components/start/hooks/use_indices_redirect.tsx b/x-pack/plugins/search_indices/public/components/start/hooks/use_indices_redirect.tsx index d7a24a6e102d..86fdf75a1d08 100644 --- a/x-pack/plugins/search_indices/public/components/start/hooks/use_indices_redirect.tsx +++ b/x-pack/plugins/search_indices/public/components/start/hooks/use_indices_redirect.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { useEffect } from 'react'; +import { useEffect, useState } from 'react'; import type { IndicesStatusResponse } from '../../../../common'; @@ -15,13 +15,30 @@ import { navigateToIndexDetails } from './utils'; export const useIndicesRedirect = (indicesStatus?: IndicesStatusResponse) => { const { application, http } = useKibana().services; + const [lastStatus, setLastStatus] = useState(() => undefined); + const [hasDoneRedirect, setHasDoneRedirect] = useState(() => false); return useEffect(() => { - if (!indicesStatus) return; - if (indicesStatus.indexNames.length === 0) return; + if (hasDoneRedirect) { + return; + } + if (!indicesStatus) { + return; + } + if (indicesStatus.indexNames.length === 0) { + setLastStatus(indicesStatus); + return; + } + if (lastStatus === undefined && indicesStatus.indexNames.length > 0) { + application.navigateToApp('management', { deepLinkId: 'index_management' }); + setHasDoneRedirect(true); + return; + } if (indicesStatus.indexNames.length === 1) { navigateToIndexDetails(application, http, indicesStatus.indexNames[0]); + setHasDoneRedirect(true); return; } application.navigateToApp('management', { deepLinkId: 'index_management' }); - }, [application, http, indicesStatus]); + setHasDoneRedirect(true); + }, [application, http, indicesStatus, lastStatus, hasDoneRedirect]); }; diff --git a/x-pack/plugins/search_indices/public/plugin.ts b/x-pack/plugins/search_indices/public/plugin.ts index bec4f7cb7bfe..39c3151cf761 100644 --- a/x-pack/plugins/search_indices/public/plugin.ts +++ b/x-pack/plugins/search_indices/public/plugin.ts @@ -16,6 +16,8 @@ import type { SearchIndicesServicesContextDeps, } from './types'; import { initQueryClient } from './services/query_client'; +import { INDICES_APP_ID, START_APP_ID } from '../common'; +import { INDICES_APP_BASE, START_APP_BASE } from './routes'; export class SearchIndicesPlugin implements Plugin @@ -26,8 +28,8 @@ export class SearchIndicesPlugin const queryClient = initQueryClient(core.notifications.toasts); core.application.register({ - id: 'elasticsearchStart', - appRoute: '/app/elasticsearch/start', + id: START_APP_ID, + appRoute: START_APP_BASE, title: i18n.translate('xpack.searchIndices.elasticsearchStart.startAppTitle', { defaultMessage: 'Elasticsearch Start', }), @@ -43,8 +45,8 @@ export class SearchIndicesPlugin }, }); core.application.register({ - id: 'elasticsearchIndices', - appRoute: '/app/elasticsearch/indices', + id: INDICES_APP_ID, + appRoute: INDICES_APP_BASE, title: i18n.translate('xpack.searchIndices.elasticsearchIndices.startAppTitle', { defaultMessage: 'Elasticsearch Indices', }), @@ -62,12 +64,18 @@ export class SearchIndicesPlugin return { enabled: true, + startAppId: START_APP_ID, + startRoute: START_APP_BASE, }; } public start(core: CoreStart): SearchIndicesPluginStart { docLinks.setDocLinks(core.docLinks.links); - return {}; + return { + enabled: true, + startAppId: START_APP_ID, + startRoute: START_APP_BASE, + }; } public stop() {} diff --git a/x-pack/plugins/search_indices/public/routes.ts b/x-pack/plugins/search_indices/public/routes.ts index 9afa04638557..c72e84c66a7d 100644 --- a/x-pack/plugins/search_indices/public/routes.ts +++ b/x-pack/plugins/search_indices/public/routes.ts @@ -13,3 +13,6 @@ export enum SearchIndexDetailsTabs { MAPPINGS = 'mappings', SETTINGS = 'settings', } + +export const START_APP_BASE = '/app/elasticsearch/start'; +export const INDICES_APP_BASE = '/app/elasticsearch/indices'; diff --git a/x-pack/plugins/search_indices/public/types.ts b/x-pack/plugins/search_indices/public/types.ts index a3e63df2642b..ebefaf10cb6e 100644 --- a/x-pack/plugins/search_indices/public/types.ts +++ b/x-pack/plugins/search_indices/public/types.ts @@ -15,13 +15,20 @@ import type { MappingProperty, MappingPropertyBase, } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { IndexManagementPluginStart } from '@kbn/index-management-shared-types'; +import type { IndexManagementPluginStart } from '@kbn/index-management-shared-types'; +import type { AppDeepLinkId } from '@kbn/core-chrome-browser'; export interface SearchIndicesPluginSetup { enabled: boolean; + startAppId: string; + startRoute: string; +} + +export interface SearchIndicesPluginStart { + enabled: boolean; + startAppId: AppDeepLinkId; + startRoute: string; } -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface SearchIndicesPluginStart {} export interface AppPluginStartDependencies { navigation: NavigationPublicPluginStart; diff --git a/x-pack/plugins/search_indices/tsconfig.json b/x-pack/plugins/search_indices/tsconfig.json index a564b87c7f6e..dfd73633b3c3 100644 --- a/x-pack/plugins/search_indices/tsconfig.json +++ b/x-pack/plugins/search_indices/tsconfig.json @@ -36,7 +36,9 @@ "@kbn/es-types", "@kbn/search-api-keys-server", "@kbn/search-api-keys-components", - "@kbn/search-shared-ui" + "@kbn/search-shared-ui", + "@kbn/deeplinks-search", + "@kbn/core-chrome-browser" ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/serverless_search/public/navigation_tree.ts b/x-pack/plugins/serverless_search/public/navigation_tree.ts index 572aa4ea2e76..1b3b980ec9fa 100644 --- a/x-pack/plugins/serverless_search/public/navigation_tree.ts +++ b/x-pack/plugins/serverless_search/public/navigation_tree.ts @@ -5,11 +5,27 @@ * 2.0. */ -import type { NavigationTreeDefinition } from '@kbn/core-chrome-browser'; +import type { + AppDeepLinkId, + NavigationTreeDefinition, + NodeDefinition, +} from '@kbn/core-chrome-browser'; import { i18n } from '@kbn/i18n'; import { CONNECTORS_LABEL } from '../common/i18n_string'; -export const navigationTree = (): NavigationTreeDefinition => ({ +const gettingStartedItem: NodeDefinition = { + id: 'gettingStarted', + title: i18n.translate('xpack.serverlessSearch.nav.gettingStarted', { + defaultMessage: 'Getting Started', + }), + link: 'serverlessElasticsearch', + spaceBefore: 'm', +}; + +export const navigationTree = ( + homeLink: AppDeepLinkId = 'serverlessElasticsearch' as AppDeepLinkId, + showGettingStarted: boolean +): NavigationTreeDefinition => ({ body: [ { type: 'navGroup', @@ -25,7 +41,7 @@ export const navigationTree = (): NavigationTreeDefinition => ({ title: i18n.translate('xpack.serverlessSearch.nav.home', { defaultMessage: 'Home', }), - link: 'serverlessElasticsearch', + link: homeLink, spaceBefore: 'm', }, { @@ -70,6 +86,16 @@ export const navigationTree = (): NavigationTreeDefinition => ({ link: 'management:index_management', breadcrumbStatus: 'hidden' /* management sub-pages set their breadcrumbs themselves */, + getIsActive: ({ pathNameSerialized, prepend }) => { + return ( + pathNameSerialized.startsWith( + prepend('/app/management/data/index_management/') + ) || + pathNameSerialized.startsWith( + prepend('/app/elasticsearch/indices/index_details/') + ) + ); + }, }, { title: CONNECTORS_LABEL, @@ -112,6 +138,7 @@ export const navigationTree = (): NavigationTreeDefinition => ({ }, ], }, + ...(showGettingStarted ? [gettingStartedItem] : []), ], }, ], diff --git a/x-pack/plugins/serverless_search/public/plugin.ts b/x-pack/plugins/serverless_search/public/plugin.ts index 66daece706ea..211a1cb2384d 100644 --- a/x-pack/plugins/serverless_search/public/plugin.ts +++ b/x-pack/plugins/serverless_search/public/plugin.ts @@ -73,6 +73,10 @@ export class ServerlessSearchPlugin const homeTitle = i18n.translate('xpack.serverlessSearch.app.home.title', { defaultMessage: 'Home', }); + const useGlobalEmptyState = setupDeps.searchIndices?.enabled ?? false; + const serverlessElasticsearchAppRoute = useGlobalEmptyState + ? '/app/elasticsearch/getting_started' + : '/app/elasticsearch'; core.application.register({ id: 'serverlessElasticsearch', @@ -81,7 +85,7 @@ export class ServerlessSearchPlugin }), euiIconType: 'logoElastic', category: DEFAULT_APP_CATEGORIES.enterpriseSearch, - appRoute: '/app/elasticsearch', + appRoute: serverlessElasticsearchAppRoute, async mount({ element, history }: AppMountParameters) { const { renderApp } = await import('./application/elasticsearch'); const [coreStart, services] = await core.getStartServices(); @@ -120,6 +124,24 @@ export class ServerlessSearchPlugin }, }); + if (useGlobalEmptyState) { + const redirectApp = setupDeps.searchIndices!.startAppId; + core.application.register({ + id: 'serverlessHomeRedirect', + title: homeTitle, + appRoute: '/app/elasticsearch', + euiIconType: 'logoElastic', + category: DEFAULT_APP_CATEGORIES.enterpriseSearch, + visibleIn: [], + async mount({}: AppMountParameters) { + const [coreStart] = await core.getStartServices(); + coreStart.chrome.docTitle.change(homeTitle); + coreStart.application.navigateToApp(redirectApp); + return () => {}; + }, + }); + } + setupDeps.discover.showInlineTopNav(); return {}; @@ -130,10 +152,15 @@ export class ServerlessSearchPlugin services: ServerlessSearchPluginStartDependencies ): ServerlessSearchPluginStart { const { serverless, management, indexManagement, security } = services; - - serverless.setProjectHome('/app/elasticsearch'); - - const navigationTree$ = of(navigationTree()); + const useGlobalEmptyState = services.searchIndices?.enabled ?? false; + const homeRoute = useGlobalEmptyState + ? services.searchIndices!.startRoute + : '/app/elasticsearch'; + serverless.setProjectHome(homeRoute); + + const navigationTree$ = of( + navigationTree(services.searchIndices?.startAppId, useGlobalEmptyState) + ); serverless.initNavigation('search', navigationTree$, { dataTestSubj: 'svlSearchSideNav' }); const extendCardNavDefinitions = serverless.getNavigationCards( diff --git a/x-pack/plugins/serverless_search/public/types.ts b/x-pack/plugins/serverless_search/public/types.ts index 7067851bc019..65952c963a2a 100644 --- a/x-pack/plugins/serverless_search/public/types.ts +++ b/x-pack/plugins/serverless_search/public/types.ts @@ -15,6 +15,10 @@ import type { ServerlessPluginSetup, ServerlessPluginStart } from '@kbn/serverle import type { SharePluginStart } from '@kbn/share-plugin/public'; import type { IndexManagementPluginStart } from '@kbn/index-management-plugin/public'; import type { DiscoverSetup } from '@kbn/discover-plugin/public'; +import type { + SearchIndicesPluginSetup, + SearchIndicesPluginStart, +} from '@kbn/search-indices/public'; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface ServerlessSearchPluginSetup {} @@ -27,6 +31,7 @@ export interface ServerlessSearchPluginSetupDependencies { management: ManagementSetup; serverless: ServerlessPluginSetup; discover: DiscoverSetup; + searchIndices?: SearchIndicesPluginSetup; } export interface ServerlessSearchPluginStartDependencies { @@ -39,4 +44,5 @@ export interface ServerlessSearchPluginStartDependencies { serverless: ServerlessPluginStart; share: SharePluginStart; indexManagement?: IndexManagementPluginStart; + searchIndices?: SearchIndicesPluginStart; } diff --git a/x-pack/plugins/serverless_search/tsconfig.json b/x-pack/plugins/serverless_search/tsconfig.json index c856b155acc7..cc3b7b073dce 100644 --- a/x-pack/plugins/serverless_search/tsconfig.json +++ b/x-pack/plugins/serverless_search/tsconfig.json @@ -51,5 +51,6 @@ "@kbn/security-api-key-management", "@kbn/search-inference-endpoints", "@kbn/security-plugin-types-common", + "@kbn/search-indices", ] } diff --git a/x-pack/test_serverless/functional/config.base.ts b/x-pack/test_serverless/functional/config.base.ts index 826b8bce0388..963be692d58e 100644 --- a/x-pack/test_serverless/functional/config.base.ts +++ b/x-pack/test_serverless/functional/config.base.ts @@ -116,6 +116,7 @@ export function createTestConfig(options: CreateTestConfigOptions) { integrations: { pathname: '/app/integrations', }, + ...(options.apps ?? {}), }, // choose where screenshots should be saved screenshots: { diff --git a/x-pack/test_serverless/functional/services/svl_search_navigation.ts b/x-pack/test_serverless/functional/services/svl_search_navigation.ts index 9de765cabd6b..cf91aac11277 100644 --- a/x-pack/test_serverless/functional/services/svl_search_navigation.ts +++ b/x-pack/test_serverless/functional/services/svl_search_navigation.ts @@ -22,12 +22,20 @@ export function SvlSearchNavigationServiceProvider({ await testSubjects.existOrFail('svlSearchOverviewPage', { timeout: 2000 }); }); }, - async navigateToElasticsearchStartPage() { + async navigateToGettingStartedPage() { await retry.tryForTime(60 * 1000, async () => { - await PageObjects.common.navigateToApp('elasticsearch/start', { + await PageObjects.common.navigateToApp('serverlessElasticsearch'); + await testSubjects.existOrFail('svlSearchOverviewPage', { timeout: 2000 }); + }); + }, + async navigateToElasticsearchStartPage(expectRedirect: boolean = false) { + await retry.tryForTime(60 * 1000, async () => { + await PageObjects.common.navigateToApp('elasticsearchStart', { shouldLoginIfPrompted: false, }); - await testSubjects.existOrFail('elasticsearchStartPage', { timeout: 2000 }); + if (!expectRedirect) { + await testSubjects.existOrFail('elasticsearchStartPage', { timeout: 2000 }); + } }); }, async navigateToIndexDetailPage(indexName: string) { diff --git a/x-pack/test_serverless/functional/test_suites/search/config.feature_flags.ts b/x-pack/test_serverless/functional/test_suites/search/config.feature_flags.ts index 824d14528225..ebd539fd34f4 100644 --- a/x-pack/test_serverless/functional/test_suites/search/config.feature_flags.ts +++ b/x-pack/test_serverless/functional/test_suites/search/config.feature_flags.ts @@ -34,4 +34,15 @@ export default createTestConfig({ // include settings from project controller // https://github.com/elastic/project-controller/blob/main/internal/project/esproject/config/elasticsearch.yml esServerArgs: ['xpack.security.authc.native_roles.enabled=true'], + apps: { + serverlessElasticsearch: { + pathname: '/app/elasticsearch/getting_started', + }, + elasticsearchStart: { + pathname: '/app/elasticsearch/start', + }, + elasticsearchIndices: { + pathname: '/app/elasticsearch/indices', + }, + }, }); diff --git a/x-pack/test_serverless/functional/test_suites/search/config.ts b/x-pack/test_serverless/functional/test_suites/search/config.ts index 4739cde53bf8..678adecd4bff 100644 --- a/x-pack/test_serverless/functional/test_suites/search/config.ts +++ b/x-pack/test_serverless/functional/test_suites/search/config.ts @@ -24,4 +24,15 @@ export default createTestConfig({ `--xpack.cloud.base_url=https://fake-cloud.elastic.co`, `--xpack.cloud.projects_url=/projects/`, ], + apps: { + serverlessElasticsearch: { + pathname: '/app/elasticsearch', + }, + serverlessConnectors: { + pathname: '/app/connectors', + }, + searchPlayground: { + pathname: '/app/search_playground', + }, + }, }); diff --git a/x-pack/test_serverless/functional/test_suites/search/elasticsearch_start.ts b/x-pack/test_serverless/functional/test_suites/search/elasticsearch_start.ts index 25b9c0e93ff7..d9d4389d4d63 100644 --- a/x-pack/test_serverless/functional/test_suites/search/elasticsearch_start.ts +++ b/x-pack/test_serverless/functional/test_suites/search/elasticsearch_start.ts @@ -76,6 +76,12 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await es.indices.create({ index: 'test-my-index-002' }); await pageObjects.svlSearchElasticsearchStartPage.expectToBeOnIndexListPage(); }); + it('should redirect to indices list if single index exist on page load', async () => { + await svlSearchNavigation.navigateToGettingStartedPage(); + await es.indices.create({ index: 'test-my-index-001' }); + await svlSearchNavigation.navigateToElasticsearchStartPage(true); + await pageObjects.svlSearchElasticsearchStartPage.expectToBeOnIndexListPage(); + }); it('should support switching between UI and Code Views', async () => { await pageObjects.svlSearchElasticsearchStartPage.expectToBeOnStartPage(); @@ -86,7 +92,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await pageObjects.svlSearchElasticsearchStartPage.expectCreateIndexUIView(); }); - it('should show the api key in code view', async () => { + // Failing: See https://github.com/elastic/kibana/issues/194673 + it.skip('should show the api key in code view', async () => { await pageObjects.svlSearchElasticsearchStartPage.expectToBeOnStartPage(); await pageObjects.svlSearchElasticsearchStartPage.clickCodeViewButton(); await pageObjects.svlApiKeys.expectAPIKeyAvailable(); @@ -124,7 +131,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await pageObjects.svlApiKeys.expectAPIKeyAvailable(); }); - it('Same API Key should be present on start page and index detail view', async () => { + // Failing: See https://github.com/elastic/kibana/issues/194673 + it.skip('Same API Key should be present on start page and index detail view', async () => { await pageObjects.svlSearchElasticsearchStartPage.clickCodeViewButton(); await pageObjects.svlApiKeys.expectAPIKeyAvailable(); const apiKeyUI = await pageObjects.svlApiKeys.getAPIKeyFromUI(); @@ -150,41 +158,40 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await pageObjects.svlSearchElasticsearchStartPage.expectAnalyzeLogsLink(); await pageObjects.svlSearchElasticsearchStartPage.expectO11yTrialLink(); }); + }); + describe('viewer', function () { + before(async () => { + await pageObjects.svlCommonPage.loginAsViewer(); + await deleteAllTestIndices(); + }); + beforeEach(async () => { + await svlSearchNavigation.navigateToElasticsearchStartPage(); + }); + after(async () => { + await deleteAllTestIndices(); + }); + + it('should default to code view when lacking create index permissions', async () => { + await pageObjects.svlSearchElasticsearchStartPage.expectToBeOnStartPage(); + await pageObjects.svlSearchElasticsearchStartPage.expectCreateIndexCodeView(); + await pageObjects.svlSearchElasticsearchStartPage.clickUIViewButton(); + await pageObjects.svlSearchElasticsearchStartPage.expectCreateIndexUIView(); + await pageObjects.svlSearchElasticsearchStartPage.expectCreateIndexButtonToBeDisabled(); + }); + + it('should not create an API key if the user only has viewer permissions', async () => { + await pageObjects.svlSearchElasticsearchStartPage.expectToBeOnStartPage(); + await pageObjects.svlSearchElasticsearchStartPage.clickCodeViewButton(); + await pageObjects.svlSearchElasticsearchStartPage.expectAPIKeyFormNotAvailable(); + const apiKey = await pageObjects.svlApiKeys.getAPIKeyFromSessionStorage(); + expect(apiKey).to.be(null); + }); - describe('viewer', function () { - before(async () => { - await pageObjects.svlCommonPage.loginAsViewer(); - await deleteAllTestIndices(); - }); - beforeEach(async () => { - await svlSearchNavigation.navigateToElasticsearchStartPage(); - }); - after(async () => { - await deleteAllTestIndices(); - }); - - it('should default to code view when lacking create index permissions', async () => { - await pageObjects.svlSearchElasticsearchStartPage.expectToBeOnStartPage(); - await pageObjects.svlSearchElasticsearchStartPage.expectCreateIndexCodeView(); - await pageObjects.svlSearchElasticsearchStartPage.clickUIViewButton(); - await pageObjects.svlSearchElasticsearchStartPage.expectCreateIndexUIView(); - await pageObjects.svlSearchElasticsearchStartPage.expectCreateIndexButtonToBeDisabled(); - }); - - it('should not create an API key if the user only has viewer permissions', async () => { - await pageObjects.svlSearchElasticsearchStartPage.expectToBeOnStartPage(); - await pageObjects.svlSearchElasticsearchStartPage.clickCodeViewButton(); - await pageObjects.svlSearchElasticsearchStartPage.expectAPIKeyFormNotAvailable(); - const apiKey = await pageObjects.svlApiKeys.getAPIKeyFromSessionStorage(); - expect(apiKey).to.be(null); - }); - - it('should redirect to index details when index is created via API', async () => { - await pageObjects.svlSearchElasticsearchStartPage.expectToBeOnStartPage(); - await pageObjects.svlSearchElasticsearchStartPage.expectCreateIndexCodeView(); - await es.indices.create({ index: 'test-my-api-index' }); - await pageObjects.svlSearchElasticsearchStartPage.expectToBeOnIndexDetailsPage(); - }); + it('should redirect to index details when index is created via API', async () => { + await pageObjects.svlSearchElasticsearchStartPage.expectToBeOnStartPage(); + await pageObjects.svlSearchElasticsearchStartPage.expectCreateIndexCodeView(); + await es.indices.create({ index: 'test-my-api-index' }); + await pageObjects.svlSearchElasticsearchStartPage.expectToBeOnIndexDetailsPage(); }); }); }); diff --git a/x-pack/test_serverless/functional/test_suites/search/landing_page.ts b/x-pack/test_serverless/functional/test_suites/search/getting_started.ts similarity index 95% rename from x-pack/test_serverless/functional/test_suites/search/landing_page.ts rename to x-pack/test_serverless/functional/test_suites/search/getting_started.ts index 643d163bf767..f521a03ccde8 100644 --- a/x-pack/test_serverless/functional/test_suites/search/landing_page.ts +++ b/x-pack/test_serverless/functional/test_suites/search/getting_started.ts @@ -13,13 +13,13 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const pageObjects = getPageObjects(['svlSearchLandingPage', 'svlCommonPage', 'embeddedConsole']); const svlSearchNavigation = getService('svlSearchNavigation'); - describe('landing page', function () { + describe('getting started', function () { before(async () => { await pageObjects.svlCommonPage.loginAsViewer(); }); it('has serverless side nav', async () => { - await svlSearchNavigation.navigateToLandingPage(); + await svlSearchNavigation.navigateToGettingStartedPage(); await pageObjects.svlSearchLandingPage.assertSvlSearchSideNavExists(); }); @@ -44,7 +44,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { describe('API Key creation', () => { beforeEach(async () => { // We need to reload the page between api key creations - await svlSearchNavigation.navigateToLandingPage(); + await svlSearchNavigation.navigateToGettingStartedPage(); }); it('can create an API key that expires', async () => { @@ -86,7 +86,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { describe('Pipelines', () => { beforeEach(async () => { - await svlSearchNavigation.navigateToLandingPage(); + await svlSearchNavigation.navigateToGettingStartedPage(); }); it('can redirect to the pipeline creation index page', async () => { await pageObjects.svlSearchLandingPage.pipeline.createPipeline(); diff --git a/x-pack/test_serverless/functional/test_suites/search/index.feature_flags.ts b/x-pack/test_serverless/functional/test_suites/search/index.feature_flags.ts index c5c9b82dd21c..db9df2e8d913 100644 --- a/x-pack/test_serverless/functional/test_suites/search/index.feature_flags.ts +++ b/x-pack/test_serverless/functional/test_suites/search/index.feature_flags.ts @@ -12,6 +12,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { // add tests that require feature flags, defined in config.feature_flags.ts loadTestFile(require.resolve('./elasticsearch_start.ts')); loadTestFile(require.resolve('./search_index_detail.ts')); + loadTestFile(require.resolve('./getting_started')); loadTestFile(require.resolve('../common/platform_security/navigation/management_nav_cards.ts')); loadTestFile(require.resolve('../common/platform_security/roles.ts')); loadTestFile(require.resolve('../common/spaces/multiple_spaces_enabled.ts')); diff --git a/x-pack/test_serverless/functional/test_suites/search/index.ts b/x-pack/test_serverless/functional/test_suites/search/index.ts index bc2056268f8b..250f99d13a3a 100644 --- a/x-pack/test_serverless/functional/test_suites/search/index.ts +++ b/x-pack/test_serverless/functional/test_suites/search/index.ts @@ -11,7 +11,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { describe('serverless search UI', function () { this.tags(['esGate']); - loadTestFile(require.resolve('./landing_page')); + loadTestFile(require.resolve('./getting_started')); loadTestFile(require.resolve('./connectors/connectors_overview')); loadTestFile(require.resolve('./default_dataview')); loadTestFile(require.resolve('./navigation')); diff --git a/x-pack/test_serverless/functional/test_suites/search/search_index_detail.ts b/x-pack/test_serverless/functional/test_suites/search/search_index_detail.ts index db855e9522f9..0f1ee8334e20 100644 --- a/x-pack/test_serverless/functional/test_suites/search/search_index_detail.ts +++ b/x-pack/test_serverless/functional/test_suites/search/search_index_detail.ts @@ -84,7 +84,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await pageObjects.embeddedConsole.clickEmbeddedConsoleControlBar(); }); - it('should show api key', async () => { + // Failing: See https://github.com/elastic/kibana/issues/194673 + it.skip('should show api key', async () => { await pageObjects.svlApiKeys.expectAPIKeyAvailable(); const apiKey = await pageObjects.svlApiKeys.getAPIKeyFromUI(); await pageObjects.svlSearchIndexDetailPage.expectAPIKeyToBeVisibleInCodeBlock(apiKey); diff --git a/x-pack/test_serverless/shared/types/index.ts b/x-pack/test_serverless/shared/types/index.ts index e07c649d86cb..2545bc0d3053 100644 --- a/x-pack/test_serverless/shared/types/index.ts +++ b/x-pack/test_serverless/shared/types/index.ts @@ -16,4 +16,5 @@ export interface CreateTestConfigOptions { junit: { reportName: string }; suiteTags?: { include?: string[]; exclude?: string[] }; services?: InheritedServices; + apps?: Record; }