[Fleet] skip loading agents when in progress (#136624)

* skip loading agents when in progress

* added unit test

* added comment
This commit is contained in:
Julia Bardi 2022-07-19 18:11:49 +02:00 committed by GitHub
parent 302bd423f3
commit 68cb7fb680
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 125 additions and 83 deletions

View file

@ -12,7 +12,7 @@ import { act, fireEvent, waitFor } from '@testing-library/react';
import { createFleetTestRendererMock } from '../../../../../mock';
import { sendGetAgents } from '../../../hooks';
import { sendGetAgents, sendGetAgentStatus } from '../../../hooks';
import { AgentListPage } from '.';
@ -28,17 +28,7 @@ jest.mock('../../../hooks', () => ({
return props.children;
},
useFleetStatus: jest.fn().mockReturnValue({}),
sendGetAgentStatus: jest.fn().mockResolvedValue({
data: {
results: {
online: 6,
error: 0,
offline: 0,
updating: 0,
},
totalInactive: 0,
},
}),
sendGetAgentStatus: jest.fn(),
useAuthz: jest.fn().mockReturnValue({ fleet: { all: true } }),
useStartServices: jest.fn().mockReturnValue({
notifications: {
@ -74,6 +64,7 @@ jest.mock('./components/search_and_filter_bar', () => {
});
const mockedSendGetAgents = sendGetAgents as jest.Mock;
const mockedSendGetAgentStatus = sendGetAgentStatus as jest.Mock;
function renderAgentList() {
const renderer = createFleetTestRendererMock();
@ -111,96 +102,140 @@ describe('agent_list_page', () => {
},
});
jest.useFakeTimers();
({ utils } = renderAgentList());
await waitFor(() => {
expect(utils.getByText('Showing 6 agents')).toBeInTheDocument();
});
act(() => {
const selectAll = utils.container.querySelector('[data-test-subj="checkboxSelectAll"]');
fireEvent.click(selectAll!);
});
await waitFor(() => {
utils.getByText('5 agents selected');
});
act(() => {
fireEvent.click(utils.getByText('Select everything on all pages'));
});
utils.getByText('All agents selected');
});
afterEach(() => {
jest.useRealTimers();
});
it('should not set selection mode when agent selection changed automatically', async () => {
it('should not send another agents status request if first one takes longer', () => {
mockedSendGetAgentStatus.mockImplementation(async () => {
const sleep = () => {
return new Promise((res) => {
setTimeout(() => res({}), 35000);
});
};
await sleep();
return {
data: {
results: {
online: 6,
error: 0,
offline: 0,
updating: 0,
},
totalInactive: 0,
},
};
});
({ utils } = renderAgentList());
act(() => {
jest.runOnlyPendingTimers();
jest.advanceTimersByTime(65000);
});
await waitFor(() => {
expect(utils.getByText('agent6')).toBeInTheDocument();
});
utils.getByText('All agents selected');
expect(
utils
.getByText('agent6')
.closest('tr')!
.getAttribute('class')!
.includes('euiTableRow-isSelected')
).toBeTruthy();
expect(mockedSendGetAgentStatus).toHaveBeenCalledTimes(1);
});
it('should set selection mode when agent selection changed manually', async () => {
act(() => {
fireEvent.click(utils.getAllByRole('checkbox')[3]);
describe('selection change', () => {
beforeEach(async () => {
mockedSendGetAgentStatus.mockResolvedValue({
data: {
results: {
online: 6,
error: 0,
offline: 0,
updating: 0,
},
totalInactive: 0,
},
});
({ utils } = renderAgentList());
await waitFor(() => {
expect(utils.getByText('Showing 6 agents')).toBeInTheDocument();
});
act(() => {
const selectAll = utils.container.querySelector('[data-test-subj="checkboxSelectAll"]');
fireEvent.click(selectAll!);
});
await waitFor(() => {
utils.getByText('5 agents selected');
});
act(() => {
fireEvent.click(utils.getByText('Select everything on all pages'));
});
utils.getByText('All agents selected');
});
utils.getByText('4 agents selected');
});
it('should not set selection mode when agent selection changed automatically', async () => {
act(() => {
jest.runOnlyPendingTimers();
});
it('should pass sort parameters on table sort', () => {
act(() => {
fireEvent.click(utils.getByTitle('Last activity'));
await waitFor(() => {
expect(utils.getByText('agent6')).toBeInTheDocument();
});
utils.getByText('All agents selected');
expect(
utils
.getByText('agent6')
.closest('tr')!
.getAttribute('class')!
.includes('euiTableRow-isSelected')
).toBeTruthy();
});
expect(mockedSendGetAgents).toHaveBeenCalledWith(
expect.objectContaining({
sortField: 'last_checkin',
sortOrder: 'asc',
})
);
});
it('should set selection mode when agent selection changed manually', async () => {
act(() => {
fireEvent.click(utils.getAllByRole('checkbox')[3]);
});
it('should pass keyword field on table sort on version', () => {
act(() => {
fireEvent.click(utils.getByTitle('Version'));
utils.getByText('4 agents selected');
});
expect(mockedSendGetAgents).toHaveBeenCalledWith(
expect.objectContaining({
sortField: 'local_metadata.elastic.agent.version.keyword',
sortOrder: 'asc',
})
);
});
it('should pass sort parameters on table sort', () => {
act(() => {
fireEvent.click(utils.getByTitle('Last activity'));
});
it('should pass keyword field on table sort on hostname', () => {
act(() => {
fireEvent.click(utils.getByTitle('Host'));
expect(mockedSendGetAgents).toHaveBeenCalledWith(
expect.objectContaining({
sortField: 'last_checkin',
sortOrder: 'asc',
})
);
});
expect(mockedSendGetAgents).toHaveBeenCalledWith(
expect.objectContaining({
sortField: 'local_metadata.host.hostname.keyword',
sortOrder: 'asc',
})
);
it('should pass keyword field on table sort on version', () => {
act(() => {
fireEvent.click(utils.getByTitle('Version'));
});
expect(mockedSendGetAgents).toHaveBeenCalledWith(
expect.objectContaining({
sortField: 'local_metadata.elastic.agent.version.keyword',
sortOrder: 'asc',
})
);
});
it('should pass keyword field on table sort on hostname', () => {
act(() => {
fireEvent.click(utils.getByTitle('Host'));
});
expect(mockedSendGetAgents).toHaveBeenCalledWith(
expect.objectContaining({
sortField: 'local_metadata.host.hostname.keyword',
sortOrder: 'asc',
})
);
});
});
});

View file

@ -220,14 +220,20 @@ export const AgentListPage: React.FunctionComponent<{}> = () => {
},
};
const isLoadingVar = useRef<boolean>(false);
// Request to fetch agents and agent status
const currentRequestRef = useRef<number>(0);
const fetchData = useCallback(
({ refreshTags = false }: { refreshTags?: boolean } = {}) => {
async function fetchDataAsync() {
// skipping refresh if previous request is in progress
if (isLoadingVar.current) {
return;
}
currentRequestRef.current++;
const currentRequest = currentRequestRef.current;
isLoadingVar.current = true;
try {
setIsLoading(true);
const [agentsRequest, agentsStatusRequest] = await Promise.all([
@ -244,7 +250,8 @@ export const AgentListPage: React.FunctionComponent<{}> = () => {
kuery: kuery && kuery !== '' ? kuery : undefined,
}),
]);
// Return if a newer request as been triggered
isLoadingVar.current = false;
// Return if a newer request has been triggered
if (currentRequestRef.current !== currentRequest) {
return;
}