diff --git a/x-pack/solutions/search/plugins/search_homepage/test/scout/ui/fixtures/index.ts b/x-pack/solutions/search/plugins/search_homepage/test/scout/ui/fixtures/index.ts index c014cd1134898..4a50d29479d5d 100644 --- a/x-pack/solutions/search/plugins/search_homepage/test/scout/ui/fixtures/index.ts +++ b/x-pack/solutions/search/plugins/search_homepage/test/scout/ui/fixtures/index.ts @@ -7,7 +7,6 @@ import type { BrowserAuthFixture, - KibanaUrl, PageObjects, ScoutTestFixtures, ScoutWorkerFixtures, @@ -30,7 +29,6 @@ export const test = base.extend( }: { pageObjects: ExtendedScoutTestFixtures['pageObjects']; page: ExtendedScoutTestFixtures['page']; - kbnUrl: KibanaUrl; }, use: (pageObjects: ExtendedScoutTestFixtures['pageObjects']) => Promise ) => { diff --git a/x-pack/solutions/search/plugins/search_homepage/test/scout/ui/fixtures/page_objects/homepage.ts b/x-pack/solutions/search/plugins/search_homepage/test/scout/ui/fixtures/page_objects/homepage.ts index 670e276d21790..1a748710512f2 100644 --- a/x-pack/solutions/search/plugins/search_homepage/test/scout/ui/fixtures/page_objects/homepage.ts +++ b/x-pack/solutions/search/plugins/search_homepage/test/scout/ui/fixtures/page_objects/homepage.ts @@ -31,6 +31,12 @@ export class Homepage { return this.page.testSubj.locator(cardId).click(); } + async getGettingStartedButton() { + return this.page.testSubj.locator( + 'searchHomepageGettingStartedBannerGetStartedWithElasticsearchButton' + ); + } + async clickGettingStartedButton() { await this.page.testSubj.waitForSelector( 'searchHomepageGettingStartedBannerGetStartedWithElasticsearchButton' @@ -40,14 +46,6 @@ export class Homepage { .click(); } - async getCloudResourceCards() { - return this.page.locator('[data-test-subj^="cloudResourceCard-"]'); - } - - async getCloudResourceCardLink(cardId: string) { - return this.page.testSubj.locator(cardId).getByRole('link'); - } - async getApiKeyButton() { return this.page.testSubj.locator('searchHomepageConnectToElasticsearchApiKeysButton'); } @@ -85,4 +83,47 @@ export class Homepage { async getApiKeyValueRow() { return this.page.testSubj.locator('connectionDetailsApiKeyValueRow'); } + + // Embedded Console methods + async expectEmbeddedConsoleControlBarExists() { + await this.page.testSubj.waitForSelector('consoleEmbeddedSection'); + } + + async getEmbeddedConsoleBody() { + return this.page.testSubj.locator('consoleEmbeddedBody'); + } + + async clickEmbeddedConsoleControlBar() { + await this.page.testSubj.locator('consoleEmbeddedControlBar').click(); + } + + async getFullscreenToggleButton() { + return this.page.testSubj.locator('consoleToggleFullscreenButton'); + } + + async getSearchHomepageContainer() { + return this.page.testSubj.locator('search-homepage'); + } + + // Elasticsearch endpoint and copy functionality + async getCopyEndpointButton() { + return this.page.testSubj.locator('copyEndpointButton'); + } + + async getCopyEndpointButtonCopied() { + return this.page.testSubj.locator('copyEndpointButton-copied'); + } + + async getEndpointValueField() { + return this.page.testSubj.locator('endpointValueField'); + } + + // Body Links methods + async getBodyLinks() { + return this.page.testSubj.locator('searchHomepageBodyLinkLink'); + } + + async getBodyLinkByText(text: string) { + return this.page.getByRole('link', { name: text }); + } } diff --git a/x-pack/solutions/search/plugins/search_homepage/test/scout/ui/parallel_tests/homepage_admin.spec.ts b/x-pack/solutions/search/plugins/search_homepage/test/scout/ui/parallel_tests/homepage_admin.spec.ts index 08b7572416d49..f72bc094f306f 100644 --- a/x-pack/solutions/search/plugins/search_homepage/test/scout/ui/parallel_tests/homepage_admin.spec.ts +++ b/x-pack/solutions/search/plugins/search_homepage/test/scout/ui/parallel_tests/homepage_admin.spec.ts @@ -8,7 +8,7 @@ import { expect } from '@kbn/scout-search'; import { test } from '../fixtures'; -test.describe('Homepage - Admin', { tag: ['@svlSearch'] }, () => { +test.describe('Homepage - Admin', { tag: ['@svlSearch', '@ess'] }, () => { test.beforeEach(async ({ page, browserAuth, pageObjects }) => { await browserAuth.loginAsAdmin(); await page.addInitScript(() => { @@ -55,4 +55,163 @@ test.describe('Homepage - Admin', { tag: ['@svlSearch'] }, () => { const apiKeyValueRow = await pageObjects.homepage.getApiKeyValueRow(); await expect(apiKeyValueRow).toBeVisible(); }); + + // === Embedded Console Tests === + test('should have embedded dev console that can be toggled', async ({ pageObjects }) => { + await pageObjects.homepage.expectEmbeddedConsoleControlBarExists(); + + // Console body should be hidden initially + const consoleBodyInitial = await pageObjects.homepage.getEmbeddedConsoleBody(); + await expect(consoleBodyInitial).toBeHidden(); + + // Click to open console + await pageObjects.homepage.clickEmbeddedConsoleControlBar(); + + // Verify console is open and fullscreen toggle is visible + const fullscreenToggle = await pageObjects.homepage.getFullscreenToggleButton(); + await expect(fullscreenToggle).toBeVisible(); + + const consoleBodyOpen = await pageObjects.homepage.getEmbeddedConsoleBody(); + await expect(consoleBodyOpen).toBeVisible(); + + // Click to close console + await pageObjects.homepage.clickEmbeddedConsoleControlBar(); + + const consoleBodyClosed = await pageObjects.homepage.getEmbeddedConsoleBody(); + await expect(consoleBodyClosed).toBeHidden(); + }); + + // === Endpoint Copy Functionality Tests === + test('should show Elasticsearch endpoint with copy functionality', async ({ pageObjects }) => { + const endpointValueField = await pageObjects.homepage.getEndpointValueField(); + await expect(endpointValueField).toBeVisible(); + + const copyEndpointButton = await pageObjects.homepage.getCopyEndpointButton(); + await expect(copyEndpointButton).toBeVisible(); + }); + + test('should show checkmark feedback when copy button is clicked', async ({ pageObjects }) => { + const copyEndpointButton = await pageObjects.homepage.getCopyEndpointButton(); + await expect(copyEndpointButton).toBeVisible(); + + await copyEndpointButton.click(); + + // After clicking, the button should show copied state + const copiedButton = await pageObjects.homepage.getCopyEndpointButtonCopied(); + await expect(copiedButton).toBeVisible(); + + // After a short delay, it should revert back to normal state + const normalButton = await pageObjects.homepage.getCopyEndpointButton(); + await expect(normalButton).toBeVisible(); + }); + + // === Navigation Cards Tests === + test('navigation cards should navigate to correct places', async ({ pageObjects, page }) => { + const navigationCards = await pageObjects.homepage.getNavigationCards(); + await expect(navigationCards).toHaveCount(5); + + const navCardTests = [ + { + cardTestId: 'searchHomepageNavLinks-discover', + expectedUrl: 'discover', + }, + { + cardTestId: 'searchHomepageNavLinks-dashboards', + expectedUrl: 'dashboards', + }, + { + cardTestId: 'searchHomepageNavLinks-agentBuilder', + expectedUrl: 'agent_builder', + }, + { + cardTestId: 'searchHomepageNavLinks-machineLearning', + expectedUrl: 'ml/overview', + }, + { + cardTestId: 'searchHomepageNavLinks-dataManagement', + expectedUrl: 'index_management', + }, + ]; + + for (const { cardTestId, expectedUrl } of navCardTests) { + await pageObjects.homepage.clickNavigationCard(cardTestId); + await expect(page).toHaveURL(new RegExp(expectedUrl)); + await pageObjects.homepage.goto(); + } + }); + + // === Getting Started Banner Tests === + test('should display Getting Started banner with title and button', async ({ pageObjects }) => { + const gettingStartedButton = await pageObjects.homepage.getGettingStartedButton(); + await expect(gettingStartedButton).toBeVisible(); + await expect(gettingStartedButton).toContainText('Get started with Elasticsearch'); + }); + + test('Get started button should navigate to getting started page', async ({ + pageObjects, + page, + }) => { + await pageObjects.homepage.clickGettingStartedButton(); + await expect(page).toHaveURL(new RegExp('getting_started')); + }); + + // === Body Links Tests === + test('should display all body links with external documentation', async ({ pageObjects }) => { + const bodyLinks = await pageObjects.homepage.getBodyLinks(); + await expect(bodyLinks).toHaveCount(3); + + // Verify specific links exist + const askExpertLink = await pageObjects.homepage.getBodyLinkByText( + 'Contact customer engineering' + ); + await expect(askExpertLink).toBeVisible(); + + const trainingLink = await pageObjects.homepage.getBodyLinkByText('Elastic Training'); + await expect(trainingLink).toBeVisible(); + + const docsLink = await pageObjects.homepage.getBodyLinkByText('View documentation'); + await expect(docsLink).toBeVisible(); + }); + + test('body links should have external target attribute', async ({ pageObjects }) => { + const bodyLinks = await pageObjects.homepage.getBodyLinks(); + const allLinks = await bodyLinks.all(); + + for (const link of allLinks) { + await expect(link).toHaveAttribute('target', '_blank'); + await expect(link).toHaveAttribute('rel', 'noopener noreferrer'); + } + }); + + test('body links should navigate to correct URLs when clicked', async ({ pageObjects, page }) => { + const bodyLinkTests = [ + { + linkText: 'Contact customer engineering', + expectedUrlPattern: /contact\/ce-help/, + }, + { + linkText: 'Elastic Training', + expectedUrlPattern: /training/, + }, + { + linkText: 'View documentation', + expectedUrlPattern: /solutions\/search\/get-started/, + }, + ]; + + for (const { linkText, expectedUrlPattern } of bodyLinkTests) { + const link = await pageObjects.homepage.getBodyLinkByText(linkText); + await expect(link).toBeVisible(); + + // Click the link and wait for new page to open + const context = page.context(); + const [newPage] = await Promise.all([context.waitForEvent('page'), link.click()]); + + // Verify the new page URL matches expected pattern + await expect(newPage).toHaveURL(expectedUrlPattern); + + // Close the new page and continue with the original page + await newPage.close(); + } + }); }); diff --git a/x-pack/solutions/search/plugins/search_homepage/test/scout/ui/parallel_tests/homepage_viewer.spec.ts b/x-pack/solutions/search/plugins/search_homepage/test/scout/ui/parallel_tests/homepage_viewer.spec.ts index 7b3eb10452637..dba7f7457e232 100644 --- a/x-pack/solutions/search/plugins/search_homepage/test/scout/ui/parallel_tests/homepage_viewer.spec.ts +++ b/x-pack/solutions/search/plugins/search_homepage/test/scout/ui/parallel_tests/homepage_viewer.spec.ts @@ -8,7 +8,7 @@ import { expect } from '@kbn/scout-search'; import { test } from '../fixtures'; -test.describe('Homepage - Viewer', { tag: ['@svlSearch'] }, () => { +test.describe('Homepage - Viewer', { tag: ['@svlSearch', '@ess'] }, () => { test.beforeEach(async ({ page, browserAuth, pageObjects }) => { await browserAuth.loginAsViewer(); await page.addInitScript(() => { @@ -71,4 +71,113 @@ test.describe('Homepage - Viewer', { tag: ['@svlSearch'] }, () => { const apiKeysButton = await pageObjects.homepage.getApiKeyButton(); await expect(apiKeysButton).toBeDisabled(); }); + + // === Embedded Console Tests === + test('should have embedded dev console that can be toggled', async ({ pageObjects }) => { + await pageObjects.homepage.expectEmbeddedConsoleControlBarExists(); + + // Console body should be hidden initially + const consoleBodyInitial = await pageObjects.homepage.getEmbeddedConsoleBody(); + await expect(consoleBodyInitial).toBeHidden(); + + // Click to open console + await pageObjects.homepage.clickEmbeddedConsoleControlBar(); + + // Verify console is open and fullscreen toggle is visible + const fullscreenToggle = await pageObjects.homepage.getFullscreenToggleButton(); + await expect(fullscreenToggle).toBeVisible(); + + const consoleBodyOpen = await pageObjects.homepage.getEmbeddedConsoleBody(); + await expect(consoleBodyOpen).toBeVisible(); + + // Click to close console + await pageObjects.homepage.clickEmbeddedConsoleControlBar(); + + const consoleBodyClosed = await pageObjects.homepage.getEmbeddedConsoleBody(); + await expect(consoleBodyClosed).toBeHidden(); + }); + + // === Endpoint Copy Functionality Tests === + test('should show Elasticsearch endpoint with copy functionality', async ({ pageObjects }) => { + const endpointValueField = await pageObjects.homepage.getEndpointValueField(); + await expect(endpointValueField).toBeVisible(); + + const copyEndpointButton = await pageObjects.homepage.getCopyEndpointButton(); + await expect(copyEndpointButton).toBeVisible(); + }); + + test('should show checkmark feedback when copy button is clicked', async ({ pageObjects }) => { + const copyEndpointButton = await pageObjects.homepage.getCopyEndpointButton(); + await expect(copyEndpointButton).toBeVisible(); + + await copyEndpointButton.click(); + + // After clicking, the button should show copied state + const copiedButton = await pageObjects.homepage.getCopyEndpointButtonCopied(); + await expect(copiedButton).toBeVisible(); + + // After a short delay, it should revert back to normal state + const normalButton = await pageObjects.homepage.getCopyEndpointButton(); + await expect(normalButton).toBeVisible(); + }); + + // === Body Links Tests === + test('should display all body links with external documentation', async ({ pageObjects }) => { + const bodyLinks = await pageObjects.homepage.getBodyLinks(); + await expect(bodyLinks).toHaveCount(3); + + // Verify specific links exist + const askExpertLink = await pageObjects.homepage.getBodyLinkByText( + 'Contact customer engineering' + ); + await expect(askExpertLink).toBeVisible(); + + const trainingLink = await pageObjects.homepage.getBodyLinkByText('Elastic Training'); + await expect(trainingLink).toBeVisible(); + + const docsLink = await pageObjects.homepage.getBodyLinkByText('View documentation'); + await expect(docsLink).toBeVisible(); + }); + + test('body links should have external target attribute', async ({ pageObjects }) => { + const bodyLinks = await pageObjects.homepage.getBodyLinks(); + const allLinks = await bodyLinks.all(); + + for (const link of allLinks) { + await expect(link).toHaveAttribute('target', '_blank'); + await expect(link).toHaveAttribute('rel', 'noopener noreferrer'); + } + }); + + test('body links should navigate to correct URLs when clicked', async ({ pageObjects, page }) => { + const bodyLinkTests = [ + { + linkText: 'Contact customer engineering', + expectedUrlPattern: /contact\/ce-help/, + }, + { + linkText: 'Elastic Training', + expectedUrlPattern: /training/, + }, + { + linkText: 'View documentation', + expectedUrlPattern: /solutions\/search\/get-started/, + }, + ]; + + for (const { linkText, expectedUrlPattern } of bodyLinkTests) { + const link = await pageObjects.homepage.getBodyLinkByText(linkText); + await expect(link).toBeVisible(); + + // Click the link and wait for new page to open + const context = page.context(); + const [newPage] = await Promise.all([context.waitForEvent('page'), link.click()]); + + // Verify the new page URL matches expected pattern + await expect(newPage).toHaveURL(expectedUrlPattern); + + // Close the new page and continue with the original page + await newPage.close(); + } + }); }); diff --git a/x-pack/solutions/search/test/functional_search/index.ts b/x-pack/solutions/search/test/functional_search/index.ts index e407f1b1a92f4..9429ef41f46b6 100644 --- a/x-pack/solutions/search/test/functional_search/index.ts +++ b/x-pack/solutions/search/test/functional_search/index.ts @@ -10,7 +10,6 @@ import type { FtrProviderContext } from './ftr_provider_context'; export default ({ loadTestFile }: FtrProviderContext): void => { describe('Search solution tests', function () { - loadTestFile(require.resolve('./tests/search_homepage')); loadTestFile(require.resolve('./tests/classic_navigation')); loadTestFile(require.resolve('./tests/solution_navigation')); loadTestFile(require.resolve('./tests/agent_builder')); diff --git a/x-pack/solutions/search/test/functional_search/tests/search_homepage.ts b/x-pack/solutions/search/test/functional_search/tests/search_homepage.ts deleted file mode 100644 index e5535bde2d879..0000000000000 --- a/x-pack/solutions/search/test/functional_search/tests/search_homepage.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 expect from '@kbn/expect'; -import type { FtrProviderContext } from '../ftr_provider_context'; -import { testHasEmbeddedConsole } from './embedded_console'; - -export default function ({ getPageObjects, getService }: FtrProviderContext) { - const pageObjects = getPageObjects([ - 'embeddedConsole', - 'header', - 'apiKeys', - 'searchHomePage', - 'searchNavigation', - ]); - const es = getService('es'); - const searchSpace = getService('searchSpace'); - const browser = getService('browser'); - const testSubjects = getService('testSubjects'); - const retry = getService('retry'); - - const esDeleteAllIndices = getService('esDeleteAllIndices'); - - const indexName = 'test-my-index'; - - // Failing: See https://github.com/elastic/kibana/issues/228946 - describe.skip('Search Home page', function () { - describe('Solution Nav - Search', function () { - let cleanUp: () => Promise; - let spaceCreated: { id: string } = { id: '' }; - - before(async () => { - ({ cleanUp, spaceCreated } = await searchSpace.createTestSpace('search-homepage-ftr')); - await searchSpace.navigateTo(spaceCreated.id); - }); - - after(async () => { - // Clean up space created - await cleanUp(); - await esDeleteAllIndices(['test-*', 'search-*']); - }); - - describe('search home page', () => { - beforeEach(async () => { - await esDeleteAllIndices(['test-*', 'search-*']); - await pageObjects.searchNavigation.navigateToElasticsearchSearchHomePage( - `/s/${spaceCreated.id}` - ); - }); - - afterEach(async () => { - await esDeleteAllIndices(['test-*', 'search-*']); - }); - - it('should have embedded dev console', async () => { - await testHasEmbeddedConsole(pageObjects); - }); - - it('load search home page', async () => { - await es.indices.create({ index: indexName }); - await pageObjects.searchNavigation.navigateToElasticsearchSearchHomePage(); - await pageObjects.searchHomePage.expectSearchHomePageIsLoaded(); - }); - }); - - describe('search home page with existing indices', () => { - before(async () => { - await es.indices.create({ index: indexName }); - await pageObjects.searchNavigation.navigateToElasticsearchSearchHomePage( - `/s/${spaceCreated.id}` - ); - }); - - beforeEach(async () => { - await pageObjects.searchNavigation.navigateToElasticsearchSearchHomePage(); - }); - - after(async () => { - await esDeleteAllIndices(['test-*', 'search-*']); - }); - - describe('Elasticsearch endpoint and API Keys', function () { - it('renders Elasticsearch endpoint with copy functionality', async () => { - await testSubjects.existOrFail('copyEndpointButton'); - await testSubjects.existOrFail('endpointValueField'); - }); - - it('shows checkmark icon feedback when copy button is clicked', async () => { - await testSubjects.existOrFail('copyEndpointButton'); - await testSubjects.click('copyEndpointButton'); - // After clicking, the button should show copied state - await retry.try(async () => { - await testSubjects.existOrFail('copyEndpointButton-copied'); - }); - // After 1 second, it should revert back to normal state - await retry.try(async () => { - await testSubjects.existOrFail('copyEndpointButton'); - await testSubjects.missingOrFail('copyEndpointButton-copied'); - }); - }); - - it('renders API keys buttons and active badge correctly', async () => { - await testSubjects.existOrFail('createApiKeyButton'); - await testSubjects.existOrFail('manageApiKeysButton'); - await testSubjects.existOrFail('activeApiKeysBadge'); - }); - - it('opens create_api_key flyout on clicking CreateApiKey button', async () => { - await testSubjects.click('createApiKeyButton'); - await retry.try(async () => { - expect(await pageObjects.apiKeys.getFlyoutTitleText()).to.be('Create API key'); - }); - }); - - it('opens API keys management page on clicking Manage API Keys', async () => { - await testSubjects.existOrFail('manageApiKeysButton'); - await testSubjects.click('manageApiKeysButton'); - expect(await browser.getCurrentUrl()).contain('/app/management/security/api_keys'); - }); - }); - - describe('Connect To Elasticsearch Side Panel', function () { - it('renders the "Upload a file" card with copy link', async () => { - await testSubjects.existOrFail('uploadFileButton'); - await testSubjects.click('uploadFileButton'); - expect(await browser.getCurrentUrl()).contain('ml/filedatavisualizer'); - }); - - describe('Sample data section', function () { - it('renders the sample data section', async () => { - await testSubjects.existOrFail('sampleDataSection'); - }); - - describe('when kibana_sample_data_elasticsearch_documentation index does not exist', function () { - it('renders the "Install sample data" button', async () => { - await testSubjects.existOrFail('installSampleBtn'); - }); - }); - - describe('when kibana_sample_data_elasticsearch_documentation index exists', function () { - before(async () => { - await es.indices.create({ - index: 'kibana_sample_data_elasticsearch_documentation', - }); - }); - - after(async () => { - await esDeleteAllIndices(['kibana_sample_data_elasticsearch_documentation']); - }); - - it('renders the "View data" button', async () => { - await testSubjects.existOrFail('viewDataBtn'); - }); - }); - }); - }); - describe('Get started with API', function () { - it('clicking on search basics tutorial open console', async () => { - await testSubjects.existOrFail('console_tutorials_search_basics'); - await testSubjects.existOrFail('console_tutorials_search_basics_console_btn'); - await testSubjects.click('console_tutorials_search_basics_console_btn'); - await testSubjects.existOrFail('consoleEditorContainer'); - }); - it('clicking on semantic search tutorial open console', async () => { - await testSubjects.existOrFail('console_tutorials_semantic_search'); - await testSubjects.existOrFail('console_tutorials_semantic_search_console_btn'); - await testSubjects.click('console_tutorials_semantic_search_console_btn'); - await testSubjects.existOrFail('consoleEditorContainer'); - }); - it('clicking on esql tutorial open console', async () => { - await testSubjects.existOrFail('console_tutorials_esql'); - await testSubjects.existOrFail('console_tutorials_esql_console_btn'); - await testSubjects.click('console_tutorials_esql_console_btn'); - await testSubjects.existOrFail('consoleEditorContainer'); - }); - // TODO: uncomment below lines when we are ready to show TSDS tutorial. review https://github.com/elastic/kibana/pull/237384#issuecomment-3411670210 - // it('clicking on tsds tutorial open console', async () => { - // await testSubjects.existOrFail('console_tutorials_tsds'); - // await testSubjects.existOrFail('console_tutorials_tsds_console_btn'); - // await testSubjects.click('console_tutorials_tsds_console_btn'); - // await testSubjects.existOrFail('consoleEditorContainer'); - // }); - }); - describe('Alternate Solutions', function () { - it('renders Observability content', async () => { - await testSubjects.scrollIntoView('analyzeLogsBrowseIntegrations'); - await testSubjects.existOrFail('analyzeLogsBrowseIntegrations'); - await testSubjects.click('analyzeLogsBrowseIntegrations'); - expect(await browser.getCurrentUrl()).contain('browse/observability'); - }); - }); - - // FLAKY: https://github.com/elastic/kibana/issues/226572 - describe.skip('Dive deeper with Elasticsearch', function () { - it('renders Search labs content', async () => { - await testSubjects.existOrFail('searchLabsSection'); - await testSubjects.existOrFail('searchLabsButton'); - await testSubjects.click('searchLabsButton'); - expect(await browser.getCurrentUrl()).contain('search-labs'); - }); - - it('renders Open Notebooks content', async () => { - await testSubjects.existOrFail('pythonNotebooksSection'); - await testSubjects.existOrFail('openNotebooksButton'); - await testSubjects.click('openNotebooksButton'); - expect(await browser.getCurrentUrl()).contain('search-labs/tutorials/examples'); - }); - - it('renders Elasticsearch Documentation content', async () => { - await testSubjects.existOrFail('elasticsearchDocumentationSection'); - await testSubjects.existOrFail('viewDocumentationButton'); - await testSubjects.click('viewDocumentationButton'); - expect(await browser.getCurrentUrl()).contain('docs/solutions/search/get-started'); - }); - }); - - describe('Footer content', function () { - it('displays the community link', async () => { - await testSubjects.existOrFail('elasticCommunityLink'); - await testSubjects.click('elasticCommunityLink'); - expect(await browser.getCurrentUrl()).contain('community/'); - }); - - it('displays the feedbacks link', async () => { - await testSubjects.existOrFail('giveFeedbackLink'); - await testSubjects.click('giveFeedbackLink'); - expect(await browser.getCurrentUrl()).contain('kibana/feedback'); - }); - }); - }); - }); - }); -} diff --git a/x-pack/solutions/search/test/serverless/functional/configs/index.search_features.ts b/x-pack/solutions/search/test/serverless/functional/configs/index.search_features.ts index 7f43e8ac8e147..f6b5702eb8db1 100644 --- a/x-pack/solutions/search/test/serverless/functional/configs/index.search_features.ts +++ b/x-pack/solutions/search/test/serverless/functional/configs/index.search_features.ts @@ -11,7 +11,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { describe('serverless search UI - search features', function () { this.tags(['esGate']); - loadTestFile(require.resolve('../test_suites/search_homepage')); loadTestFile(require.resolve('../test_suites/search_index_detail.ts')); loadTestFile(require.resolve('../test_suites/connectors/connectors_overview')); loadTestFile(require.resolve('../test_suites/search_playground/playground_overview')); diff --git a/x-pack/solutions/search/test/serverless/functional/test_suites/search_homepage.ts b/x-pack/solutions/search/test/serverless/functional/test_suites/search_homepage.ts deleted file mode 100644 index a54e0b60c5b71..0000000000000 --- a/x-pack/solutions/search/test/serverless/functional/test_suites/search_homepage.ts +++ /dev/null @@ -1,304 +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 type { FtrProviderContext } from '../ftr_provider_context'; -import type { RoleCredentials } from '../services'; -import { testHasEmbeddedConsole } from './embedded_console'; - -export default function ({ getPageObjects, getService }: FtrProviderContext) { - const pageObjects = getPageObjects([ - 'svlCommonPage', - 'svlCommonNavigation', - 'searchHomePage', - 'embeddedConsole', - 'common', - ]); - const svlUserManager = getService('svlUserManager'); - let roleAuthc: RoleCredentials; - const es = getService('es'); - const esDeleteAllIndices = getService('esDeleteAllIndices'); - - const deleteAllTestIndices = async () => { - await esDeleteAllIndices(['test-*', 'search-*']); - }; - - const testSubjects = getService('testSubjects'); - const retry = getService('retry'); - - // Skip the tests until timeout flakes can be diagnosed and resolved - describe.skip('Search Homepage', function () { - describe('as viewer', function () { - before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); - - await pageObjects.svlCommonPage.loginAsViewer(); - }); - - beforeEach(async () => { - await pageObjects.common.navigateToApp('searchHomepage'); - }); - - after(async () => { - if (!roleAuthc) return; - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); - }); - - it('has search homepage with Home sidenav', async () => { - await pageObjects.searchHomePage.expectToBeOnHomepage(); - await pageObjects.searchHomePage.expectHomepageHeader(); - // Navigate to another page - await pageObjects.svlCommonNavigation.sidenav.clickLink({ - deepLinkId: 'discover', - }); - await pageObjects.searchHomePage.expectToNotBeOnHomepage(); - // Click Home in Side nav - await pageObjects.svlCommonNavigation.sidenav.clickLink({ - deepLinkId: 'searchHomepage', - }); - await pageObjects.searchHomePage.expectToBeOnHomepage(); - }); - - it('has embedded dev console', async () => { - await testHasEmbeddedConsole(pageObjects); - }); - - describe('Elasticsearch endpoint and API Keys', function () { - it('renders Elasticsearch endpoint with copy functionality', async () => { - await testSubjects.existOrFail('copyEndpointButton'); - await testSubjects.existOrFail('endpointValueField'); - await testSubjects.existOrFail('apiKeyFormNoUserPrivileges'); - }); - - it('shows checkmark icon feedback when copy button is clicked', async () => { - await testSubjects.existOrFail('copyEndpointButton'); - await testSubjects.click('copyEndpointButton'); - // After clicking, the button should show copied state - await retry.try(async () => { - await testSubjects.existOrFail('copyEndpointButton-copied'); - }); - // After 1 second, it should revert back to normal state - await retry.try(async () => { - await testSubjects.existOrFail('copyEndpointButton'); - await testSubjects.missingOrFail('copyEndpointButton-copied'); - }); - }); - }); - - describe('Connect To Elasticsearch Side Panel', function () { - it('renders the "Upload a file" card with copy link', async () => { - await testSubjects.existOrFail('uploadFileButton'); - await testSubjects.click('uploadFileButton'); - // TODO: Should this retry to allow time for new page to load? - await pageObjects.searchHomePage.expectToBeOnUploadDataPage(); - }); - - it('does not render the "Add sample data" card', async () => { - await testSubjects.missingOrFail('sampleDataSection'); - }); - }); - describe('Get started with API', function () { - it('clicking on search basics tutorial open console', async () => { - await testSubjects.existOrFail('console_tutorials_search_basics'); - await testSubjects.click('console_tutorials_search_basics'); - await testSubjects.existOrFail('consoleEditorContainer'); - }); - it('clicking on semantic search tutorial open console', async () => { - await testSubjects.existOrFail('console_tutorials_semantic_search'); - await testSubjects.click('console_tutorials_semantic_search'); - await testSubjects.existOrFail('consoleEditorContainer'); - }); - it('clicking on esql tutorial open console', async () => { - await testSubjects.existOrFail('console_tutorials_esql'); - await testSubjects.click('console_tutorials_esql'); - await testSubjects.existOrFail('consoleEditorContainer'); - }); - // TODO: uncomment below lines when we are ready to show TSDS tutorial. review https://github.com/elastic/kibana/pull/237384#issuecomment-3411670210 - // it('clicking on tsds tutorial open console', async () => { - // await testSubjects.existOrFail('console_tutorials_tsds'); - // await testSubjects.click('console_tutorials_tsds'); - // await testSubjects.existOrFail('consoleEditorContainer'); - // }); - }); - - describe('Alternate Solutions', function () { - it('renders Observability content', async () => { - await testSubjects.existOrFail('observabilitySection'); - await testSubjects.existOrFail('exploreLogstashAndBeatsLink'); - await testSubjects.click('exploreLogstashAndBeatsLink'); - await pageObjects.searchHomePage.expectToBeOnObservabilityPage(); - }); - - it('renders SIEM link', async () => { - await testSubjects.existOrFail('setupSiemLink'); - await testSubjects.click('setupSiemLink'); - await pageObjects.searchHomePage.expectToBeOnIngestDataToSecurityPage(); - }); - - it('renders Elastic Defend link', async () => { - await testSubjects.existOrFail('setupElasticDefendLink'); - await testSubjects.click('setupElasticDefendLink'); - await pageObjects.searchHomePage.expectToBeOnInstallElasticDefendPage(); - }); - - it('renders Cloud Security Posture Management link', async () => { - await testSubjects.existOrFail('cloudSecurityPostureManagementLink'); - await testSubjects.click('cloudSecurityPostureManagementLink'); - await pageObjects.searchHomePage.expectToBeOnCloudSecurityPosturePage(); - }); - }); - - describe('Dive deeper with Elasticsearch', function () { - it('renders Search labs content', async () => { - await testSubjects.existOrFail('searchLabsSection'); - await testSubjects.existOrFail('searchLabsButton'); - await testSubjects.click('searchLabsButton'); - await pageObjects.searchHomePage.expectToBeOnSearchLabsPage(); - }); - - it('renders Open Notebooks content', async () => { - await testSubjects.existOrFail('pythonNotebooksSection'); - await testSubjects.existOrFail('openNotebooksButton'); - await testSubjects.click('openNotebooksButton'); - await pageObjects.searchHomePage.expectToBeOnNotebooksExamplesPage(); - }); - - it('renders Elasticsearch Documentation content', async () => { - await testSubjects.existOrFail('elasticsearchDocumentationSection'); - await testSubjects.existOrFail('viewDocumentationButton'); - await testSubjects.click('viewDocumentationButton'); - await pageObjects.searchHomePage.expectToBeOnGetStartedDocumentationPage(); - }); - }); - - describe('Footer content', function () { - it('displays the community link', async () => { - await testSubjects.existOrFail('elasticCommunityLink'); - await testSubjects.click('elasticCommunityLink'); - await pageObjects.searchHomePage.expectToBeOnCommunityPage(); - }); - - it('displays the feedbacks link', async () => { - await testSubjects.existOrFail('giveFeedbackLink'); - await testSubjects.click('giveFeedbackLink'); - await pageObjects.searchHomePage.expectToBeOnGiveFeedbackPage(); - }); - }); - }); - - describe('as admin', function () { - before(async () => { - await es.indices.create({ index: 'test-my-index-001' }); - await pageObjects.svlCommonPage.loginAsAdmin(); - }); - - after(async () => { - await deleteAllTestIndices(); - }); - - it('goes to the home page if there exists at least one index', async () => { - await pageObjects.common.navigateToApp('searchHomepage'); - await pageObjects.searchHomePage.expectToBeOnHomepage(); - }); - - describe('Elasticsearch endpoint and API Keys', function () { - it('renders Elasticsearch endpoint with copy functionality', async () => { - await testSubjects.existOrFail('copyEndpointButton'); - await testSubjects.existOrFail('endpointValueField'); - }); - - it('renders API keys buttons and active badge correctly', async () => { - await testSubjects.existOrFail('createApiKeyButton'); - await testSubjects.existOrFail('manageApiKeysButton'); - await testSubjects.existOrFail('activeApiKeysBadge'); - }); - it('opens API keys management page on clicking Manage API Keys', async () => { - await pageObjects.searchHomePage.clickManageApiKeysLink(); - await pageObjects.searchHomePage.expectToBeOnManageApiKeysPage(); - }); - }); - - describe('Sample data section', function () { - it('renders the sample data section', async () => { - await pageObjects.common.navigateToApp('searchHomepage'); - await testSubjects.existOrFail('sampleDataSection'); - await testSubjects.existOrFail('installSampleBtn'); - }); - - describe('when sample-data-elasticsearch index exists', function () { - before(async () => { - await es.indices.create({ index: 'sample-data-elasticsearch' }); - await pageObjects.common.navigateToApp('searchHomepage'); - }); - - after(async () => { - await esDeleteAllIndices(['sample-data-elasticsearch']); - }); - - it('renders the "View data" button', async () => { - await testSubjects.existOrFail('viewDataBtn'); - }); - }); - }); - }); - - describe('as developer', function () { - before(async () => { - await es.indices.create({ index: 'test-my-index-001' }); - await pageObjects.svlCommonPage.loginAsDeveloper(); - }); - - after(async () => { - await deleteAllTestIndices(); - }); - - it('goes to the home page if there exists at least one index', async () => { - await pageObjects.common.navigateToApp('searchHomepage'); - await pageObjects.searchHomePage.expectToBeOnHomepage(); - }); - - describe('Elasticsearch endpoint and API Keys', function () { - it('renders Elasticsearch endpoint with copy functionality', async () => { - await testSubjects.existOrFail('copyEndpointButton'); - await testSubjects.existOrFail('endpointValueField'); - }); - - it('renders API keys buttons and active badge correctly', async () => { - await testSubjects.existOrFail('createApiKeyButton'); - await testSubjects.existOrFail('manageApiKeysButton'); - await testSubjects.existOrFail('activeApiKeysBadge'); - }); - it('opens API keys management page on clicking Manage API Keys', async () => { - await pageObjects.searchHomePage.clickManageApiKeysLink(); - await pageObjects.searchHomePage.expectToBeOnManageApiKeysPage(); - }); - }); - - describe('Sample data section', function () { - it('renders the sample data section', async () => { - await pageObjects.common.navigateToApp('searchHomepage'); - await testSubjects.existOrFail('sampleDataSection'); - await testSubjects.existOrFail('installSampleBtn'); - }); - - describe('when sample-data-elasticsearch index exists', function () { - before(async () => { - await es.indices.create({ index: 'sample-data-elasticsearch' }); - await pageObjects.common.navigateToApp('searchHomepage'); - }); - - after(async () => { - await esDeleteAllIndices(['sample-data-elasticsearch']); - }); - - it('renders the "View data" button', async () => { - await testSubjects.existOrFail('viewDataBtn'); - }); - }); - }); - }); - }); -}