Skip to content

Commit 3650221

Browse files
committed
Add cypress test for dashboards assistant feature flag
Signed-off-by: Owen Wang <[email protected]>
1 parent 6979d4f commit 3650221

File tree

3 files changed

+331
-5
lines changed

3 files changed

+331
-5
lines changed

.github/workflows/assistant-release-e2e-workflow.yml

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
test-name: dashboards assistant
2525
test-command: env CYPRESS_DASHBOARDS_ASSISTANT_ENABLED=true yarn cypress:run-with-security --browser chromium --spec 'cypress/integration/plugins/dashboards-assistant/*chatbot*.js'
2626
osd-serve-args: --assistant.chat.enabled=true
27-
artifact-name-suffix: "-with-security"
27+
artifact-name-suffix: '-with-security'
2828

2929
tests-without-security:
3030
needs: changes
@@ -35,7 +35,7 @@ jobs:
3535
test-command: env CYPRESS_DASHBOARDS_ASSISTANT_ENABLED=true yarn cypress:run-without-security --browser chromium --spec 'cypress/integration/plugins/dashboards-assistant/*chatbot*.js'
3636
osd-serve-args: --assistant.chat.enabled=true
3737
security-enabled: false
38-
artifact-name-suffix: "-without-security"
38+
artifact-name-suffix: '-without-security'
3939
multi-opensearch-enabled: false
4040

4141
tests-with-multiple-data-source-and-disabled-local-cluster:
@@ -47,7 +47,7 @@ jobs:
4747
test-command: env CYPRESS_DISABLE_LOCAL_CLUSTER=true CYPRESS_DATASOURCE_MANAGEMENT_ENABLED=true CYPRESS_DASHBOARDS_ASSISTANT_ENABLED=true yarn cypress:run-with-security --browser chromium --spec 'cypress/integration/plugins/dashboards-assistant/mds_chatbot*.js'
4848
osd-serve-args: --data_source.enabled=true --data_source.ssl.verificationMode=none --data_source.hideLocalCluster=true --assistant.chat.enabled=true
4949
security-enabled: true
50-
artifact-name-suffix: "-with-security-and-mds"
50+
artifact-name-suffix: '-with-security-and-mds'
5151

5252
tests-with-query-enhancements:
5353
needs: changes
@@ -58,5 +58,15 @@ jobs:
5858
test-command: env CYPRESS_DISABLE_LOCAL_CLUSTER=true CYPRESS_DATASOURCE_MANAGEMENT_ENABLED=true CYPRESS_DASHBOARDS_ASSISTANT_ENABLED=true CYPRESS_WORKSPACE_ENABLED=true yarn cypress:run-with-security --browser chromium --spec 'cypress/integration/plugins/dashboards-assistant/mds_query_enhancements*.js'
5959
osd-serve-args: --data_source.enabled=true --data_source.ssl.verificationMode=none --data_source.hideLocalCluster=true --assistant.chat.enabled=true --assistant.alertInsight.enabled=true --assistant.smartAnomalyDetector.enabled=true --queryEnhancements.queryAssist.summary.enabled=true --uiSettings.overrides.home:useNewHomePage=true --uiSettings.overrides.query:enhancements:enabled=true --workspace.enabled=true --savedObjects.permission.enabled=true --assistant.text2viz.enabled=true --opensearchDashboards.dashboardAdmin.users='["admin"]' --opensearch_security.multitenancy.enabled=false
6060
security-enabled: true
61-
artifact-name-suffix: "-with-query-enhancements"
61+
artifact-name-suffix: '-with-query-enhancements'
6262

63+
tests-with-assistant-feature-flag:
64+
needs: changes
65+
if: ${{ needs.changes.outputs.tests == 'true' }}
66+
uses: ./.github/workflows/release-e2e-workflow-template.yml
67+
with:
68+
test-name: dashboards assistant
69+
test-command: env CYPRESS_DISABLE_LOCAL_CLUSTER=true CYPRESS_DATASOURCE_MANAGEMENT_ENABLED=false CYPRESS_DASHBOARDS_ASSISTANT_ENABLED=true CYPRESS_WORKSPACE_ENABLED=true yarn cypress:run-with-security --browser chromium --spec 'cypress/integration/plugins/dashboards-assistant/mds_assistant_feature_flag_spec.js'
70+
osd-serve-args: --data_source.enabled=true --data_source.ssl.verificationMode=none --data_source.hideLocalCluster=true --assistant.chat.enabled=true --assistant.alertInsight.enabled=true --assistant.smartAnomalyDetector.enabled=true --queryEnhancements.queryAssist.summary.enabled=true --uiSettings.overrides.home:useNewHomePage=true --uiSettings.overrides.query:enhancements:enabled=true --workspace.enabled=true --savedObjects.permission.enabled=true --assistant.text2viz.enabled=true --opensearchDashboards.dashboardAdmin.users='["admin","workspace-test"]' --opensearch_security.multitenancy.enabled=false
71+
security-enabled: true
72+
artifact-name-suffix: '-with-assistant-feature-flag'

