Skip to content

Commit 0dc2db7

Browse files
committed
Add tests
1 parent 6c08e44 commit 0dc2db7

File tree

5 files changed

+150
-8
lines changed

5 files changed

+150
-8
lines changed

grafana/fire-datasource/pkg/plugin/plugin_test.go

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
1-
package plugin_test
1+
package plugin
22

33
import (
44
"context"
55
"testing"
66

77
"github.com/grafana/grafana-plugin-sdk-go/backend"
8-
9-
"github.com/grafana/fire/grafana/fire-datasource/pkg/plugin"
8+
"github.com/stretchr/testify/require"
109
)
1110

1211
// This is where the tests for the datasource backend live.
13-
func TestQueryData(t *testing.T) {
14-
ds := plugin.FireDatasource{}
12+
func Test_QueryData(t *testing.T) {
13+
ds := FireDatasource{}
1514

1615
resp, err := ds.QueryData(
1716
context.Background(),
@@ -29,3 +28,37 @@ func TestQueryData(t *testing.T) {
2928
t.Fatal("QueryData must return a response")
3029
}
3130
}
31+
32+
func Test_CallResource(t *testing.T) {
33+
ds := &FireDatasource{
34+
client: &FakeClient{},
35+
}
36+
37+
t.Run("series resource", func(t *testing.T) {
38+
sender := &FakeSender{}
39+
err := ds.CallResource(
40+
context.Background(),
41+
&backend.CallResourceRequest{
42+
PluginContext: backend.PluginContext{},
43+
Path: "series",
44+
Method: "GET",
45+
URL: "series?matchers=%7B%7D",
46+
Headers: nil,
47+
Body: nil,
48+
},
49+
sender,
50+
)
51+
require.NoError(t, err)
52+
require.Equal(t, 200, sender.Resp.Status)
53+
require.Equal(t, `[{"labels":[{"name":"instance","value":"127.0.0.1"},{"name":"job","value":"default"}]}]`, string(sender.Resp.Body))
54+
})
55+
}
56+
57+
type FakeSender struct {
58+
Resp *backend.CallResourceResponse
59+
}
60+
61+
func (fs *FakeSender) Send(resp *backend.CallResourceResponse) error {
62+
fs.Resp = resp
63+
return nil
64+
}

grafana/fire-datasource/pkg/plugin/query_test.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"time"
77

88
"github.com/bufbuild/connect-go"
9+
v1 "github.com/grafana/fire/pkg/gen/common/v1"
910
querierv1 "github.com/grafana/fire/pkg/gen/querier/v1"
1011
"github.com/grafana/grafana-plugin-sdk-go/backend"
1112
"github.com/grafana/grafana-plugin-sdk-go/data"
@@ -73,7 +74,26 @@ func (f FakeClient) LabelValues(ctx context.Context, c *connect.Request[querierv
7374
}
7475

7576
func (f FakeClient) Series(ctx context.Context, c *connect.Request[querierv1.SeriesRequest]) (*connect.Response[querierv1.SeriesResponse], error) {
76-
panic("implement me")
77+
return &connect.Response[querierv1.SeriesResponse]{
78+
Msg: &querierv1.SeriesResponse{
79+
LabelsSet: []*v1.Labels{{
80+
Labels: []*v1.LabelPair{
81+
{
82+
Name: "__unit__",
83+
Value: "cpu",
84+
},
85+
{
86+
Name: "instance",
87+
Value: "127.0.0.1",
88+
},
89+
{
90+
Name: "job",
91+
Value: "default",
92+
},
93+
},
94+
}},
95+
},
96+
}, nil
7797
}
7898

7999
func (f FakeClient) SelectMergeStacktraces(ctx context.Context, c *connect.Request[querierv1.SelectMergeStacktracesRequest]) (*connect.Response[querierv1.SelectMergeStacktracesResponse], error) {

grafana/fire-datasource/src/QueryEditor/LabelsEditor.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { useAsync } from 'react-use';
77

88
import { languageDefinition } from '../fireql';
99
import { FireDataSource } from '../datasource';
10-
import { CompletionProvider } from './autocompletition';
10+
import { CompletionProvider } from './autocomplete';
1111

1212
interface Props {
1313
value: string;
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { CompletionProvider } from './autocomplete';
2+
import { SeriesMessage } from '../types';
3+
import { monacoTypes } from '@grafana/ui';
4+
5+
describe('CompletionProvider', () => {
6+
it('suggests labels', () => {
7+
const { provider, model } = setup('{}', 1, defaultLabels);
8+
const result = provider.provideCompletionItems(model as any, {} as any);
9+
expect((result! as monacoTypes.languages.CompletionList).suggestions).toEqual([
10+
expect.objectContaining({ label: 'foo', insertText: 'foo' }),
11+
]);
12+
});
13+
14+
it('suggests label names with quotes', () => {
15+
const { provider, model } = setup('{foo=}', 6, defaultLabels);
16+
const result = provider.provideCompletionItems(model as any, {} as any);
17+
expect((result! as monacoTypes.languages.CompletionList).suggestions).toEqual([
18+
expect.objectContaining({ label: 'bar', insertText: '"bar"' }),
19+
]);
20+
});
21+
22+
it('suggests label names without quotes', () => {
23+
const { provider, model } = setup('{foo="}', 7, defaultLabels);
24+
const result = provider.provideCompletionItems(model as any, {} as any);
25+
expect((result! as monacoTypes.languages.CompletionList).suggestions).toEqual([
26+
expect.objectContaining({ label: 'bar', insertText: 'bar' }),
27+
]);
28+
});
29+
30+
it('suggests nothing without labels', () => {
31+
const { provider, model } = setup('{foo="}', 7, []);
32+
const result = provider.provideCompletionItems(model as any, {} as any);
33+
expect((result! as monacoTypes.languages.CompletionList).suggestions).toEqual([]);
34+
});
35+
36+
it('suggests labels on empty input', () => {
37+
const { provider, model } = setup('', 0, defaultLabels);
38+
const result = provider.provideCompletionItems(model as any, {} as any);
39+
expect((result! as monacoTypes.languages.CompletionList).suggestions).toEqual([
40+
expect.objectContaining({ label: 'foo', insertText: '{foo="' }),
41+
]);
42+
});
43+
});
44+
45+
const defaultLabels = [{ labels: [{ name: 'foo', value: 'bar' }] }];
46+
47+
function setup(value: string, offset: number, series?: SeriesMessage) {
48+
const provider = new CompletionProvider();
49+
if (series) {
50+
provider.setSeries(series);
51+
}
52+
const model = makeModel(value, offset);
53+
provider.monaco = {
54+
Range: {
55+
fromPositions() {
56+
return null;
57+
},
58+
},
59+
languages: {
60+
CompletionItemKind: {
61+
Enum: 1,
62+
EnumMember: 2,
63+
},
64+
},
65+
} as any;
66+
provider.editor = {
67+
getModel() {
68+
return model;
69+
},
70+
} as any;
71+
72+
return { provider, model };
73+
}
74+
75+
function makeModel(value: string, offset: number) {
76+
return {
77+
id: 'test_monaco',
78+
getWordAtPosition() {
79+
return null;
80+
},
81+
getOffsetAt() {
82+
return offset;
83+
},
84+
getValue() {
85+
return value;
86+
},
87+
};
88+
}

grafana/fire-datasource/src/QueryEditor/autocompletition.tsx renamed to grafana/fire-datasource/src/QueryEditor/autocomplete.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import type { Monaco, monacoTypes } from '@grafana/ui';
1+
import type { Monaco } from '@grafana/ui';
2+
import { monacoTypes } from '@grafana/ui';
23
import { SeriesMessage } from '../types';
34

45
/**

0 commit comments

Comments
 (0)