Skip to content

Commit 6ffd631

Browse files
committed
button tests
1 parent f653510 commit 6ffd631

File tree

4 files changed

+304
-188
lines changed

4 files changed

+304
-188
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"@grafana/runtime": "next",
2121
"@grafana/toolkit": "next",
2222
"@grafana/ui": "next",
23+
"@types/enzyme": "^3.10.5",
2324
"emotion": "10.0.27",
2425
"enzyme": "^3.11.0",
2526
"enzyme-adapter-react-16": "1.15.2"

src/buttonPanel.test.tsx

Lines changed: 96 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,26 @@
11
import {
2+
AppEvents,
23
DefaultTimeRange,
34
DefaultTimeZone,
45
LoadingState,
56
PanelProps,
67
} from '@grafana/data';
7-
import { mount } from 'enzyme';
8+
import { getBackendSrv, getDataSourceSrv, SystemJS } from '@grafana/runtime';
9+
import { Button, HorizontalGroup, VerticalGroup } from '@grafana/ui';
10+
import { shallow } from 'enzyme';
811
import React from 'react';
9-
import { Options } from 'types';
12+
import { ButtonOptions, Options } from 'types';
1013
import { ButtonPanel } from './buttonPanel';
14+
jest.mock('@grafana/runtime');
1115

