LogContext: Fix filtering out log lines with the same entry (#70538)

* fix bug with filtering out too many log lines

* fix acts

* remove unused line
This commit is contained in:
Sven Grossmann 2023-06-23 10:20:07 +02:00 committed by GitHub
parent fbfd1c24e4
commit 9cf685cfda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 103 additions and 73 deletions

View File

@ -4,13 +4,66 @@ import React from 'react';
import { act } from 'react-dom/test-utils'; import { act } from 'react-dom/test-utils';
import { render } from 'test/redux-rtl'; import { render } from 'test/redux-rtl';
import { SplitOpenOptions } from '@grafana/data'; import {
createDataFrame,
import { createLogRow } from '../__mocks__/logRow'; FieldType,
LogRowContextQueryDirection,
LogsSortOrder,
SplitOpenOptions,
} from '@grafana/data';
import { dataFrameToLogsModel } from 'app/core/logsModel';
import { LogRowContextModal } from './LogRowContextModal'; import { LogRowContextModal } from './LogRowContextModal';
const getRowContext = jest.fn().mockResolvedValue({ data: { fields: [], rows: [] } }); const dfBefore = createDataFrame({
fields: [
{
name: 'time',
type: FieldType.time,
values: ['2019-04-26T07:28:11.352440161Z', '2019-04-26T09:28:11.352440161Z'],
},
{
name: 'message',
type: FieldType.string,
values: ['foo123', 'foo123'],
},
],
});
const dfNow = createDataFrame({
fields: [
{
name: 'time',
type: FieldType.time,
values: ['2019-04-26T09:28:11.352440161Z'],
},
{
name: 'message',
type: FieldType.string,
values: ['foo123'],
},
],
});
const dfAfter = createDataFrame({
fields: [
{
name: 'time',
type: FieldType.time,
values: ['2019-04-26T14:42:50.991981292Z', '2019-04-26T16:28:11.352440161Z'],
},
{
name: 'message',
type: FieldType.string,
values: ['foo123', 'bar123'],
},
],
});
const getRowContext = jest.fn().mockImplementation(async (_, options) => {
if (options.direction === LogRowContextQueryDirection.Forward) {
return { data: [dfBefore] };
} else {
return { data: [dfAfter] };
}
});
const getRowContextQuery = jest.fn().mockResolvedValue({ datasource: { uid: 'test-uid' } }); const getRowContextQuery = jest.fn().mockResolvedValue({ datasource: { uid: 'test-uid' } });
const dispatchMock = jest.fn(); const dispatchMock = jest.fn();
@ -28,7 +81,8 @@ jest.mock('app/features/explore/state/main', () => ({
}, },
})); }));
const row = createLogRow({ uid: '1' }); const logs = dataFrameToLogsModel([dfNow]);
const row = logs.rows[0];
const timeZone = 'UTC'; const timeZone = 'UTC';
@ -44,54 +98,37 @@ describe('LogRowContextModal', () => {
}); });
it('should not render modal when it is closed', async () => { it('should not render modal when it is closed', async () => {
act(() => {
render( render(
<LogRowContextModal <LogRowContextModal row={row} open={false} onClose={() => {}} getRowContext={getRowContext} timeZone={timeZone} />
row={row}
open={false}
onClose={() => {}}
getRowContext={getRowContext}
timeZone={timeZone}
/>
); );
});
await waitFor(() => expect(screen.queryByText('Log context')).not.toBeInTheDocument()); await waitFor(() => expect(screen.queryByText('Log context')).not.toBeInTheDocument());
}); });
it('should render modal when it is open', async () => { it('should render modal when it is open', async () => {
act(() => {
render( render(
<LogRowContextModal <LogRowContextModal row={row} open={true} onClose={() => {}} getRowContext={getRowContext} timeZone={timeZone} />
row={row}
open={true}
onClose={() => {}}
getRowContext={getRowContext}
timeZone={timeZone}
/>
); );
});
await waitFor(() => expect(screen.queryByText('Log context')).toBeInTheDocument()); await waitFor(() => expect(screen.queryByText('Log context')).toBeInTheDocument());
}); });
it('should call getRowContext on open and change of row', async () => { it('should call getRowContext on open and change of row', async () => {
act(() => {
render( render(
<LogRowContextModal <LogRowContextModal row={row} open={false} onClose={() => {}} getRowContext={getRowContext} timeZone={timeZone} />
row={row}
open={false}
onClose={() => {}}
getRowContext={getRowContext}
timeZone={timeZone}
/>
); );
});
await waitFor(() => expect(getRowContext).not.toHaveBeenCalled()); await waitFor(() => expect(getRowContext).not.toHaveBeenCalled());
}); });
it('should call getRowContext on open', async () => { it('should call getRowContext on open', async () => {
act(() => { render(
<LogRowContextModal row={row} open={true} onClose={() => {}} getRowContext={getRowContext} timeZone={timeZone} />
);
await waitFor(() => expect(getRowContext).toHaveBeenCalledTimes(2));
});
it('should render 3 lines containing `foo123`', async () => {
render( render(
<LogRowContextModal <LogRowContextModal
row={row} row={row}
@ -99,36 +136,27 @@ describe('LogRowContextModal', () => {
onClose={() => {}} onClose={() => {}}
getRowContext={getRowContext} getRowContext={getRowContext}
timeZone={timeZone} timeZone={timeZone}
logsSortOrder={LogsSortOrder.Descending}
/> />
); );
}); // there need to be 2 lines with that message. 1 in before, 1 in now, 1 in after
await waitFor(() => expect(getRowContext).toHaveBeenCalledTimes(2)); await waitFor(() => expect(screen.getAllByText('foo123').length).toBe(3));
}); });
it('should call getRowContext when limit changes', async () => { it('should call getRowContext when limit changes', async () => {
act(() => {
render( render(
<LogRowContextModal <LogRowContextModal row={row} open={true} onClose={() => {}} getRowContext={getRowContext} timeZone={timeZone} />
row={row}
open={true}
onClose={() => {}}
getRowContext={getRowContext}
timeZone={timeZone}
/>
); );
});
await waitFor(() => expect(getRowContext).toHaveBeenCalledTimes(2)); await waitFor(() => expect(getRowContext).toHaveBeenCalledTimes(2));
const tenLinesButton = screen.getByRole('button', { const fiftyLinesButton = screen.getByRole('button', {
name: /50 lines/i, name: /50 lines/i,
}); });
await userEvent.click(tenLinesButton); await userEvent.click(fiftyLinesButton);
const twentyLinesButton = screen.getByRole('menuitemradio', { const twentyLinesButton = screen.getByRole('menuitemradio', {
name: /20 lines/i, name: /20 lines/i,
}); });
act(() => { await userEvent.click(twentyLinesButton);
userEvent.click(twentyLinesButton);
});
await waitFor(() => expect(getRowContext).toHaveBeenCalledTimes(4)); await waitFor(() => expect(getRowContext).toHaveBeenCalledTimes(4));
}); });
@ -190,12 +218,14 @@ describe('LogRowContextModal', () => {
<LogRowContextModal row={row} open={true} onClose={() => {}} getRowContext={getRowContext} timeZone={timeZone} /> <LogRowContextModal row={row} open={true} onClose={() => {}} getRowContext={getRowContext} timeZone={timeZone} />
); );
await waitFor(() => {
expect( expect(
screen.queryByRole('button', { screen.queryByRole('button', {
name: /open in split view/i, name: /open in split view/i,
}) })
).not.toBeInTheDocument(); ).not.toBeInTheDocument();
}); });
});
it('should call getRowContextQuery', async () => { it('should call getRowContextQuery', async () => {
const getRowContextQuery = jest.fn().mockResolvedValue({ datasource: { uid: 'test-uid' } }); const getRowContextQuery = jest.fn().mockResolvedValue({ datasource: { uid: 'test-uid' } });
@ -233,7 +263,7 @@ describe('LogRowContextModal', () => {
await userEvent.click(splitViewButton); await userEvent.click(splitViewButton);
expect(onClose).toHaveBeenCalled(); await waitFor(() => expect(onClose).toHaveBeenCalled());
}); });
it('should create correct splitOpen', async () => { it('should create correct splitOpen', async () => {

View File

@ -224,10 +224,10 @@ export const LogRowContextModal: React.FunctionComponent<LogRowContextModalProps
setContext({ setContext({
after: afterRows.filter((r) => { after: afterRows.filter((r) => {
return r.timeEpochNs !== row.timeEpochNs && r.entry !== row.entry; return r.timeEpochNs !== row.timeEpochNs || r.entry !== row.entry;
}), }),
before: beforeRows.filter((r) => { before: beforeRows.filter((r) => {
return r.timeEpochNs !== row.timeEpochNs && r.entry !== row.entry; return r.timeEpochNs !== row.timeEpochNs || r.entry !== row.entry;
}), }),
}); });
} else { } else {