Skip to content

Commit

Permalink
Add integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
adamyeats committed Mar 22, 2024
1 parent 9b172af commit 3d210b2
Show file tree
Hide file tree
Showing 3 changed files with 268 additions and 35 deletions.
267 changes: 267 additions & 0 deletions e2e/datasource/datasource_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
package integration_test

import (
"context"
"encoding/json"
"os"
"testing"

"github.com/grafana-labs/surrealdb-datasource/pkg/client"
"github.com/grafana-labs/surrealdb-datasource/pkg/plugin"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
)

// table is a list of test cases for the QueryData method.
var cases = []struct {
input string
name string
}{
{
input: "SELECT * FROM person WHERE name = 'Richie Buck';",
name: "SELECT query with WHERE clause",
},
{
input: "SELECT id, name FROM person;",
name: "SELECT specific columns",
},
{
input: "SELECT count() FROM person GROUP all;",
name: "Aggregate function",
},
{
input: "SELECT * FROM person ORDER BY name DESC;",
name: "SELECT query with ORDER BY clause",
},
{
input: "SELECT * FROM person WHERE first_name ~ 'rich';",
name: "SELECT with fuzzy equality",
},
{
input: "SELECT * FROM person WHERE company_name == NONE;",
name: "SELECT with IS NONE",
},
{
input: "SELECT * FROM person WHERE company_name != NONE;",
name: "SELECT with IS NOT NONE",
},
{
input: "SELECT * FROM person LIMIT 10;",
name: "SELECT with LIMIT",
},
{
input: "SELECT product.name FROM review;",
name: "SELECT with Record links",
},
}

// getSurrealEndpoint returns the endpoint for the SurrealDB server.
func getSurrealEndpoint() string {
env := os.Getenv("SURREAL_DB_URL")

if env != "" {
return env
}

if os.Getenv("CI") != "true" {
return "ws://localhost:8000/rpc"
}

return "ws://surrealdb:8000/rpc"
}

func createTestInstance() (instancemgmt.Instance, error) {
config := client.SurrealConfig{
Database: "test",
Endpoint: getSurrealEndpoint(),
Namespace: "test",
Username: "root",
}

msg, err := json.Marshal(config)

if err != nil {
return nil, err
}

dsiConfig := backend.DataSourceInstanceSettings{
JSONData: msg,
DecryptedSecureJSONData: map[string]string{"password": "test"},
}

return plugin.NewDatasource(context.Background(), dsiConfig)
}

func TestNewDatasource(t *testing.T) {
instance, err := createTestInstance()

if err != nil {
t.Errorf("unexpected error: %s", err)
}

if instance == nil {
t.Error("expected instance to be non-nil")
}

if _, ok := instance.(*plugin.SurrealDatasource); ok {
t.Error("expected instance to be the correct type")
}
}

func TestCheckHealth(t *testing.T) {
instance, err := createTestInstance()

if err != nil {
t.Errorf("unexpected error: %s", err)
}

(*instance.(*plugin.SurrealDatasource)).CheckHealth(context.Background(), &backend.CheckHealthRequest{})

if err != nil {
t.Errorf("unexpected error: %s", err)
}

if instance == nil {
t.Error("expected instance to be non-nil")
}

if _, ok := instance.(plugin.SurrealDatasource); ok {
t.Error("expected instance to be the correct type")
}
}

func TestQueryData_Success(t *testing.T) {
instance, err := createTestInstance()

if err != nil {
t.Errorf("unexpected error: %s", err)
}

if _, ok := instance.(plugin.SurrealDatasource); ok {
t.Error("expected instance to be the correct type")
}

for _, tt := range cases {
t.Run(tt.name, func(t *testing.T) {
dqs := []backend.DataQuery{
{
RefID: "A",
JSON: json.RawMessage(`{"queryText":"` + tt.input + `"}`),
},
}

req := backend.QueryDataRequest{
PluginContext: backend.PluginContext{
OrgID: 1,
},
Queries: dqs,
}

res, err := (*instance.(*plugin.SurrealDatasource)).QueryData(context.Background(), &req)

if err != nil {
t.Errorf("unexpected error: %s", err)
}

if res == nil {
t.Error("expected response to be non-nil")
} else {
if len(res.Responses) != 1 {
t.Errorf("expected 1 response, got %d", len(res.Responses))
}

if res.Responses["A"].Frames == nil {
t.Error("expected frames to be non-nil")
}

if res.Responses["A"].Frames[0].Fields == nil {
t.Error("expected fields to be non-nil")
}
}
})
}
}

