1import React from 'react';
2import { range } from 'lodash';
3import { LogRows, PREVIEW_LIMIT } from './LogRows';
4import { mount } from 'enzyme';
5import { LogLevel, LogRowModel, LogsDedupStrategy, MutableDataFrame, LogsSortOrder } from '@grafana/data';
6import { LogRow } from './LogRow';
7
8describe('LogRows', () => {
9  it('renders rows', () => {
10    const rows: LogRowModel[] = [makeLog({ uid: '1' }), makeLog({ uid: '2' }), makeLog({ uid: '3' })];
11    const wrapper = mount(
12      <LogRows
13        logRows={rows}
14        dedupStrategy={LogsDedupStrategy.none}
15        showLabels={false}
16        showTime={false}
17        wrapLogMessage={true}
18        prettifyLogMessage={true}
19        timeZone={'utc'}
20        enableLogDetails={true}
21      />
22    );
23
24    expect(wrapper.find(LogRow).length).toBe(3);
25    expect(wrapper.contains('log message 1')).toBeTruthy();
26    expect(wrapper.contains('log message 2')).toBeTruthy();
27    expect(wrapper.contains('log message 3')).toBeTruthy();
28  });
29
30  it('renders rows only limited number of rows first', () => {
31    const rows: LogRowModel[] = [makeLog({ uid: '1' }), makeLog({ uid: '2' }), makeLog({ uid: '3' })];
32    jest.useFakeTimers('modern');
33    const wrapper = mount(
34      <LogRows
35        logRows={rows}
36        dedupStrategy={LogsDedupStrategy.none}
37        showLabels={false}
38        showTime={false}
39        wrapLogMessage={true}
40        prettifyLogMessage={true}
41        timeZone={'utc'}
42        previewLimit={1}
43        enableLogDetails={true}
44      />
45    );
46
47    expect(wrapper.find(LogRow).length).toBe(1);
48    expect(wrapper.contains('log message 1')).toBeTruthy();
49    jest.runAllTimers();
50    wrapper.update();
51
52    expect(wrapper.find(LogRow).length).toBe(3);
53    expect(wrapper.contains('log message 1')).toBeTruthy();
54    expect(wrapper.contains('log message 2')).toBeTruthy();
55    expect(wrapper.contains('log message 3')).toBeTruthy();
56
57    jest.useRealTimers();
58  });
59
60  it('renders deduped rows if supplied', () => {
61    const rows: LogRowModel[] = [makeLog({ uid: '1' }), makeLog({ uid: '2' }), makeLog({ uid: '3' })];
62    const dedupedRows: LogRowModel[] = [makeLog({ uid: '4' }), makeLog({ uid: '5' })];
63    const wrapper = mount(
64      <LogRows
65        logRows={rows}
66        deduplicatedRows={dedupedRows}
67        dedupStrategy={LogsDedupStrategy.none}
68        showLabels={false}
69        showTime={false}
70        wrapLogMessage={true}
71        prettifyLogMessage={true}
72        timeZone={'utc'}
73        enableLogDetails={true}
74      />
75    );
76
77    expect(wrapper.find(LogRow).length).toBe(2);
78    expect(wrapper.contains('log message 4')).toBeTruthy();
79    expect(wrapper.contains('log message 5')).toBeTruthy();
80  });
81
82  it('renders with default preview limit', () => {
83    // PREVIEW_LIMIT * 2 is there because otherwise we just render all rows
84    const rows: LogRowModel[] = range(PREVIEW_LIMIT * 2 + 1).map((num) => makeLog({ uid: num.toString() }));
85    const wrapper = mount(
86      <LogRows
87        logRows={rows}
88        dedupStrategy={LogsDedupStrategy.none}
89        showLabels={false}
90        showTime={false}
91        wrapLogMessage={true}
92        prettifyLogMessage={true}
93        timeZone={'utc'}
94        enableLogDetails={true}
95      />
96    );
97
98    expect(wrapper.find(LogRow).length).toBe(100);
99  });
100
101  it('renders asc ordered rows if order and function supplied', () => {
102    const rows: LogRowModel[] = [
103      makeLog({ uid: '1', timeEpochMs: 1 }),
104      makeLog({ uid: '3', timeEpochMs: 3 }),
105      makeLog({ uid: '2', timeEpochMs: 2 }),
106    ];
107    const wrapper = mount(
108      <LogRows
109        logRows={rows}
110        dedupStrategy={LogsDedupStrategy.none}
111        showLabels={false}
112        showTime={false}
113        wrapLogMessage={true}
114        prettifyLogMessage={true}
115        timeZone={'utc'}
116        logsSortOrder={LogsSortOrder.Ascending}
117        enableLogDetails={true}
118      />
119    );
120
121    expect(wrapper.find(LogRow).at(0).text()).toBe('log message 1');
122    expect(wrapper.find(LogRow).at(1).text()).toBe('log message 2');
123    expect(wrapper.find(LogRow).at(2).text()).toBe('log message 3');
124  });
125  it('renders desc ordered rows if order and function supplied', () => {
126    const rows: LogRowModel[] = [
127      makeLog({ uid: '1', timeEpochMs: 1 }),
128      makeLog({ uid: '3', timeEpochMs: 3 }),
129      makeLog({ uid: '2', timeEpochMs: 2 }),
130    ];
131    const wrapper = mount(
132      <LogRows
133        logRows={rows}
134        dedupStrategy={LogsDedupStrategy.none}
135        showLabels={false}
136        showTime={false}
137        wrapLogMessage={true}
138        prettifyLogMessage={true}
139        timeZone={'utc'}
140        logsSortOrder={LogsSortOrder.Descending}
141        enableLogDetails={true}
142      />
143    );
144
145    expect(wrapper.find(LogRow).at(0).text()).toBe('log message 3');
146    expect(wrapper.find(LogRow).at(1).text()).toBe('log message 2');
147    expect(wrapper.find(LogRow).at(2).text()).toBe('log message 1');
148  });
149});
150
151const makeLog = (overrides: Partial<LogRowModel>): LogRowModel => {
152  const uid = overrides.uid || '1';
153  const timeEpochMs = overrides.timeEpochMs || 1;
154  const entry = `log message ${uid}`;
155  return {
156    entryFieldIndex: 0,
157    rowIndex: 0,
158    // Does not need to be filled with current tests
159    dataFrame: new MutableDataFrame(),
160    uid,
161    logLevel: LogLevel.debug,
162    entry,
163    hasAnsi: false,
164    hasUnescapedContent: false,
165    labels: {},
166    raw: entry,
167    timeFromNow: '',
168    timeEpochMs,
169    timeEpochNs: (timeEpochMs * 1000000).toString(),
170    timeLocal: '',
171    timeUtc: '',
172    searchWords: [],
173    ...overrides,
174  };
175};
176