diff --git a/public/app/features/search/constants.ts b/public/app/features/search/constants.ts index a1e5dca3f07..1801eed1f4b 100644 --- a/public/app/features/search/constants.ts +++ b/public/app/features/search/constants.ts @@ -4,3 +4,4 @@ export const SEARCH_ITEM_HEIGHT = 48; export const SEARCH_ITEM_MARGIN = 4; export const DEFAULT_SORT = { label: 'A-Z', value: 'alpha-asc' }; export const SECTION_STORAGE_KEY = 'search.sections'; +export const GENERAL_FOLDER_ID = 0; diff --git a/public/app/features/search/hooks/useManageDashboards.test.ts b/public/app/features/search/hooks/useManageDashboards.test.ts new file mode 100644 index 00000000000..7a6ddc2297a --- /dev/null +++ b/public/app/features/search/hooks/useManageDashboards.test.ts @@ -0,0 +1,98 @@ +import { Dispatch } from 'react'; +import { renderHook } from '@testing-library/react-hooks'; + +import * as useSearch from './useSearch'; +import { DashboardQuery, DashboardSearchItemType, DashboardSection, SearchAction } from '../types'; +import { ManageDashboardsState } from '../reducers/manageDashboards'; +import { useManageDashboards } from './useManageDashboards'; +import { GENERAL_FOLDER_ID } from '../constants'; + +describe('useManageDashboards', () => { + const useSearchMock = jest.spyOn(useSearch, 'useSearch'); + const toggle = async (section: DashboardSection) => section; + + function setupTestContext({ results = [] }: { results?: DashboardSection[] } = {}) { + jest.clearAllMocks(); + + const state: ManageDashboardsState = { + results, + loading: false, + selectedIndex: 0, + initialLoading: false, + allChecked: false, + }; + const dispatch: Dispatch = (null as unknown) as Dispatch; + useSearchMock.mockReturnValue({ state, dispatch, onToggleSection: toggle }); + const dashboardQuery: DashboardQuery = ({} as unknown) as DashboardQuery; + + const { result } = renderHook(() => useManageDashboards(dashboardQuery, {})); + + return { result }; + } + + describe('when called and only General folder is selected', () => { + it('then canDelete should be false', () => { + const results: DashboardSection[] = [ + { id: 1, checked: false, items: [], title: 'One', type: DashboardSearchItemType.DashFolder, toggle, url: '/' }, + { + id: GENERAL_FOLDER_ID, + checked: true, + items: [], + title: 'General', + type: DashboardSearchItemType.DashFolder, + toggle, + url: '/', + }, + { id: 2, checked: false, items: [], title: 'Two', type: DashboardSearchItemType.DashFolder, toggle, url: '/' }, + ]; + + const { result } = setupTestContext({ results }); + + expect(result.current.canDelete).toBe(false); + }); + }); + + describe('when called and General folder and another folder are selected', () => { + it('then canDelete should be true', () => { + const results: DashboardSection[] = [ + { id: 1, checked: true, items: [], title: 'One', type: DashboardSearchItemType.DashFolder, toggle, url: '/' }, + { + id: GENERAL_FOLDER_ID, + checked: true, + items: [], + title: 'General', + type: DashboardSearchItemType.DashFolder, + toggle, + url: '/', + }, + { id: 2, checked: false, items: [], title: 'Two', type: DashboardSearchItemType.DashFolder, toggle, url: '/' }, + ]; + + const { result } = setupTestContext({ results }); + + expect(result.current.canDelete).toBe(true); + }); + }); + + describe('when called and no folder is selected', () => { + it('then canDelete should be false', () => { + const results: DashboardSection[] = [ + { id: 1, checked: false, items: [], title: 'One', type: DashboardSearchItemType.DashFolder, toggle, url: '/' }, + { + id: GENERAL_FOLDER_ID, + checked: false, + items: [], + title: 'General', + type: DashboardSearchItemType.DashFolder, + toggle, + url: '/', + }, + { id: 2, checked: false, items: [], title: 'Two', type: DashboardSearchItemType.DashFolder, toggle, url: '/' }, + ]; + + const { result } = setupTestContext({ results }); + + expect(result.current.canDelete).toBe(false); + }); + }); +}); diff --git a/public/app/features/search/hooks/useManageDashboards.ts b/public/app/features/search/hooks/useManageDashboards.ts index f272c03cb13..1b60c3e485a 100644 --- a/public/app/features/search/hooks/useManageDashboards.ts +++ b/public/app/features/search/hooks/useManageDashboards.ts @@ -5,6 +5,7 @@ import { DashboardQuery, DashboardSection, OnDeleteItems, OnMoveItems, OnToggleC import { DELETE_ITEMS, MOVE_ITEMS, TOGGLE_ALL_CHECKED, TOGGLE_CHECKED } from '../reducers/actionTypes'; import { manageDashboardsReducer, manageDashboardsState, ManageDashboardsState } from '../reducers/manageDashboards'; import { useSearch } from './useSearch'; +import { GENERAL_FOLDER_ID } from '../constants'; export const useManageDashboards = ( query: DashboardQuery, @@ -42,10 +43,10 @@ export const useManageDashboards = ( () => results.some((result: DashboardSection) => result.items && result.items.some(item => item.checked)), [results] ); - const canDelete = useMemo(() => canMove || results.some((result: DashboardSection) => result.checked), [ - canMove, - results, - ]); + const canDelete = useMemo( + () => canMove || results.some((result: DashboardSection) => result.checked && result.id !== GENERAL_FOLDER_ID), + [canMove, results] + ); const canSave = folder?.canSave; const hasEditPermissionInFolders = folder ? canSave : contextSrv.hasEditPermissionInFolders;