cypress/fixtures/plugins/dashboards-assistant/flow-templates/chat.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@
120120
},
121121
"user_inputs": {
122122
"parameters": {
123-
"prompt": "\n\nHuman:\" turn\" You are an AI that only speaks JSON. Do not write normal text. Output should follow example JSON format: \n\n {\"response\": [\"question1\", \"question2\"]}\n\n. \n\nHuman:\" turn\":You will be given a chat history between OpenSearch Assistant and a Human.\nUse the context provided to generate follow up questions the Human would ask to the Assistant.\nThe Assistant can answer general questions about logs, traces and metrics.\nAssistant can access a set of tools listed below to answer questions given by the Human:\nQuestion suggestions generator tool\nHere's the chat history between the human and the Assistant.\n${parameters.AgentTool.output}\nUse the following steps to generate follow up questions Human may ask after the response of the Assistant:\nStep 1. Use the chat history to understand what human is trying to search and explore.\nStep 2. Understand what capabilities the assistant has with the set of tools it has access to.\nStep 3. Use the above context and generate follow up questions.Step4:You are an AI that only speaks JSON. Do not write normal text. Output should follow example JSON format: \n\n {\"response\": [\"question1\", \"question2\"]} \n \n----------------\n\nAssistant:"
123+
"prompt": "You are an AI that only speaks JSON"
124124
},
125125
"description": "A general tool to answer any question.",
126126
"alias": "language_model_tool",
Lines changed: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import { BASE_PATH } from '../../../utils/constants';
7+
import sampleQueryLevelMonitorForAlertSummary from '../../../fixtures/plugins/alerting-dashboards-plugin/sample_query_level_monitor_for_alert_summary.json';
8+
import { ADMIN_AUTH } from '../../../utils/commands';
9+
import workspaceTestUser from '../../../fixtures/dashboard/opensearch_dashboards/workspace/workspaceTestUser.json';
10+
import workspaceTestRole from '../../../fixtures/dashboard/opensearch_dashboards/workspace/workspaceTestRole.json';
11+
12+
const workspaceName = `test_workspace_${Math.random()
13+
.toString(36)
14+
.substring(7)}`;
15+
16+
const toggleOnAIFeature = () => {
17+
cy.getElementByTestId('advancedSetting-resetField-enableAIFeatures').click();
18+
cy.getElementByTestId('advancedSetting-editField-enableAIFeatures').should(
19+
'have.attr',
20+
'aria-checked',
21+
'true'
22+
);
23+
cy.getElementByTestId('advancedSetting-saveButton')
24+
.should('be.visible')
25+
.click();
26+
};
27+
28+
const toggleOffAIFeature = () => {
29+
cy.getElementByTestId('advancedSetting-editField-enableAIFeatures').click();
30+
cy.getElementByTestId('advancedSetting-editField-enableAIFeatures').should(
31+
'have.attr',
32+
'aria-checked',
33+
'false'
34+
);
35+
cy.getElementByTestId('advancedSetting-saveButton')
36+
.should('be.visible')
37+
.click();
38+
};
39+
40+
function dashboardsAssistantFeatureFlagTestCases() {
41+
describe('Dashboards assistant feature flag', () => {
42+
let workspaceId;
43+
let dataSourceId;
44+
before(() => {
45+
cy.createDataSourceNoAuth().then((result) => {
46+
dataSourceId = result[0];
47+
cy.createWorkspace({
48+
name: workspaceName,
49+
description: 'Workspace for cypress testing',
50+
features: ['use-case-all'],
51+
settings: {
52+
permissions: {
53+
library_write: { users: ['%me%'] },
54+
write: { users: ['%me%'] },
55+
},
56+
dataSources: [dataSourceId],
57+
},
58+
})
59+
.then((wsId) => {
60+
workspaceId = wsId;
61+
})
62+
.then(() =>
63+
cy.loadSampleDataForWorkspace(
64+
'ecommerce',
65+
workspaceId,
66+
dataSourceId
67+
)
68+
);
69+
});
70+
});
71+
72+
after(() => {
73+
if (workspaceId) {
74+
if (dataSourceId) {
75+
cy.removeSampleDataForWorkspace(
76+
'ecommerce',
77+
workspaceId,
78+
dataSourceId
79+
);
80+
}
81+
cy.deleteWorkspaceById(workspaceId);
82+
}
83+
if (dataSourceId) {
84+
cy.deleteDataSource(dataSourceId);
85+
}
86+
});
87+
88+
describe('AI feature flag enabled', () => {
89+
it('AI feature flag toggle on advanced settings page should be enabled', () => {
90+
cy.visit(`${BASE_PATH}/app/settings`);
91+
92+
cy.getElementByTestId(
93+
'advancedSetting-editField-enableAIFeatures'
94+
).then(($el) => {
95+
if ($el.attr('aria-checked') === 'false') {
96+
toggleOnAIFeature();
97+
} else {
98+
cy.getElementByTestId(
99+
'advancedSetting-resetField-enableAIFeatures'
100+
).should('not.exist');
101+
}
102+
});
103+
});
104+
105+
it('Data2summary and suggested AD should be available on the discover', () => {
106+
cy.visit(`w/${workspaceId}/app/discover`);
107+
108+
cy.get('.languageSelector__button').should('be.visible').click();
109+
cy.contains('button', 'PPL').should('be.visible').click();
110+
cy.getElementByTestId('languageReferenceButton')
111+
.should('be.visible')
112+
.click();
113+
cy.getElementByTestId('queryAssist__summary').should('be.visible');
114+
115+
cy.get('button[aria-label="OpenSearch assistant trigger button', {
116+
timeout: 60000,
117+
}).click();
118+
cy.contains('Suggest anomaly detector').click();
119+
cy.get('.add-anomaly-detector').should('be.visible');
120+
});
121+
122+
it('Chatbot should be available on the overview page', () => {
123+
cy.visit(`w/${workspaceId}/app/all_overview`);
124+
125+
cy.openAssistantChatbot();
126+
});
127+
128+
it('Alert summary should be available on the alert', () => {
129+
const dataSourceUrl = Cypress.env('remoteDataSourceBasicAuthUrl');
130+
cy.createMonitor(sampleQueryLevelMonitorForAlertSummary, dataSourceUrl);
131+
132+
cy.wait(80000);
133+
134+
cy.visit(`w/${workspaceId}/app/alerts`);
135+
cy.get('.incontextInsightAnchorIcon', { timeout: 60000 }).should(
136+
'be.visible'
137+
);
138+
139+
cy.deleteAllAlerts(dataSourceUrl);
140+
cy.deleteAllMonitors(dataSourceUrl);
141+
});
142+
});
143+
144+
describe('AI feature flag disabled', () => {
145+
after(() => {
146+
cy.visit(`${BASE_PATH}/app/settings`);
147+
148+
cy.reload();
149+
150+
cy.getElementByTestId('advancedSetting-editField-enableAIFeatures')
151+
.should('exist')
152+
.and('be.visible')
153+
.click();
154+
cy.getElementByTestId('advancedSetting-saveButton')
155+
.should('be.visible')
156+
.click();
157+
});
158+
159+
it('AI feature flag on advanced settings page can be toggle off', () => {
160+
cy.visit(`${BASE_PATH}/app/settings`);
161+
162+
cy.contains('Enable AI features');
163+
cy.getElementByTestId(
164+
'advancedSetting-editField-enableAIFeatures'
165+
).then(($el) => {
166+
if ($el.attr('aria-checked') === 'true') {
167+
toggleOffAIFeature();
168+
} else {
169+
cy.getElementByTestId(
170+
'advancedSetting-resetField-enableAIFeatures'
171+
).should('be.visible');
172+
}
173+
});
174+
cy.getElementByTestId(
175+
'advancedSetting-resetField-enableAIFeatures'
176+
).should('be.visible');
177+
});
178+
179+
it('Data2summary and suggested AD should be unavailable on the discover', () => {
180+
cy.visit(`w/${workspaceId}/app/discover`);
181+
182+
cy.get('.languageSelector__button').should('be.visible').click();
183+
cy.contains('button', 'PPL').should('be.visible').click();
184+
cy.getElementByTestId('languageReferenceButton')
185+
.should('be.visible')
186+
.click();
187+
188+
cy.getElementByTestId('queryAssist__summary').should('not.exist');
189+
cy.get('button[aria-label="OpenSearch assistant trigger button').should(
190+
'not.exist'
191+
);
192+
});
193+
194+
it('Chatbot should be unavailable on the overview page', () => {
195+
cy.visit(`w/${workspaceId}/app/all_overview`);
196+
197+
cy.get('button[aria-label="toggle chat flyout icon').should(
198+
'not.exist'
199+
);
200+
});
201+
202+
it('Alert summary should be unavailable on the alert', () => {
203+
const dataSourceUrl = Cypress.env('remoteDataSourceBasicAuthUrl');
204+
cy.createMonitor(sampleQueryLevelMonitorForAlertSummary);
205+
206+
cy.wait(80000);
207+
208+
cy.visit(`w/${workspaceId}/app/alerts`);
209+
cy.get('.euiTableRow').should('exist').and('be.visible');
210+
cy.get('.incontextInsightAnchorIcon').should('not.exist');
211+
212+
cy.deleteAllAlerts(dataSourceUrl);
213+
cy.deleteAllMonitors(dataSourceUrl);
214+
});
215+
});
216+
});
217+
}
218+
219+
function dashboardAdminUiSettingsTestCases() {
220+
describe('Dashboard admin UI settings', () => {
221+
describe('Dashboard amin user', () => {
222+
it('can toggle AI feature flag', () => {
223+
cy.visit(`${BASE_PATH}/app/settings`);
224+
225+
cy.contains('Enable AI features');
226+
227+
cy.getElementByTestId(
228+
'advancedSetting-editField-enableAIFeatures'
229+
).then(($el) => {
230+
if ($el.attr('aria-checked') === 'false') {
231+
toggleOnAIFeature();
232+
233+
cy.reload();
234+
}
235+
toggleOffAIFeature();
236+
});
237+
});
238+
239+
it('can delete dashboard admin settings saved object', () => {
240+
cy.visit(`${BASE_PATH}/app/objects`);
241+
242+
cy.getElementByTestId('savedObjectsTableRow row-_dashboard_admin')
243+
.contains('_dashboard_admin')
244+
.getElementByTestId('checkboxSelectRow-_dashboard_admin')
245+
.click();
246+
247+
cy.getElementByTestId('savedObjectsManagementDelete')
248+
.should('exist')
249+
.click();
250+
cy.getElementByTestId('confirmModalConfirmButton')
251+
.should('exist')
252+
.click();
253+
254+
cy.visit(`${BASE_PATH}/app/settings`);
255+
});
256+
});
257+
258+
describe('Non-dashboard admin user', () => {
259+
const NONE_DASHBOARDS_ADMIN_USERNAME = 'workspace-test';
260+
const WORKSPACE_TEST_ROLE_NAME = 'workspace-test-role';
261+
const originalUser = ADMIN_AUTH.username;
262+
const originalPassword = ADMIN_AUTH.password;
263+
264+
before(() => {
265+
cy.createInternalUser(
266+
NONE_DASHBOARDS_ADMIN_USERNAME,
267+
workspaceTestUser
268+
);
269+
cy.createRole(WORKSPACE_TEST_ROLE_NAME, workspaceTestRole);
270+
cy.createRoleMapping(WORKSPACE_TEST_ROLE_NAME, {
271+
users: [NONE_DASHBOARDS_ADMIN_USERNAME],
272+
});
273+
});
274+
275+
beforeEach(() => {
276+
// Login as non OSD admin user
277+
ADMIN_AUTH.newUser = NONE_DASHBOARDS_ADMIN_USERNAME;
278+
ADMIN_AUTH.newPassword = workspaceTestUser.password;
279+
});
280+
281+
after(() => {
282+
ADMIN_AUTH.newUser = originalUser;
283+
ADMIN_AUTH.newPassword = originalPassword;
284+
cy.deleteRoleMapping(WORKSPACE_TEST_ROLE_NAME);
285+
cy.deleteInternalUser(NONE_DASHBOARDS_ADMIN_USERNAME);
286+
cy.deleteRole(WORKSPACE_TEST_ROLE_NAME);
287+
});
288+
289+
it('cannot toggle AI feature flag', () => {
290+
cy.visit(`${BASE_PATH}/app/settings`);
291+
292+
cy.contains('Enable AI features');
293+
cy.getElementByTestId(
294+
'advancedSetting-editField-enableAIFeatures'
295+
).should('be.disabled');
296+
});
297+
298+
it('cannot see admin settings saved object in assets page', () => {
299+
cy.visit(`${BASE_PATH}/app/objects`);
300+
301+
cy.getElementByTestId('savedObjectsTable').within(() => {
302+
cy.get('.euiTableRow').should('be.visible');
303+
cy.contains('_dashboard_admin').should('not.exist');
304+
});
305+
});
306+
});
307+
});
308+
}
309+
310+
if (Cypress.env('DASHBOARDS_ASSISTANT_ENABLED')) {
311+
dashboardsAssistantFeatureFlagTestCases();
312+
313+
if (Cypress.env('SECURITY_ENABLED')) {
314+
dashboardAdminUiSettingsTestCases();
315+
}
316+
}

0 commit comments

Comments
 (0)