diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index 3fc5d45dafe3e..c9826e5fca03e 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -140,7 +140,7 @@ pageLoadAssetSize: screenshotMode: 2351 screenshotting: 3252 searchAssistant: 6150 - searchGettingStarted: 6600 + searchGettingStarted: 7327 searchHomepage: 7962 searchIndices: 9991 searchInferenceEndpoints: 8071 diff --git a/x-pack/solutions/search/plugins/search_getting_started/public/components/footer/doc_links.ts b/x-pack/solutions/search/plugins/search_getting_started/public/common/doc_links.ts similarity index 100% rename from x-pack/solutions/search/plugins/search_getting_started/public/components/footer/doc_links.ts rename to x-pack/solutions/search/plugins/search_getting_started/public/common/doc_links.ts diff --git a/x-pack/solutions/search/plugins/search_getting_started/public/components/connect_code/code_box.tsx b/x-pack/solutions/search/plugins/search_getting_started/public/components/connect_code/code_box.tsx index 5c75c902b7389..dbdb792df4c52 100644 --- a/x-pack/solutions/search/plugins/search_getting_started/public/components/connect_code/code_box.tsx +++ b/x-pack/solutions/search/plugins/search_getting_started/public/components/connect_code/code_box.tsx @@ -45,7 +45,13 @@ export const CodeBox = ({ selectedLanguage, codeBlockLanguage }: Props) => { }, [selectedExample, codeParams]); return ( - + {codeExample} ); diff --git a/x-pack/solutions/search/plugins/search_getting_started/public/components/footer/footer_links.tsx b/x-pack/solutions/search/plugins/search_getting_started/public/components/footer/footer_links.tsx deleted file mode 100644 index 5d699350b3b6d..0000000000000 --- a/x-pack/solutions/search/plugins/search_getting_started/public/components/footer/footer_links.tsx +++ /dev/null @@ -1,66 +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 { i18n } from '@kbn/i18n'; -import { docLinks } from './doc_links'; - -export interface DocLinkItem { - id: string; - title: string; - description: string; - buttonLabel: string; - buttonHref: string; - dataTestSubj: string; -} - -export const footerLinks: DocLinkItem[] = [ - { - id: 'searchLabs', - title: i18n.translate('xpack.gettingStarted.searchLabs.title', { - defaultMessage: 'Search Labs', - }), - description: i18n.translate('xpack.gettingStarted.searchLabs.description', { - defaultMessage: - 'Explore the latest articles and tutorials on using Elasticsearch for AI/ML-powered search experiences.', - }), - buttonLabel: i18n.translate('xpack.gettingStarted.searchLabs.buttonText', { - defaultMessage: 'Visit Elasticsearch Labs', - }), - buttonHref: docLinks.visitSearchLabs, - dataTestSubj: 'gettingStartedSearchLabsButton', - }, - { - id: 'pythonNotebooks', - title: i18n.translate('xpack.gettingStarted.pythonNotebooks.title', { - defaultMessage: 'Python notebooks', - }), - description: i18n.translate('xpack.gettingStarted.pythonNotebooks.description', { - defaultMessage: - 'A range of executable Python notebooks available to easily test features in a virtual environment.', - }), - buttonLabel: i18n.translate('xpack.gettingStarted.pythonNotebooks.buttonText', { - defaultMessage: 'Browse our notebooks', - }), - buttonHref: docLinks.notebooksExamples, - dataTestSubj: 'gettingStartedOpenNotebooksButton', - }, - { - id: 'elasticsearchDocs', - title: i18n.translate('xpack.gettingStarted.elasticsearchDocs.title', { - defaultMessage: 'Elasticsearch documentation', - }), - description: i18n.translate('xpack.gettingStarted.elasticsearchDocumentation.description', { - defaultMessage: - 'Comprehensive reference material to help you learn, build, and deploy search solutions with Elasticsearch.', - }), - buttonLabel: i18n.translate('xpack.gettingStarted.elasticsearchDocumentation.buttonText', { - defaultMessage: 'View documentation', - }), - buttonHref: docLinks.elasticsearchDocs, - dataTestSubj: 'gettingStartedViewDocumentationButton', - }, -]; diff --git a/x-pack/solutions/search/plugins/search_getting_started/public/components/footer/index.tsx b/x-pack/solutions/search/plugins/search_getting_started/public/components/footer/index.tsx index 1fb2f19a951b0..000c6d50038a6 100644 --- a/x-pack/solutions/search/plugins/search_getting_started/public/components/footer/index.tsx +++ b/x-pack/solutions/search/plugins/search_getting_started/public/components/footer/index.tsx @@ -13,24 +13,82 @@ import { EuiSpacer, useCurrentEuiBreakpoint, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + import { DocCallouts } from './doc_callouts'; -import { footerLinks } from './footer_links'; +import { docLinks } from '../../common/doc_links'; +interface DocLinkItem { + id: string; + title: string; + description: string; + buttonLabel: string; + buttonHref: string; + dataTestSubj: string; +} export const GettingStartedFooter = () => { const currentBreakpoint = useCurrentEuiBreakpoint(); + + const footerLinks: DocLinkItem[] = [ + { + id: 'searchLabs', + title: i18n.translate('xpack.gettingStarted.searchLabs.title', { + defaultMessage: 'Search Labs', + }), + description: i18n.translate('xpack.gettingStarted.searchLabs.description', { + defaultMessage: + 'Explore the latest articles and tutorials on using Elasticsearch for AI/ML-powered search experiences.', + }), + buttonLabel: i18n.translate('xpack.gettingStarted.searchLabs.buttonText', { + defaultMessage: 'Visit Elasticsearch Labs', + }), + buttonHref: docLinks.visitSearchLabs, + dataTestSubj: 'gettingStartedSearchLabs', + }, + { + id: 'pythonNotebooks', + title: i18n.translate('xpack.gettingStarted.pythonNotebooks.title', { + defaultMessage: 'Python notebooks', + }), + description: i18n.translate('xpack.gettingStarted.pythonNotebooks.description', { + defaultMessage: + 'A range of executable Python notebooks available to easily test features in a virtual environment.', + }), + buttonLabel: i18n.translate('xpack.gettingStarted.pythonNotebooks.buttonText', { + defaultMessage: 'Browse our notebooks', + }), + buttonHref: docLinks.notebooksExamples, + dataTestSubj: 'gettingStartedOpenNotebooks', + }, + { + id: 'elasticsearchDocs', + title: i18n.translate('xpack.gettingStarted.elasticsearchDocs.title', { + defaultMessage: 'Elasticsearch documentation', + }), + description: i18n.translate('xpack.gettingStarted.elasticsearchDocumentation.description', { + defaultMessage: + 'Comprehensive reference material to help you learn, build, and deploy search solutions with Elasticsearch.', + }), + buttonLabel: i18n.translate('xpack.gettingStarted.elasticsearchDocumentation.buttonText', { + defaultMessage: 'View documentation', + }), + buttonHref: docLinks.elasticsearchDocs, + dataTestSubj: 'gettingStartedViewDocumentation', + }, + ]; return ( <> {footerLinks.map((item) => ( - + ))} diff --git a/x-pack/solutions/search/plugins/search_getting_started/public/components/header/index.tsx b/x-pack/solutions/search/plugins/search_getting_started/public/components/header/index.tsx index e78aaf7ce057c..1f804ac304cf2 100644 --- a/x-pack/solutions/search/plugins/search_getting_started/public/components/header/index.tsx +++ b/x-pack/solutions/search/plugins/search_getting_started/public/components/header/index.tsx @@ -71,7 +71,7 @@ export const SearchGettingStartedHeader: React.FC = () => { { application.navigateToApp(SEARCH_HOMEPAGE); }} diff --git a/x-pack/solutions/search/plugins/search_getting_started/public/components/search_getting_started.tsx b/x-pack/solutions/search/plugins/search_getting_started/public/components/search_getting_started.tsx index e91c79d6dbf58..e1a32418b110f 100644 --- a/x-pack/solutions/search/plugins/search_getting_started/public/components/search_getting_started.tsx +++ b/x-pack/solutions/search/plugins/search_getting_started/public/components/search_getting_started.tsx @@ -25,16 +25,16 @@ export const SearchGettingStartedPage: React.FC = () => { return ( - + - + - + diff --git a/x-pack/solutions/search/plugins/search_getting_started/public/components/tutorials/console_tutorials_group.tsx b/x-pack/solutions/search/plugins/search_getting_started/public/components/tutorials/console_tutorials_group.tsx index d9be800a6ec4c..b8e9a10c59c24 100644 --- a/x-pack/solutions/search/plugins/search_getting_started/public/components/tutorials/console_tutorials_group.tsx +++ b/x-pack/solutions/search/plugins/search_getting_started/public/components/tutorials/console_tutorials_group.tsx @@ -114,6 +114,7 @@ export const ConsoleTutorialsGroup = () => { onClick={() => { tutorial.buttonRef.current?.click(); }} + data-test-subj={tutorial.dataTestSubj} footer={ { sharePlugin={share} consolePlugin={consolePlugin} telemetryId={tutorial.dataTestSubj} - data-test-subj={tutorial.dataTestSubj} + data-test-subj={`${tutorial.dataTestSubj}-btn`} buttonProps={{ buttonRef: tutorial.buttonRef }} content={ { loadTestFile(require.resolve('./apps/shared/solution_tour')); // add tests that require feature flags, defined in config.feature_flags.ts loadTestFile(require.resolve('./tests/agent_builder')); + loadTestFile(require.resolve('./tests/search_getting_started')); }); }; diff --git a/x-pack/solutions/search/test/functional_search/page_objects/search_navigation.ts b/x-pack/solutions/search/test/functional_search/page_objects/search_navigation.ts index cbad0c787a18f..2a63f18032178 100644 --- a/x-pack/solutions/search/test/functional_search/page_objects/search_navigation.ts +++ b/x-pack/solutions/search/test/functional_search/page_objects/search_navigation.ts @@ -33,6 +33,14 @@ export function SearchNavigationProvider({ getService, getPageObjects }: FtrProv }); }); }, + async navigateToElasticsearchSearchGettingStartedPage(basePath?: string) { + await retry.tryForTime(60 * 1000, async () => { + await common.navigateToApp('searchGettingStarted', { + shouldLoginIfPrompted: false, + basePath, + }); + }); + }, async navigateToIndexDetailPage(indexName: string) { await solutionNavigation.sidenav.expectLinkExists({ navId: 'data_management' }); await solutionNavigation.sidenav.clickLink({ diff --git a/x-pack/solutions/search/test/functional_search/tests/search_getting_started.ts b/x-pack/solutions/search/test/functional_search/tests/search_getting_started.ts new file mode 100644 index 0000000000000..0332310c7bd65 --- /dev/null +++ b/x-pack/solutions/search/test/functional_search/tests/search_getting_started.ts @@ -0,0 +1,195 @@ +/* + * 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([ + 'common', + 'embeddedConsole', + 'apiKeys', + 'searchGettingStarted', + 'searchHomePage', + 'searchNavigation', + ]); + const searchSpace = getService('searchSpace'); + const browser = getService('browser'); + const testSubjects = getService('testSubjects'); + const retry = getService('retry'); + + describe('Search Getting Started page', function () { + describe('Solution Nav - Search', function () { + let cleanUp: () => Promise; + let spaceCreated: { id: string } = { id: '' }; + + before(async () => { + ({ cleanUp, spaceCreated } = await searchSpace.createTestSpace( + 'search-getting-started-ftr' + )); + await searchSpace.navigateTo(spaceCreated.id); + }); + + after(async () => { + // Clean up space created + await cleanUp(); + }); + + describe('Getting Started page', function () { + beforeEach(async () => { + await pageObjects.searchNavigation.navigateToElasticsearchSearchGettingStartedPage(); + }); + + it('load search getting started', async () => { + await pageObjects.searchGettingStarted.expectSearchGettingStartedIsLoaded(); + }); + it('should have embedded dev console', async () => { + await testHasEmbeddedConsole(pageObjects); + }); + }); + + describe('Getting Started page interactions', function () { + beforeEach(async () => { + await pageObjects.searchNavigation.navigateToElasticsearchSearchGettingStartedPage(); + }); + + describe('Add data button', function () { + it('navigates to the upload file page when option is selected', async () => { + await pageObjects.searchGettingStarted.selectAddDataOption( + 'gettingStartedUploadMenuItem' + ); + await retry.tryWithRetries( + 'wait for URL to change', + async () => { + expect(await browser.getCurrentUrl()).to.contain('/tutorial_directory/fileDataViz'); + }, + { initialDelay: 200, retryCount: 5, retryDelay: 500 } + ); + }); + it('navigates to the sample data page when option is selected', async () => { + await pageObjects.searchGettingStarted.selectAddDataOption( + 'gettingStartedSampleDataMenuItem' + ); + await retry.tryWithRetries( + 'wait for URL to change', + async () => { + expect(await browser.getCurrentUrl()).to.contain('/tutorial_directory/sampleData'); + }, + { initialDelay: 200, retryCount: 5, retryDelay: 500 } + ); + }); + it('navigates to the empty index page when option is selected', async () => { + await pageObjects.searchGettingStarted.selectAddDataOption( + 'gettingStartedCreateIndexMenuItem' + ); + + await retry.tryWithRetries( + 'wait for URL to change', + async () => { + expect(await browser.getCurrentUrl()).to.contain('/indices/create'); + }, + { initialDelay: 200, retryCount: 5, retryDelay: 500 } + ); + }); + }); + + describe('Skip and go to Home button', function () { + it('navigates to the home page when clicked', async () => { + await testSubjects.click('skipAndGoHomeBtn'); + await pageObjects.searchHomePage.expectToBeOnHomepage(); + }); + }); + + describe('Elasticsearch endpoint', function () { + it('renders endpoint field and copy button', async () => { + await testSubjects.existOrFail('endpointValueField'); + await testSubjects.existOrFail('copyEndpointButton'); + const endpointValue = await testSubjects.getVisibleText('endpointValueField'); + expect(endpointValue).to.contain('https://'); + }); + }); + + describe('View connection details', function () { + it('renders the view connection details button', async () => { + await testSubjects.existOrFail('viewConnectionDetailsLink'); + }); + it('opens the connection flyout when the button is clicked', async () => { + await testSubjects.click('viewConnectionDetailsLink'); + await testSubjects.existOrFail('connectionDetailsModalTitle'); + }); + }); + + describe('Explore the API', function () { + it('renders all the tutorial cards', async () => { + await testSubjects.existOrFail('console_tutorials_search_basics'); + await testSubjects.existOrFail('console_tutorials_semantic_search'); + await testSubjects.existOrFail('console_tutorials_esql'); + }); + it('renders all the tutorial card buttons', async () => { + await testSubjects.existOrFail('console_tutorials_search_basics-btn'); + await testSubjects.existOrFail('console_tutorials_semantic_search-btn'); + await testSubjects.existOrFail('console_tutorials_esql-btn'); + }); + it('opens the console when you click the search basics tutorial card', async () => { + await testSubjects.existOrFail('console_tutorials_search_basics'); + await testSubjects.click('console_tutorials_search_basics'); + await pageObjects.embeddedConsole.expectEmbeddedConsoleToBeOpen(); + await pageObjects.embeddedConsole.clickEmbeddedConsoleControlBar(); + await pageObjects.embeddedConsole.expectEmbeddedConsoleToBeClosed(); + }); + it('opens the console when you click the semantic search tutorial button', async () => { + await testSubjects.existOrFail('console_tutorials_semantic_search-btn'); + const tutorialButton = await testSubjects.find('console_tutorials_semantic_search-btn'); + await tutorialButton.scrollIntoView(); + await tutorialButton.click(); + await pageObjects.embeddedConsole.expectEmbeddedConsoleToBeOpen(); + await pageObjects.embeddedConsole.clickEmbeddedConsoleControlBar(); + await pageObjects.embeddedConsole.expectEmbeddedConsoleToBeClosed(); + }); + }); + + describe('Connect to your application', function () { + it('renders the JavaScript code example when selected in Language Selector', async () => { + await pageObjects.searchGettingStarted.selectCodingLanguage('javascript'); + await pageObjects.searchGettingStarted.expectCodeSampleContainsValue( + 'import { Client } from' + ); + }); + it('renders the cURL code example when selected in Language Selector', async () => { + await pageObjects.searchGettingStarted.selectCodingLanguage('curl'); + await pageObjects.searchGettingStarted.expectCodeSampleContainsValue('curl -X PUT'); + }); + it('renders the Python code example when selected in Language Selector', async () => { + await pageObjects.searchGettingStarted.selectCodingLanguage('python'); + await pageObjects.searchGettingStarted.expectCodeSampleContainsValue( + 'from elasticsearch import' + ); + }); + }); + + describe('Footer content', function () { + it('renders Search Labs callout and navigates correctly', async () => { + const href = await testSubjects.getAttribute('gettingStartedSearchLabs-btn', 'href'); + expect(href).to.contain('search-labs'); + }); + it('renders Python Notebooks callout and navigates correctly', async () => { + const href = await testSubjects.getAttribute('gettingStartedOpenNotebooks-btn', 'href'); + expect(href).to.contain('search-labs/tutorials/examples'); + }); + it('renders Elasticsearch Documentation callout and navigates correctly', async () => { + const href = await testSubjects.getAttribute( + 'gettingStartedViewDocumentation-btn', + 'href' + ); + expect(href).to.contain('docs/solutions/search/get-started'); + }); + }); + }); + }); + }); +} diff --git a/x-pack/solutions/search/test/page_objects/index.ts b/x-pack/solutions/search/test/page_objects/index.ts index 7844e635b5dfd..2be196001903b 100644 --- a/x-pack/solutions/search/test/page_objects/index.ts +++ b/x-pack/solutions/search/test/page_objects/index.ts @@ -6,6 +6,7 @@ */ import { SearchInferenceManagementPageProvider } from './inference_management_page'; +import { SearchGettingStartedProvider } from './search_getting_started_page'; import { SearchHomePageProvider } from './search_homepage'; import { SearchIndexDetailPageProvider } from './search_index_details_page'; import { SearchPlaygroundPageProvider } from './search_playground_page'; @@ -14,6 +15,7 @@ import { SearchSynonymsPageProvider } from './search_synonyms_page'; export const searchSharedPageObjects = { searchHomePage: SearchHomePageProvider, + searchGettingStarted: SearchGettingStartedProvider, searchIndexDetailsPage: SearchIndexDetailPageProvider, searchInferenceManagementPage: SearchInferenceManagementPageProvider, searchPlayground: SearchPlaygroundPageProvider, diff --git a/x-pack/solutions/search/test/page_objects/search_getting_started_page.ts b/x-pack/solutions/search/test/page_objects/search_getting_started_page.ts new file mode 100644 index 0000000000000..e38b6fc71696b --- /dev/null +++ b/x-pack/solutions/search/test/page_objects/search_getting_started_page.ts @@ -0,0 +1,44 @@ +/* + * 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'; + +export function SearchGettingStartedProvider({ getService }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + const browser = getService('browser'); + + return { + async expectSearchGettingStartedIsLoaded() { + await testSubjects.existOrFail('search-getting-started', { timeout: 2000 }); + }, + async expectToBeOnGettingStartedPage() { + expect(await browser.getCurrentUrl()).contain('/app/elasticsearch/getting_started'); + }, + async expectToNotBeOnGettingStartedPage() { + expect(await browser.getCurrentUrl()).not.contain('/app/elasticsearch/getting_started'); + }, + async selectAddDataOption(optionDataTestSubj: string) { + await testSubjects.click('gettingStartedAddDataButton'); + await testSubjects.click(optionDataTestSubj); + }, + async selectCodingLanguage(language: string) { + await testSubjects.existOrFail('codeExampleLanguageSelect'); + await testSubjects.click('codeExampleLanguageSelect'); + await testSubjects.existOrFail(`lang-option-${language}`); + await testSubjects.click(`lang-option-${language}`); + expect( + (await testSubjects.getVisibleText('codeExampleLanguageSelect')).toLowerCase() + ).contain(language); + }, + async expectCodeSampleContainsValue(value: string) { + const tstSubjId = 'gettingStartedExampleCode'; + await testSubjects.existOrFail(tstSubjId); + expect(await testSubjects.getVisibleText(tstSubjId)).contain(value); + }, + }; +} diff --git a/x-pack/solutions/search/test/serverless/functional/configs/config.feature_flags.ts b/x-pack/solutions/search/test/serverless/functional/configs/config.feature_flags.ts index c7b43f9f90bd6..505695014e550 100644 --- a/x-pack/solutions/search/test/serverless/functional/configs/config.feature_flags.ts +++ b/x-pack/solutions/search/test/serverless/functional/configs/config.feature_flags.ts @@ -25,6 +25,8 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ...baseConfig.get('kbnTestServer.serverArgs'), `--uiSettings.overrides.agentBuilder:enabled=true`, `--uiSettings.overrides.searchPlayground:searchModeEnabled=true`, + '--uiSettings.overrides.hideAnnouncements=true', + '--feature_flags.overrides.searchSolution.gettingStartedEnabled=true', ], }, // load tests in the index file diff --git a/x-pack/solutions/search/test/serverless/functional/configs/config.ts b/x-pack/solutions/search/test/serverless/functional/configs/config.ts index 3344e7a4fcf1e..fa6d185fa46ad 100644 --- a/x-pack/solutions/search/test/serverless/functional/configs/config.ts +++ b/x-pack/solutions/search/test/serverless/functional/configs/config.ts @@ -59,5 +59,8 @@ export default createTestConfig({ searchQueryRules: { pathname: '/app/elasticsearch/query_rules', }, + searchGettingStarted: { + pathname: '/app/elasticsearch/getting_started', + }, }, }); diff --git a/x-pack/solutions/search/test/serverless/functional/configs/index.feature_flags.ts b/x-pack/solutions/search/test/serverless/functional/configs/index.feature_flags.ts index 8f0549d0fce65..492ba5d22dd41 100644 --- a/x-pack/solutions/search/test/serverless/functional/configs/index.feature_flags.ts +++ b/x-pack/solutions/search/test/serverless/functional/configs/index.feature_flags.ts @@ -12,5 +12,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { // add tests that require feature flags, defined in config.feature_flags.ts loadTestFile(require.resolve('../test_suites/agent_builder')); loadTestFile(require.resolve('../test_suites/search_playground/search_relevance')); + loadTestFile(require.resolve('../test_suites/search_getting_started')); }); } diff --git a/x-pack/solutions/search/test/serverless/functional/test_suites/search_getting_started.ts b/x-pack/solutions/search/test/serverless/functional/test_suites/search_getting_started.ts new file mode 100644 index 0000000000000..dda8c5647b7d8 --- /dev/null +++ b/x-pack/solutions/search/test/serverless/functional/test_suites/search_getting_started.ts @@ -0,0 +1,238 @@ +/* + * 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([ + 'svlCommonPage', + 'svlCommonNavigation', + 'searchHomePage', + 'embeddedConsole', + 'common', + 'apiKeys', + 'searchGettingStarted', + ]); + const browser = getService('browser'); + const testSubjects = getService('testSubjects'); + const retry = getService('retry'); + + describe('Search Getting Started page', function () { + describe('as viewer', function () { + before(async () => { + await pageObjects.svlCommonPage.loginAsViewer(); + }); + + describe('Getting Started page', function () { + beforeEach(async () => { + await pageObjects.common.navigateToApp('searchGettingStarted'); + }); + + it('load search getting started', async () => { + await pageObjects.searchGettingStarted.expectSearchGettingStartedIsLoaded(); + }); + it('should have embedded dev console', async () => { + await testHasEmbeddedConsole(pageObjects); + }); + }); + + describe('Getting Started page interactions', function () { + beforeEach(async () => { + await pageObjects.common.navigateToApp('searchGettingStarted'); + }); + + describe('Add data button', function () { + it('navigates to the sample data page when option is selected', async () => { + await pageObjects.searchGettingStarted.selectAddDataOption( + 'gettingStartedSampleDataMenuItem' + ); + await retry.tryWithRetries( + 'wait for URL to change', + async () => { + expect(await browser.getCurrentUrl()).to.contain('/tutorial_directory/sampleData'); + }, + { initialDelay: 200, retryCount: 5, retryDelay: 500 } + ); + }); + }); + + describe('Elasticsearch endpoint and API Keys', function () { + it('renders endpoint field and copy button', async () => { + await testSubjects.existOrFail('endpointValueField'); + await testSubjects.existOrFail('copyEndpointButton'); + const endpointValue = await testSubjects.getVisibleText('endpointValueField'); + expect(endpointValue).to.contain('https://'); + await testSubjects.existOrFail('apiKeyFormNoUserPrivileges'); + }); + }); + + describe('View connection details', function () { + it('renders the view connection details button', async () => { + await testSubjects.existOrFail('viewConnectionDetailsLink'); + }); + it('opens the connection flyout when the button is clicked', async () => { + await testSubjects.click('viewConnectionDetailsLink'); + await testSubjects.existOrFail('connectionDetailsModalTitle'); + }); + }); + + describe('Connect to your application', function () { + it('renders the JavaScript code example when selected in Language Selector', async () => { + await pageObjects.searchGettingStarted.selectCodingLanguage('javascript'); + await pageObjects.searchGettingStarted.expectCodeSampleContainsValue( + 'import { Client } from' + ); + }); + }); + + describe('Footer content', function () { + it('renders Python Notebooks callout and navigates correctly', async () => { + const href = await testSubjects.getAttribute('gettingStartedOpenNotebooks-btn', 'href'); + expect(href).to.contain('search-labs/tutorials/examples'); + }); + }); + }); + }); + + describe('as developer', function () { + before(async () => { + await pageObjects.svlCommonPage.loginAsDeveloper(); + }); + + describe('Getting Started page interactions', function () { + beforeEach(async () => { + await pageObjects.common.navigateToApp('searchGettingStarted'); + }); + + describe('Add data button', function () { + it('navigates to the upload file page when option is selected', async () => { + await pageObjects.searchGettingStarted.selectAddDataOption( + 'gettingStartedUploadMenuItem' + ); + await retry.tryWithRetries( + 'wait for URL to change', + async () => { + expect(await browser.getCurrentUrl()).to.contain('/tutorial_directory/fileDataViz'); + }, + { initialDelay: 200, retryCount: 5, retryDelay: 500 } + ); + }); + it('navigates to the sample data page when option is selected', async () => { + await pageObjects.searchGettingStarted.selectAddDataOption( + 'gettingStartedSampleDataMenuItem' + ); + await retry.tryWithRetries( + 'wait for URL to change', + async () => { + expect(await browser.getCurrentUrl()).to.contain('/tutorial_directory/sampleData'); + }, + { initialDelay: 200, retryCount: 5, retryDelay: 500 } + ); + }); + it('navigates to the empty index page when option is selected', async () => { + await pageObjects.searchGettingStarted.selectAddDataOption( + 'gettingStartedCreateIndexMenuItem' + ); + + await retry.tryWithRetries( + 'wait for URL to change', + async () => { + expect(await browser.getCurrentUrl()).to.contain('/indices/create'); + }, + { initialDelay: 200, retryCount: 5, retryDelay: 500 } + ); + }); + }); + + describe('Skip and go to Home button', function () { + it('navigates to the home page when clicked', async () => { + await testSubjects.click('skipAndGoHomeBtn'); + await pageObjects.searchHomePage.expectToBeOnHomepage(); + }); + }); + + describe('View connection details', function () { + it('renders the view connection details button', async () => { + await testSubjects.existOrFail('viewConnectionDetailsLink'); + }); + it('opens the connection flyout when the button is clicked', async () => { + await testSubjects.click('viewConnectionDetailsLink'); + await testSubjects.existOrFail('connectionDetailsModalTitle'); + }); + }); + + describe('Explore the API', function () { + it('renders all the tutorial cards', async () => { + await testSubjects.existOrFail('console_tutorials_search_basics'); + await testSubjects.existOrFail('console_tutorials_semantic_search'); + await testSubjects.existOrFail('console_tutorials_esql'); + }); + it('renders all the tutorial card buttons', async () => { + await testSubjects.existOrFail('console_tutorials_search_basics-btn'); + await testSubjects.existOrFail('console_tutorials_semantic_search-btn'); + await testSubjects.existOrFail('console_tutorials_esql-btn'); + }); + it('opens the console when you click the search basics tutorial card', async () => { + await testSubjects.existOrFail('console_tutorials_search_basics'); + await testSubjects.click('console_tutorials_search_basics'); + await pageObjects.embeddedConsole.expectEmbeddedConsoleToBeOpen(); + await pageObjects.embeddedConsole.clickEmbeddedConsoleControlBar(); + await pageObjects.embeddedConsole.expectEmbeddedConsoleToBeClosed(); + }); + it('opens the console when you click the semantic search tutorial button', async () => { + await testSubjects.existOrFail('console_tutorials_semantic_search-btn'); + const tutorialButton = await testSubjects.find('console_tutorials_semantic_search-btn'); + await tutorialButton.scrollIntoView(); + await tutorialButton.click(); + await pageObjects.embeddedConsole.expectEmbeddedConsoleToBeOpen(); + await pageObjects.embeddedConsole.clickEmbeddedConsoleControlBar(); + await pageObjects.embeddedConsole.expectEmbeddedConsoleToBeClosed(); + }); + }); + + describe('Connect to your application', function () { + it('renders the JavaScript code example when selected in Language Selector', async () => { + await pageObjects.searchGettingStarted.selectCodingLanguage('javascript'); + await pageObjects.searchGettingStarted.expectCodeSampleContainsValue( + 'import { Client } from' + ); + }); + it('renders the cURL code example when selected in Language Selector', async () => { + await pageObjects.searchGettingStarted.selectCodingLanguage('curl'); + await pageObjects.searchGettingStarted.expectCodeSampleContainsValue('curl -X PUT'); + }); + it('renders the Python code example when selected in Language Selector', async () => { + await pageObjects.searchGettingStarted.selectCodingLanguage('python'); + await pageObjects.searchGettingStarted.expectCodeSampleContainsValue( + 'from elasticsearch import' + ); + }); + }); + + describe('Footer content', function () { + it('renders Search Labs callout and navigates correctly', async () => { + const href = await testSubjects.getAttribute('gettingStartedSearchLabs-btn', 'href'); + expect(href).to.contain('search-labs'); + }); + it('renders Python Notebooks callout and navigates correctly', async () => { + const href = await testSubjects.getAttribute('gettingStartedOpenNotebooks-btn', 'href'); + expect(href).to.contain('search-labs/tutorials/examples'); + }); + it('renders Elasticsearch Documentation callout and navigates correctly', async () => { + const href = await testSubjects.getAttribute( + 'gettingStartedViewDocumentation-btn', + 'href' + ); + expect(href).to.contain('docs/solutions/search/get-started'); + }); + }); + }); + }); + }); +}