[Search][ES3] GA Navigation (#195661)

## Summary

Updating the Serverless Search side navigation for GA and aligning as
closely as possible with the Search Solution navigation that is
available going forward in stateful releases.

Additionally expanded the serverless search navigation FTR test to
ensure expected items are available and ONLY expected items are
available.

### Screenshots
<img width="1468" alt="image"
src="https://github.com/user-attachments/assets/729f5495-87ab-445c-b5b9-c9fdeca529d3">

### Checklist

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [x] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
This commit is contained in:
Rodney Norris 2024-10-11 12:16:24 -05:00 committed by GitHub
parent 072df4a4d4
commit 99055a5b3a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 246 additions and 61 deletions

View file

@ -45,37 +45,9 @@ export const navigationTree = (
spaceBefore: 'm',
},
{
id: 'dev_tools',
title: i18n.translate('xpack.serverlessSearch.nav.devTools', {
defaultMessage: 'Dev Tools',
}),
link: 'dev_tools',
getIsActive: ({ pathNameSerialized, prepend }) => {
return pathNameSerialized.startsWith(prepend('/app/dev_tools'));
},
},
{
id: 'kibana',
title: i18n.translate('xpack.serverlessSearch.nav.kibana', {
defaultMessage: 'Kibana',
}),
spaceBefore: 'm',
children: [
{
link: 'discover',
},
{
link: 'dashboards',
getIsActive: ({ pathNameSerialized, prepend }) => {
return pathNameSerialized.startsWith(prepend('/app/dashboards'));
},
},
],
},
{
id: 'content',
title: i18n.translate('xpack.serverlessSearch.nav.content', {
defaultMessage: 'Content',
id: 'data',
title: i18n.translate('xpack.serverlessSearch.nav.data', {
defaultMessage: 'Data',
}),
spaceBefore: 'm',
children: [
@ -110,6 +82,16 @@ export const navigationTree = (
}),
spaceBefore: 'm',
children: [
{
id: 'dev_tools',
title: i18n.translate('xpack.serverlessSearch.nav.devTools', {
defaultMessage: 'Dev Tools',
}),
link: 'dev_tools',
getIsActive: ({ pathNameSerialized, prepend }) => {
return pathNameSerialized.startsWith(prepend('/app/dev_tools'));
},
},
{
id: 'searchPlayground',
title: i18n.translate('xpack.serverlessSearch.nav.build.searchPlayground', {
@ -138,6 +120,32 @@ export const navigationTree = (
},
],
},
{
id: 'analyze',
title: i18n.translate('xpack.serverlessSearch.nav.analyze', {
defaultMessage: 'Analyze',
}),
spaceBefore: 'm',
children: [
{
link: 'discover',
},
{
link: 'dashboards',
getIsActive: ({ pathNameSerialized, prepend }) => {
return pathNameSerialized.startsWith(prepend('/app/dashboards'));
},
},
],
},
{
id: 'otherTools',
title: i18n.translate('xpack.serverlessSearch.nav.otherTools', {
defaultMessage: 'Other tools',
}),
spaceBefore: 'm',
children: [{ link: 'maps' }],
},
...(showGettingStarted ? [gettingStartedItem] : []),
],
},
@ -152,12 +160,22 @@ export const navigationTree = (
icon: 'gear',
breadcrumbStatus: 'hidden',
children: [
{
link: 'ml:modelManagement',
title: i18n.translate('xpack.serverlessSearch.nav.trainedModels', {
defaultMessage: 'Trained models',
}),
},
{
link: 'management',
title: i18n.translate('xpack.serverlessSearch.nav.mngt', {
defaultMessage: 'Management',
}),
},
{
id: 'cloudLinkUserAndRoles',
cloudLink: 'userAndRoles',
},
{
id: 'cloudLinkDeployment',
cloudLink: 'deployment',
@ -165,10 +183,6 @@ export const navigationTree = (
defaultMessage: 'Performance',
}),
},
{
id: 'cloudLinkUserAndRoles',
cloudLink: 'userAndRoles',
},
{
id: 'cloudLinkBilling',
cloudLink: 'billingAndSub',

View file

@ -40977,11 +40977,9 @@
"xpack.serverlessSearch.learnMore": "En savoir plus",
"xpack.serverlessSearch.nav.build": "Développer",
"xpack.serverlessSearch.nav.build.searchPlayground": "Playground",
"xpack.serverlessSearch.nav.content": "Contenu",
"xpack.serverlessSearch.nav.content.indices": "Gestion des index",
"xpack.serverlessSearch.nav.devTools": "Outils de développement",
"xpack.serverlessSearch.nav.home": "Accueil",
"xpack.serverlessSearch.nav.kibana": "Kibana",
"xpack.serverlessSearch.nav.mngt": "Gestion",
"xpack.serverlessSearch.nav.performance": "Performances",
"xpack.serverlessSearch.nav.projectSettings": "Paramètres de projet",

View file

@ -40722,11 +40722,9 @@
"xpack.serverlessSearch.learnMore": "詳細",
"xpack.serverlessSearch.nav.build": "ビルド",
"xpack.serverlessSearch.nav.build.searchPlayground": "Playground",
"xpack.serverlessSearch.nav.content": "コンテンツ",
"xpack.serverlessSearch.nav.content.indices": "インデックス管理",
"xpack.serverlessSearch.nav.devTools": "開発ツール",
"xpack.serverlessSearch.nav.home": "ホーム",
"xpack.serverlessSearch.nav.kibana": "Kibana",
"xpack.serverlessSearch.nav.mngt": "管理",
"xpack.serverlessSearch.nav.performance": "パフォーマンス",
"xpack.serverlessSearch.nav.projectSettings": "プロジェクト設定",

View file

@ -40767,11 +40767,9 @@
"xpack.serverlessSearch.learnMore": "了解详情",
"xpack.serverlessSearch.nav.build": "构建",
"xpack.serverlessSearch.nav.build.searchPlayground": "Playground",
"xpack.serverlessSearch.nav.content": "内容",
"xpack.serverlessSearch.nav.content.indices": "索引管理",
"xpack.serverlessSearch.nav.devTools": "开发工具",
"xpack.serverlessSearch.nav.home": "主页",
"xpack.serverlessSearch.nav.kibana": "Kibana",
"xpack.serverlessSearch.nav.mngt": "管理",
"xpack.serverlessSearch.nav.performance": "性能",
"xpack.serverlessSearch.nav.projectSettings": "项目设置",

View file

@ -21,8 +21,16 @@ export default createTestConfig({
kbnServerArgs: [
`--xpack.cloud.id=ES3_FTR_TESTS:ZmFrZS1kb21haW4uY2xkLmVsc3RjLmNvJGZha2Vwcm9qZWN0aWQuZXMkZmFrZXByb2plY3RpZC5rYg==`,
`--xpack.cloud.serverless.project_id=fakeprojectid`,
`--xpack.cloud.serverless.project_name=ES3_FTR_TESTS`,
`--xpack.cloud.serverless.project_type=elasticsearch`,
`--xpack.cloud.base_url=https://fake-cloud.elastic.co`,
`--xpack.cloud.profile_url=/user/settings/`,
`--xpack.cloud.billing_url=/billing/overview/`,
`--xpack.cloud.deployments_url=/deployments`,
`--xpack.cloud.deployment_url=/projects/elasticsearch/fakeprojectid`,
`--xpack.cloud.users_and_roles_url=/account/members/`,
`--xpack.cloud.projects_url=/projects/`,
`--xpack.cloud.organization_url=/account/`,
],
apps: {
serverlessElasticsearch: {

View file

@ -12,9 +12,9 @@ export default function ({ loadTestFile }: FtrProviderContext) {
this.tags(['esGate']);
loadTestFile(require.resolve('./getting_started'));
loadTestFile(require.resolve('./navigation'));
loadTestFile(require.resolve('./connectors/connectors_overview'));
loadTestFile(require.resolve('./default_dataview'));
loadTestFile(require.resolve('./navigation'));
loadTestFile(require.resolve('./pipelines'));
loadTestFile(require.resolve('./cases/attachment_framework'));
loadTestFile(require.resolve('./dashboards/build_dashboard'));

View file

@ -13,6 +13,7 @@ export default function ({ getPageObject, getService }: FtrProviderContext) {
const svlSearchNavigation = getService('svlSearchNavigation');
const svlCommonNavigation = getPageObject('svlCommonNavigation');
const svlCommonPage = getPageObject('svlCommonPage');
const solutionNavigation = getPageObject('solutionNavigation');
const testSubjects = getService('testSubjects');
const browser = getService('browser');
const header = getPageObject('header');
@ -31,28 +32,144 @@ export default function ({ getPageObject, getService }: FtrProviderContext) {
await svlSearchLandingPage.assertSvlSearchSideNavExists();
// check side nav links
await solutionNavigation.sidenav.expectSectionExists('search_project_nav');
await solutionNavigation.sidenav.expectLinkActive({
deepLinkId: 'serverlessElasticsearch',
});
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
deepLinkId: 'serverlessElasticsearch',
});
await testSubjects.existOrFail(`svlSearchOverviewPage`);
await svlCommonNavigation.sidenav.expectLinkActive({
deepLinkId: 'serverlessElasticsearch',
});
await svlCommonNavigation.breadcrumbs.expectBreadcrumbExists({
deepLinkId: 'serverlessElasticsearch',
});
// TODO: test something search project specific instead of generic discover
// navigate to discover
await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'discover' });
await svlCommonNavigation.sidenav.expectLinkActive({ deepLinkId: 'discover' });
await svlCommonNavigation.breadcrumbs.expectBreadcrumbExists({ deepLinkId: 'discover' });
expect(await browser.getCurrentUrl()).contain('/app/discover');
// navigate to a different section
await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'management:index_management' });
await svlCommonNavigation.sidenav.expectLinkActive({
// check Data
// > Index Management
await solutionNavigation.sidenav.clickLink({
deepLinkId: 'management:index_management',
});
await svlCommonNavigation.breadcrumbs.expectBreadcrumbExists({ text: `Index Management` });
await testSubjects.existOrFail(`indicesTab`);
await solutionNavigation.sidenav.expectLinkActive({
deepLinkId: 'management:index_management',
});
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Data' });
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Index Management' });
// > Connectors
await solutionNavigation.sidenav.clickLink({
deepLinkId: 'serverlessConnectors',
});
await solutionNavigation.sidenav.expectLinkActive({
deepLinkId: 'serverlessConnectors',
});
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Data' });
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Connectors' });
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
deepLinkId: 'serverlessConnectors',
});
// check Build
// > Dev Tools
await solutionNavigation.sidenav.clickLink({
deepLinkId: 'dev_tools',
});
await solutionNavigation.sidenav.expectLinkActive({
deepLinkId: 'dev_tools',
});
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Build' });
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Dev Tools' });
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
deepLinkId: 'dev_tools',
});
// > Playground
await solutionNavigation.sidenav.clickLink({
deepLinkId: 'searchPlayground',
});
await solutionNavigation.sidenav.expectLinkActive({
deepLinkId: 'searchPlayground',
});
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Build' });
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Playground' });
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
deepLinkId: 'searchPlayground',
});
// check Relevance
// > Inference Endpoints
// await solutionNavigation.sidenav.clickLink({
// deepLinkId: 'searchInferenceEndpoints',
// });
// await solutionNavigation.sidenav.expectLinkActive({
// deepLinkId: 'searchInferenceEndpoints',
// });
// await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Relevance' });
// await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Inference Endpoints' });
// await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
// deepLinkId: 'searchInferenceEndpoints',
// });
// check Analyze
// > Discover
await solutionNavigation.sidenav.clickLink({
deepLinkId: 'discover',
});
await solutionNavigation.sidenav.expectLinkActive({
deepLinkId: 'discover',
});
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Analyze' });
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Discover' });
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
deepLinkId: 'discover',
});
// > Dashboards
await solutionNavigation.sidenav.clickLink({
deepLinkId: 'dashboards',
});
await solutionNavigation.sidenav.expectLinkActive({
deepLinkId: 'dashboards',
});
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Analyze' });
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Dashboards' });
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
deepLinkId: 'dashboards',
});
// check Other tools
// > Maps
await solutionNavigation.sidenav.clickLink({
deepLinkId: 'maps',
});
await solutionNavigation.sidenav.expectLinkActive({
deepLinkId: 'maps',
});
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Other tools' });
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
text: 'Maps',
});
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
deepLinkId: 'maps',
});
// Open Project Settings
await solutionNavigation.sidenav.openSection('project_settings_project_nav');
// check Project Settings
// > Trained Models
await solutionNavigation.sidenav.clickLink({
deepLinkId: 'ml:modelManagement',
});
await solutionNavigation.sidenav.expectLinkActive({
deepLinkId: 'ml:modelManagement',
});
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Model Management' });
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Trained Models' });
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
deepLinkId: 'ml:modelManagement',
});
// > Management
await solutionNavigation.sidenav.clickLink({
deepLinkId: 'management',
});
await solutionNavigation.sidenav.expectLinkActive({
deepLinkId: 'management',
});
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Management' });
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
deepLinkId: 'management',
});
// navigate back to serverless search overview
await svlCommonNavigation.clickLogo();
@ -77,7 +194,7 @@ export default function ({ getPageObject, getService }: FtrProviderContext) {
it("management apps from the sidenav hide the 'stack management' root from the breadcrumbs", async () => {
await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'management:index_management' });
await svlCommonNavigation.breadcrumbs.expectBreadcrumbTexts([
'Content',
'Data',
'Index Management',
'Indices',
]);
@ -113,5 +230,57 @@ export default function ({ getPageObject, getService }: FtrProviderContext) {
expect(await browser.getCurrentUrl()).not.contain('/app/management/cases');
await testSubjects.missingOrFail('cases-all-title');
});
it('renders expected side navigation items', async () => {
await solutionNavigation.sidenav.openSection('project_settings_project_nav');
// Verify all expected top-level links exist
await solutionNavigation.sidenav.expectLinkExists({ text: 'Home' });
await solutionNavigation.sidenav.expectLinkExists({ text: 'Data' });
await solutionNavigation.sidenav.expectLinkExists({ text: 'Index Management' });
await solutionNavigation.sidenav.expectLinkExists({ text: 'Connectors' });
await solutionNavigation.sidenav.expectLinkExists({ text: 'Build' });
await solutionNavigation.sidenav.expectLinkExists({ text: 'Dev Tools' });
await solutionNavigation.sidenav.expectLinkExists({ text: 'Playground' });
// await solutionNavigation.sidenav.expectLinkExists({ text: 'Relevance' });
// await solutionNavigation.sidenav.expectLinkExists({ text: 'Inference Endpoints' });
await solutionNavigation.sidenav.expectLinkExists({ text: 'Analyze' });
await solutionNavigation.sidenav.expectLinkExists({ text: 'Discover' });
await solutionNavigation.sidenav.expectLinkExists({ text: 'Dashboards' });
await solutionNavigation.sidenav.expectLinkExists({ text: 'Other tools' });
await solutionNavigation.sidenav.expectLinkExists({ text: 'Maps' });
// await solutionNavigation.sidenav.expectLinkExists({ text: 'Getting Started' });
await solutionNavigation.sidenav.expectLinkExists({ text: 'Trained models' });
await solutionNavigation.sidenav.expectLinkExists({ text: 'Management' });
await solutionNavigation.sidenav.expectLinkExists({ text: 'Users and roles' });
await solutionNavigation.sidenav.expectLinkExists({ text: 'Performance' });
await solutionNavigation.sidenav.expectLinkExists({ text: 'Billing and subscription' });
await solutionNavigation.sidenav.openSection('project_settings_project_nav');
await solutionNavigation.sidenav.expectOnlyDefinedLinks([
'search_project_nav',
'home',
'data',
'management:index_management',
'serverlessConnectors',
'build',
'dev_tools',
'searchPlayground',
// 'relevance',
// 'searchInferenceEndpoints',
'analyze',
'discover',
'dashboards',
'otherTools',
'maps',
// 'gettingStarted',
'project_settings_project_nav',
'ml:modelManagement',
'management',
'cloudLinkUserAndRoles',
'cloudLinkDeployment',
'cloudLinkBilling',
]);
});
});
}