[Security Solution][Endpoint][Response Actions]fix tray collapse on history page (#165260)

## Summary

Fixes a bug on the response actions history page where the details tray
does not collapse on a single click.

**before** 
elastic/kibana/issues/165058

**after**

![response-actions-hisotry-collapse](71ee1663-c087-41ef-b7c0-3c9be65f7ef6)

### Checklist

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
This commit is contained in:
Ash 2023-09-04 10:57:32 +02:00 committed by GitHub
parent a2e841e6e4
commit c9c7f076ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 25 deletions

View file

@ -7,19 +7,19 @@
import React, { memo, useCallback, useEffect, useMemo, useState } from 'react';
import {
EuiI18nNumber,
type CriteriaWithPagination,
EuiAvatar,
EuiBasicTable,
EuiButtonIcon,
EuiFacetButton,
EuiHorizontalRule,
RIGHT_ALIGNMENT,
EuiI18nNumber,
EuiScreenReaderOnly,
EuiSkeletonText,
EuiText,
EuiToolTip,
type HorizontalAlignment,
type CriteriaWithPagination,
EuiSkeletonText,
RIGHT_ALIGNMENT,
} from '@elastic/eui';
import { euiStyled } from '@kbn/kibana-react-plugin/common';
import { FormattedMessage } from '@kbn/i18n-react';
@ -30,14 +30,13 @@ import { SecuritySolutionLinkAnchor } from '../../../../common/components/links'
import type { ActionListApiResponse } from '../../../../../common/endpoint/types';
import type { EndpointActionListRequestQuery } from '../../../../../common/api/endpoint';
import { FormattedDate } from '../../../../common/components/formatted_date';
import { TABLE_COLUMN_NAMES, UX_MESSAGES, ARIA_LABELS } from '../translations';
import { ARIA_LABELS, TABLE_COLUMN_NAMES, UX_MESSAGES } from '../translations';
import { getActionStatus, getUiCommand } from './hooks';
import { getEmptyValue } from '../../../../common/components/empty_value';
import { StatusBadge } from './status_badge';
import { ActionsLogExpandedTray } from './action_log_expanded_tray';
import { useTestIdGenerator } from '../../../hooks/use_test_id_generator';
import { MANAGEMENT_PAGE_SIZE_OPTIONS } from '../../../common/constants';
import { useActionHistoryUrlParams } from './use_action_history_url_params';
import { useUrlPagination } from '../../../hooks/use_url_pagination';
const emptyValue = getEmptyValue();
@ -292,22 +291,19 @@ export const ActionsLogTable = memo<ActionsLogTableProps>(
}) => {
const getTestId = useTestIdGenerator(dataTestSubj);
const { pagination: paginationFromUrlParams } = useUrlPagination();
const { withOutputs: withOutputsFromUrl } = useActionHistoryUrlParams();
const [expandedRowMap, setExpandedRowMap] = useState<ExpandedRowMapType>({});
const actionIdsWithOpenTrays = useMemo((): string[] => {
// get the list of action ids from URL params on the history page
if (!isFlyout) {
return withOutputsFromUrl ?? [];
}
// get the list of action ids form the query params for flyout view
return queryParams.withOutputs
? typeof queryParams.withOutputs === 'string'
? [queryParams.withOutputs]
: queryParams.withOutputs
: [];
}, [isFlyout, queryParams.withOutputs, withOutputsFromUrl]);
const actionIdsWithOpenTrays = useMemo(
(): string[] =>
// get the list of action ids from the query params for flyout view
queryParams.withOutputs
? typeof queryParams.withOutputs === 'string'
? [queryParams.withOutputs]
: queryParams.withOutputs
: [],
[queryParams.withOutputs]
);
const redoOpenTrays = useCallback(() => {
if (actionIdsWithOpenTrays.length && items.length) {

View file

@ -7,12 +7,13 @@
import React from 'react';
import * as reactTestingLibrary from '@testing-library/react';
import { waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl';
import type { IHttpFetchError } from '@kbn/core-http-browser';
import {
createAppRootMockRenderer,
type AppContextTestRender,
createAppRootMockRenderer,
} from '../../../../common/mock/endpoint';
import { ResponseActionsLog } from '../response_actions_log';
import type {
@ -29,7 +30,6 @@ import { v4 as uuidv4 } from 'uuid';
import { RESPONSE_ACTION_API_COMMANDS_NAMES } from '../../../../../common/endpoint/service/response_actions/constants';
import { useUserPrivileges as _useUserPrivileges } from '../../../../common/components/user_privileges';
import { responseActionsHttpMocks } from '../../../mocks/response_actions_http_mocks';
import { waitFor } from '@testing-library/react';
import { getEndpointAuthzInitialStateMock } from '../../../../../common/endpoint/service/authz/mocks';
import { useGetEndpointActionList as _useGetEndpointActionList } from '../../../hooks/response_actions/use_get_endpoint_action_list';
import { OUTPUT_MESSAGES } from '../translations';
@ -470,7 +470,7 @@ describe('Response actions history', () => {
);
});
it('should expand each row to show details', async () => {
it('should expand/collapse each row to show/hide details', async () => {
render();
const { getAllByTestId, queryAllByTestId } = renderResult;
@ -961,8 +961,7 @@ describe('Response actions history', () => {
const expandButtons = getAllByTestId(`${testPrefix}-expand-button`);
expandButtons.map((button) => userEvent.click(button));
const outputs = getAllByTestId(`${testPrefix}-details-tray-output`);
return outputs;
return getAllByTestId(`${testPrefix}-details-tray-output`);
};
it.each(RESPONSE_ACTION_API_COMMANDS_NAMES)(

View file

@ -50,4 +50,25 @@ describe('Response actions history page', () => {
cy.getByTestSubj('pagination-button-0').click();
cy.getByTestSubj('response-actions-list-details-tray').should('exist');
});
it('collapses expanded tray with a single click', () => {
loadPage(`/app/security/administration/response_actions_history`);
// 2nd row on 1st page
const row = cy.getByTestSubj('response-actions-list-expand-button').eq(1);
// expand the row
row.click();
cy.getByTestSubj('response-actions-list-details-tray').should('exist');
cy.url().should('include', 'withOutputs');
// collapse the row
cy.intercept('GET', '/api/endpoint/action*').as('getResponses');
row.click();
// wait for the API response to come back
// and then see if the tray is actually closed
cy.wait('@getResponses', { timeout: 500 }).then(() => {
cy.getByTestSubj('response-actions-list-details-tray').should('not.exist');
cy.url().should('not.include', 'withOutputs');
});
});
});

View file

@ -236,7 +236,7 @@ describe('Response actions history page', () => {
return {
id: `agent-id-${i}`,
name: `Host-name-${i}`,
selected: [0, 1, 3, 5].includes(i) ? true : false,
selected: [0, 1, 3, 5].includes(i),
};
}),
page: 0,