forked from grafana/grafana
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathPromQueryField.test.tsx
183 lines (155 loc) · 5.61 KB
/
PromQueryField.test.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
// Core Grafana history https://github.com/grafana/grafana/blob/v11.0.0-preview/public/app/plugins/datasource/prometheus/components/PromQueryField.test.tsx
import { getByTestId, render, screen, waitFor } from '@testing-library/react';
// @ts-ignore
import userEvent from '@testing-library/user-event';
import { CoreApp, DataFrame, LoadingState, PanelData } from '@grafana/data';
import { PrometheusDatasource } from '../datasource';
import PromQlLanguageProvider from '../language_provider';
import { PromQueryField } from './PromQueryField';
import { Props } from './monaco-query-field/MonacoQueryFieldProps';
// the monaco-based editor uses lazy-loading and that does not work
// well with this test, and we do not need the monaco-related
// functionality in this test anyway, so we mock it out.
jest.mock('./monaco-query-field/MonacoQueryFieldLazy', () => {
const fakeQueryField = (props: Props) => {
return <input onBlur={(e) => props.onBlur(e.currentTarget.value)} data-testid={'dummy-code-input'} type={'text'} />;
};
return {
MonacoQueryFieldLazy: fakeQueryField,
};
});
const defaultProps = {
datasource: {
languageProvider: {
start: () => Promise.resolve([]),
syntax: () => {},
getLabelKeys: () => [],
metrics: [],
},
getInitHints: () => [],
} as unknown as PrometheusDatasource,
query: {
expr: '',
refId: '',
},
onRunQuery: () => {},
onChange: () => {},
history: [],
};
describe('PromQueryField', () => {
beforeAll(() => {
// @ts-ignore
window.getSelection = () => {};
});
it('renders metrics chooser regularly if lookups are not disabled in the datasource settings', async () => {
const queryField = render(<PromQueryField {...defaultProps} />);
// wait for component to render
await screen.findByRole('button');
expect(queryField.getAllByRole('button')).toHaveLength(1);
});
it('renders a disabled metrics chooser if lookups are disabled in datasource settings', async () => {
const props = defaultProps;
props.datasource.lookupsDisabled = true;
const queryField = render(<PromQueryField {...props} />);
// wait for component to render
await screen.findByRole('button');
const bcButton = queryField.getByRole('button');
expect(bcButton).toBeDisabled();
});
it('renders an initial hint if no data and initial hint provided', async () => {
const props = defaultProps;
props.datasource.lookupsDisabled = true;
props.datasource.getInitHints = () => [{ label: 'Initial hint', type: 'INFO' }];
render(<PromQueryField {...props} />);
// wait for component to render
await screen.findByRole('button');
expect(screen.getByText('Initial hint')).toBeInTheDocument();
});
it('renders query hint if data, query hint and initial hint provided', async () => {
const props = defaultProps;
props.datasource.lookupsDisabled = true;
props.datasource.getInitHints = () => [{ label: 'Initial hint', type: 'INFO' }];
props.datasource.getQueryHints = () => [{ label: 'Query hint', type: 'INFO' }];
render(
<PromQueryField
{...props}
data={
{
series: [{ name: 'test name' }] as DataFrame[],
state: LoadingState.Done,
} as PanelData
}
/>
);
// wait for component to render
await screen.findByRole('button');
expect(screen.getByText('Query hint')).toBeInTheDocument();
expect(screen.queryByText('Initial hint')).not.toBeInTheDocument();
});
it('refreshes metrics when the data source changes', async () => {
const defaultProps = {
query: { expr: '', refId: '' },
onRunQuery: () => {},
onChange: () => {},
history: [],
};
const metrics = ['foo', 'bar'];
const queryField = render(
<PromQueryField
datasource={
{
languageProvider: makeLanguageProvider({ metrics: [metrics] }),
getInitHints: () => [],
} as unknown as PrometheusDatasource
}
{...defaultProps}
/>
);
// wait for component to render
await screen.findByRole('button');
const changedMetrics = ['baz', 'moo'];
queryField.rerender(
<PromQueryField
// @ts-ignore
datasource={{
languageProvider: makeLanguageProvider({ metrics: [changedMetrics] }),
}}
{...defaultProps}
/>
);
// If we check the label browser right away it should be in loading state
let labelBrowser = screen.getByRole('button');
expect(labelBrowser).toHaveTextContent('Loading');
// wait for component to rerender
labelBrowser = await screen.findByRole('button');
await waitFor(() => {
expect(labelBrowser).toHaveTextContent('Metrics browser');
});
});
it('should not run query onBlur', async () => {
const onRunQuery = jest.fn();
const { container } = render(<PromQueryField {...defaultProps} app={CoreApp.Explore} onRunQuery={onRunQuery} />);
// wait for component to rerender
await screen.findByRole('button');
const input = getByTestId(container, 'dummy-code-input');
expect(input).toBeInTheDocument();
await userEvent.type(input, 'metric');
// blur element
await userEvent.click(document.body);
expect(onRunQuery).not.toHaveBeenCalled();
});
});
function makeLanguageProvider(options: { metrics: string[][] }) {
const metricsStack = [...options.metrics];
return {
histogramMetrics: [],
metrics: [],
metricsMetadata: {},
lookupsDisabled: false,
getLabelKeys: () => [],
start() {
this.metrics = metricsStack.shift();
return Promise.resolve([]);
},
} as any as PromQlLanguageProvider;
}