diff --git a/public/app/plugins/panel/logs/LogsPanel.test.tsx b/public/app/plugins/panel/logs/LogsPanel.test.tsx index 5e6130ac227..7c3fdbf0726 100644 --- a/public/app/plugins/panel/logs/LogsPanel.test.tsx +++ b/public/app/plugins/panel/logs/LogsPanel.test.tsx @@ -3,7 +3,17 @@ import userEvent from '@testing-library/user-event'; import React, { ComponentProps } from 'react'; import { DatasourceSrvMock, MockDataSourceApi } from 'test/mocks/datasource_srv'; -import { LoadingState, createDataFrame, FieldType, LogsSortOrder, CoreApp } from '@grafana/data'; +import { + LoadingState, + createDataFrame, + FieldType, + LogsSortOrder, + CoreApp, + getDefaultTimeRange, + LogsDedupStrategy, + EventBusSrv, +} from '@grafana/data'; +import * as styles from 'app/features/logs/components/getLogRowStyles'; import { LogRowContextModal } from 'app/features/logs/components/log-context/LogRowContextModal'; import { LogsPanel } from './LogsPanel'; @@ -252,15 +262,76 @@ describe('LogsPanel', () => { }); }); }); + + describe('Performance regressions', () => { + const series = [ + createDataFrame({ + refId: 'A', + fields: [ + { + name: 'time', + type: FieldType.time, + values: ['2019-04-26T09:28:11.352440161Z'], + }, + { + name: 'message', + type: FieldType.string, + values: ['logline text'], + labels: { + app: 'common_app', + job: 'common_job', + }, + }, + ], + }), + ]; + + beforeEach(() => { + /** + * For the lack of a better option, we spy on getLogRowStyles calls to count re-renders. + */ + jest.spyOn(styles, 'getLogRowStyles'); + jest.mocked(styles.getLogRowStyles).mockClear(); + }); + + it('does not rerender without changes', async () => { + const { rerender, props } = setup({ + data: { + series, + }, + }); + + expect(await screen.findByRole('row')).toBeInTheDocument(); + + rerender(); + + expect(await screen.findByRole('row')).toBeInTheDocument(); + expect(styles.getLogRowStyles).toHaveBeenCalledTimes(3); + }); + + it('rerenders when prop changes', async () => { + const { rerender, props } = setup({ + data: { + series, + }, + }); + + expect(await screen.findByRole('row')).toBeInTheDocument(); + + rerender(); + + expect(await screen.findByRole('row')).toBeInTheDocument(); + expect(jest.mocked(styles.getLogRowStyles).mock.calls.length).toBeGreaterThan(3); + }); + }); }); const setup = (propsOverrides?: {}) => { - const props = { + const props: LogsPanelProps = { data: { error: undefined, request: { panelId: 4, - dashboardId: 123, app: 'dashboard', requestId: 'A', timezone: 'browser', @@ -268,17 +339,44 @@ const setup = (propsOverrides?: {}) => { intervalMs: 30000, maxDataPoints: 823, targets: [], - range: {}, + range: getDefaultTimeRange(), + scopedVars: {}, + startTime: 1, }, series: [], state: LoadingState.Done, + timeRange: getDefaultTimeRange(), }, timeZone: 'utc', - options: {}, + timeRange: getDefaultTimeRange(), + options: { + showLabels: false, + showTime: false, + wrapLogMessage: false, + showCommonLabels: false, + prettifyLogMessage: false, + sortOrder: LogsSortOrder.Descending, + dedupStrategy: LogsDedupStrategy.none, + enableLogDetails: false, + showLogContextToggle: false, + }, title: 'Logs panel', id: 1, + transparent: false, + width: 400, + height: 100, + renderCounter: 0, + fieldConfig: { + defaults: {}, + overrides: [], + }, + eventBus: new EventBusSrv(), + onOptionsChange: jest.fn(), + onFieldConfigChange: jest.fn(), + replaceVariables: jest.fn(), + onChangeTimeRange: jest.fn(), ...propsOverrides, - } as unknown as LogsPanelProps; + }; - return render(); + return { ...render(), props }; };