From 706b301285545307197e293d0c3c751b0481ed2e Mon Sep 17 00:00:00 2001 From: Kristin Laemmert Date: Wed, 2 Nov 2022 09:15:50 -0400 Subject: [PATCH] feat(nested folders): add CountDashboardsInFolder (#57847) * feat(nested folders): add CountDashboardsInFolder This commit adds a new method to the Dashboard service and stores: CountDashboardsInFolder. The command struct takes a folderUID, but the store implementation still depends on the parent folder ID. This is temporary; eventually we will replace all references to FolderIDs (associated with Dashboards) with folder UIDs. There are some unfortunate additional test changes that were necessary after generating the service & store mocks; it looks like that hasn't been generated since the last change(s). * more test updates * don't forget the service test * that didn't end up used, so bye for now * agree to disagree with the linter --- pkg/api/dashboard_test.go | 2 +- pkg/services/dashboards/dashboard.go | 5 + .../dashboards/dashboard_provisioning_mock.go | 49 +++---- .../dashboards/dashboard_service_mock.go | 49 +++++-- pkg/services/dashboards/database/database.go | 15 +++ .../dashboards/database/database_test.go | 16 +++ pkg/services/dashboards/folder_store_mock.go | 13 +- pkg/services/dashboards/models.go | 13 ++ .../dashboards/service/dashboard_service.go | 15 +++ .../service/dashboard_service_test.go | 48 ++++--- pkg/services/dashboards/store_mock.go | 121 +++++++++++------- pkg/services/folder/folderimpl/folder_test.go | 10 +- .../dashboards/file_reader_test.go | 24 ++-- .../provisioning/dashboards/validator_test.go | 9 +- 14 files changed, 271 insertions(+), 118 deletions(-) diff --git a/pkg/api/dashboard_test.go b/pkg/api/dashboard_test.go index bc7dfdd407c..b4fc7c52e3c 100644 --- a/pkg/api/dashboard_test.go +++ b/pkg/api/dashboard_test.go @@ -920,7 +920,7 @@ func TestDashboardAPIEndpoint(t *testing.T) { t.Run("Given provisioned dashboard", func(t *testing.T) { mockSQLStore := mockstore.NewSQLStoreMock() dashboardStore := dashboards.NewFakeDashboardStore(t) - dashboardStore.On("GetProvisionedDataByDashboardID", mock.Anything).Return(&models.DashboardProvisioning{ExternalId: "/dashboard1.json"}, nil).Once() + dashboardStore.On("GetProvisionedDataByDashboardID", mock.Anything, mock.AnythingOfType("int64")).Return(&models.DashboardProvisioning{ExternalId: "/dashboard1.json"}, nil).Once() teamService := &teamtest.FakeService{} dashboardService := dashboards.NewFakeDashboardService(t) diff --git a/pkg/services/dashboards/dashboard.go b/pkg/services/dashboards/dashboard.go index d5aba4a4cb6..82f4eaa0850 100644 --- a/pkg/services/dashboards/dashboard.go +++ b/pkg/services/dashboards/dashboard.go @@ -26,6 +26,7 @@ type DashboardService interface { SearchDashboards(ctx context.Context, query *models.FindPersistedDashboardsQuery) error UpdateDashboardACL(ctx context.Context, uid int64, items []*models.DashboardACL) error DeleteACLByUser(ctx context.Context, userID int64) error + CountDashboardsInFolder(ctx context.Context, query *CountDashboardsInFolderQuery) (int64, error) } // PluginService is a service for operating on plugin dashboards. @@ -76,6 +77,10 @@ type Store interface { ValidateDashboardBeforeSave(ctx context.Context, dashboard *models.Dashboard, overwrite bool) (bool, error) DeleteACLByUser(context.Context, int64) error + // CountDashboardsInFolder returns the number of dashboards associated with + // the given parent folder ID. + CountDashboardsInFolder(ctx context.Context, request *CountDashboardsInFolderRequest) (int64, error) + FolderStore } diff --git a/pkg/services/dashboards/dashboard_provisioning_mock.go b/pkg/services/dashboards/dashboard_provisioning_mock.go index adbbbbfd17f..32493be45a7 100644 --- a/pkg/services/dashboards/dashboard_provisioning_mock.go +++ b/pkg/services/dashboards/dashboard_provisioning_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.12.1. DO NOT EDIT. +// Code generated by mockery v2.14.0. DO NOT EDIT. package dashboards @@ -7,8 +7,6 @@ import ( models "github.com/grafana/grafana/pkg/models" mock "github.com/stretchr/testify/mock" - - testing "testing" ) // FakeDashboardProvisioning is an autogenerated mock type for the DashboardProvisioningService type @@ -44,13 +42,13 @@ func (_m *FakeDashboardProvisioning) DeleteProvisionedDashboard(ctx context.Cont return r0 } -// GetProvisionedDashboardData provides a mock function with given fields: name +// GetProvisionedDashboardData provides a mock function with given fields: ctx, name func (_m *FakeDashboardProvisioning) GetProvisionedDashboardData(ctx context.Context, name string) ([]*models.DashboardProvisioning, error) { - ret := _m.Called(name) + ret := _m.Called(ctx, name) var r0 []*models.DashboardProvisioning - if rf, ok := ret.Get(0).(func(string) []*models.DashboardProvisioning); ok { - r0 = rf(name) + if rf, ok := ret.Get(0).(func(context.Context, string) []*models.DashboardProvisioning); ok { + r0 = rf(ctx, name) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]*models.DashboardProvisioning) @@ -58,8 +56,8 @@ func (_m *FakeDashboardProvisioning) GetProvisionedDashboardData(ctx context.Con } var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, name) } else { r1 = ret.Error(1) } @@ -67,13 +65,13 @@ func (_m *FakeDashboardProvisioning) GetProvisionedDashboardData(ctx context.Con return r0, r1 } -// GetProvisionedDashboardDataByDashboardID provides a mock function with given fields: dashboardID +// GetProvisionedDashboardDataByDashboardID provides a mock function with given fields: ctx, dashboardID func (_m *FakeDashboardProvisioning) GetProvisionedDashboardDataByDashboardID(ctx context.Context, dashboardID int64) (*models.DashboardProvisioning, error) { - ret := _m.Called(dashboardID) + ret := _m.Called(ctx, dashboardID) var r0 *models.DashboardProvisioning - if rf, ok := ret.Get(0).(func(int64) *models.DashboardProvisioning); ok { - r0 = rf(dashboardID) + if rf, ok := ret.Get(0).(func(context.Context, int64) *models.DashboardProvisioning); ok { + r0 = rf(ctx, dashboardID) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*models.DashboardProvisioning) @@ -81,8 +79,8 @@ func (_m *FakeDashboardProvisioning) GetProvisionedDashboardDataByDashboardID(ct } var r1 error - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(dashboardID) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, dashboardID) } else { r1 = ret.Error(1) } @@ -90,13 +88,13 @@ func (_m *FakeDashboardProvisioning) GetProvisionedDashboardDataByDashboardID(ct return r0, r1 } -// GetProvisionedDashboardDataByDashboardUID provides a mock function with given fields: orgID, dashboardUID +// GetProvisionedDashboardDataByDashboardUID provides a mock function with given fields: ctx, orgID, dashboardUID func (_m *FakeDashboardProvisioning) GetProvisionedDashboardDataByDashboardUID(ctx context.Context, orgID int64, dashboardUID string) (*models.DashboardProvisioning, error) { - ret := _m.Called(orgID, dashboardUID) + ret := _m.Called(ctx, orgID, dashboardUID) var r0 *models.DashboardProvisioning - if rf, ok := ret.Get(0).(func(int64, string) *models.DashboardProvisioning); ok { - r0 = rf(orgID, dashboardUID) + if rf, ok := ret.Get(0).(func(context.Context, int64, string) *models.DashboardProvisioning); ok { + r0 = rf(ctx, orgID, dashboardUID) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*models.DashboardProvisioning) @@ -104,8 +102,8 @@ func (_m *FakeDashboardProvisioning) GetProvisionedDashboardDataByDashboardUID(c } var r1 error - if rf, ok := ret.Get(1).(func(int64, string) error); ok { - r1 = rf(orgID, dashboardUID) + if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok { + r1 = rf(ctx, orgID, dashboardUID) } else { r1 = ret.Error(1) } @@ -173,8 +171,13 @@ func (_m *FakeDashboardProvisioning) UnprovisionDashboard(ctx context.Context, d return r0 } -// NewFakeDashboardProvisioning creates a new instance of FakeDashboardProvisioning. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations. -func NewFakeDashboardProvisioning(t testing.TB) *FakeDashboardProvisioning { +type mockConstructorTestingTNewFakeDashboardProvisioning interface { + mock.TestingT + Cleanup(func()) +} + +// NewFakeDashboardProvisioning creates a new instance of FakeDashboardProvisioning. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewFakeDashboardProvisioning(t mockConstructorTestingTNewFakeDashboardProvisioning) *FakeDashboardProvisioning { mock := &FakeDashboardProvisioning{} mock.Mock.Test(t) diff --git a/pkg/services/dashboards/dashboard_service_mock.go b/pkg/services/dashboards/dashboard_service_mock.go index 4a52a07335e..180dd8016bd 100644 --- a/pkg/services/dashboards/dashboard_service_mock.go +++ b/pkg/services/dashboards/dashboard_service_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.12.1. DO NOT EDIT. +// Code generated by mockery v2.14.0. DO NOT EDIT. package dashboards @@ -7,14 +7,11 @@ import ( models "github.com/grafana/grafana/pkg/models" mock "github.com/stretchr/testify/mock" - - testing "testing" ) // FakeDashboardService is an autogenerated mock type for the DashboardService type type FakeDashboardService struct { mock.Mock - ExpectedError error } // BuildSaveDashboardCommand provides a mock function with given fields: ctx, dto, shouldValidateAlerts, validateProvisionedDashboard @@ -40,6 +37,41 @@ func (_m *FakeDashboardService) BuildSaveDashboardCommand(ctx context.Context, d return r0, r1 } +// CountDashboardsInFolder provides a mock function with given fields: ctx, query +func (_m *FakeDashboardService) CountDashboardsInFolder(ctx context.Context, query *CountDashboardsInFolderQuery) (int64, error) { + ret := _m.Called(ctx, query) + + var r0 int64 + if rf, ok := ret.Get(0).(func(context.Context, *CountDashboardsInFolderQuery) int64); ok { + r0 = rf(ctx, query) + } else { + r0 = ret.Get(0).(int64) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *CountDashboardsInFolderQuery) error); ok { + r1 = rf(ctx, query) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteACLByUser provides a mock function with given fields: ctx, userID +func (_m *FakeDashboardService) DeleteACLByUser(ctx context.Context, userID int64) error { + ret := _m.Called(ctx, userID) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok { + r0 = rf(ctx, userID) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // DeleteDashboard provides a mock function with given fields: ctx, dashboardId, orgId func (_m *FakeDashboardService) DeleteDashboard(ctx context.Context, dashboardId int64, orgId int64) error { ret := _m.Called(ctx, dashboardId, orgId) @@ -263,12 +295,13 @@ func (_m *FakeDashboardService) UpdateDashboardACL(ctx context.Context, uid int6 return r0 } -func (_m *FakeDashboardService) DeleteACLByUser(ctx context.Context, userID int64) error { - return _m.ExpectedError +type mockConstructorTestingTNewFakeDashboardService interface { + mock.TestingT + Cleanup(func()) } -// NewFakeDashboardService creates a new instance of FakeDashboardService. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations. -func NewFakeDashboardService(t testing.TB) *FakeDashboardService { +// NewFakeDashboardService creates a new instance of FakeDashboardService. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewFakeDashboardService(t mockConstructorTestingTNewFakeDashboardService) *FakeDashboardService { mock := &FakeDashboardService{} mock.Mock.Test(t) diff --git a/pkg/services/dashboards/database/database.go b/pkg/services/dashboards/database/database.go index 016cf4afcb3..321e7eab7c0 100644 --- a/pkg/services/dashboards/database/database.go +++ b/pkg/services/dashboards/database/database.go @@ -1017,3 +1017,18 @@ func (d *DashboardStore) GetDashboardTags(ctx context.Context, query *models.Get return err }) } + +// This will be updated to take CountDashboardsInFolderQuery as an argument and +// lookup dashboards using the ParentFolderUID when the NestedFolder +// implementation is complete. +func (d *DashboardStore) CountDashboardsInFolder( + ctx context.Context, req *dashboards.CountDashboardsInFolderRequest) (int64, error) { + var dashboards = make([]*models.Dashboard, 0) + err := d.store.WithDbSession(ctx, func(sess *db.Session) error { + session := sess.In("folder_id", req.FolderID).In("org_id", req.OrgID). + In("is_folder", d.store.GetDialect().BooleanStr(false)) + err := session.Find(&dashboards) + return err + }) + return int64(len(dashboards)), err +} diff --git a/pkg/services/dashboards/database/database_test.go b/pkg/services/dashboards/database/database_test.go index fc0512c95e3..39222b6414e 100644 --- a/pkg/services/dashboards/database/database_test.go +++ b/pkg/services/dashboards/database/database_test.go @@ -560,6 +560,22 @@ func TestIntegrationDashboardDataAccess(t *testing.T) { require.Equal(t, len(res), 1) require.Equal(t, res[0].Title, "starred dash") }) + + t.Run("Can count dashboards by parent folder", func(t *testing.T) { + setup() + // setup() saves one dashboard in the general folder and two in the "savedFolder". + count, err := dashboardStore.CountDashboardsInFolder( + context.Background(), + &dashboards.CountDashboardsInFolderRequest{FolderID: 0, OrgID: 1}) + require.NoError(t, err) + require.Equal(t, int64(1), count) + + count, err = dashboardStore.CountDashboardsInFolder( + context.Background(), + &dashboards.CountDashboardsInFolderRequest{FolderID: savedFolder.Id, OrgID: 1}) + require.NoError(t, err) + require.Equal(t, int64(2), count) + }) } func TestIntegrationDashboardDataAccessGivenPluginWithImportedDashboards(t *testing.T) { diff --git a/pkg/services/dashboards/folder_store_mock.go b/pkg/services/dashboards/folder_store_mock.go index d44e60c4732..4c279cf758a 100644 --- a/pkg/services/dashboards/folder_store_mock.go +++ b/pkg/services/dashboards/folder_store_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.12.1. DO NOT EDIT. +// Code generated by mockery v2.14.0. DO NOT EDIT. package dashboards @@ -7,8 +7,6 @@ import ( models "github.com/grafana/grafana/pkg/models" mock "github.com/stretchr/testify/mock" - - testing "testing" ) // FakeFolderStore is an autogenerated mock type for the FolderStore type @@ -85,8 +83,13 @@ func (_m *FakeFolderStore) GetFolderByUID(ctx context.Context, orgID int64, uid return r0, r1 } -// NewFakeFolderStore creates a new instance of FakeFolderStore. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations. -func NewFakeFolderStore(t testing.TB) *FakeFolderStore { +type mockConstructorTestingTNewFakeFolderStore interface { + mock.TestingT + Cleanup(func()) +} + +// NewFakeFolderStore creates a new instance of FakeFolderStore. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewFakeFolderStore(t mockConstructorTestingTNewFakeFolderStore) *FakeFolderStore { mock := &FakeFolderStore{} mock.Mock.Test(t) diff --git a/pkg/services/dashboards/models.go b/pkg/services/dashboards/models.go index 5b2b08e2a3e..21c184cff5c 100644 --- a/pkg/services/dashboards/models.go +++ b/pkg/services/dashboards/models.go @@ -29,3 +29,16 @@ type DashboardSearchProjection struct { FolderTitle string SortMeta int64 } + +type CountDashboardsInFolderQuery struct { + FolderUID string +} + +// Note for reviewers: I wasn't sure what to name this. It's not actually a DTO +// CountDashboardsInFolderRequest is the request passed from the service to the +// store layer. The FolderID will be replaced with FolderUID when dashboards are +// updated with parent folder UIDs. +type CountDashboardsInFolderRequest struct { + FolderID int64 + OrgID int64 +} diff --git a/pkg/services/dashboards/service/dashboard_service.go b/pkg/services/dashboards/service/dashboard_service.go index b74ba9b7d26..671dc054888 100644 --- a/pkg/services/dashboards/service/dashboard_service.go +++ b/pkg/services/dashboards/service/dashboard_service.go @@ -8,6 +8,7 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend/gtime" + "github.com/grafana/grafana/pkg/infra/appcontext" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/accesscontrol" @@ -587,3 +588,17 @@ func (dr *DashboardServiceImpl) GetDashboardTags(ctx context.Context, query *mod func (dr *DashboardServiceImpl) DeleteACLByUser(ctx context.Context, userID int64) error { return dr.dashboardStore.DeleteACLByUser(ctx, userID) } + +func (dr DashboardServiceImpl) CountDashboardsInFolder(ctx context.Context, query *dashboards.CountDashboardsInFolderQuery) (int64, error) { + u, err := appcontext.User(ctx) + if err != nil { + return 0, err + } + + folder, err := dr.dashboardStore.GetFolderByUID(ctx, u.OrgID, query.FolderUID) + if err != nil { + return 0, err + } + + return dr.dashboardStore.CountDashboardsInFolder(ctx, &dashboards.CountDashboardsInFolderRequest{FolderID: folder.Id, OrgID: u.OrgID}) +} diff --git a/pkg/services/dashboards/service/dashboard_service_test.go b/pkg/services/dashboards/service/dashboard_service_test.go index 82e6699ff01..fac1f73b8fa 100644 --- a/pkg/services/dashboards/service/dashboard_service_test.go +++ b/pkg/services/dashboards/service/dashboard_service_test.go @@ -10,6 +10,7 @@ import ( "github.com/xorcare/pointer" "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/infra/appcontext" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/dashboards" @@ -80,7 +81,7 @@ func TestDashboardService(t *testing.T) { dto.User = &user.SignedInUser{} if tc.Error == nil { - fakeStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything).Return(true, nil).Once() + fakeStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything, mock.AnythingOfType("bool")).Return(true, nil).Once() } _, err := service.BuildSaveDashboardCommand(context.Background(), dto, true, false) require.Equal(t, err, tc.Error) @@ -88,8 +89,8 @@ func TestDashboardService(t *testing.T) { }) t.Run("Should return validation error if dashboard is provisioned", func(t *testing.T) { - fakeStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything).Return(true, nil).Once() - fakeStore.On("GetProvisionedDataByDashboardID", mock.Anything).Return(&models.DashboardProvisioning{}, nil).Once() + fakeStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything, mock.AnythingOfType("bool")).Return(true, nil).Once() + fakeStore.On("GetProvisionedDataByDashboardID", mock.Anything, mock.AnythingOfType("int64")).Return(&models.DashboardProvisioning{}, nil).Once() dto.Dashboard = models.NewDashboard("Dash") dto.Dashboard.SetId(3) @@ -99,8 +100,8 @@ func TestDashboardService(t *testing.T) { }) t.Run("Should not return validation error if dashboard is provisioned but UI updates allowed", func(t *testing.T) { - fakeStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything).Return(true, nil).Once() - fakeStore.On("SaveDashboard", mock.Anything).Return(&models.Dashboard{Data: simplejson.New()}, nil).Once() + fakeStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything, mock.AnythingOfType("bool")).Return(true, nil).Once() + fakeStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("models.SaveDashboardCommand")).Return(&models.Dashboard{Data: simplejson.New()}, nil).Once() dto.Dashboard = models.NewDashboard("Dash") dto.Dashboard.SetId(3) @@ -124,9 +125,9 @@ func TestDashboardService(t *testing.T) { } }) - fakeStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything).Return(true, nil).Once() - fakeStore.On("GetProvisionedDataByDashboardID", mock.Anything).Return(nil, nil).Once() - fakeStore.On("SaveDashboard", mock.Anything).Return(&models.Dashboard{Data: simplejson.New()}, nil).Once() + fakeStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything, mock.AnythingOfType("bool")).Return(true, nil).Once() + fakeStore.On("GetProvisionedDataByDashboardID", mock.Anything, mock.AnythingOfType("int64")).Return(nil, nil).Once() + fakeStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("models.SaveDashboardCommand")).Return(&models.Dashboard{Data: simplejson.New()}, nil).Once() fakeStore.On("SaveAlerts", mock.Anything, mock.Anything, mock.Anything).Return(errors.New("alert validation error")).Once() dto.Dashboard = models.NewDashboard("Dash") @@ -141,8 +142,8 @@ func TestDashboardService(t *testing.T) { dto := &dashboards.SaveDashboardDTO{} t.Run("Should not return validation error if dashboard is provisioned", func(t *testing.T) { - fakeStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything).Return(true, nil).Once() - fakeStore.On("SaveProvisionedDashboard", mock.Anything, mock.Anything).Return(&models.Dashboard{Data: simplejson.New()}, nil).Once() + fakeStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything, mock.AnythingOfType("bool")).Return(true, nil).Once() + fakeStore.On("SaveProvisionedDashboard", mock.Anything, mock.AnythingOfType("models.SaveDashboardCommand"), mock.AnythingOfType("*models.DashboardProvisioning")).Return(&models.Dashboard{Data: simplejson.New()}, nil).Once() dto.Dashboard = models.NewDashboard("Dash") dto.Dashboard.SetId(3) @@ -152,8 +153,8 @@ func TestDashboardService(t *testing.T) { }) t.Run("Should override invalid refresh interval if dashboard is provisioned", func(t *testing.T) { - fakeStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything).Return(true, nil).Once() - fakeStore.On("SaveProvisionedDashboard", mock.Anything, mock.Anything).Return(&models.Dashboard{Data: simplejson.New()}, nil).Once() + fakeStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything, mock.AnythingOfType("bool")).Return(true, nil).Once() + fakeStore.On("SaveProvisionedDashboard", mock.Anything, mock.AnythingOfType("models.SaveDashboardCommand"), mock.AnythingOfType("*models.DashboardProvisioning")).Return(&models.Dashboard{Data: simplejson.New()}, nil).Once() oldRefreshInterval := setting.MinRefreshInterval setting.MinRefreshInterval = "5m" @@ -173,8 +174,8 @@ func TestDashboardService(t *testing.T) { dto := &dashboards.SaveDashboardDTO{} t.Run("Should return validation error if dashboard is provisioned", func(t *testing.T) { - fakeStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything).Return(true, nil).Once() - fakeStore.On("GetProvisionedDataByDashboardID", mock.Anything).Return(&models.DashboardProvisioning{}, nil).Once() + fakeStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything, mock.AnythingOfType("bool")).Return(true, nil).Once() + fakeStore.On("GetProvisionedDataByDashboardID", mock.Anything, mock.AnythingOfType("int64")).Return(&models.DashboardProvisioning{}, nil).Once() dto.Dashboard = models.NewDashboard("Dash") dto.Dashboard.SetId(3) @@ -193,7 +194,7 @@ func TestDashboardService(t *testing.T) { }) t.Run("DeleteDashboard should fail to delete it when provisioning information is missing", func(t *testing.T) { - fakeStore.On("GetProvisionedDataByDashboardID", mock.Anything).Return(&models.DashboardProvisioning{}, nil).Once() + fakeStore.On("GetProvisionedDataByDashboardID", mock.Anything, mock.AnythingOfType("int64")).Return(&models.DashboardProvisioning{}, nil).Once() err := service.DeleteDashboard(context.Background(), 1, 1) require.Equal(t, err, dashboards.ErrDashboardCannotDeleteProvisionedDashboard) }) @@ -210,7 +211,7 @@ func TestDashboardService(t *testing.T) { t.Run("DeleteDashboard should delete it", func(t *testing.T) { args := &models.DeleteDashboardCommand{OrgId: 1, Id: 1} fakeStore.On("DeleteDashboard", mock.Anything, args).Return(nil).Once() - fakeStore.On("GetProvisionedDataByDashboardID", mock.Anything).Return(nil, nil).Once() + fakeStore.On("GetProvisionedDataByDashboardID", mock.Anything, mock.AnythingOfType("int64")).Return(nil, nil).Once() err := service.DeleteDashboard(context.Background(), 1, 1) require.NoError(t, err) }) @@ -223,10 +224,25 @@ func TestDashboardService(t *testing.T) { // require.NoError(t, err) // }) }) + + t.Run("Count dashboards in folder", func(t *testing.T) { + fakeStore.On("GetFolderByUID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).Return(&models.Folder{}, nil) + fakeStore.On("CountDashboardsInFolder", mock.Anything, mock.AnythingOfType("*dashboards.CountDashboardsInFolderRequest")).Return(int64(3), nil) + + // set up a ctx with signed in user + ctx := context.Background() + usr := &user.SignedInUser{UserID: 1} + ctx = appcontext.WithUser(ctx, usr) + + count, err := service.CountDashboardsInFolder(ctx, &dashboards.CountDashboardsInFolderQuery{FolderUID: "i am a folder"}) + require.NoError(t, err) + require.Equal(t, int64(3), count) + }) }) t.Run("Delete user by acl", func(t *testing.T) { fakeStore := dashboards.FakeDashboardStore{} + fakeStore.On("DeleteACLByUser", mock.Anything, mock.AnythingOfType("int64")).Return(nil) defer fakeStore.AssertExpectations(t) service := &DashboardServiceImpl{ diff --git a/pkg/services/dashboards/store_mock.go b/pkg/services/dashboards/store_mock.go index cd30c34a745..5824d5332db 100644 --- a/pkg/services/dashboards/store_mock.go +++ b/pkg/services/dashboards/store_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.12.1. DO NOT EDIT. +// Code generated by mockery v2.14.0. DO NOT EDIT. package dashboards @@ -7,14 +7,46 @@ import ( models "github.com/grafana/grafana/pkg/models" mock "github.com/stretchr/testify/mock" - - testing "testing" ) // FakeDashboardStore is an autogenerated mock type for the Store type type FakeDashboardStore struct { mock.Mock - ExpectedError error +} + +// CountDashboardsInFolder provides a mock function with given fields: ctx, request +func (_m *FakeDashboardStore) CountDashboardsInFolder(ctx context.Context, request *CountDashboardsInFolderRequest) (int64, error) { + ret := _m.Called(ctx, request) + + var r0 int64 + if rf, ok := ret.Get(0).(func(context.Context, *CountDashboardsInFolderRequest) int64); ok { + r0 = rf(ctx, request) + } else { + r0 = ret.Get(0).(int64) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *CountDashboardsInFolderRequest) error); ok { + r1 = rf(ctx, request) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteACLByUser provides a mock function with given fields: _a0, _a1 +func (_m *FakeDashboardStore) DeleteACLByUser(_a0 context.Context, _a1 int64) error { + ret := _m.Called(_a0, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 } // DeleteDashboard provides a mock function with given fields: ctx, cmd @@ -230,13 +262,13 @@ func (_m *FakeDashboardStore) GetFolderByUID(ctx context.Context, orgID int64, u return r0, r1 } -// GetProvisionedDashboardData provides a mock function with given fields: name +// GetProvisionedDashboardData provides a mock function with given fields: ctx, name func (_m *FakeDashboardStore) GetProvisionedDashboardData(ctx context.Context, name string) ([]*models.DashboardProvisioning, error) { - ret := _m.Called(name) + ret := _m.Called(ctx, name) var r0 []*models.DashboardProvisioning - if rf, ok := ret.Get(0).(func(string) []*models.DashboardProvisioning); ok { - r0 = rf(name) + if rf, ok := ret.Get(0).(func(context.Context, string) []*models.DashboardProvisioning); ok { + r0 = rf(ctx, name) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]*models.DashboardProvisioning) @@ -244,8 +276,8 @@ func (_m *FakeDashboardStore) GetProvisionedDashboardData(ctx context.Context, n } var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, name) } else { r1 = ret.Error(1) } @@ -253,13 +285,13 @@ func (_m *FakeDashboardStore) GetProvisionedDashboardData(ctx context.Context, n return r0, r1 } -// GetProvisionedDataByDashboardID provides a mock function with given fields: dashboardID +// GetProvisionedDataByDashboardID provides a mock function with given fields: ctx, dashboardID func (_m *FakeDashboardStore) GetProvisionedDataByDashboardID(ctx context.Context, dashboardID int64) (*models.DashboardProvisioning, error) { - ret := _m.Called(dashboardID) + ret := _m.Called(ctx, dashboardID) var r0 *models.DashboardProvisioning - if rf, ok := ret.Get(0).(func(int64) *models.DashboardProvisioning); ok { - r0 = rf(dashboardID) + if rf, ok := ret.Get(0).(func(context.Context, int64) *models.DashboardProvisioning); ok { + r0 = rf(ctx, dashboardID) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*models.DashboardProvisioning) @@ -267,8 +299,8 @@ func (_m *FakeDashboardStore) GetProvisionedDataByDashboardID(ctx context.Contex } var r1 error - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(dashboardID) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, dashboardID) } else { r1 = ret.Error(1) } @@ -276,13 +308,13 @@ func (_m *FakeDashboardStore) GetProvisionedDataByDashboardID(ctx context.Contex return r0, r1 } -// GetProvisionedDataByDashboardUID provides a mock function with given fields: orgID, dashboardUID +// GetProvisionedDataByDashboardUID provides a mock function with given fields: ctx, orgID, dashboardUID func (_m *FakeDashboardStore) GetProvisionedDataByDashboardUID(ctx context.Context, orgID int64, dashboardUID string) (*models.DashboardProvisioning, error) { - ret := _m.Called(orgID, dashboardUID) + ret := _m.Called(ctx, orgID, dashboardUID) var r0 *models.DashboardProvisioning - if rf, ok := ret.Get(0).(func(int64, string) *models.DashboardProvisioning); ok { - r0 = rf(orgID, dashboardUID) + if rf, ok := ret.Get(0).(func(context.Context, int64, string) *models.DashboardProvisioning); ok { + r0 = rf(ctx, orgID, dashboardUID) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*models.DashboardProvisioning) @@ -290,8 +322,8 @@ func (_m *FakeDashboardStore) GetProvisionedDataByDashboardUID(ctx context.Conte } var r1 error - if rf, ok := ret.Get(1).(func(int64, string) error); ok { - r1 = rf(orgID, dashboardUID) + if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok { + r1 = rf(ctx, orgID, dashboardUID) } else { r1 = ret.Error(1) } @@ -341,13 +373,13 @@ func (_m *FakeDashboardStore) SaveAlerts(ctx context.Context, dashID int64, aler return r0 } -// SaveDashboard provides a mock function with given fields: cmd +// SaveDashboard provides a mock function with given fields: ctx, cmd func (_m *FakeDashboardStore) SaveDashboard(ctx context.Context, cmd models.SaveDashboardCommand) (*models.Dashboard, error) { - ret := _m.Called(cmd) + ret := _m.Called(ctx, cmd) var r0 *models.Dashboard - if rf, ok := ret.Get(0).(func(models.SaveDashboardCommand) *models.Dashboard); ok { - r0 = rf(cmd) + if rf, ok := ret.Get(0).(func(context.Context, models.SaveDashboardCommand) *models.Dashboard); ok { + r0 = rf(ctx, cmd) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*models.Dashboard) @@ -355,8 +387,8 @@ func (_m *FakeDashboardStore) SaveDashboard(ctx context.Context, cmd models.Save } var r1 error - if rf, ok := ret.Get(1).(func(models.SaveDashboardCommand) error); ok { - r1 = rf(cmd) + if rf, ok := ret.Get(1).(func(context.Context, models.SaveDashboardCommand) error); ok { + r1 = rf(ctx, cmd) } else { r1 = ret.Error(1) } @@ -364,13 +396,13 @@ func (_m *FakeDashboardStore) SaveDashboard(ctx context.Context, cmd models.Save return r0, r1 } -// SaveProvisionedDashboard provides a mock function with given fields: cmd, provisioning +// SaveProvisionedDashboard provides a mock function with given fields: ctx, cmd, provisioning func (_m *FakeDashboardStore) SaveProvisionedDashboard(ctx context.Context, cmd models.SaveDashboardCommand, provisioning *models.DashboardProvisioning) (*models.Dashboard, error) { - ret := _m.Called(cmd, provisioning) + ret := _m.Called(ctx, cmd, provisioning) var r0 *models.Dashboard - if rf, ok := ret.Get(0).(func(models.SaveDashboardCommand, *models.DashboardProvisioning) *models.Dashboard); ok { - r0 = rf(cmd, provisioning) + if rf, ok := ret.Get(0).(func(context.Context, models.SaveDashboardCommand, *models.DashboardProvisioning) *models.Dashboard); ok { + r0 = rf(ctx, cmd, provisioning) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*models.Dashboard) @@ -378,8 +410,8 @@ func (_m *FakeDashboardStore) SaveProvisionedDashboard(ctx context.Context, cmd } var r1 error - if rf, ok := ret.Get(1).(func(models.SaveDashboardCommand, *models.DashboardProvisioning) error); ok { - r1 = rf(cmd, provisioning) + if rf, ok := ret.Get(1).(func(context.Context, models.SaveDashboardCommand, *models.DashboardProvisioning) error); ok { + r1 = rf(ctx, cmd, provisioning) } else { r1 = ret.Error(1) } @@ -415,20 +447,20 @@ func (_m *FakeDashboardStore) UpdateDashboardACL(ctx context.Context, uid int64, return r0 } -// ValidateDashboardBeforeSave provides a mock function with given fields: dashboard, overwrite +// ValidateDashboardBeforeSave provides a mock function with given fields: ctx, dashboard, overwrite func (_m *FakeDashboardStore) ValidateDashboardBeforeSave(ctx context.Context, dashboard *models.Dashboard, overwrite bool) (bool, error) { - ret := _m.Called(dashboard, overwrite) + ret := _m.Called(ctx, dashboard, overwrite) var r0 bool - if rf, ok := ret.Get(0).(func(*models.Dashboard, bool) bool); ok { - r0 = rf(dashboard, overwrite) + if rf, ok := ret.Get(0).(func(context.Context, *models.Dashboard, bool) bool); ok { + r0 = rf(ctx, dashboard, overwrite) } else { r0 = ret.Get(0).(bool) } var r1 error - if rf, ok := ret.Get(1).(func(*models.Dashboard, bool) error); ok { - r1 = rf(dashboard, overwrite) + if rf, ok := ret.Get(1).(func(context.Context, *models.Dashboard, bool) error); ok { + r1 = rf(ctx, dashboard, overwrite) } else { r1 = ret.Error(1) } @@ -436,12 +468,13 @@ func (_m *FakeDashboardStore) ValidateDashboardBeforeSave(ctx context.Context, d return r0, r1 } -func (_m *FakeDashboardStore) DeleteACLByUser(ctx context.Context, userID int64) error { - return _m.ExpectedError +type mockConstructorTestingTNewFakeDashboardStore interface { + mock.TestingT + Cleanup(func()) } -// NewFakeDashboardStore creates a new instance of FakeDashboardStore. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations. -func NewFakeDashboardStore(t testing.TB) *FakeDashboardStore { +// NewFakeDashboardStore creates a new instance of FakeDashboardStore. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewFakeDashboardStore(t mockConstructorTestingTNewFakeDashboardStore) *FakeDashboardStore { mock := &FakeDashboardStore{} mock.Mock.Test(t) diff --git a/pkg/services/folder/folderimpl/folder_test.go b/pkg/services/folder/folderimpl/folder_test.go index 45246154880..7cb51195980 100644 --- a/pkg/services/folder/folderimpl/folder_test.go +++ b/pkg/services/folder/folderimpl/folder_test.go @@ -95,7 +95,7 @@ func TestIntegrationFolderService(t *testing.T) { }) t.Run("When creating folder should return access denied error", func(t *testing.T) { - store.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything).Return(true, nil).Times(2) + store.On("ValidateDashboardBeforeSave", mock.Anything, mock.AnythingOfType("*models.Dashboard"), mock.AnythingOfType("bool")).Return(true, nil).Times(2) _, err := service.CreateFolder(context.Background(), usr, orgID, folder.Title, folderUID) require.Equal(t, err, dashboards.ErrFolderAccessDenied) }) @@ -133,8 +133,8 @@ func TestIntegrationFolderService(t *testing.T) { dash.Id = rand.Int63() f := models.DashboardToFolder(dash) - store.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything).Return(true, nil) - store.On("SaveDashboard", mock.Anything).Return(dash, nil).Once() + store.On("ValidateDashboardBeforeSave", mock.Anything, mock.AnythingOfType("*models.Dashboard"), mock.AnythingOfType("bool")).Return(true, nil) + store.On("SaveDashboard", mock.Anything, mock.AnythingOfType("models.SaveDashboardCommand")).Return(dash, nil).Once() store.On("GetFolderByID", mock.Anything, orgID, dash.Id).Return(f, nil) actualFolder, err := service.CreateFolder(context.Background(), usr, orgID, dash.Title, "") @@ -156,8 +156,8 @@ func TestIntegrationFolderService(t *testing.T) { dashboardFolder.Uid = util.GenerateShortUID() f := models.DashboardToFolder(dashboardFolder) - store.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything).Return(true, nil) - store.On("SaveDashboard", mock.Anything).Return(dashboardFolder, nil) + store.On("ValidateDashboardBeforeSave", mock.Anything, mock.AnythingOfType("*models.Dashboard"), mock.AnythingOfType("bool")).Return(true, nil) + store.On("SaveDashboard", mock.Anything, mock.AnythingOfType("models.SaveDashboardCommand")).Return(dashboardFolder, nil) store.On("GetFolderByID", mock.Anything, orgID, dashboardFolder.Id).Return(f, nil) req := &models.UpdateFolderCommand{ diff --git a/pkg/services/provisioning/dashboards/file_reader_test.go b/pkg/services/provisioning/dashboards/file_reader_test.go index 30eb32e0dca..d29015b88bd 100644 --- a/pkg/services/provisioning/dashboards/file_reader_test.go +++ b/pkg/services/provisioning/dashboards/file_reader_test.go @@ -113,7 +113,7 @@ func TestDashboardFileReader(t *testing.T) { cfg.Options["path"] = defaultDashboards cfg.Folder = "Team A" - fakeService.On("GetProvisionedDashboardData", configName).Return(nil, nil).Once() + fakeService.On("GetProvisionedDashboardData", mock.Anything, configName).Return(nil, nil).Once() fakeService.On("SaveFolderForProvisionedDashboards", mock.Anything, mock.Anything).Return(&models.Dashboard{Id: 1}, nil).Once() fakeService.On("SaveProvisionedDashboard", mock.Anything, mock.Anything, mock.Anything).Return(&models.Dashboard{Id: 2}, nil).Times(2) @@ -130,7 +130,7 @@ func TestDashboardFileReader(t *testing.T) { cfg.Options["path"] = oneDashboard inserted := 0 - fakeService.On("GetProvisionedDashboardData", configName).Return(nil, nil).Once() + fakeService.On("GetProvisionedDashboardData", mock.Anything, configName).Return(nil, nil).Once() fakeService.On("SaveProvisionedDashboard", mock.Anything, mock.Anything, mock.Anything). Return(&models.Dashboard{}, nil).Once(). Run(func(args mock.Arguments) { @@ -172,7 +172,7 @@ func TestDashboardFileReader(t *testing.T) { }, } - fakeService.On("GetProvisionedDashboardData", configName).Return(provisionedDashboard, nil).Once() + fakeService.On("GetProvisionedDashboardData", mock.Anything, configName).Return(provisionedDashboard, nil).Once() reader, err := NewDashboardFileReader(cfg, logger, nil, fakeStore) reader.dashboardProvisioningService = fakeService @@ -199,7 +199,7 @@ func TestDashboardFileReader(t *testing.T) { }, } - fakeService.On("GetProvisionedDashboardData", configName).Return(provisionedDashboard, nil).Once() + fakeService.On("GetProvisionedDashboardData", mock.Anything, configName).Return(provisionedDashboard, nil).Once() fakeService.On("SaveProvisionedDashboard", mock.Anything, mock.Anything, mock.Anything).Return(&models.Dashboard{}, nil).Once() reader, err := NewDashboardFileReader(cfg, logger, nil, fakeStore) @@ -235,7 +235,7 @@ func TestDashboardFileReader(t *testing.T) { }, } - fakeService.On("GetProvisionedDashboardData", configName).Return(provisionedDashboard, nil).Once() + fakeService.On("GetProvisionedDashboardData", mock.Anything, configName).Return(provisionedDashboard, nil).Once() reader, err := NewDashboardFileReader(cfg, logger, nil, fakeStore) reader.dashboardProvisioningService = fakeService @@ -262,7 +262,7 @@ func TestDashboardFileReader(t *testing.T) { }, } - fakeService.On("GetProvisionedDashboardData", configName).Return(provisionedDashboard, nil).Once() + fakeService.On("GetProvisionedDashboardData", mock.Anything, configName).Return(provisionedDashboard, nil).Once() fakeService.On("SaveProvisionedDashboard", mock.Anything, mock.Anything, mock.Anything).Return(&models.Dashboard{}, nil).Once() reader, err := NewDashboardFileReader(cfg, logger, nil, fakeStore) @@ -277,7 +277,7 @@ func TestDashboardFileReader(t *testing.T) { setup() cfg.Options["path"] = containingID - fakeService.On("GetProvisionedDashboardData", configName).Return(nil, nil).Once() + fakeService.On("GetProvisionedDashboardData", mock.Anything, configName).Return(nil, nil).Once() fakeService.On("SaveProvisionedDashboard", mock.Anything, mock.Anything, mock.Anything).Return(&models.Dashboard{}, nil).Once() reader, err := NewDashboardFileReader(cfg, logger, nil, fakeStore) @@ -293,7 +293,7 @@ func TestDashboardFileReader(t *testing.T) { cfg.Options["path"] = foldersFromFilesStructure cfg.Options["foldersFromFilesStructure"] = true - fakeService.On("GetProvisionedDashboardData", configName).Return(nil, nil).Once() + fakeService.On("GetProvisionedDashboardData", mock.Anything, configName).Return(nil, nil).Once() fakeService.On("SaveFolderForProvisionedDashboards", mock.Anything, mock.Anything).Return(&models.Dashboard{}, nil).Times(2) fakeService.On("SaveProvisionedDashboard", mock.Anything, mock.Anything, mock.Anything).Return(&models.Dashboard{}, nil).Times(3) @@ -331,7 +331,7 @@ func TestDashboardFileReader(t *testing.T) { cfg1 := &config{Name: "1", Type: "file", OrgID: 1, Folder: "f1", Options: map[string]interface{}{"path": containingID}} cfg2 := &config{Name: "2", Type: "file", OrgID: 1, Folder: "f2", Options: map[string]interface{}{"path": containingID}} - fakeService.On("GetProvisionedDashboardData", mock.Anything).Return(nil, nil).Times(2) + fakeService.On("GetProvisionedDashboardData", mock.Anything, mock.AnythingOfType("string")).Return(nil, nil).Times(2) fakeService.On("SaveFolderForProvisionedDashboards", mock.Anything, mock.Anything).Return(&models.Dashboard{}, nil).Times(2) fakeService.On("SaveProvisionedDashboard", mock.Anything, mock.Anything, mock.Anything).Return(&models.Dashboard{}, nil).Times(2) @@ -451,15 +451,15 @@ func TestDashboardFileReader(t *testing.T) { t.Run("Missing dashboard should be unprovisioned if DisableDeletion = true", func(t *testing.T) { setupFakeService() - fakeService.On("GetProvisionedDashboardData", configName).Return(provisionedDashboard, nil).Once() + fakeService.On("GetProvisionedDashboardData", mock.Anything, configName).Return(provisionedDashboard, nil).Once() fakeService.On("UnprovisionDashboard", mock.Anything, mock.Anything).Return(nil).Once() fakeService.On("SaveProvisionedDashboard", mock.Anything, mock.Anything, mock.Anything).Return(&models.Dashboard{}, nil).Once() cfg.DisableDeletion = true reader, err := NewDashboardFileReader(cfg, logger, nil, fakeStore) - reader.dashboardProvisioningService = fakeService require.NoError(t, err) + reader.dashboardProvisioningService = fakeService err = reader.walkDisk(context.Background()) require.NoError(t, err) @@ -468,7 +468,7 @@ func TestDashboardFileReader(t *testing.T) { t.Run("Missing dashboard should be deleted if DisableDeletion = false", func(t *testing.T) { setupFakeService() - fakeService.On("GetProvisionedDashboardData", configName).Return(provisionedDashboard, nil).Once() + fakeService.On("GetProvisionedDashboardData", mock.Anything, configName).Return(provisionedDashboard, nil).Once() fakeService.On("SaveProvisionedDashboard", mock.Anything, mock.Anything, mock.Anything).Return(&models.Dashboard{}, nil).Once() fakeService.On("DeleteProvisionedDashboard", mock.Anything, mock.Anything, mock.Anything).Return(nil).Once() diff --git a/pkg/services/provisioning/dashboards/validator_test.go b/pkg/services/provisioning/dashboards/validator_test.go index b3e39e3072d..380bb1db995 100644 --- a/pkg/services/provisioning/dashboards/validator_test.go +++ b/pkg/services/provisioning/dashboards/validator_test.go @@ -5,11 +5,12 @@ import ( "sort" "testing" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/dashboards" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" ) const ( @@ -37,7 +38,7 @@ func TestDuplicatesValidator(t *testing.T) { r, err := NewDashboardFileReader(cfg, logger, nil, fakeStore) require.NoError(t, err) fakeService.On("SaveFolderForProvisionedDashboards", mock.Anything, mock.Anything).Return(&models.Dashboard{}, nil).Times(6) - fakeService.On("GetProvisionedDashboardData", mock.Anything).Return([]*models.DashboardProvisioning{}, nil).Times(4) + fakeService.On("GetProvisionedDashboardData", mock.Anything, mock.AnythingOfType("string")).Return([]*models.DashboardProvisioning{}, nil).Times(4) fakeService.On("SaveProvisionedDashboard", mock.Anything, mock.Anything, mock.Anything).Return(&models.Dashboard{}, nil).Times(5) folderID, err := r.getOrCreateFolderID(context.Background(), cfg, fakeService, folderName) require.NoError(t, err) @@ -151,7 +152,7 @@ func TestDuplicatesValidator(t *testing.T) { t.Run("Duplicates validator should restrict write access only for readers with duplicates", func(t *testing.T) { fakeService.On("SaveFolderForProvisionedDashboards", mock.Anything, mock.Anything).Return(&models.Dashboard{}, nil).Times(5) - fakeService.On("GetProvisionedDashboardData", mock.Anything).Return([]*models.DashboardProvisioning{}, nil).Times(3) + fakeService.On("GetProvisionedDashboardData", mock.Anything, mock.AnythingOfType("string")).Return([]*models.DashboardProvisioning{}, nil).Times(3) fakeService.On("SaveProvisionedDashboard", mock.Anything, mock.Anything, mock.Anything).Return(&models.Dashboard{}, nil).Times(5) fakeStore := &fakeDashboardStore{}