[Search] [Playground] FTR tests (#183329)

Approach with different configs for kibana ui and serverless was peek
out from security_solution test. 48 serverless config files are defined
in the test folder.

Test: no index

check no index message
Test: no connector

Add Index of example data (can be 10 docs into elasticsearch, BM25)
Add a connector (showing the modal)
verify the modal is shown
Test: with connector

seed ES with a connector in the test
Ask a question
Validate the connector has been called and respond back
validate the response is returned
validate the view query can be opened and content (query + fields) is as
expected
validate the edit context is can be opened and the fields is as expected
This commit is contained in:
Yan Savitski 2024-05-20 16:18:11 +02:00 committed by GitHub
parent e450763e12
commit a9cb7d2423
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 456 additions and 50 deletions

View file

@ -322,6 +322,7 @@ enabled:
- x-pack/test/functional/apps/saved_query_management/config.ts
- x-pack/test/functional/apps/security/config.ts
- x-pack/test/functional/apps/slo/embeddables/config.ts
- x-pack/test/functional/apps/search_playground/config.ts
- x-pack/test/functional/apps/snapshot_restore/config.ts
- x-pack/test/functional/apps/spaces/config.ts
- x-pack/test/functional/apps/spaces/in_solution_navigation/config.ts

View file

@ -7,7 +7,7 @@
import { i18n } from '@kbn/i18n';
import React, { useMemo } from 'react';
import { EuiBetaBadge, EuiFlexGroup, EuiFlexItem, EuiPageTemplate } from '@elastic/eui';
import { EuiBetaBadge, EuiFlexGroup, EuiFlexItem, EuiPageTemplate, EuiTitle } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
import { PlaygroundProvider } from './providers/playground_provider';
@ -39,15 +39,21 @@ export const ChatPlaygroundOverview: React.FC = () => {
grow={false}
>
<EuiPageTemplate.Header
css={{ '.euiPageHeaderContent > .euiFlexGroup': { flexWrap: 'wrap' } }}
pageTitle={
<EuiFlexGroup>
<EuiFlexItem grow={false}>
<span data-test-subj="chat-playground-home-page-title">
<FormattedMessage
id="xpack.searchPlayground.pageTitle"
defaultMessage="Playground"
/>
</span>
<EuiTitle
css={{ whiteSpace: 'nowrap' }}
data-test-subj="chat-playground-home-page-title"
>
<h2>
<FormattedMessage
id="xpack.searchPlayground.pageTitle"
defaultMessage="Playground"
/>
</h2>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiBetaBadge

View file

@ -117,6 +117,7 @@ export const Chat = () => {
component="form"
css={{ display: 'flex', flexGrow: 1 }}
onSubmit={handleSubmit(onSubmit)}
data-test-subj="chatPage"
>
<EuiFlexGroup gutterSize="none">
<EuiFlexItem
@ -220,6 +221,7 @@ export const Chat = () => {
isLoading={isSubmitting}
isDisabled={!isValid}
iconType={TelegramIcon}
data-test-subj="sendQuestionButton"
/>
)
}

View file

@ -22,7 +22,11 @@ export const EditContextAction: React.FC = () => {
return (
<>
{showFlyout && <EditContextFlyout onClose={closeFlyout} />}
<EuiButtonEmpty onClick={() => setShowFlyout(true)} disabled={selectedIndices?.length === 0}>
<EuiButtonEmpty
onClick={() => setShowFlyout(true)}
disabled={selectedIndices?.length === 0}
data-test-subj="editContextActionButton"
>
<FormattedMessage
id="xpack.searchPlayground.editContext.actionButtonLabel"
defaultMessage="Edit context"

View file

@ -85,7 +85,7 @@ export const EditContextFlyout: React.FC<EditContextFlyoutProps> = ({ onClose })
}, [usageTracker]);
return (
<EuiFlyout ownFocus onClose={onClose} size="s">
<EuiFlyout ownFocus onClose={onClose} size="s" data-test-subj="editContextFlyout">
<EuiFlyoutHeader hasBorder>
<EuiTitle size="m">
<h2>
@ -172,6 +172,7 @@ export const EditContextFlyout: React.FC<EditContextFlyoutProps> = ({ onClose })
options={group.source_fields.map((field) => ({
value: field,
inputDisplay: field,
'data-test-subj': 'contextField',
}))}
valueOfSelected={tempSourceFields[index]?.[0]}
onChange={(value) => updateSourceField(index, value)}

View file

@ -57,6 +57,7 @@ export const UserMessage: React.FC<UserMessageProps> = ({ content, createdAt })
})}
/>
}
data-test-subj="userMessage"
>
<EuiText size="s" css={UserMessageCSS}>
<p>{content}</p>

