2020-12-09 06:10:18 -06:00
package librarypanels
import (
2021-02-01 23:25:35 -06:00
"context"
2020-12-21 02:40:27 -06:00
"encoding/json"
2021-01-20 02:28:10 -06:00
"fmt"
2020-12-09 06:10:18 -06:00
"testing"
"time"
2020-12-23 05:42:52 -06:00
"github.com/google/go-cmp/cmp"
2020-12-09 06:10:18 -06:00
"github.com/stretchr/testify/require"
2021-02-01 23:25:35 -06:00
"github.com/grafana/grafana/pkg/components/simplejson"
2021-03-17 10:06:10 -05:00
dboards "github.com/grafana/grafana/pkg/dashboards"
2020-12-09 06:10:18 -06:00
"github.com/grafana/grafana/pkg/models"
2021-02-24 07:06:22 -06:00
"github.com/grafana/grafana/pkg/services/dashboards"
2021-05-11 00:10:19 -05:00
"github.com/grafana/grafana/pkg/services/libraryelements"
2020-12-09 06:10:18 -06:00
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/setting"
)
2021-09-20 03:58:24 -05:00
const userInDbName = "user_in_db"
const userInDbAvatar = "/avatar/402d08de060496d6b6874495fe20f5ad"
2020-12-23 05:42:52 -06:00
2021-01-20 02:28:10 -06:00
func TestLoadLibraryPanelsForDashboard ( t * testing . T ) {
2021-09-20 03:58:24 -05:00
scenarioWithLibraryPanel ( t , "When an admin tries to load a dashboard with a library panel, it should copy JSON properties from library panel." ,
2021-01-20 02:28:10 -06:00
func ( t * testing . T , sc scenarioContext ) {
dashJSON := map [ string ] interface { } {
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 1 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 0 ,
} ,
} ,
map [ string ] interface { } {
"id" : int64 ( 2 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 6 ,
"y" : 0 ,
} ,
"libraryPanel" : map [ string ] interface { } {
2021-02-24 07:06:22 -06:00
"uid" : sc . initialResult . Result . UID ,
"name" : sc . initialResult . Result . Name ,
2021-01-20 02:28:10 -06:00
} ,
} ,
} ,
}
dash := models . Dashboard {
2021-05-11 00:10:19 -05:00
Title : "Testing LoadLibraryPanelsForDashboard" ,
Data : simplejson . NewFromAny ( dashJSON ) ,
2021-01-20 02:28:10 -06:00
}
2021-05-11 00:10:19 -05:00
dashInDB := createDashboard ( t , sc . sqlStore , sc . user , & dash , sc . folder . Id )
2021-09-27 02:04:36 -05:00
err := sc . elementService . ConnectElementsToDashboard ( sc . ctx , sc . user , [ ] string { sc . initialResult . Result . UID } , dashInDB . Id )
2021-05-11 00:10:19 -05:00
require . NoError ( t , err )
2021-01-20 02:28:10 -06:00
2021-09-27 02:04:36 -05:00
err = sc . service . LoadLibraryPanelsForDashboard ( sc . ctx , dashInDB )
2021-01-20 02:28:10 -06:00
require . NoError ( t , err )
expectedJSON := map [ string ] interface { } {
2021-05-11 00:10:19 -05:00
"title" : "Testing LoadLibraryPanelsForDashboard" ,
"uid" : dashInDB . Uid ,
"version" : dashInDB . Version ,
2021-01-20 02:28:10 -06:00
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 1 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 0 ,
} ,
} ,
map [ string ] interface { } {
"id" : int64 ( 2 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 6 ,
"y" : 0 ,
} ,
2021-03-24 07:43:51 -05:00
"datasource" : "${DS_GDEV-TESTDATA}" ,
"description" : "A description" ,
2021-01-20 02:28:10 -06:00
"libraryPanel" : map [ string ] interface { } {
2021-03-24 07:43:51 -05:00
"uid" : sc . initialResult . Result . UID ,
"name" : sc . initialResult . Result . Name ,
"type" : sc . initialResult . Result . Type ,
"description" : sc . initialResult . Result . Description ,
"version" : sc . initialResult . Result . Version ,
2021-02-01 23:25:35 -06:00
"meta" : map [ string ] interface { } {
2021-05-05 04:09:12 -05:00
"folderName" : "ScenarioFolder" ,
"folderUid" : sc . folder . Uid ,
2021-02-01 23:25:35 -06:00
"connectedDashboards" : int64 ( 1 ) ,
2021-02-24 07:06:22 -06:00
"created" : sc . initialResult . Result . Meta . Created ,
"updated" : sc . initialResult . Result . Meta . Updated ,
2021-02-01 23:25:35 -06:00
"createdBy" : map [ string ] interface { } {
2021-02-24 07:06:22 -06:00
"id" : sc . initialResult . Result . Meta . CreatedBy . ID ,
2021-09-20 03:58:24 -05:00
"name" : userInDbName ,
"avatarUrl" : userInDbAvatar ,
2021-02-01 23:25:35 -06:00
} ,
"updatedBy" : map [ string ] interface { } {
2021-02-24 07:06:22 -06:00
"id" : sc . initialResult . Result . Meta . UpdatedBy . ID ,
2021-09-20 03:58:24 -05:00
"name" : userInDbName ,
"avatarUrl" : userInDbAvatar ,
2021-02-01 23:25:35 -06:00
} ,
} ,
2021-01-20 02:28:10 -06:00
} ,
2021-02-24 07:06:22 -06:00
"title" : "Text - Library Panel" ,
2021-01-20 02:28:10 -06:00
"type" : "text" ,
} ,
} ,
}
expected := simplejson . NewFromAny ( expectedJSON )
if diff := cmp . Diff ( expected . Interface ( ) , dash . Data . Interface ( ) , getCompareOptions ( ) ... ) ; diff != "" {
t . Fatalf ( "Result mismatch (-want +got):\n%s" , diff )
}
} )
2021-09-08 03:53:55 -05:00
scenarioWithLibraryPanel ( t , "When an admin tries to load a dashboard with library panels inside and outside of rows, it should copy JSON properties from library panels" ,
func ( t * testing . T , sc scenarioContext ) {
cmd := libraryelements . CreateLibraryElementCommand {
FolderID : sc . initialResult . Result . FolderID ,
Name : "Outside row" ,
Model : [ ] byte ( `
{
"datasource" : "${DS_GDEV-TESTDATA}" ,
"id" : 1 ,
"title" : "Text - Library Panel" ,
"type" : "text" ,
"description" : "A description"
}
` ) ,
Kind : int64 ( models . PanelElement ) ,
}
2021-09-27 02:04:36 -05:00
outsidePanel , err := sc . elementService . CreateElement ( sc . ctx , sc . user , cmd )
2021-09-08 03:53:55 -05:00
require . NoError ( t , err )
dashJSON := map [ string ] interface { } {
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 1 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 0 ,
} ,
} ,
map [ string ] interface { } {
"collapsed" : true ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 6 ,
} ,
"id" : int64 ( 2 ) ,
"type" : "row" ,
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 3 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 7 ,
} ,
} ,
map [ string ] interface { } {
"id" : int64 ( 4 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 6 ,
"y" : 13 ,
} ,
"datasource" : "${DS_GDEV-TESTDATA}" ,
"libraryPanel" : map [ string ] interface { } {
"uid" : sc . initialResult . Result . UID ,
"name" : sc . initialResult . Result . Name ,
} ,
"title" : "Inside row" ,
"type" : "text" ,
} ,
} ,
} ,
map [ string ] interface { } {
"id" : int64 ( 5 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 19 ,
} ,
"datasource" : "${DS_GDEV-TESTDATA}" ,
"libraryPanel" : map [ string ] interface { } {
"uid" : outsidePanel . UID ,
"name" : outsidePanel . Name ,
} ,
"title" : "Outside row" ,
"type" : "text" ,
} ,
} ,
}
dash := models . Dashboard {
Title : "Testing LoadLibraryPanelsForDashboard" ,
Data : simplejson . NewFromAny ( dashJSON ) ,
}
dashInDB := createDashboard ( t , sc . sqlStore , sc . user , & dash , sc . folder . Id )
2021-09-27 02:04:36 -05:00
err = sc . elementService . ConnectElementsToDashboard ( sc . ctx , sc . user , [ ] string { outsidePanel . UID , sc . initialResult . Result . UID } , dashInDB . Id )
2021-09-08 03:53:55 -05:00
require . NoError ( t , err )
2021-09-27 02:04:36 -05:00
err = sc . service . LoadLibraryPanelsForDashboard ( sc . ctx , dashInDB )
2021-09-08 03:53:55 -05:00
require . NoError ( t , err )
expectedJSON := map [ string ] interface { } {
"title" : "Testing LoadLibraryPanelsForDashboard" ,
"uid" : dashInDB . Uid ,
"version" : dashInDB . Version ,
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 1 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 0 ,
} ,
} ,
map [ string ] interface { } {
"collapsed" : true ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 6 ,
} ,
"id" : int64 ( 2 ) ,
"type" : "row" ,
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 3 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 7 ,
} ,
} ,
map [ string ] interface { } {
"id" : int64 ( 4 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 6 ,
"y" : 13 ,
} ,
"datasource" : "${DS_GDEV-TESTDATA}" ,
"description" : "A description" ,
"libraryPanel" : map [ string ] interface { } {
"uid" : sc . initialResult . Result . UID ,
"name" : sc . initialResult . Result . Name ,
"type" : sc . initialResult . Result . Type ,
"description" : sc . initialResult . Result . Description ,
"version" : sc . initialResult . Result . Version ,
"meta" : map [ string ] interface { } {
"folderName" : "ScenarioFolder" ,
"folderUid" : sc . folder . Uid ,
"connectedDashboards" : int64 ( 1 ) ,
"created" : sc . initialResult . Result . Meta . Created ,
"updated" : sc . initialResult . Result . Meta . Updated ,
"createdBy" : map [ string ] interface { } {
"id" : sc . initialResult . Result . Meta . CreatedBy . ID ,
2021-09-20 03:58:24 -05:00
"name" : userInDbName ,
"avatarUrl" : userInDbAvatar ,
2021-09-08 03:53:55 -05:00
} ,
"updatedBy" : map [ string ] interface { } {
"id" : sc . initialResult . Result . Meta . UpdatedBy . ID ,
2021-09-20 03:58:24 -05:00
"name" : userInDbName ,
"avatarUrl" : userInDbAvatar ,
2021-09-08 03:53:55 -05:00
} ,
} ,
} ,
"title" : "Text - Library Panel" ,
"type" : "text" ,
} ,
} ,
} ,
map [ string ] interface { } {
"id" : int64 ( 5 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 19 ,
} ,
"datasource" : "${DS_GDEV-TESTDATA}" ,
"description" : "A description" ,
"libraryPanel" : map [ string ] interface { } {
"uid" : outsidePanel . UID ,
"name" : outsidePanel . Name ,
"type" : outsidePanel . Type ,
"description" : outsidePanel . Description ,
"version" : outsidePanel . Version ,
"meta" : map [ string ] interface { } {
"folderName" : "ScenarioFolder" ,
"folderUid" : sc . folder . Uid ,
"connectedDashboards" : int64 ( 1 ) ,
"created" : outsidePanel . Meta . Created ,
"updated" : outsidePanel . Meta . Updated ,
"createdBy" : map [ string ] interface { } {
"id" : outsidePanel . Meta . CreatedBy . ID ,
2021-09-20 03:58:24 -05:00
"name" : userInDbName ,
"avatarUrl" : userInDbAvatar ,
2021-09-08 03:53:55 -05:00
} ,
"updatedBy" : map [ string ] interface { } {
"id" : outsidePanel . Meta . UpdatedBy . ID ,
2021-09-20 03:58:24 -05:00
"name" : userInDbName ,
"avatarUrl" : userInDbAvatar ,
2021-09-08 03:53:55 -05:00
} ,
} ,
} ,
"title" : "Text - Library Panel" ,
"type" : "text" ,
} ,
} ,
}
expected := simplejson . NewFromAny ( expectedJSON )
if diff := cmp . Diff ( expected . Interface ( ) , dash . Data . Interface ( ) , getCompareOptions ( ) ... ) ; diff != "" {
t . Fatalf ( "Result mismatch (-want +got):\n%s" , diff )
}
} )
2021-02-24 07:06:22 -06:00
scenarioWithLibraryPanel ( t , "When an admin tries to load a dashboard with a library panel without uid, it should fail" ,
2021-01-20 02:28:10 -06:00
func ( t * testing . T , sc scenarioContext ) {
dashJSON := map [ string ] interface { } {
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 1 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 0 ,
} ,
} ,
map [ string ] interface { } {
"id" : int64 ( 2 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 6 ,
"y" : 0 ,
} ,
"libraryPanel" : map [ string ] interface { } {
2021-02-24 07:06:22 -06:00
"name" : sc . initialResult . Result . Name ,
2021-01-20 02:28:10 -06:00
} ,
} ,
} ,
}
dash := models . Dashboard {
2021-05-11 00:10:19 -05:00
Title : "Testing LoadLibraryPanelsForDashboard" ,
Data : simplejson . NewFromAny ( dashJSON ) ,
2021-01-20 02:28:10 -06:00
}
2021-05-11 00:10:19 -05:00
dashInDB := createDashboard ( t , sc . sqlStore , sc . user , & dash , sc . folder . Id )
2021-09-27 02:04:36 -05:00
err := sc . elementService . ConnectElementsToDashboard ( sc . ctx , sc . user , [ ] string { sc . initialResult . Result . UID } , dashInDB . Id )
2021-05-11 00:10:19 -05:00
require . NoError ( t , err )
2021-01-20 02:28:10 -06:00
2021-09-27 02:04:36 -05:00
err = sc . service . LoadLibraryPanelsForDashboard ( sc . ctx , dashInDB )
2021-01-20 02:28:10 -06:00
require . EqualError ( t , err , errLibraryPanelHeaderUIDMissing . Error ( ) )
} )
2021-02-24 07:06:22 -06:00
scenarioWithLibraryPanel ( t , "When an admin tries to load a dashboard with a library panel that is not connected, it should set correct JSON and continue" ,
2021-01-20 02:28:10 -06:00
func ( t * testing . T , sc scenarioContext ) {
dashJSON := map [ string ] interface { } {
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 1 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 0 ,
} ,
} ,
map [ string ] interface { } {
"id" : int64 ( 2 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 6 ,
"y" : 0 ,
} ,
"libraryPanel" : map [ string ] interface { } {
2021-02-24 07:06:22 -06:00
"uid" : sc . initialResult . Result . UID ,
"name" : sc . initialResult . Result . Name ,
2021-01-20 02:28:10 -06:00
} ,
} ,
} ,
}
dash := models . Dashboard {
2021-05-11 00:10:19 -05:00
Title : "Testing LoadLibraryPanelsForDashboard" ,
Data : simplejson . NewFromAny ( dashJSON ) ,
2021-01-20 02:28:10 -06:00
}
2021-05-11 00:10:19 -05:00
dashInDB := createDashboard ( t , sc . sqlStore , sc . user , & dash , sc . folder . Id )
2021-01-20 02:28:10 -06:00
2021-09-27 02:04:36 -05:00
err := sc . service . LoadLibraryPanelsForDashboard ( sc . ctx , dashInDB )
2021-01-28 23:11:13 -06:00
require . NoError ( t , err )
expectedJSON := map [ string ] interface { } {
2021-05-11 00:10:19 -05:00
"title" : "Testing LoadLibraryPanelsForDashboard" ,
"uid" : dashInDB . Uid ,
"version" : dashInDB . Version ,
2021-01-28 23:11:13 -06:00
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 1 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 0 ,
} ,
} ,
map [ string ] interface { } {
"id" : int64 ( 2 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 6 ,
"y" : 0 ,
} ,
"libraryPanel" : map [ string ] interface { } {
2021-02-24 07:06:22 -06:00
"uid" : sc . initialResult . Result . UID ,
"name" : sc . initialResult . Result . Name ,
2021-01-28 23:11:13 -06:00
} ,
2021-02-24 07:06:22 -06:00
"type" : fmt . Sprintf ( "Name: \"%s\", UID: \"%s\"" , sc . initialResult . Result . Name , sc . initialResult . Result . UID ) ,
2021-01-28 23:11:13 -06:00
} ,
} ,
}
expected := simplejson . NewFromAny ( expectedJSON )
if diff := cmp . Diff ( expected . Interface ( ) , dash . Data . Interface ( ) , getCompareOptions ( ) ... ) ; diff != "" {
t . Fatalf ( "Result mismatch (-want +got):\n%s" , diff )
}
2021-01-20 02:28:10 -06:00
} )
}
func TestCleanLibraryPanelsForDashboard ( t * testing . T ) {
2021-02-24 07:06:22 -06:00
scenarioWithLibraryPanel ( t , "When an admin tries to store a dashboard with a library panel, it should just keep the correct JSON properties in library panel" ,
2021-01-20 02:28:10 -06:00
func ( t * testing . T , sc scenarioContext ) {
dashJSON := map [ string ] interface { } {
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 1 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 0 ,
} ,
} ,
map [ string ] interface { } {
"id" : int64 ( 2 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 6 ,
"y" : 0 ,
} ,
"datasource" : "${DS_GDEV-TESTDATA}" ,
"libraryPanel" : map [ string ] interface { } {
2021-02-24 07:06:22 -06:00
"uid" : sc . initialResult . Result . UID ,
"name" : sc . initialResult . Result . Name ,
2021-01-20 02:28:10 -06:00
} ,
"title" : "Text - Library Panel" ,
"type" : "text" ,
} ,
} ,
}
dash := models . Dashboard {
2021-05-11 00:10:19 -05:00
Title : "Testing CleanLibraryPanelsForDashboard" ,
Data : simplejson . NewFromAny ( dashJSON ) ,
2021-01-20 02:28:10 -06:00
}
2021-05-11 00:10:19 -05:00
dashInDB := createDashboard ( t , sc . sqlStore , sc . user , & dash , sc . folder . Id )
2021-01-20 02:28:10 -06:00
2021-05-11 00:10:19 -05:00
err := sc . service . CleanLibraryPanelsForDashboard ( dashInDB )
2021-01-20 02:28:10 -06:00
require . NoError ( t , err )
expectedJSON := map [ string ] interface { } {
2021-05-11 00:10:19 -05:00
"title" : "Testing CleanLibraryPanelsForDashboard" ,
"uid" : dashInDB . Uid ,
"version" : dashInDB . Version ,
2021-01-20 02:28:10 -06:00
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 1 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 0 ,
} ,
} ,
map [ string ] interface { } {
"id" : int64 ( 2 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 6 ,
"y" : 0 ,
} ,
"libraryPanel" : map [ string ] interface { } {
2021-02-24 07:06:22 -06:00
"uid" : sc . initialResult . Result . UID ,
"name" : sc . initialResult . Result . Name ,
2021-01-20 02:28:10 -06:00
} ,
} ,
} ,
}
expected := simplejson . NewFromAny ( expectedJSON )
if diff := cmp . Diff ( expected . Interface ( ) , dash . Data . Interface ( ) , getCompareOptions ( ) ... ) ; diff != "" {
t . Fatalf ( "Result mismatch (-want +got):\n%s" , diff )
}
} )
2021-09-08 03:53:55 -05:00
scenarioWithLibraryPanel ( t , "When an admin tries to store a dashboard with library panels inside and outside of rows, it should just keep the correct JSON properties" ,
func ( t * testing . T , sc scenarioContext ) {
cmd := libraryelements . CreateLibraryElementCommand {
FolderID : sc . initialResult . Result . FolderID ,
Name : "Outside row" ,
Model : [ ] byte ( `
{
"datasource" : "${DS_GDEV-TESTDATA}" ,
"id" : 1 ,
"title" : "Text - Library Panel" ,
"type" : "text" ,
"description" : "A description"
}
` ) ,
Kind : int64 ( models . PanelElement ) ,
}
2021-09-27 02:04:36 -05:00
outsidePanel , err := sc . elementService . CreateElement ( sc . ctx , sc . user , cmd )
2021-09-08 03:53:55 -05:00
require . NoError ( t , err )
dashJSON := map [ string ] interface { } {
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 1 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 0 ,
} ,
} ,
map [ string ] interface { } {
"collapsed" : true ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 6 ,
} ,
"id" : int64 ( 2 ) ,
"type" : "row" ,
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 3 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 7 ,
} ,
} ,
map [ string ] interface { } {
"id" : int64 ( 4 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 6 ,
"y" : 13 ,
} ,
"datasource" : "${DS_GDEV-TESTDATA}" ,
"libraryPanel" : map [ string ] interface { } {
"uid" : sc . initialResult . Result . UID ,
"name" : sc . initialResult . Result . Name ,
} ,
"title" : "Inside row" ,
"type" : "text" ,
} ,
} ,
} ,
map [ string ] interface { } {
"id" : int64 ( 5 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 19 ,
} ,
"datasource" : "${DS_GDEV-TESTDATA}" ,
"libraryPanel" : map [ string ] interface { } {
"uid" : outsidePanel . UID ,
"name" : outsidePanel . Name ,
} ,
"title" : "Outside row" ,
"type" : "text" ,
} ,
} ,
}
dash := models . Dashboard {
Title : "Testing CleanLibraryPanelsForDashboard" ,
Data : simplejson . NewFromAny ( dashJSON ) ,
}
dashInDB := createDashboard ( t , sc . sqlStore , sc . user , & dash , sc . folder . Id )
err = sc . service . CleanLibraryPanelsForDashboard ( dashInDB )
require . NoError ( t , err )
expectedJSON := map [ string ] interface { } {
"title" : "Testing CleanLibraryPanelsForDashboard" ,
"uid" : dashInDB . Uid ,
"version" : dashInDB . Version ,
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 1 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 0 ,
} ,
} ,
map [ string ] interface { } {
"collapsed" : true ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 6 ,
} ,
"id" : int64 ( 2 ) ,
"type" : "row" ,
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 3 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 7 ,
} ,
} ,
map [ string ] interface { } {
"id" : int64 ( 4 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 6 ,
"y" : 13 ,
} ,
"libraryPanel" : map [ string ] interface { } {
"uid" : sc . initialResult . Result . UID ,
"name" : sc . initialResult . Result . Name ,
} ,
} ,
} ,
} ,
map [ string ] interface { } {
"id" : int64 ( 5 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 19 ,
} ,
"libraryPanel" : map [ string ] interface { } {
"uid" : outsidePanel . UID ,
"name" : outsidePanel . Name ,
} ,
} ,
} ,
}
expected := simplejson . NewFromAny ( expectedJSON )
if diff := cmp . Diff ( expected . Interface ( ) , dash . Data . Interface ( ) , getCompareOptions ( ) ... ) ; diff != "" {
t . Fatalf ( "Result mismatch (-want +got):\n%s" , diff )
}
} )
2021-02-24 07:06:22 -06:00
scenarioWithLibraryPanel ( t , "When an admin tries to store a dashboard with a library panel without uid, it should fail" ,
2021-01-20 02:28:10 -06:00
func ( t * testing . T , sc scenarioContext ) {
dashJSON := map [ string ] interface { } {
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 1 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 0 ,
} ,
} ,
map [ string ] interface { } {
"id" : int64 ( 2 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 6 ,
"y" : 0 ,
} ,
"datasource" : "${DS_GDEV-TESTDATA}" ,
"libraryPanel" : map [ string ] interface { } {
2021-02-24 07:06:22 -06:00
"name" : sc . initialResult . Result . Name ,
2021-01-20 02:28:10 -06:00
} ,
"title" : "Text - Library Panel" ,
"type" : "text" ,
} ,
} ,
}
dash := models . Dashboard {
2021-05-11 00:10:19 -05:00
Title : "Testing CleanLibraryPanelsForDashboard" ,
Data : simplejson . NewFromAny ( dashJSON ) ,
2021-01-20 02:28:10 -06:00
}
2021-05-11 00:10:19 -05:00
dashInDB := createDashboard ( t , sc . sqlStore , sc . user , & dash , sc . folder . Id )
2021-01-20 02:28:10 -06:00
2021-05-11 00:10:19 -05:00
err := sc . service . CleanLibraryPanelsForDashboard ( dashInDB )
2021-01-20 02:28:10 -06:00
require . EqualError ( t , err , errLibraryPanelHeaderUIDMissing . Error ( ) )
} )
2021-02-24 07:06:22 -06:00
scenarioWithLibraryPanel ( t , "When an admin tries to store a dashboard with a library panel without name, it should fail" ,
2021-01-20 02:28:10 -06:00
func ( t * testing . T , sc scenarioContext ) {
dashJSON := map [ string ] interface { } {
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 1 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 0 ,
} ,
} ,
map [ string ] interface { } {
"id" : int64 ( 2 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 6 ,
"y" : 0 ,
} ,
"datasource" : "${DS_GDEV-TESTDATA}" ,
"libraryPanel" : map [ string ] interface { } {
2021-02-24 07:06:22 -06:00
"uid" : sc . initialResult . Result . UID ,
2021-01-20 02:28:10 -06:00
} ,
"title" : "Text - Library Panel" ,
"type" : "text" ,
} ,
} ,
}
dash := models . Dashboard {
2021-05-11 00:10:19 -05:00
Title : "Testing CleanLibraryPanelsForDashboard" ,
Data : simplejson . NewFromAny ( dashJSON ) ,
2021-01-20 02:28:10 -06:00
}
2021-05-11 00:10:19 -05:00
dashInDB := createDashboard ( t , sc . sqlStore , sc . user , & dash , sc . folder . Id )
2021-01-20 02:28:10 -06:00
2021-05-11 00:10:19 -05:00
err := sc . service . CleanLibraryPanelsForDashboard ( dashInDB )
2021-01-20 02:28:10 -06:00
require . EqualError ( t , err , errLibraryPanelHeaderNameMissing . Error ( ) )
} )
}
func TestConnectLibraryPanelsForDashboard ( t * testing . T ) {
2021-02-24 07:06:22 -06:00
scenarioWithLibraryPanel ( t , "When an admin tries to store a dashboard with a library panel, it should connect the two" ,
2021-01-20 02:28:10 -06:00
func ( t * testing . T , sc scenarioContext ) {
dashJSON := map [ string ] interface { } {
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 1 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 0 ,
} ,
} ,
map [ string ] interface { } {
"id" : int64 ( 2 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 6 ,
"y" : 0 ,
} ,
"datasource" : "${DS_GDEV-TESTDATA}" ,
"libraryPanel" : map [ string ] interface { } {
2021-02-24 07:06:22 -06:00
"uid" : sc . initialResult . Result . UID ,
"name" : sc . initialResult . Result . Name ,
2021-01-20 02:28:10 -06:00
} ,
"title" : "Text - Library Panel" ,
"type" : "text" ,
} ,
} ,
}
dash := models . Dashboard {
2021-05-11 00:10:19 -05:00
Title : "Testing ConnectLibraryPanelsForDashboard" ,
Data : simplejson . NewFromAny ( dashJSON ) ,
2021-01-20 02:28:10 -06:00
}
2021-05-11 00:10:19 -05:00
dashInDB := createDashboard ( t , sc . sqlStore , sc . user , & dash , sc . folder . Id )
2021-01-20 02:28:10 -06:00
2021-09-27 02:04:36 -05:00
err := sc . service . ConnectLibraryPanelsForDashboard ( sc . ctx , sc . user , dashInDB )
2021-01-20 02:28:10 -06:00
require . NoError ( t , err )
2021-09-27 02:04:36 -05:00
elements , err := sc . elementService . GetElementsForDashboard ( sc . ctx , dashInDB . Id )
2021-01-20 02:28:10 -06:00
require . NoError ( t , err )
2021-05-11 00:10:19 -05:00
require . Len ( t , elements , 1 )
require . Equal ( t , sc . initialResult . Result . UID , elements [ sc . initialResult . Result . UID ] . UID )
2021-01-20 02:28:10 -06:00
} )
2021-09-08 03:53:55 -05:00
scenarioWithLibraryPanel ( t , "When an admin tries to store a dashboard with library panels inside and outside of rows, it should connect all" ,
func ( t * testing . T , sc scenarioContext ) {
cmd := libraryelements . CreateLibraryElementCommand {
FolderID : sc . initialResult . Result . FolderID ,
Name : "Outside row" ,
Model : [ ] byte ( `
{
"datasource" : "${DS_GDEV-TESTDATA}" ,
"id" : 1 ,
"title" : "Text - Library Panel" ,
"type" : "text" ,
"description" : "A description"
}
` ) ,
Kind : int64 ( models . PanelElement ) ,
}
2021-09-27 02:04:36 -05:00
outsidePanel , err := sc . elementService . CreateElement ( sc . ctx , sc . user , cmd )
2021-09-08 03:53:55 -05:00
require . NoError ( t , err )
dashJSON := map [ string ] interface { } {
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 1 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 0 ,
} ,
} ,
map [ string ] interface { } {
"collapsed" : true ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 6 ,
} ,
"id" : int64 ( 2 ) ,
"type" : "row" ,
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 3 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 7 ,
} ,
} ,
map [ string ] interface { } {
"id" : int64 ( 4 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 6 ,
"y" : 13 ,
} ,
"datasource" : "${DS_GDEV-TESTDATA}" ,
"libraryPanel" : map [ string ] interface { } {
"uid" : sc . initialResult . Result . UID ,
"name" : sc . initialResult . Result . Name ,
} ,
"title" : "Inside row" ,
"type" : "text" ,
} ,
} ,
} ,
map [ string ] interface { } {
"id" : int64 ( 5 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 19 ,
} ,
"datasource" : "${DS_GDEV-TESTDATA}" ,
"libraryPanel" : map [ string ] interface { } {
"uid" : outsidePanel . UID ,
"name" : outsidePanel . Name ,
} ,
"title" : "Outside row" ,
"type" : "text" ,
} ,
} ,
}
dash := models . Dashboard {
Title : "Testing ConnectLibraryPanelsForDashboard" ,
Data : simplejson . NewFromAny ( dashJSON ) ,
}
dashInDB := createDashboard ( t , sc . sqlStore , sc . user , & dash , sc . folder . Id )
2021-09-27 02:04:36 -05:00
err = sc . service . ConnectLibraryPanelsForDashboard ( sc . ctx , sc . user , dashInDB )
2021-09-08 03:53:55 -05:00
require . NoError ( t , err )
2021-09-27 02:04:36 -05:00
elements , err := sc . elementService . GetElementsForDashboard ( sc . ctx , dashInDB . Id )
2021-09-08 03:53:55 -05:00
require . NoError ( t , err )
require . Len ( t , elements , 2 )
require . Equal ( t , sc . initialResult . Result . UID , elements [ sc . initialResult . Result . UID ] . UID )
require . Equal ( t , outsidePanel . UID , elements [ outsidePanel . UID ] . UID )
} )
2021-02-24 07:06:22 -06:00
scenarioWithLibraryPanel ( t , "When an admin tries to store a dashboard with a library panel without uid, it should fail" ,
2021-01-20 02:28:10 -06:00
func ( t * testing . T , sc scenarioContext ) {
dashJSON := map [ string ] interface { } {
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 1 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 0 ,
} ,
} ,
map [ string ] interface { } {
"id" : int64 ( 2 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 6 ,
"y" : 0 ,
} ,
"datasource" : "${DS_GDEV-TESTDATA}" ,
"libraryPanel" : map [ string ] interface { } {
2021-02-24 07:06:22 -06:00
"name" : sc . initialResult . Result . Name ,
2021-01-20 02:28:10 -06:00
} ,
"title" : "Text - Library Panel" ,
"type" : "text" ,
} ,
} ,
}
dash := models . Dashboard {
2021-05-11 00:10:19 -05:00
Title : "Testing ConnectLibraryPanelsForDashboard" ,
Data : simplejson . NewFromAny ( dashJSON ) ,
2021-01-20 02:28:10 -06:00
}
2021-05-11 00:10:19 -05:00
dashInDB := createDashboard ( t , sc . sqlStore , sc . user , & dash , sc . folder . Id )
2021-01-20 02:28:10 -06:00
2021-09-27 02:04:36 -05:00
err := sc . service . ConnectLibraryPanelsForDashboard ( sc . ctx , sc . user , dashInDB )
2021-01-20 02:28:10 -06:00
require . EqualError ( t , err , errLibraryPanelHeaderUIDMissing . Error ( ) )
} )
2021-02-16 06:00:56 -06:00
2021-02-24 07:06:22 -06:00
scenarioWithLibraryPanel ( t , "When an admin tries to store a dashboard with unused/removed library panels, it should disconnect unused/removed library panels" ,
2021-02-16 06:00:56 -06:00
func ( t * testing . T , sc scenarioContext ) {
2021-09-27 02:04:36 -05:00
unused , err := sc . elementService . CreateElement ( sc . ctx , sc . user , libraryelements . CreateLibraryElementCommand {
2021-05-11 00:10:19 -05:00
FolderID : sc . folder . Id ,
Name : "Unused Libray Panel" ,
Model : [ ] byte ( `
{
"datasource" : "${DS_GDEV-TESTDATA}" ,
"id" : 4 ,
"title" : "Unused Libray Panel" ,
"type" : "text" ,
"description" : "Unused description"
2021-02-16 06:00:56 -06:00
}
2021-05-11 00:10:19 -05:00
` ) ,
2021-05-23 23:11:01 -05:00
Kind : int64 ( models . PanelElement ) ,
2021-05-11 00:10:19 -05:00
} )
2021-02-16 06:00:56 -06:00
require . NoError ( t , err )
2021-01-20 02:28:10 -06:00
dashJSON := map [ string ] interface { } {
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 1 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 0 ,
} ,
} ,
map [ string ] interface { } {
2021-05-11 00:10:19 -05:00
"id" : int64 ( 4 ) ,
2021-01-20 02:28:10 -06:00
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 6 ,
"y" : 0 ,
} ,
"datasource" : "${DS_GDEV-TESTDATA}" ,
"libraryPanel" : map [ string ] interface { } {
2021-05-11 00:10:19 -05:00
"uid" : unused . UID ,
"name" : unused . Name ,
2021-01-20 02:28:10 -06:00
} ,
2021-05-11 00:10:19 -05:00
"title" : "Unused Libray Panel" ,
"description" : "Unused description" ,
2021-01-20 02:28:10 -06:00
} ,
} ,
}
2021-05-11 00:10:19 -05:00
2021-01-20 02:28:10 -06:00
dash := models . Dashboard {
2021-05-11 00:10:19 -05:00
Title : "Testing ConnectLibraryPanelsForDashboard" ,
Data : simplejson . NewFromAny ( dashJSON ) ,
2021-01-20 02:28:10 -06:00
}
2021-05-11 00:10:19 -05:00
dashInDB := createDashboard ( t , sc . sqlStore , sc . user , & dash , sc . folder . Id )
2021-09-27 02:04:36 -05:00
err = sc . elementService . ConnectElementsToDashboard ( sc . ctx , sc . user , [ ] string { sc . initialResult . Result . UID } , dashInDB . Id )
2021-01-20 02:28:10 -06:00
require . NoError ( t , err )
2021-05-11 00:10:19 -05:00
panelJSON := [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 1 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 0 ,
2021-01-20 02:28:10 -06:00
} ,
2021-05-11 00:10:19 -05:00
} ,
map [ string ] interface { } {
"id" : int64 ( 2 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 6 ,
"y" : 0 ,
} ,
"datasource" : "${DS_GDEV-TESTDATA}" ,
"libraryPanel" : map [ string ] interface { } {
"uid" : sc . initialResult . Result . UID ,
"name" : sc . initialResult . Result . Name ,
2021-01-20 02:28:10 -06:00
} ,
2021-05-11 00:10:19 -05:00
"title" : "Text - Library Panel" ,
"type" : "text" ,
2021-01-20 02:28:10 -06:00
} ,
}
2021-05-11 00:10:19 -05:00
dashInDB . Data . Set ( "panels" , panelJSON )
2021-09-27 02:04:36 -05:00
err = sc . service . ConnectLibraryPanelsForDashboard ( sc . ctx , sc . user , dashInDB )
2021-03-02 03:34:01 -06:00
require . NoError ( t , err )
2021-09-27 02:04:36 -05:00
elements , err := sc . elementService . GetElementsForDashboard ( sc . ctx , dashInDB . Id )
2021-03-02 03:34:01 -06:00
require . NoError ( t , err )
2021-05-11 00:10:19 -05:00
require . Len ( t , elements , 1 )
require . Equal ( t , sc . initialResult . Result . UID , elements [ sc . initialResult . Result . UID ] . UID )
2021-03-02 03:34:01 -06:00
} )
}
2021-09-20 03:58:24 -05:00
func TestImportLibraryPanelsForDashboard ( t * testing . T ) {
testScenario ( t , "When an admin tries to import a dashboard with a library panel that does not exist, it should import the library panel" ,
func ( t * testing . T , sc scenarioContext ) {
var missingUID = "jL6MrxCMz"
var missingName = "Missing Library Panel"
var missingModel = map [ string ] interface { } {
"id" : int64 ( 2 ) ,
"gridPos" : map [ string ] interface { } {
"h" : int64 ( 6 ) ,
"w" : int64 ( 6 ) ,
"x" : int64 ( 0 ) ,
"y" : int64 ( 0 ) ,
} ,
"description" : "" ,
"datasource" : "${DS_GDEV-TESTDATA}" ,
"libraryPanel" : map [ string ] interface { } {
"uid" : missingUID ,
"name" : missingName ,
} ,
"title" : "Text - Library Panel" ,
"type" : "text" ,
}
dashJSON := map [ string ] interface { } {
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 1 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 0 ,
} ,
} ,
missingModel ,
} ,
}
dash := models . Dashboard {
Title : "Testing ImportLibraryPanelsForDashboard" ,
Data : simplejson . NewFromAny ( dashJSON ) ,
}
dashInDB := createDashboard ( t , sc . sqlStore , sc . user , & dash , sc . folder . Id )
2021-09-27 02:04:36 -05:00
_ , err := sc . elementService . GetElement ( sc . ctx , sc . user , missingUID )
2021-09-20 03:58:24 -05:00
require . EqualError ( t , err , libraryelements . ErrLibraryElementNotFound . Error ( ) )
2021-09-27 02:04:36 -05:00
err = sc . service . ImportLibraryPanelsForDashboard ( sc . ctx , sc . user , dashInDB , 0 )
2021-09-20 03:58:24 -05:00
require . NoError ( t , err )
2021-09-27 02:04:36 -05:00
element , err := sc . elementService . GetElement ( sc . ctx , sc . user , missingUID )
2021-09-20 03:58:24 -05:00
require . NoError ( t , err )
var expected = getExpected ( t , element , missingUID , missingName , missingModel )
var result = toLibraryElement ( t , element )
if diff := cmp . Diff ( expected , result , getCompareOptions ( ) ... ) ; diff != "" {
t . Fatalf ( "Result mismatch (-want +got):\n%s" , diff )
}
} )
scenarioWithLibraryPanel ( t , "When an admin tries to import a dashboard with a library panel that already exist, it should not import the library panel and existing library panel should be unchanged" ,
func ( t * testing . T , sc scenarioContext ) {
var existingUID = sc . initialResult . Result . UID
var existingName = sc . initialResult . Result . Name
dashJSON := map [ string ] interface { } {
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 1 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 0 ,
} ,
} ,
map [ string ] interface { } {
"id" : int64 ( 1 ) ,
"description" : "Updated description" ,
"datasource" : "Updated datasource" ,
"libraryPanel" : map [ string ] interface { } {
"uid" : sc . initialResult . Result . UID ,
"name" : sc . initialResult . Result . Name ,
} ,
"title" : "Updated Title" ,
"type" : "stat" ,
} ,
} ,
}
dash := models . Dashboard {
Title : "Testing ImportLibraryPanelsForDashboard" ,
Data : simplejson . NewFromAny ( dashJSON ) ,
}
dashInDB := createDashboard ( t , sc . sqlStore , sc . user , & dash , sc . folder . Id )
2021-09-27 02:04:36 -05:00
_ , err := sc . elementService . GetElement ( sc . ctx , sc . user , existingUID )
2021-09-20 03:58:24 -05:00
require . NoError ( t , err )
2021-09-27 02:04:36 -05:00
err = sc . service . ImportLibraryPanelsForDashboard ( sc . ctx , sc . user , dashInDB , sc . folder . Id )
2021-09-20 03:58:24 -05:00
require . NoError ( t , err )
2021-09-27 02:04:36 -05:00
element , err := sc . elementService . GetElement ( sc . ctx , sc . user , existingUID )
2021-09-20 03:58:24 -05:00
require . NoError ( t , err )
var expected = getExpected ( t , element , existingUID , existingName , sc . initialResult . Result . Model )
expected . FolderID = sc . initialResult . Result . FolderID
expected . Description = sc . initialResult . Result . Description
expected . Meta . FolderUID = sc . folder . Uid
expected . Meta . FolderName = sc . folder . Title
var result = toLibraryElement ( t , element )
if diff := cmp . Diff ( expected , result , getCompareOptions ( ) ... ) ; diff != "" {
t . Fatalf ( "Result mismatch (-want +got):\n%s" , diff )
}
} )
testScenario ( t , "When an admin tries to import a dashboard with library panels inside and outside of rows, it should import all that do not exist" ,
func ( t * testing . T , sc scenarioContext ) {
var outsideUID = "jL6MrxCMz"
var outsideName = "Outside Library Panel"
var outsideModel = map [ string ] interface { } {
"id" : int64 ( 5 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 19 ,
} ,
"datasource" : "${DS_GDEV-TESTDATA}" ,
"libraryPanel" : map [ string ] interface { } {
"uid" : outsideUID ,
"name" : outsideName ,
} ,
"title" : "Outside row" ,
"type" : "text" ,
}
var insideUID = "iK7NsyDNz"
var insideName = "Inside Library Panel"
var insideModel = map [ string ] interface { } {
"id" : int64 ( 4 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 6 ,
"y" : 13 ,
} ,
"datasource" : "${DS_GDEV-TESTDATA}" ,
"libraryPanel" : map [ string ] interface { } {
"uid" : insideUID ,
"name" : insideName ,
} ,
"title" : "Inside row" ,
"type" : "text" ,
}
dashJSON := map [ string ] interface { } {
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 1 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 0 ,
} ,
} ,
map [ string ] interface { } {
"collapsed" : true ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 6 ,
} ,
"id" : int64 ( 2 ) ,
"type" : "row" ,
"panels" : [ ] interface { } {
map [ string ] interface { } {
"id" : int64 ( 3 ) ,
"gridPos" : map [ string ] interface { } {
"h" : 6 ,
"w" : 6 ,
"x" : 0 ,
"y" : 7 ,
} ,
} ,
insideModel ,
} ,
} ,
outsideModel ,
} ,
}
dash := models . Dashboard {
Title : "Testing ImportLibraryPanelsForDashboard" ,
Data : simplejson . NewFromAny ( dashJSON ) ,
}
dashInDB := createDashboard ( t , sc . sqlStore , sc . user , & dash , sc . folder . Id )
2021-09-27 02:04:36 -05:00
_ , err := sc . elementService . GetElement ( sc . ctx , sc . user , outsideUID )
2021-09-20 03:58:24 -05:00
require . EqualError ( t , err , libraryelements . ErrLibraryElementNotFound . Error ( ) )
2021-09-27 02:04:36 -05:00
_ , err = sc . elementService . GetElement ( sc . ctx , sc . user , insideUID )
2021-09-20 03:58:24 -05:00
require . EqualError ( t , err , libraryelements . ErrLibraryElementNotFound . Error ( ) )
2021-09-27 02:04:36 -05:00
err = sc . service . ImportLibraryPanelsForDashboard ( sc . ctx , sc . user , dashInDB , 0 )
2021-09-20 03:58:24 -05:00
require . NoError ( t , err )
2021-09-27 02:04:36 -05:00
element , err := sc . elementService . GetElement ( sc . ctx , sc . user , outsideUID )
2021-09-20 03:58:24 -05:00
require . NoError ( t , err )
expected := getExpected ( t , element , outsideUID , outsideName , outsideModel )
result := toLibraryElement ( t , element )
if diff := cmp . Diff ( expected , result , getCompareOptions ( ) ... ) ; diff != "" {
t . Fatalf ( "Result mismatch (-want +got):\n%s" , diff )
}
2021-09-27 02:04:36 -05:00
element , err = sc . elementService . GetElement ( sc . ctx , sc . user , insideUID )
2021-09-20 03:58:24 -05:00
require . NoError ( t , err )
expected = getExpected ( t , element , insideUID , insideName , insideModel )
result = toLibraryElement ( t , element )
if diff := cmp . Diff ( expected , result , getCompareOptions ( ) ... ) ; diff != "" {
t . Fatalf ( "Result mismatch (-want +got):\n%s" , diff )
}
} )
}
2020-12-21 02:40:27 -06:00
type libraryPanel struct {
2021-05-11 00:10:19 -05:00
ID int64
OrgID int64
FolderID int64
UID string
Name string
2021-03-24 07:43:51 -05:00
Type string
Description string
2021-05-11 00:10:19 -05:00
Model map [ string ] interface { }
Version int64
Meta libraryelements . LibraryElementDTOMeta
2020-12-21 02:40:27 -06:00
}
2020-12-10 23:08:32 -06:00
2021-09-20 03:58:24 -05:00
type libraryElementGridPos struct {
H int64 ` json:"h" `
W int64 ` json:"w" `
X int64 ` json:"x" `
Y int64 ` json:"y" `
}
type libraryElementLibraryPanel struct {
UID string ` json:"uid" `
Name string ` json:"name" `
}
type libraryElementModel struct {
ID int64 ` json:"id" `
Datasource string ` json:"datasource" `
Description string ` json:"description" `
Title string ` json:"title" `
Type string ` json:"type" `
GridPos libraryElementGridPos ` json:"gridPos" `
LibraryPanel libraryElementLibraryPanel ` json:"libraryPanel" `
}
type libraryElement struct {
ID int64 ` json:"id" `
OrgID int64 ` json:"orgId" `
FolderID int64 ` json:"folderId" `
UID string ` json:"uid" `
Name string ` json:"name" `
Kind int64 ` json:"kind" `
Type string ` json:"type" `
Description string ` json:"description" `
Model libraryElementModel ` json:"model" `
Version int64 ` json:"version" `
Meta libraryelements . LibraryElementDTOMeta ` json:"meta" `
}
2020-12-21 02:40:27 -06:00
type libraryPanelResult struct {
Result libraryPanel ` json:"result" `
}
2020-12-10 23:08:32 -06:00
2020-12-21 02:40:27 -06:00
type scenarioContext struct {
2021-09-27 02:04:36 -05:00
ctx context . Context
2021-05-12 01:48:17 -05:00
service Service
elementService libraryelements . Service
2021-09-27 02:04:36 -05:00
user * models . SignedInUser
2021-05-11 00:10:19 -05:00
folder * models . Folder
initialResult libraryPanelResult
sqlStore * sqlstore . SQLStore
2021-02-24 07:06:22 -06:00
}
2021-03-01 08:33:17 -06:00
type folderACLItem struct {
roleType models . RoleType
permission models . PermissionType
}
2021-09-20 03:58:24 -05:00
func toLibraryElement ( t * testing . T , res libraryelements . LibraryElementDTO ) libraryElement {
var model = libraryElementModel { }
err := json . Unmarshal ( res . Model , & model )
require . NoError ( t , err )
return libraryElement {
ID : res . ID ,
OrgID : res . OrgID ,
FolderID : res . FolderID ,
UID : res . UID ,
Name : res . Name ,
Type : res . Type ,
Description : res . Description ,
Kind : res . Kind ,
Model : model ,
Version : res . Version ,
Meta : libraryelements . LibraryElementDTOMeta {
FolderName : res . Meta . FolderName ,
FolderUID : res . Meta . FolderUID ,
ConnectedDashboards : res . Meta . ConnectedDashboards ,
Created : res . Meta . Created ,
Updated : res . Meta . Updated ,
CreatedBy : libraryelements . LibraryElementDTOMetaUser {
ID : res . Meta . CreatedBy . ID ,
Name : res . Meta . CreatedBy . Name ,
AvatarURL : res . Meta . CreatedBy . AvatarURL ,
} ,
UpdatedBy : libraryelements . LibraryElementDTOMetaUser {
ID : res . Meta . UpdatedBy . ID ,
Name : res . Meta . UpdatedBy . Name ,
AvatarURL : res . Meta . UpdatedBy . AvatarURL ,
} ,
} ,
}
}
func getExpected ( t * testing . T , res libraryelements . LibraryElementDTO , UID string , name string , model map [ string ] interface { } ) libraryElement {
marshalled , err := json . Marshal ( model )
require . NoError ( t , err )
var libModel libraryElementModel
err = json . Unmarshal ( marshalled , & libModel )
require . NoError ( t , err )
return libraryElement {
ID : res . ID ,
OrgID : 1 ,
FolderID : 0 ,
UID : UID ,
Name : name ,
Type : "text" ,
Description : "" ,
Kind : 1 ,
Model : libModel ,
Version : 1 ,
Meta : libraryelements . LibraryElementDTOMeta {
FolderName : "General" ,
FolderUID : "" ,
ConnectedDashboards : 0 ,
Created : res . Meta . Created ,
Updated : res . Meta . Updated ,
CreatedBy : libraryelements . LibraryElementDTOMetaUser {
ID : 1 ,
Name : userInDbName ,
AvatarURL : userInDbAvatar ,
} ,
UpdatedBy : libraryelements . LibraryElementDTOMetaUser {
ID : 1 ,
Name : userInDbName ,
AvatarURL : userInDbAvatar ,
} ,
} ,
}
}
2021-09-27 02:04:36 -05:00
func createDashboard ( t * testing . T , sqlStore * sqlstore . SQLStore , user * models . SignedInUser , dash * models . Dashboard , folderID int64 ) * models . Dashboard {
2021-03-01 08:33:17 -06:00
dash . FolderId = folderID
dashItem := & dashboards . SaveDashboardDTO {
Dashboard : dash ,
Message : "" ,
OrgId : user . OrgId ,
2021-09-27 02:04:36 -05:00
User : user ,
2021-03-01 08:33:17 -06:00
Overwrite : false ,
}
2021-03-17 10:06:10 -05:00
origUpdateAlerting := dashboards . UpdateAlerting
t . Cleanup ( func ( ) {
dashboards . UpdateAlerting = origUpdateAlerting
2021-03-01 08:33:17 -06:00
} )
2021-11-03 08:10:39 -05:00
dashboards . UpdateAlerting = func ( ctx context . Context , store dboards . Store , orgID int64 , dashboard * models . Dashboard ,
2021-03-17 10:06:10 -05:00
user * models . SignedInUser ) error {
2021-03-01 08:33:17 -06:00
return nil
2021-03-17 10:06:10 -05:00
}
2021-03-01 08:33:17 -06:00
2021-11-03 08:10:39 -05:00
dashboard , err := dashboards . NewService ( sqlStore ) . SaveDashboard ( context . Background ( ) , dashItem , true )
2021-02-24 07:06:22 -06:00
require . NoError ( t , err )
2021-03-01 08:33:17 -06:00
return dashboard
}
2021-09-27 02:04:36 -05:00
func createFolderWithACL ( t * testing . T , sqlStore * sqlstore . SQLStore , title string , user * models . SignedInUser ,
2021-03-17 10:06:10 -05:00
items [ ] folderACLItem ) * models . Folder {
t . Helper ( )
2021-09-27 02:04:36 -05:00
s := dashboards . NewFolderService ( user . OrgId , user , sqlStore )
2021-03-17 10:06:10 -05:00
t . Logf ( "Creating folder with title and UID %q" , title )
2021-09-14 09:08:04 -05:00
folder , err := s . CreateFolder ( context . Background ( ) , title , title )
2021-03-01 08:33:17 -06:00
require . NoError ( t , err )
2021-03-17 10:06:10 -05:00
updateFolderACL ( t , sqlStore , folder . Id , items )
2021-03-01 08:33:17 -06:00
2021-03-17 10:06:10 -05:00
return folder
2021-02-24 07:06:22 -06:00
}
2021-03-17 10:06:10 -05:00
func updateFolderACL ( t * testing . T , sqlStore * sqlstore . SQLStore , folderID int64 , items [ ] folderACLItem ) {
t . Helper ( )
2021-03-01 08:33:17 -06:00
if len ( items ) == 0 {
return
}
2021-03-17 10:06:10 -05:00
var aclItems [ ] * models . DashboardAcl
2021-03-01 08:33:17 -06:00
for _ , item := range items {
role := item . roleType
permission := item . permission
2021-03-17 10:06:10 -05:00
aclItems = append ( aclItems , & models . DashboardAcl {
2021-03-01 08:33:17 -06:00
DashboardID : folderID ,
Role : & role ,
Permission : permission ,
Created : time . Now ( ) ,
Updated : time . Now ( ) ,
} )
}
2021-12-22 04:02:42 -06:00
err := sqlStore . UpdateDashboardACL ( context . Background ( ) , folderID , aclItems )
2021-02-24 07:06:22 -06:00
require . NoError ( t , err )
}
func scenarioWithLibraryPanel ( t * testing . T , desc string , fn func ( t * testing . T , sc scenarioContext ) ) {
2021-03-17 10:06:10 -05:00
t . Helper ( )
2021-02-24 07:06:22 -06:00
testScenario ( t , desc , func ( t * testing . T , sc scenarioContext ) {
2021-05-11 00:10:19 -05:00
command := libraryelements . CreateLibraryElementCommand {
FolderID : sc . folder . Id ,
Name : "Text - Library Panel" ,
Model : [ ] byte ( `
{
"datasource" : "${DS_GDEV-TESTDATA}" ,
"id" : 1 ,
"title" : "Text - Library Panel" ,
"type" : "text" ,
"description" : "A description"
}
` ) ,
2021-05-23 23:11:01 -05:00
Kind : int64 ( models . PanelElement ) ,
2021-05-11 00:10:19 -05:00
}
2021-09-27 02:04:36 -05:00
resp , err := sc . elementService . CreateElement ( sc . ctx , sc . user , command )
2021-05-11 00:10:19 -05:00
require . NoError ( t , err )
var model map [ string ] interface { }
err = json . Unmarshal ( resp . Model , & model )
require . NoError ( t , err )
sc . initialResult = libraryPanelResult {
Result : libraryPanel {
ID : resp . ID ,
OrgID : resp . OrgID ,
FolderID : resp . FolderID ,
UID : resp . UID ,
Name : resp . Name ,
Type : resp . Type ,
Description : resp . Description ,
Model : model ,
Version : resp . Version ,
Meta : resp . Meta ,
} ,
}
2021-02-24 07:06:22 -06:00
fn ( t , sc )
} )
2020-12-21 02:40:27 -06:00
}
// testScenario is a wrapper around t.Run performing common setup for library panel tests.
// It takes your real test function as a callback.
2020-12-22 05:00:41 -06:00
func testScenario ( t * testing . T , desc string , fn func ( t * testing . T , sc scenarioContext ) ) {
2020-12-21 02:40:27 -06:00
t . Helper ( )
t . Run ( desc , func ( t * testing . T ) {
2021-05-12 01:48:17 -05:00
cfg := setting . NewCfg ( )
2020-12-21 02:40:27 -06:00
orgID := int64 ( 1 )
role := models . ROLE_ADMIN
sqlStore := sqlstore . InitTestDB ( t )
2021-05-12 01:48:17 -05:00
elementService := libraryelements . LibraryElementService {
Cfg : cfg ,
SQLStore : sqlStore ,
}
service := LibraryPanelService {
Cfg : cfg ,
SQLStore : sqlStore ,
LibraryElementService : & elementService ,
}
2020-12-21 02:40:27 -06:00
2021-09-27 02:04:36 -05:00
user := & models . SignedInUser {
2020-12-21 02:40:27 -06:00
UserId : 1 ,
2021-02-01 23:25:35 -06:00
Name : "Signed In User" ,
Login : "signed_in_user" ,
Email : "signed.in.user@test.com" ,
2020-12-21 02:40:27 -06:00
OrgId : orgID ,
OrgRole : role ,
LastSeenAt : time . Now ( ) ,
}
2021-02-24 07:06:22 -06:00
2021-02-01 23:25:35 -06:00
// deliberate difference between signed in user and user in db to make it crystal clear
// what to expect in the tests
// In the real world these are identical
2021-03-17 10:06:10 -05:00
cmd := models . CreateUserCommand {
2021-02-01 23:25:35 -06:00
Email : "user.in.db@test.com" ,
Name : "User In DB" ,
2021-09-20 03:58:24 -05:00
Login : userInDbName ,
2021-02-01 23:25:35 -06:00
}
2022-01-20 04:10:12 -06:00
2021-03-17 10:06:10 -05:00
_ , err := sqlStore . CreateUser ( context . Background ( ) , cmd )
2021-02-01 23:25:35 -06:00
require . NoError ( t , err )
2020-12-21 02:40:27 -06:00
sc := scenarioContext {
2021-05-11 00:10:19 -05:00
user : user ,
2021-09-27 02:04:36 -05:00
ctx : context . Background ( ) ,
2021-05-12 01:48:17 -05:00
service : & service ,
elementService : & elementService ,
2021-05-11 00:10:19 -05:00
sqlStore : sqlStore ,
2020-12-21 02:40:27 -06:00
}
2021-02-24 07:06:22 -06:00
2021-03-17 10:06:10 -05:00
sc . folder = createFolderWithACL ( t , sc . sqlStore , "ScenarioFolder" , sc . user , [ ] folderACLItem { } )
2021-02-24 07:06:22 -06:00
2020-12-21 02:40:27 -06:00
fn ( t , sc )
} )
}
2020-12-23 05:42:52 -06:00
func getCompareOptions ( ) [ ] cmp . Option {
return [ ] cmp . Option {
cmp . Transformer ( "Time" , func ( in time . Time ) int64 {
return in . UTC ( ) . Unix ( )
} ) ,
}
}