mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[8.x] [kbn/response-ops-alerts-table] set data-test-subj for EuiDataGrid based on loading status (#217230) (#218243)
# Backport This will backport the following commits from `main` to `8.x`: - [[kbn/response-ops-alerts-table] set data-test-subj for EuiDataGrid based on loading status (#217230)](https://github.com/elastic/kibana/pull/217230) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Dzmitry Lemechko","email":"dzmitry.lemechko@elastic.co"},"sourceCommit":{"committedDate":"2025-04-15T11:05:49Z","message":"[kbn/response-ops-alerts-table] set data-test-subj for EuiDataGrid based on loading status (#217230)\n\n## Summary\n\nFollow-up to #217153\n\n### Problem Description\nIn UI tests, there was no reliable way to determine when the Alerts\ntable content had fully loaded before interacting with it. This could\nlead to flaky tests where interactions occurred before the data was\navailable (rows are not present yet), causing failures or inconsistent\nresults (checking for row with specific content to exist)\n\n\n\n\nQuite often we see tests waiting for global indicator (spinner in the\ntop left corner) to be hidden as a condition for page loading is\ncomplete. This is quite unreliable approach and testing tools have no\nconsistent built-in solution: FTR, Cypress or even Playwright - network\nidle wait is officially marked as\n[discouraged](https://playwright.dev/docs/api/class-page)).\nWe need to help testing tool to interact with UI components in ready\nstate only.\n\n\n### Solution\nTo address this issue, I modified a `data-test-subj` property in the\n`<EuiDataGrid>` component. The property dynamically switches between\n`alertsTableIsLoading` when data is still loading and\n`alertsTableIsLoaded `once the content is available. This allows UI\ntests to wait for precisely `alertsTableIsLoaded` to be in in the DOM\nbefore interacting with the table, ensuring more reliable and stable\ntest execution.\n\n\nPassed 10/10\n<img width=\"538\" alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/e44bae5f-4094-4ed2-89f3-74a52cb2be53\"\n/>","sha":"edf8d6d975f7ae2bd4df8a469bc391ca602ddc1e","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","backport:version","v9.1.0","v8.19.0","v9.0.1"],"title":"[kbn/response-ops-alerts-table] set data-test-subj for EuiDataGrid based on loading status","number":217230,"url":"https://github.com/elastic/kibana/pull/217230","mergeCommit":{"message":"[kbn/response-ops-alerts-table] set data-test-subj for EuiDataGrid based on loading status (#217230)\n\n## Summary\n\nFollow-up to #217153\n\n### Problem Description\nIn UI tests, there was no reliable way to determine when the Alerts\ntable content had fully loaded before interacting with it. This could\nlead to flaky tests where interactions occurred before the data was\navailable (rows are not present yet), causing failures or inconsistent\nresults (checking for row with specific content to exist)\n\n\n\n\nQuite often we see tests waiting for global indicator (spinner in the\ntop left corner) to be hidden as a condition for page loading is\ncomplete. This is quite unreliable approach and testing tools have no\nconsistent built-in solution: FTR, Cypress or even Playwright - network\nidle wait is officially marked as\n[discouraged](https://playwright.dev/docs/api/class-page)).\nWe need to help testing tool to interact with UI components in ready\nstate only.\n\n\n### Solution\nTo address this issue, I modified a `data-test-subj` property in the\n`<EuiDataGrid>` component. The property dynamically switches between\n`alertsTableIsLoading` when data is still loading and\n`alertsTableIsLoaded `once the content is available. This allows UI\ntests to wait for precisely `alertsTableIsLoaded` to be in in the DOM\nbefore interacting with the table, ensuring more reliable and stable\ntest execution.\n\n\nPassed 10/10\n<img width=\"538\" alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/e44bae5f-4094-4ed2-89f3-74a52cb2be53\"\n/>","sha":"edf8d6d975f7ae2bd4df8a469bc391ca602ddc1e"}},"sourceBranch":"main","suggestedTargetBranches":["8.x","9.0"],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/217230","number":217230,"mergeCommit":{"message":"[kbn/response-ops-alerts-table] set data-test-subj for EuiDataGrid based on loading status (#217230)\n\n## Summary\n\nFollow-up to #217153\n\n### Problem Description\nIn UI tests, there was no reliable way to determine when the Alerts\ntable content had fully loaded before interacting with it. This could\nlead to flaky tests where interactions occurred before the data was\navailable (rows are not present yet), causing failures or inconsistent\nresults (checking for row with specific content to exist)\n\n\n\n\nQuite often we see tests waiting for global indicator (spinner in the\ntop left corner) to be hidden as a condition for page loading is\ncomplete. This is quite unreliable approach and testing tools have no\nconsistent built-in solution: FTR, Cypress or even Playwright - network\nidle wait is officially marked as\n[discouraged](https://playwright.dev/docs/api/class-page)).\nWe need to help testing tool to interact with UI components in ready\nstate only.\n\n\n### Solution\nTo address this issue, I modified a `data-test-subj` property in the\n`<EuiDataGrid>` component. The property dynamically switches between\n`alertsTableIsLoading` when data is still loading and\n`alertsTableIsLoaded `once the content is available. This allows UI\ntests to wait for precisely `alertsTableIsLoaded` to be in in the DOM\nbefore interacting with the table, ensuring more reliable and stable\ntest execution.\n\n\nPassed 10/10\n<img width=\"538\" alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/e44bae5f-4094-4ed2-89f3-74a52cb2be53\"\n/>","sha":"edf8d6d975f7ae2bd4df8a469bc391ca602ddc1e"}},{"branch":"8.x","label":"v8.19.0","branchLabelMappingKey":"^v8.19.0$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"9.0","label":"v9.0.1","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT-->
This commit is contained in:
parent
93b2fd62d9
commit
2e306a27f3
13 changed files with 23 additions and 20 deletions
|
@ -358,7 +358,7 @@ export const AlertsDataGrid = typedMemo(
|
|||
ref={dataGridRef}
|
||||
css={rowStyles}
|
||||
aria-label="Alerts table"
|
||||
data-test-subj="alertsTable"
|
||||
data-test-subj={isLoading ? `alertsTableIsLoading` : `alertsTableIsLoaded`}
|
||||
height={height}
|
||||
columns={columnsWithCellActions}
|
||||
columnVisibility={columnVisibility}
|
||||
|
|
|
@ -10,16 +10,14 @@ import { ScoutPage, Locator, expect } from '@kbn/scout';
|
|||
const PAGE_URL = 'security/alerts';
|
||||
|
||||
export class AlertsTablePage {
|
||||
public detectionsAlertsContainer: Locator;
|
||||
public detectionsAlertsWrapper: Locator;
|
||||
public alertRow: Locator;
|
||||
public alertsTableBody: Locator;
|
||||
public alertsTable: Locator;
|
||||
|
||||
constructor(private readonly page: ScoutPage) {
|
||||
this.detectionsAlertsContainer = this.page.testSubj.locator('detectionsAlertsPage');
|
||||
this.detectionsAlertsWrapper = this.page.testSubj.locator('detectionsAlertsPage');
|
||||
this.alertRow = this.page.locator('div.euiDataGridRow');
|
||||
this.alertsTableBody = this.page.testSubj
|
||||
.locator('alertsTable')
|
||||
.locator(`[data-test-subj='euiDataGridBody']`);
|
||||
this.alertsTable = this.page.testSubj.locator('alertsTableIsLoaded'); // Search for loaded Alerts table
|
||||
}
|
||||
|
||||
async navigate() {
|
||||
|
@ -27,7 +25,7 @@ export class AlertsTablePage {
|
|||
}
|
||||
|
||||
async expandAlertDetailsFlyout(ruleName: string) {
|
||||
await this.alertsTableBody.waitFor({ state: 'visible' });
|
||||
await this.alertsTable.waitFor({ state: 'visible' });
|
||||
// Filter alert by unique rule name
|
||||
const row = this.alertRow.filter({ hasText: ruleName });
|
||||
await expect(
|
||||
|
@ -37,4 +35,9 @@ export class AlertsTablePage {
|
|||
|
||||
return row.locator(`[data-test-subj='expand-event']`).click();
|
||||
}
|
||||
|
||||
async waitForDetectionsAlertsWrapper() {
|
||||
// Increased timeout to 20 seconds because this page sometimes takes longer to load
|
||||
return this.detectionsAlertsWrapper.waitFor({ state: 'visible', timeout: 20_000 });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,7 +139,7 @@ describe('Isolate command', { tags: ['@ess', '@serverless', '@brokenInServerless
|
|||
loadPage(APP_ALERTS_PATH);
|
||||
closeAllToasts();
|
||||
|
||||
cy.getByTestSubj('alertsTable').within(() => {
|
||||
cy.getByTestSubj('alertsTableIsLoaded').within(() => {
|
||||
cy.getByTestSubj('expand-event')
|
||||
.first()
|
||||
.within(() => {
|
||||
|
|
|
@ -30,7 +30,7 @@ export const getAlertsTableRows = (timeout?: number): Cypress.Chainable<JQuery<H
|
|||
clickAlertListRefreshButton();
|
||||
|
||||
return cy
|
||||
.getByTestSubj('alertsTable')
|
||||
.getByTestSubj('alertsTableIsLoaded')
|
||||
.find<HTMLDivElement>('.euiDataGridRow')
|
||||
.then(($rowsFound) => {
|
||||
$rows = $rowsFound;
|
||||
|
|
|
@ -28,7 +28,7 @@ spaceTest.describe('Expandable flyout state sync', { tag: ['@ess', '@svlSecurity
|
|||
const urlBeforeAlertDetails = page.url();
|
||||
expect(urlBeforeAlertDetails).not.toContain(RIGHT);
|
||||
|
||||
await pageObjects.alertsTablePage.detectionsAlertsContainer.waitFor({ state: 'visible' });
|
||||
await pageObjects.alertsTablePage.waitForDetectionsAlertsWrapper();
|
||||
await pageObjects.alertsTablePage.expandAlertDetailsFlyout(ruleName);
|
||||
|
||||
const urlAfterAlertDetails = page.url();
|
||||
|
@ -38,7 +38,7 @@ spaceTest.describe('Expandable flyout state sync', { tag: ['@ess', '@svlSecurity
|
|||
await expect(headerTitle).toHaveText(ruleName);
|
||||
|
||||
await page.reload();
|
||||
await pageObjects.alertsTablePage.detectionsAlertsContainer.waitFor({ state: 'visible' });
|
||||
await pageObjects.alertsTablePage.waitForDetectionsAlertsWrapper();
|
||||
|
||||
const urlAfterReload = page.url();
|
||||
expect(urlAfterReload).toContain(RIGHT);
|
||||
|
|
|
@ -64,7 +64,7 @@ export const testSubjectIds = {
|
|||
GRAPH_ACTIONS_TOGGLE_SEARCH_ID: 'cloudSecurityGraphGraphInvestigationToggleSearch',
|
||||
GRAPH_ACTIONS_INVESTIGATE_IN_TIMELINE_ID:
|
||||
'cloudSecurityGraphGraphInvestigationInvestigateInTimeline',
|
||||
ALERT_TABLE_ROW_CSS_SELECTOR: '[data-test-subj="alertsTable"] .euiDataGridRow',
|
||||
ALERT_TABLE_ROW_CSS_SELECTOR: '[data-test-subj="alertsTableIsLoaded"] .euiDataGridRow',
|
||||
SETUP_TECHNOLOGY_SELECTOR: 'setup-technology-selector',
|
||||
DIRECT_ACCESS_KEYS: 'direct_access_keys',
|
||||
SETUP_TECHNOLOGY_SELECTOR_AGENTLESS_RADIO: 'setup-technology-agentless-radio',
|
||||
|
|
|
@ -21,7 +21,7 @@ const DATE_WITH_DATA = {
|
|||
|
||||
const ALERTS_FLYOUT_SELECTOR = 'alertsFlyout';
|
||||
const FILTER_FOR_VALUE_BUTTON_SELECTOR = 'filterForValue';
|
||||
const ALERTS_TABLE_CONTAINER_SELECTOR = 'alertsTable';
|
||||
const ALERTS_TABLE_CONTAINER_SELECTOR = 'alertsTableIsLoaded';
|
||||
const ALERTS_TABLE_ERROR_PROMPT_SELECTOR = 'alertsTableErrorPrompt';
|
||||
const ALERTS_TABLE_ACTIONS_MENU_SELECTOR = 'alertsTableActionsMenu';
|
||||
const VIEW_RULE_DETAILS_SELECTOR = 'viewRuleDetails';
|
||||
|
|
|
@ -22,7 +22,7 @@ const ALERTS_TITLE = 'Alerts';
|
|||
const ALERTS_ACCORDION_SELECTOR = `accordion-${ALERTS_TITLE}`;
|
||||
const ALERTS_SECTION_BUTTON_CSS_SELECTOR = `[data-test-subj=${ALERTS_ACCORDION_SELECTOR}] button.euiAccordion__button`;
|
||||
const ALERTS_TABLE_NO_DATA_SELECTOR = 'alertsTableEmptyState';
|
||||
const ALERTS_TABLE_WITH_DATA_SELECTOR = 'alertsTable';
|
||||
const ALERTS_TABLE_WITH_DATA_SELECTOR = 'alertsTableIsLoaded';
|
||||
const ALERTS_TABLE_LOADING_SELECTOR = 'internalAlertsPageLoading';
|
||||
|
||||
export function ObservabilityOverviewCommonProvider({
|
||||
|
|
|
@ -41,7 +41,7 @@ describe('Alert Table API calls', { tags: ['@ess', '@serverless'] }, () => {
|
|||
});
|
||||
|
||||
it('should call `api/lists/index` only once', () => {
|
||||
cy.get('[data-test-subj="alertsTable"]').then(() => {
|
||||
cy.get('[data-test-subj="alertsTableIsLoaded"]').then(() => {
|
||||
expect(callCount, 'number of times lists index api is called').to.equal(1);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -38,7 +38,7 @@ export const GET_DATA_GRID_HEADER_CELL_ACTION_GROUP = (fieldName: string) => {
|
|||
};
|
||||
|
||||
export const DATA_GRID_FULL_SCREEN =
|
||||
'[data-test-subj="alertsTable"] [data-test-subj="dataGridFullScreenButton"]';
|
||||
'[data-test-subj="alertsTableIsLoaded"] [data-test-subj="dataGridFullScreenButton"]';
|
||||
|
||||
export const DATA_GRID_FIELD_SORT_BTN = '[data-test-subj="dataGridColumnSortingButton"]';
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ export const NEW_TERMS_FIELDS_DETAILS = 'Fields';
|
|||
export const NEW_TERMS_HISTORY_WINDOW_DETAILS = 'History Window Size';
|
||||
|
||||
export const FIELDS_BROWSER_BTN =
|
||||
'[data-test-subj="alertsTable"] [data-test-subj="show-field-browser"]';
|
||||
'[data-test-subj="alertsTableIsLoaded"] [data-test-subj="show-field-browser"]';
|
||||
|
||||
export const LAST_EXECUTION_STATUS_REFRESH_BUTTON =
|
||||
'[data-test-subj="ruleLastExecutionStatusRefreshButton"]';
|
||||
|
|
|
@ -489,7 +489,7 @@ export const sumAlertCountFromAlertCountTable = (callback?: (sumOfEachRow: numbe
|
|||
};
|
||||
|
||||
export const selectFirstPageAlerts = () => {
|
||||
const ALERTS_DATA_GRID = '[data-test-subj="alertsTable"]';
|
||||
const ALERTS_DATA_GRID = '[data-test-subj="alertsTableIsLoaded"]';
|
||||
cy.get(ALERTS_DATA_GRID).find(SELECT_ALL_VISIBLE_ALERTS).scrollIntoView();
|
||||
cy.get(ALERTS_DATA_GRID).find(SELECT_ALL_VISIBLE_ALERTS).click({ force: true });
|
||||
};
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services';
|
||||
import { FtrService } from '../../../functional/ftr_provider_context';
|
||||
|
||||
const ALERT_TABLE_ROW_CSS_SELECTOR = '[data-test-subj="alertsTable"] .euiDataGridRow';
|
||||
const ALERT_TABLE_ROW_CSS_SELECTOR = '[data-test-subj="alertsTableIsLoaded"] .euiDataGridRow';
|
||||
|
||||
export class DetectionsPageObject extends FtrService {
|
||||
private readonly find = this.ctx.getService('find');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue