mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Security Solution][Endpoint][Response Actions] Show correct number of items in response actions history (#142221) (#142265)
* Show correct number of items in page when status filters are selected
When there are more items than the page size, the API was returning one less item when a status filter was selected. This commit fixes that.
* Tests
* some unrelated test cleanup
(cherry picked from commit 1530d1720a
)
Co-authored-by: Ashokaditya <1849116+ashokaditya@users.noreply.github.com>
This commit is contained in:
parent
1e88196d61
commit
26b181e672
4 changed files with 86 additions and 29 deletions
|
@ -344,26 +344,20 @@ describe('Response actions history', () => {
|
|||
);
|
||||
|
||||
// should have 4 pages each of size 10.
|
||||
expect(renderResult.getByTestId('pagination-button-0')).toHaveAttribute(
|
||||
'aria-label',
|
||||
'Page 1 of 4'
|
||||
);
|
||||
expect(getByTestId('pagination-button-0')).toHaveAttribute('aria-label', 'Page 1 of 4');
|
||||
|
||||
// toggle page size popover
|
||||
userEvent.click(renderResult.getByTestId('tablePaginationPopoverButton'));
|
||||
userEvent.click(getByTestId('tablePaginationPopoverButton'));
|
||||
await waitForEuiPopoverOpen();
|
||||
// click size 20
|
||||
userEvent.click(renderResult.getByTestId('tablePagination-20-rows'));
|
||||
userEvent.click(getByTestId('tablePagination-20-rows'));
|
||||
|
||||
expect(renderResult.getByTestId(`${testPrefix}-endpointListTableTotal`)).toHaveTextContent(
|
||||
expect(getByTestId(`${testPrefix}-endpointListTableTotal`)).toHaveTextContent(
|
||||
'Showing 1-20 of 33 response actions'
|
||||
);
|
||||
|
||||
// should have only 2 pages each of size 20
|
||||
expect(renderResult.getByTestId('pagination-button-0')).toHaveAttribute(
|
||||
'aria-label',
|
||||
'Page 1 of 2'
|
||||
);
|
||||
expect(getByTestId('pagination-button-0')).toHaveAttribute('aria-label', 'Page 1 of 2');
|
||||
});
|
||||
|
||||
it('should show 1-1 record label when only 1 record', async () => {
|
||||
|
@ -544,8 +538,10 @@ describe('Response actions history', () => {
|
|||
|
||||
it('should have a search bar', () => {
|
||||
render();
|
||||
userEvent.click(renderResult.getByTestId(`${testPrefix}-${filterPrefix}-popoverButton`));
|
||||
const searchBar = renderResult.getByTestId(`${testPrefix}-${filterPrefix}-search`);
|
||||
|
||||
const { getByTestId } = renderResult;
|
||||
userEvent.click(getByTestId(`${testPrefix}-${filterPrefix}-popoverButton`));
|
||||
const searchBar = getByTestId(`${testPrefix}-${filterPrefix}-search`);
|
||||
expect(searchBar).toBeTruthy();
|
||||
expect(searchBar.querySelector('input')?.getAttribute('placeholder')).toEqual(
|
||||
'Search actions'
|
||||
|
@ -594,10 +590,10 @@ describe('Response actions history', () => {
|
|||
it('should have `clear all` button `disabled` when no selected values', () => {
|
||||
render();
|
||||
|
||||
userEvent.click(renderResult.getByTestId(`${testPrefix}-${filterPrefix}-popoverButton`));
|
||||
const clearAllButton = renderResult.getByTestId(
|
||||
`${testPrefix}-${filterPrefix}-clearAllButton`
|
||||
);
|
||||
const { getByTestId } = renderResult;
|
||||
|
||||
userEvent.click(getByTestId(`${testPrefix}-${filterPrefix}-popoverButton`));
|
||||
const clearAllButton = getByTestId(`${testPrefix}-${filterPrefix}-clearAllButton`);
|
||||
expect(clearAllButton.hasAttribute('disabled')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -14,7 +14,7 @@ import type {
|
|||
LogsEndpointActionResponse,
|
||||
} from '../../../../common/endpoint/types';
|
||||
import { EndpointActionGenerator } from '../../../../common/endpoint/data_generators/endpoint_action_generator';
|
||||
import { getActionList } from './action_list';
|
||||
import { getActionList, getActionListByStatus } from './action_list';
|
||||
import { CustomHttpRequestError } from '../../../utils/custom_http_request_error';
|
||||
import {
|
||||
applyActionListEsSearchMock,
|
||||
|
@ -650,3 +650,59 @@ describe('When using `getActionList()', () => {
|
|||
await expect(getActionListPromise).rejects.toBeInstanceOf(CustomHttpRequestError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('When using `getActionListByStatus()', () => {
|
||||
let esClient: ElasticsearchClientMock;
|
||||
let logger: MockedLogger;
|
||||
// let endpointActionGenerator: EndpointActionGenerator;
|
||||
let actionRequests: estypes.SearchResponse<LogsEndpointAction>;
|
||||
let actionResponses: estypes.SearchResponse<EndpointActionResponse | LogsEndpointActionResponse>;
|
||||
let endpointAppContextService: EndpointAppContextService;
|
||||
|
||||
beforeEach(() => {
|
||||
esClient = elasticsearchServiceMock.createScopedClusterClient().asInternalUser;
|
||||
logger = loggingSystemMock.createLogger();
|
||||
// endpointActionGenerator = new EndpointActionGenerator('seed');
|
||||
endpointAppContextService = new EndpointAppContextService();
|
||||
endpointAppContextService.setup(createMockEndpointAppContextServiceSetupContract());
|
||||
endpointAppContextService.start(createMockEndpointAppContextServiceStartContract());
|
||||
|
||||
actionRequests = createActionRequestsEsSearchResultsMock(undefined);
|
||||
actionResponses = createActionResponsesEsSearchResultsMock();
|
||||
|
||||
applyActionListEsSearchMock(esClient, actionRequests, actionResponses);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
endpointAppContextService.stop();
|
||||
});
|
||||
|
||||
it('should return expected output `data` length for selected statuses', async () => {
|
||||
actionRequests = createActionRequestsEsSearchResultsMock(undefined, true);
|
||||
actionResponses = createActionResponsesEsSearchResultsMock();
|
||||
|
||||
applyActionListEsSearchMock(esClient, actionRequests, actionResponses);
|
||||
// mock metadataService.findHostMetadataForFleetAgents resolved value
|
||||
(endpointAppContextService.getEndpointMetadataService as jest.Mock) = jest
|
||||
.fn()
|
||||
.mockReturnValue({
|
||||
findHostMetadataForFleetAgents: jest.fn().mockResolvedValue([]),
|
||||
});
|
||||
|
||||
const getActionListByStatusPromise = ({ page }: { page: number }) =>
|
||||
getActionListByStatus({
|
||||
esClient,
|
||||
logger,
|
||||
metadataService: endpointAppContextService.getEndpointMetadataService(),
|
||||
page: page ?? 1,
|
||||
pageSize: 10,
|
||||
statuses: ['failed', 'pending', 'successful'],
|
||||
});
|
||||
|
||||
expect(await (await getActionListByStatusPromise({ page: 1 })).data.length).toEqual(10);
|
||||
|
||||
expect(await (await getActionListByStatusPromise({ page: 2 })).data.length).toEqual(10);
|
||||
|
||||
expect(await (await getActionListByStatusPromise({ page: 3 })).data.length).toEqual(3);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -92,8 +92,8 @@ export const getActionListByStatus = async ({
|
|||
userIds,
|
||||
commands,
|
||||
statuses,
|
||||
// for size 20 -> page 1: (0, 19), page 2: (20,39) ...etc
|
||||
data: actionDetailsByStatus.slice((page - 1) * size, size * page - 1),
|
||||
// for size 20 -> page 1: (0, 20), page 2: (20, 40) ...etc
|
||||
data: actionDetailsByStatus.slice((page - 1) * size, size * page),
|
||||
total: actionDetailsByStatus.length,
|
||||
};
|
||||
};
|
||||
|
@ -251,7 +251,7 @@ const getActionDetailsList = async ({
|
|||
});
|
||||
|
||||
// compute action details list for each action id
|
||||
const actionDetails: ActionDetails[] = normalizedActionRequests.map((action) => {
|
||||
const actionDetails: ActionListApiResponse['data'] = normalizedActionRequests.map((action) => {
|
||||
// pick only those responses that match the current action id
|
||||
const matchedResponses = categorizedResponses.filter((categorizedResponse) =>
|
||||
categorizedResponse.type === 'response'
|
||||
|
|
|
@ -21,17 +21,22 @@ import {
|
|||
} from '../../../../common/endpoint/constants';
|
||||
|
||||
export const createActionRequestsEsSearchResultsMock = (
|
||||
agentIds?: string[]
|
||||
agentIds?: string[],
|
||||
isMultipleActions: boolean = false
|
||||
): estypes.SearchResponse<LogsEndpointAction> => {
|
||||
const endpointActionGenerator = new EndpointActionGenerator('seed');
|
||||
|
||||
return endpointActionGenerator.toEsSearchResponse<LogsEndpointAction>([
|
||||
endpointActionGenerator.generateActionEsHit({
|
||||
EndpointActions: { action_id: '123' },
|
||||
agent: { id: agentIds ? agentIds : 'agent-a' },
|
||||
'@timestamp': '2022-04-27T16:08:47.449Z',
|
||||
}),
|
||||
]);
|
||||
return isMultipleActions
|
||||
? endpointActionGenerator.toEsSearchResponse<LogsEndpointAction>(
|
||||
Array.from({ length: 23 }).map(() => endpointActionGenerator.generateActionEsHit())
|
||||
)
|
||||
: endpointActionGenerator.toEsSearchResponse<LogsEndpointAction>([
|
||||
endpointActionGenerator.generateActionEsHit({
|
||||
EndpointActions: { action_id: '123' },
|
||||
agent: { id: agentIds ? agentIds : 'agent-a' },
|
||||
'@timestamp': '2022-04-27T16:08:47.449Z',
|
||||
}),
|
||||
]);
|
||||
};
|
||||
|
||||
export const createActionResponsesEsSearchResultsMock = (
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue