dashboard_service_test.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. package dashboards
  2. import (
  3. "testing"
  4. "github.com/grafana/grafana/pkg/bus"
  5. "github.com/grafana/grafana/pkg/models"
  6. "github.com/grafana/grafana/pkg/services/guardian"
  7. "github.com/pkg/errors"
  8. . "github.com/smartystreets/goconvey/convey"
  9. )
  10. func TestDashboardService(t *testing.T) {
  11. Convey("Dashboard service tests", t, func() {
  12. bus.ClearBusHandlers()
  13. service := &dashboardServiceImpl{}
  14. origNewDashboardGuardian := guardian.New
  15. guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
  16. Convey("Save dashboard validation", func() {
  17. dto := &SaveDashboardDTO{}
  18. Convey("When saving a dashboard with empty title it should return error", func() {
  19. titles := []string{"", " ", " \t "}
  20. for _, title := range titles {
  21. dto.Dashboard = models.NewDashboard(title)
  22. _, err := service.SaveDashboard(dto)
  23. So(err, ShouldEqual, models.ErrDashboardTitleEmpty)
  24. }
  25. })
  26. Convey("Should return validation error if it's a folder and have a folder id", func() {
  27. dto.Dashboard = models.NewDashboardFolder("Folder")
  28. dto.Dashboard.FolderId = 1
  29. _, err := service.SaveDashboard(dto)
  30. So(err, ShouldEqual, models.ErrDashboardFolderCannotHaveParent)
  31. })
  32. Convey("Should return validation error if folder is named General", func() {
  33. dto.Dashboard = models.NewDashboardFolder("General")
  34. _, err := service.SaveDashboard(dto)
  35. So(err, ShouldEqual, models.ErrDashboardFolderNameExists)
  36. })
  37. Convey("When saving a dashboard should validate uid", func() {
  38. bus.AddHandler("test", func(cmd *models.ValidateDashboardAlertsCommand) error {
  39. return nil
  40. })
  41. bus.AddHandler("test", func(cmd *models.ValidateDashboardBeforeSaveCommand) error {
  42. cmd.Result = &models.ValidateDashboardBeforeSaveResult{}
  43. return nil
  44. })
  45. bus.AddHandler("test", func(cmd *models.IsDashboardProvisionedQuery) error {
  46. cmd.Result = false
  47. return nil
  48. })
  49. testCases := []struct {
  50. Uid string
  51. Error error
  52. }{
  53. {Uid: "", Error: nil},
  54. {Uid: " ", Error: nil},
  55. {Uid: " \t ", Error: nil},
  56. {Uid: "asdf90_-", Error: nil},
  57. {Uid: "asdf/90", Error: models.ErrDashboardInvalidUid},
  58. {Uid: " asdfghjklqwertyuiopzxcvbnmasdfghjklqwer ", Error: nil},
  59. {Uid: "asdfghjklqwertyuiopzxcvbnmasdfghjklqwertyuiopzxcvbnmasdfghjklqwertyuiopzxcvbnm", Error: models.ErrDashboardUidToLong},
  60. }
  61. for _, tc := range testCases {
  62. dto.Dashboard = models.NewDashboard("title")
  63. dto.Dashboard.SetUid(tc.Uid)
  64. dto.User = &models.SignedInUser{}
  65. _, err := service.buildSaveDashboardCommand(dto, true, false)
  66. So(err, ShouldEqual, tc.Error)
  67. }
  68. })
  69. Convey("Should return validation error if dashboard is provisioned", func() {
  70. provisioningValidated := false
  71. bus.AddHandler("test", func(cmd *models.IsDashboardProvisionedQuery) error {
  72. provisioningValidated = true
  73. cmd.Result = true
  74. return nil
  75. })
  76. bus.AddHandler("test", func(cmd *models.ValidateDashboardAlertsCommand) error {
  77. return nil
  78. })
  79. bus.AddHandler("test", func(cmd *models.ValidateDashboardBeforeSaveCommand) error {
  80. cmd.Result = &models.ValidateDashboardBeforeSaveResult{}
  81. return nil
  82. })
  83. dto.Dashboard = models.NewDashboard("Dash")
  84. dto.Dashboard.SetId(3)
  85. dto.User = &models.SignedInUser{UserId: 1}
  86. _, err := service.SaveDashboard(dto)
  87. So(provisioningValidated, ShouldBeTrue)
  88. So(err, ShouldEqual, models.ErrDashboardCannotSaveProvisionedDashboard)
  89. })
  90. Convey("Should return validation error if alert data is invalid", func() {
  91. bus.AddHandler("test", func(cmd *models.IsDashboardProvisionedQuery) error {
  92. cmd.Result = false
  93. return nil
  94. })
  95. bus.AddHandler("test", func(cmd *models.ValidateDashboardAlertsCommand) error {
  96. return errors.New("Alert validation error")
  97. })
  98. dto.Dashboard = models.NewDashboard("Dash")
  99. _, err := service.SaveDashboard(dto)
  100. So(err.Error(), ShouldEqual, "Alert validation error")
  101. })
  102. })
  103. Convey("Save provisioned dashboard validation", func() {
  104. dto := &SaveDashboardDTO{}
  105. Convey("Should not return validation error if dashboard is provisioned", func() {
  106. provisioningValidated := false
  107. bus.AddHandler("test", func(cmd *models.IsDashboardProvisionedQuery) error {
  108. provisioningValidated = true
  109. cmd.Result = true
  110. return nil
  111. })
  112. bus.AddHandler("test", func(cmd *models.ValidateDashboardAlertsCommand) error {
  113. return nil
  114. })
  115. bus.AddHandler("test", func(cmd *models.ValidateDashboardBeforeSaveCommand) error {
  116. cmd.Result = &models.ValidateDashboardBeforeSaveResult{}
  117. return nil
  118. })
  119. bus.AddHandler("test", func(cmd *models.SaveProvisionedDashboardCommand) error {
  120. return nil
  121. })
  122. bus.AddHandler("test", func(cmd *models.UpdateDashboardAlertsCommand) error {
  123. return nil
  124. })
  125. dto.Dashboard = models.NewDashboard("Dash")
  126. dto.Dashboard.SetId(3)
  127. dto.User = &models.SignedInUser{UserId: 1}
  128. _, err := service.SaveProvisionedDashboard(dto, nil)
  129. So(err, ShouldBeNil)
  130. So(provisioningValidated, ShouldBeFalse)
  131. })
  132. })
  133. Convey("Import dashboard validation", func() {
  134. dto := &SaveDashboardDTO{}
  135. Convey("Should return validation error if dashboard is provisioned", func() {
  136. provisioningValidated := false
  137. bus.AddHandler("test", func(cmd *models.IsDashboardProvisionedQuery) error {
  138. provisioningValidated = true
  139. cmd.Result = true
  140. return nil
  141. })
  142. bus.AddHandler("test", func(cmd *models.ValidateDashboardAlertsCommand) error {
  143. return nil
  144. })
  145. bus.AddHandler("test", func(cmd *models.ValidateDashboardBeforeSaveCommand) error {
  146. cmd.Result = &models.ValidateDashboardBeforeSaveResult{}
  147. return nil
  148. })
  149. bus.AddHandler("test", func(cmd *models.SaveProvisionedDashboardCommand) error {
  150. return nil
  151. })
  152. bus.AddHandler("test", func(cmd *models.UpdateDashboardAlertsCommand) error {
  153. return nil
  154. })
  155. dto.Dashboard = models.NewDashboard("Dash")
  156. dto.Dashboard.SetId(3)
  157. dto.User = &models.SignedInUser{UserId: 1}
  158. _, err := service.ImportDashboard(dto)
  159. So(provisioningValidated, ShouldBeTrue)
  160. So(err, ShouldEqual, models.ErrDashboardCannotSaveProvisionedDashboard)
  161. })
  162. })
  163. Convey("Given provisioned dashboard", func() {
  164. result := setupDeleteHandlers(true)
  165. Convey("DeleteProvisionedDashboard should delete it", func() {
  166. err := service.DeleteProvisionedDashboard(1, 1)
  167. So(err, ShouldBeNil)
  168. So(result.deleteWasCalled, ShouldBeTrue)
  169. })
  170. Convey("DeleteDashboard should fail to delete it", func() {
  171. err := service.DeleteDashboard(1, 1)
  172. So(err, ShouldEqual, models.ErrDashboardCannotDeleteProvisionedDashboard)
  173. So(result.deleteWasCalled, ShouldBeFalse)
  174. })
  175. })
  176. Convey("Given non provisioned dashboard", func() {
  177. result := setupDeleteHandlers(false)
  178. Convey("DeleteProvisionedDashboard should delete it", func() {
  179. err := service.DeleteProvisionedDashboard(1, 1)
  180. So(err, ShouldBeNil)
  181. So(result.deleteWasCalled, ShouldBeTrue)
  182. })
  183. Convey("DeleteDashboard should delete it", func() {
  184. err := service.DeleteDashboard(1, 1)
  185. So(err, ShouldBeNil)
  186. So(result.deleteWasCalled, ShouldBeTrue)
  187. })
  188. })
  189. Reset(func() {
  190. guardian.New = origNewDashboardGuardian
  191. })
  192. })
  193. }
  194. type Result struct {
  195. deleteWasCalled bool
  196. }
  197. func setupDeleteHandlers(provisioned bool) *Result {
  198. bus.AddHandler("test", func(cmd *models.IsDashboardProvisionedQuery) error {
  199. cmd.Result = provisioned
  200. return nil
  201. })
  202. result := &Result{}
  203. bus.AddHandler("test", func(cmd *models.DeleteDashboardCommand) error {
  204. So(cmd.Id, ShouldEqual, 1)
  205. So(cmd.OrgId, ShouldEqual, 1)
  206. result.deleteWasCalled = true
  207. return nil
  208. })
  209. return result
  210. }