func TestQueryData_BadTableName(t *testing.T) {
instance, err := createTestInstance()

if err != nil {
t.Errorf("unexpected error: %s", err)
}

if _, ok := instance.(plugin.SurrealDatasource); ok {
t.Error("expected instance to be the correct type")
}

dqs := []backend.DataQuery{
{
RefID: "A",
JSON: json.RawMessage(`{"queryText":"` + "SELECT * FROM doesnt_exist;" + `"}`),
},
}

req := backend.QueryDataRequest{
PluginContext: backend.PluginContext{
OrgID: 1,
},
Queries: dqs,
}

res, err := (*instance.(*plugin.SurrealDatasource)).QueryData(context.Background(), &req)

if err != nil {
t.Errorf("unexpected error: %s", err)
} else {
if len(res.Responses) != 1 {
t.Errorf("expected 1 response, got %d", len(res.Responses))
}

if res.Responses["A"].Frames != nil {
t.Error("expected frames to be nil")
}
}
}

func TestQueryData_BadQuerySyntax(t *testing.T) {
instance, err := createTestInstance()

if err != nil {
t.Errorf("unexpected error: %s", err)
}

if _, ok := instance.(plugin.SurrealDatasource); ok {
t.Error("expected instance to be the correct type")
}

dqs := []backend.DataQuery{
{
RefID: "A",
JSON: json.RawMessage(`{"queryText":"` + "SELECT * FROM person JOIN address ON person.id = address.person_id;" + `"}`),
},
}

req := backend.QueryDataRequest{
PluginContext: backend.PluginContext{
OrgID: 1,
},
Queries: dqs,
}

res, err := (*instance.(*plugin.SurrealDatasource)).QueryData(context.Background(), &req)

if err != nil {
t.Errorf("unexpected error: %s", err)
} else {
if len(res.Responses) != 1 {
t.Errorf("expected 1 response, got %d", len(res.Responses))
}

if res.Responses["A"].Frames != nil {
t.Error("expected frames to be nil")
}

if res.Responses["A"].Error == nil {
t.Error("expected error to be non-nil")
}
}
}
4 changes: 1 addition & 3 deletions pkg/plugin/datasource.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,7 @@ func NewDatasource(ctx context.Context, dsiConfig backend.DataSourceInstanceSett
return NewDatasourceInstance(db, &config), nil
}

// Dispose here tells plugin SDK that plugin wants to clean up resources when a new instance
// created. As soon as datasource settings change detected by SDK old datasource instance will
// be disposed and a new one will be created using NewSampleDatasource factory function.
// Dispose cleans up the datasource instance resources.
func (d *SurrealDatasource) Dispose() {
// Clean up datasource instance resources.
// d.db.Close()
Expand Down
32 changes: 0 additions & 32 deletions pkg/plugin/datasource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,6 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
)

// IMPORTANT!
//
// As it stands, this test suite requires a running instance of SurrealDB. You
// can start one by bringing up the Docker containers with the following command:
//
// `docker-compose up -d`
//
// What can be tested in isolation at the moment, is being tested in isolation.

var mock = mocks.MockSurrealDBClient{}

var config = client.SurrealConfig{
Expand All @@ -30,29 +21,6 @@ var config = client.SurrealConfig{
Username: "grafana",
}

// @TODO: Move this test to an integration test suite.
// func TestNewDatasource_Success(t *testing.T) {
// msg, err := json.Marshal(config)

// if err != nil {
// t.Errorf("unexpected error: %s", err)
// }

// config := backend.DataSourceInstanceSettings{
// JSONData: msg,
// DecryptedSecureJSONData: map[string]string{"password": "password"},
// }

// instance, err := plugin.NewDatasource(context.Background(), config)

// if err != nil {
// t.Errorf("unexpected error: %s", err)
// }
// if instance == nil {
// t.Error("expected instance to be non-nil")
// }
// }

func TestNewDatasource_InvalidJSON(t *testing.T) {
config := backend.DataSourceInstanceSettings{
JSONData: json.RawMessage(`invalid json`),
Expand Down

0 comments on commit 3d210b2

Please sign in to comment.