View file

@ -66,6 +66,7 @@ export const QuestionInput: React.FC<QuestionInputProps> = ({
onChange={handleChange}
disabled={isDisabled}
resize="none"
data-test-subj="questionInput"
/>
<div

View file

@ -58,6 +58,7 @@ export const AddIndicesField: React.FC<AddIndicesFieldProps> = ({
disabled: selectedIndices.includes(index),
}))}
isClearable={false}
data-test-subj="selectIndicesComboBox"
/>
</EuiFormRow>
);

View file

@ -41,7 +41,7 @@ export const StartNewChat: React.FC<StartNewChatProps> = ({ onStartClick }) => {
}, [usageTracker]);
return (
<EuiFlexGroup justifyContent="center" className="eui-yScroll">
<EuiFlexGroup justifyContent="center" className="eui-yScroll" data-test-subj="startChatPage">
<EuiFlexGroup
css={{
height: 'fit-content',
@ -85,7 +85,7 @@ export const StartNewChat: React.FC<StartNewChatProps> = ({ onStartClick }) => {
<SourcesPanelForStartChat />
</EuiFlexItem>
<EuiFlexGroup justifyContent="flexEnd" data-test-subj="startChatButton">
<EuiFlexGroup justifyContent="flexEnd">
<EuiButton
fill
iconType="arrowRight"
@ -96,6 +96,7 @@ export const StartNewChat: React.FC<StartNewChatProps> = ({ onStartClick }) => {
!watch(ChatFormFields.elasticsearchQuery, '')
}
onClick={onStartClick}
data-test-subj="startChatButton"
>
<FormattedMessage
id="xpack.searchPlayground.startNewChat.startBtn"

View file

@ -26,6 +26,7 @@ export const ViewCodeAction: React.FC = () => {
fill
onClick={() => setShowFlyout(true)}
disabled={!selectedIndices || selectedIndices?.length === 0}
data-test-subj="viewCodeActionButton"
>
<FormattedMessage
id="xpack.searchPlayground.viewCode.actionButtonLabel"

View file

@ -78,7 +78,7 @@ export const ViewCodeFlyout: React.FC<ViewCodeFlyoutProps> = ({ onClose }) => {
}, [usageTracker, selectedLanguage]);
return (
<EuiFlyout ownFocus onClose={onClose}>
<EuiFlyout ownFocus onClose={onClose} data-test-subj="viewCodeFlyout">
<EuiFlyoutHeader hasBorder>
<EuiTitle size="m">
<h2>

View file

@ -20,7 +20,11 @@ export const ViewQueryAction: React.FC = () => {
return (
<>
{showFlyout && <ViewQueryFlyout onClose={() => setShowFlyout(false)} />}
<EuiButtonEmpty onClick={() => setShowFlyout(true)} disabled={selectedIndices?.length === 0}>
<EuiButtonEmpty
onClick={() => setShowFlyout(true)}
disabled={selectedIndices?.length === 0}
data-test-subj="viewQueryActionButton"
>
<FormattedMessage
id="xpack.searchPlayground.viewQuery.actionButtonLabel"
defaultMessage="View query"

View file

@ -126,7 +126,7 @@ export const ViewQueryFlyout: React.FC<ViewQueryFlyoutProps> = ({ onClose }) =>
}, [usageTracker]);
return (
<EuiFlyout ownFocus onClose={onClose} size="l">
<EuiFlyout ownFocus onClose={onClose} size="l" data-test-subj="viewQueryFlyout">
<EuiFlyoutHeader hasBorder>
<EuiTitle size="m">
<h2>
@ -216,6 +216,7 @@ export const ViewQueryFlyout: React.FC<ViewQueryFlyoutProps> = ({ onClose }) =>
/>
),
checked: checked ? 'on' : undefined,
'data-test-subj': 'queryField',
};
})}
listProps={{

View file

@ -0,0 +1,17 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { FtrConfigProviderContext } from '@kbn/test';
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
const functionalConfig = await readConfigFile(require.resolve('../../config.base.js'));
return {
...functionalConfig.getAll(),
testFiles: [require.resolve('.')],
};
}

View file

@ -0,0 +1,13 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { FtrProviderContext } from '../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('playground', async () => {
loadTestFile(require.resolve('./playground_overview.ess.ts'));
});
}

