diff --git a/public/app/features/dashboard-scene/scene/DashboardControls.test.tsx b/public/app/features/dashboard-scene/scene/DashboardControls.test.tsx index c13e65574be..b71aaee816b 100644 --- a/public/app/features/dashboard-scene/scene/DashboardControls.test.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardControls.test.tsx @@ -1,11 +1,21 @@ -import { render } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import { selectors } from '@grafana/e2e-selectors'; +import { config } from '@grafana/runtime'; import { SceneVariableSet, ScopesVariable, TextBoxVariable } from '@grafana/scenes'; +import { playlistSrv } from 'app/features/playlist/PlaylistSrv'; import { DashboardControls, DashboardControlsState } from './DashboardControls'; import { DashboardScene } from './DashboardScene'; +jest.mock('app/features/playlist/PlaylistSrv', () => ({ + playlistSrv: { + useState: jest.fn().mockReturnValue({ isPlaying: false }), + state: { isPlaying: false }, + stop: jest.fn(), + }, +})); + describe('DashboardControls', () => { describe('Given a standard scene', () => { it('should initialize with default values', () => { @@ -221,8 +231,85 @@ describe('DashboardControls', () => { expect(setState).toHaveBeenCalledTimes(0); }); }); + + describe('DashboardControlActions editable flag', () => { + const originalFeatureToggles = { ...config.featureToggles }; + + beforeEach(() => { + config.featureToggles.dashboardNewLayouts = true; + jest.mocked(playlistSrv.useState).mockReturnValue({ isPlaying: false }); + }); + + afterEach(() => { + config.featureToggles = originalFeatureToggles; + jest.clearAllMocks(); + }); + + it('should show EditDashboardSwitch when editable is true', async () => { + const controls = buildTestSceneWithEditable({ editable: true, canEdit: true }); + render(); + + expect(await screen.findByRole('button', { name: /edit/i })).toBeInTheDocument(); + expect(screen.queryByRole('button', { name: /make editable/i })).not.toBeInTheDocument(); + }); + + it('should show MakeDashboardEditableButton when editable is false', async () => { + const controls = buildTestSceneWithEditable({ editable: false, canEdit: false, canMakeEditable: true }); + render(); + + expect(await screen.findByRole('button', { name: /make editable/i })).toBeInTheDocument(); + expect(screen.queryByRole('button', { name: /^edit$/i })).not.toBeInTheDocument(); + }); + + it('should not show edit buttons when canEditDashboard returns false', async () => { + const controls = buildTestSceneWithEditable({ + editable: true, + canEdit: false, + canMakeEditable: false, + isSnapshot: true, + }); + render(); + + expect(screen.queryByRole('button', { name: /edit/i })).not.toBeInTheDocument(); + expect(screen.queryByRole('button', { name: /make editable/i })).not.toBeInTheDocument(); + }); + + it('should not show edit buttons when playlist is playing', async () => { + jest.mocked(playlistSrv.useState).mockReturnValue({ isPlaying: true }); + + const controls = buildTestSceneWithEditable({ editable: true, canEdit: true }); + render(); + + expect(screen.queryByRole('button', { name: /^edit$/i })).not.toBeInTheDocument(); + expect(await screen.findByTestId(selectors.pages.Dashboard.DashNav.playlistControls.stop)).toBeInTheDocument(); + }); + }); }); +function buildTestSceneWithEditable(options: { + editable: boolean; + canEdit?: boolean; + canMakeEditable?: boolean; + isSnapshot?: boolean; +}): DashboardControls { + const { editable, canEdit = true, canMakeEditable = false, isSnapshot = false } = options; + + const dashboard = new DashboardScene({ + uid: 'test-uid', + editable, + meta: { + canEdit, + canMakeEditable, + isSnapshot, + }, + controls: new DashboardControls({}), + }); + + dashboard.activate(); + + return dashboard.state.controls as DashboardControls; +} + function buildTestScene(state?: Partial): DashboardControls { const variable = new TextBoxVariable({ name: 'A', diff --git a/public/app/features/dashboard-scene/scene/DashboardControls.tsx b/public/app/features/dashboard-scene/scene/DashboardControls.tsx index 16be88595d9..32f7d5289f8 100644 --- a/public/app/features/dashboard-scene/scene/DashboardControls.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardControls.tsx @@ -31,6 +31,7 @@ import { VariableControls } from './VariableControls'; import { DashboardControlsButton } from './dashboard-controls-menu/DashboardControlsMenuButton'; import { hasDashboardControls, useHasDashboardControls } from './dashboard-controls-menu/utils'; import { EditDashboardSwitch } from './new-toolbar/actions/EditDashboardSwitch'; +import { MakeDashboardEditableButton } from './new-toolbar/actions/MakeDashboardEditableButton'; import { SaveDashboard } from './new-toolbar/actions/SaveDashboard'; import { ShareDashboardButton } from './new-toolbar/actions/ShareDashboardButton'; @@ -191,7 +192,7 @@ function DashboardControlsRenderer({ model }: SceneComponentProps {showShareButton && } {isEditing && } - {!isPlaying && canEditDashboard && } + {!isPlaying && canEditDashboard && isEditable && } + {!isPlaying && canEditDashboard && !isEditable && !isEditing && ( + + )} {isPlaying && (