1216
describe('button panel', () => {
13-
test('panel', () => {
14-
let props: PanelProps<Options> = {
17+
const status = 200;
18+
const statusError = 500;
19+
const statusText = 'OKI';
20+
let defaultProps: PanelProps<Options>;
21+
22+
beforeEach(() => {
23+
defaultProps = {
1524
id: 1,
1625
data: {
1726
timeRange: DefaultTimeRange,
@@ -34,7 +43,89 @@ describe('button panel', () => {
3443
orientation: 'horizontal',
3544
} as Options,
3645
};
46+
});
47+
48+
test('orientation', () => {
49+
let wrapper = shallow(<ButtonPanel {...defaultProps} />);
50+
expect(wrapper.find(HorizontalGroup)).toHaveLength(1);
51+
expect(wrapper.find(VerticalGroup)).toHaveLength(0);
52+
wrapper.setProps({ options: { buttons: [], orientation: 'vertical' } });
53+
expect(wrapper.find(HorizontalGroup)).toHaveLength(0);
54+
expect(wrapper.find(VerticalGroup)).toHaveLength(1);
55+
});
56+
57+
test('buttons', () => {
58+
const wrapper = shallow(<ButtonPanel {...defaultProps} />);
59+
expect(wrapper.find(Button)).toHaveLength(0);
60+
61+
const buttons: ButtonOptions[] = [
62+
{ text: 'a', variant: 'destructive', datasource: 'a' },
63+
{ text: 'b', variant: 'primary', datasource: 'b' },
64+
];
65+
wrapper.setProps({ options: { buttons: buttons } });
66+
67+
const mockGet = jest.fn().mockReturnValue({ id: 1 });
68+
getDataSourceSrv.mockImplementation(() => ({ get: mockGet }));
69+
const mockDataSourceRequest = jest.fn().mockReturnValue({
70+
status: status,
71+
statusText: statusText,
72+
});
73+
getBackendSrv.mockImplementation(() => ({
74+
datasourceRequest: mockDataSourceRequest,
75+
}));
76+
const mockEmit = jest.fn();
77+
SystemJS.load.mockImplementation(async () => ({
78+
emit: mockEmit,
79+
}));
80+
81+
const buttonWidgets = wrapper.find(Button);
82+
expect(buttonWidgets).toHaveLength(buttons.length);
83+
buttonWidgets.forEach((b: any, i: number) => {
84+
expect(b.key()).toBe(i.toString());
85+
expect(b.prop('variant')).toBe(buttons[i].variant);
86+
expect(b.text()).toBe(buttons[i].text);
87+
b.simulate('click');
88+
setImmediate(() => {
89+
expect(mockGet).toHaveBeenCalledWith(buttons[i].datasource);
90+
expect(mockDataSourceRequest).toHaveBeenCalled();
91+
expect(mockEmit).toHaveBeenCalledWith(AppEvents.alertSuccess, [
92+
buttons[i].text + ': ' + status + ' (' + statusText + ')',
93+
]);
94+
});
95+
});
96+
});
97+
98+
test('button error', () => {
99+
const wrapper = shallow(<ButtonPanel {...defaultProps} />);
100+
const buttons: ButtonOptions[] = [
101+
{ variant: 'destructive', datasource: 'a' },
102+
];
103+
wrapper.setProps({ options: { buttons: buttons } });
104+
105+
const mockGet = jest.fn().mockReturnValue({ id: 1 });
106+
getDataSourceSrv.mockImplementation(() => ({ get: mockGet }));
107+
const msg = 'msg';
108+
const mockDataSourceRequest = jest.fn().mockRejectedValue({
109+
status: statusError,
110+
statusText: statusText,
111+
data: { message: msg },
112+
});
113+
getBackendSrv.mockImplementation(() => ({
114+
datasourceRequest: mockDataSourceRequest,
115+
}));
116+
const mockEmit = jest.fn();
117+
SystemJS.load.mockImplementation(async () => ({
118+
emit: mockEmit,
119+
}));
37120

38-
mount(<ButtonPanel {...props} />);
121+
const widget = wrapper.find(Button);
122+
expect(widget.text()).toBe('Button');
123+
widget.simulate('click');
124+
setImmediate(() => {
125+
expect(mockEmit).toHaveBeenCalledWith(AppEvents.alertError, [
126+
widget.text() + ': ' + statusError + ' (' + statusText + ')',
127+
msg,
128+
]);
129+
});
39130
});
40131
});

src/buttonPanel.tsx

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,45 +8,46 @@ interface Props extends PanelProps<Options> {}
88

99
export const ButtonPanel: React.FC<Props> = ({ options }) => {
1010
const renderButtons = (buttons: ButtonOptions[]) => {
11-
return buttons.map((b: ButtonOptions, index: number) => (
12-
<Button
13-
key={index}
14-
variant={b.variant}
15-
onClick={async () => {
16-
const payload = JSON.parse(b.query || '');
17-
const ds = await getDataSourceSrv().get(b.datasource);
18-
try {
19-
const resp = await getBackendSrv().datasourceRequest({
20-
method: 'POST',
21-
url: 'api/tsdb/query',
22-
data: {
23-
queries: [
24-
{
25-
datasourceId: ds.id,
26-
refId: '1',
27-
...payload,
28-
},
29-
],
30-
},
31-
});
32-
SystemJS.load('app/core/app_events').then((appEvents: any) => {
33-
appEvents.emit(AppEvents.alertSuccess, [
34-
b.text + ': ' + resp.status + ' (' + resp.statusText + ')',
11+
return buttons.map((b: ButtonOptions, index: number) => {
12+
const text = b.text || 'Button';
13+
return (
14+
<Button
15+
key={index}
16+
variant={b.variant}
17+
onClick={async () => {
18+
const payload = JSON.parse(b.query || '{}');
19+
const ds = await getDataSourceSrv().get(b.datasource);
20+
try {
21+
const resp = await getBackendSrv().datasourceRequest({
22+
method: 'POST',
23+
url: 'api/tsdb/query',
24+
data: {
25+
queries: [
26+
{
27+
datasourceId: ds.id,
28+
refId: '1',
29+
...payload,
30+
},
31+
],
32+
},
33+
});
34+
const events = await SystemJS.load('app/core/app_events');
35+
events.emit(AppEvents.alertSuccess, [
36+
text + ': ' + resp.status + ' (' + resp.statusText + ')',
3537
]);
36-
});
37-
} catch (error) {
38-
SystemJS.load('app/core/app_events').then((appEvents: any) => {
39-
appEvents.emit(AppEvents.alertError, [
40-
b.text + ': ' + error.status + ' (' + error.statusText + ')',
38+
} catch (error) {
39+
const events = await SystemJS.load('app/core/app_events');
40+
events.emit(AppEvents.alertError, [
41+
text + ': ' + error.status + ' (' + error.statusText + ')',
4142
error.data.message,
4243
]);
43-
});
44-
}
45-
}}
46-
>
47-
{b.text || 'Button'}
48-
</Button>
49-
));
44+
}
45+
}}
46+
>
47+
{text}
48+
</Button>
49+
);
50+
});
5051
};
5152

5253
return (

0 commit comments

Comments
 (0)