View file

@ -0,0 +1,94 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { FtrProviderContext } from '../../ftr_provider_context';
import { createOpenAIConnector } from './utils/create_openai_connector';
import { MachineLearningCommonAPIProvider } from '../../services/ml/common_api';
const indexName = 'basic_index';
const esArchiveIndex = 'test/api_integration/fixtures/es_archiver/index_patterns/basic_index';
export default function (ftrContext: FtrProviderContext) {
const { getService, getPageObjects } = ftrContext;
const pageObjects = getPageObjects(['common', 'searchPlayground']);
const commonAPI = MachineLearningCommonAPIProvider(ftrContext);
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
const createIndex = async () => await esArchiver.load(esArchiveIndex);
let removeOpenAIConnector: () => Promise<void>;
const createConnector = async () => {
removeOpenAIConnector = await createOpenAIConnector({
supertest,
requestHeader: commonAPI.getCommonRequestHeader(),
});
};
describe('Playground Overview', () => {
before(async () => {
await pageObjects.common.navigateToApp('enterpriseSearchApplications/playground');
});
after(async () => {
await esArchiver.unload(esArchiveIndex);
await removeOpenAIConnector?.();
});
describe('start chat page', () => {
it('playground app is loaded', async () => {
await pageObjects.searchPlayground.PlaygroundStartChatPage.expectPlaygroundStartChatPageComponentsToExist();
await pageObjects.searchPlayground.PlaygroundStartChatPage.expectPlaygroundHeaderComponentsToExist();
});
it('show no index callout', async () => {
await pageObjects.searchPlayground.PlaygroundStartChatPage.expectNoIndexCalloutExists();
await pageObjects.searchPlayground.PlaygroundStartChatPage.expectCreateIndexButtonToExists();
});
it('hide no index callout when index added', async () => {
await createIndex();
await pageObjects.searchPlayground.PlaygroundStartChatPage.expectSelectIndex(indexName);
});
it('show add connector button', async () => {
await pageObjects.searchPlayground.PlaygroundStartChatPage.expectAddConnectorButtonExists();
});
it('click add connector button opens connector flyout', async () => {
await pageObjects.searchPlayground.PlaygroundStartChatPage.expectOpenConnectorPagePlayground();
});
it('hide gen ai panel when connector exists', async () => {
await pageObjects.searchPlayground.PlaygroundStartChatPage.expectHideGenAIPanelConnector(
createConnector
);
});
it('show chat page', async () => {
await pageObjects.searchPlayground.PlaygroundStartChatPage.expectSelectIndex(indexName);
await pageObjects.searchPlayground.PlaygroundStartChatPage.expectToStartChatPage();
});
});
describe('chat page', () => {
it('chat works', async () => {
await pageObjects.searchPlayground.PlaygroundChatPage.expectChatWorks();
});
it('open view code', async () => {
await pageObjects.searchPlayground.PlaygroundChatPage.expectOpenViewCode();
});
it('show fields and code in view query', async () => {
await pageObjects.searchPlayground.PlaygroundChatPage.expectViewQueryHasFields();
});
it('show edit context', async () => {
await pageObjects.searchPlayground.PlaygroundChatPage.expectEditContextOpens();
});
});
});
}

View file

