Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
e0e0dd4
Initial commit
JoseLuisGJ Jun 12, 2025
78b3bc8
Fixing feature flag enablement
JoseLuisGJ Jun 12, 2025
e4062e0
Create ruleset tests
JoseLuisGJ Jun 13, 2025
5b8b5f6
Delete ruleset tests
JoseLuisGJ Jun 16, 2025
5bb890b
Ruleset rule document and criteria tests
JoseLuisGJ Jun 17, 2025
19c4c2b
Merge branch 'main' into query-rules-ftr-tests
elasticmachine Jun 17, 2025
915daad
Fixing linting issues
JoseLuisGJ Jun 17, 2025
ebd740e
Removing unnused browser
JoseLuisGJ Jun 17, 2025
6e27abc
Bringing back all feature flag tests
JoseLuisGJ Jun 17, 2025
734c23d
Managing after and before calls
JoseLuisGJ Jun 18, 2025
9f478d3
Removing Query Rules menu entry point by default
JoseLuisGJ Jun 18, 2025
9648b5a
Fixing before after sequence
JoseLuisGJ Jun 18, 2025
133173c
Enabling all FF tests
JoseLuisGJ Jun 18, 2025
d9e4acb
Moving after methods to the end
JoseLuisGJ Jun 18, 2025
917ced1
Merge branch 'main' into query-rules-ftr-tests
JoseLuisGJ Jun 19, 2025
ceff7d4
Using ComboBox servicce
JoseLuisGJ Jun 23, 2025
58b9607
Merge branch 'main' into query-rules-ftr-tests
elasticmachine Jun 23, 2025
56cab18
Merge branch 'main' into query-rules-ftr-tests
elasticmachine Jun 25, 2025
3fb94ff
Merge branch 'main' of github.com:elastic/kibana into query-rules-ftr…
efegurkan Jun 25, 2025
747c285
Merge branch 'main' of github.com:elastic/kibana into query-rules-ftr…
efegurkan Jun 26, 2025
c1ccbe8
Update tests to make them stable
efegurkan Jun 28, 2025
c0518e4
Fix linting
efegurkan Jun 29, 2025
e86325f
Remove unused variable
efegurkan Jun 30, 2025
0e3865f
Merge branch 'main' into query-rules-ftr-tests
elasticmachine Jun 30, 2025
55d530e
Merge branch 'main' into query-rules-ftr-tests
elasticmachine Jun 30, 2025
e934476
Merge branch 'main' of github.com:elastic/kibana into query-rules-ftr…
efegurkan Jul 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export const DeleteRulesetModal = ({
<EuiCheckbox
id={confirmCheckboxId}
label="This ruleset is safe to delete"
data-test-subj="confirmDeleteRulesetCheckbox"
checked={checked}
onChange={(e) => {
setChecked(e.target.checked);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ export const QueryRulesSets = () => {
icon: 'trash',
color: 'danger',
type: 'icon',
'data-test-subj': 'queryRulesSetDeleteButton',
isPrimary: true,
onClick: (ruleset: QueryRulesListRulesetsQueryRulesetListItem) => {
useTracker?.click?.(AnalyticsEvents.deleteRulesetInlineDropdownClicked);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export const QueryRuleFlyout: React.FC<QueryRuleFlyoutProps> = ({
onClose={onClose}
ownFocus={false}
size="l"
data-test-subj="searchQueryRulesQueryRuleFlyout"
aria-labelledby="flyoutTitle"
css={css({
overflowY: 'hidden',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const QueryRuleMetadataEditor: React.FC<QueryRuleMetadataEditorProps> = (
const [metadataField, setMetadataField] = useState<string>(criteria.metadata || '');

return (
<EuiPanel hasBorder>
<EuiPanel data-test-subj="searchQueryRulesQueryRuleMetadataEditor" hasBorder>
<EuiFlexGroup direction="row">
<EuiFlexItem>
<EuiFormRow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ export const QueryRulesetDetail: React.FC<QueryRulesetDetailProps> = ({ createMo
})}
</>
),
'data-test-subj': 'queryRulesetDetailBackButton',
color: 'primary',
'aria-current': false,
onClick: () => {
Expand Down Expand Up @@ -371,7 +372,7 @@ export const QueryRulesetDetail: React.FC<QueryRulesetDetailProps> = ({ createMo
id={splitButtonPopoverActionsId}
button={
<EuiButtonIcon
data-test-subj="searchQueryRulesQueryRulesetDetailButton"
data-test-subj="searchQueryRulesQueryRulesetActionsButton"
size="m"
iconType="boxesVertical"
aria-label="More"
Expand Down
2 changes: 2 additions & 0 deletions x-pack/test/functional/page_objects/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import { UptimePageObject } from './uptime_page';
import { UserProfilePageProvider } from './user_profile_page';
import { SearchPlaygroundPageProvider } from './search_playground_page';
import { SearchSynonymsPageProvider } from './search_synonyms_page';
import { SearchQueryRulesPageProvider } from './search_query_rules_page';
import { SearchClassicNavigationProvider } from './search_classic_navigation';
import { SearchStartProvider } from './search_start';
import { SearchApiKeysProvider } from './search_api_keys';
Expand Down Expand Up @@ -111,6 +112,7 @@ export const pageObjects = {
searchProfiler: SearchProfilerPageProvider,
searchPlayground: SearchPlaygroundPageProvider,
searchSynonyms: SearchSynonymsPageProvider,
searchQueryRules: SearchQueryRulesPageProvider,
searchSessionsManagement: SearchSessionsPageProvider,
security: SecurityPageObject,
shareSavedObjectsToSpace: ShareSavedObjectsToSpacePageProvider,
Expand Down
260 changes: 260 additions & 0 deletions x-pack/test/functional/page_objects/search_query_rules_page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
/*
* 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 { Key } from 'selenium-webdriver';
import { FtrProviderContext } from '../ftr_provider_context';

export function SearchQueryRulesPageProvider({ getService }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const find = getService('find');
const comboBox = getService('comboBox');
const browser = getService('browser');

return {
QueryRulesEmptyPromptPage: {
TEST_IDS: {
GET_STARTED_BUTTON: 'searchQueryRulesEmptyPromptGetStartedButton',
},
async expectQueryRulesEmptyPromptPageComponentsToExist() {
await testSubjects.existOrFail(this.TEST_IDS.GET_STARTED_BUTTON);
},
async clickCreateQueryRulesSetButton() {
await testSubjects.click(this.TEST_IDS.GET_STARTED_BUTTON);
},
},
QueryRulesManagementPage: {
TEST_IDS: {
QUERY_RULES_RULESETS_TABLE: 'queryRulesSetTable',
QUERY_RULES_ITEM_NAME: 'queryRuleSetName',
QUERY_RULES_ITEM_RULE_COUNT: 'queryRuleSetItemRuleCount',
QUERY_RULES_ITEM_ACTIONS_DELETE_BUTTON: 'queryRulesSetDeleteButton',
CREATE_RULESET_BUTTON: 'queryRulesOverviewCreateButton',
PAGINATION_NEXT_BUTTON: 'pagination-button-next',
PAGINATION_PREVIOUS_BUTTON: 'pagination-button-previous',
},
async clickCreateQueryRulesRulesetButton() {
await testSubjects.click(this.TEST_IDS.CREATE_RULESET_BUTTON);
},
async expectQueryRulesTableToExist() {
await testSubjects.existOrFail(this.TEST_IDS.QUERY_RULES_RULESETS_TABLE);
},
async getQueryRulesRulesetsList() {
const table = await testSubjects.find(this.TEST_IDS.QUERY_RULES_RULESETS_TABLE);
const allRows = await table
.findByTagName('tbody')
.then((tbody) => tbody.findAllByTagName('tr'));

return Promise.all(
allRows.map(async (row) => {
const $ = await row.parseDomContent();
return {
name: $.findTestSubject(this.TEST_IDS.QUERY_RULES_ITEM_NAME).text().trim(),
ruleCount: Number(
$.findTestSubject(this.TEST_IDS.QUERY_RULES_ITEM_RULE_COUNT).text()
),
};
})
);
},
async clickRuleset(name: string) {
// find rulesets with name and click on it
const table = await testSubjects.findAll(this.TEST_IDS.QUERY_RULES_ITEM_NAME);
for (const item of table) {
const text = await item.getVisibleText();
if (text === name) {
await item.click();
return;
}
}
throw new Error(`Ruleset with name "${name}" not found`);
},
async clickDeleteRulesetRow(index: number) {
const table = await testSubjects.find(this.TEST_IDS.QUERY_RULES_RULESETS_TABLE);
const allRows = await table
.findByTagName('tbody')
.then((tbody) => tbody.findAllByTagName('tr'));
const deleteButton = await allRows[index].findByTestSubject(
this.TEST_IDS.QUERY_RULES_ITEM_ACTIONS_DELETE_BUTTON
);
await deleteButton.click();
},
async expectQueryRulesListPageComponentsToExist() {
await testSubjects.existOrFail(this.TEST_IDS.QUERY_RULES_RULESETS_TABLE);
await testSubjects.existOrFail(this.TEST_IDS.QUERY_RULES_ITEM_RULE_COUNT);
},
async clickPaginationNext() {
await testSubjects.click(this.TEST_IDS.PAGINATION_NEXT_BUTTON);
},
async clickPaginationPrevious() {
await testSubjects.click(this.TEST_IDS.PAGINATION_PREVIOUS_BUTTON);
},
},
QueryRulesDetailPage: {
TEST_IDS: {
RULESET_DETAILS_PAGE_BACK_BUTTON: 'queryRulesetDetailBackButton',
RULESET_DETAILS_PAGE_SAVE_BUTTON: 'queryRulesetDetailHeaderSaveButton',
RULESET_DETAILS_PAGE_HEADER: 'queryRulesetDetailHeader',
RULESET_DETAILS_PAGE_ACTIONS_BUTTON: 'searchQueryRulesQueryRulesetActionsButton',
RULESET_DETAILS_PAGE_DELETE_BUTTON: 'queryRulesetDetailDeleteButton',
RULESET_RULES_CONTAINER: 'searchQueryRulesDroppable',
RULESET_RULE_ITEM_NAME: 'searchQueryRulesDraggableItem',
RULESET_RULE_ITEM_ACTIONS_BUTTON: 'searchQueryRulesQueryRulesetDetailButton',
RULESET_RULE_ITEM_ACTIONS_DELETE_BUTTON: 'searchQueryRulesQueryRulesetDetailDeleteButton',
RULESET_RULE_ITEM_ACTIONS_EDIT_BUTTON: 'searchQueryRulesQueryRulesetDetailEditButton',
},
async expectQueryRulesDetailPageNavigated(name: string) {
const h1Element = await find.byCssSelector(
`main header[data-test-subj="${this.TEST_IDS.RULESET_DETAILS_PAGE_HEADER}"] h1`
);
const text = await h1Element.getVisibleText();
if (text !== name) {
throw new Error(`Expected page title to be "${name}" but got "${text}"`);
}
},
async expectQueryRulesDetailPageBackButtonToExist() {
await testSubjects.existOrFail(this.TEST_IDS.RULESET_DETAILS_PAGE_BACK_BUTTON);
},
async expectQueryRulesDetailPageSaveButtonToExist() {
await testSubjects.existOrFail(this.TEST_IDS.RULESET_DETAILS_PAGE_SAVE_BUTTON);
},
async clickQueryRulesDetailPageSaveButton() {
await testSubjects.click(this.TEST_IDS.RULESET_DETAILS_PAGE_SAVE_BUTTON);
},
async clickQueryRulesDetailPageActionsButton() {
await testSubjects.click(this.TEST_IDS.RULESET_DETAILS_PAGE_ACTIONS_BUTTON);
},
async clickQueryRulesDetailPageDeleteButton() {
await testSubjects.click(this.TEST_IDS.RULESET_DETAILS_PAGE_DELETE_BUTTON);
},
async clickEditRulesetRule(id: number) {
const items = await testSubjects.findAll(this.TEST_IDS.RULESET_RULE_ITEM_NAME);
if (items[id]) {
const actionButton = await items[id].findByTestSubject(
this.TEST_IDS.RULESET_RULE_ITEM_ACTIONS_BUTTON
);
await actionButton.click();
await testSubjects.click(this.TEST_IDS.RULESET_RULE_ITEM_ACTIONS_EDIT_BUTTON);
} else {
throw new Error(`Ruleset rule with id "${id}" not found`);
}
},
},
QueryRulesCreateRulesetModal: {
TEST_IDS: {
CREATE_QUERY_RULES_SET_MODAL_INPUT: 'searchRulesetCreateRulesetModalFieldText',
CREATE_QUERY_RULES_SET_MODAL_CREATE_BUTTON: 'searchRulesetCreateRulesetModalCreateButton',
},
async setQueryRulesSetName(name: string) {
await testSubjects.setValue(this.TEST_IDS.CREATE_QUERY_RULES_SET_MODAL_INPUT, name);
},
async clickSaveButton() {
await testSubjects.click(this.TEST_IDS.CREATE_QUERY_RULES_SET_MODAL_CREATE_BUTTON);
},
},
QueryRulesDeleteRulesetModal: {
TEST_IDS: {
DELETE_QUERY_RULES_RULESET_MODAL_DELETE_BUTTON:
'searchRulesetDeleteRulesetModalDeleteButton',
DELETE_QUERY_RULES_RULESET_MODAL_ACKNOWLEDGE_BUTTON: 'confirmDeleteRulesetCheckbox',
DELETE_QUERY_RULES_RULESET_MODAL_CANCEL_BUTTON:
'searchRulesetDeleteRulesetModalCancelButton',
},
async clickDeleteButton() {
await testSubjects.click(this.TEST_IDS.DELETE_QUERY_RULES_RULESET_MODAL_DELETE_BUTTON);
},
async clickAcknowledgeButton() {
await testSubjects.click(this.TEST_IDS.DELETE_QUERY_RULES_RULESET_MODAL_ACKNOWLEDGE_BUTTON);
},
async clickCancelButton() {
await testSubjects.click(this.TEST_IDS.DELETE_QUERY_RULES_RULESET_MODAL_CANCEL_BUTTON);
},
async clickConfirmDeleteModal() {
await testSubjects.click('confirmModalConfirmButton');
},
},
QueryRulesRuleFlyout: {
TEST_IDS: {
RULE_FLYOUT: 'searchQueryRulesQueryRuleFlyout',
RULE_FLYOUT_UPDATE_BUTTON: 'searchQueryRulesQueryRuleFlyoutUpdateButton',
RULE_FLYOUT_PIN_MORE_BUTTON: 'searchQueryRulesPinMoreButton',
RULE_FLYOUT_METADATA_ADD_BUTTON: 'searchQueryRulesQueryRuleMetadataEditorAddCriteriaButton',
RULE_FLYOUT_DOCUMENT_DRAGGABLE_ID: 'editableResultDocumentId',
RULE_FLYOUT_DOCUMENT_INDEX: 'editableResultIndexSelector',
RULE_FLYOUT_ACTION_TYPE_EXCLUDE: 'searchQueryRulesQueryRuleActionTypeExclude',
RULE_FLYOUT_ACTION_TYPE_PINNED: 'searchQueryRulesQueryRuleActionTypePinned',
RULE_FLYOUT_CRITERIA_CUSTOM: 'searchQueryRulesQueryRuleCriteriaCustom',
RULE_FLYOUT_CRITERIA_ALWAYS: 'searchQueryRulesQueryRuleCriteriaAlways',
RULE_FLYOUT_CRITERIA_METADATA_BLOCK: 'searchQueryRulesQueryRuleMetadataEditor',
RULE_FLYOUT_CRITERIA_METADATA_BLOCK_FIELD: 'searchQueryRulesQueryRuleMetadataEditorField',
RULE_FLYOUT_CRITERIA_METADATA_BLOCK_VALUES: 'searchQueryRulesQueryRuleMetadataEditorValues',
},
async expectRuleFlyoutToExist() {
await testSubjects.existOrFail(this.TEST_IDS.RULE_FLYOUT);
},
async clickUpdateButton() {
await testSubjects.click(this.TEST_IDS.RULE_FLYOUT_UPDATE_BUTTON);
},
async clickActionTypeExclude() {
await testSubjects.click(this.TEST_IDS.RULE_FLYOUT_ACTION_TYPE_EXCLUDE);
},
async clickActionTypePinned() {
await testSubjects.click(this.TEST_IDS.RULE_FLYOUT_ACTION_TYPE_PINNED);
},
async clickCriteriaCustom() {
await testSubjects.click(this.TEST_IDS.RULE_FLYOUT_CRITERIA_CUSTOM);
},
async clickCriteriaAlways() {
await testSubjects.click(this.TEST_IDS.RULE_FLYOUT_CRITERIA_ALWAYS);
},
async changeDocumentIdField(id: number, newValue: string = '') {
const documentFields = await testSubjects.findAll(
this.TEST_IDS.RULE_FLYOUT_DOCUMENT_DRAGGABLE_ID
);
if (documentFields[id]) {
const targetField = documentFields[id];
await targetField.click();
await targetField.type(newValue);
} else {
await testSubjects.click(this.TEST_IDS.RULE_FLYOUT_PIN_MORE_BUTTON);
await this.changeDocumentIdField(id);
}
},
async changeDocumentIndexField(id: number, newValue: string = '') {
const comboBoxes = await testSubjects.findAll(this.TEST_IDS.RULE_FLYOUT_DOCUMENT_INDEX);
if (comboBoxes[id]) {
const targetComboBox = comboBoxes[id];
await targetComboBox.click();
await comboBox.setCustom(this.TEST_IDS.RULE_FLYOUT_DOCUMENT_INDEX, newValue);
// Press tab to ensure the value is set correctly
await browser.pressKeys(Key.TAB);
}
},
async changeMetadataField(id: number, newValue: string = '') {
const metadataFields = await testSubjects.findAll(
this.TEST_IDS.RULE_FLYOUT_CRITERIA_METADATA_BLOCK
);
if (metadataFields[id]) {
const targetMetadataBlock = metadataFields[id];
const targetField = await targetMetadataBlock.findByTestSubject(
this.TEST_IDS.RULE_FLYOUT_CRITERIA_METADATA_BLOCK_FIELD
);
await targetField.click();
await targetField.type(newValue);
} else {
await testSubjects.click(this.TEST_IDS.RULE_FLYOUT_METADATA_ADD_BUTTON);
await this.changeMetadataField(id);
}
},
async changeMetadataValues(_: number, newValue: string = '') {
await comboBox.setCustom(
this.TEST_IDS.RULE_FLYOUT_CRITERIA_METADATA_BLOCK_VALUES,
newValue
);
},
},
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ export default createTestConfig({
kbnServerArgs: [
`--xpack.cloud.id=ES3_FTR_TESTS:ZmFrZS1kb21haW4uY2xkLmVsc3RjLmNvJGZha2Vwcm9qZWN0aWQuZXMkZmFrZXByb2plY3RpZC5rYg==`,
`--uiSettings.overrides.searchPlayground:searchModeEnabled=true`,
`--uiSettings.overrides.queryRules:queryRulesEnabled=true`,
'--xpack.searchQueryRules.enabled=true',
],
// load tests in the index file
testFiles: [require.resolve('./index.feature_flags.ts')],
Expand All @@ -41,6 +43,9 @@ export default createTestConfig({
searchSynonyms: {
pathname: '/app/elasticsearch/search_synonyms',
},
searchQueryRules: {
pathname: '/app/elasticsearch/query_rules',
},
elasticsearchStart: {
pathname: '/app/elasticsearch/start',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export default function ({ loadTestFile }: FtrProviderContext) {
loadTestFile(require.resolve('./search_synonyms/search_synonyms_overview'));
loadTestFile(require.resolve('./search_synonyms/search_synonym_detail'));
loadTestFile(require.resolve('./search_playground/search_relevance'));
loadTestFile(require.resolve('./search_query_rules/search_query_rules_overview'));
loadTestFile(require.resolve('./search_playground/saved_playgrounds'));
});
}
Loading