@ -0,0 +1,50 @@
/*
* 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 SuperTest from 'supertest';
export async function createOpenAIConnector({
supertest,
requestHeader = {},
apiKeyHeader = {},
}: {
supertest: SuperTest.Agent;
requestHeader?: Record<string, string>;
apiKeyHeader?: Record<string, string>;
}): Promise<() => Promise<void>> {
const config = {
apiProvider: 'OpenAI',
defaultModel: 'gpt-4',
apiUrl: 'http://localhost:3002',
};
const connector: { id: string } | undefined = (
await supertest
.post('/api/actions/connector')
.set(requestHeader)
.set(apiKeyHeader)
.send({
name: 'test Open AI',
connector_type_id: '.gen-ai',
config,
secrets: {
apiKey: 'genAiApiKey',
},
})
.expect(200)
).body;
return async () => {
if (connector) {
await supertest
.delete(`/api/actions/connector/${connector.id}`)
.set(requestHeader)
.set(apiKeyHeader)
.expect(204);
}
};
}

View file

@ -53,6 +53,7 @@ import { UptimePageObject } from './uptime_page';
import { UserProfilePageProvider } from './user_profile_page';
import { WatcherPageObject } from './watcher_page';
import { SearchProfilerPageProvider } from './search_profiler_page';
import { SearchPlaygroundPageProvider } from './search_playground_page';
// just like services, PageObjects are defined as a map of
// names to Providers. Merge in Kibana's or pick specific ones
@ -93,6 +94,7 @@ export const pageObjects = {
roleMappings: RoleMappingsPageProvider,
rollup: RollupPageObject,
searchProfiler: SearchProfilerPageProvider,
searchPlayground: SearchPlaygroundPageProvider,
searchSessionsManagement: SearchSessionsPageProvider,
security: SecurityPageObject,
shareSavedObjectsToSpace: ShareSavedObjectsToSpacePageProvider,

View file

@ -0,0 +1,114 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import expect from '@kbn/expect';
import { FtrProviderContext } from '../ftr_provider_context';
export function SearchPlaygroundPageProvider({ getService }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const comboBox = getService('comboBox');
const browser = getService('browser');
return {
PlaygroundStartChatPage: {
async expectPlaygroundStartChatPageComponentsToExist() {
await testSubjects.existOrFail('startChatPage');
await testSubjects.existOrFail('selectIndicesChatPanel');
await testSubjects.existOrFail('startChatButton');
},
async expectPlaygroundHeaderComponentsToExist() {
await testSubjects.existOrFail('playground-header-actions');
await testSubjects.existOrFail('playground-documentation-link');
},
async expectCreateIndexButtonToMissed() {
await testSubjects.missingOrFail('createIndexButton');
},
async expectCreateIndexButtonToExists() {
await testSubjects.existOrFail('createIndexButton');
},
async expectNoIndexCalloutExists() {
await testSubjects.existOrFail('createIndexCallout');
},
async expectSelectIndex(indexName: string) {
await browser.refresh();
await testSubjects.missingOrFail('createIndexCallout');
await testSubjects.existOrFail('selectIndicesComboBox');
await comboBox.setCustom('selectIndicesComboBox', indexName);
},
async expectNoIndicesFieldsWarningExists() {
await testSubjects.existOrFail('NoIndicesFieldsMessage');
},
async expectAddConnectorButtonExists() {
await testSubjects.existOrFail('setupGenAIConnectorButton');
},
async expectOpenConnectorPagePlayground() {
await testSubjects.click('setupGenAIConnectorButton');
await testSubjects.existOrFail('create-connector-flyout');
},
async expectHideGenAIPanelConnector(createConnector: () => Promise<void>) {
await createConnector();
await browser.refresh();
await testSubjects.missingOrFail('connectToLLMChatPanel');
},
async expectToStartChatPage() {
expect(await testSubjects.isEnabled('startChatButton')).to.be(true);
await testSubjects.click('startChatButton');
await testSubjects.existOrFail('chatPage');
},
},
PlaygroundChatPage: {
async expectChatWorks() {
await testSubjects.existOrFail('questionInput');
await testSubjects.setValue('questionInput', 'test question');
await testSubjects.click('sendQuestionButton');
await testSubjects.existOrFail('userMessage');
},
async expectOpenViewCode() {
await testSubjects.click('viewCodeActionButton');
await testSubjects.existOrFail('viewCodeFlyout');
await testSubjects.click('euiFlyoutCloseButton');
},
async expectViewQueryHasFields() {
await testSubjects.click('viewQueryActionButton');
await testSubjects.existOrFail('viewQueryFlyout');
const fields = await testSubjects.findAll('queryField');
expect(fields.length).to.be(1);
const codeBlock = await testSubjects.find('ViewElasticsearchQueryResult');
const code = await codeBlock.getVisibleText();
expect(code.replace(/ /g, '')).to.be(
'{\n"retriever":{\n"standard":{\n"query":{\n"multi_match":{\n"query":"{query}",\n"fields":[\n"baz"\n]\n}\n}\n}\n}\n}'
);
await testSubjects.click('euiFlyoutCloseButton');
},
async expectEditContextOpens() {
await testSubjects.click('editContextActionButton');
await testSubjects.existOrFail('editContextFlyout');
await testSubjects.click('contextFieldsSelectable_basic_index');
await testSubjects.existOrFail('contextField');
const fields = await testSubjects.findAll('contextField');
expect(fields.length).to.be(1);
await testSubjects.click('euiFlyoutCloseButton');
},
},
};
}

View file

@ -21,7 +21,6 @@ import { SvlRuleDetailsPageProvider } from './svl_rule_details_ui_page';
import { SvlSearchConnectorsPageProvider } from './svl_search_connectors_page';
import { SvlManagementPageProvider } from './svl_management_page';
import { SvlIngestPipelines } from './svl_ingest_pipelines';
import { SvlPlaygroundPageProvider } from './svl_playground_page';
export const pageObjects = {
...xpackFunctionalPageObjects,
@ -39,5 +38,4 @@ export const pageObjects = {
svlRuleDetailsUI: SvlRuleDetailsPageProvider,
svlManagementPage: SvlManagementPageProvider,
svlIngestPipelines: SvlIngestPipelines,
svlPlaygroundUI: SvlPlaygroundPageProvider,
};

View file

@ -1,26 +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 { FtrProviderContext } from '../ftr_provider_context';
export function SvlPlaygroundPageProvider({ getService }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
return {
PlaygrounStartChatPage: {
async expectPlaygroundStartChatPageComponentsToExist() {
await testSubjects.existOrFail('chat-playground-home-page-title');
await testSubjects.existOrFail('selectIndicesChatPanel');
await testSubjects.existOrFail('startChatButton');
},
async expectPlaygroundHeaderComponentsToExist() {
await testSubjects.existOrFail('playground-header-actions');
await testSubjects.existOrFail('playground-documentation-link');
},
},
};
}

View file

@ -5,24 +5,144 @@
* 2.0.
*/
import { FtrProviderContext } from '../../ftr_provider_context';
import type SuperTest from 'supertest';
import { testHasEmbeddedConsole } from './embedded_console';
import { FtrProviderContext } from '../../ftr_provider_context';
import { RoleCredentials } from '../../../shared/services';
const indexName = 'basic_index';
const esArchiveIndex = 'test/api_integration/fixtures/es_archiver/index_patterns/basic_index';
async function createOpenAIConnector({
supertest,
requestHeader = {},
apiKeyHeader = {},
}: {
supertest: SuperTest.Agent;
requestHeader?: Record<string, string>;
apiKeyHeader?: Record<string, string>;
}): Promise<() => Promise<void>> {
const config = {
apiProvider: 'OpenAI',
defaultModel: 'gpt-4',
apiUrl: 'http://localhost:3002',
};
const connector: { id: string } | undefined = (
await supertest
.post('/api/actions/connector')
.set(requestHeader)
.set(apiKeyHeader)
.send({
name: 'test Open AI',
connector_type_id: '.gen-ai',
config,
secrets: {
apiKey: 'genAiApiKey',
},
})
.expect(200)
).body;
return async () => {
if (connector) {
await supertest
.delete(`/api/actions/connector/${connector.id}`)
.set(requestHeader)
.set(apiKeyHeader)
.expect(204);
}
};
}
export default function ({ getPageObjects, getService }: FtrProviderContext) {
const pageObjects = getPageObjects(['svlCommonPage', 'svlCommonNavigation', 'searchPlayground']);
const svlCommonApi = getService('svlCommonApi');
const svlUserManager = getService('svlUserManager');
const supertestWithoutAuth = getService('supertestWithoutAuth');
const esArchiver = getService('esArchiver');
const createIndex = async () => await esArchiver.load(esArchiveIndex);
let roleAuthc: RoleCredentials;
describe('Serverless Playground Overview', () => {
let removeOpenAIConnector: () => Promise<void>;
let createConnector: () => Promise<void>;
export default function ({ getPageObjects }: FtrProviderContext) {
const pageObjects = getPageObjects(['svlCommonPage', 'svlCommonNavigation', 'svlPlaygroundUI']);
describe('Playground', function () {
before(async () => {
await pageObjects.svlCommonPage.login();
await pageObjects.svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'searchPlayground' });
await pageObjects.svlCommonNavigation.sidenav.clickLink({
deepLinkId: 'searchPlayground',
});
const requestHeader = svlCommonApi.getInternalRequestHeader();
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
createConnector = async () => {
removeOpenAIConnector = await createOpenAIConnector({
supertest: supertestWithoutAuth,
requestHeader,
apiKeyHeader: roleAuthc.apiKeyHeader,
});
};
});
after(async () => {
await removeOpenAIConnector?.();
await esArchiver.unload(esArchiveIndex);
await svlUserManager.invalidateApiKeyForRole(roleAuthc);
await pageObjects.svlCommonPage.forceLogout();
});
it('playground app is loaded', async () => {
await pageObjects.svlPlaygroundUI.PlaygrounStartChatPage.expectPlaygroundStartChatPageComponentsToExist();
await pageObjects.svlPlaygroundUI.PlaygrounStartChatPage.expectPlaygroundHeaderComponentsToExist();
describe('start chat page', () => {
it('playground app is loaded', async () => {
await pageObjects.searchPlayground.PlaygroundStartChatPage.expectPlaygroundStartChatPageComponentsToExist();
await pageObjects.searchPlayground.PlaygroundStartChatPage.expectPlaygroundHeaderComponentsToExist();
});
it('show no index callout', async () => {
await pageObjects.searchPlayground.PlaygroundStartChatPage.expectNoIndexCalloutExists();
await pageObjects.searchPlayground.PlaygroundStartChatPage.expectCreateIndexButtonToMissed();
});
it('hide no index callout when index added', async () => {
await createIndex();
await pageObjects.searchPlayground.PlaygroundStartChatPage.expectSelectIndex(indexName);
});
it('show add connector button', async () => {
await pageObjects.searchPlayground.PlaygroundStartChatPage.expectAddConnectorButtonExists();
});
it('click add connector button opens connector flyout', async () => {
await pageObjects.searchPlayground.PlaygroundStartChatPage.expectOpenConnectorPagePlayground();
});
it('hide gen ai panel when connector exists', async () => {
await pageObjects.searchPlayground.PlaygroundStartChatPage.expectHideGenAIPanelConnector(
createConnector
);
});
it('show chat page', async () => {
await pageObjects.searchPlayground.PlaygroundStartChatPage.expectSelectIndex(indexName);
await pageObjects.searchPlayground.PlaygroundStartChatPage.expectToStartChatPage();
});
});
describe('chat page', () => {
it('chat works', async () => {
await pageObjects.searchPlayground.PlaygroundChatPage.expectChatWorks();
});
it('open view code', async () => {
await pageObjects.searchPlayground.PlaygroundChatPage.expectOpenViewCode();
});
it('show fields and code in view query', async () => {
await pageObjects.searchPlayground.PlaygroundChatPage.expectViewQueryHasFields();
});
it('show edit context', async () => {
await pageObjects.searchPlayground.PlaygroundChatPage.expectEditContextOpens();
});
});
it('has embedded console', async () => {